Repository navigation
feat(voice): recognise this project's names - #102
Merged
Merged
Conversation
Committed dictation spells the thread's project's names the way the code
does ("use dictation dot ts" -> use-dictation.ts) and the user's own word
list with sounds-like spellings. fs.vocabulary builds the project terms
from git (tracked names, exported symbols, branches, thread titles),
capped at 3000 and cached by commit and index. Hotwords were measured on
Parakeet and not kept.
ANT1OFF
added a commit
that referenced
this pull request
Nov 3, 2026
Desktop release metadata proposal only. Merging this PR does not publish or tag Gram; follow docs/RELEASING.md to release. --- ## [1.5.0](v1.4.0...v1.5.0) (2026-11-03) ### Features * **voice:** a normal Voice setting with a push-to-talk key picker ([#98](#98)) ([a49acdf](a49acdf)) * **voice:** recognise this project's names ([#102](#102)) ([d306e35](d306e35)) * **voice:** spoken symbols, formatting and filler clean-up ([#99](#99)) ([912b5e5](912b5e5)) * **voice:** voice input on Linux with a TTS-free sherpa-onnx build ([#100](#100)) ([4606b96](4606b96)) ### Bug Fixes * **release:** stop the release notes saying voice is missing on Linux ([#107](#107)) ([fbde4f2](fbde4f2)) * **worktrees:** sweep archived merged and no-PR worker worktrees ([#103](#103)) ([b9ed8d4](b9ed8d4)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --------- Co-authored-by: gram-release-please[bot] <351321620+gram-release-please[bot]@users.noreply.github.com> Co-authored-by: Johan <32440065+ANT1OFF@users.noreply.github.com>
ANT1OFF
added a commit
that referenced
this pull request
Nov 3, 2026
## What When a worker or an orchestrator is at rest waiting on something, the sidebar now says what, at a glance: an hourglass and a short line under its name, and the whole list on hover. The Board's chips and ⌘J's Workers list read the same selector, so the three surfaces say the same words. Presentation only. Nothing in `packages/` changes: everything comes from the ledger the web already gets (PRs, wakes, watched runs, limit waits) and the threads store. ### One "waiting on" model `apps/web/src/orchestration/waiting-on.ts` turns a calm worker's or orchestrator's waits into: - `label`: the row's line, e.g. `Waiting · checks on #69` - `reasons`: every wait, each with a kind, a short form and a full line - `hint`: the hover, i.e. the label with `+N` when more apply, then every wait's line | Kind | Label | Comes from | | --- | --- | --- | | checks | `Waiting · checks on #69`, `Waiting · local check #69` | required checks pending; Gram's local check running | | review | `Waiting · review on #69` | the review bot reviewing the head | | merge | `Waiting · merge of #69`, `Waiting · #69 held` | an armed `merge_when_ready`; a hold on an agent's work | | dependency | `Waiting · #102 to merge`, `Waiting · acme/api#7 to merge`, `Waiting · #645 to move` | `depends_on`; a wake on another PR | | run | `Waiting · Release run` | `run_monitor` | | condition | `Waiting · main to move`, `Waiting · thread to finish`; any other kind as its chip reads it (`wakeConditionLabel`) | #108's condition wakes; the hover names the thread and says `wakeConditionWhen` | | timer | `Waiting · until 08:10`, `Waiting · until Wed 09:00` | a timed wake | | limit | `Paused · limit until 08:10`, `Paused · retry at 07:05` | a usage-limit or rate-limit wait | | held | `Held · by you` | the user holds the worker | | frozen | (reserved) | nothing produces it yet; the merge freeze will | **Which wait the label names.** What holds everything else comes first (a limit, a frozen base, your hold). Then what clears soonest by its nature (CI, the review bot, Gram's merge), then the longer waits (another PR, a run, a condition). A timed wake comes last, since it's mostly the fallback beside the others. Within a kind, the soonest wins. **Waiting is never "needs you".** A wait is only said of a calm tone (waiting, idle, or finished with a run still watched), never beside work, an ask or a failure. Nothing here touches the Needs you list or counts. ### Surfaces - **Sidebar worker rows**: the hourglass line replaces the card's now line ("checks running", "you hold it") while the worker waits. The hover card lists every wait. - **Orchestrator line**: a second line under the workspace name for its own pending wakes, or a limit it waits out. The line's hover adds the list. It's hidden while the workspace is paused or parked. - **Board**: a chip's line is the same label, and its hover the same list. - **⌘J**: a row's now line is the same label, and its hover the same list. - The waiting tone's label is now "Waiting" rather than "Waiting on checks", since it covers more than checks. ### Behaviour change A worker waiting out a usage limit (`limitWait` in the ledger) now reads as waiting on automation, with the hollow dot. Before, its activity ignored the limit, so it showed idle (or attention). ### Labels kept to four words The Board keeps a chip's line to four words. Every label fits, with the ` · ` separator counted as punctuation; `board-rail.spec.ts` now counts it that way. ### Condition kinds still to come `conditionShort` special-cases `branchMoved` and `threadFinished` only. Any other kind falls back to contracts' `wakeConditionLabel`, and its hover line to `wakeConditionWhen`. So #110 (`freezeLifted`), #111 (`ciStuck`, machine load and disk) and #112 (`releasePublished`, `versionChanged`) show up without a change here. Whichever lands last adds any icon, words or priority of its own. The `frozen` kind is reserved for #110's frozen-main state. ## Screenshots From `pr-shots` on synthetic mock data. The "kinds" scene (`simulateWaitingOn`) adds a timed wake, a watched release run, a usage limit, an armed merge, a wake on another PR and one on `main` moving, and the orchestrator resting on two wakes of its own (a thread to finish, ranked first, and a timed one). **The sidebar over `casefiles`: workers waiting on CI, the review bot and a dependency say what they wait on** (dark) _After only: the base timed out staging it; the light pair below has the before._  **The sidebar over `casefiles`: workers waiting on CI, the review bot and a dependency say what they wait on** (light) | Before | After | | --- | --- | |  |  | **Every kind of wait in the sidebar, and the orchestrator resting on a wake of its own** (dark) _After only: the scene's mock scenario is new in this PR._  **Every kind of wait in the sidebar, and the orchestrator resting on a wake of its own** (light) _After only: the scene's mock scenario is new in this PR._  **A waiting worker's hover card lists every wait, the one its row names first** (dark) _After only: the scene's mock scenario is new in this PR._  **The same waits on the Board's chips, in the sidebar's words** (dark) _After only: the scene's mock scenario is new in this PR._  **The same waits on the Board's chips, in the sidebar's words** (light) _After only: the scene's mock scenario is new in this PR._  **⌘J's Workers list says the same** (dark) _After only: the scene's mock scenario is new in this PR._  **The same `casefiles` workers on the Board: the chips agree with Quiet's dots** (dark) | Before | After | | --- | --- | |  |  | **The same `casefiles` workers on the Board: the chips agree with Quiet's dots** (light) | Before | After | | --- | --- | |  |  | ## Verification On `fc8e877`, rebased onto `main` after #108: - `bun run typecheck`, `bun run lint`, `bun run fmt:check`, `bun run check:scaffold`: pass - `vitest run src/orchestration src/views src/sidebar src/thread src/shell src/api`: 1228 passed (on `767c1af`); `waiting-on.test.ts`: 30 passed on the head - Affected e2e, `--workers=2` (`overview-sidebar board-parity board-rail board-virtual feature-sheet orchestration workers-list quiet-view overview-extras workspace-density reaching-workers worker-questions one-thread-budgets ask-stack`): 135 passed, 3 failed. Two were tests to update for this change (the orchestrator's waits read in rank order; ⌘J's four-word cap counting the ` · `), fixed in `fc8e877`. The third, `overview-sidebar.spec.ts:851` (a Needs you count of 9 for 8), is untouched by this and passed alone. All three passed alone on the head. - Specs updated, not deleted: `board-rail` and `workers-list` count words without the separator; `overview-sidebar` reads a row's name with its wait, and tells the agent's glyph from the hourglass. - Not run: the full `bun run check`, left to the merge gate. ## Known limits - `frozen` has a label and a rank but no source until the merge freeze lands. - A thread-finished condition shows "thread to finish" on the row; the thread's title is in the hover only, to keep the line short. - Synthetic mock data only; not run against a live provider or real workspace.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Dictation now spells the names of the project you're working in the way the code does, plus your own word list. It's layer 1 of the plan, a pass after the commit. Layer 2, sherpa-onnx hotwords on Parakeet, was measured and not kept (see below).
What changes
apps/web/src/dictation/vocabulary.tsis pure. It runs on each committed utterance, after feat(voice): spoken symbols, formatting and filler clean-up #99'spostprocess()(committedText→applyVocabulary), never on the live partial.useDictation, "dictation dot TS" ordictation.ts→dictation.ts, "feat slash voice vocab" →feat/voice-vocab.Nemotron, "feet slash voice vocad" →feat/voice-vocab).fs.vocabularyRPC,packages/server/src/fs/vocabulary.ts):git ls-files), folder names, top-level exports found by a cappedgit grep -oover TS/JS/Rust/Python, local branches, and words from the project's recent thread titles.distinctiveTerm).Limits
Hotwords: measured, not kept
Clips: Parakeet TDT v2 int8 offline, through sherpa-onnx-node 2.0.0, with 2 threads like the product. 12 synthetic
sayclips × 2 voices (Samantha, Daniel): 10 name repo identifiers and 2 are controls of only common words.Hotword setup: they only apply with
modelingUnit: "bpe"and abpe.vocab, which these exports don't ship. One was generated from tokens.txt with scores of −id. Pre-tokenized phrases are rejected ("Encode hotwords failed").Metrics:
Why hotwords weren't kept:
The two names layer 1 still misses:
accurate.ts: "inaccurate" is a real word.sherpa-onnx: 2 edits on a 10-letter name.Merge with #98 and #99
Checks
bun run typecheck,bun run lint,bun run fmt:check,bun run check:scaffold,bun run check:docs: pass.bun run testover dictation, speech process and module, serverfsand the fs handler, contracts rpc, settings and vocabulary, and web settings and composer: 97 files, 979 passed, 1 skipped.playwright test e2e/dictation.spec.ts: 21 passed. That includes the new test: a committed utterance spellsretry.test.tsand the user's "para keet" → Parakeet, and with "Use this project's names" off only the user's word is spelled.bun run checkof my own: the machine is shared.Known limits:
Screenshots
Settings → Voice input with a word list, the whole page (dark)
Settings → Voice input with a word list, the whole page (light)