@dtlabs/ai-toolkit 0.16.0 → 0.16.2

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/CHANGELOG.md CHANGED
@@ -1,4 +1,20 @@
1
1
  ## 0.1.4 (2026-07-21)
2
+ ## [0.16.2](https://github.com/dtlab-tech/ai-toolkit/compare/v0.16.1...v0.16.2) (2026-10-02)
3
+
4
+
5
+ ### Bug Fixes
6
+
7
+ * **gaia-generate-work-breakdown:** forbid citing an AC outside its owning phase ([525e2ce](https://github.com/dtlab-tech/ai-toolkit/commit/525e2cef928dafb8b80470b572d214b85aecb1dc))
8
+ * **gaia-generate-work-breakdown:** forbid citing an AC outside its owning phase ([5376d67](https://github.com/dtlab-tech/ai-toolkit/commit/5376d67a67140d5b46e507f2092e389d362ce723))
9
+
10
+ ## [0.16.1](https://github.com/dtlab-tech/ai-toolkit/compare/v0.16.0...v0.16.1) (2026-10-02)
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * **wb-validate:** require groupingRationale only when outputCount > 1 ([e3cb71a](https://github.com/dtlab-tech/ai-toolkit/commit/e3cb71a7f38fbd974c70f3dbdd99223a6aa05048))
16
+ * **wb-validate:** require groupingRationale only when outputCount > 1 ([7406fbe](https://github.com/dtlab-tech/ai-toolkit/commit/7406fbe336304c2ebcd012fc6a6b1b4980121a64))
17
+
2
18
  ## [0.16.0](https://github.com/dtlab-tech/ai-toolkit/compare/v0.15.1...v0.16.0) (2026-10-02)
3
19
 
4
20
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dtlabs/ai-toolkit",
3
- "version": "0.16.0",
3
+ "version": "0.16.2",
4
4
  "description": "AI Toolkit — reusable agents and procedures for developers to build AI-powered applications.",
5
5
  "files": [
6
6
  "docs/",
@@ -128,7 +128,7 @@ Decomposition strategy by domain:
128
128
  | `domain` | string | One of: `BE`, `FE`, `DB`, `DevOps`, `INFRA`, `TEST` |
129
129
  | `agentType` | string | One of: `developer-backend`, `developer-frontend`, `developer-testing`, `review-solution` (deprecated: `developer-database` — maps to `developer-backend`) |
130
130
  | `dependsOn` | array of strings | Task IDs this task depends on; may be empty `[]`; all IDs must be defined within this same JSON |
131
- | `acceptanceCriteria` | array of strings | AC IDs from Requirements that this task covers; may be empty `[]` |
131
+ | `acceptanceCriteria` | array of strings | AC IDs from Requirements scoped to this task's own phase that this task covers; may be empty `[]`. Never an AC owned by a different phase (see Guidelines) |
132
132
  | `verification` | object | `{ "commands": ["..."] }` — one or more shell commands that verify the task output; array must be non-empty |
133
133
  | `estimate` | object | `{ "agentMinutes": N, "tokens": N }` — target ≤ 15 minutes; positive integers |
134
134
  | `outputCount` | integer | Number of distinct outputs; must be ≥ 1 |
@@ -339,7 +339,7 @@ Do NOT guess or invent task decompositions when the source is unclear. Ask first
339
339
  - **Cross-phase dependencies are expected** — US tasks may depend on INFRA tasks; cross-US task dependencies are also valid
340
340
  - **INFRA phase first** (if present), then US phases in priority order (Must before Should before Could)
341
341
  - **Within a phase, order tasks by layer dependency** (DB → BE → FE → TEST); independent tasks within the same layer may be listed in any order
342
- - **acceptanceCriteria** must list AC IDs from the Requirements that this task covers; leave empty `[]` if the task covers no AC directly (e.g., pure infrastructure setup)
342
+ - **acceptanceCriteria** must list only AC IDs whose Requirements AC-table scope ("Related UC") matches this task's own phase, or that are marked cross-cutting ("All UCs"/multiple UCs including this phase's). **Never cite an AC owned by a different phase on this task, even when this task is prerequisite or contributing work for it** — an INFRA task that lays groundwork for an AC verified in a later US does not "cover" that AC; leave `acceptanceCriteria` empty `[]` on that task instead (e.g., pure infrastructure setup, or groundwork for an AC owned elsewhere). If an AC is genuinely cross-cutting, reflect that in the AC's own "Related UC" column, not by citing it from an unrelated task.
343
343
  - **schemaVersion must be exactly 2** — do not omit it, do not use any other value
344
344
  - **No pipes, CR, or LF** in `phase.title`, `task.title`, or `commit.subject` — these characters break CSV generation
345
- - **Traceability**: every UC must map to a US phase; every Must-priority AC must be covered by at least one task's `acceptanceCriteria`
345
+ - **Traceability**: every UC must map to a US phase; every Must-priority AC must be covered by at least one task's `acceptanceCriteria` **within that AC's own owning US phase** (per its "Related UC" scope) — not by a task in an earlier or later phase, even one that contributes toward satisfying it eventually
@@ -359,7 +359,7 @@ for (const phase of phases) {
359
359
 
360
360
  const topLevelFields = [
361
361
  'id', 'title', 'outcome', 'domain', 'agentType', 'dependsOn',
362
- 'acceptanceCriteria', 'outputCount', 'groupingRationale', 'commit',
362
+ 'acceptanceCriteria', 'outputCount', 'commit',
363
363
  ]
364
364
  for (const field of topLevelFields) {
365
365
  if (task[field] == null) {
@@ -374,6 +374,20 @@ for (const phase of phases) {
374
374
  }
375
375
  }
376
376
 
377
+ // groupingRationale is required only when outputCount > 1 (the generator agent's own
378
+ // contract: a single-output task has nothing to justify grouping, so it emits null) —
379
+ // null is the documented, correct value there, not a missing field.
380
+ if (task.outputCount > 1 && task.groupingRationale == null) {
381
+ report.errors.push({
382
+ category: ERRORS.MISSING_FIELD,
383
+ severity: 'error',
384
+ taskId,
385
+ field: 'groupingRationale',
386
+ message: `Task "${taskId}" has outputCount > 1 but is missing required field "groupingRationale"`,
387
+ details: { taskId, field: 'groupingRationale' },
388
+ })
389
+ }
390
+
377
391
  // Nested: verification.commands — existence and array type only; emptiness checked later
378
392
  if (task.verification == null || task.verification.commands == null) {
379
393
  report.errors.push({