@rubytech/create-maxy-code 0.1.82 → 0.1.83

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/plugins/admin/PLUGIN.md +1 -1
  3. package/payload/platform/scripts/seed-neo4j.sh +8 -14
  4. package/payload/platform/services/claude-session-manager/dist/jsonl-tail.d.ts +6 -0
  5. package/payload/platform/services/claude-session-manager/dist/jsonl-tail.d.ts.map +1 -1
  6. package/payload/platform/services/claude-session-manager/dist/jsonl-tail.js +21 -0
  7. package/payload/platform/services/claude-session-manager/dist/jsonl-tail.js.map +1 -1
  8. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts +47 -0
  9. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
  10. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +252 -26
  11. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
  12. package/payload/platform/templates/agents/admin/IDENTITY.md +1 -1
  13. package/payload/platform/templates/specialists/agents/database-operator.md +8 -10
  14. package/payload/premium-plugins/real-agent/plugins/brochures/skills/property-brochure/SKILL.md +1 -0
  15. package/payload/premium-plugins/real-agent/plugins/brochures/skills/property-brochure/references/template.html +1 -1
  16. package/payload/server/public/assets/{admin-Dl273yTS.js → admin-BHaOSIuo.js} +1 -1
  17. package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-Iyf6H93s.js → architectureDiagram-Q4EWVU46-B8o-_aT-.js} +1 -1
  18. package/payload/server/public/assets/{blockDiagram-DXYQGD6D-e7l5Mhun.js → blockDiagram-DXYQGD6D-BcprLXNk.js} +1 -1
  19. package/payload/server/public/assets/{brand-CTMGYFDd.css → brand-C_iHnsbT.css} +1 -1
  20. package/payload/server/public/assets/{c4Diagram-AHTNJAMY-bDICnX2_.js → c4Diagram-AHTNJAMY-CAkKlTxa.js} +1 -1
  21. package/payload/server/public/assets/channel-C9mhUrr8.js +1 -0
  22. package/payload/server/public/assets/{chunk-336JU56O-CbnUj19H.js → chunk-336JU56O-DZ53mw2n.js} +2 -2
  23. package/payload/server/public/assets/{chunk-426QAEUC-DxGLqjw5.js → chunk-426QAEUC-3s5PxkHp.js} +1 -1
  24. package/payload/server/public/assets/{chunk-4TB4RGXK-CzvvHuMJ.js → chunk-4TB4RGXK-MLx8Jj8R.js} +1 -1
  25. package/payload/server/public/assets/{chunk-5FUZZQ4R-DxqHPDro.js → chunk-5FUZZQ4R-DFWTZhLd.js} +1 -1
  26. package/payload/server/public/assets/{chunk-5PVQY5BW-BA6nMu9F.js → chunk-5PVQY5BW-vTE3gFPo.js} +1 -1
  27. package/payload/server/public/assets/{chunk-EDXVE4YY-gUSTktie.js → chunk-EDXVE4YY-Bp1I_rQl.js} +1 -1
  28. package/payload/server/public/assets/{chunk-ENJZ2VHE-C-wW17kd.js → chunk-ENJZ2VHE-DsDBZ8WH.js} +1 -1
  29. package/payload/server/public/assets/{chunk-ICPOFSXX-zLc9NsO5.js → chunk-ICPOFSXX-BKO6vxzn.js} +1 -1
  30. package/payload/server/public/assets/{chunk-OYMX7WX6-Bt9RJ_rb.js → chunk-OYMX7WX6-D-ievGGw.js} +1 -1
  31. package/payload/server/public/assets/{chunk-U2HBQHQK-BAM6MO6g.js → chunk-U2HBQHQK-D_5PbJhp.js} +1 -1
  32. package/payload/server/public/assets/{chunk-X2U36JSP-DbOwgg1R.js → chunk-X2U36JSP-QmmoxQya.js} +1 -1
  33. package/payload/server/public/assets/{chunk-YZCP3GAM-BXUfYLeM.js → chunk-YZCP3GAM-BXSWZZag.js} +1 -1
  34. package/payload/server/public/assets/{chunk-ZZ45TVLE-BBIHnMjI.js → chunk-ZZ45TVLE-oyzperET.js} +1 -1
  35. package/payload/server/public/assets/classDiagram-6PBFFD2Q-BXiYcaCJ.js +1 -0
  36. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-BRxESuCS.js +1 -0
  37. package/payload/server/public/assets/clone-Bz40VsQ_.js +1 -0
  38. package/payload/server/public/assets/{dagre-Bv8aHCaJ.js → dagre-65Q3iWcL.js} +1 -1
  39. package/payload/server/public/assets/{dagre-KV5264BT-BZ0q7dDA.js → dagre-KV5264BT-Cyc37LVU.js} +1 -1
  40. package/payload/server/public/assets/data-DU2ZQbl-.js +1 -0
  41. package/payload/server/public/assets/{device-url-actions-CK6x8-FQ.js → device-url-actions-BftdR4st.js} +1 -1
  42. package/payload/server/public/assets/{diagram-5BDNPKRD-Bbzy2KoW.js → diagram-5BDNPKRD-DKItZE_3.js} +1 -1
  43. package/payload/server/public/assets/{diagram-G4DWMVQ6-CadVHWrV.js → diagram-G4DWMVQ6-DKlYJZby.js} +1 -1
  44. package/payload/server/public/assets/{diagram-MMDJMWI5-DwJ6fVMv.js → diagram-MMDJMWI5-DLqF5x2e.js} +1 -1
  45. package/payload/server/public/assets/{diagram-TYMM5635-Bh8d1vg-.js → diagram-TYMM5635-Cdufrh7g.js} +1 -1
  46. package/payload/server/public/assets/{erDiagram-SMLLAGMA-B1oTY2ob.js → erDiagram-SMLLAGMA-D6eSXJWj.js} +1 -1
  47. package/payload/server/public/assets/{flowDiagram-DWJPFMVM-BZU76iLs.js → flowDiagram-DWJPFMVM-BB4luljp.js} +1 -1
  48. package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-PjhJx62i.js → ganttDiagram-T4ZO3ILL-USBgsV4V.js} +1 -1
  49. package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-DLrxzJYi.js → gitGraphDiagram-UUTBAWPF-BqyKsQZ9.js} +1 -1
  50. package/payload/server/public/assets/graph-BgLMP7mY.js +1 -0
  51. package/payload/server/public/assets/{graph-labels-CpFvcba2.js → graph-labels-CUN_9NnB.js} +1 -1
  52. package/payload/server/public/assets/{graphlib-D2ExKXiT.js → graphlib-C5MkULnV.js} +1 -1
  53. package/payload/server/public/assets/{infoDiagram-42DDH7IO-Cn0r9nCK.js → infoDiagram-42DDH7IO-BF1spWbk.js} +1 -1
  54. package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-Ed8ANWEq.js → ishikawaDiagram-UXIWVN3A-CODjk_-5.js} +1 -1
  55. package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-DF1gG775.js → journeyDiagram-VCZTEJTY-RyhxP8aB.js} +1 -1
  56. package/payload/server/public/assets/{kanban-definition-6JOO6SKY-D8VcaKAp.js → kanban-definition-6JOO6SKY-jrm_4IpR.js} +1 -1
  57. package/payload/server/public/assets/{line-CgMZIaVM.js → line-DsE8JMaX.js} +1 -1
  58. package/payload/server/public/assets/{mermaid-parser.core-ez9lChuL.js → mermaid-parser.core-F27uElsX.js} +1 -1
  59. package/payload/server/public/assets/{mermaid.core-BiVW_Lka.js → mermaid.core-B0PzAHME.js} +3 -3
  60. package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-C-BlLBbo.js → mindmap-definition-QFDTVHPH-GA-xLC9K.js} +1 -1
  61. package/payload/server/public/assets/{page-DStDaJgc.js → page-CXFoiyRN.js} +2 -2
  62. package/payload/server/public/assets/{page-BQCQwUG5.js → page-vRUDyjk4.js} +1 -1
  63. package/payload/server/public/assets/{pieDiagram-DEJITSTG-BK0-LxVl.js → pieDiagram-DEJITSTG-CkP9U2tn.js} +1 -1
  64. package/payload/server/public/assets/{public-DMk9cZKl.js → public-B_gqH5Cf.js} +3 -3
  65. package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-vKAQHu-t.js → quadrantDiagram-34T5L4WZ-sYIgx5bu.js} +1 -1
  66. package/payload/server/public/assets/{requirementDiagram-MS252O5E-Df9sXR35.js → requirementDiagram-MS252O5E-CKtMUXvK.js} +1 -1
  67. package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-DG6xirA4.js → sankeyDiagram-XADWPNL6-CP5qebN_.js} +1 -1
  68. package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-B1a38KHX.js → sequenceDiagram-FGHM5R23-zvkjl2R6.js} +1 -1
  69. package/payload/server/public/assets/{stateDiagram-FHFEXIEX-CRiIDR4O.js → stateDiagram-FHFEXIEX-D-1VwYNL.js} +1 -1
  70. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BGmOYY_E.js +1 -0
  71. package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-CkBOE7Y8.js → timeline-definition-GMOUNBTQ-BSd_xlMt.js} +1 -1
  72. package/payload/server/public/assets/{vennDiagram-DHZGUBPP-CwKBydYc.js → vennDiagram-DHZGUBPP-D1hxlYfF.js} +1 -1
  73. package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-BWXYfzIr.js → wardleyDiagram-NUSXRM2D-yNOC0LD-.js} +1 -1
  74. package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-D-4v5Dy_.js → xychartDiagram-5P7HB3ND-D9D_gyVi.js} +1 -1
  75. package/payload/server/public/data.html +5 -5
  76. package/payload/server/public/graph.html +5 -5
  77. package/payload/server/public/index.html +7 -7
  78. package/payload/server/public/public.html +4 -4
  79. package/payload/server/public/assets/channel-CkgyfA91.js +0 -1
  80. package/payload/server/public/assets/classDiagram-6PBFFD2Q-PyvJekA9.js +0 -1
  81. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-6hFNhiTb.js +0 -1
  82. package/payload/server/public/assets/clone-CFIJrRLl.js +0 -1
  83. package/payload/server/public/assets/data-BgADjmk1.js +0 -1
  84. package/payload/server/public/assets/graph-B1_erzSo.js +0 -1
  85. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-C8cVmi_o.js +0 -1
  86. /package/payload/server/public/assets/{brand-dPgPNs7n.js → brand-kwAWaknq.js} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rubytech/create-maxy-code",
