@gajae-code/coding-agent 0.11.11 → 0.12.1

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 (344) hide show
  1. package/CHANGELOG.md +131 -4
  2. package/dist/types/async/job-manager.d.ts +17 -3
  3. package/dist/types/cli/read-cli.d.ts +1 -0
  4. package/dist/types/commands/deep-interview.d.ts +9 -0
  5. package/dist/types/commands/harness.d.ts +22 -0
  6. package/dist/types/commands/read.d.ts +6 -0
  7. package/dist/types/config/model-registry.d.ts +4 -0
  8. package/dist/types/config/provider-auth-health.d.ts +14 -0
  9. package/dist/types/config/provider-ranking.d.ts +59 -0
  10. package/dist/types/config/settings-schema.d.ts +83 -1
  11. package/dist/types/config/settings.d.ts +2 -0
  12. package/dist/types/exa/mcp-client.d.ts +10 -1
  13. package/dist/types/exec/bash-executor.d.ts +45 -12
  14. package/dist/types/extensibility/extensions/types.d.ts +38 -4
  15. package/dist/types/extensibility/gjc-plugins/index.d.ts +12 -2
  16. package/dist/types/extensibility/gjc-plugins/installer.d.ts +63 -7
  17. package/dist/types/extensibility/gjc-plugins/lifecycle-reconciliation.d.ts +55 -0
  18. package/dist/types/extensibility/gjc-plugins/lifecycle.d.ts +64 -0
  19. package/dist/types/extensibility/gjc-plugins/runtime-quarantine.d.ts +67 -0
  20. package/dist/types/extensibility/gjc-plugins/session-validation.d.ts +3 -1
  21. package/dist/types/extensibility/gjc-plugins/types.d.ts +124 -0
  22. package/dist/types/extensibility/shared-events.d.ts +6 -0
  23. package/dist/types/gjc-runtime/deep-interview-ambiguity.d.ts +5 -12
  24. package/dist/types/gjc-runtime/deep-interview-recorder.d.ts +17 -32
  25. package/dist/types/gjc-runtime/deep-interview-stage.d.ts +37 -0
  26. package/dist/types/gjc-runtime/deep-interview-state.d.ts +4 -135
  27. package/dist/types/gjc-runtime/gc-runtime.d.ts +1 -1
  28. package/dist/types/gjc-runtime/launch-tmux.d.ts +1 -0
  29. package/dist/types/gjc-runtime/memory-guard-owner-claims.d.ts +47 -0
  30. package/dist/types/gjc-runtime/ralplan-runtime.d.ts +70 -1
  31. package/dist/types/gjc-runtime/state-writer.d.ts +5 -46
  32. package/dist/types/gjc-runtime/team-launch.d.ts +1 -1
  33. package/dist/types/gjc-runtime/team-runtime.d.ts +27 -1
  34. package/dist/types/gjc-runtime/team-store.d.ts +12 -0
  35. package/dist/types/gjc-runtime/team-worker-heartbeat.d.ts +43 -0
  36. package/dist/types/gjc-runtime/team-worker-memory-guard.d.ts +92 -0
  37. package/dist/types/gjc-runtime/tmux-owner-isolation.d.ts +17 -0
  38. package/dist/types/gjc-runtime/ultragoal-receipt-freshness.d.ts +8 -0
  39. package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +31 -80
  40. package/dist/types/gjc-runtime/workflow-manifest.d.ts +3 -5
  41. package/dist/types/internal-urls/local-root-gc.d.ts +2 -0
  42. package/dist/types/main.d.ts +1 -1
  43. package/dist/types/memories/index.d.ts +2 -0
  44. package/dist/types/modes/acp/acp-agent.d.ts +10 -19
  45. package/dist/types/modes/components/assistant-message.d.ts +3 -1
  46. package/dist/types/modes/components/gjc-bundle-settings.d.ts +34 -0
  47. package/dist/types/modes/components/irc-sidebar.d.ts +41 -0
  48. package/dist/types/modes/components/notifications-settings-editor.d.ts +1 -0
  49. package/dist/types/modes/components/read-tool-group.d.ts +4 -4
  50. package/dist/types/modes/components/session-observer-overlay.d.ts +22 -0
  51. package/dist/types/modes/components/settings-selector.d.ts +11 -0
  52. package/dist/types/modes/components/status-line/gh.d.ts +5 -0
  53. package/dist/types/modes/components/tool-execution.d.ts +8 -0
  54. package/dist/types/modes/components/transcript-viewer-overlay.d.ts +18 -1
  55. package/dist/types/modes/controllers/event-controller.d.ts +3 -0
  56. package/dist/types/modes/interactive-mode.d.ts +2 -0
  57. package/dist/types/modes/irc-observation-ledger.d.ts +17 -1
  58. package/dist/types/modes/types.d.ts +2 -0
  59. package/dist/types/modes/utils/ui-helpers.d.ts +16 -0
  60. package/dist/types/reminders/star-reminder.d.ts +3 -13
  61. package/dist/types/runtime-mcp/manager.d.ts +1 -0
  62. package/dist/types/runtime-mcp/smithery-auth.d.ts +5 -0
  63. package/dist/types/sdk/acp/adapter.d.ts +3 -1
  64. package/dist/types/sdk/broker/lifecycle.d.ts +5 -0
  65. package/dist/types/sdk/broker/transport.d.ts +2 -0
  66. package/dist/types/sdk/bus/attachment-registry.d.ts +1 -0
  67. package/dist/types/sdk/bus/chat-daemon-control.d.ts +4 -1
  68. package/dist/types/sdk/bus/config.d.ts +6 -2
  69. package/dist/types/sdk/bus/control-drain-lease.d.ts +52 -0
  70. package/dist/types/sdk/bus/index.d.ts +44 -1
  71. package/dist/types/sdk/bus/kind-aware-reconciliation.d.ts +44 -0
  72. package/dist/types/sdk/bus/lifecycle-control-runtime.d.ts +4 -0
  73. package/dist/types/sdk/bus/prompt-reconciliation.d.ts +2 -1
  74. package/dist/types/sdk/bus/reconciliation-store.d.ts +69 -0
  75. package/dist/types/sdk/bus/rich-draft.d.ts +1 -0
  76. package/dist/types/sdk/bus/rich-render.d.ts +2 -0
  77. package/dist/types/sdk/bus/telegram-adoption-intent.d.ts +165 -0
  78. package/dist/types/sdk/bus/telegram-cli.d.ts +12 -0
  79. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +11 -4
  80. package/dist/types/sdk/bus/telegram-daemon.d.ts +25 -1
  81. package/dist/types/sdk/bus/telegram-reference.d.ts +11 -1
  82. package/dist/types/sdk/bus/threaded-render.d.ts +3 -2
  83. package/dist/types/sdk/bus/topic-registry.d.ts +11 -1
  84. package/dist/types/sdk/host/control/operations.d.ts +1 -1
  85. package/dist/types/sdk/host/host.d.ts +2 -0
  86. package/dist/types/sdk/host/query/handlers.d.ts +5 -0
  87. package/dist/types/sdk/host/query/revision-store.d.ts +2 -0
  88. package/dist/types/sdk/host/reverse-leases.d.ts +1 -1
  89. package/dist/types/sdk/prompt-status.d.ts +23 -3
  90. package/dist/types/sdk/session.d.ts +6 -0
  91. package/dist/types/session/agent-session.d.ts +82 -12
  92. package/dist/types/session/artifacts.d.ts +8 -0
  93. package/dist/types/session/blob-store.d.ts +57 -4
  94. package/dist/types/session/internal/managed-session-storage.d.ts +8 -1
  95. package/dist/types/session/memory-guard-checkpoint-participant.d.ts +69 -0
  96. package/dist/types/session/session-manager.d.ts +48 -19
  97. package/dist/types/session/session-storage.d.ts +4 -0
  98. package/dist/types/session/streaming-output.d.ts +96 -12
  99. package/dist/types/setup/credential-import.d.ts +12 -0
  100. package/dist/types/skill-state/active-state.d.ts +12 -4
  101. package/dist/types/skill-state/workflow-hud.d.ts +9 -0
  102. package/dist/types/task/executor.d.ts +3 -2
  103. package/dist/types/task/index.d.ts +3 -1
  104. package/dist/types/task/provider-retry-status.d.ts +8 -0
  105. package/dist/types/task/receipt.d.ts +7 -1
  106. package/dist/types/task/types.d.ts +23 -0
  107. package/dist/types/tools/ask-answer-registry.d.ts +2 -2
  108. package/dist/types/tools/bash-interactive.d.ts +4 -1
  109. package/dist/types/tools/bash.d.ts +3 -1
  110. package/dist/types/tools/browser/launch.d.ts +7 -0
  111. package/dist/types/tools/fetch.d.ts +17 -1
  112. package/dist/types/tools/image-gen.d.ts +4 -0
  113. package/dist/types/tools/index.d.ts +4 -0
  114. package/dist/types/tools/output-meta.d.ts +44 -3
  115. package/dist/types/tools/path-utils.d.ts +1 -0
  116. package/dist/types/tools/read-internals.d.ts +12 -0
  117. package/dist/types/tools/read.d.ts +45 -7
  118. package/dist/types/tools/resource-gc.d.ts +4 -0
  119. package/dist/types/tools/review.d.ts +5 -7
  120. package/dist/types/tools/subagent.d.ts +2 -0
  121. package/dist/types/tools/tool-result.d.ts +7 -1
  122. package/dist/types/utils/gh.d.ts +13 -0
  123. package/dist/types/utils/image-resize.d.ts +1 -0
  124. package/dist/types/web/search/providers/kimi.d.ts +2 -0
  125. package/dist/types/web/search/providers/searxng.d.ts +7 -0
  126. package/dist/types/web/search/providers/xai.d.ts +2 -0
  127. package/package.json +11 -13
  128. package/scripts/acp-conformance-agent.ts +218 -0
  129. package/scripts/benchmark-sticky-viewport-pr1.ts +239 -0
  130. package/scripts/capture-gjc-bundle-settings.ts +306 -0
  131. package/scripts/capture-sticky-viewport-showcase.ts +292 -0
  132. package/scripts/generate-sdk-operation-inventory.ts +5 -0
  133. package/scripts/resident-memory-bench.ts +1341 -0
  134. package/scripts/run-acp-conformance.ts +285 -0
  135. package/scripts/verify-gjc-sdk-canonicalization.ts +122 -18
  136. package/scripts/verify-sticky-viewport-showcase.ts +611 -0
  137. package/src/async/job-manager.ts +78 -20
  138. package/src/capability/index.ts +8 -0
  139. package/src/cli/fast-help.ts +1 -1
  140. package/src/cli/plugin-cli.ts +176 -18
  141. package/src/cli/read-cli.ts +2 -1
  142. package/src/cli.ts +1 -0
  143. package/src/commands/deep-interview.ts +29 -9
  144. package/src/commands/harness.ts +35 -12
  145. package/src/commands/read.ts +11 -2
  146. package/src/commands/team.ts +20 -2
  147. package/src/config/file-lock.ts +11 -2
  148. package/src/config/model-registry.ts +21 -2
  149. package/src/config/provider-auth-health.ts +42 -0
  150. package/src/config/provider-ranking.ts +119 -0
  151. package/src/config/settings-schema.ts +74 -1
  152. package/src/config/settings.ts +246 -108
  153. package/src/coordinator-mcp/question-gate-codec.ts +1 -1
  154. package/src/coordinator-mcp/server.ts +5 -12
  155. package/src/defaults/gjc/skills/deep-interview/SKILL.md +230 -82
  156. package/src/defaults/gjc/skills/ralplan/SKILL.md +77 -41
  157. package/src/defaults/gjc/skills/team/SKILL.md +3 -1
  158. package/src/defaults/gjc/skills/ultragoal/SKILL.md +62 -39
  159. package/src/defaults/gjc/skills/ultragoal/validation-batch-contracts.md +12 -0
  160. package/src/defaults/gjc-defaults.ts +4 -4
  161. package/src/eval/py/executor.ts +7 -2
  162. package/src/exa/mcp-client.ts +12 -3
  163. package/src/exec/bash-executor.ts +144 -27
  164. package/src/extensibility/extensions/runner.ts +15 -0
  165. package/src/extensibility/extensions/types.ts +46 -5
  166. package/src/extensibility/gjc-plugins/constrained-hooks.ts +8 -2
  167. package/src/extensibility/gjc-plugins/index.ts +19 -2
  168. package/src/extensibility/gjc-plugins/installer.ts +189 -50
  169. package/src/extensibility/gjc-plugins/lifecycle-reconciliation.ts +199 -0
  170. package/src/extensibility/gjc-plugins/lifecycle.ts +626 -0
  171. package/src/extensibility/gjc-plugins/observability.ts +3 -3
  172. package/src/extensibility/gjc-plugins/prompt-appendix.ts +5 -1
  173. package/src/extensibility/gjc-plugins/runtime-adapters.ts +12 -2
  174. package/src/extensibility/gjc-plugins/runtime-quarantine.ts +121 -0
  175. package/src/extensibility/gjc-plugins/schema.ts +84 -12
  176. package/src/extensibility/gjc-plugins/session-validation.ts +9 -3
  177. package/src/extensibility/gjc-plugins/types.ts +141 -0
  178. package/src/extensibility/gjc-plugins/validation.ts +9 -0
  179. package/src/extensibility/shared-events.ts +5 -0
  180. package/src/gjc-runtime/deep-interview-ambiguity.ts +47 -82
  181. package/src/gjc-runtime/deep-interview-recorder.ts +227 -310
  182. package/src/gjc-runtime/deep-interview-runtime.ts +109 -270
  183. package/src/gjc-runtime/deep-interview-stage.ts +1016 -0
  184. package/src/gjc-runtime/deep-interview-state.ts +12 -943
  185. package/src/gjc-runtime/gc-render.ts +1 -0
  186. package/src/gjc-runtime/gc-runtime.ts +11 -1
  187. package/src/gjc-runtime/launch-tmux.ts +25 -6
  188. package/src/gjc-runtime/managed-owner-admission.ts +1 -1
  189. package/src/gjc-runtime/memory-guard-owner-claims.ts +389 -0
  190. package/src/gjc-runtime/ralplan-runtime.ts +1149 -98
  191. package/src/gjc-runtime/state-runtime.ts +2 -1
  192. package/src/gjc-runtime/state-writer.ts +70 -222
  193. package/src/gjc-runtime/team-launch.ts +42 -5
  194. package/src/gjc-runtime/team-runtime.ts +1085 -40
  195. package/src/gjc-runtime/team-store.ts +32 -0
  196. package/src/gjc-runtime/team-worker-heartbeat.ts +149 -0
  197. package/src/gjc-runtime/team-worker-memory-guard.ts +363 -0
  198. package/src/gjc-runtime/team-workers.ts +1 -0
  199. package/src/gjc-runtime/tmux-owner-isolation.ts +28 -0
  200. package/src/gjc-runtime/tmux-sessions.ts +58 -13
  201. package/src/gjc-runtime/ultragoal-receipt-freshness.ts +20 -0
  202. package/src/gjc-runtime/ultragoal-runtime.ts +414 -618
  203. package/src/gjc-runtime/workflow-manifest.generated.json +105 -449
  204. package/src/gjc-runtime/workflow-manifest.ts +38 -247
  205. package/src/hooks/native-skill-hook.ts +17 -4
  206. package/src/hooks/skill-state.ts +1 -23
  207. package/src/internal-urls/docs-index.generated.ts +21 -22
  208. package/src/internal-urls/local-root-gc.ts +127 -0
  209. package/src/main.ts +9 -5
  210. package/src/memories/index.ts +10 -0
  211. package/src/modes/DESIGN.md +98 -0
  212. package/src/modes/acp/acp-agent.ts +339 -191
  213. package/src/modes/acp/acp-event-mapper.ts +14 -7
  214. package/src/modes/acp/acp-mode.ts +39 -3
  215. package/src/modes/components/assistant-message.ts +123 -22
  216. package/src/modes/components/gjc-bundle-settings.ts +508 -0
  217. package/src/modes/components/irc-sidebar.ts +176 -62
  218. package/src/modes/components/model-selector.ts +61 -4
  219. package/src/modes/components/notifications-settings-editor.ts +12 -1
  220. package/src/modes/components/oauth-selector.ts +96 -28
  221. package/src/modes/components/read-tool-group.ts +82 -14
  222. package/src/modes/components/session-observer-overlay.ts +457 -83
  223. package/src/modes/components/settings-selector.ts +116 -23
  224. package/src/modes/components/status-line/gh.ts +16 -0
  225. package/src/modes/components/tool-execution.ts +138 -27
  226. package/src/modes/components/tool-status-header.ts +3 -14
  227. package/src/modes/components/transcript-viewer-overlay.ts +99 -24
  228. package/src/modes/controllers/command-controller.ts +4 -0
  229. package/src/modes/controllers/event-controller.ts +109 -27
  230. package/src/modes/controllers/extension-ui-controller.ts +26 -2
  231. package/src/modes/controllers/input-controller.ts +18 -3
  232. package/src/modes/controllers/selector-controller.ts +127 -36
  233. package/src/modes/interactive-mode.ts +62 -3
  234. package/src/modes/irc-observation-ledger.ts +71 -15
  235. package/src/modes/runtime-init.ts +22 -2
  236. package/src/modes/types.ts +2 -0
  237. package/src/modes/utils/ui-helpers.ts +94 -1
  238. package/src/prompts/agent-fragments/ralplan-persistence.md +4 -3
  239. package/src/prompts/agents/architect.md +9 -1
  240. package/src/prompts/agents/critic.md +9 -0
  241. package/src/prompts/system/eager-todo.md +8 -4
  242. package/src/prompts/system/system-prompt.md +11 -5
  243. package/src/prompts/tools/bash.md +5 -5
  244. package/src/prompts/tools/read.md +4 -2
  245. package/src/prompts/tools/search-tool-bm25.md +5 -0
  246. package/src/prompts/tools/task.md +1 -1
  247. package/src/reminders/star-reminder.ts +4 -42
  248. package/src/runtime-mcp/manager.ts +19 -4
  249. package/src/runtime-mcp/smithery-auth.ts +17 -2
  250. package/src/runtime-mcp/smithery-connect.ts +11 -1
  251. package/src/sdk/acp/adapter.ts +22 -6
  252. package/src/sdk/broker/lifecycle.ts +25 -6
  253. package/src/sdk/broker/transport.ts +35 -3
  254. package/src/sdk/bus/attachment-registry.ts +5 -1
  255. package/src/sdk/bus/chat-daemon-cli.ts +4 -39
  256. package/src/sdk/bus/chat-daemon-control.ts +6 -3
  257. package/src/sdk/bus/config.ts +18 -2
  258. package/src/sdk/bus/control-drain-lease.ts +104 -0
  259. package/src/sdk/bus/index.ts +984 -146
  260. package/src/sdk/bus/kind-aware-reconciliation.ts +317 -0
  261. package/src/sdk/bus/lifecycle-commands.ts +4 -1
  262. package/src/sdk/bus/lifecycle-control-runtime.ts +403 -88
  263. package/src/sdk/bus/prompt-reconciliation.ts +2 -1
  264. package/src/sdk/bus/reconciliation-store.ts +303 -0
  265. package/src/sdk/bus/rich-draft.ts +1 -1
  266. package/src/sdk/bus/rich-render.ts +2 -2
  267. package/src/sdk/bus/telegram-adoption-intent.ts +574 -0
  268. package/src/sdk/bus/telegram-cli.ts +33 -8
  269. package/src/sdk/bus/telegram-daemon-cli.ts +1 -0
  270. package/src/sdk/bus/telegram-daemon-contract.ts +11 -4
  271. package/src/sdk/bus/telegram-daemon.ts +916 -23
  272. package/src/sdk/bus/telegram-reference.ts +40 -3
  273. package/src/sdk/bus/threaded-render.ts +48 -3
  274. package/src/sdk/bus/topic-registry.ts +20 -0
  275. package/src/sdk/host/control/dispatch.ts +5 -1
  276. package/src/sdk/host/control/operations.ts +1 -1
  277. package/src/sdk/host/host.ts +23 -1
  278. package/src/sdk/host/query/handlers.ts +55 -0
  279. package/src/sdk/host/query/revision-store.ts +36 -2
  280. package/src/sdk/host/reverse-leases.ts +44 -7
  281. package/src/sdk/mcp/server.ts +46 -18
  282. package/src/sdk/prompt-status.ts +16 -3
  283. package/src/sdk/protocol/operation-inventory.generated.json +51 -0
  284. package/src/sdk/protocol/operation-registry.ts +7 -2
  285. package/src/sdk/session.ts +101 -10
  286. package/src/session/agent-session.ts +1286 -220
  287. package/src/session/artifacts.ts +22 -0
  288. package/src/session/auth-broker-config.ts +10 -3
  289. package/src/session/blob-store.ts +915 -24
  290. package/src/session/internal/managed-session-scope.ts +44 -6
  291. package/src/session/internal/managed-session-storage.ts +48 -6
  292. package/src/session/memory-guard-checkpoint-participant.ts +131 -0
  293. package/src/session/session-manager.ts +2364 -438
  294. package/src/session/session-storage.ts +9 -1
  295. package/src/session/streaming-output.ts +500 -111
  296. package/src/setup/credential-import.ts +75 -13
  297. package/src/setup/provider-onboarding.ts +19 -4
  298. package/src/skill-state/active-state.ts +32 -10
  299. package/src/skill-state/workflow-hud.ts +42 -2
  300. package/src/skill-state/workflow-mutation-guard.ts +560 -8
  301. package/src/task/executor.ts +122 -39
  302. package/src/task/index.ts +23 -14
  303. package/src/task/provider-retry-status.ts +16 -0
  304. package/src/task/receipt.ts +23 -7
  305. package/src/task/render.ts +6 -2
  306. package/src/task/types.ts +108 -0
  307. package/src/tools/ask-answer-registry.ts +12 -6
  308. package/src/tools/ask.ts +169 -118
  309. package/src/tools/ast-edit.ts +1 -0
  310. package/src/tools/ast-grep.ts +1 -0
  311. package/src/tools/bash-interactive.ts +8 -3
  312. package/src/tools/bash.ts +503 -60
  313. package/src/tools/browser/launch.ts +41 -6
  314. package/src/tools/fetch.ts +114 -23
  315. package/src/tools/find.ts +1 -0
  316. package/src/tools/image-gen.ts +29 -5
  317. package/src/tools/index.ts +4 -0
  318. package/src/tools/output-meta.ts +281 -20
  319. package/src/tools/path-utils.ts +8 -3
  320. package/src/tools/read-internals.ts +44 -0
  321. package/src/tools/read.ts +1560 -310
  322. package/src/tools/resource-gc.ts +182 -18
  323. package/src/tools/review.ts +5 -7
  324. package/src/tools/search.ts +1 -0
  325. package/src/tools/subagent-render.ts +6 -2
  326. package/src/tools/subagent.ts +6 -0
  327. package/src/tools/telegram-send.ts +6 -3
  328. package/src/tools/tool-result.ts +14 -1
  329. package/src/utils/gh.ts +39 -0
  330. package/src/utils/image-resize.ts +3 -0
  331. package/src/web/search/providers/anthropic.ts +4 -4
  332. package/src/web/search/providers/codex.ts +1 -1
  333. package/src/web/search/providers/kimi.ts +15 -5
  334. package/src/web/search/providers/searxng.ts +47 -4
  335. package/src/web/search/providers/xai.ts +7 -2
  336. package/dist/types/gjc-runtime/deep-interview-draft.d.ts +0 -8
  337. package/dist/types/gjc-runtime/deep-interview-payload.d.ts +0 -41
  338. package/dist/types/gjc-runtime/deep-interview-repair.d.ts +0 -17
  339. package/dist/types/gjc-runtime/ultragoal-pipeline.d.ts +0 -23
  340. package/src/defaults/gjc/skills/ultragoal/pipeline-validation-contracts.md +0 -30
  341. package/src/gjc-runtime/deep-interview-draft.ts +0 -843
  342. package/src/gjc-runtime/deep-interview-payload.ts +0 -262
  343. package/src/gjc-runtime/deep-interview-repair.ts +0 -1674
  344. package/src/gjc-runtime/ultragoal-pipeline.ts +0 -306
