chati-dev 2.0.3 → 2.0.5

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.
package/assets/logo.svg CHANGED
@@ -35,8 +35,8 @@
35
35
  <ellipse cx="77" cy="100" rx="3.5" ry="2.5" fill="rgba(255,255,255,0.3)"/>
36
36
  <ellipse cx="133" cy="100" rx="3.5" ry="2.5" fill="rgba(255,255,255,0.3)"/>
37
37
 
38
- <!-- "chati.dev" text inline -->
38
+ <!-- "Chati.dev" text inline -->
39
39
  <text x="210" y="122" font-family="ui-monospace,'SF Mono','Menlo','Consolas','Liberation Mono',monospace" font-weight="700" font-size="68" letter-spacing="-1">
40
- <tspan fill="#e6edf3">chati</tspan><tspan fill="#4A90D9">.</tspan><tspan fill="#e6edf3">dev</tspan>
40
+ <tspan fill="#e6edf3">Chati</tspan><tspan fill="#4A90D9">.</tspan><tspan fill="#e6edf3">dev</tspan>
41
41
  </text>
42
42
  </svg>
@@ -338,6 +338,19 @@ Rules:
338
338
 
339
339
  ---
340
340
 
341
+ ## Parallelization
342
+
343
+ ```
344
+ This agent supports TASK-LEVEL parallelization (all modes):
345
+ - Independent tasks (no shared file dependencies) MUST run in parallel terminals
346
+ - Tasks with dependencies run sequentially within their dependency chain
347
+ - Each parallel terminal gets isolated write scope per task
348
+ - Orchestrator monitors all terminals and merges results after each batch
349
+ - See Transition Logic step 4.5, Group 2 for details
350
+ ```
351
+
352
+ ---
353
+
341
354
  ## Input
342
355
 
343
356
  $ARGUMENTS
@@ -362,7 +362,7 @@ Beyond self-validation (Protocol 5.1), the Architect agent enforces:
362
362
 
363
363
  ---
364
364
 
365
- ## Parallelization Hints
365
+ ## Parallelization
366
366
 
367
367
  - **Can run in parallel with**: Detail agent and UX agent (all three activate post-Brief in parallel-eligible pipelines)
368
368
  - **Cannot run in parallel with**: Brief agent (upstream dependency), Phases agent (downstream dependency — requires architecture as input)
@@ -215,7 +215,7 @@ agents:
215
215
  score: {calculated}
216
216
  criteria_count: 9
217
217
  completed_at: "{timestamp}"
218
- current_agent: detail # (greenfield) or architect (brownfield)
218
+ next_parallel_group: [detail, architect, ux] # PARALLEL GROUP see Transition Logic 4.5
219
219
  last_handoff: chati.dev/artifacts/handoffs/brief-handoff.md
220
220
  ```
221
221
 
@@ -226,7 +226,7 @@ last_handoff: chati.dev/artifacts/handoffs/brief-handoff.md
226
226
  **Greenfield:**
227
227
  ```
228
228
  Next steps:
229
- 1. Continue to Detail/PRD agent (Recommended) — define WHAT we'll build
229
+ 1. Continue to Detail + Architect + UX in parallel (Recommended) — 3 agents run simultaneously
230
230
  2. Review the Brief report
231
231
  3. Adjust Brief content
232
232
  ```
@@ -234,7 +234,7 @@ Next steps:
234
234
  **Brownfield:**
235
235
  ```
236
236
  Next steps:
237
- 1. Continue to Architect agent (Recommended) — understand existing constraints first
237
+ 1. Continue to Detail + Architect + UX in parallel (Recommended) — 3 agents run simultaneously
238
238
  2. Review the Brief report
239
239
  3. Adjust Brief content
240
240
  ```
@@ -444,7 +444,7 @@ On failure:
444
444
 
445
445
  ---
446
446
 
447
- ## Parallelization Hints
447
+ ## Parallelization
448
448
 
449
449
  ```
450
450
  This agent is NOT parallelizable.
@@ -453,7 +453,7 @@ On failure:
453
453
 
454
454
  ---
455
455
 
456
- ## Parallelization Hints
456
+ ## Parallelization
457
457
 