3
- "version": "0.1.82",
3
+ "version": "0.1.83",
4
4
  "description": "Install Maxy — AI for Productive People",
5
5
  "bin": {
6
6
  "create-maxy-code": "./dist/index.js"
@@ -129,7 +129,7 @@ Tools are available via the `admin` MCP server.
129
129
  - `hooks/pre-tool-use.sh` — enforces admin agent write boundaries
130
130
  - `hooks/playwright-file-guard.sh` — rewrites file:// URLs to a backgrounded loopback http.server before Playwright sees them
131
131
  - `hooks/webfetch-preflight.mjs` — short-circuits WebFetch on JS-SPA shells with a structured `WEBFETCH_CANNOT_READ_JS_SPA` error so the agent surfaces a loud failure to the owner instead of paying the 60s extraction timeout. Fail-open on any internal error.
132
- - `hooks/turn-completed-graph-write.sh` — Stop hook fired once per completed admin-agent turn. Gates on `MAXY_SESSION_ROLE=admin` + `MAXY_SPECIALIST!=database-operator` so it never recurses into the recorder PTY or fires on public sessions. **Task 147** — the recorder is spawned via the same route Sidebar uses. ONE POST to `POST /api/admin/claude-sessions`, body carries `{specialist:'database-operator', model:'haiku', initialMessage:<json-envelope>, adminSessionId:<op>}` — no synthetic `senderId: 'turn-recorder'` marker. The Hono wrapper bypasses cookie auth on this exact method+path when the request originates from `127.0.0.1` (same trust boundary the claude-session-manager itself relies on), looks up the operator's senderId from the manager's `/<adminSessionId>/meta`, and forwards a Sidebar-shape spawn body. The `/recorder-spawn` sibling route is gone. The hook reads its UI port from `MAXY_UI_INTERNAL_PORT` (stamped on the manager systemd unit) — no fallback; absence emits `[turn-recorder] spawn-failed reason=missing-env env=MAXY_UI_INTERNAL_PORT` to stderr instead of silently 19199-ing. **Task 177** — `initialMessage` is a JSON-stringified envelope; the schema lives in [`platform/plugins/docs/references/admin-session.md`](../docs/references/admin-session.md) under "`initialMessage` JSON envelope (Task 177)". Top-level keys exactly: `turns`, `conversationId`, `accountId`, `occurredAt`. `turns` is the full conversation transcript, oldest first, newest last, with each entry `{ role: "user"|"assistant", text, ts, toolCalls? }`. No windowing, no truncation. Multi-record assistant messages collapse on `message.id`. `tool_use` and matching `tool_result` blocks attach as a single `toolCalls` entry on the owning assistant turn; the user record carrying only the `tool_result` does not create a separate user turn. No leading instruction prose. `toolCalls[].input` and `toolCalls[].output` are native JSON values, never re-stringified. (Replaces Task 175's `(operatorMessage, assistantReply)` pair, which asserted a temporal Q→A relationship the walker never enforced.) One observability line `[turn-recorder] envelope sessionId=<op> turnsCount=<n> userTurns=<n> assistantTurns=<n> toolCallTurns=<n>` precedes `spawn-request`. The envelope rides on the `/spawn` body as a trailing positional argv to `claude`, so the database-operator session's JSONL first `role=user` line is the JSON object verbatim. No separate `POST /:id/input` call, no bracketed-paste, no keystroke injection. The recorder-auto-archive subscriber stops the recorder PTY as soon as its JSONL contains an assistant message with `stop_reason === "end_turn"`. **Task 129** — every emit goes through `POST /api/admin/log-ingest` so the lines land in `server.log` keyed by the operator session id. The chain is `trigger` → `spawn-request` → `spawn-success` → `input-delivered` → `tool-call` × N → `tool-result` × N → `write-complete` → `auto-archive`; each gated-off path emits one `trigger-skipped reason=<role-not-admin|is-recorder|empty-stdin|missing-transcript|conversation-empty>` line. Failure modes — `spawn-failed`, `tool-surface-missing`, `input-failed`, `write-empty`, `auto-archive reason=stale-recorder` — each emit one named line; absence is itself a defect.
132
+ - `hooks/turn-completed-graph-write.sh` — **Dormant since Task 214** — the Stop-hook registration is no longer written to account settings.json; admin delegates graph writes to `database-operator` via the Task tool. The script, envelope walker, loopback `/api/admin/claude-sessions` 127.0.0.1 bypass, `[turn-recorder]` emitters, recorder-auto-archive subscriber, and `initialMessage` envelope spec are preserved as reusable infrastructure for any future autonomous post-turn flow. Historical contract (still describes the dormant path): Stop hook fired once per completed admin-agent turn. Gates on `MAXY_SESSION_ROLE=admin` + `MAXY_SPECIALIST!=database-operator` so it never recurses into the recorder PTY or fires on public sessions. **Task 147** — the recorder is spawned via the same route Sidebar uses. ONE POST to `POST /api/admin/claude-sessions`, body carries `{specialist:'database-operator', model:'haiku', initialMessage:<json-envelope>, adminSessionId:<op>}` — no synthetic `senderId: 'turn-recorder'` marker. The Hono wrapper bypasses cookie auth on this exact method+path when the request originates from `127.0.0.1` (same trust boundary the claude-session-manager itself relies on), looks up the operator's senderId from the manager's `/<adminSessionId>/meta`, and forwards a Sidebar-shape spawn body. The `/recorder-spawn` sibling route is gone. The hook reads its UI port from `MAXY_UI_INTERNAL_PORT` (stamped on the manager systemd unit) — no fallback; absence emits `[turn-recorder] spawn-failed reason=missing-env env=MAXY_UI_INTERNAL_PORT` to stderr instead of silently 19199-ing. **Task 177** — `initialMessage` is a JSON-stringified envelope; the schema lives in [`platform/plugins/docs/references/admin-session.md`](../docs/references/admin-session.md) under "`initialMessage` JSON envelope (Task 177)". Top-level keys exactly: `turns`, `conversationId`, `accountId`, `occurredAt`. `turns` is the full conversation transcript, oldest first, newest last, with each entry `{ role: "user"|"assistant", text, ts, toolCalls? }`. No windowing, no truncation. Multi-record assistant messages collapse on `message.id`. `tool_use` and matching `tool_result` blocks attach as a single `toolCalls` entry on the owning assistant turn; the user record carrying only the `tool_result` does not create a separate user turn. No leading instruction prose. `toolCalls[].input` and `toolCalls[].output` are native JSON values, never re-stringified. (Replaces Task 175's `(operatorMessage, assistantReply)` pair, which asserted a temporal Q→A relationship the walker never enforced.) One observability line `[turn-recorder] envelope sessionId=<op> turnsCount=<n> userTurns=<n> assistantTurns=<n> toolCallTurns=<n>` precedes `spawn-request`. The envelope rides on the `/spawn` body as a trailing positional argv to `claude`, so the database-operator session's JSONL first `role=user` line is the JSON object verbatim. No separate `POST /:id/input` call, no bracketed-paste, no keystroke injection. The recorder-auto-archive subscriber stops the recorder PTY as soon as its JSONL contains an assistant message with `stop_reason === "end_turn"`. **Task 129** — every emit goes through `POST /api/admin/log-ingest` so the lines land in `server.log` keyed by the operator session id. The chain is `trigger` → `spawn-request` → `spawn-success` → `input-delivered` → `tool-call` × N → `tool-result` × N → `write-complete` → `auto-archive`; each gated-off path emits one `trigger-skipped reason=<role-not-admin|is-recorder|empty-stdin|missing-transcript|conversation-empty>` line. Failure modes — `spawn-failed`, `tool-surface-missing`, `input-failed`, `write-empty`, `auto-archive reason=stale-recorder` — each emit one named line; absence is itself a defect.
133
133
 
134
134
  ## Session identifiers (Task 135)
135
135
 
@@ -123,13 +123,14 @@ fi
123
123
  # and a PostToolUse regex matcher for parse tools.
124
124
  # UserPromptSubmit — archive-ingest-surface-gate.sh clears the
125
125
  # parse-error flag when the operator's next prompt arrives.
126
- # Stop — turn-completed-graph-write.sh fires once per admin foreground
127
- # turn and POSTs a hidden /spawn against the
128
- # database-operator specialist with the transcript tail
129
- # as stdin. The hook gates on MAXY_SESSION_ROLE=admin and
130
- # MAXY_HIDDEN_SPAWN=0 so public PTYs and the hidden
131
- # recorder PTY itself are no-ops. Per-turn graph writes
132
- # happen there, not in the admin agent's reply path.
126
+ #
127
+ # Task 214 the Stop-hook registration that fired
128
+ # turn-completed-graph-write.sh once per admin turn is no longer written.
129
+ # The script, envelope walker, loopback /api/admin/claude-sessions 127.0.0.1
130
+ # bypass, [turn-recorder] emitters, recorder-auto-archive subscriber, and
131
+ # initialMessage envelope spec are preserved as dormant infrastructure for
132
+ # any future autonomous post-turn flow. Admin now delegates graph writes
133
+ # to database-operator via the Task tool inside its own session.
133
134
  HOOKS_PATH="\$PLATFORM_ROOT/plugins/admin/hooks"
134
135
  cat > "$ACCOUNT_SETTINGS" << SETTINGS_EOF
135
136
  {
@@ -197,13 +198,6 @@ cat > "$ACCOUNT_SETTINGS" << SETTINGS_EOF
197
198
  { "type": "command", "command": "bash $HOOKS_PATH/archive-ingest-surface-gate.sh" }
198
199
  ]
199
200
  }
200
- ],
201
- "Stop": [
202
- {
203
- "hooks": [
204
- { "type": "command", "command": "bash $HOOKS_PATH/turn-completed-graph-write.sh" }
205
- ]
206
- }
207
201
  ]
208
202
  }
