Files
gods-eye-view/src/voice/speechLint.js
T
Bilawal Sidhu a19897ad15 feat(voice): voice core — honest layer reach, spoken summary with on-screen card, narration, point-and-ask
- Voice layer manifest (src/voice/layerManifest.js) generates the layer enums,
  aliases and analyst field hints; a test fails when a catalog layer has no entry.
- analyst_query validates fields, operators, units, values and scopes, counts up
  to 250,000 loaded records per layer, reports complete/partial/unanswered, tells
  LAYER_OFF / NOT_READY / FEED_UNAVAILABLE apart from zero, refuses mismatched
  follow-ups and never lets a superseded query replace follow-up memory. Seven
  more layers expose analyst records.
- Tool results carry a code-built say line and a display card; the voice card in
  the mic control shows captions, plan steps and the result
  (src/voice/resultDisplay.js is the one adapter). Slow tools narrate their
  current step out of band; holding Space while the assistant talks cuts it off.
  Turn spans go to the debug log; caption transcription is metered; the log
  omits what was said unless GEV_VOICE_LOG_CONTENT=1.
- Point and ask: the Space-down pointer snapshot resolves "this", "that one" and
  "around here" through 'pointer' targets, and "the second one" through
  referent:n from the last numbered list.
- Prompt states each policy once (instructions + tools 48.5k -> 46.7k chars).
- Voice benchmark harness (scripts/qa-voice-bench.mjs, scripts/voice-bench/)
  shares its phrase table and grading with scripts/qa-voice-routing.mjs.
2026-09-28 21:19:23 -05:00

55 lines
1.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Spoken-reply lint shared by the turn spans, the unit tests and the QA
* harnesses. Pure: no browser or provider dependencies.
*/
/**
* Phrases that add length without adding an answer. Tool numbers are spoken
* verbatim, so approximations are hedges too.
*/
export const HEDGE_PHRASES = Object.freeze([
'keep in mind',
"it's worth noting",
'it is worth noting',
'please note',
'note that',
'based on the data available',
'based on the available data',
'i should mention',
'as of my',
'it seems',
'it appears',
'approximately',
'roughly',
'let me think',
'let me check',
'one moment while',
'bear with me',
'just to be clear',
]);
const WORD = /[\p{L}\p{N}][\p{L}\p{N}'’-]*/gu;
/**
* Count spoken words in a transcript.
* @param {string} text
* @returns {number}
*/
export function countWords(text) {
return String(text || '').match(WORD)?.length || 0;
}
/**
* Return every hedge phrase found in a transcript, in list order.
* @param {string} text
* @returns {string[]}
*/
export function findHedges(text) {
const normalized = ` ${String(text || '')
.toLowerCase()
.replace(/[’]/g, "'")
.replace(/[^\p{L}\p{N}' ]+/gu, ' ')
.replace(/\s+/g, ' ')} `;
return HEDGE_PHRASES.filter((phrase) => normalized.includes(` ${phrase} `));
}