458
458
  ```
459
459
  This agent is NOT parallelizable.
@@ -371,7 +371,7 @@ Beyond self-validation (Protocol 5.1), the Detail agent enforces:
371
371
 
372
372
  ---
373
373
 
374
- ## Parallelization Hints
374
+ ## Parallelization
375
375
 
376
376
  - **Can run in parallel with**: Architect agent and UX agent (all three activate post-Brief in parallel-eligible pipelines)
377
377
  - **Cannot run in parallel with**: Brief agent (upstream dependency), Phases agent (downstream dependency — requires PRD as input)
@@ -370,7 +370,7 @@ On failure:
370
370
 
371
371
  ---
372
372
 
373
- ## Parallelization Hints
373
+ ## Parallelization
374
374
 
375
375
  ```
376
376
  This agent is NOT parallelizable.
@@ -392,7 +392,7 @@ Beyond self-validation (Protocol 5.1), the UX agent enforces:
392
392
 
393
393
  ---
394
394
 
395
- ## Parallelization Hints
395
+ ## Parallelization
396
396
 
397
397
  - **Can run in parallel with**: Detail agent and Architect agent (all three activate post-Brief in parallel-eligible pipelines)
398
398
  - **Cannot run in parallel with**: Brief agent (upstream dependency), Phases agent (downstream dependency — requires UX specification as input)
@@ -5,37 +5,57 @@
5
5
  * Validates that the model being used matches the agent's assignment.
6
6
  * Constitution Article XVI enforcement.
7
7
  *
8
- * Model assignments (from agent definitions):
9
- * - orchestrator: opus
10
- * - brief, detail, phases, tasks: sonnet
11
- * - architect, dev: sonnet | upgrade: opus if complex
12
- * - ux: sonnet
13
- * - qa-planning, qa-implementation: sonnet
14
- * - devops: sonnet
15
- * - greenfield-wu, brownfield-wu: sonnet
8
+ * Model assignments (from orchestrator spec — Model Map):
9
+ * - orchestrator: sonnet | upgrade: opus if complex routing
10
+ * - greenfield-wu: haiku | upgrade: sonnet if multi-stack
11
+ * - brownfield-wu: opus | no downgrade
12
+ * - brief: sonnet | upgrade: opus if 10+ integrations
13
+ * - detail: opus | no downgrade
14
+ * - architect: opus | no downgrade
15
+ * - ux: sonnet | upgrade: opus if design system from scratch
16
+ * - phases: sonnet | upgrade: opus if 20+ requirements
17
+ * - tasks: sonnet | upgrade: opus if 50+ tasks
18
+ * - qa-planning: opus | no downgrade
19
+ * - qa-implementation: opus | no downgrade
20
+ * - dev: opus | no downgrade
21
+ * - devops: sonnet | upgrade: opus if multi-env
16
22
  *
17
- * This hook is advisory — it warns but does not block.
23
+ * This hook is advisory in IDE mode — it warns but does not block.
18
24
  */
19
25
 
20
26
  import { existsSync, readFileSync } from 'fs';
21
27
  import { join } from 'path';
22
28
 
23
29
  const AGENT_MODELS = {
24
- orchestrator: 'opus',
25
- 'greenfield-wu': 'sonnet',
26
- 'brownfield-wu': 'sonnet',
30
+ orchestrator: 'sonnet',
31
+ 'greenfield-wu': 'haiku',
32
+ 'brownfield-wu': 'opus',
27
33
  brief: 'sonnet',
28
- detail: 'sonnet',
29
- architect: 'sonnet',
34
+ detail: 'opus',
35
+ architect: 'opus',
30
36
  ux: 'sonnet',
31
37
  phases: 'sonnet',
32
38
  tasks: 'sonnet',
33
- 'qa-planning': 'sonnet',
34
- 'qa-implementation': 'sonnet',
35
- dev: 'sonnet',
39
+ 'qa-planning': 'opus',
40
+ 'qa-implementation': 'opus',
41
+ dev: 'opus',
36
42
  devops: 'sonnet',
37
43
  };
38
44
 
45
+ /**
46
+ * Upgrade conditions per agent. When context matches, the model
47
+ * should be upgraded to the specified target.
48
+ */
49
+ const UPGRADE_CONDITIONS = {
50
+ orchestrator: { to: 'opus', condition: 'complex routing or deviation handling' },
51
+ 'greenfield-wu': { to: 'sonnet', condition: 'multi-stack or enterprise' },
52
+ brief: { to: 'opus', condition: '10+ integrations' },
53
+ ux: { to: 'opus', condition: 'design system from scratch' },
54
+ phases: { to: 'opus', condition: '20+ requirements' },
55
+ tasks: { to: 'opus', condition: '50+ tasks' },
56
+ devops: { to: 'opus', condition: 'multi-environment or IaC' },
57
+ };
58
+
39
59
  function getCurrentAgent(projectDir) {
40
60
  const sessionPath = join(projectDir, '.chati', 'session.yaml');
41
61
  if (!existsSync(sessionPath)) return null;
@@ -71,6 +91,6 @@ async function main() {
71
91
  }
72
92
  }