209
203
  }
@@ -11,6 +11,12 @@ export interface JsonlTailDeps {
11
11
  export interface JsonlTailRegisterArgs {
12
12
  specialist: string;
13
13
  argvTools: readonly string[];
14
+ /** Task 215 — fires once when the FIRST non-thinking `assistant` record
15
+ * emits a `[recorder-turn]` line. pty-spawner attaches this to fire
16
+ * the `[pty-spawn-tool-inventory-final]` snapshot. The tail invokes it
17
+ * fire-and-forget and clears the reference after the first call so
18
+ * multi-turn sessions don't re-trigger the snapshot. */
19
+ onFirstTurn?: () => void;
14
20
  }
15
21
  export interface JsonlTail {
16
22
  /** Called by pty-spawner at spawn time for the database-operator
@@ -1 +1 @@
1
- {"version":3,"file":"jsonl-tail.d.ts","sourceRoot":"","sources":["../src/jsonl-tail.ts"],"names":[],"mappings":"AA2CA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAWxC;;;uDAGuD;AACvD,MAAM,MAAM,aAAa,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;AAEjG,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,aAAa,CAAA;IAC1B,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,SAAS,MAAM,EAAE,CAAA;CAC7B;AAED,MAAM,WAAW,SAAS;IACxB;;qDAEiD;IACjD,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,qBAAqB,GAAG,IAAI,CAAA;IAC9D;;;8CAG0C;IAC1C,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACzD,iDAAiD;IACjD,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACnC,0EAA0E;IAC1E,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,OAAO,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;CACxG;AAkBD;;oDAEoD;AACpD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,aAAa,CAY3F;AA4GD,wBAAgB,eAAe,CAAC,IAAI,EAAE,aAAa,GAAG,SAAS,CAkL9D"}
1
+ {"version":3,"file":"jsonl-tail.d.ts","sourceRoot":"","sources":["../src/jsonl-tail.ts"],"names":[],"mappings":"AA2CA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAWxC;;;uDAGuD;AACvD,MAAM,MAAM,aAAa,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;AAEjG,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,aAAa,CAAA;IAC1B,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,SAAS,MAAM,EAAE,CAAA;IAC5B;;;;6DAIyD;IACzD,WAAW,CAAC,EAAE,MAAM,IAAI,CAAA;CACzB;AAED,MAAM,WAAW,SAAS;IACxB;;qDAEiD;IACjD,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,qBAAqB,GAAG,IAAI,CAAA;IAC9D;;;8CAG0C;IAC1C,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACzD,iDAAiD;IACjD,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACnC,0EAA0E;IAC1E,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,OAAO,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;CACxG;AA0BD;;oDAEoD;AACpD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,aAAa,CAY3F;AA4GD,wBAAgB,eAAe,CAAC,IAAI,EAAE,aAAa,GAAG,SAAS,CAoM9D"}
@@ -222,6 +222,25 @@ export function createJsonlTail(deps) {
222
222
  ` toolUseNames=${namesField}` +
223
223
  ` containsToolCallText=${containsToolCallText}`;
224
224
  deps.postLogLine('recorder-turn', 'info', line);
225
+ // Task 215 — fire the first-turn callback exactly once. The flag
226
+ // flip and reference clear happen BEFORE invoking the callback so a
227
+ // thrown callback can't leave `firstTurnEmitted=false` and re-fire
228
+ // on the next record. Errors from the callback are caught and
229
+ // logged but never propagate — the `recorder-turn` line above is
230
+ // the contract, and the callback is a downstream observer.
231
+ if (!state.firstTurnEmitted) {
232
+ state.firstTurnEmitted = true;
233
+ const cb = state.onFirstTurn;
234
+ state.onFirstTurn = null;
235
+ if (cb !== null) {
236
+ try {
237
+ cb();
238
+ }
239
+ catch (err) {
240
+ deps.logger(`[jsonl-tail] first-turn-callback-threw sessionId=${state.sessionId} err=${err instanceof Error ? err.message : String(err)}`);
241
+ }
242
+ }
243
+ }
225
244
  }
226
245
  function processRecord(state, rec) {
227
246
  // Probe init candidates against EVERY record until init emits — the
@@ -329,6 +348,8 @@ export function createJsonlTail(deps) {
329
348
  initEmitted: false,
330
349
  emittedMsgIds: new Set(),
331
350
  nextTurnIndex: 0,
351
+ onFirstTurn: args.onFirstTurn ?? null,
352
+ firstTurnEmitted: false,
332
353
  });
333
354
  deps.logger(`[jsonl-tail] register sessionId=${sessionId} specialist=${args.specialist} argvTools=${argvTools.size}`);
334
355
  },
@@ -1 +1 @@
1
- {"version":3,"file":"jsonl-tail.js","sourceRoot":"","sources":["../src/jsonl-tail.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,2EAA2E;AAC3E,wEAAwE;AACxE,sBAAsB;AACtB,EAAE;AACF,uEAAuE;AACvE,0EAA0E;AAC1E,mEAAmE;AACnE,0EAA0E;AAC1E,0EAA0E;AAC1E,uEAAuE;AACvE,wEAAwE;AACxE,yEAAyE;AACzE,0EAA0E;AAC1E,yEAAyE;AACzE,wEAAwE;AACxE,wEAAwE;AACxE,wEAAwE;AACxE,mEAAmE;AACnE,yEAAyE;AACzE,uEAAuE;AACvE,gEAAgE;AAChE,EAAE;AACF,0EAA0E;AAC1E,qDAAqD;AACrD,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,wEAAwE;AACxE,0EAA0E;AAC1E,6DAA6D;AAC7D,yEAAyE;AACzE,2EAA2E;AAC3E,sEAAsE;AACtE,2EAA2E;AAC3E,EAAE;AACF,0EAA0E;AAC1E,mEAAmE;AACnE,wEAAwE;AACxE,0EAA0E;AAC1E,sDAAsD;AAEtD,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAG7E,MAAM,eAAe,GAAG,EAAE,GAAG,IAAI,CAAA;AACjC,kEAAkE;AAClE,wEAAwE;AACxE,yEAAyE;AACzE,iEAAiE;AACjE,0EAA0E;AAC1E,wCAAwC;AACxC,MAAM,sBAAsB,GAAG,4CAA4C,CAAA;AAkD3E;;oDAEoD;AACpD,MAAM,UAAU,mBAAmB,CAAC,IAAwC;IAC1E,MAAM,GAAG,GAAG,oBAAoB,IAAI,CAAC,MAAM,uBAAuB,CAAA;IAClE,OAAO,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QAC1B,KAAK,KAAK,CAAC,GAAG,EAAE;YACd,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;SAC3C,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACf,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YAC5D,IAAI,CAAC,MAAM,CAAC,2CAA2C,GAAG,QAAQ,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QAC1F,CAAC,CAAC,CAAA;IACJ,CAAC,CAAA;AACH,CAAC;AAED;;2BAE2B;AAC3B,SAAS,UAAU,CAAC,IAAY;IAC9B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAA;IAC3B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IACrC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;QAC/B,IAAI,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1D,OAAO,GAA8B,CAAA;QACvC,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC;AAED;;;;;;;gDAOgD;AAChD,SAAS,cAAc,CAAC,GAA4B;IAClD,uEAAuE;IACvE,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,IAAI,GAAG,CAAC,OAAO,KAAK,MAAM,EAAE,CAAC;QACpD,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAA;QACvB,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACzB,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAA;YACrE,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;gBAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,KAAK,EAAE,CAAA;QACtE,CAAC;IACH,CAAC;IACD,gEAAgE;IAChE,8CAA8C;IAC9C,MAAM,GAAG,GAAG,GAAG,CAAC,UAAU,CAAA;IAC1B,IAAI,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1D,MAAM,CAAC,GAAG,GAA8B,CAAA;QACxC,IAAI,CAAC,CAAC,IAAI,KAAK,qBAAqB,EAAE,CAAC;YACrC,MAAM,OAAO,GAAG,CAAC,CAAC,YAAY,CAAA;YAC9B,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC3B,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAA;gBACvE,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;oBAAE,OAAO,EAAE,MAAM,EAAE,qBAAqB,EAAE,KAAK,EAAE,KAAK,EAAE,CAAA;YAC9E,CAAC;QACH,CAAC;QACD,oEAAoE;QACpE,qEAAqE;QACrE,8BAA8B;QAC9B,IAAI,CAAC,CAAC,IAAI,KAAK,sBAAsB,EAAE,CAAC;YACtC,MAAM,KAAK,GAAG,CAAC,CAAC,UAAU,CAAA;YAC1B,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBACzB,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAA;gBACrE,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;oBAAE,OAAO,EAAE,MAAM,EAAE,sBAAsB,EAAE,KAAK,EAAE,KAAK,EAAE,CAAA;YAC/E,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED;;;yCAGyC;AACzC,SAAS,UAAU,CAAC,CAAS;IAC3B,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;AAC1B,CAAC;AAUD,SAAS,wBAAwB,CAAC,GAA4B;IAC5D,IAAI,GAAG,CAAC,IAAI,KAAK,WAAW;QAAE,OAAO,IAAI,CAAA;IACzC,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAA;IACvB,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAA;IACtE,MAAM,CAAC,GAAG,GAA8B,CAAA;IACxC,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;IACpD,MAAM,UAAU,GAAG,OAAO,CAAC,CAAC,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAA;IACzE,MAAM,OAAO,GAAG,CAAC,CAAC,OAAO,CAAA;IACzB,IAAI,IAAI,GAAG,EAAE,CAAA;IACb,MAAM,YAAY,GAAa,EAAE,CAAA;IACjC,IAAI,WAAW,GAAG,KAAK,CAAA;IACvB,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3B,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;gBAAE,SAAQ;YACjD,MAAM,CAAC,GAAG,KAAgC,CAAA;YAC1C,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACpD,IAAI,IAAI,CAAC,CAAC,IAAI,CAAA;YAChB,CAAC;iBAAM,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC/D,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;YAC3B,CAAC;iBAAM,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;gBACjC,WAAW,GAAG,IAAI,CAAA;YACpB,CAAC;QACH,CAAC;IACH,CAAC;SAAM,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QACvC,IAAI,GAAG,OAAO,CAAA;IAChB,CAAC;IACD,MAAM,cAAc,GAAG,WAAW,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,CAAA;IACpF,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,YAAY,EAAE,cAAc,EAAE,CAAA;AAClE,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAmB;IACjD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAwB,CAAA;IAEhD,SAAS,aAAa,CAAC,KAAmB,EAAE,MAAc,EAAE,OAA0B;QACpF,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAA;QACnC,MAAM,OAAO,GAAa,EAAE,CAAA;QAC5B,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;YAChC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;gBAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACzC,CAAC;QACD,OAAO,CAAC,IAAI,EAAE,CAAA;QACd,MAAM,IAAI,GACR,aAAa,KAAK,CAAC,SAAS,eAAe,KAAK,CAAC,UAAU,EAAE;YAC7D,sBAAsB,OAAO,CAAC,MAAM,iBAAiB,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;YACxE,mBAAmB,KAAK,CAAC,SAAS,CAAC,IAAI,EAAE;YACzC,gCAAgC,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;YAChF,WAAW,MAAM,EAAE,CAAA;QACrB,IAAI,CAAC,WAAW,CAAC,uBAAuB,EAAE,MAAM,EAAE,IAAI,CAAC,CAAA;QACvD,KAAK,CAAC,WAAW,GAAG,IAAI,CAAA;IAC1B,CAAC;IAED,SAAS,oBAAoB,CAAC,KAAmB;QAC/C,mEAAmE;QACnE,oEAAoE;QACpE,+CAA+C;QAC/C,yEAAyE;QACzE,sEAAsE;QACtE,oEAAoE;QACpE,sEAAsE;QACtE,gEAAgE;QAChE,sEAAsE;QACtE,sEAAsE;QACtE,qEAAqE;QACrE,uBAAuB;QACvB,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,CAAA;QAClD,MAAM,IAAI,GACR,aAAa,KAAK,CAAC,SAAS,eAAe,KAAK,CAAC,UAAU,EAAE;YAC7D,sBAAsB,OAAO,CAAC,MAAM,iBAAiB,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;YACxE,mBAAmB,KAAK,CAAC,SAAS,CAAC,IAAI,EAAE;YACzC,gCAAgC;YAChC,gCAAgC,CAAA;QAClC,IAAI,CAAC,WAAW,CAAC,uBAAuB,EAAE,MAAM,EAAE,IAAI,CAAC,CAAA;QACvD,KAAK,CAAC,WAAW,GAAG,IAAI,CAAA;IAC1B,CAAC;IAED,SAAS,QAAQ,CAAC,KAAmB,EAAE,OAAyB;QAC9D,MAAM,GAAG,GAAG,KAAK,CAAC,aAAa,CAAA;QAC/B,KAAK,CAAC,aAAa,IAAI,CAAC,CAAA;QACxB,MAAM,SAAS,GAAG,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;QACzD,MAAM,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAC3F,MAAM,oBAAoB,GAAG,sBAAsB,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;QACtE,MAAM,IAAI,GACR,aAAa,KAAK,CAAC,SAAS,cAAc,GAAG,EAAE;YAC/C,eAAe,OAAO,CAAC,UAAU,IAAI,GAAG,EAAE;YAC1C,cAAc,SAAS,EAAE;YACzB,SAAS,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;YACnC,iBAAiB,UAAU,EAAE;YAC7B,yBAAyB,oBAAoB,EAAE,CAAA;QACjD,IAAI,CAAC,WAAW,CAAC,eAAe,EAAE,MAAM,EAAE,IAAI,CAAC,CAAA;IACjD,CAAC;IAED,SAAS,aAAa,CAAC,KAAmB,EAAE,GAA4B;QACtE,oEAAoE;QACpE,oEAAoE;QACpE,wEAAwE;QACxE,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;YACvB,MAAM,MAAM,GAAG,cAAc,CAAC,GAAG,CAAC,CAAA;YAClC,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;gBACpB,aAAa,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAA;YACnD,CAAC;QACH,CAAC;QACD,8DAA8D;QAC9D,MAAM,OAAO,GAAG,wBAAwB,CAAC,GAAG,CAAC,CAAA;QAC7C,IAAI,OAAO,KAAK,IAAI;YAAE,OAAM;QAC5B,IAAI,OAAO,CAAC,cAAc;YAAE,OAAM;QAClC,oEAAoE;QACpE,uDAAuD;QACvD,0DAA0D;QAC1D,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;YACvB,oBAAoB,CAAC,KAAK,CAAC,CAAA;QAC7B,CAAC;QACD,IAAI,OAAO,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;YAC3B,IAAI,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC;gBAAE,OAAM;YAClD,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;QACxC,CAAC;QACD,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;IAC1B,CAAC;IAED,SAAS,YAAY,CAAC,KAAmB,EAAE,SAAiB;QAC1D,IAAI,KAAK,CAAA;QACT,IAAI,CAAC;YACH,KAAK,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAA;QAC7B,CAAC;QAAC,MAAM,CAAC;YACP,OAAM;QACR,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;YAAE,OAAM;QAC3B,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAA;QACvB,IAAI,IAAI,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;YAC/B,+DAA+D;YAC/D,sCAAsC;YACtC,IAAI,IAAI,GAAG,KAAK,CAAC,YAAY,EAAE,CAAC;gBAC9B,KAAK,CAAC,YAAY,GAAG,CAAC,CAAA;gBACtB,KAAK,CAAC,WAAW,GAAG,EAAE,CAAA;YACxB,CAAC;YACD,OAAM;QACR,CAAC;QACD,IAAI,EAAU,CAAA;QACd,IAAI,CAAC;YACH,EAAE,GAAG,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,CAAA;QAC/B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,MAAM,CAAC,sCAAsC,KAAK,CAAC,SAAS,SAAS,SAAS,QAAQ,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;YAC9I,OAAM;QACR,CAAC;QACD,IAAI,CAAC;YACH,IAAI,MAAM,GAAG,KAAK,CAAC,YAAY,CAAA;YAC/B,IAAI,MAAM,GAAG,KAAK,CAAC,WAAW,CAAA;YAC9B,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,CAAA;YAC3C,OAAO,MAAM,GAAG,IAAI,EAAE,CAAC;gBACrB,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,eAAe,EAAE,IAAI,GAAG,MAAM,CAAC,CAAA;gBACrD,MAAM,CAAC,GAAG,QAAQ,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,CAAA;gBAC9C,IAAI,CAAC,IAAI,CAAC;oBAAE,MAAK;gBACjB,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;gBACtC,MAAM,IAAI,CAAC,CAAA;YACb,CAAC;YACD,mEAAmE;YACnE,iEAAiE;YACjE,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;YACvC,MAAM,aAAa,GAAG,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAA;YAClE,MAAM,SAAS,GAAG,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;YACnE,KAAK,CAAC,YAAY,GAAG,MAAM,CAAA;YAC3B,KAAK,CAAC,WAAW,GAAG,SAAS,CAAA;YAC7B,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAM;YACtC,KAAK,MAAM,GAAG,IAAI,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC5C,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,CAAA;gBAC3B,IAAI,GAAG,KAAK,IAAI;oBAAE,SAAQ;gBAC1B,aAAa,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;YAC3B,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC;gBAAC,SAAS,CAAC,EAAE,CAAC,CAAA;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IAED,OAAO;QACL,QAAQ,CAAC,SAAS,EAAE,IAAI;YACtB,IAAI,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC;gBAAE,OAAM;YACnC,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAA;YACnG,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE;gBACtB,SAAS;gBACT,UAAU,EAAE,IAAI,CAAC,UAAU;gBAC3B,SAAS;gBACT,YAAY,EAAE,CAAC;gBACf,WAAW,EAAE,EAAE;gBACf,WAAW,EAAE,KAAK;gBAClB,aAAa,EAAE,IAAI,GAAG,EAAE;gBACxB,aAAa,EAAE,CAAC;aACjB,CAAC,CAAA;YACF,IAAI,CAAC,MAAM,CAAC,mCAAmC,SAAS,eAAe,IAAI,CAAC,UAAU,cAAc,SAAS,CAAC,IAAI,EAAE,CAAC,CAAA;QACvH,CAAC;QACD,aAAa,CAAC,SAAS,EAAE,SAAS;YAChC,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;YACrC,IAAI,CAAC,KAAK;gBAAE,OAAM;YAClB,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;gBAAE,OAAM;YAClC,YAAY,CAAC,KAAK,EAAE,SAAS,CAAC,CAAA;QAChC,CAAC;QACD,UAAU,CAAC,SAAS;YAClB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC;gBAAE,OAAM;YACpC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;YAC1B,IAAI,CAAC,MAAM,CAAC,qCAAqC,SAAS,EAAE,CAAC,CAAA;QAC/D,CAAC;QACD,MAAM,CAAC,SAAS;YACd,MAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;YACjC,IAAI,CAAC,CAAC;gBAAE,OAAO,IAAI,CAAA;YACnB,OAAO;gBACL,YAAY,EAAE,CAAC,CAAC,YAAY;gBAC5B,WAAW,EAAE,CAAC,CAAC,WAAW;gBAC1B,aAAa,EAAE,CAAC,CAAC,aAAa;aAC/B,CAAA;QACH,CAAC;KACF,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"jsonl-tail.js","sourceRoot":"","sources":["../src/jsonl-tail.ts"],"names":[],"mappings":"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"}
@@ -204,10 +204,57 @@ interface McpConfigWriteParams {
204
204
  * names in the order they were declared (the caller sorts before
205
205
  * emitting argv). */
206
206
  export declare function readSpecialistTools(claudeConfigDir: string, specialist: string): string[];
207
+ /** Task 215 — pull the `<server>` segment out of a qualified MCP tool name
208
+ * the way Claude Code's plugin-tool registry surfaces it. Two shapes
209
+ * exist in the wild:
210
+ *
211
+ * - Long prefix: `mcp__plugin_<plugin>_<server>__<tool>` — emitted by
212
+ * Claude Code when an MCP server is registered via plugin manifest
213
+ * (post-Task-209 native plugin-system path; what `--agent <name>`
214
+ * specialist spawns receive in Registry #1).
215
+ * - Short prefix: `mcp__<server>__<tool>` — emitted by Claude Code when
216
+ * an MCP server is registered via `--mcp-config <path>` (admin operator
217
+ * spawns; what Registry #2 produces directly).
218
+ *
219
+ * Both must resolve to the same `<server>` slug so the probe can match
220
+ * the qualified name against `toolSurface.mcpServers` keys, which the
221
+ * manager populates from PLUGIN.md basenames in `tool-surface.ts`. The
222
+ * pre-Task-215 inline regex `/^mcp__(.+?)__/` extracted `plugin_<plugin>_<server>`
223
+ * from the long-prefix shape (lazy match stops at the first `__`),
224
+ * which never matched any tool-surface key — the failure mode this
225
+ * helper closes.
226
+ *
227
+ * Returns `null` for any name that matches neither shape. The caller
228
+ * surfaces those names through the inventory line's `unparseable-tools=`
229
+ * field so a malformed agent-frontmatter entry can't masquerade as a
230
+ * missing server. */
231
+ export declare function extractServerNameFromQualifiedTool(qualified: string): string | null;
232
+ /** Task 215 — classify the agent's frontmatter `tools:` list against the
233
+ * manager's tool-surface registry. Used by both the per-spawn `.mcp.json`
234
+ * writer (admin) and the tool-inventory probe (specialist). Returns the
235
+ * set of server names to spawn AND the two diagnostic sets the inventory
236
+ * line surfaces when non-empty: tokens that didn't parse at all
237
+ * (`unparseableTools`) and parseable tokens whose server isn't in the
238
+ * registry (`missingServers`). Both diagnostic sets are empty in the
239
+ * healthy case, so the existing log line shape stays unchanged for
240
+ * passing spawns. */
241
+ export declare function classifySpecialistTools(tools: readonly string[], toolSurfaceServers: ReadonlyMap<string, unknown>): {
242
+ matchedServers: ReadonlySet<string>;
243
+ unparseableTools: readonly string[];
244
+ missingServers: readonly string[];
245
+ };
207
246
  /** Builds the placeholder map for per-spawn `mcp.json` env substitution.
208
247
  * Exported for Task 142 unit coverage that asserts `PLATFORM_PORT` and
209
248
  * `MAXY_BRAND_PORT` resolve from the manager process env. */
210
249
  export declare function buildMcpPlaceholders(p: Pick<McpConfigWriteParams, 'platformRoot' | 'accountId' | 'userId' | 'bridgeSuffixHint' | 'logDir'>, env?: NodeJS.ProcessEnv): Record<string, string>;
250
+ /** Test seam. Production never calls this; the `__` prefix matches the
251
+ * in-repo convention for non-API helpers. */
252
+ export declare function __setFirstTurnTimeoutMsForTests(ms: number): void;
253
+ export declare function __resetFirstTurnTimeoutMsForTests(): void;
254
+ /** Test seam — clear any leftover per-spawn state between tests so a
255
+ * failing test doesn't pollute the next one's Map. Production never
256
+ * invokes this; the only legitimate eviction path is PTY exit. */
257
+ export declare function __clearFinalSnapshotStateForTests(): void;
211
258
  export declare function spawnClaudeSession(deps: SpawnDeps, args: SpawnArgs): Promise<SpawnResult>;
212
259
  export interface StopDeps {
213
260
  store: SessionStore;
@@ -1 +1 @@
1
- {"version":3,"file":"pty-spawner.d.ts","sourceRoot":"","sources":["../src/pty-spawner.ts"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAElE,OAAO,EAAE,YAAY,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAA;AACrE,OAAO,KAAK,EAAE,SAAS,EAAc,MAAM,iBAAiB,CAAA;AAC5D,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,wBAAwB,EAC9B,MAAM,sBAAsB,CAAA;AA+B7B,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACtB,MAAM,oBAAoB,CAAA;AAE3B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AACpD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAEhD,MAAM,MAAM,kBAAkB,GAC1B,wBAAwB,GACxB,kBAAkB,GAClB,kBAAkB,GAClB,yBAAyB,GACzB,qBAAqB,GACrB,yBAAyB,CAAA;AAE7B,MAAM,MAAM,oBAAoB,GAC5B,wBAAwB,GACxB,yBAAyB,CAAA;AAE7B,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,wBAAwB,CAAA;IAC9B,YAAY,EAAE,MAAM,CAAA;IACpB,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,yBAAyB,CAAA;IAC/B,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,MAAM,WAAW,GACnB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,aAAa,CAAA;CAAE,GACpC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,kBAAkB,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAC7D;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,sBAAsB,GAAG,wBAAwB,CAAA;CAAE,CAAA;AAE9E,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,KAAK,SAAS,CAAA;IAC5E,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB;qDACiD;IACjD,gBAAgB,EAAE,MAAM,CAAA;IACxB;6DACyD;IACzD,mBAAmB,EAAE,MAAM,CAAA;IAC3B,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,YAAY,CAAA;IACnB,OAAO,EAAE,SAAS,CAAA;IAClB,IAAI,EAAE,cAAc,CAAA;IACpB,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,YAAY,EAAE,MAAM,CAAA;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC,CAAA;IACrD,wBAAwB,EAAE,MAAM,CAAA;IAChC;;;;;sBAKkB;IAClB,eAAe,EAAE,MAAM,CAAA;IACvB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,WAAW,EAAE,WAAW,CAAA;IACxB;;mBAEe;IACf,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,CAAA;IACjD;;;;;8EAK0E;IAC1E,aAAa,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAA;IAC3C,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACjC,kEAAkE;IAClE,aAAa,EAAE,MAAM,CAAA;IACrB,oDAAoD;IACpD,eAAe,EAAE,MAAM,CAAA;IACvB,4EAA4E;IAC5E,WAAW,EAAE,MAAM,CAAA;IACnB;;;;;;iEAM6D;IAC7D,uBAAuB,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAA;IAClE;;;;;;;;;;2BAUuB;IACvB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB;;;;;;4CAMwC;IACxC,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAC7B;;;;+DAI2D;IAC3D,oBAAoB,CAAC,EAAE,CAAC,GAAG,EAAE;QAC3B,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAAA;QACtD,SAAS,EAAE,MAAM,CAAA;KAClB,KAAK,OAAO,CAAC,cAAc,CAAC,CAAA;IAC7B;;sDAEkD;IAClD,2BAA2B,CAAC,EAAE,MAAM,CAAA;IACpC;;;;;;qEAMiE;IACjE,SAAS,CAAC,EAAE,SAAS,CAAA;CACtB;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,cAAc,EAAE,WAAW,CAAC,MAAM,CAK7C,CAAA;AAEF,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAA;IAChB;;;;;yEAKqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,IAAI,CAAA;IACV,OAAO,EAAE,OAAO,CAAA;IAChB,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IACnB,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,UAAU,CAAC,EAAE,iBAAiB,CAAA;IAC9B,cAAc,CAAC,EAAE,SAAS,aAAa,EAAE,CAAA;IACzC,aAAa,CAAC,EAAE,SAAS,YAAY,EAAE,CAAA;IACvC,iBAAiB,CAAC,EAAE,SAAS,gBAAgB,EAAE,CAAA;IAC/C,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;kEAG8D;IAC9D,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;;;0BAKsB;IACtB,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,aAAa,GAAG,MAAM,GAAG,MAAM,GAAG,mBAAmB,CAAA;AAC9F,eAAO,MAAM,gBAAgB,EAAE,SAAS,cAAc,EAAoE,CAAA;AAE1H,UAAU,oBAAoB;IAC5B,IAAI,EAAE,IAAI,CAAA;IACV,WAAW,EAAE,WAAW,CAAA;IACxB,SAAS,EAAE,MAAM,CAAA;IACjB;;;kBAGc;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,YAAY,EAAE,MAAM,CAAA;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,gBAAgB,EAAE,MAAM,CAAA;IACxB,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd;;;;mBAIe;IACf,eAAe,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAAA;CAC1C;AAiBD;;;;;;sBAMsB;AACtB,wBAAgB,mBAAmB,CAAC,eAAe,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAmCzF;AAWD;;8DAE8D;AAC9D,wBAAgB,oBAAoB,CAClC,CAAC,EAAE,IAAI,CAAC,oBAAoB,EAAE,cAAc,GAAG,WAAW,GAAG,QAAQ,GAAG,kBAAkB,GAAG,QAAQ,CAAC,EACtG,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAsBxB;AAwLD,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CA2gB/F;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,YAAY,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;CACf;AAED;;;;;;;;;;;;;;;;;;;;;YAqBY;AACZ,wBAAgB,oBAAoB,CAClC,IAAI,EAAE;IAAE,KAAK,EAAE,YAAY,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAC7C,OAAO,EAAE,aAAa,EACtB,IAAI,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,EAC3C,UAAU,EAAE,MAAM,GACjB,IAAI,CAYN;AAmBD;0EAC0E;AAC1E,wBAAsB,WAAW,CAC/B,IAAI,EAAE,QAAQ,EACd,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CA+B/B"}
1
+ {"version":3,"file":"pty-spawner.d.ts","sourceRoot":"","sources":["../src/pty-spawner.ts"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAElE,OAAO,EAAE,YAAY,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAA;AACrE,OAAO,KAAK,EAAE,SAAS,EAAc,MAAM,iBAAiB,CAAA;AAC5D,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,wBAAwB,EAC9B,MAAM,sBAAsB,CAAA;AA+B7B,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACtB,MAAM,oBAAoB,CAAA;AAE3B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AACpD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAEhD,MAAM,MAAM,kBAAkB,GAC1B,wBAAwB,GACxB,kBAAkB,GAClB,kBAAkB,GAClB,yBAAyB,GACzB,qBAAqB,GACrB,yBAAyB,CAAA;AAE7B,MAAM,MAAM,oBAAoB,GAC5B,wBAAwB,GACxB,yBAAyB,CAAA;AAE7B,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,wBAAwB,CAAA;IAC9B,YAAY,EAAE,MAAM,CAAA;IACpB,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,yBAAyB,CAAA;IAC/B,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,MAAM,WAAW,GACnB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,aAAa,CAAA;CAAE,GACpC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,kBAAkB,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAC7D;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,sBAAsB,GAAG,wBAAwB,CAAA;CAAE,CAAA;AAE9E,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,KAAK,SAAS,CAAA;IAC5E,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB;qDACiD;IACjD,gBAAgB,EAAE,MAAM,CAAA;IACxB;6DACyD;IACzD,mBAAmB,EAAE,MAAM,CAAA;IAC3B,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,YAAY,CAAA;IACnB,OAAO,EAAE,SAAS,CAAA;IAClB,IAAI,EAAE,cAAc,CAAA;IACpB,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,YAAY,EAAE,MAAM,CAAA;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC,CAAA;IACrD,wBAAwB,EAAE,MAAM,CAAA;IAChC;;;;;sBAKkB;IAClB,eAAe,EAAE,MAAM,CAAA;IACvB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,WAAW,EAAE,WAAW,CAAA;IACxB;;mBAEe;IACf,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,CAAA;IACjD;;;;;8EAK0E;IAC1E,aAAa,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAA;IAC3C,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACjC,kEAAkE;IAClE,aAAa,EAAE,MAAM,CAAA;IACrB,oDAAoD;IACpD,eAAe,EAAE,MAAM,CAAA;IACvB,4EAA4E;IAC5E,WAAW,EAAE,MAAM,CAAA;IACnB;;;;;;iEAM6D;IAC7D,uBAAuB,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAA;IAClE;;;;;;;;;;2BAUuB;IACvB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB;;;;;;4CAMwC;IACxC,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAC7B;;;;+DAI2D;IAC3D,oBAAoB,CAAC,EAAE,CAAC,GAAG,EAAE;QAC3B,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAAA;QACtD,SAAS,EAAE,MAAM,CAAA;KAClB,KAAK,OAAO,CAAC,cAAc,CAAC,CAAA;IAC7B;;sDAEkD;IAClD,2BAA2B,CAAC,EAAE,MAAM,CAAA;IACpC;;;;;;qEAMiE;IACjE,SAAS,CAAC,EAAE,SAAS,CAAA;CACtB;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,cAAc,EAAE,WAAW,CAAC,MAAM,CAK7C,CAAA;AAEF,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAA;IAChB;;;;;yEAKqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,IAAI,CAAA;IACV,OAAO,EAAE,OAAO,CAAA;IAChB,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IACnB,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,UAAU,CAAC,EAAE,iBAAiB,CAAA;IAC9B,cAAc,CAAC,EAAE,SAAS,aAAa,EAAE,CAAA;IACzC,aAAa,CAAC,EAAE,SAAS,YAAY,EAAE,CAAA;IACvC,iBAAiB,CAAC,EAAE,SAAS,gBAAgB,EAAE,CAAA;IAC/C,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;kEAG8D;IAC9D,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;;;0BAKsB;IACtB,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,aAAa,GAAG,MAAM,GAAG,MAAM,GAAG,mBAAmB,CAAA;AAC9F,eAAO,MAAM,gBAAgB,EAAE,SAAS,cAAc,EAAoE,CAAA;AAE1H,UAAU,oBAAoB;IAC5B,IAAI,EAAE,IAAI,CAAA;IACV,WAAW,EAAE,WAAW,CAAA;IACxB,SAAS,EAAE,MAAM,CAAA;IACjB;;;kBAGc;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,YAAY,EAAE,MAAM,CAAA;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,gBAAgB,EAAE,MAAM,CAAA;IACxB,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd;;;;mBAIe;IACf,eAAe,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAAA;CAC1C;AAiBD;;;;;;sBAMsB;AACtB,wBAAgB,mBAAmB,CAAC,eAAe,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAmCzF;AAWD;;;;;;;;;;;;;;;;;;;;;;;sBAuBsB;AACtB,wBAAgB,kCAAkC,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAanF;AAED;;;;;;;;sBAQsB;AACtB,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,kBAAkB,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/C;IACD,cAAc,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;IACnC,gBAAgB,EAAE,SAAS,MAAM,EAAE,CAAA;IACnC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAA;CAClC,CAqBA;AAED;;8DAE8D;AAC9D,wBAAgB,oBAAoB,CAClC,CAAC,EAAE,IAAI,CAAC,oBAAoB,EAAE,cAAc,GAAG,WAAW,GAAG,QAAQ,GAAG,kBAAkB,GAAG,QAAQ,CAAC,EACtG,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAsBxB;AA6PD;8CAC8C;AAC9C,wBAAgB,+BAA+B,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAEhE;AACD,wBAAgB,iCAAiC,IAAI,IAAI,CAExD;AAgDD;;mEAEmE;AACnE,wBAAgB,iCAAiC,IAAI,IAAI,CAKxD;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CA+jB/F;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,YAAY,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;CACf;AAED;;;;;;;;;;;;;;;;;;;;;YAqBY;AACZ,wBAAgB,oBAAoB,CAClC,IAAI,EAAE;IAAE,KAAK,EAAE,YAAY,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAC7C,OAAO,EAAE,aAAa,EACtB,IAAI,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,EAC3C,UAAU,EAAE,MAAM,GACjB,IAAI,CAYN;AAmBD;0EAC0E;AAC1E,wBAAsB,WAAW,CAC/B,IAAI,EAAE,QAAQ,EACd,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CA+B/B"}
@@ -120,6 +120,78 @@ function expandPlaceholders(raw, vars) {
120
120
  return Object.prototype.hasOwnProperty.call(vars, name) ? vars[name] : m;
121
121
  });
122
122
  }
123
+ /** Task 215 — pull the `<server>` segment out of a qualified MCP tool name
124
+ * the way Claude Code's plugin-tool registry surfaces it. Two shapes
125
+ * exist in the wild:
126
+ *
127
+ * - Long prefix: `mcp__plugin_<plugin>_<server>__<tool>` — emitted by
128
+ * Claude Code when an MCP server is registered via plugin manifest
129
+ * (post-Task-209 native plugin-system path; what `--agent <name>`
130
+ * specialist spawns receive in Registry #1).
131
+ * - Short prefix: `mcp__<server>__<tool>` — emitted by Claude Code when
132
+ * an MCP server is registered via `--mcp-config <path>` (admin operator
133
+ * spawns; what Registry #2 produces directly).
134
+ *
135
+ * Both must resolve to the same `<server>` slug so the probe can match
136
+ * the qualified name against `toolSurface.mcpServers` keys, which the
137
+ * manager populates from PLUGIN.md basenames in `tool-surface.ts`. The
138
+ * pre-Task-215 inline regex `/^mcp__(.+?)__/` extracted `plugin_<plugin>_<server>`
139
+ * from the long-prefix shape (lazy match stops at the first `__`),
140
+ * which never matched any tool-surface key — the failure mode this
141
+ * helper closes.
142
+ *
143
+ * Returns `null` for any name that matches neither shape. The caller
144
+ * surfaces those names through the inventory line's `unparseable-tools=`
145
+ * field so a malformed agent-frontmatter entry can't masquerade as a
146
+ * missing server. */
147
+ export function extractServerNameFromQualifiedTool(qualified) {
148
+ // Long prefix has the literal `plugin` marker between `mcp__` and the
149
+ // plugin slug — Claude Code stamps it for every plugin-manifest MCP
150
+ // server, even when plugin and server slugs are equal (the common
151
+ // maxy case: plugin=memory, server=memory).
152
+ const longMatch = qualified.match(/^mcp__plugin_([^_]+)_([^_]+)__/);
153
+ if (longMatch)
154
+ return longMatch[2];
155
+ // Short prefix has no `plugin` marker; the first segment IS the server
156
+ // slug. Used by admin's `--mcp-config` registrations and by any
157
+ // historical fixture that predates the plugin-manifest rename.
158
+ const shortMatch = qualified.match(/^mcp__([^_]+)__/);
159
+ if (shortMatch)
160
+ return shortMatch[1];
161
+ return null;
162
+ }
163
+ /** Task 215 — classify the agent's frontmatter `tools:` list against the
164
+ * manager's tool-surface registry. Used by both the per-spawn `.mcp.json`
165
+ * writer (admin) and the tool-inventory probe (specialist). Returns the
166
+ * set of server names to spawn AND the two diagnostic sets the inventory
167
+ * line surfaces when non-empty: tokens that didn't parse at all
168
+ * (`unparseableTools`) and parseable tokens whose server isn't in the
169
+ * registry (`missingServers`). Both diagnostic sets are empty in the
170
+ * healthy case, so the existing log line shape stays unchanged for
171
+ * passing spawns. */
172
+ export function classifySpecialistTools(tools, toolSurfaceServers) {
173
+ const matchedServers = new Set();
174
+ const unparseable = [];
175
+ const missingSet = new Set();
176
+ for (const t of tools) {
177
+ const server = extractServerNameFromQualifiedTool(t);
178
+ if (server === null) {
179
+ unparseable.push(t);
180
+ continue;
181
+ }
182
+ if (toolSurfaceServers.has(server)) {
183
+ matchedServers.add(server);
184
+ }
185
+ else if (!missingSet.has(server)) {
186
+ missingSet.add(server);
187
+ }
188
+ }
189
+ return {
190
+ matchedServers,
191
+ unparseableTools: unparseable,
192
+ missingServers: Array.from(missingSet),
193
+ };
194
+ }
123
195
  /** Builds the placeholder map for per-spawn `mcp.json` env substitution.
124
196
  * Exported for Task 142 unit coverage that asserts `PLATFORM_PORT` and
125
197
  * `MAXY_BRAND_PORT` resolve from the manager process env. */
@@ -152,16 +224,19 @@ function writePerSpawnMcpConfig(p) {
152
224
  // Task 165 — specialist spawn. Project the agent's `tools:`
153
225
  // frontmatter to the set of plugin namespaces it references; include
154
226
  // only those MCP servers. A specialist that only writes graph
155
- // (database-operator: memory, contacts, tasks) does not get the
227
+ // (database-operator: memory, contacts, work) does not get the
156
228
  // dozens of other admin servers stamped into its mcp.json.
157
- const specialistPluginNames = new Set();
158
- for (const t of p.specialistTools) {
159
- const m = t.match(/^mcp__(.+?)__/);
160
- if (m)
161
- specialistPluginNames.add(m[1]);
162
- }
229
+ //
230
+ // Task 215 uses `classifySpecialistTools` so post-Task-209
231
+ // long-prefix names (`mcp__plugin_<plugin>_<server>__<tool>`) resolve
232
+ // to their `<server>` slug rather than the legacy lazy-regex capture
233
+ // of `plugin_<plugin>_<server>`. This branch is dead for production
234
+ // (Task 207 dropped `.mcp.json` writes for specialists) but the
235
+ // classifier keeps it correct for any future caller and for tests
236
+ // that exercise the legacy path.
237
+ const { matchedServers } = classifySpecialistTools(p.specialistTools, p.toolSurface.mcpServers);
163
238
  for (const [name, desc] of p.toolSurface.mcpServers) {
164
- if (specialistPluginNames.has(name))
239
+ if (matchedServers.has(name))
165
240
  serversForRole.push([name, desc]);
166
241
  }
167
242
  }
@@ -268,24 +343,55 @@ function checkSlotsAndMaybeEvict(deps, args) {
268
343
  }
269
344
  return undefined;
270
345
  }
346
+ /** Task 215 — single source of truth for matching probe results against
347
+ * the frontmatter allowlist. Builds the `offered` set with BOTH short
348
+ * and long prefix shapes so an agent file's `mcp__plugin_<plugin>_<server>__<tool>`
349
+ * declaration intersects with the probe's per-tool reply regardless of
350
+ * which Claude Code registry path registers the server at runtime.
351
+ * `mcpListedCount` is incremented per actual tool, not per prefix variant
352
+ * — the two prefixes refer to the same underlying tool. */
353
+ function buildOfferedSet(result) {
354
+ const offered = new Set();
355
+ let mcpListedCount = 0;
356
+ for (const [serverName, tools] of result) {
357
+ for (const tool of tools) {
358
+ offered.add(`mcp__${serverName}__${tool}`);
359
+ offered.add(`mcp__plugin_${serverName}_${serverName}__${tool}`);
360
+ mcpListedCount++;
361
+ }
362
+ }
363
+ return { offered, mcpListedCount };
364
+ }
365
+ /** Task 215 — render the optional `unparseable-tools=` and `missing-servers=`
366
+ * fields. Empty inputs return an empty string so the inventory line stays
367
+ * exactly the legacy shape when the spawn is healthy (no need to teach
368
+ * every operator-side grep to skip blank fields). */
369
+ function buildDiagnosticFields(unparseable, missing) {
370
+ let out = '';
371
+ if (unparseable.length > 0)
372
+ out += ` unparseable-tools=${unparseable.join(',')}`;
373
+ if (missing.length > 0)
374
+ out += ` missing-servers=${missing.join(',')}`;
375
+ return out;
376
+ }
271
377
  /** Task 178 — fire-and-forget aggregator. Probes each MCP server in the
272
378
  * spawn's resolved mcp.json for its `tools/list` reply, then emits one
273
379
  * `[pty-spawn-tool-inventory]` line per spawn. Specialist spawns only —
274
380
  * operator spawns have no agent frontmatter and the failure shape this
275
381
  * closes the gap on is recorder-specific. The function never throws;
276
382
  * probe errors emit a `[pty-spawn-tool-inventory-failed]` line on the
277
- * same logger so the gap is itself observable. */
383
+ * same logger so the gap is itself observable.
384
+ *
385
+ * Task 215 — accepts `unparseableTools` and `missingServers` from the
386
+ * caller's classifier so the line surfaces both diagnostic classes when
387
+ * non-empty. The two paths catch different defects: an unparseable token
388
+ * signals a malformed frontmatter entry; a missing server signals a typo
389
+ * or a stale plugin name that no longer maps to a tool-surface registry
390
+ * key. */
278
391
  function emitToolInventoryAsync(p) {
279
392
  p.readMcpToolInventory({ servers: p.resolvedServers, timeoutMs: p.timeoutMs })
280
393
  .then((result) => {
281
- const offered = new Set();
282
- let mcpListedCount = 0;
283
- for (const [serverName, tools] of result) {
284
- for (const tool of tools) {
285
- offered.add(`mcp__${serverName}__${tool}`);
286
- mcpListedCount++;
287
- }
288
- }
394
+ const { offered, mcpListedCount } = buildOfferedSet(result);
289
395
  const exposed = [];
290
396
  const notExposed = [];
291
397
  for (const name of p.frontmatterAllowlist) {
@@ -301,13 +407,86 @@ function emitToolInventoryAsync(p) {
301
407
  // plugin-system?) and `not-exposed` (does it match what the agent
302
408
  // declared?). When both reach the brief's target values, the
303
409
  // recorder turn produces real `tool_use` blocks.
304
- p.logger(`[pty-spawn-tool-inventory] sessionId=${p.sessionId} specialist=${p.specialist} argv-tools=0 mcp-listed-tools=${mcpListedCount} exposed=${exposed.join(',')} not-exposed=${notExposed.join(',')}`);
410
+ const diag = buildDiagnosticFields(p.unparseableTools, p.missingServers);
411
+ p.logger(`[pty-spawn-tool-inventory] sessionId=${p.sessionId} specialist=${p.specialist} argv-tools=0 mcp-listed-tools=${mcpListedCount} exposed=${exposed.join(',')} not-exposed=${notExposed.join(',')}${diag}`);
305
412
  })
306
413
  .catch((err) => {
307
414
  const msg = err instanceof Error ? err.message : String(err);
308
415
  p.logger(`[pty-spawn-tool-inventory-failed] sessionId=${p.sessionId} specialist=${p.specialist} err=${JSON.stringify(msg)}`);
309
416
  });
310
417
  }
418
+ const finalSnapshotState = new Map();
419
+ /** Watchdog ceiling for "model never produced a first turn" — if no
420
+ * `[recorder-turn]` lands within this window, the watchdog fires the
421
+ * final snapshot with `reason=first-turn-timeout`. 60 s is the same
422
+ * order-of-magnitude as the PID-file timeout and well below typical
423
+ * operator patience; tunable in tests via `__setFirstTurnTimeoutMsForTests`. */
424
+ const DEFAULT_FIRST_TURN_TIMEOUT_MS = 60_000;
425
+ let firstTurnTimeoutMs = DEFAULT_FIRST_TURN_TIMEOUT_MS;
426
+ /** Test seam. Production never calls this; the `__` prefix matches the
427
+ * in-repo convention for non-API helpers. */
428
+ export function __setFirstTurnTimeoutMsForTests(ms) {
429
+ firstTurnTimeoutMs = ms;
430
+ }
431
+ export function __resetFirstTurnTimeoutMsForTests() {
432
+ firstTurnTimeoutMs = DEFAULT_FIRST_TURN_TIMEOUT_MS;
433
+ }
434
+ /** Task 215 — fire the `[pty-spawn-tool-inventory-final]` line once per
435
+ * specialist spawn. Idempotent: a second call (e.g. watchdog races a
436
+ * late recorder-turn) is a no-op via the `fired` guard. Re-runs the
437
+ * probe against the same resolvedServers map the spawn-time probe used,
438
+ * so the line reports what the probe would observe AT first-turn
439
+ * time — the timing question Phase 1 of Task 215 was filed to answer.
440
+ *
441
+ * The probe is async and the PTY can exit while it's in flight. Both the
442
+ * `.then` and `.catch` paths gate emission on `finalSnapshotState.has`
443
+ * to suppress phantom lines for sessions whose PTY-exit cleanup ran
444
+ * while the probe was still running. The captured `state` reference
445
+ * still holds the logger, so the emission would mechanically work — but
446
+ * it would lie about a dead session, which is worse than no line. */
447
+ function fireFinalSnapshot(sessionId, reason) {
448
+ const state = finalSnapshotState.get(sessionId);
449
+ if (!state || state.fired)
450
+ return;
451
+ state.fired = true;
452
+ if (state.watchdog) {
453
+ clearTimeout(state.watchdog);
454
+ state.watchdog = null;
455
+ }
456
+ state.readMcpToolInventory({ servers: state.resolvedServers, timeoutMs: state.timeoutMs })
457
+ .then((result) => {
458
+ if (!finalSnapshotState.has(sessionId))
459
+ return;
460
+ const { offered, mcpListedCount } = buildOfferedSet(result);
461
+ const exposed = [];
462
+ const notExposed = [];
463
+ for (const name of state.frontmatterAllowlist) {
464
+ if (offered.has(name))
465
+ exposed.push(name);
466
+ else
467
+ notExposed.push(name);
468
+ }
469
+ const msSinceSpawn = Date.now() - state.spawnedAt;
470
+ const diag = buildDiagnosticFields(state.unparseableTools, state.missingServers);
471
+ state.logger(`[pty-spawn-tool-inventory-final] sessionId=${sessionId} specialist=${state.specialist} mcp-listed-tools=${mcpListedCount} exposed=${exposed.join(',')} not-exposed=${notExposed.join(',')} ms-since-spawn=${msSinceSpawn} reason=${reason}${diag}`);
472
+ })
473
+ .catch((err) => {
474
+ if (!finalSnapshotState.has(sessionId))
475
+ return;
476
+ const msg = err instanceof Error ? err.message : String(err);
477
+ state.logger(`[pty-spawn-tool-inventory-final-failed] sessionId=${sessionId} specialist=${state.specialist} reason=${reason} err=${JSON.stringify(msg)}`);
478
+ });
479
+ }
480
+ /** Test seam — clear any leftover per-spawn state between tests so a
481
+ * failing test doesn't pollute the next one's Map. Production never
482
+ * invokes this; the only legitimate eviction path is PTY exit. */
483
+ export function __clearFinalSnapshotStateForTests() {
484
+ for (const state of finalSnapshotState.values()) {
485
+ if (state.watchdog)
486
+ clearTimeout(state.watchdog);
487
+ }
488
+ finalSnapshotState.clear();
489
+ }
311
490
  export async function spawnClaudeSession(deps, args) {
312
491
  const rejection = checkSlotsAndMaybeEvict(deps, args);
313
492
  if (rejection) {
@@ -737,15 +916,16 @@ export async function spawnClaudeSession(deps, args) {
737
916
  bridgeSuffixHint: args.senderId,
738
917
  logDir: deps.logDir,
739
918
  });
740
- const specialistPluginNames = new Set();
741
- for (const t of specialistTools) {
742
- const m = t.match(/^mcp__(.+?)__/);
743
- if (m)
744
- specialistPluginNames.add(m[1]);
745
- }
919
+ // Task 215 classify the frontmatter list once. `matchedServers` is
920
+ // the set of `toolSurface.mcpServers` keys to spawn for the probe;
921
+ // `unparseableTools` and `missingServers` ride downstream into both
922
+ // the spawn-time and end-of-first-turn inventory lines, so a future
923
+ // namespace drift (or an agent file with a typo) can be told apart
924
+ // from a real MCP boot failure by reading server.log alone.
925
+ const { matchedServers, unparseableTools, missingServers } = classifySpecialistTools(specialistTools, deps.toolSurface.mcpServers);
746
926
  const resolvedServers = new Map();
747
927
  for (const [name, desc] of deps.toolSurface.mcpServers) {
748
- if (!specialistPluginNames.has(name))
928
+ if (!matchedServers.has(name))
749
929
  continue;
750
930
  const probeEnv = desc.env
751
931
  ? Object.fromEntries(Object.entries(desc.env).map(([k, v]) => [k, expandPlaceholders(v, placeholders)]))
@@ -762,15 +942,39 @@ export async function spawnClaudeSession(deps, args) {
762
942
  baseEnv: process.env,
763
943
  timeoutMs: req.timeoutMs,
764
944
  }));
945
+ const inventoryTimeoutMs = deps.toolInventoryProbeTimeoutMs ?? 5_000;
765
946
  emitToolInventoryAsync({
766
947
  sessionId: session.sessionId,
767
948
  specialist: args.specialist,
768
949
  frontmatterAllowlist: specialistTools,
769
950
  resolvedServers,
951
+ unparseableTools,
952
+ missingServers,
770
953
  readMcpToolInventory: readInventory,
771
- timeoutMs: deps.toolInventoryProbeTimeoutMs ?? 5_000,
954
+ timeoutMs: inventoryTimeoutMs,
772
955
  logger: deps.logger,
773
956
  });
957
+ // Task 215 — register the per-spawn state that the JsonlTail callback
958
+ // (or the watchdog timer) needs to fire the final snapshot. State is
959
+ // module-scoped so a stale entry past PTY exit is a leak; the exit
960
+ // handler below explicitly clears it. The watchdog covers the failure
961
+ // mode where the model emits zero useful content (the exact defect
962
+ // this task investigates): without the timer, a spawn that never
963
+ // produces a first turn would never emit a final snapshot, and the
964
+ // operator would have no signal at all for the broken case.
965
+ finalSnapshotState.set(session.sessionId, {
966
+ specialist: args.specialist,
967
+ frontmatterAllowlist: specialistTools,
968
+ resolvedServers,
969
+ unparseableTools,
970
+ missingServers,
971
+ readMcpToolInventory: readInventory,
972
+ timeoutMs: inventoryTimeoutMs,
973
+ logger: deps.logger,
974
+ spawnedAt: Date.now(),
975
+ fired: false,
976
+ watchdog: setTimeout(() => fireFinalSnapshot(session.sessionId, 'first-turn-timeout'), firstTurnTimeoutMs),
977
+ });
774
978
  }
775
979
  // Task 183 — register the specialist spawn with the JSONL tail. The
776
980
  // tail's state must exist BEFORE any JSONL modify event fires so the
@@ -780,13 +984,35 @@ export async function spawnClaudeSession(deps, args) {
780
984
  // correct semantic (nothing was launched on argv, so nothing can be
781
985
  // missing). Operator spawns do not register; the tail emits nothing for
782
986
  // them.
987
+ //
988
+ // Task 215 — `onFirstTurn` fires the `[pty-spawn-tool-inventory-final]`
989
+ // snapshot when the model emits its first non-thinking assistant
990
+ // record. Paired with the watchdog timer set above (in the Task-178
991
+ // probe block); whichever fires first wins, the other is a no-op via
992
+ // the `fired` guard inside `fireFinalSnapshot`.
783
993
  if (isSpecialistSpawn && deps.jsonlTail) {
784
994
  deps.jsonlTail.register(session.sessionId, {
785
995
  specialist: args.specialist,
786
996
  argvTools: [],
997
+ onFirstTurn: () => fireFinalSnapshot(session.sessionId, 'first-turn'),
787
998
  });
788
999
  pty.onExit(() => deps.jsonlTail?.unregister(session.sessionId));
789
1000
  }
1001
+ // Task 215 — PTY-exit cleanup for the final-snapshot state runs
1002
+ // INDEPENDENTLY of the JsonlTail wiring. When `deps.jsonlTail` is
1003
+ // undefined (test fixtures, partial-mock deployments), state was
1004
+ // still registered above in the Task-178 probe block, and the
1005
+ // watchdog timer needs to be canceled on exit to prevent a leak
1006
+ // that fires `[pty-spawn-tool-inventory-final] reason=first-turn-timeout`
1007
+ // against a long-dead session 60 s later.
1008
+ if (isSpecialistSpawn && specialistTools !== null) {
1009
+ pty.onExit(() => {
1010
+ const state = finalSnapshotState.get(session.sessionId);
1011
+ if (state?.watchdog)
1012
+ clearTimeout(state.watchdog);
1013
+ finalSnapshotState.delete(session.sessionId);
1014
+ });
1015
+ }
790
1016
  deps.onSessionReady?.(session);
791
1017
  return { ok: true, session };
792
1018
  }