@gajae-code/coding-agent 0.2.5 → 0.3.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 (234) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/types/async/job-manager.d.ts +91 -2
  3. package/dist/types/cli/args.d.ts +1 -1
  4. package/dist/types/commands/deep-interview.d.ts +3 -0
  5. package/dist/types/commands/harness.d.ts +37 -0
  6. package/dist/types/config/keybindings.d.ts +5 -0
  7. package/dist/types/config/settings-schema.d.ts +10 -4
  8. package/dist/types/config/settings.d.ts +2 -0
  9. package/dist/types/debug/crash-diagnostics.d.ts +45 -0
  10. package/dist/types/debug/runtime-gauges.d.ts +6 -0
  11. package/dist/types/deep-interview/render-middleware.d.ts +6 -0
  12. package/dist/types/eval/py/executor.d.ts +2 -0
  13. package/dist/types/eval/py/kernel.d.ts +2 -0
  14. package/dist/types/exec/bash-executor.d.ts +10 -0
  15. package/dist/types/extensibility/custom-tools/types.d.ts +1 -0
  16. package/dist/types/extensibility/extensions/types.d.ts +6 -0
  17. package/dist/types/extensibility/shared-events.d.ts +1 -0
  18. package/dist/types/gjc-runtime/cli-write-receipt.d.ts +24 -0
  19. package/dist/types/gjc-runtime/deep-interview-runtime.d.ts +1 -0
  20. package/dist/types/gjc-runtime/state-graph.d.ts +4 -0
  21. package/dist/types/gjc-runtime/state-migrations.d.ts +33 -0
  22. package/dist/types/gjc-runtime/state-renderer.d.ts +65 -0
  23. package/dist/types/gjc-runtime/state-runtime.d.ts +2 -0
  24. package/dist/types/gjc-runtime/state-schema.d.ts +317 -0
  25. package/dist/types/gjc-runtime/state-validation.d.ts +6 -0
  26. package/dist/types/gjc-runtime/state-writer.d.ts +147 -0
  27. package/dist/types/gjc-runtime/team-runtime.d.ts +81 -7
  28. package/dist/types/gjc-runtime/workflow-command-ref.d.ts +43 -0
  29. package/dist/types/gjc-runtime/workflow-manifest.d.ts +54 -0
  30. package/dist/types/harness-control-plane/classifier.d.ts +13 -0
  31. package/dist/types/harness-control-plane/control-endpoint.d.ts +31 -0
  32. package/dist/types/harness-control-plane/finalize.d.ts +47 -0
  33. package/dist/types/harness-control-plane/frame-mapper.d.ts +29 -0
  34. package/dist/types/harness-control-plane/operate.d.ts +35 -0
  35. package/dist/types/harness-control-plane/owner.d.ts +46 -0
  36. package/dist/types/harness-control-plane/preserve.d.ts +19 -0
  37. package/dist/types/harness-control-plane/receipts.d.ts +88 -0
  38. package/dist/types/harness-control-plane/rpc-adapter.d.ts +66 -0
  39. package/dist/types/harness-control-plane/seams.d.ts +21 -0
  40. package/dist/types/harness-control-plane/session-lease.d.ts +65 -0
  41. package/dist/types/harness-control-plane/state-machine.d.ts +19 -0
  42. package/dist/types/harness-control-plane/storage.d.ts +53 -0
  43. package/dist/types/harness-control-plane/types.d.ts +162 -0
  44. package/dist/types/hooks/skill-keywords.d.ts +2 -1
  45. package/dist/types/hooks/skill-state.d.ts +23 -29
  46. package/dist/types/internal-urls/agent-protocol.d.ts +2 -2
  47. package/dist/types/internal-urls/artifact-protocol.d.ts +2 -2
  48. package/dist/types/internal-urls/registry-helpers.d.ts +8 -7
  49. package/dist/types/internal-urls/types.d.ts +4 -0
  50. package/dist/types/lsp/index.d.ts +10 -10
  51. package/dist/types/modes/bridge/auth.d.ts +12 -0
  52. package/dist/types/modes/bridge/bridge-client-bridge.d.ts +9 -0
  53. package/dist/types/modes/bridge/bridge-mode.d.ts +44 -0
  54. package/dist/types/modes/bridge/bridge-ui-context.d.ts +88 -0
  55. package/dist/types/modes/bridge/event-stream.d.ts +8 -0
  56. package/dist/types/modes/components/custom-editor.d.ts +6 -0
  57. package/dist/types/modes/components/hook-selector.d.ts +1 -0
  58. package/dist/types/modes/components/jobs-overlay-model.d.ts +31 -0
  59. package/dist/types/modes/components/jobs-overlay.d.ts +30 -0
  60. package/dist/types/modes/components/status-line/types.d.ts +2 -0
  61. package/dist/types/modes/components/status-line.d.ts +2 -0
  62. package/dist/types/modes/controllers/input-controller.d.ts +1 -0
  63. package/dist/types/modes/controllers/selector-controller.d.ts +8 -0
  64. package/dist/types/modes/index.d.ts +1 -0
  65. package/dist/types/modes/interactive-mode.d.ts +2 -0
  66. package/dist/types/modes/jobs-observer.d.ts +57 -0
  67. package/dist/types/modes/rpc/host-tools.d.ts +1 -16
  68. package/dist/types/modes/rpc/host-uris.d.ts +1 -38
  69. package/dist/types/modes/shared/agent-wire/command-dispatch.d.ts +20 -0
  70. package/dist/types/modes/shared/agent-wire/command-validation.d.ts +2 -0
  71. package/dist/types/modes/shared/agent-wire/event-envelope.d.ts +24 -0
  72. package/dist/types/modes/shared/agent-wire/handshake.d.ts +46 -0
  73. package/dist/types/modes/shared/agent-wire/host-tool-bridge.d.ts +16 -0
  74. package/dist/types/modes/shared/agent-wire/host-uri-bridge.d.ts +17 -0
  75. package/dist/types/modes/shared/agent-wire/protocol.d.ts +44 -0
  76. package/dist/types/modes/shared/agent-wire/responses.d.ts +4 -0
  77. package/dist/types/modes/shared/agent-wire/scopes.d.ts +18 -0
  78. package/dist/types/modes/shared/agent-wire/ui-request-broker.d.ts +42 -0
  79. package/dist/types/modes/shared/agent-wire/ui-result.d.ts +27 -0
  80. package/dist/types/modes/types.d.ts +2 -0
  81. package/dist/types/sdk.d.ts +4 -0
  82. package/dist/types/session/agent-session.d.ts +19 -1
  83. package/dist/types/skill-state/active-state.d.ts +2 -0
  84. package/dist/types/skill-state/deep-interview-mutation-guard.d.ts +1 -1
  85. package/dist/types/skill-state/workflow-state-contract.d.ts +25 -2
  86. package/dist/types/skill-state/workflow-state-version.d.ts +3 -0
  87. package/dist/types/task/executor.d.ts +3 -0
  88. package/dist/types/task/id.d.ts +7 -0
  89. package/dist/types/task/index.d.ts +5 -0
  90. package/dist/types/task/receipt.d.ts +85 -0
  91. package/dist/types/task/spawn-gate.d.ts +38 -0
  92. package/dist/types/task/types.d.ts +198 -14
  93. package/dist/types/tools/cron.d.ts +6 -0
  94. package/dist/types/tools/index.d.ts +2 -0
  95. package/dist/types/tools/path-utils.d.ts +1 -0
  96. package/dist/types/tools/subagent.d.ts +26 -1
  97. package/package.json +7 -7
  98. package/scripts/build-binary.ts +7 -0
  99. package/src/async/job-manager.ts +334 -6
  100. package/src/cli/args.ts +9 -2
  101. package/src/cli/auth-broker-cli.ts +1 -0
  102. package/src/cli/config-cli.ts +10 -2
  103. package/src/cli.ts +2 -0
  104. package/src/commands/deep-interview.ts +1 -0
  105. package/src/commands/harness.ts +862 -0
  106. package/src/commands/launch.ts +2 -2
  107. package/src/commands/state.ts +2 -1
  108. package/src/commands/team.ts +54 -39
  109. package/src/config/keybindings.ts +6 -0
  110. package/src/config/settings-schema.ts +13 -3
  111. package/src/config/settings.ts +5 -0
  112. package/src/dap/client.ts +17 -3
  113. package/src/debug/crash-diagnostics.ts +223 -0
  114. package/src/debug/runtime-gauges.ts +20 -0
  115. package/src/deep-interview/render-middleware.ts +372 -0
  116. package/src/defaults/gjc/skills/deep-interview/SKILL.md +1 -1
  117. package/src/defaults/gjc/skills/ralplan/SKILL.md +31 -2
  118. package/src/defaults/gjc/skills/team/SKILL.md +47 -21
  119. package/src/defaults/gjc/skills/ultragoal/SKILL.md +106 -13
  120. package/src/eval/py/executor.ts +21 -1
  121. package/src/eval/py/kernel.ts +15 -0
  122. package/src/exec/bash-executor.ts +41 -0
  123. package/src/extensibility/custom-tools/types.ts +1 -0
  124. package/src/extensibility/extensions/types.ts +6 -0
  125. package/src/extensibility/shared-events.ts +1 -0
  126. package/src/gjc-runtime/cli-write-receipt.ts +31 -0
  127. package/src/gjc-runtime/deep-interview-runtime.ts +98 -42
  128. package/src/gjc-runtime/goal-mode-request.ts +11 -3
  129. package/src/gjc-runtime/ralplan-runtime.ts +235 -43
  130. package/src/gjc-runtime/state-graph.ts +86 -0
  131. package/src/gjc-runtime/state-migrations.ts +179 -0
  132. package/src/gjc-runtime/state-renderer.ts +345 -0
  133. package/src/gjc-runtime/state-runtime.ts +1155 -46
  134. package/src/gjc-runtime/state-schema.ts +192 -0
  135. package/src/gjc-runtime/state-validation.ts +49 -0
  136. package/src/gjc-runtime/state-writer.ts +749 -0
  137. package/src/gjc-runtime/team-runtime.ts +1255 -189
  138. package/src/gjc-runtime/ultragoal-runtime.ts +460 -43
  139. package/src/gjc-runtime/workflow-command-ref.ts +239 -0
  140. package/src/gjc-runtime/workflow-manifest.generated.json +1601 -0
  141. package/src/gjc-runtime/workflow-manifest.ts +427 -0
  142. package/src/harness-control-plane/classifier.ts +128 -0
  143. package/src/harness-control-plane/control-endpoint.ts +148 -0
  144. package/src/harness-control-plane/finalize.ts +222 -0
  145. package/src/harness-control-plane/frame-mapper.ts +286 -0
  146. package/src/harness-control-plane/operate.ts +225 -0
  147. package/src/harness-control-plane/owner.ts +600 -0
  148. package/src/harness-control-plane/preserve.ts +102 -0
  149. package/src/harness-control-plane/receipts.ts +216 -0
  150. package/src/harness-control-plane/rpc-adapter.ts +276 -0
  151. package/src/harness-control-plane/seams.ts +39 -0
  152. package/src/harness-control-plane/session-lease.ts +388 -0
  153. package/src/harness-control-plane/state-machine.ts +98 -0
  154. package/src/harness-control-plane/storage.ts +257 -0
  155. package/src/harness-control-plane/types.ts +214 -0
  156. package/src/hooks/skill-keywords.ts +4 -2
  157. package/src/hooks/skill-state.ts +197 -64
  158. package/src/internal-urls/agent-protocol.ts +68 -21
  159. package/src/internal-urls/artifact-protocol.ts +12 -17
  160. package/src/internal-urls/docs-index.generated.ts +3 -2
  161. package/src/internal-urls/registry-helpers.ts +19 -16
  162. package/src/internal-urls/types.ts +4 -0
  163. package/src/lsp/client.ts +18 -2
  164. package/src/main.ts +21 -5
  165. package/src/modes/bridge/auth.ts +41 -0
  166. package/src/modes/bridge/bridge-client-bridge.ts +47 -0
  167. package/src/modes/bridge/bridge-mode.ts +520 -0
  168. package/src/modes/bridge/bridge-ui-context.ts +200 -0
  169. package/src/modes/bridge/event-stream.ts +70 -0
  170. package/src/modes/components/assistant-message.ts +5 -1
  171. package/src/modes/components/custom-editor.ts +101 -0
  172. package/src/modes/components/hook-selector.ts +133 -20
  173. package/src/modes/components/jobs-overlay-model.ts +109 -0
  174. package/src/modes/components/jobs-overlay.ts +172 -0
  175. package/src/modes/components/status-line/presets.ts +7 -5
  176. package/src/modes/components/status-line/segments.ts +25 -0
  177. package/src/modes/components/status-line/types.ts +2 -0
  178. package/src/modes/components/status-line.ts +9 -1
  179. package/src/modes/controllers/event-controller.ts +71 -6
  180. package/src/modes/controllers/extension-ui-controller.ts +43 -1
  181. package/src/modes/controllers/input-controller.ts +105 -9
  182. package/src/modes/controllers/selector-controller.ts +31 -1
  183. package/src/modes/index.ts +1 -0
  184. package/src/modes/interactive-mode.ts +28 -0
  185. package/src/modes/jobs-observer.ts +204 -0
  186. package/src/modes/rpc/host-tools.ts +1 -186
  187. package/src/modes/rpc/host-uris.ts +1 -235
  188. package/src/modes/rpc/rpc-client.ts +25 -10
  189. package/src/modes/rpc/rpc-mode.ts +12 -381
  190. package/src/modes/shared/agent-wire/command-dispatch.ts +341 -0
  191. package/src/modes/shared/agent-wire/command-validation.ts +131 -0
  192. package/src/modes/shared/agent-wire/event-envelope.ts +108 -0
  193. package/src/modes/shared/agent-wire/handshake.ts +117 -0
  194. package/src/modes/shared/agent-wire/host-tool-bridge.ts +194 -0
  195. package/src/modes/shared/agent-wire/host-uri-bridge.ts +236 -0
  196. package/src/modes/shared/agent-wire/protocol.ts +96 -0
  197. package/src/modes/shared/agent-wire/responses.ts +17 -0
  198. package/src/modes/shared/agent-wire/scopes.ts +89 -0
  199. package/src/modes/shared/agent-wire/ui-request-broker.ts +150 -0
  200. package/src/modes/shared/agent-wire/ui-result.ts +48 -0
  201. package/src/modes/types.ts +2 -0
  202. package/src/prompts/agents/executor.md +13 -0
  203. package/src/prompts/tools/subagent.md +39 -4
  204. package/src/prompts/tools/task-summary.md +3 -9
  205. package/src/prompts/tools/task.md +5 -1
  206. package/src/sdk.ts +8 -0
  207. package/src/session/agent-session.ts +445 -71
  208. package/src/session/session-manager.ts +13 -1
  209. package/src/skill-state/active-state.ts +58 -65
  210. package/src/skill-state/deep-interview-mutation-guard.ts +114 -17
  211. package/src/skill-state/initial-phase.ts +2 -0
  212. package/src/skill-state/workflow-state-contract.ts +33 -4
  213. package/src/skill-state/workflow-state-version.ts +3 -0
  214. package/src/slash-commands/builtin-registry.ts +8 -0
  215. package/src/task/executor.ts +79 -13
  216. package/src/task/id.ts +33 -0
  217. package/src/task/index.ts +376 -74
  218. package/src/task/output-manager.ts +5 -4
  219. package/src/task/receipt.ts +297 -0
  220. package/src/task/render.ts +54 -134
  221. package/src/task/spawn-gate.ts +132 -0
  222. package/src/task/types.ts +104 -10
  223. package/src/tools/ask.ts +88 -27
  224. package/src/tools/ast-edit.ts +1 -0
  225. package/src/tools/ast-grep.ts +1 -0
  226. package/src/tools/bash.ts +1 -1
  227. package/src/tools/cron.ts +48 -0
  228. package/src/tools/find.ts +4 -1
  229. package/src/tools/index.ts +2 -0
  230. package/src/tools/path-utils.ts +3 -2
  231. package/src/tools/read.ts +1 -0
  232. package/src/tools/search.ts +1 -0
  233. package/src/tools/skill.ts +6 -1
  234. package/src/tools/subagent.ts +423 -79