73
93
 
74
- export { AGENT_MODELS, getCurrentAgent };
94
+ export { AGENT_MODELS, UPGRADE_CONDITIONS, getCurrentAgent };
75
95
 
76
96
  main();
@@ -158,6 +158,7 @@ brownfield-wu -> Brief -> Architect -> Detail -> UX -> Phases -> Tasks -> QA-Pla
158
158
  | devops | chati.dev/agents/deploy/devops.md |
159
159
 
160
160
  ### Transition Logic
161
+
161
162
  ```
162
163
  When an agent completes (score >= 95%):
163
164
  1. Agent generates handoff at chati.dev/artifacts/handoffs/{agent-name}-handoff.md
@@ -170,17 +171,124 @@ When an agent completes (score >= 95%):
170
171
  - Dev + QA-Implementation = build
171
172
  - Final validation = validate
172
173
  - DevOps = deploy
173
- 7. Read next agent's command file -> Extract Model field from Identity section
174
- 8. Evaluate upgrade conditions against session context
175
- 9. Display model recommendation (see Model Selection Protocol below)
176
- 10. Activate agent
174
+ 7. Activate agent using Hybrid Activation Protocol (see below)
175
+ ```
176
+
177
+ ---
178
+
179
+ ## Hybrid Activation Protocol
180
+
181
+ The orchestrator uses TWO activation modes depending on the agent type:
182
+
183
+ ### Interactive Agents (run IN-CONVERSATION)
184
+
185
+ These agents require human interaction and run in the same terminal as the orchestrator:
186
+ - **greenfield-wu** — needs user description of the project
187
+ - **brownfield-wu** — needs user guidance on codebase
188
+ - **brief** — needs iterative requirement extraction with user
189
+
190
+ For interactive agents:
191
+ ```
192
+ 1. Read the agent's .md file from the Agent Location Map
193
+ 2. Display model recommendation (see Model Map below)
194
+ 3. Load agent context into the conversation
195
+ 4. User interacts with the agent directly
196
+ 5. Agent completes, generates handoff, orchestrator continues
197
+ ```
198
+
199
+ ### Autonomous Agents (run in SEPARATE TERMINALS)
200
+
201
+ All other agents run in separate Claude Code processes with the correct model:
202
+ - **detail**, **architect**, **ux**, **phases**, **tasks**
203
+ - **qa-planning**, **dev**, **qa-implementation**, **devops**
204
+
205
+ For autonomous agents:
206
+ ```
207
+ 1. Use the Bash tool to spawn the agent in a separate terminal:
208
+
209
+ node packages/chati-dev/src/terminal/run-agent.js \
210
+ --agent {agent_name} \
211
+ --task-id {primary_task_id} \
212
+ --project-dir {absolute_project_path} \
213
+ --previous-agent {previous_agent_name} \
214
+ --timeout 600000
215
+
216
+ 2. Wait for the JSON output
217
+
218
+ 3. Parse the result:
219
+ - If "status": "complete" → Save handoff, continue to next agent
220
+ - If "status": "needs_input" → Read "needs_input_question", ask the user,
221
+ then re-run with --additional-context "{user_response}"
222
+ - If "status": "error" → Apply Recovery Protocol (retry up to 2 times)
223
+ - If retries exhausted → Fall back to in-conversation activation
224
+
225
+ 4. Update session.yaml with completion data
226
+ ```
227
+
228
+ ### Parallel Group Execution
229
+
230
+ ╔══════════════════════════════════════════════════════════════╗
231
+ ║ PARALLELIZATION CHECK (MANDATORY — DO NOT SKIP) ║
232
+ ║ ║
233
+ ║ GROUP 1 — Clarity Phase (after Brief completes): ║
234
+ ║ Agents: [detail, architect, ux] ║
235
+ ║ ALL run in parallel via separate terminals ║
236
+ ║ ║
237
+ ║ GROUP 2 — Build Phase (Dev agent tasks): ║
238
+ ║ Independent tasks ALWAYS run in parallel ║
239
+ ║ Tasks with dependencies = sequential within chain ║
240
+ ╚══════════════════════════════════════════════════════════════╝
241
+
242
+ When the next agent is part of a parallel group, use:
243
+
244
+ ```
245
+ node packages/chati-dev/src/terminal/run-parallel.js \
246
+ --agents detail,architect,ux \
247
+ --task-ids {task_id_detail},{task_id_architect},{task_id_ux} \
248
+ --project-dir {absolute_project_path} \
249
+ --previous-agent brief \
250
+ --timeout 900000
251
+ ```
252
+
253
+ Parse the consolidated JSON output:
254
+ - If all agents completed → merged handoff ready, continue to next sequential agent
255
+ - If partial failure → present failed agents to user with options:
256
+ 1. Retry failed agents only
257
+ 2. Continue with partial results
258
+ 3. Fall back to sequential execution for failed agents
259
+
260
+ ### Sequential Fallback
261
+
262
+ If terminal spawning fails (claude CLI not found, system error, etc.):
263
+ ```
264
+ 1. Log the failure
265
+ 2. Fall back to in-conversation activation (read agent .md file, become agent)
266
+ 3. Record in session.yaml:
267
+ terminal_fallback:
268
+ agent: {name}
269
+ reason: "{error_message}"
270
+ timestamp: "{now}"
271
+ 4. Continue pipeline normally
272
+ ```
273
+
274
+ ### Needs-Input Relay Pattern
275
+
276
+ When a spawned agent needs user input:
277
+ ```
278
+ 1. Agent returns status: "needs_input" in JSON output
279
+ 2. Agent includes question in "needs_input_question" field
280
+ 3. Orchestrator reads the question
281
+ 4. Orchestrator presents question to user (in their language)
282
+ 5. User responds
283
+ 6. Orchestrator re-spawns agent with --additional-context "{user_response}"
284
+ 7. Repeat until agent completes or max 3 relay cycles
177
285
  ```
