@dtlabs/ai-toolkit 0.24.7 → 0.24.9
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,22 @@
|
|
|
1
1
|
## 0.1.4 (2026-07-21)
|
|
2
|
+
## [0.24.9](https://github.com/dtlab-tech/ai-toolkit/compare/v0.24.8...v0.24.9) (2026-11-03)
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
### Bug Fixes
|
|
6
|
+
|
|
7
|
+
* **pm-phase1:** never overwrite a good skeleton with a non-document reply, and repair last-cycle AC traceability once ([8f2f32f](https://github.com/dtlab-tech/ai-toolkit/commit/8f2f32f1852ade4551da62cbac8bc07d8f0c2961))
|
|
8
|
+
* **pm-phase1:** never overwrite a good skeleton with a non-document reply, and repair last-cycle AC traceability once ([3038efe](https://github.com/dtlab-tech/ai-toolkit/commit/3038efed641464b93da50377cd834cc1d4a85e48))
|
|
9
|
+
* **pm-phase1:** never overwrite a good skeleton with a non-document reply, and repair last-cycle AC traceability once ([784f814](https://github.com/dtlab-tech/ai-toolkit/commit/784f8141fb4afdefe2b2592f9d8b57a4f41207c2))
|
|
10
|
+
|
|
11
|
+
## [0.24.8](https://github.com/dtlab-tech/ai-toolkit/compare/v0.24.7...v0.24.8) (2026-11-02)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
### Bug Fixes
|
|
15
|
+
|
|
16
|
+
* **pm-phase1:** hand gaps still open after three validation cycles to Gate 1 instead of failing the run ([a57e05a](https://github.com/dtlab-tech/ai-toolkit/commit/a57e05abf61ea3c42a36a92cd190cc3d3a57a39c))
|
|
17
|
+
* **pm-phase1:** hand gaps still open after three validation cycles to Gate 1 instead of failing the run ([d759efa](https://github.com/dtlab-tech/ai-toolkit/commit/d759efa9e13d464740698d3b8e01f131e91c848a))
|
|
18
|
+
* **pm-phase1:** hand gaps still open after three validation cycles to Gate 1 instead of failing the run ([976aa27](https://github.com/dtlab-tech/ai-toolkit/commit/976aa2724b8e1e2e91293d88bc0581a5fef01f01))
|
|
19
|
+
|
|
2
20
|
## [0.24.7](https://github.com/dtlab-tech/ai-toolkit/compare/v0.24.6...v0.24.7) (2026-10-30)
|
|
3
21
|
|
|
4
22
|
|
package/package.json
CHANGED
|
@@ -71,6 +71,9 @@ Extract from the result:
|
|
|
71
71
|
- `tech_spec.path` / `tech_spec.summary` — Tech-Spec artifact path (the split `spec/index.md` by
|
|
72
72
|
default) and its summary
|
|
73
73
|
- `validation.summary` — validation result (gaps or clean)
|
|
74
|
+
- `validation.open_gaps` — array of the validator's findings still open after the last revision
|
|
75
|
+
cycle; empty when validation was clean. Non-empty means the workflow stopped revising and left
|
|
76
|
+
these for the Gate 1 reviewer to accept, reject or send back
|
|
74
77
|
- `docs_digest` — content digest binding this approval to the exact Requirements/Tech-Spec
|
|
75
78
|
bytes just produced; embed verbatim into `{PREFIX}-Approvals.md` in Step 2 below
|
|
76
79
|
- `token_ledger` — array of per-agent token data from phase 1
|
|
@@ -92,6 +95,11 @@ Documents generated for {PREFIX}:
|
|
|
92
95
|
{tech_spec.path} — {tech_spec.summary}
|
|
93
96
|
{PREFIX}-Validation-Report.md — {validation.summary}
|
|
94
97
|
|
|
98
|
+
If `validation.open_gaps` is non-empty, also list every entry verbatim under a heading
|
|
99
|
+
"Open validation gaps — your decision at this gate", then continue. These are design points the
|
|
100
|
+
validator could not close in three cycles. "Approve with notes" records the ones you accept in
|
|
101
|
+
`{PREFIX}-Approvals.md`; "Request changes" sends them back.
|
|
102
|
+
|
|
95
103
|
To view a single combined document instead of the split source files, run:
|
|
96
104
|
/assemble-docs {PREFIX} [req|spec|all]
|
|
97
105
|
```
|
|
@@ -39,6 +39,32 @@ return c.run(meta.name, featureDir, prefix, async () => {
|
|
|
39
39
|
// per-UC and per-component generation loops' own fail-fast validity check.
|
|
40
40
|
const USE_CASE_RETRY_ATTEMPTS = 2
|
|
41
41
|
const COMPONENT_RETRY_ATTEMPTS = 2
|
|
42
|
+
const SKELETON_RETRY_ATTEMPTS = 2
|
|
43
|
+
|
|
44
|
+
// A skeleton worker occasionally answers with a question or an apology instead of the document
|
|
45
|
+
// ("I have not generated the skeleton yet ... I'm asking here"). The skeleton was written
|
|
46
|
+
// straight onto req/index.md or spec/index.md and only checked afterwards, so one such reply
|
|
47
|
+
// destroyed the good document that was there (FTR-034, revision cycle 2). The reply is now
|
|
48
|
+
// checked for every numbered section BEFORE the target file is touched; on a bad reply the
|
|
49
|
+
// worker is asked once more, and if that fails too the run stops with the existing file intact.
|
|
50
|
+
async function writeSkeleton(label, workerId, basePrompt, sectionCount, outPath, transform) {
|
|
51
|
+
let raw
|
|
52
|
+
for (let attempt = 1; attempt <= SKELETON_RETRY_ATTEMPTS; attempt++) {
|
|
53
|
+
const prompt = attempt === 1 ? basePrompt : basePrompt +
|
|
54
|
+
'\n\nYour previous reply was not the document. This is a non-interactive run: nobody can answer a question. ' +
|
|
55
|
+
'Reply with ONLY the complete document, every numbered section included, and with no preamble. Where feature.md ' +
|
|
56
|
+
'leaves a point undecided, record it inside the document as an open question instead of asking.'
|
|
57
|
+
raw = await c.worker(workerId, prompt, attempt === 1 ? undefined : { label: `${label}:skeleton:retry:${attempt}` })
|
|
58
|
+
if (missingSections(raw, sectionCount).length === 0) {
|
|
59
|
+
c.writeOutput(outPath, transform ? transform(raw) : raw)
|
|
60
|
+
return
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// same message the post-write completeness check has always produced (truncation guard)
|
|
64
|
+
try { assertCompleteSections(label, raw, sectionCount) } catch (e) {
|
|
65
|
+
throw new Error(`${e.message}; after ${SKELETON_RETRY_ATTEMPTS} attempts the existing file was left untouched`)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
42
68
|
|
|
43
69
|
// Templates live under the toolkit's own installed scripts/templates/ — outside this project
|
|
44
70
|
// for a globally-installed toolkit, which a non-interactive `--print` worker invocation has no
|
|
@@ -215,8 +241,9 @@ return c.run(meta.name, featureDir, prefix, async () => {
|
|
|
215
241
|
// 1. Skeleton (no declared worker() output — host writes it itself, mirroring FTR-020's
|
|
216
242
|
// skeleton step)
|
|
217
243
|
if (regenSkeleton) {
|
|
218
|
-
|
|
219
|
-
|
|
244
|
+
await writeSkeleton('Requirements', reqId,
|
|
245
|
+
withTemplate(featurePath, 'req/index.md', 'gaia-requirements-index-template.md') + revisionSection(revisionFindings),
|
|
246
|
+
9, reqIndexPath)
|
|
220
247
|
}
|
|
221
248
|
|
|
222
249
|
// 2. Structural self-consistency pre-check (req-skeleton-check.js, same
|
|
@@ -565,8 +592,9 @@ return c.run(meta.name, featureDir, prefix, async () => {
|
|
|
565
592
|
|
|
566
593
|
// 1. Skeleton (no declared worker() output — host writes it itself)
|
|
567
594
|
if (regenSkeleton) {
|
|
568
|
-
|
|
569
|
-
|
|
595
|
+
await writeSkeleton('Tech-Spec', specId,
|
|
596
|
+
withTemplate(featurePath, 'spec/index.md', 'gaia-tech-spec-index-template.md') + revisionSection(revisionFindings),
|
|
597
|
+
12, specIndexPath, skeleton => applyComponentSlugs(skeleton, manifest))
|
|
570
598
|
}
|
|
571
599
|
|
|
572
600
|
// 2. Structural pre-check (tech-spec-graph-checks.js, unmodified — FTR-023 — now pointed at
|
|
@@ -677,6 +705,8 @@ return c.run(meta.name, featureDir, prefix, async () => {
|
|
|
677
705
|
let assembledRequirements = assembleRequirements()
|
|
678
706
|
let assembledTechSpec = assembleTechSpec()
|
|
679
707
|
let validationSummary = 'skipped (fresh)'
|
|
708
|
+
// Gaps still open after the last revision cycle, handed to Gate 1 for a human decision.
|
|
709
|
+
let openGaps = []
|
|
680
710
|
if (force || changed || !fresh(file('Validation-Report'), [featurePath, reqIndexPath, specIndexPath])) {
|
|
681
711
|
for (let cycle = 1; cycle <= 3; cycle++) {
|
|
682
712
|
// needsRequirementsFix/needsTechSpecFix: explicit structured routing fields,
|
|
@@ -766,7 +796,32 @@ return c.run(meta.name, featureDir, prefix, async () => {
|
|
|
766
796
|
validationSummary = `0 gaps (clean on cycle ${cycle})`
|
|
767
797
|
break
|
|
768
798
|
}
|
|
769
|
-
if (cycle === 3)
|
|
799
|
+
if (cycle === 3) {
|
|
800
|
+
// The deterministic AC<->component traceability gaps stay a hard failure if the repair
|
|
801
|
+
// below cannot close them: they are mechanical and the Work Breakdown relies on that
|
|
802
|
+
// mapping. What the validator judges
|
|
803
|
+
// (open design points, drill-down findings) is for a person to accept or reject, and Gate
|
|
804
|
+
// 1 is that review: regenerating again cannot decide a point feature.md leaves undecided
|
|
805
|
+
// (on FTR-034 three full runs of three cycles each never converged for that reason).
|
|
806
|
+
//
|
|
807
|
+
// A traceability gap found on the LAST cycle used to be unrecoverable: a Requirements
|
|
808
|
+
// revision on cycle 2 can add acceptance criteria the Tech-Spec does not yet address, and
|
|
809
|
+
// that gap is only routed to a Tech-Spec revision on the cycle after. Give it one repair:
|
|
810
|
+
// regenerate the Tech-Spec once with the gaps as feedback, then re-check mechanically.
|
|
811
|
+
let repaired = false
|
|
812
|
+
if (structuralFindings.length) {
|
|
813
|
+
revisionFindings = structuralFindings
|
|
814
|
+
await generateTechSpec(true)
|
|
815
|
+
assembledTechSpec = assembleTechSpec()
|
|
816
|
+
if (computeAcComponentTraceabilityGaps(c.read(reqIndexPath), c.read(specIndexPath)).length) throw new Error('Validation gaps remain after 3 cycles')
|
|
817
|
+
repaired = true
|
|
818
|
+
c.append(file('Validation-Report'), '\n\n## Post-validation repair\nThe AC traceability findings listed above were repaired after the last validation cycle by regenerating the Tech-Spec once. The repaired Tech-Spec was checked mechanically (every AC is addressed) but was not re-validated by the validator.\n')
|
|
819
|
+
}
|
|
820
|
+
openGaps = mergedFindings.filter(f => !structuralFindings.includes(f))
|
|
821
|
+
validationSummary = `${openGaps.length} open gap(s) after 3 cycles, left for Gate 1 review (see the Validation Report)` +
|
|
822
|
+
(repaired ? '; the Tech-Spec was regenerated once to repair AC traceability and not re-validated' : '')
|
|
823
|
+
break
|
|
824
|
+
}
|
|
770
825
|
if (!mergedNeedsRequirementsFix && !mergedNeedsTechSpecFix) throw new Error(`Validation agent reported gaps on cycle ${cycle} but flagged neither document for revision`)
|
|
771
826
|
revisionFindings = mergedFindings
|
|
772
827
|
if (mergedNeedsRequirementsFix) { await generateRequirements(true); assembledRequirements = assembleRequirements() }
|
|
@@ -784,7 +839,7 @@ return c.run(meta.name, featureDir, prefix, async () => {
|
|
|
784
839
|
prefix, feature_dir: featureDir, feature_path: featurePath,
|
|
785
840
|
requirements: { path: reqIndexPath, summary: 'Requirements ready (split; req/index.md + req/use-cases/*.md)' },
|
|
786
841
|
tech_spec: { path: specIndexPath, summary: 'Tech-Spec ready (split; spec/index.md + spec/components/*.md)' },
|
|
787
|
-
validation: { path: file('Validation-Report'), summary: validationSummary },
|
|
842
|
+
validation: { path: file('Validation-Report'), summary: validationSummary, open_gaps: openGaps },
|
|
788
843
|
docs_digest: docsDigest,
|
|
789
844
|
token_ledger: c.tokenLedger, errors: [],
|
|
790
845
|
}
|