@@ -0,0 +1,372 @@
1
+ import { type Component, Container, Markdown, Spacer, Text } from "@gajae-code/tui";
2
+ import { getMarkdownTheme, type Theme } from "../modes/theme/theme";
3
+
4
+ interface RoundQuestionModel {
5
+ kind: "round-question";
6
+ round: string;
7
+ component?: string;
8
+ targeting?: string;
9
+ mode?: string;
10
+ whyNow?: string;
11
+ ambiguity?: string;
12
+ question: string;
13
+ }
14
+
15
+ interface TopologyQuestionModel {
16
+ kind: "topology-question";
17
+ context?: string;
18
+ components: Array<{ name: string; description: string }>;
19
+ question: string;
20
+ }
21
+
22
+ interface ProgressDimension {
23
+ name: string;
24
+ score: string;
25
+ weight: string;
26
+ weighted: string;
27
+ gap: string;
28
+ }
29
+
30
+ interface ProgressModel {
31
+ kind: "progress";
32
+ round: string;
33
+ dimensions: ProgressDimension[];
34
+ ambiguity?: string;
35
+ topology?: string;
36
+ ontology?: string;
37
+ nextTarget?: string;
38
+ status?: string;
39
+ extra?: string;
40
+ }
41
+
42
+ interface ThresholdModel {
43
+ kind: "threshold";
44
+ threshold: string;
45
+ source: string;
46
+ rest: string;
47
+ }
48
+
49
+ type DeepInterviewModel = RoundQuestionModel | TopologyQuestionModel | ProgressModel | ThresholdModel;
50
+
51
+ function normalizeText(text: string): string {
52
+ return text.trim().replaceAll("\r\n", "\n");
53
+ }
54
+
55
+ function stripMarkdownEmphasis(value: string): string {
56
+ return value.replace(/\*\*/g, "").replace(/^"|"$/g, "").trim();
57
+ }
58
+
59
+ function parseRoundQuestion(text: string): RoundQuestionModel | null {
60
+ const normalized = normalizeText(text);
61
+ const lines = normalized.split("\n");
62
+ const headerIndex = lines.findIndex(line => /^Round\s+\d+\s+\|/i.test(line.trim()));
63
+ if (headerIndex < 0) return null;
64
+ const headerLine = lines[headerIndex]?.trim() ?? "";
65
+ const body = lines
66
+ .slice(headerIndex + 1)
67
+ .join("\n")
68
+ .trim();
69
+ if (!body) return null;
70
+
71
+ const componentMatch =
72
+ /^Round\s+(\d+)\s+\|\s+Component:\s*(.*?)\s+\|\s+Targeting:\s*(.*?)\s+\|\s+Why now:\s*(.*?)\s+\|\s+Ambiguity:\s*(.+?)%?\s*$/i.exec(
73
+ headerLine,
74
+ );
75
+ if (componentMatch) {
76
+ return {
77
+ kind: "round-question",
78
+ round: componentMatch[1] ?? "?",
79
+ component: componentMatch[2]?.trim(),
80
+ targeting: componentMatch[3]?.trim(),
81
+ whyNow: componentMatch[4]?.trim(),
82
+ ambiguity: componentMatch[5]?.trim(),
83
+ question: body,
84
+ };
85
+ }
86
+
87
+ const targetingMatch =
88
+ /^Round\s+(\d+)\s+\|\s+Targeting:\s*(.*?)\s+\|\s+Why now:\s*(.*?)\s+\|\s+Ambiguity:\s*(.+?)%?\s*$/i.exec(
89
+ headerLine,
90
+ );
91
+ if (targetingMatch) {
92
+ return {
93
+ kind: "round-question",
94
+ round: targetingMatch[1] ?? "?",
95
+ targeting: targetingMatch[2]?.trim(),
96
+ whyNow: targetingMatch[3]?.trim(),
97
+ ambiguity: targetingMatch[4]?.trim(),
98
+ question: body,
99
+ };
100
+ }
101
+
102
+ const modeMatch = /^Round\s+(\d+)\s+\|\s+(.*?)\s+\|\s+Ambiguity:\s*(.+?)%?\s*$/i.exec(headerLine);
103
+ if (modeMatch) {
104
+ return {
105
+ kind: "round-question",
106
+ round: modeMatch[1] ?? "?",
107
+ mode: modeMatch[2]?.trim(),
108
+ ambiguity: modeMatch[3]?.trim(),
109
+ question: body,
110
+ };
111
+ }
112
+
113
+ return null;
114
+ }
115
+
116
+ function parseTopologyQuestion(text: string): TopologyQuestionModel | null {
117
+ const normalized = normalizeText(text);
118
+ const lines = normalized.split("\n");
119
+ const headerIndex = lines.findIndex(line =>
120
+ /^Round\s+0\s+\|\s+Topology confirmation\s+\|\s+Ambiguity:\s+not scored yet/i.test(line.trim()),
121
+ );
122
+ if (headerIndex < 0) {
123
+ return null;
124
+ }
125
+ const components: TopologyQuestionModel["components"] = [];
126
+ const contextLines: string[] = [];
127
+ const questionLines: string[] = [];
128
+ let inQuestion = false;
129
+ for (const line of lines.slice(headerIndex + 1)) {
130
+ const trimmed = line.trim();
131
+ const component = /^\s*\d+\.\s+([^:]+):\s+(.+)$/.exec(line);
132
+ if (component) {
133
+ components.push({ name: component[1]?.trim() ?? "", description: component[2]?.trim() ?? "" });
134
+ continue;
135
+ }
136
+ if (/\?$/.test(trimmed)) inQuestion = true;
137
+ if (!trimmed) continue;
138
+ if (inQuestion) questionLines.push(trimmed);
139
+ else contextLines.push(trimmed);
140
+ }
141
+ return {
142
+ kind: "topology-question",
143
+ context: contextLines.join("\n") || undefined,
144
+ components,
145
+ question: questionLines.join("\n"),
146
+ };
147
+ }
148
+
149
+ function splitMarkdownTableRow(line: string): string[] {
150
+ const trimmed = line.trim();
151
+ if (!trimmed.startsWith("|") || !trimmed.endsWith("|")) return [];
152
+ return trimmed
153
+ .slice(1, -1)
154
+ .split("|")
155
+ .map(cell => stripMarkdownEmphasis(cell));
156
+ }
157
+
158
+ function parseProgress(text: string): ProgressModel | null {
159
+ const normalized = normalizeText(text);
160
+ const roundMatch = /^Round\s+(\d+)\s+complete\./i.exec(normalized);
161
+ if (!roundMatch) return null;
162
+
163
+ const lines = normalized.split("\n");
164
+ const dimensions: ProgressDimension[] = [];
165
+ const extraLines: string[] = [];
166
+ let ambiguity: string | undefined;
167
+ let topology: string | undefined;
168
+ let ontology: string | undefined;
169
+ let nextTarget: string | undefined;
170
+ let status: string | undefined;
171
+
172
+ for (const [index, line] of lines.entries()) {
173
+ if (index === 0) continue;
174
+ const trimmed = line.trim();
175
+ const cells = splitMarkdownTableRow(line);
176
+ if (cells.length >= 5) {
177
+ const [name = "", score = "", weight = "", weighted = "", gap = ""] = cells;
178
+ if (/^-+$/.test(name) || /^Dimension$/i.test(name)) continue;
179
+ if (/^Ambiguity$/i.test(name)) {
180
+ ambiguity = weighted || score || gap;
181
+ continue;
182
+ }
183
+ dimensions.push({ name, score, weight, weighted, gap });
184
+ continue;
185
+ }
186
+ const topologyMatch = /^\*\*Topology:\*\*\s*(.+)$/.exec(trimmed);
187
+ if (topologyMatch) {
188
+ topology = topologyMatch[1]?.trim();
189
+ continue;
190
+ }
191
+ const ontologyMatch = /^\*\*Ontology:\*\*\s*(.+)$/.exec(trimmed);
192
+ if (ontologyMatch) {
193
+ ontology = ontologyMatch[1]?.trim();
194
+ continue;
195
+ }
196
+ const nextTargetMatch = /^\*\*Next target:\*\*\s*(.+)$/.exec(trimmed);
197
+ if (nextTargetMatch) {
198
+ nextTarget = nextTargetMatch[1]?.trim();
199
+ continue;
200
+ }
201
+ if (/^(Clarity threshold met!|Focusing next question on:)/i.test(trimmed)) {
202
+ status = trimmed;
203
+ continue;
204
+ }
205
+ if (trimmed) extraLines.push(trimmed);
206
+ }
207
+
208
+ if (dimensions.length === 0 && !ambiguity && !topology && !ontology && !nextTarget) return null;
209
+ return {
210
+ kind: "progress",
211
+ round: roundMatch[1] ?? "?",
212
+ dimensions,
213
+ ambiguity,
214
+ topology,
215
+ ontology,
216
+ nextTarget,
217
+ status,
218
+ extra: extraLines.join("\n") || undefined,
219
+ };
220
+ }
221
+
222
+ function parseThreshold(text: string): ThresholdModel | null {
223
+ const normalized = normalizeText(text);
224
+ const match = /^Deep Interview threshold:\s*(.*?)\s*\(source:\s*(.*?)\)\s*$/im.exec(normalized.split("\n")[0] ?? "");
225
+ if (!match) return null;
226
+ return {
227
+ kind: "threshold",
228
+ threshold: match[1]?.trim() ?? "",
229
+ source: match[2]?.trim() ?? "",
230
+ rest: normalized.split("\n").slice(1).join("\n").trim(),
231
+ };
232
+ }
233
+
234
+ function parseDeepInterview(text: string): DeepInterviewModel | null {
235
+ return parseProgress(text) ?? parseTopologyQuestion(text) ?? parseRoundQuestion(text) ?? parseThreshold(text);
236
+ }
237
+
238
+ function addLabel(container: Container, label: string, value: string | undefined, uiTheme: Theme): void {
239
+ if (!value) return;
240
+ container.addChild(new Spacer(1));
241
+ container.addChild(new Text(uiTheme.fg("accent", uiTheme.bold(label)), 0, 0));
242
+ container.addChild(
243
+ new Markdown(value, 2, 0, getMarkdownTheme(), { color: (text: string) => uiTheme.fg("toolOutput", text) }),
244
+ );
245
+ }
246
+
247
+ function renderPipeSummary(title: string, value: string | undefined): string | undefined {
248
+ if (!value) return undefined;
249
+ return (
250
+ value
251
+ .split("|")
252
+ .map(part => part.trim())
253
+ .filter(Boolean)
254
+ .map(part => `- ${part}`)
255
+ .join("\n") || title
256
+ );
257
+ }
258
+
259
+ function renderModel(model: DeepInterviewModel, uiTheme: Theme): Component {
260
+ const container = new Container();
261
+ if (model.kind === "round-question") {
262
+ const meta = [
263
+ `Round ${model.round}`,
264
+ model.ambiguity ? `Ambiguity ${model.ambiguity.replace(/%$/, "")}%` : undefined,
265
+ ]
266
+ .filter(Boolean)
267
+ .join(" · ");
268
+ container.addChild(new Text(uiTheme.fg("toolTitle", uiTheme.bold(`Deep Interview · ${meta}`)), 0, 0));
269
+ addLabel(container, "Component", model.component, uiTheme);
270
+ addLabel(container, "Mode", model.mode, uiTheme);
271
+ addLabel(container, "Target", model.targeting, uiTheme);
272
+ addLabel(container, "Why now", model.whyNow, uiTheme);
273
+ addLabel(container, "Question", model.question, uiTheme);
274
+ return container;
275
+ }
276
+
277
+ if (model.kind === "topology-question") {
278
+ container.addChild(
279
+ new Text(uiTheme.fg("toolTitle", uiTheme.bold("Deep Interview · Round 0 · Topology confirmation")), 0, 0),
280
+ );
281
+ addLabel(container, "Ambiguity", "Not scored yet", uiTheme);
282
+ addLabel(container, "Reading", model.context, uiTheme);
283
+ if (model.components.length > 0) {
284
+ const components = model.components
285
+ .map((component, index) => `${index + 1}. **${component.name}**\n ${component.description}`)
286
+ .join("\n\n");
287
+ addLabel(container, "Components", components, uiTheme);
288
+ }
289
+ addLabel(container, "Question", model.question, uiTheme);
290
+ return container;
291
+ }
292
+
293
+ if (model.kind === "progress") {
294
+ container.addChild(
295
+ new Text(uiTheme.fg("toolTitle", uiTheme.bold(`Deep Interview · Round ${model.round} complete`)), 0, 0),
296
+ );
297
+ addLabel(container, "Ambiguity", model.ambiguity, uiTheme);
298
+ if (model.dimensions.length > 0) {
299
+ container.addChild(new Spacer(1));
300
+ container.addChild(new Text(uiTheme.fg("accent", uiTheme.bold("Clarity")), 0, 0));
301
+ for (const dimension of model.dimensions) {
302
+ const body = [`Score ${dimension.score} · weight ${dimension.weight} · weighted ${dimension.weighted}`];
303
+ if (dimension.gap) body.push(/^clear$/i.test(dimension.gap) ? "Clear" : `Gap: ${dimension.gap}`);
304
+ addLabel(container, dimension.name, body.join("\n"), uiTheme);
305
+ }
306
+ }
307
+ addLabel(container, "Topology", renderPipeSummary("Topology", model.topology), uiTheme);
308
+ addLabel(container, "Ontology", renderPipeSummary("Ontology", model.ontology), uiTheme);
309
+ addLabel(container, "Next target", model.nextTarget, uiTheme);
310
+ addLabel(container, "Status", model.status, uiTheme);
311
+ addLabel(container, "Additional details", model.extra, uiTheme);
312
+ return container;
313
+ }
314
+
315
+ container.addChild(new Text(uiTheme.fg("toolTitle", uiTheme.bold("Deep Interview · Started")), 0, 0));
316
+ addLabel(container, "Threshold", `${model.threshold} · source: ${model.source}`, uiTheme);
317
+ addLabel(container, "Details", model.rest, uiTheme);
318
+ return container;
319
+ }
320
+
321
+ export function renderDeepInterviewAssistantText(text: string, uiTheme: Theme): Component | null {
322
+ const model = parseDeepInterview(text);
323
+ if (!model || model.kind === "round-question" || model.kind === "topology-question") return null;
324
+ return renderModel(model, uiTheme);
325
+ }
326
+
327
+ export function renderDeepInterviewAskQuestion(question: string, uiTheme: Theme): Component | null {
328
+ const model = parseTopologyQuestion(question) ?? parseRoundQuestion(question);
329
+ if (!model) return null;
330
+ return renderModel(model, uiTheme);
331
+ }
332
+
333
+ export function isDeepInterviewAskQuestion(question: string): boolean {
334
+ if (parseTopologyQuestion(question) ?? parseRoundQuestion(question)) return true;
335
+ const normalized = normalizeText(question);
336
+ return /(?:^|\n)\s*Round\s+\d+\s*\|.*?\bAmbiguity\b/i.test(normalized);
337
+ }
338
+
339
+ export function formatDeepInterviewSelectorPrompt(question: string): string | null {
340
+ const model = parseTopologyQuestion(question) ?? parseRoundQuestion(question);
341
+ if (!model) return null;
342
+ if (model.kind === "topology-question") {
343
+ const componentLines =
344
+ model.components.length > 0
345
+ ? [
346
+ "Components:",
347
+ ...model.components.map(
348
+ (component, index) => `${index + 1}. ${component.name} — ${component.description}`,
349
+ ),
350
+ ]
351
+ : [];
352
+ return [
353
+ "Deep Interview · Round 0 · Topology confirmation",
354
+ "Ambiguity: not scored yet",
355
+ model.context ? `Reading:\n${model.context}` : undefined,
356
+ ...componentLines,
357
+ model.question ? `Question:\n${model.question}` : undefined,
358
+ ]
359
+ .filter((line): line is string => Boolean(line))
360
+ .join("\n\n");
361
+ }
362
+ return [
363
+ `Deep Interview · Round ${model.round}${model.ambiguity ? ` · Ambiguity ${model.ambiguity.replace(/%$/, "")}%` : ""}`,
364
+ model.component ? `Component: ${model.component}` : undefined,
365
+ model.mode ? `Mode: ${model.mode}` : undefined,
366
+ model.targeting ? `Target: ${model.targeting}` : undefined,
367
+ model.whyNow ? `Why now: ${model.whyNow}` : undefined,
368
+ model.question,
369
+ ]
370
+ .filter((line): line is string => Boolean(line))
371
+ .join("\n");
372
+ }
@@ -125,7 +125,7 @@ Deep Interview threshold: <resolvedThresholdPercent> (source: <resolvedThreshold
125
125
  ```json
126
126
  {
127
127
  "active": true,
128
- "current_phase": "deep-interview",
128
+ "current_phase": "interviewing",
129
129
  "state": {
130
130
  "interview_id": "<uuid>",
131
131
  "type": "greenfield|brownfield",
@@ -49,10 +49,12 @@ Restricted read-only role agents (`planner`, `architect`, and `critic`) must pas
49
49
 
50
50
  After a role agent persists a stage artifact, its model-facing response to the caller SHOULD be receipt-only: return the `gjc ralplan --write --json` receipt (`run_id`, `path`, `stage`, `stage_n`, `sha256`, `created_at`) plus the minimal verdict/status fields the caller needs for routing, and do **not** paste the full persisted markdown back into the parent conversation. Downstream reviewers should receive the artifact path/receipt and read the persisted file themselves when they actually need the body. This preserves the audit trail while preventing Planner/Architect/Critic verdict bodies from being duplicated into the main-agent context.
51
51
 
52
+ RECEIPT-ONLY guideline: role agents (`planner`, `architect`, and `critic`) persist durable outputs via `gjc ralplan --write` and return ONLY the receipt fields (`run_id`, `path`, `sha256`) plus verdict/status routing fields; include `stage` and `stage_n` when available, and never return the full persisted body.
53
+
52
54
  This skill runs GJC planning in consensus mode for the provided arguments.
53
55
 
54
56
  The consensus workflow:
55
- 1. **Planner** creates initial plan and a compact **RALPLAN-DR summary** before review, then persists the stage with `gjc ralplan --write --stage planner --stage_n 1 --artifact "..."`:
57
+ 1. **Planner** creates the initial plan and a compact **RALPLAN-DR summary** before review. Launch the Planner ONCE per run as a detached, resumable subagent (await it before the Architect) and record its returned subagent id as the run's persisted Planner id; persist the stage with `gjc ralplan --write --stage planner --stage_n 1 --artifact "..." --planner-id <id> --planner-resumable <true|false>` (see **Persisted Planner** below):
56
58
  - After persistence, return only the receipt/path plus compact planning status; do not paste the full plan markdown back to the caller unless explicitly requested.
57
59
  - Principles (3-5)
58
60
  - Decision Drivers (top 3)
@@ -66,7 +68,7 @@ The consensus workflow:
66
68
  - The Critic agent/subagent must persist its evaluation with `gjc ralplan --write --stage critic --stage_n <N> --artifact "..." --json`, then return the receipt/path plus compact verdict/status (`OKAY`/`ITERATE`/`REJECT`) instead of pasting the full evaluation body.
67
69
  5. **Re-review loop** (max 5 iterations): Any non-`APPROVE` Critic verdict (`ITERATE` or `REJECT`) MUST run the same full closed loop:
68
70
  a. Collect Architect + Critic feedback
69
- b. Revise the plan with Planner
71
+ b. Revise the plan by resuming the SAME persisted Planner subagent with consolidated Architect + Critic feedback (see **Persisted Planner** below); fall back to a fresh Planner spawn only per the fallback routing table
70
72
  c. Return to Architect review
71
73
  - Persist each Planner revision with `gjc ralplan --write --stage revision --stage_n <N> --artifact "..." --json` before re-review, then pass the receipt/path forward instead of duplicating the full revision markdown in the parent conversation.
72
74
  d. Return to Critic evaluation
@@ -88,6 +90,33 @@ The consensus workflow:
88
90
 
89
91
  Follow the Plan skill's full documentation for consensus mode details.
90
92
 
93
+ ### Persisted Planner (consensus loop)
94
+
95
+ The Planner is a **same-session persisted subagent**: launched detached once, awaited before the Architect, then **resumed** with consolidated Architect + Critic feedback on every re-review pass instead of being re-spawned. The Architect and Critic stay **fresh, independent spawns each pass** so their verdicts remain reproducible from their pass artifacts alone. Do NOT modify the subagent control surface; this orchestration uses the existing `subagent` resume/steer controls only.
96
+
97
+ **Persistence boundary:** this is same-parent, active-session continuity only. Resumability depends on the in-memory subagent record (and a persistent parent session — an in-memory parent yields `resumable:false`), not just a session file. The `.gjc` run-state record is an audit/routing hint, NOT a durable cross-process subagent registry. After a process restart, a missing record, or any unavailable/failed resume, use the fresh Planner fallback.
98
+
99
+ **Resume routing table** (per re-review pass, when resuming the persisted Planner id):
100
+
101
+ | Resume outcome | Action |
102
+ |---|---|
103
+ | `running` | `steer`/inject the consolidated feedback to the same id, then await — do NOT fresh-spawn |
104
+ | `queued` | retain/update the queued message or await the same id — do NOT fresh-spawn just because it is queued |
105
+ | `context_unavailable`, `not_found`, `no_runner`, `resume_failed` | fresh Planner spawn for that pass; record the fallback metadata |
106
+ | terminal (`completed`/`failed`/`cancelled`) + revision message | resume the same id when context is available; otherwise use the fresh fallback above |
107
+
108
+ **Recording persisted-Planner metadata** (audit/routing only — never claim `subagent list` proves resumability, since the snapshot does not expose `resumable`). Ride these optional flags on the normal `--write` for the planner/revision stage of the pass:
109
+
110
+ ```
111
+ gjc ralplan --write --stage revision --stage_n <N> --artifact "..." \
112
+ --planner-id <id> --planner-resumable <true|false> \
113
+ --fallback-reason <context_unavailable|not_found|no_runner|resume_failed|process_restart|missing_record> \
114
+ --fallback-attempted-id <id> --fallback-stage-n <N> \
115
+ --fallback-receipt-path <fresh-planner-stage-artifact-path> --json
116
+ ```
117
+
118
+ Set `--planner-resumable true` only when the parent session is provably persistent; set/record `false` after an observed `context_unavailable`; otherwise omit it (unknown). Fallback flags are recorded only when a fresh-spawn fallback actually occurs: a fallback record requires `--fallback-reason` **together with** `--fallback-attempted-id` and `--fallback-stage-n` (the failed id and the pass it failed on), while `--fallback-receipt-path` (the fresh Planner's stage artifact) is optional.
119
+
91
120
  ## Pre-Execution Gate
92
121
 
93
122
  ### Why the Gate Exists
@@ -56,6 +56,7 @@ requiring a separate linked execution loop up front. GJC team supports current-w
56
56
 
57
57
  - **Canonical launch:** use plain `gjc team ...` / `$team ...` for the coordinated worker.
58
58
  - **Verification ownership:** keep one lane focused on tests, regression coverage, and evidence before shutdown.
59
+ - **Typed lanes:** model delivery, verification, architecture, or specialist work as task `lane` metadata plus `required_role` / `allowed_roles`; claiming enforces owner, role, dependency, and lease order.
59
60
  - **Escalation:** use a new explicit follow-up task only when later manual work still needs a persistent single-owner fix/verification loop.
60
61
  - **Deprecation:** nested team execution commands have been removed. Use plain `gjc team ...` for coordinated execution.
61
62
 
@@ -135,6 +136,9 @@ When `$team` is used as a follow-up mode from ralplan, carry forward the approve
135
136
  - `.gjc/state/team/<team>/manifest.v2.json`
136
137
  - `.gjc/state/team/<team>/tasks/task-1.json`
137
138
  - `.gjc/state/team/<team>/mailbox/worker-1.json`
139
+ - `.gjc/state/team/<team>/workers/<worker>/status.json`
140
+ - `.gjc/state/team/<team>/workers/<worker>/lifecycle.json`
141
+ - `.gjc/state/team/<team>/workers/<worker>/heartbeat.json`
138
142
  4. Resolve the worker command from `GJC_TEAM_WORKER_COMMAND` or the active `gjc` entrypoint.
139
143
  5. Split the current tmux window like GJC team: worker 1 is split horizontally to the right of the leader, workers 2..N are vertically stacked in the right column, then `select-layout main-vertical` and `main-pane-width` keep leader-left/worker-right at roughly 50/50.
140
144
  6. Launch the worker with:
@@ -148,7 +152,7 @@ When `$team` is used as a follow-up mode from ralplan, carry forward the approve
148
152
  - diverged worker history is cherry-picked into the leader
149
153
  - idle/done/failed worker worktrees are cross-rebased onto the updated leader after integration; working workers are skipped
150
154
  - conflicts are aborted, recorded, and reported to the leader mailbox without falsely advancing `last_integrated_head`
151
- 8. Store pane/target/integration evidence in config/manifest/snapshot: `tmux_session`, `tmux_session_name`, `tmux_target`, leader pane id, worker pane ids, and `integration_by_worker`.
155
+ 8. Store pane/target/integration/lifecycle evidence in config/manifest/snapshot: `tmux_session`, `tmux_session_name`, `tmux_target`, leader pane id, worker pane ids, `worker_lifecycle_by_id`, and `integration_by_worker`.
152
156
  9. Return control to the leader; follow-up uses `status`, `resume`, `shutdown`, and `gjc team api`.
153
157
 
154
158
  Important:
@@ -163,14 +167,15 @@ Important:
163
167
 
164
168
  Follow this exact lifecycle when running `$team`:
165
169
 
166
- 1. Start team and verify startup evidence (team line, tmux target, worker pane id, state dir).
170
+ 1. Start team and verify startup evidence (team line, tmux target, worker pane id, state dir, `worker_lifecycle_by_id.<worker>.lifecycle_state=ready` after startup ACK).
167
171
  2. Monitor task progress with runtime/state tools first (`gjc team status <team>`, `gjc team resume <team>`, task files).
168
- 3. Wait for terminal task state before shutdown:
172
+ 3. Wait for terminal task state and integration settlement before shutdown:
169
173
  - `pending=0`
170
174
  - `in_progress=0`
171
175
  - `failed=0` (or explicitly acknowledged failure path)
176
+ - no pending integration request/conflict (`status` / `resume` must not report `phase=awaiting_integration`)
172
177
  4. Only then run `gjc team shutdown <team>`.
173
- 5. Verify shutdown evidence and preserved state (`phase=complete`, worker status `stopped`). If shutdown is forced before task completion, expect `phase=cancelled` or `phase=failed`, not `complete`.
178
+ 5. Verify shutdown evidence and preserved state (`phase=complete`, worker runtime status `stopped`, lifecycle `stopped` with a matching graceful shutdown request id). If shutdown is forced before evidence-backed task completion, expect `phase=cancelled` or `phase=failed`; if tasks are complete but integration is still pending or conflicted, expect `phase=awaiting_integration`, not `complete`.
174
179
 
175
180
  Do not run `shutdown` while the worker is actively writing updates unless user explicitly requested abort/cancel. Do not treat ad-hoc pane typing as primary control flow when runtime/state evidence is available.
176
181
 
@@ -181,24 +186,28 @@ While a team is running, keep checking live team state until terminal completion
181
186
  Minimum acceptable loop:
182
187
 
183
188
  ```bash
184
- sleep 30 && gjc team status <team-name>
189
+ sleep 30 && gjc team monitor <team-name>
185
190
  ```
191
+ The mutating monitor path also performs bounded liveness recovery: expired task claims, stale heartbeat claims, and missing recorded worker panes are requeued instead of leaving work permanently `in_progress`.
186
192
 
187
193
  ## Operational Commands
188
194
 
189
195
  ```bash
190
196
  gjc team status <team-name>
197
+ gjc team monitor <team-name>
191
198
  gjc team resume <team-name>
192
199
  gjc team shutdown <team-name>
193
200
  ```
194
201
 
195
202
  Semantics:
196
203
 
197
- - `status`: mutating monitor path; reads team snapshot and applies pending worker worktree integration before returning task counts, worker state, tmux target/pane evidence, and `integration_by_worker`.
198
- - `resume`: mutating monitor path; performs the same integration-aware live snapshot for reconnect/inspection flows.
204
+ - `status`: read-only snapshot path; it does not recover claims, replay notifications, integrate worker commits, or sync HUD state.
205
+ - `monitor`: mutating monitor path; reads team snapshot, recovers expired/stale worker claims, applies pending worker worktree integration, replays notifications, syncs HUD state, and returns task counts, worker state, tmux target/pane evidence, `worker_lifecycle_by_id`, and `integration_by_worker`.
206
+ - `resume`: mutating monitor path; performs the same liveness-recovery and integration-aware live snapshot for reconnect/inspection flows.
199
207
  - `list`: pure read path; lists known teams without integrating worker commits.
200
- - API/read-only snapshot operations are pure unless explicitly documented as a monitor/status path.
201
- - `shutdown`: kills the recorded worker pane when it still belongs to the stored tmux target, removes clean created worktrees, marks worker stopped, and sets phase from task state: `complete` only when all tasks completed, `failed` when tasks failed/blocked, and `cancelled` when work remains pending or in progress. It preserves `.gjc/state/team/<team>` as evidence.
208
+ - API/read-only snapshot operations are pure unless explicitly documented as a monitor path.
209
+ - `claim-task`: mutating task path; before granting a new claim, it recovers expired claims and rejects claims from workers already classified as not live.
210
+ - `shutdown`: writes per-worker graceful `shutdown-request.json`, moves lifecycle through `draining` to `stopped`, kills the recorded worker pane when it still belongs to the stored tmux target, removes clean created worktrees, marks worker runtime status stopped, and sets phase from task, lifecycle, and integration state: `complete` only when all tasks have verified `completion_evidence`, every worker has matching graceful shutdown lifecycle evidence, and no integration request/conflict is pending; `awaiting_integration` when tasks and lifecycle are complete but leader integration still requires action; `failed` when tasks failed/blocked or completed tasks lack valid evidence; and `cancelled` when work remains pending or in progress. It preserves `.gjc/state/team/<team>` as evidence.
202
211
 
203
212
  ## Data Plane and Control Plane
204
213
 
@@ -214,15 +223,20 @@ Semantics:
214
223
  - `.gjc/state/team/<team>/manifest.v2.json`
215
224
  - `.gjc/state/team/<team>/phase.json`
216
225
  - `.gjc/state/team/<team>/events.jsonl`
226
+ - `.gjc/state/team/<team>/trace.jsonl`
227
+ - `.gjc/state/team/<team>/trace-errors.jsonl`
217
228
  - `.gjc/state/team/<team>/telemetry.jsonl`
218
229
  - `.gjc/state/team/<team>/monitor-snapshot.json`
219
230
  - `.gjc/state/team/<team>/integration-report.md`
220
- - `.gjc/state/team/<team>/tasks/task-1.json`
221
- - `.gjc/state/team/<team>/evidence/tasks/task-1.json`
231
+ - `.gjc/state/team/<team>/tasks/task-1.json` (includes structured `completion_evidence` after completed transitions)
222
232
  - `.gjc/state/team/<team>/mailbox/worker-1/<message-id>.json`
223
233
  - `.gjc/state/team/<team>/mailbox/worker-1.json` (legacy compatibility view)
224
234
  - `.gjc/state/team/<team>/notifications/<notification-id>.json`
225
235
  - `.gjc/state/team/<team>/workers/<worker>/startup-ack.json`
236
+ - `.gjc/state/team/<team>/workers/<worker>/status.json`
237
+ - `.gjc/state/team/<team>/workers/<worker>/lifecycle.json`
238
+ - `.gjc/state/team/<team>/workers/<worker>/heartbeat.json`
239
+ - `.gjc/state/team/<team>/workers/<worker>/shutdown-request.json`
226
240
  - `.gjc/state/team/<team>/workers/<worker>/nudges/<fingerprint>.json`
227
241
  - `.gjc/reports/team-commit-hygiene/<team>.ledger.json`
228
242
 
@@ -233,17 +247,28 @@ Use `gjc team api` for machine-readable task lifecycle operations.
233
247
  ```bash
234
248
  gjc team api worker-startup-ack --input '{"team_name":"my-team","worker_id":"worker-1","protocol_version":"1"}' --json
235
249
  gjc team api claim-task --input '{"team_name":"my-team","worker_id":"worker-1"}' --json
236
- gjc team api transition-task-status --input '{"team_name":"my-team","task_id":"task-1","to":"completed","worker_id":"worker-1","claim_token":"<claim-token>","evidence":"summary of completed work and validation"}' --json
250
+ gjc team api transition-task-status --input '{"team_name":"my-team","task_id":"task-1","to":"completed","worker_id":"worker-1","claim_token":"<claim-token>","completion_evidence":{"summary":"Completed requested work and verified it locally.","items":[{"kind":"command","status":"passed","summary":"Focused test passed","command":"bun test packages/coding-agent/test/gjc-runtime/team-runtime.test.ts"}],"files":["packages/coding-agent/test/gjc-runtime/team-runtime.test.ts"],"notes":"Include at least one passed command or verified inspection/artifact item."}}' --json
251
+ gjc team api update-worker-status --input '{"team_name":"my-team","worker_id":"worker-1","status":"working","current_task_id":"task-1"}' --json
252
+ gjc team api recover-stale-claims --input '{"team_name":"my-team"}' --json
253
+ gjc team api read-traces --input '{"team_name":"my-team"}' --json
254
+ gjc team api create-task --input '{"team_name":"my-team","subject":"Verify delivery","description":"Run verification","owner":"worker-1","lane":"verification","required_role":"executor","depends_on":["task-1"]}' --json
237
255
  ```
238
256
 
239
257
  Canonical worker lifecycle operations:
240
258
 
241
- - `worker-startup-ack` before task work
259
+ - `worker-startup-ack` before task work; this records startup ACK and moves `workers/<worker>/lifecycle.json` to `ready`
242
260
  - `claim-task`
243
- - `transition-task-status` with the claim token, worker id, and completion evidence
261
+ - `update-worker-status` when the worker starts/stops a task-local activity; this updates worker-reported `status.json` without replacing the runtime lifecycle source of truth
262
+ - `recover-stale-claims` is leader/runtime-owned; it clears expired claim files, requeues in-progress tasks claimed by stale workers, and records `task_claim_recovered` events without modifying terminal task records or completion evidence
263
+ - `transition-task-status` with the claim token, worker id, and structured `completion_evidence` object
244
264
  - `release-task-claim`
265
+ Claim eligibility is ordered and must not be bypassed: explicit task id selection, task status/terminal checks, owner/assignee checks, lane/role checks, dependency/blocked checks, then active lease creation. `lane` is descriptive metadata; `required_role` and `allowed_roles` are the enforced worker role gates.
245
266
 
246
- GJC-team interop operations are also available for mailbox, native notification, worker heartbeat/status, startup ACK, events, monitor snapshots, approvals, and shutdown request/ack flows; run `gjc team api --help` for the full operation list.
267
+ Completion evidence is stored inline on the task record as `completion_evidence`. It must include a non-empty `summary`, an `items` array, and at least one item with `status: "passed"` or `status: "verified"`. Valid item kinds are `command`, `inspection`, and `artifact`; command items require `command`. The camel-case alias `completionEvidence` is accepted by the API input, but legacy string `evidence` and separate evidence files are not part of the public completion contract.
268
+
269
+ GJC-team interop operations are also available for mailbox, native notification, worker heartbeat/status, stale-claim recovery, startup ACK, events, monitor snapshots, approvals, and shutdown request/ack flows; run `gjc team api --help` for the full operation list.
270
+
271
+ Structured trace records in `trace.jsonl` are append-only schema version 1 entries. Each trace references the legacy `events.jsonl` source via `source_event_id`, keeps `event_type`, worker/task ids, and includes `evidence_refs` for completion evidence or claim recovery when available. Trace append failures are isolated in `trace-errors.jsonl` and do not break `events.jsonl` compatibility.
247
272
 
248
273
  ## GJC-native concept parity
249
274
 
@@ -262,9 +287,10 @@ Forbidden assumptions: do not copy OMX paths, Codex notify payload formats, OMX
262
287
  Worker protocol:
263
288
 
264
289
  - Send startup ACK with `worker-startup-ack` before task work.
290
+ - Report worker activity with `update-worker-status`; this is the worker-reported status plane, not the runtime lifecycle state.
265
291
  - Claim pending work with `claim-task`.
266
292
  - Transition the task to `completed`, `failed`, or `blocked` with `transition-task-status`, including claim token and evidence for completion.
267
- - Commit or leave worktree changes in the worker worktree; the leader `status`/`resume` monitor path will auto-checkpoint dirty worktrees and integrate committed history where possible.
293
+ - Commit or leave worktree changes in the worker worktree; the leader `monitor`/`resume` path will auto-checkpoint dirty worktrees and integrate committed history where possible.
268
294
  - Record implementation/verification evidence in normal task output and state files; leader integration/conflict notifications are delivered through `.gjc/state/team/<team>/mailbox/leader-fixed.json`.
269
295
 
270
296
  ## Environment Knobs
@@ -291,7 +317,7 @@ Operator note (important for GJC panes):
291
317
  - **Split failure:** startup records a failed phase if state was already initialized, rolls back created worktrees, and never kills the leader tmux session.
292
318
  - **Worker API ENOENT:** team state is missing or `GJC_TEAM_STATE_ROOT` points somewhere else. Check `.gjc/state/team/<team>/` before assuming worker failure.
293
319
  - **Stale pane on shutdown:** shutdown only kills a recorded worker pane when it still belongs to the stored `tmux_target` and is not the leader pane. Stale panes outside that target require manual inspection.
294
- - **Integration conflict:** `gjc team status <team>` / `resume` aborts the failing merge, cherry-pick, or worker rebase; inspect `.gjc/state/team/<team>/integration-report.md`, `.gjc/state/team/<team>/events.jsonl`, `.gjc/state/team/<team>/mailbox/leader-fixed.json`, and `.gjc/reports/team-commit-hygiene/<team>.ledger.json`.
320
+ - **Integration conflict:** `gjc team monitor <team>` / `resume` aborts the failing merge, cherry-pick, or worker rebase; `gjc team status <team>` is read-only inspection. Inspect `.gjc/state/team/<team>/integration-report.md`, `.gjc/state/team/<team>/events.jsonl`, `.gjc/state/team/<team>/mailbox/leader-fixed.json`, and `.gjc/reports/team-commit-hygiene/<team>.ledger.json`.
295
321
 
296
322
  ### Safe Manual Intervention (last resort)
297
323
 
@@ -330,8 +356,8 @@ tmux list-panes -F '#{pane_id} #{pane_current_command} #{pane_start_command}'
330
356
  tmux kill-pane -t %450
331
357
  tmux kill-pane -t %451
332
358
 
333
- # 3) Remove stale team state only after preserving needed evidence (example)
334
- rm -rf .gjc/state/team/<team-name>
359
+ # 3) Remove stale team state only after preserving needed evidence, using the state runtime
360
+ # cleanup verb documented by the current manifest
335
361
 
336
362
  # 4) Retry
337
363
  gjc team executor "fresh retry"
@@ -349,8 +375,8 @@ When operating this skill, provide concrete progress evidence:
349
375
 
350
376
  1. Team started line (`Team started: <name>`)
351
377
  2. tmux target and worker pane id
352
- 3. task state from `gjc team status <team>` or `.gjc/state/team/<team>/tasks/task-1.json`
353
- 4. shutdown outcome (`phase=complete`, worker status `stopped`) when the run is terminal; incomplete shutdowns must report `phase=cancelled`/`failed`
378
+ 3. task state from read-only `gjc team status <team>`, mutating `gjc team monitor <team>`, or `.gjc/state/team/<team>/tasks/task-1.json`
379
+ 4. shutdown outcome (`phase=complete`, worker status `stopped`) when the run is terminal; incomplete shutdowns must report `phase=cancelled`/`failed`, and integration-blocked shutdowns must report `phase=awaiting_integration`
354
380
 
355
381
  Do not claim success without file/pane evidence.
356
382
  Do not claim clean completion if shutdown occurred with `in_progress>0`.