178
286
 
179
287
  ---
180
288
 
181
289
  ## Model Selection Protocol
182
290
 
183
- Before activating any agent, the orchestrator reads the agent's `Model` field and recommends the optimal model.
291
+ Model selection is **enforced by construction**: the orchestrator passes `--model` to the spawned terminal. For interactive agents, the model is recommended to the user.
184
292
 
185
293
  ### Model Map (Quick Reference)
186
294
 
@@ -199,30 +307,19 @@ Before activating any agent, the orchestrator reads the agent's `Model` field an
199
307
  | qa-implementation | opus | no downgrade |
200
308
  | devops | sonnet | opus if multi-environment or IaC |
201
309
 
202
- ### Evaluation Logic
203
-
204
- ```
205
- 1. Read agent's Model field from its .md file
206
- 2. Extract default model and upgrade condition
207
- 3. If upgrade condition exists:
208
- a. Check session context (project.type, codebase_size, integrations_count, requirements_count)
209
- b. Check previous agent signals (handoff complexity, discovered tech debt)
210
- c. If condition matches -> recommend upgraded model
211
- d. If condition does not match -> use default model
212
- 4. If "no downgrade" -> always use the specified model
213
- ```
214
-
215
- ### Recommendation Message (IDE Mode)
216
-
217
- When the recommended model differs from the current model, display:
310
+ ### Enforcement
218
311
 
219
312
  ```
220
- 💡 Model recommendation for {agent_name}: {recommended_model}
221
- Reason: {justification}
222
- Current: {current_model}
313
+ For autonomous agents (spawned terminals):
314
+ Model is AUTOMATICALLY selected and passed via --model flag
315
+ No user intervention needed
316
+ → Correct model guaranteed by the prompt builder
223
317
 
224
- To switch: /model {recommended_model}
225
- Or continue with current model.
318
+ For interactive agents (in-conversation):
319
+ Display model recommendation to user:
320
+ 💡 Model recommendation for {agent_name}: {recommended_model}
321
+ To switch: /model {recommended_model}
322
+ → Model governance hook provides defense-in-depth validation
226
323
  ```
227
324
 
228
325
  ### Session Logging
