Skip to content

fix(orchestrator): bootstrap-token discipline + SQLite agent-channel queries#9

Open
evannadeau wants to merge 1 commit into
SpawnBox-dev:mainfrom
evannadeau:fix/bootstrap-token-discipline
Open

fix(orchestrator): bootstrap-token discipline + SQLite agent-channel queries#9
evannadeau wants to merge 1 commit into
SpawnBox-dev:mainfrom
evannadeau:fix/bootstrap-token-discipline

Conversation

@evannadeau
Copy link
Copy Markdown

Summary

Two related fixes to the PA/SA bootstrap skill recipes. Recipe-only changes — no MCP server / source code modifications, no dist/ rebuild required.

Fix 1 — Bootstrap token discipline

getting-started/SKILL.md step 1 and pa-bootstrap/SKILL.md steps 5.5/5.6 currently instruct the agent to call briefing() and five lookup() calls in full-content mode without any output narrowing. On a representative Quayline workspace this consumes ~204KB of persisted tool-results per PA bootstrap (~50K tokens of context, roughly 10% of a Max 5x plan's 5-hour rolling window — and every fresh SA pays its own cost).

Changes:

  • getting-started step 1: add sections: ["work_items","open_threads","decisions","checkpoint","user_model","cross_session"] to the briefing() call. Default rendering includes neglected_areas (large tag soup), drift, and curation_candidates — useful for explicit maintenance turns (orchestrator:reflect) but inflates routine bootstrap by 5-15K tokens.
  • pa-bootstrap steps 5.5 + 5.6: add output_mode: "summary" to all five enumeration lookups (user_pattern, architecture, decision, convention, anti_pattern). The skill's own stated intent — "Skim each. You don't need to memorize content - you need to know WHAT exists so you can surface specific notes by ID" — exactly matches summary mode's one-line-per-result rendering. Agents can still drill into full content via lookup({id: "<id8>"}) when an SA's task intersects a specific note.

Empirical validation (Quayline workspace, 2026-05-15):

Session Override applied tool-results size
Pre-fix PA bootstrap none 204KB
Post-fix PA bootstrap lookup-side summary mode 56KB (72% reduction)
Post-fix SA bootstrap lookup-side summary mode 60KB (71% reduction)

The largest individual lookup persisted at 84KB in full mode and disappears entirely under summary mode (the response fits inline at ~1-2KB and is never persisted to disk). Across a multi-session workday (1 PA + N SAs), savings compound linearly with N.

The sections filter change is independently needed because operators who try to workaround at the project level cannot — the upstream skill calls briefing() before the project's CLAUDE.md is read, so a project-side override has no chance to apply. Only the upstream skill can claim that ~5-15K savings.

Fix 2 — SQLite agent-channel queries

pa-bootstrap/SKILL.md steps 2, 3, and 6 instruct the agent to cat sessions.json and cat state.json in $CLAUDE_PROJECT_DIR/.orchestrator-state/agent-channel/. Neither file exists in current plugin versions — agent-channel was migrated to SQLite (WAL-mode agent_channel.db) with the sessions, global_pause, and sa_pause tables replacing the JSON files. The recipe was never updated.

Compounding the issue, $CLAUDE_PROJECT_DIR is not propagated to PA sessions in Claude Code 2.1.142 (verified empirically via env); the recipe's bash commands silently expand to /.orchestrator-state/... (root-anchored) and report "missing" even when state exists. The launchers DO set $ORCHESTRATOR_PROJECT_ROOT.

Changes:

  • Steps 2 + 3 (role check + active subordinates list): replace cat sessions.json with a Python stdlib sqlite3 query against agent_channel.db. The query joins role/heartbeat/name/current_task in one call and powers both steps (Step 2 looks for the agent's own row; Step 3 lists rows where role=subordinate and heartbeat age < 90s).
  • Step 6 (global pause check): replace cat state.json with SELECT * FROM global_pause WHERE active=1.
  • Step 4 (agent-channel-wired verification): tighten to "your own row in Step 2's query IS the wiring confirmation" — when the MCP is running, your heartbeat is in the table; that's the loop-closure.
  • All path references: switch from $CLAUDE_PROJECT_DIR to $ORCHESTRATOR_PROJECT_ROOT.
  • Skill description (frontmatter): update "reads active sessions from sessions.json" to "reads active sessions from the SQLite agent-channel DB".

The Python stdlib approach avoids requiring sqlite3 CLI to be installed (it isn't on a fresh Ubuntu-24.04 WSL workstation).

Failure mode without these fixes

A fresh PA running /pa-bootstrap on current plugin code:

  1. Reports sessions.json missing (the file doesn't exist).
  2. Per the skill's own "if you can't confirm agent-channel is running, surface the failure verbatim and abort" instruction, the agent is told to abort the bootstrap — even though agent-channel is fully wired in SQLite.
  3. Operators currently work around this with inline Python queries per session, which works but accumulates as upstream-tooling-debt.

Test plan

  • Read upstream pa-bootstrap/SKILL.md and getting-started/SKILL.md directly from main@cb407712 before drafting the diff (no rebase risk; the fork was in sync).
  • Verified the Python sqlite3 query empirically: it returns the running session's row with role=prime, fresh heartbeat, and current_task on Quayline workspace 369009bc / a29491cd. Output matches what cat sessions.json would have produced in pre-migration plugin versions.
  • Verified $ORCHESTRATOR_PROJECT_ROOT is set in Claude Code 2.1.142 PA sessions via env | grep ORCHESTRATOR.
  • Verified briefing({sections: [...]}) empirically — returns the requested sections only, suppresses neglected_areas / drift / curation_candidates (saves ~10-15K tokens on this workspace).
  • Verified lookup({type:..., output_mode:"summary"}) empirically — returns one-line-per-result rendering with id8 + type + truncated content. Disk persistence threshold not triggered for limit=15 results.
  • Reviewer might want one more empirical pass on a different workspace (this was Quayline-specific). Happy to coordinate if so.

Out of scope (separate upstream PR candidates)

The Quayline workspace's KB tracks several other upstream-PR candidates touching plugins/orchestrator/mcp/server.ts (path-hashing leading-dash strip; version-drift Version: ... line bug at server.ts:655; agent-channel filewatcher silently truncating PA-to-SA multi-paragraph addresses at the first colon-after-blank-line; concurrent stop-hook deadlock between parallel Claude Code sessions). These are MCP server source changes and would require dist/ rebuild — they should ship as a separate PR (or PRs) to keep this skill-recipe-only change reviewable in isolation.

References

For SpawnBox-dev maintainers: this PR was developed against the operator's local orchestrator KB notes (anti-patterns b1cc1bc2 and e2239a05 for the two fixes respectively, plus the empirical-confirmation appends from session a29491cd). Happy to share the full note bodies if useful — they include diff shapes verbatim from the operator's investigation.

🤖 Generated with Claude Code (Admiral PA orchestrating a meta-team-cleanup batch)

…queries

Two related fixes to PA/SA bootstrap skills (recipes only; no source changes):

1. Bootstrap token discipline — getting-started step 1 adds `sections:` filter to
   briefing() and pa-bootstrap step 5.5/5.6 add `output_mode: "summary"` to all
   five lookups. Empirically validated: PA bootstrap drops from 204KB persisted
   tool-results to 56KB (72% reduction); SA bootstrap drops to 60KB. Per-session
   savings compound across multi-agent workdays.

2. SQLite agent-channel queries — pa-bootstrap steps 2/3/6 replace `cat
   sessions.json` / `cat state.json` with Python sqlite3 queries against
   `agent_channel.db`. The JSON state files no longer exist (migrated to SQLite
   WAL); the recipe was never updated. Also: switch path env var from
   `$CLAUDE_PROJECT_DIR` (unset in PA sessions on Claude Code 2.1.142) to
   `$ORCHESTRATOR_PROJECT_ROOT` (set by the launchers).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant