@dtlabs/ai-toolkit 0.17.4 → 0.18.0

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 (35) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/lib/agent-registry.js +39 -0
  3. package/lib/workflow-control.js +65 -13
  4. package/package.json +1 -1
  5. package/src/claude/agents/gaia-generate-requirements-use-case.md +97 -0
  6. package/src/claude/agents/gaia-generate-requirements.md +22 -27
  7. package/src/claude/agents/gaia-generate-tech-spec-component.md +93 -0
  8. package/src/claude/agents/gaia-generate-tech-spec.md +47 -103
  9. package/src/claude/agents/gaia-generate-work-breakdown-task.md +151 -0
  10. package/src/claude/agents/gaia-generate-work-breakdown.md +94 -100
  11. package/src/claude/agents/gaia-validate-feature-docs.md +13 -8
  12. package/src/claude/commands/assemble-docs.md +16 -0
  13. package/src/claude/commands/feature-status.md +9 -4
  14. package/src/claude/scripts/ac-task-matrix.js +87 -0
  15. package/src/claude/scripts/assemble-docs.js +66 -0
  16. package/src/claude/scripts/req-assembler.js +127 -0
  17. package/src/claude/scripts/req-graph-checks.js +71 -0
  18. package/src/claude/scripts/req-skeleton-check.js +64 -0
  19. package/src/claude/scripts/tech-spec-assembler.js +188 -0
  20. package/src/claude/scripts/tech-spec-graph-checks.js +84 -0
  21. package/src/claude/scripts/templates/gaia-component-template.md +64 -0
  22. package/src/claude/scripts/templates/gaia-dependency-graph-template.md +85 -0
  23. package/src/claude/scripts/templates/gaia-requirements-index-template.md +144 -0
  24. package/src/claude/scripts/templates/gaia-task-template.md +92 -0
  25. package/src/claude/scripts/templates/gaia-tech-spec-index-template.md +137 -0
  26. package/src/claude/scripts/templates/gaia-use-case-template.md +56 -0
  27. package/src/claude/scripts/templates/gaia-user-story-template.md +61 -0
  28. package/src/claude/scripts/wb-graph-checks.js +754 -0
  29. package/src/claude/scripts/wb-render.js +6 -11
  30. package/src/claude/scripts/wb-skeleton-check.js +99 -0
  31. package/src/claude/scripts/wb-validate.js +49 -655
  32. package/src/claude/scripts/wbs-assembler.js +368 -0
  33. package/src/claude/skills/implement-feature/SKILL.md +12 -6
  34. package/src/claude/workflows/pm-phase1.js +342 -16
  35. package/src/claude/workflows/pm-phase2.js +277 -14
package/CHANGELOG.md CHANGED
@@ -1,4 +1,34 @@
1
1
  ## 0.1.4 (2026-07-21)