@@ -230,10 +327,11 @@ When the recommended model differs from the current model, display:
230
327
  ```yaml
231
328
  # Appended to session.yaml on each agent activation
232
329
  model_selections:
233
- - agent: brief
234
- recommended: sonnet
235
- actual: opus # What the user actually used
236
- reason: "default"
330
+ - agent: detail
331
+ recommended: opus
332
+ actual: opus
333
+ mode: terminal # terminal | in-conversation
334
+ reason: "no downgrade"
237
335
  timestamp: "2026-..."
238
336
  ```
239
337
 
@@ -862,6 +960,7 @@ Level 4 - Graceful Degradation:
862
960
  ### Autonomous Mode
863
961
  ```
864
962
  - Execute pipeline transitions silently when gates pass (score >= 95%)
963
+ - Spawn parallel agent groups automatically (Detail + Architect + UX after Brief; independent Dev tasks in parallel)
865
964
  - Auto-resolve simple deviations (redirect to correct agent)
866
965
  - Pause only on:
867
966
  - Quality gate failure (score < 95%)
@@ -886,25 +985,28 @@ Present suggestion with reasoning. User always has final say.
886
985
 
887
986
  ---
888
987
 
889
- ## Parallelization Hints
988
+ ## Parallelization Rules
890
989
 
891
990
  ### Parallelizable Agent Groups
892
991
  ```
893
- Group 1 (post-Brief):
992
+ Group 1 (post-Brief) — MANDATORY PARALLEL:
894
993
  - Detail + Architect + UX
895
- - Can run in 3 parallel terminals
994
+ - MUST run in 3 parallel terminals (autonomous mode)
995
+ - SHOULD offer parallel option (human-in-the-loop mode)
896
996
  - Each writes to isolated artifact directories
897
- - Orchestrator collects and merges results
997
+ - Orchestrator MUST collect and merge ALL handoffs before proceeding to Phases
898
998
 
899
- Group 2 (Dev tasks):
900
- - Independent dev tasks can run in N parallel terminals
901
- - Each terminal has isolated write scope
999
+ Group 2 (Dev tasks) — MANDATORY PARALLEL:
1000
+ - Independent dev tasks MUST run in N parallel terminals (all modes)
1001
+ - Each terminal has isolated write scope per task
902
1002
  - Orchestrator monitors and collects results
1003
+ - Tasks with no shared file dependencies run simultaneously
1004
+ - Tasks with dependencies run sequentially within their chain
903
1005
 
904
- NOT parallelizable:
1006
+ NOT parallelizable (always sequential):
905
1007
  - WU (needs user interaction)
906
1008
  - Brief (needs user interaction)
907
- - Phases (depends on Detail + Architect + UX)
1009
+ - Phases (depends on Detail + Architect + UX results)
908
1010
  - Tasks (depends on Phases)
909
1011
  - QA-Planning (validates everything)
910
1012
  - QA-Implementation (validates everything)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chati-dev",
3
- "version": "2.0.3",
3
+ "version": "2.0.5",
4
4
  "description": "AI-Powered Multi-Agent Orchestration System — 13 agents, 6 IDEs, 4 languages",
5
5
  "type": "module",