@@ -857,7 +857,8 @@ function buildHudForMode(
857
857
  : typeof payload.mode === "string"
858
858
  ? (payload.mode as string)
859
859
  : undefined;
860
- const verdict = typeof payload.verdict === "string" ? (payload.verdict as string) : undefined;
860
+ const rawVerdict = payload.last_review_verdict ?? payload.verdict;
861
+ const verdict = typeof rawVerdict === "string" ? rawVerdict : undefined;
861
862
  const iteration = typeof payload.iteration === "number" ? (payload.iteration as number) : undefined;
862
863
  const pendingApproval = payload.pending_approval === true || stage === "final";
863
864
  return buildRalplanHudSummary({
@@ -11,7 +11,6 @@ import {
11
11
  type WorkflowStateMutationOwner,
12
12
  type WorkflowStateReceipt,
13
13
  } from "../skill-state/workflow-state-contract";
14
- import { validateDeepInterviewV1Envelope } from "./deep-interview-state";
15
14
  import {
16
15
  activeEntryPath as layoutActiveEntryPath,
17
16
  activeSnapshotPath as layoutActiveSnapshotPath,
@@ -78,47 +77,6 @@ export interface WorkflowEnvelopeIntegrityMismatch {
78
77
  expected: string;
79
78
  actual: string;
80
79
  }
81
- export type WorkflowReceiptVerification =
82
- | "legacy"
83
- | "native-valid"
84
- | "receipt-malformed"
85
- | "receipt-missing"
86
- | "checksum-mismatch";
87
-
88
- export interface GuardedWorkflowEnvelopeTransformOptions extends StateWriterOptions {
89
- expectedRevision: number;
90
- /** Additional native schema validation applied to both current and candidate envelopes. */
91
- validate?: (value: Record<string, unknown>, legacy: boolean) => void;
92
- transform: (
93
- current: Record<string, unknown>,
94
- context: { revision: number; legacy: boolean },
95
- ) =>
96
- | { kind: "noop" }
97
- | { kind: "write"; value: Record<string, unknown> }
98
- | Promise<{ kind: "noop" } | { kind: "write"; value: Record<string, unknown> }>;
99
- }
100
-
101
- export interface GuardedWorkflowEnvelopeWarning {
102
- code: "DI_POST_COMMIT_AUDIT_FAILED";
103
- message: string;
104
- }
105
-
106
- export type GuardedWorkflowEnvelopeTransformResult =
107
- | { path: string; written: false; reason: "noop"; revision: number; warnings: [] }
108
- | {
109
- path: string;
110
- written: true;
111
- revision: number;
112
- stamped: Record<string, unknown>;
113
- warnings: GuardedWorkflowEnvelopeWarning[];
114
- };
115
-
116
- export class GuardedWorkflowEnvelopeError extends Error {
117
- constructor(public readonly code: string) {
118
- super(code);
119
- this.name = "GuardedWorkflowEnvelopeError";
120
- }
121
- }
122
80
 
123
81
  export interface WorkflowTransactionJournal {
124
82
  version: 1;
@@ -138,7 +96,6 @@ export interface GuardedStateWriterOptions extends StateWriterOptions {
138
96
  policy: StateWritePolicy;
139
97
  expectedRevision?: number;
140
98
  sourceRevision?: number;
141
- lockHeld?: boolean;
142
99
  }
143
100
 
144
101
  export type GuardedWriteResult =
@@ -150,13 +107,17 @@ export interface StateWriterOptions {
150
107
  receipt?: StateWriterReceiptContext;
151
108
  audit?: StateWriterAuditContext;
152
109
  sourceRevision?: number;
153
- orderingRevision?: number;
154
110
  /**
155
111
  * Cross-process lock tuning for read-modify-write paths that route through
156
112
  * `withWorkflowStateLock` / `updateJsonAtomic`. Omit for the hardened
157
113
  * `withFileLock` defaults.
158
114
  */
159
115
  lock?: FileLockOptions;
116
+ /**
117
+ * Caller already holds the workflow state lock for this target path (via
118
+ * `withWorkflowStateLock`). Skip re-acquisition to avoid self-deadlock.
119
+ */
120
+ lockHeld?: boolean;
160
121
  }
161
122
 
162
123
  export class StateWriteConflictError extends Error {
@@ -298,49 +259,6 @@ export function workflowEnvelopeContentSha256(value: unknown): string {
298
259
  .update(JSON.stringify(canonicalizeJson(withoutReceiptChecksum(value))))
299
260
  .digest("hex");
300
261
  }
301
- export function isNativeDeepInterviewV1(value: Record<string, unknown>): boolean {
302
- if (value.skill !== "deep-interview") return false;
303
- return value.schema_version === 1 || (isPlainObject(value.state) && value.state.schema_version === 1);
304
- }
305
-
306
- export function verifyWorkflowEnvelopeReceiptValue(value: unknown, filePath: string): WorkflowReceiptVerification {
307
- if (!isPlainObject(value)) return "receipt-malformed";
308
- const native = isNativeDeepInterviewV1(value);
309
- if (!Object.hasOwn(value, "receipt")) return native ? "receipt-missing" : "legacy";
310
- if (!isPlainObject(value.receipt) || !isPlainObject(value.receipt.content_sha256)) return "receipt-malformed";
311
-
312
- const receipt = value.receipt as Record<string, unknown>;
313
- const checksum = receipt.content_sha256 as Record<string, unknown>;
314
- if (
315
- typeof value.skill !== "string" ||
316
- receipt.version !== 1 ||
317
- receipt.skill !== value.skill ||
318
- (receipt.skill !== "deep-interview" &&
319
- receipt.skill !== "ralplan" &&
320
- receipt.skill !== "ultragoal" &&
321
- receipt.skill !== "team") ||
322
- (receipt.owner !== "gjc-state-cli" && receipt.owner !== "gjc-runtime" && receipt.owner !== "gjc-hook") ||
323
- typeof receipt.command !== "string" ||
324
- typeof receipt.state_path !== "string" ||
325
- typeof receipt.storage_path !== "string" ||
326
- typeof receipt.mutated_at !== "string" ||
327
- !Number.isFinite(Date.parse(receipt.mutated_at)) ||
328
- typeof receipt.fresh_until !== "string" ||
329
- !Number.isFinite(Date.parse(receipt.fresh_until)) ||
330
- (receipt.status !== "fresh" && receipt.status !== "stale") ||
331
- typeof receipt.mutation_id !== "string" ||
332
- checksum.algorithm !== "sha256" ||
333
- typeof checksum.value !== "string" ||
334
- !/^[0-9a-f]{64}$/.test(checksum.value) ||
335
- typeof checksum.covered_path !== "string" ||
336
- path.resolve(checksum.covered_path) !== path.resolve(filePath) ||
337
- typeof checksum.computed_at !== "string" ||
338
- !Number.isFinite(Date.parse(checksum.computed_at))
339
- ) {
340
- return "receipt-malformed";
341
- }
342
- return workflowEnvelopeContentSha256(value) === checksum.value ? "native-valid" : "checksum-mismatch";
343
- }
344
262
 
345
263
  export function stampWorkflowEnvelopeChecksum<T>(value: T, filePath: string, computedAt = new Date().toISOString()): T {
346
264
  if (!value || typeof value !== "object" || Array.isArray(value)) return value;
@@ -507,11 +425,6 @@ function persistedSourceRevision(value: unknown): number {
507
425
  const revision = value.source_state_revision;
508
426
  return typeof revision === "number" && Number.isFinite(revision) ? revision : persistedStateRevision(value);
509
427
  }
510
- function persistedCommittedModeRevision(value: unknown): number {
511
- if (!isPlainObject(value)) return 0;
512
- const revision = value.committed_mode_state_revision;
513
- return typeof revision === "number" && Number.isFinite(revision) ? revision : 0;
514
- }
515
428
 
516
429
  function withoutCandidateRevision(value: unknown): unknown {
517
430
  if (!isPlainObject(value)) return value;
@@ -620,12 +533,7 @@ async function writeGuardedResolvedJsonAtomic(
620
533
 
621
534
  const incomingSourceRevision =
622
535
  options.sourceRevision ?? (isPlainObject(value) ? persistedStateRevision(value) : 0);
623
- if (
624
- current !== undefined &&
625
- (options.orderingRevision !== undefined
626
- ? options.orderingRevision <= persistedCommittedModeRevision(current)
627
- : incomingSourceRevision <= persistedSourceRevision(current))
628
- ) {
536
+ if (current !== undefined && incomingSourceRevision <= persistedSourceRevision(current)) {
629
537
  return { path: filePath, written: false, reason: "stale-skip", revision: currentRevision };
630
538
  }
631
539
  const next = stampStateRevision(
@@ -659,7 +567,6 @@ export async function writeGuardedWorkflowEnvelopeAtomic(
659
567
  const write = async (): Promise<GuardedWriteResult> => {
660
568
  const current = await readJsonIfPresentTolerant(filePath);
661
569
  const currentRevision = persistedStateRevision(current);
662
-
663
570
  if (options.policy === "source") {
664
571
  if (options.expectedRevision !== undefined && options.expectedRevision !== currentRevision) {
665
572
  throw new StateWriteConflictError(filePath, options.expectedRevision, currentRevision);
@@ -683,15 +590,9 @@ export async function writeGuardedWorkflowEnvelopeAtomic(
683
590
  await maybeAudit(filePath, options);
684
591
  return { path: filePath, written: true, revision: currentRevision + 1, stamped: next };
685
592
  }
686
-
687
593
  const incomingSourceRevision =
688
594
  options.sourceRevision ?? (isPlainObject(value) ? persistedStateRevision(value) : 0);
689
- if (
690
- current !== undefined &&
691
- (options.orderingRevision !== undefined
692
- ? options.orderingRevision <= persistedCommittedModeRevision(current)
693
- : incomingSourceRevision <= persistedSourceRevision(current))
694
- ) {
595
+ if (current !== undefined && incomingSourceRevision <= persistedSourceRevision(current)) {
695
596
  return { path: filePath, written: false, reason: "stale-skip", revision: currentRevision };
696
597
  }
697
598
  const next = stampWorkflowEnvelopeRevisionAndChecksum(
@@ -715,67 +616,6 @@ export async function writeGuardedWorkflowEnvelopeAtomic(
715
616
  };
716
617
  return options.lockHeld ? write() : lockResolvedWorkflowTarget(filePath, write, options.lock);
717
618
  }
718
- export async function transformGuardedWorkflowEnvelopeAtomic(
719
- targetPath: string,
720
- options: GuardedWorkflowEnvelopeTransformOptions,
721
- ): Promise<GuardedWorkflowEnvelopeTransformResult> {
722
- const filePath = resolveGjcTarget(targetPath, cwdForOptions(options));
723
- return lockResolvedWorkflowTarget(
724
- filePath,
725
- async () => {
726
- const read = await readExistingStateForMutation(filePath);
727
- if (read.kind === "absent") throw new GuardedWorkflowEnvelopeError("DI_STATE_ABSENT");
728
- if (read.kind === "corrupt") throw new GuardedWorkflowEnvelopeError("DI_STATE_CORRUPT");
729
- const receipt = verifyWorkflowEnvelopeReceiptValue(read.value, filePath);
730
- if (receipt === "receipt-malformed") throw new GuardedWorkflowEnvelopeError("DI_RECEIPT_MALFORMED");
731
- if (receipt === "receipt-missing") throw new GuardedWorkflowEnvelopeError("DI_RECEIPT_MISSING");
732
- if (receipt === "checksum-mismatch") throw new GuardedWorkflowEnvelopeError("DI_RECEIPT_CHECKSUM_MISMATCH");
733
- const legacy = receipt === "legacy";
734
- try {
735
- if (isNativeDeepInterviewV1(read.value)) validateDeepInterviewV1Envelope(read.value);
736
- options.validate?.(read.value, legacy);
737
- } catch {
738
- throw new GuardedWorkflowEnvelopeError("DI_STATE_SCHEMA_INVALID");
739
- }
740
- const phase = read.value.current_phase;
741
- if (phase === "complete" || phase === "handoff" || read.value.active === false) {
742
- throw new GuardedWorkflowEnvelopeError("DI_PHASE_NOT_REPAIRABLE");
743
- }
744
- const revision = persistedStateRevision(read.value);
745
- if (revision !== options.expectedRevision) throw new GuardedWorkflowEnvelopeError("DI_REVISION_CONFLICT");
746
- const transformed = await options.transform(read.value, { revision, legacy });
747
- if (transformed.kind === "noop")
748
- return { path: filePath, written: false, reason: "noop", revision, warnings: [] };
749
- try {
750
- if (isNativeDeepInterviewV1(transformed.value)) validateDeepInterviewV1Envelope(transformed.value);
751
- options.validate?.(transformed.value, false);
752
- } catch {
753
- throw new GuardedWorkflowEnvelopeError("DI_STATE_SCHEMA_INVALID");
754
- }
755
- const stamped = stampWorkflowEnvelopeRevisionAndChecksum(
756
- transformed.value,
757
- filePath,
758
- revision + 1,
759
- undefined,
760
- options,
761
- ) as Record<string, unknown>;
762
- const parsed = RequiredOnWriteEnvelopeSchema.safeParse(stamped);
763
- if (!parsed.success) throw new GuardedWorkflowEnvelopeError("DI_STATE_SCHEMA_INVALID");
764
- await atomicWrite(filePath, jsonText(stamped));
765
- const warnings: GuardedWorkflowEnvelopeWarning[] = [];
766
- try {
767
- await maybeAudit(filePath, options);
768
- } catch (error) {
769
- warnings.push({
770
- code: "DI_POST_COMMIT_AUDIT_FAILED",
771
- message: error instanceof Error ? error.message : String(error),
772
- });
773
- }
774
- return { path: filePath, written: true, revision: revision + 1, stamped, warnings };
775
- },
776
- options.lock,
777
- );
778
- }
779
619
 
780
620
  export async function writeJsonAtomic(
781
621
  targetPath: string,
@@ -845,63 +685,71 @@ export async function writeWorkflowEnvelopeAtomic(
845
685
  options?: StateWriterOptions,
846
686
  ): Promise<string> {
847
687
  const filePath = resolveGjcTarget(targetPath, cwdForOptions(options));
848
- const withReceipt = withWorkflowReceipt(value, buildReceipt(options));
849
- const stamped = stampWorkflowEnvelopeChecksum(withReceipt, filePath);
850
- const parsed = RequiredOnWriteEnvelopeSchema.safeParse(stamped);
851
- if (!parsed.success) {
852
- throw new Error(
853
- `Refusing to write invalid workflow state envelope to ${filePath}: ${parsed.error.issues
854
- .map(issue => `${issue.path.join(".") || "<root>"}: ${issue.message}`)
855
- .join("; ")}`,
856
- );
857
- }
858
- // #658: internal runtime writers (ralplan/ultragoal/deep-interview/team) persist
859
- // envelopes directly, bypassing the `gjc state` CLI transition gate (`isValidTransition`,
860
- // historically the sole call site in state-runtime.ts). Re-assert that gate on every
861
- // sanctioned envelope write so internal writes cannot persist invalid state-machine phase
862
- // transitions silently. Forced writes (`gjc state ... --force`, reconcile repairs) carry
863
- // `audit.forced` and bypass, mirroring the CLI's `use --force to bypass`.
864
- //
865
- // The gate governs ACTIVE workflow progression only. Deactivation/teardown writes
866
- // (`active: false`, e.g. `gjc state clear`, which persists the universal `complete`
867
- // sentinel that is not a per-skill manifest state) leave the transition graph and are
868
- // intentionally exempt.
869
- if (options?.audit?.forced !== true && parsed.data.active === true) {
870
- const toPhase = parsed.data.current_phase.trim();
871
- if (toPhase) {
872
- // Lazy import: workflow-manifest dereferences CANONICAL_GJC_WORKFLOW_SKILLS at
873
- // module load, and active-state -> state-writer -> workflow-manifest -> active-state
874
- // is a load-time cycle. Importing at call time (after init) avoids the TDZ.
875
- const { isKnownWorkflowState, isValidTransition } = await import("./workflow-manifest");
876
- const skill = parsed.data.skill;
877
- // Structural invariant (hard): a `current_phase` absent from the skill's manifest is
878
- // never a legitimate internal write, matching the CLI/reconcile unknown-phase gate.
879
- if (!isKnownWorkflowState(skill, toPhase)) {
880
- throw new Error(
881
- `Refusing to write unknown ${skill} phase "${toPhase}" to ${filePath}: not a known ${skill} manifest state (forced writes bypass via audit.forced)`,
882
- );
883
- }
884
- // Transition invariant (#658, diagnostic-only safety net): resolve the prior phase
885
- // (caller-supplied `audit.fromPhase`, else the active persisted envelope on disk) and
886
- // flag edges the manifest does not define. Intentionally NON-blocking and audit-only
887
- // — the CLI path already hard-fails invalid edges before reaching here, and legitimate
888
- // internal repairs / ralplan short-mode stage skips move between valid states without a
889
- // direct manifest edge. It records an `invalid_transition_detected` audit entry (no
890
- // stderr) so such transitions are non-silent without breaking those flows.
891
- const fromPhase = (options?.audit?.fromPhase ?? (await readPersistedPhase(filePath)))?.trim();
892
- if (
893
- fromPhase &&
894
- fromPhase !== toPhase &&
895
- isKnownWorkflowState(skill, fromPhase) &&
896
- !isValidTransition(skill, fromPhase, toPhase)
897
- ) {
898
- await recordInvalidWorkflowTransition({ filePath, skill, fromPhase, toPhase, options });
688
+ const write = async (): Promise<string> => {
689
+ const withReceipt = withWorkflowReceipt(value, buildReceipt(options));
690
+ const stamped = stampWorkflowEnvelopeChecksum(withReceipt, filePath);
691
+ const parsed = RequiredOnWriteEnvelopeSchema.safeParse(stamped);
692
+ if (!parsed.success) {
693
+ throw new Error(
694
+ `Refusing to write invalid workflow state envelope to ${filePath}: ${parsed.error.issues
695
+ .map(issue => `${issue.path.join(".") || "<root>"}: ${issue.message}`)
696
+ .join("; ")}`,
697
+ );
698
+ }
699
+ // #658: internal runtime writers (ralplan/ultragoal/deep-interview/team) persist
700
+ // envelopes directly, bypassing the `gjc state` CLI transition gate (`isValidTransition`,
701
+ // historically the sole call site in state-runtime.ts). Re-assert that gate on every
702
+ // sanctioned envelope write so internal writes cannot persist invalid state-machine phase
703
+ // transitions silently. Forced writes (`gjc state ... --force`, reconcile repairs) carry
704
+ // `audit.forced` and bypass, mirroring the CLI's `use --force to bypass`.
705
+ //
706
+ // The gate governs ACTIVE workflow progression only. Deactivation/teardown writes
707
+ // (`active: false`, e.g. `gjc state clear`, which persists the universal `complete`
708
+ // sentinel that is not a per-skill manifest state) leave the transition graph and are
709
+ // intentionally exempt.
710
+ if (options?.audit?.forced !== true && parsed.data.active === true) {
711
+ const toPhase = parsed.data.current_phase.trim();
712
+ if (toPhase) {
713
+ // Lazy import: workflow-manifest dereferences CANONICAL_GJC_WORKFLOW_SKILLS at
714
+ // module load, and active-state -> state-writer -> workflow-manifest -> active-state
715
+ // is a load-time cycle. Importing at call time (after init) avoids the TDZ.
716
+ const { isKnownWorkflowState, isValidTransition } = await import("./workflow-manifest");
717
+ const skill = parsed.data.skill;
718
+ // Structural invariant (hard): a `current_phase` absent from the skill's manifest is
719
+ // never a legitimate internal write, matching the CLI/reconcile unknown-phase gate.
720
+ if (!isKnownWorkflowState(skill, toPhase)) {
721
+ throw new Error(
722
+ `Refusing to write unknown ${skill} phase "${toPhase}" to ${filePath}: not a known ${skill} manifest state (forced writes bypass via audit.forced)`,
723
+ );
724
+ }
725
+ // Transition invariant (#658, diagnostic-only safety net): resolve the prior phase
726
+ // (caller-supplied `audit.fromPhase`, else the active persisted envelope on disk) and
727
+ // flag edges the manifest does not define. Intentionally NON-blocking and audit-only
728
+ // — the CLI path already hard-fails invalid edges before reaching here, and legitimate
729
+ // internal repairs / ralplan short-mode stage skips move between valid states without a
730
+ // direct manifest edge. It records an `invalid_transition_detected` audit entry (no
731
+ // stderr) so such transitions are non-silent without breaking those flows.
732
+ const fromPhase = (options?.audit?.fromPhase ?? (await readPersistedPhase(filePath)))?.trim();
733
+ if (
734
+ fromPhase &&
735
+ fromPhase !== toPhase &&
736
+ isKnownWorkflowState(skill, fromPhase) &&
737
+ !isValidTransition(skill, fromPhase, toPhase)
738
+ ) {
739
+ await recordInvalidWorkflowTransition({ filePath, skill, fromPhase, toPhase, options });
740
+ }
899
741
  }
900
742
  }
901
- }
902
- await atomicWrite(filePath, jsonText(stamped));
903
- await maybeAudit(filePath, options);
904
- return filePath;
743
+ await atomicWrite(filePath, jsonText(stamped));
744
+ await maybeAudit(filePath, options);
745
+ return filePath;
746
+ };
747
+ // Serialize with every other writer of the same state path. Without this, a
748
+ // revision-preserving envelope write (seed/spec persistence) can interleave
749
+ // inside a staged apply's check-then-write window and be silently overwritten
750
+ // (#3387 architect finding 1). Callers already inside `withWorkflowStateLock`
751
+ // for this path pass `lockHeld: true`.
752
+ return options?.lockHeld ? write() : lockResolvedWorkflowTarget(filePath, write, options?.lock);
905
753
  }
906
754
 
907
755
  export async function writeTextAtomic(targetPath: string, text: string, options?: StateWriterOptions): Promise<string> {
@@ -12,6 +12,7 @@ import type {
12
12
  GjcTeamWorkerLifecycle,
13
13
  GjcTeamWorktreeMode,
14
14
  } from "./team-runtime";
15
+ import { createInitialGjcTeamWorkerMemoryGuardLedger, workerMemoryGuardLedgerPath } from "./team-worker-memory-guard";
15
16
 
16
17
  /** Launch-specific option wiring kept separate from runtime dispatch. */
17
18
  export function withTeamLaunchTransport(
@@ -34,6 +35,8 @@ export function buildWorkerCommand(
34
35
  config: GjcTeamConfig,
35
36
  worker: GjcTeamWorker,
36
37
  platform: NodeJS.Platform = process.platform,
38
+ promptOverride?: string,
39
+ env: NodeJS.ProcessEnv = process.env,
37
40
  ): string {
38
41
  const quote = platform === "win32" ? powershellQuote : shellQuote;
39
42
  const envAssignment = (key: string, value: string): string =>
@@ -41,7 +44,8 @@ export function buildWorkerCommand(
41
44
  const workspace = worker.worktree_path
42
45
  ? `Worker worktree: ${worker.worktree_path}.`
43
46
  : `Worker cwd: ${config.leader.cwd}.`;
44
- const prompt =
47
+ const initialPrompt =
48
+ promptOverride ??
45
49
  [
46
50
  `You are ${worker.id} in gjc team ${config.team_name}.`,
47
51
  `Team state root: ${config.state_root}.`,
@@ -50,8 +54,9 @@ export function buildWorkerCommand(
50
54
  "Before implementation, claim your worker-owned task and treat the claimed task record as the source of truth. Do not implement directly from the broad team brief.",
51
55
  `Before claiming work, send startup ACK: gjc team api worker-startup-ack --input '{"team_name":"${config.team_name}","worker_id":"${worker.id}","protocol_version":"1"}' --json.`,
52
56
  "Use gjc team api update-worker-status to report task-local activity, then claim-task/transition-task-status with this worker id; keep heartbeat current during long work, record completion_evidence (summary plus a passed command or verified inspection/artifact item) before completed, and do not mutate leader-owned goal state.",
53
- ]
54
- .join("\n")
57
+ ].join("\n");
58
+ const prompt =
59
+ initialPrompt
55
60
  .replace(/[\uFEFF\u200B]/g, "")
56
61
  .replace(/\r?\n+/g, " ")
57
62
  .trim() || `Worker ${worker.id} ready.`;
@@ -66,6 +71,17 @@ export function buildWorkerCommand(
66
71
  envAssignment("GJC_TEAM_DISPLAY_NAME", config.display_name),
67
72
  envAssignment(SPAWN_PROVENANCE_ENV, config.leader.session_id.trim() || config.team_name),
68
73
  ...(worker.worktree_path ? [envAssignment("GJC_TEAM_WORKTREE_PATH", worker.worktree_path)] : []),
74
+ envAssignment(
75
+ "GJC_TEAM_WORKER_MEMORY_GUARD_PATH",
76
+ workerMemoryGuardLedgerPath(path.join(config.state_root, config.team_name), worker.id),
77
+ ),
78
+ // The worker derives its heartbeat cadence from the same window the leader
79
+ // enforces. tmux panes do not inherit the launching shell's environment, so
80
+ // without this a tightened window would leave workers publishing on the
81
+ // default cadence and reported stale while they are working.
82
+ ...(env.GJC_TEAM_HEARTBEAT_STALE_MS?.trim()
83
+ ? [envAssignment("GJC_TEAM_HEARTBEAT_STALE_MS", env.GJC_TEAM_HEARTBEAT_STALE_MS.trim())]
84
+ : []),
69
85
  ];
70
86
  const joined = envLines.join(" ");
71
87
  const clearInheritedSession = config.gjc_session_id
@@ -146,6 +162,7 @@ async function initializeStateDirs(
146
162
  runtime: GjcTeamLaunchRuntime,
147
163
  dir: string,
148
164
  workers: GjcTeamWorker[],
165
+ platform: NodeJS.Platform,
149
166
  ): Promise<void> {
150
167
  await fs.mkdir(path.join(dir, "mailbox"), { recursive: true });
151
168
  for (const worker of workers) {
@@ -167,6 +184,14 @@ async function initializeStateDirs(
167
184
  turn_count: 0,
168
185
  alive: true,
169
186
  });
187
+ await runtime.writeJson(
188
+ workerMemoryGuardLedgerPath(dir, worker.id),
189
+ createInitialGjcTeamWorkerMemoryGuardLedger({
190
+ workerId: worker.id,
191
+ platform,
192
+ now: runtime.now(),
193
+ }),
194
+ );
170
195
  }
171
196
  await fs.mkdir(runtime.mailboxDirPath(dir, "leader-fixed"), { recursive: true });
172
197
  await runtime.writeJson(runtime.mailboxPath(dir, "leader-fixed"), { messages: [] });
@@ -217,6 +242,18 @@ export async function startGjcTeamLaunch(
217
242
  await runtime.rollbackCreatedWorktrees(workers);
218
243
  throw error;
219
244
  }
245
+ const tasksByOwner = new Map<string, string[]>();
246
+ for (const task of initialTasks) {
247
+ const owner = task.owner?.trim();
248
+ if (!owner) continue;
249
+ const assigned = tasksByOwner.get(owner) ?? [];
250
+ assigned.push(task.id);
251
+ tasksByOwner.set(owner, assigned);
252
+ }
253
+ const workersWithAssignments = workers.map(worker => ({
254
+ ...worker,
255
+ assigned_tasks: tasksByOwner.get(worker.id) ?? worker.assigned_tasks,
256
+ }));
220
257
  const config: GjcTeamConfig = {
221
258
  team_name: teamName,
222
259
  display_name: displayName,
@@ -242,11 +279,11 @@ export async function startGjcTeamLaunch(
242
279
  },
243
280
  leader_cwd: cwd,
244
281
  team_state_root: stateRoot,
245
- workers,
282
+ workers: workersWithAssignments,
246
283
  created_at: createdAt,
247
284
  updated_at: createdAt,
248
285
  };
249
- await initializeStateDirs(runtime, dir, config.workers);
286
+ await initializeStateDirs(runtime, dir, config.workers, platform);
250
287
  await runtime.writeJson(path.join(dir, "config.json"), config);
251
288
  await runtime.writeJson(path.join(dir, "manifest.v2.json"), {
252
289
  version: 2,