Files
gbrain/recipes/agent-voice
613da94093 v0.42.29.0 fix(minions): long-job abort-honoring + attempt accounting + supervisor singleton; topic-aware voice (#1737, #1849, #1851) (#1943)
* fix(minions): honest attempt accounting + cooperative abort-honoring + per-handler timeouts (#1737)

- Wall-clock and stall dead-letter paths now increment attempts_made (terminal,
  no retry — wall-clock fires at 2x cumulative timeout; retrying non-idempotent
  embed/subagent work would duplicate side effects). Surface stalled_counter in
  jobs get so 'started 3 / stalled 2 / attempts 0' reads true instead of looking
  like broken accounting.
- Thread AbortSignal through embed-backfill/autopilot-cycle -> runPhaseEmbed ->
  runEmbedCore -> embedAll(Stale)/embedPage, checking it on BOTH --stale and
  --all paths and between embed batches. A timed-out embed phase now bails within
  a batch, so the cycle finally releases gbrain_cycle_locks instead of running
  the full 10-15 min after the job was killed (the daily cycle-wedge). New shared
  src/core/abort-check.ts (isAborted/throwIfAborted/anySignal).
- Per-handler default wall-clock budget (handler-timeouts.ts) stamped at submit
  for long handlers without an explicit timeout_ms.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(minions): queue-scoped DB supervisor singleton + canonical pidfile + doctor max-rss check (#1849)

- Acquire a queue-scoped DB lock (tryAcquireDbLock, keyed on the raw DB identity
  + queue) on supervisor.start(): a second supervisor on the same (db, queue)
  fails fast with exit 2 regardless of $HOME/--pid-file. Refresh on a dedicated
  timer; on refresh failure past the threshold, fail SAFE (exit non-zero) before
  the TTL could lapse and let a second supervisor take over. Release on shutdown.
- Canonical default pidfile keyed on brain id (currentBrainId, config-only, no DB
  connect) so two brains under one HOME no longer share supervisor.pid.
- doctor: new supervisor_singleton check surfaces the effective --max-rss (from
  the started audit event) and warns when the lock holder's (host,pid) differs
  from the local pidfile — comparing host+pid, not bare pid. Registered in
  doctor-categories.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(agent-voice): topic-aware persona context via server-resolved topicId (#1851)

Summon Mars/Venus into a specific conversation topic so they boot already knowing
the recent thread. A per-topic call link carries only topicId (+ optional display
topicName); the server resolves the recent-conversation context from the brain
(topics/<topicId>.md) — topic CONTENT is never accepted over the wire (that would
be prompt injection + a leak into URLs/referrers/logs). topicId is a strict slug
with a path-traversal guard. New '# Topic Context' prompt slot injected after the
persona body so identity-first ordering still wins; persona identity unchanged.
No topicId -> generic behavior. Contract doc + persona skill docs updated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore: file #1737 slot-reservation fair-scheduling follow-up TODO (F7)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore: bump version and changelog (v0.42.29.0)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs: sync KEY_FILES.md for v0.42.29.0 minions + abort wave (#1737, #1849)

Fold the #1737/#1849 behavior into the existing per-file entries and add the
two new core files, keeping the doc at current-state truth:
- queue.ts: honest attempt accounting on wall-clock + stall dead-letter paths;
  defaultTimeoutMsFor stamping at submit.
- supervisor.ts: queue-scoped DB singleton lock (supervisorLockId,
  classifySupervisorSingleton, LOCK_LOST, refresh-fail-safe, brain-id pidfile,
  max_rss_mb audit).
- worker-registry.ts: currentDbIdentity().
- New entries: src/core/abort-check.ts, src/core/minions/handler-timeouts.ts.
- New doctor.ts extension: supervisor_singleton check.
- cycle.ts / embed.ts extensions: AbortSignal threading note.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 08:12:50 -07:00
..

agent-voice — reference bundle

This directory is a reference, not a runtime gbrain dependency. The gbrain compiled binary does NOT load anything under recipes/agent-voice/code/, recipes/agent-voice/skills/, or recipes/agent-voice/tests/. Those exist to be COPIED into the operator's host agent repo via gbrain integrations install agent-voice --target <host-repo>.

The paradigm

Aspect Legacy skillpack (local-managed) Reference skillpack (copy-into-host-repo)
Where code lives ~/.gbrain/skills/<name>/ <host-repo>/services/voice-agent/
Who owns edits gbrain (managed block) Operator (host repo)
Update path Overwrite or skip Diff-and-propose against manifest hashes
Resolver registration ~/.gbrain/skills/RESOLVER.md <host-repo>/RESOLVER.md or AGENTS.md
Identity of updates gbrain pushes Operator pulls per release cadence
Bisect / blame / history gbrain's git history Operator's host repo git history

The install_kind discriminator in the recipe frontmatter routes between the two paths inside gbrain integrations install.

Sibling-directory convention (for future copy-into-host-repo recipes)

This recipe pioneers the layout future copy-into-host-repo recipes should follow:

recipes/<name>.md                       # registered entrypoint (loader sees this)
recipes/<name>/
├── README.md                           # paradigm doc; gbrain-side only (not copied)
├── package.json                        # top-of-bundle; copied to <host>/services/<name>/package.json
├── code/                               # copied to <host>/services/<name>/code/
├── tests/                              # copied to <host>/services/<name>/tests/
│   ├── unit/
│   ├── e2e/
│   └── evals/
├── skills/                             # copied to <host>/skills/<skill-name>/
├── install/                            # gbrain-side only; install metadata
│   ├── manifest.json                   # src → target map + per-file SHA-256
│   ├── refresh-algorithm.md            # diff-and-propose semantics
│   └── post-install-hint.md            # next-step prompts for the install agent
└── docs/                               # any extra docs the operator should see post-install

Three rules for new recipes following this shape:

  1. Topology preservation. Tests at recipes/<name>/tests/unit/x.test.mjs MUST import code via ../../code/.... That relative path is preserved when copied to <host>/services/<name>/tests/unit/x.test.mjs<host>/services/<name>/code/.... The installer is NOT in the business of rewriting imports.

  2. PII guard scope. Every file under recipes/<name>/ is scanned by scripts/check-no-pii-in-agent-voice.sh (or future equivalent), PLUS the top-level recipes/<name>.md. The single source of truth for the blocklist is a JSON file inside the bundle.

  3. install_kind: copy-into-host-repo in frontmatter routes to the copy path. Without it, the recipe defaults to local-managed (legacy ~/.gbrain/skills/ install).

Files (gbrain-side only — NOT copied to host)

  • README.md — this doc.
  • install/manifest.json — declares src → target paths + permissions; the install command computes SHA-256 at copy time.
  • install/refresh-algorithm.md — the diff-and-propose contract.
  • install/post-install-hint.md — what the install agent prints when copy completes.
  • code/lib/personas/private-name-blocklist.json — privacy guard source of truth (read by the shipped guard script and by host-side prompt-shape tests).
  • code/lib/personas/context-builder.contract.md — API the operator implements for live brain context.

Files (in bundle = code/ + tests/ + skills/ + package.json) — copied to host repo

The install subcommand reads install/manifest.json and copies each listed file to its target path under the host repo. SHA-256s computed at copy time get persisted into <host>/services/<name>/.gbrain-source.json so --refresh can do three-way classification (unchanged-identical / unchanged-stale / locally-modified) without re-walking the entire bundle.

Reading order

If you're new to this paradigm and want to understand the moving parts:

  1. recipes/agent-voice.md — the registered recipe, top-level explainer + install steps.
  2. This file — the paradigm + sibling-directory convention.
  3. install/manifest.json — the literal src → target file map.
  4. install/refresh-algorithm.md — what --refresh does and how to extend it.
  5. code/tools.mjs — the load-bearing trust-boundary code (D14-A read-only allow-list).
  6. code/lib/personas/mars.mjs + code/lib/personas/venus.mjs — the persona prompts.
  7. code/public/call.html — the WebRTC client with ?test=1 instrumentation.
  8. code/server.mjs — the minimal voice server.