6
6
  "bin": {
@@ -45,12 +45,12 @@
45
45
  "license": "MIT",
46
46
  "repository": {
47
47
  "type": "git",
48
- "url": "https://github.com/ogabrielalonso/chati-dev.git",
48
+ "url": "https://github.com/ogabrielalonso/Chati.dev.git",
49
49
  "directory": "packages/chati-dev"
50
50
  },
51
- "homepage": "https://github.com/ogabrielalonso/chati-dev#readme",
51
+ "homepage": "https://github.com/ogabrielalonso/Chati.dev#readme",
52
52
  "bugs": {
53
- "url": "https://github.com/ogabrielalonso/chati-dev/issues"
53
+ "url": "https://github.com/ogabrielalonso/Chati.dev/issues"
54
54
  },
55
55
  "dependencies": {
56
56
  "@clack/prompts": "^0.7.0",
@@ -0,0 +1,127 @@
1
+ /**
2
+ * @fileoverview Parse structured handoff data from spawned agent output.
3
+ *
4
+ * Agents running in separate `claude -p` terminals include a
5
+ * <chati-handoff> block in their output. This module extracts
6
+ * and parses that block so the orchestrator can read the results.
7
+ */
8
+
9
+ /**
10
+ * Parse the <chati-handoff> block from agent stdout.
11
+ *
12
+ * @param {string} output - Full stdout from the agent process
13
+ * @returns {{ found: boolean, handoff: object|null, rawOutput: string }}
14
+ */
15
+ export function parseAgentOutput(output) {
16
+ if (!output || typeof output !== 'string') {
17
+ return { found: false, handoff: null, rawOutput: '' };
18
+ }
19
+
20
+ const match = output.match(/<chati-handoff>([\s\S]*?)<\/chati-handoff>/);
21
+ if (!match) {
22
+ return { found: false, handoff: null, rawOutput: output };
23
+ }
24
+
25
+ const content = match[1].trim();
26
+ const handoff = parseHandoffFields(content);
27
+
28
+ return { found: true, handoff, rawOutput: output };
29
+ }
30
+
31
+ /**
32
+ * Parse YAML-like key-value fields from the handoff block content.
33
+ *
34
+ * Supports:
35
+ * scalar: value
36
+ * list:
37
+ * - item1
38
+ * - item2
39
+ * map:
40
+ * key1: value1
41
+ * key2: value2
42
+ *
43
+ * @param {string} content - Content inside <chati-handoff> tags
44
+ * @returns {object} Parsed handoff data
45
+ */
46
+ function parseHandoffFields(content) {
47
+ const result = {
48
+ status: 'unknown',
49
+ score: null,
50
+ summary: '',
51
+ outputs: [],
52
+ decisions: {},
53
+ blockers: [],
54
+ needs_input_question: null,
55
+ };
56
+
57
+ const lines = content.split('\n');
58
+ let currentKey = null;
59
+ let currentType = null; // 'list' | 'map'
60
+
61
+ for (const line of lines) {
62
+ const trimmed = line.trim();
63
+ if (!trimmed) continue;
64
+
65
+ // Check if this is a list item ( - value)
66
+ const listMatch = trimmed.match(/^-\s+(.+)/);
67
+ if (listMatch && currentKey && currentType === 'list') {
68
+ if (Array.isArray(result[currentKey])) {
69
+ result[currentKey].push(listMatch[1].trim());
70
+ }
71
+ continue;
72
+ }
73
+
74
+ // Check if this is a map item ( key: value) under a map key
75
+ const mapMatch = trimmed.match(/^(\w[\w_-]*):\s+(.+)/);
76
+ if (mapMatch && currentKey && currentType === 'map') {
77
+ if (typeof result[currentKey] === 'object' && !Array.isArray(result[currentKey])) {
78
+ result[currentKey][mapMatch[1]] = mapMatch[2].trim();
79
+ }
80
+ continue;
81
+ }
82
+
83
+ // Top-level key: value
84
+ const kvMatch = trimmed.match(/^(\w[\w_-]*):\s*(.*)/);
85
+ if (kvMatch) {
86
+ const key = kvMatch[1];
87
+ const value = kvMatch[2].trim();
88
+
89
+ // Known list keys
90
+ if (['outputs', 'blockers'].includes(key)) {
91
+ currentKey = key;
92
+ currentType = 'list';
93
+ // If value is inline (not empty), treat as single item
94
+ if (value && value !== '') {
95
+ result[key] = [value];
96
+ currentKey = null;
97
+ currentType = null;
98
+ }
99
+ continue;
100
+ }
101
+
102
+ // Known map keys
103
+ if (['decisions'].includes(key)) {
104
+ currentKey = key;
105
+ currentType = 'map';
106
+ continue;
107
+ }
108
+
109
+ // Scalar keys
110
+ currentKey = null;
111
+ currentType = null;
112
+
113
+ if (key === 'status') {
114
+ result.status = value || 'unknown';
115
+ } else if (key === 'score') {
116
+ const num = parseInt(value, 10);
117
+ result.score = isNaN(num) ? null : num;
118
+ } else if (key === 'summary') {
119
+ result.summary = value || '';
120
+ } else if (key === 'needs_input_question') {
121
+ result.needs_input_question = value === 'null' || value === '' ? null : value;
122
+ }
123
+ }
124
+ }
125
+
126
+ return result;
127
+ }
@@ -28,3 +28,12 @@ export {
28
28
  getReadScope,
29
29
  buildIsolationEnv,
30
30
  } from './isolation.js';
31
+
32
+ export {
33
+ buildAgentPrompt,
34
+ AGENT_FILE_MAP,
35
+ } from './prompt-builder.js';
36
+
37
+ export {
38
+ parseAgentOutput,
39
+ } from './handoff-parser.js';