2
+ ## [0.18.0](https://github.com/dtlab-tech/ai-toolkit/compare/v0.17.5...v0.18.0) (2026-10-19)
3
+
4
+
5
+ ### Features
6
+
7
+ * **planning-pipeline:** split Work Breakdown and Requirements generation into skeleton+per-item passes ([f7e7b66](https://github.com/dtlab-tech/ai-toolkit/commit/f7e7b66efe94a860bbd867402a250c5d92d56f4a))
8
+ * **pm-phase1/pm-phase2:** split-only document generation with on-demand assembly ([40d8700](https://github.com/dtlab-tech/ai-toolkit/commit/40d87007d2125789c7943348ee4000467bffc882))
9
+ * **pm-phase1:** split Tech-Spec generation into skeleton+per-component passes ([a42a83c](https://github.com/dtlab-tech/ai-toolkit/commit/a42a83c9413275888c7e0fa5bfae80a165da3d71))
10
+ * **pm-phase1:** tag Tech-Spec File Inventory with AC IDs and extend the traceability matrix ([4a15510](https://github.com/dtlab-tech/ai-toolkit/commit/4a15510c4d2da110445976d1b9586b6d45252c6f))
11
+ * **pm-phase2:** render an AC-to-Task traceability matrix at Gate 2 ([d975942](https://github.com/dtlab-tech/ai-toolkit/commit/d9759423771454a8d677f747bc0d4fc1e00de375))
12
+ * **templates:** move the FTR-020 doc templates into the toolkit and make generation use them ([de7ffca](https://github.com/dtlab-tech/ai-toolkit/commit/de7ffca19b42ae324d8c8f8460cc9aeda23d8298))
13
+ * traceability matrix, template relocation, split-only doc generation (FTR-025) ([bf17caa](https://github.com/dtlab-tech/ai-toolkit/commit/bf17caa1517fa28a4f28b3efb44f7a327661e184))
14
+
15
+
16
+ ### Bug Fixes
17
+
18
+ * **pm-phase1:** host-compute each use case's Related Business Rules/Acceptance Criteria ([507ecfa](https://github.com/dtlab-tech/ai-toolkit/commit/507ecfa94cb8094049a3543dbf44d47c2ea38f80))
19
+ * **tech-spec-assembler:** make the component Change/Tests heading scan fence-aware ([90af9ca](https://github.com/dtlab-tech/ai-toolkit/commit/90af9ca0585d3280ee12a97d3f745bae7de5fe69))
20
+ * **wb-graph-checks:** scope AC-task validation by a phase's own sourceUC, not its ID ([fab14cb](https://github.com/dtlab-tech/ai-toolkit/commit/fab14cbcb2f4fc180e5b2bb234dad25a5d7a2b61))
21
+ * **wbs:** wire the FTR-020 phase-detail template into real WB generation; fix a second sourceUC-drop ([54ed68e](https://github.com/dtlab-tech/ai-toolkit/commit/54ed68e5921e271a8b6ba4c54b0db748303648b1))
22
+
23
+ ## [0.17.5](https://github.com/dtlab-tech/ai-toolkit/compare/v0.17.4...v0.17.5) (2026-10-13)
24
+
25
+
26
+ ### Bug Fixes
27
+
28
+ * **pm-phase1:** detect truncated Requirements/Tech-Spec instead of silently accepting them ([0783fe1](https://github.com/dtlab-tech/ai-toolkit/commit/0783fe1639258ea9701bffc647b9d0a54a85d3cd))
29
+ * **workflow-control, pm-phase1:** retry transient API errors; catch truncated Gate 1 docs ([47d4f2c](https://github.com/dtlab-tech/ai-toolkit/commit/47d4f2c47f79ac62b5247b44aac13dd2c80a33ad))
30
+ * **workflow-control:** retry worker dispatch on transient CLI/SDK API errors ([d75d02b](https://github.com/dtlab-tech/ai-toolkit/commit/d75d02b866a51ffde51bb276fdf21a60bd38c578))
31
+
2
32
  ## [0.17.4](https://github.com/dtlab-tech/ai-toolkit/compare/v0.17.3...v0.17.4) (2026-10-13)
3
33
 
4
34
 
@@ -168,6 +168,19 @@ const CATALOG = [
168
168
  deprecationTarget: null,
169
169
  platforms: ['claude'],
170
170
  },
171
+ {
172
+ agentId: 'gaia.agent.planner.requirements-use-case',
173
+ nativeNames: { claude: 'gaia-generate-requirements-use-case' },
174
+ relativeInstallPath: '.claude/agents/gaia-generate-requirements-use-case.md',
175
+ role: 'planner',
176
+ type: 'requirements',
177
+ authorisedPhases: ['planning'],
178
+ allowedPipelines: ['implement-feature'],
179
+ minimumToolkitVersion: '0.13.0',
180
+ deprecated: false,
181
+ deprecationTarget: null,
182
+ platforms: ['claude'],
183
+ },
171
184
  {
172
185
  agentId: 'gaia.agent.planner.tech-spec',
173
186
  nativeNames: { claude: 'gaia-generate-tech-spec' },
@@ -181,6 +194,19 @@ const CATALOG = [
181
194
  deprecationTarget: null,
182
195
  platforms: ['claude'],
183
196
  },
197
+ {
198
+ agentId: 'gaia.agent.planner.tech-spec-component',
199
+ nativeNames: { claude: 'gaia-generate-tech-spec-component' },
200
+ relativeInstallPath: '.claude/agents/gaia-generate-tech-spec-component.md',
201
+ role: 'planner',
202
+ type: 'tech-spec',
203
+ authorisedPhases: ['planning'],
204
+ allowedPipelines: ['implement-feature'],
205
+ minimumToolkitVersion: '0.13.0',
206
+ deprecated: false,
207
+ deprecationTarget: null,
208
+ platforms: ['claude'],
209
+ },
184
210
  {
185
211
  agentId: 'gaia.agent.planner.work-breakdown',
186
212
  nativeNames: { claude: 'gaia-generate-work-breakdown' },
@@ -194,6 +220,19 @@ const CATALOG = [
194
220
  deprecationTarget: null,
195
221
  platforms: ['claude'],
196
222
  },
223
+ {
224
+ agentId: 'gaia.agent.planner.work-breakdown-task',
225
+ nativeNames: { claude: 'gaia-generate-work-breakdown-task' },
226
+ relativeInstallPath: '.claude/agents/gaia-generate-work-breakdown-task.md',
227
+ role: 'planner',
228
+ type: 'work-breakdown',
229
+ authorisedPhases: ['planning'],
230
+ allowedPipelines: ['implement-feature'],
231
+ minimumToolkitVersion: '0.13.0',
232
+ deprecated: false,
233
+ deprecationTarget: null,
234
+ platforms: ['claude'],
235
+ },
197
236
  {
198
237
  agentId: 'gaia.agent.planner.validate-feature-docs',
199
238
  nativeNames: { claude: 'gaia-validate-feature-docs' },
@@ -169,28 +169,56 @@ function createControl(options) {
169
169
  });
170
170
  (options.log || (() => {}))('Worker evidence: ' + evidence.file);
171
171
  try {
172
- const result = await (options.dispatch || spawnClaudeAgent)({
173
- claudePath: options.claudePath, cwd: root, args: cliArgs, prompt,
174
- taskTimeoutMs: options.taskTimeoutMs || 1800000,
175
- });
172
+ // Retry a bounded number of times, but ONLY for a recognizable transient
173
+ // infrastructure failure — a CLI/SDK-level "API Error: ..." (stream idle
174
+ // timeout, overload, etc.), never a permission denial, schema violation,
175
+ // or any other deterministic content failure, which would just fail the
176
+ // same way again. Confirmed safe to retry: every agent dispatched through
177
+ // this path is read-only by design (no Write tool — see this function's
178
+ // own comment on why outputs are host-written, not agent-written; any
179
+ // Bash access granted is explicitly scoped to read-only assessment), so
180
+ // there is no partial side effect from a dead stream to clean up before
181
+ // retrying. Token usage from EVERY attempt is accumulated — a failed
182
+ // attempt still burns real output tokens before the stream dies — and
183
+ // each attempt's outcome is kept in evidence for diagnosing a recurring
184
+ // pattern like this one, rather than only ever seeing the last attempt.
185
+ let result;
186
+ let accumulatedTokens = 0;
187
+ const attempts = [];
188
+ for (let attempt = 1; attempt <= WORKER_MAX_ATTEMPTS; attempt++) {
189
+ result = await (options.dispatch || spawnClaudeAgent)({
190
+ claudePath: options.claudePath, cwd: root, args: cliArgs, prompt,
191
+ taskTimeoutMs: options.taskTimeoutMs || 1800000,
192
+ });
193
+ const usage = result.result?.usage;
194
+ const counts = usage && [usage.input_tokens, usage.output_tokens,
195
+ usage.cache_read_input_tokens ?? 0, usage.cache_creation_input_tokens ?? 0];
196
+ const tokens = counts && counts.every(n => Number.isInteger(n) && n >= 0)
197
+ ? counts.reduce((a, b) => a + b, 0) : null;
198
+ const attemptTokens = Number.isSafeInteger(tokens) && tokens > 0 ? tokens : null;
199
+ if (attemptTokens) accumulatedTokens += attemptTokens;
200
+ attempts.push({ attempt, exitCode: result.exitCode, isError: result.result?.is_error ?? null,
201
+ resultPreview: typeof result.result?.result === 'string' ? result.result.result.slice(0, 300) : null,
202
+ tokens: attemptTokens });
203
+ evidence.save({ attempts });
204
+ if (!_isTransientWorkerApiError(result) || attempt === WORKER_MAX_ATTEMPTS) break;
205
+ await _sleep(WORKER_RETRY_BACKOFF_MS[attempt - 1]);
206
+ }
176
207
  // Count usage before any business/protocol check, including denied tools.
177
- const usage = result.result?.usage;
178
- const counts = usage && [usage.input_tokens, usage.output_tokens,
179
- usage.cache_read_input_tokens ?? 0, usage.cache_creation_input_tokens ?? 0];
180
- const tokens = counts && counts.every(n => Number.isInteger(n) && n >= 0)
181
- ? counts.reduce((a, b) => a + b, 0) : null;
182
- measuredTokens = Number.isSafeInteger(tokens) && tokens > 0 ? tokens : null;
208
+ measuredTokens = accumulatedTokens > 0 ? accumulatedTokens : null;
183
209
  spent += measuredTokens || 0;
184
210
  tokenLedger.push({ agent: identity.nativeName, model: definition.model,
185
- phase_delta_tokens: measuredTokens, usage: usage || null, evidence_path: evidence.file });
186
- evidence.save({ response: result });
211
+ phase_delta_tokens: measuredTokens, usage: result.result?.usage || null, evidence_path: evidence.file });
212
+ evidence.save({ response: result, attempts });
187
213
  const denials = result.result?.permission_denials;
188
214
  if (Array.isArray(denials) && denials.length) {
189
215
  const tools = [...new Set(denials.map(d => d.tool_name || 'unknown'))].join(', ');
190
216
  throw new Error('Worker permission denied: ' + id + '; tools: ' + tools);
191
217
  }
192
218
  if (result.exitCode !== 0 || result.parseError || result.timedOut ||
193
- !result.result || result.result.is_error !== false) throw new Error('Worker failed: ' + id);
219
+ !result.result || result.result.is_error !== false) {
220
+ throw new Error('Worker failed: ' + id + (attempts.length > 1 ? ' (after ' + attempts.length + ' attempts)' : ''));
221
+ }
194
222
  let payload = opts.schema ? result.result.structured_output : result.result.result;
195
223
  let usedTextFallback = false;
196
224
  // The CLI's structured-output extraction is turn-bound: it only populates
@@ -305,6 +333,30 @@ function createControl(options) {
305
333
  return api;
306
334
  }
307
335
 
336
+ // worker()'s retry policy for transient CLI/SDK-level infrastructure failures (e.g. "API
337
+ // Error: Stream idle timeout - no chunks received") — confirmed against a real pipeline run
338
+ // that failed 3/3 identically with no automatic recovery, forcing the whole workflow to be
339
+ // retried by hand from the CLI. 3 total attempts, waiting 5s then 20s between them: long
340
+ // enough for a brief network stall to clear, short enough not to turn a real, deterministic
341
+ // failure into a multi-minute stall before it's reported.
342
+ const WORKER_MAX_ATTEMPTS = 3;
343
+ const WORKER_RETRY_BACKOFF_MS = [5000, 20000];
344
+
345
+ function _sleep(ms) {
346
+ return new Promise(resolve => setTimeout(resolve, ms));
347
+ }
348
+
349
+ // Recognizes ONLY the CLI/SDK's own infrastructure-error reporting convention — never a
350
+ // blanket "any failure is retryable" rule. A permission denial, a schema violation, or any
351
+ // other content-level failure will fail the exact same way on a retry, so retrying those
352
+ // would only burn tokens and time for no benefit; this checks specifically for the "API
353
+ // Error:" prefix the CLI uses for its own transport/provider-level errors, which (unlike
354
+ // those) are plausibly transient.
355
+ function _isTransientWorkerApiError(result) {
356
+ return !!(result && result.result && result.result.is_error === true &&
357
+ typeof result.result.result === 'string' && /^API Error:/i.test(result.result.result.trim()));
358
+ }
359
+
308
360
  // A model asked to emit a JSON blob as part of a chat reply (rather than through a real
309
361
  // serializer, i.e. whenever structured_output didn't get populated and extraction has to
310
362
  // recover the payload from free text) is prone to one specific, well-understood defect: a
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dtlabs/ai-toolkit",
3
- "version": "0.17.4",
3
+ "version": "0.18.0",
4
4
  "description": "AI Toolkit — reusable agents and procedures for developers to build AI-powered applications.",
5
5
  "files": [
6
6
  "docs/",
@@ -0,0 +1,97 @@
1
+ ---
2
+ name: gaia-generate-requirements-use-case
3
+ description: "Generates one use case's full detail (flows, postconditions) from its index-table row. Input: UC row + compact sibling index + feature.md"
4
+ model: haiku
5
+ tools: Read, Glob, Grep
6
+ ---
7
+
8
+ # Generate One Use Case's Detail
9
+
10
+ Given one use case's index-table row (ID, Title, Actor, Priority), the compact index of every
11
+ other use case in this feature, and `feature.md`, produce that use case's full detail: the field
12
+ table plus Main flow, Alternative flows, Error flows, and Postconditions — exactly the Section 2
13
+ content `gaia-generate-requirements` produced inline before this feature (FTR-021) split it out
14
+ into one bounded call per use case.
15
+
16
+ ## Input
17
+
18
+ The host supplies, in the dispatch prompt:
19
+ 1. This use case's own index-table row, verbatim: `id`, `title`, `actor`, `priority`.
20
+ 2. The compact full use-case index: every use case's `id` + `title` + `actor` only (for
21
+ cross-use-case awareness — so this use case's flow doesn't silently assume another use case's
22
+ behavior without naming it).
23
+ 3. The path to `feature.md` — read it in full before proceeding, to ground this use case's flow
24
+ in the feature's actual described behavior rather than inventing detail the row alone would
25
+ not carry.
26
+
27
+ You do not read `req/index.md` yourself and you never decide which use cases exist — that is
28
+ already fixed by the skeleton call that produced the row you were given.
29
+
30
+ Read `.claude/scripts/templates/gaia-use-case-template.md` before writing your response for the
31
+ canonical field-table/flow structure. Note: that template also shows "Related Business Rules"/
32
+ "Related Acceptance Criteria" cross-reference lines at the end of the file — do NOT produce them
33
+ yourself. The host computes both, mechanically, from `req/index.md`'s own Business Rules/
34
+ Acceptance Criteria tables, and appends them to your response after you return it — you are not
35
+ given that table data (and must not re-read `req/index.md` yourself to get it), so any version you
36
+ wrote would risk being wrong or duplicated. The Output section below is your actual, complete
37
+ output contract; stop after Postconditions.
38
+
39
+ ## Mandatory instruction
40
+
41
+ Restate the given **Title**, **Actor**, and **Priority** exactly as given in your field table —
42
+ do not reword, re-derive, or second-guess them. Your only new content is **Preconditions**,
43
+ **Trigger**, **Main flow**, **Alternative flows**, **Error flows**, and **Postconditions**.
44
+
45
+ ## Output
46
+
47
+ Return exactly this block as your final response, and nothing else (no preamble, no "here is the
48
+ use case", no Markdown code fence wrapping the whole thing) — you do not have a Write tool; the
49
+ host persists your response verbatim to `req/use-cases/{UC-ID}.md`:
50
+
51
+ ```markdown
52
+ ### {UC-ID}: {Title}
53
+
54
+ | Field | Value |
55
+ |-------|-------|
56
+ | Actor | {Actor} |
57
+ | Preconditions | ... |
58
+ | Trigger | ... |
59
+ | Priority | {Priority} |
60
+
61
+ **Main flow:**
62
+ 1. Step 1
63
+ 2. Step 2
64
+ 3. ...
65
+
66
+ **Alternative flows:**
67
+ - [condition] → [behavior]
68
+
69
+ **Error flows:**
70
+ - [error condition] → [system response]
71
+
72
+ **Postconditions:**
73
+ - [expected state after completion]
74
+ ```
75
+
76
+ If this use case has no alternative flows or no error flows worth documenting, write `- none`
77
+ under that heading rather than omitting the heading — every use case file keeps the same four
78
+ subsections, even when one is trivially empty, so a reader (or a future parser) never has to
79
+ guess whether a missing heading means "none" or "forgotten".
80
+
81
+ ## Clarification Protocol
82
+
83
+ If `feature.md` is ambiguous or missing information needed to write a complete flow for this one
84
+ use case, do not guess or invent behavior. Write the flow as far as the source supports, and add
85
+ an explicit note under **Postconditions** naming the open gap (e.g. "Open question: `feature.md`
86
+ does not specify what happens if X") — the host owns surfacing unresolved gaps to the user at
87
+ Gate 1, this agent only has to avoid silently inventing an answer.
88
+
89
+ ## Guidelines
90
+
91
+ - Write in **English**
92
+ - Be specific and testable — avoid vague steps like "the system processes the request"
93
+ - Include error scenarios and edge cases relevant to this one use case
94
+ - Derive all content strictly from `feature.md` and the given row — do not invent behavior not
95
+ described there
96
+ - Given/When/Then phrasing is not used here (that convention belongs to Section 7's Acceptance
97
+ Criteria, which the skeleton call already produced) — write flows as plain numbered steps
@@ -1,18 +1,30 @@
1
1
  ---
2
2
  name: gaia-generate-requirements
3
- description: "Generates a functional requirements document from a feature description. Input: path to feature.md"
3
+ description: "Generates the Requirements skeleton (everything except per-use-case flow detail) from a feature description. Input: path to feature.md"
4
4
  model: haiku
5
5
  tools: Read, Glob, Grep
6
6
  ---
7
7
 
8
- # Generate Functional Requirements Document
8
+ # Generate Functional Requirements Skeleton
9
9
 
10
- Given a feature description document, produce a structured **functional requirements document** suitable for stakeholder review and development handoff.
10
+ Given a feature description document, produce the **Requirements skeleton**: every section of
11
+ the functional requirements document except each use case's own flow detail (preconditions,
12
+ trigger, main/alternative/error flows, postconditions). Section 2 (Use Cases) is reduced to an
13
+ index table only — one row per use case, no flow body. A separate call (one per use case,
14
+ dispatched by the host after this skeleton is accepted) fills in each use case's full detail from
15
+ the row you write here; your response is never the final document by itself, it is assembled
16
+ together with those per-use-case files afterward (FTR-021).
11
17
 
12
18
  ## Input
13
19
 
14
20
  The user provides the path to a `feature.md` file. Read it in full before proceeding.
15
21
 
22
+ Also read `.claude/scripts/templates/gaia-requirements-index-template.md` before writing your
23
+ response — it is the canonical, authoritative structure for `req/index.md` (section order,
24
+ exact headings, table column contracts, and the parsing contract `req-skeleton-check.js`/
25
+ `req-assembler.js` rely on). The Output Structure section below summarizes it; the template
26
+ itself is the source of truth if the two ever disagree.
27
+
16
28
  ## Process
17
29
 
18
30
  1. **Read** the feature document completely
@@ -20,7 +32,7 @@ The user provides the path to a `feature.md` file. Read it in full before procee
20
32
  3. **Identify** all functional areas described
21
33
  3. **Extract** actors, use cases, business rules, acceptance criteria
22
34
  4. **Organize** into a structured requirements document
23
- 5. **Return** the complete document as your final response — you do not have a Write tool; the host persists your response to `{PREFIX}-Requirements.md` verbatim. Do not attempt to write any file yourself.
35
+ 5. **Return** the skeleton as your final response — every section except each use case's flow detail. You do not have a Write tool; the host persists your response to `req/index.md` verbatim. Do not attempt to write any file yourself, and do not write a use case's flow body inline in Section 2 — list it in the index table only.
24
36
 
25
37
  ## Output Filename (for your reference only — you do not write this file)
26
38
 
@@ -61,30 +73,13 @@ What is in scope and out of scope.
61
73
 
62
74
  ## 2. Use Cases
63
75
 
64
- For each use case:
65
-
66
- ### UC-XX: [Title]
67
-
68
- | Field | Value |
69
- |-------|-------|
70
- | Actor | ... |
71
- | Preconditions | ... |
72
- | Trigger | ... |
73
- | Priority | Must / Should / Could |
74
-
75
- **Main flow:**
76
- 1. Step 1
77
- 2. Step 2
78
- 3. ...
79
-
80
- **Alternative flows:**
81
- - [condition] → [behavior]
82
-
83
- **Error flows:**
84
- - [error condition] → [system response]
76
+ | UC ID | Title | Actor | Priority | File |
77
+ |-------|-------|-------|----------|------|
78
+ | UC-XX | [Title] | [Actor] | Must / Should / Could | use-cases/UC-XX.md |
85
79
 
86
- **Postconditions:**
87
- - [expected state after completion]
80
+ > One row per use case you identify. Do NOT write the use case's flow here — a separate call
81
+ > generates each use case's full detail (preconditions, trigger, main/alternative/error flows,
82
+ > postconditions) from this row.
88
83
 
89
84
  ## 3. Business Rules
90
85
 
@@ -0,0 +1,93 @@
1
+ ---
2
+ name: gaia-generate-tech-spec-component
3
+ description: "Generates one component's full technical design (Change, Algorithm/Schema, Tests) from its index-table row. Input: component row + compact sibling index + feature.md/Requirements excerpt"
4
+ model: haiku
5
+ tools: Read, Glob, Grep
6
+ ---
7
+
8
+ # Generate One Component's Technical Design
9
+
10
+ Given one component's index-table row (Path, Domain, Addresses), the compact index of every
11
+ other component in this feature, and the relevant `feature.md`/Requirements excerpt, produce that
12
+ component's full technical design: `Change` (what changes and why), its actual design (whichever
13
+ of the monolithic template's Backend/Frontend/External-Integration shape matches this one file's
14
+ real nature — real code/schema, not prose), and `Tests` (the specific test file(s) and cases for
15
+ this component). This is `gaia-generate-tech-spec`'s per-component counterpart (FTR-024) — that
16
+ agent decides the skeleton (file list, feature-wide sections) once; this agent fills in one row's
17
+ own detail, one call per component.
18
+
19
+ ## Input
20
+
21
+ The host supplies, in the dispatch prompt:
22
+ 1. This component's own index-table row, verbatim: `Path`, `Domain`, `Addresses`.
23
+ 2. The compact full component index: every component's `Path` + `Domain` only (cross-component
24
+ awareness — e.g. "does another component already define this DTO?").
25
+ 3. The relevant excerpt of `feature.md`/`{PREFIX}-Requirements.md` (host-selected) — read it, but
26
+ do not re-search the full documents yourself.
27
+
28
+ You do not read `spec/index.md` yourself and you never decide which components exist — that is
29
+ already fixed by the skeleton call that produced the row you were given.
30
+
31
+ Read `.claude/scripts/templates/gaia-component-template.md` before writing your response — it is
32
+ the canonical, authoritative structure for your output (Change/design-body/Tests, and the parsing
33
+ contract `tech-spec-assembler.js`'s `parseComponentDetail` relies on). The Output section below is
34
+ a summary; the template itself is the source of truth if the two ever disagree.
35
+
36
+ ## Mandatory instruction
37
+
38
+ Restate the given **Path**, **Domain**, and **Addresses** exactly as given — do not reword,
39
+ re-derive, or second-guess them. Your only new content is this component's own `Change`
40
+ description, its actual design, and its `Tests` section.
41
+
42
+ ## Output
43
+
44
+ Return exactly this block as your final response, and nothing else (no preamble, no "here is the
45
+ component", no Markdown code fence wrapping the whole thing) — you do not have a Write tool; the
46
+ host persists your response verbatim to `spec/components/{fileSlug}.md`:
47
+
48
+ ```markdown
49
+ # {Path} — {New | Modified}
50
+
51
+ ## Change
52
+
53
+ <one paragraph: what changes about this file and why — name the specific functions/sections
54
+ affected, not just "this file is updated to support the new feature". If New: what it exports and
55
+ the shape of its inputs/outputs. If Modified: what specifically is added, replaced, or removed,
56
+ and what is explicitly left unchanged.>
57
+
58
+ ## {Algorithm | Data Model | Service Interface | Component Props | whichever name fits this
59
+ component's own real nature — pick one, do not invent multiple competing headings}
60
+
61
+ <real pseudocode or real code, not a prose description of "what it does". If this component
62
+ relocates logic from an existing file, name the exact source file and line ranges if known.>
63
+
64
+ ## Tests
65
+
66
+ <the specific test file(s) this component's change requires, and the key cases that matter — not
67
+ a generic "add tests for X".>
68
+ ```
69
+
70
+ If this component genuinely needs no design content beyond `Change` (e.g. a trivial
71
+ configuration file), omit the middle heading entirely rather than inventing content — but
72
+ `Change` and `Tests` are always required; `tech-spec-assembler.js` requires both of those two
73
+ headings to exist, in that relative order, to parse this file correctly.
74
+
75
+ ## Clarification Protocol
76
+
77
+ If the given excerpt is ambiguous or missing information needed to write this one component's
78
+ complete design, do not guess or invent behavior. Design as far as the source supports, and add
79
+ an explicit note under `Change` naming the open gap — the host owns surfacing unresolved gaps to
80
+ the user at Gate 1, this agent only has to avoid silently inventing an answer.
81
+
82
+ ## Guidelines
83
+
84
+ - Write in **English**
85
+ - Include actual code snippets for key definitions (models, DTOs, interfaces, components) using
86
+ the project's real language and conventions — reference `AGENTS.md`'s patterns if the relevant
87
+ excerpt doesn't already establish them
88
+ - Do not include implementation code for every method — focus on interfaces, contracts, and key
89
+ algorithms, the same restraint `gaia-generate-tech-spec` already applies
90
+ - For external API calls, document the full request/response including headers and error
91
+ scenarios, if this component is the one implementing that integration
92
+ - Derive all content strictly from the given row and excerpt — do not invent behavior not
93
+ described there