@dzhechkov/skills-feature-adr 1.3.32 → 1.3.36
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dzhechkov/skills-feature-adr",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.36",
|
|
4
4
|
"description": "Adaptive Feature Development skill pack for Claude Code — 11-step pipeline with Complexity Router (S/M/L/XL), ADR-driven architecture, 15 agentic-qe skills, multi-agent fleet QE. Supports --full-qe, --full-qe-extended, --with-learning, and --knowledge-extractor modes.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"skills-feature-adr": "./bin/cli.js"
|
package/src/commands/update.js
CHANGED
|
@@ -36,11 +36,20 @@ async function run(options) {
|
|
|
36
36
|
const templatesDir = getTemplatesDir();
|
|
37
37
|
|
|
38
38
|
// ── b) Get installed components ───────────────────────────────────────
|
|
39
|
-
const
|
|
40
|
-
if (
|
|
39
|
+
const manifestKeys = manifest.components || [];
|
|
40
|
+
if (manifestKeys.length === 0) {
|
|
41
41
|
warn('Manifest lists no installed components. Consider running init instead.');
|
|
42
42
|
process.exit(1);
|
|
43
43
|
}
|
|
44
|
+
// UNION the manifest's components with the CORE components the NEW template provides. A component
|
|
45
|
+
// ADDED upstream AFTER this install (e.g. `workflows`, bundled in a later release) would otherwise be
|
|
46
|
+
// invisible to `update` — never installed, and worse, a file it ships (`.claude/workflows/feature-adr.js`)
|
|
47
|
+
// could be mis-flagged as an orphan "dropped from template" and DELETED. Installing the union fixes
|
|
48
|
+
// both: new core components get added, and every file the current template provides stays in the
|
|
49
|
+
// rebuilt file-set, so it is updated (never orphaned). Optional components are only touched if they
|
|
50
|
+
// were already installed (they stay driven by the manifest).
|
|
51
|
+
const newCoreKeys = Object.keys(COMPONENTS).filter((k) => fileExists(path.join(templatesDir, COMPONENTS[k].src)));
|
|
52
|
+
const installedKeys = [...new Set([...manifestKeys, ...newCoreKeys])];
|
|
44
53
|
|
|
45
54
|
info(`Current version: ${dim(manifest.version)}`);
|
|
46
55
|
const pkgPath = path.resolve(__dirname, '../../package.json');
|
|
@@ -274,24 +283,25 @@ async function run(options) {
|
|
|
274
283
|
}
|
|
275
284
|
|
|
276
285
|
if (totalAdded === 0 && totalModified === 0 && orphans.length === 0) {
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
286
|
+
// Nothing to copy, but the MANIFEST may still be stale: a component newly covered by the union
|
|
287
|
+
// (or a file the template ships that the old manifest never tracked) must be re-tracked so the
|
|
288
|
+
// manifest matches reality \u2014 otherwise a later `remove`/`update` mis-reasons about ownership. Also
|
|
289
|
+
// refreshes the per-file baseline so a legacy (no-hashes) install self-heals into the 3-way regime.
|
|
290
|
+
// Never bump the version (no template bytes applied) and never write under --dry-run.
|
|
291
|
+
if (!dryRun) {
|
|
292
|
+
const { allFiles, newHashes } = rebuildManifestData();
|
|
293
|
+
const prevFiles = JSON.stringify((manifest.files || []).map(toManifestPath).sort());
|
|
294
|
+
const nextFiles = JSON.stringify(allFiles.slice().sort());
|
|
295
|
+
const compsChanged = JSON.stringify((manifest.components || []).slice().sort()) !== JSON.stringify(installedKeys.slice().sort());
|
|
296
|
+
if (prevFiles !== nextFiles || compsChanged || Object.keys(newHashes).length > 0) {
|
|
297
|
+
manifest.files = allFiles.sort();
|
|
298
|
+
manifest.components = installedKeys;
|
|
299
|
+
if (Object.keys(newHashes).length > 0) manifest.hashes = newHashes;
|
|
300
|
+
manifest.updatedAt = new Date().toISOString();
|
|
301
|
+
writeManifest(targetDir, manifest);
|
|
290
302
|
}
|
|
291
|
-
success('No files to update \u2014 locally modified file(s) kept.');
|
|
292
|
-
} else {
|
|
293
|
-
success('Everything is up to date!');
|
|
294
303
|
}
|
|
304
|
+
success(keptModified.length > 0 ? 'No files to update \u2014 locally modified file(s) kept.' : 'Everything is up to date!');
|
|
295
305
|
process.exit(0);
|
|
296
306
|
}
|
|
297
307
|
|
|
@@ -60,6 +60,12 @@ Without this, the Code agent returns null and the run stalls. With `coder: 'code
|
|
|
60
60
|
detects the null, logs *"Claude unavailable (limit?) — falling back to Codex auto"*, and finishes
|
|
61
61
|
the code + tests on Codex — no restart, no lost work.
|
|
62
62
|
|
|
63
|
+
**Codex-landed barrier (Step 7.5):** Codex applies edits OUT-OF-BAND via its own runtime, so a naive
|
|
64
|
+
pipeline runs Step-8 QE before the async write flushes and false-grades *"Step 7 never ran"* (grade D on
|
|
65
|
+
real, landed code — observed on the goap-ed25519 fix). When Codex was the coder, feature-adr now polls
|
|
66
|
+
`git status` (excluding pipeline artifacts) up to ~30s until the code changes appear and hands the
|
|
67
|
+
confirmed file list to QE. Claude-coded runs are synchronous, so the barrier is skipped (zero cost).
|
|
68
|
+
|
|
63
69
|
**Example invocations:**
|
|
64
70
|
```js
|
|
65
71
|
// Plan on Codex, code+QE fall back to Codex only if Claude runs out, auto:
|
|
@@ -366,7 +366,7 @@ to Codex — always ASKING first, always with a Claude fallback (never blocks):
|
|
|
366
366
|
- **Model choice** → `args.codexModel` (`auto` default (Codex self-selects) · or an id your account exposes (e.g. `gpt-5.5`)).
|
|
367
367
|
|
|
368
368
|
*Scenario:* an L/XL run hits the session limit during coding → with `coder: 'codex-fallback'` feature-adr
|
|
369
|
-
logs *"Claude unavailable (limit?) — falling back to Codex auto"* and finishes on Codex, no restart.
|
|
369
|
+
logs *"Claude unavailable (limit?) — falling back to Codex auto"* and finishes on Codex, no restart. Codex writes out-of-band, so feature-adr confirms the edits LANDED (`git status`, ~30s poll) before QE — no false "Step 7 never ran" grade.
|
|
370
370
|
|
|
371
371
|
*Example:* `Workflow({ scriptPath: '.claude/workflows/feature-adr.js', args: { slug, description, tier:
|
|
372
372
|
'M', planner: 'codex', coder: 'codex-fallback', qeReviewer: 'codex-fallback', codexModel: 'auto' } }) // 'auto' = Codex picks top; or pin e.g. 'gpt-5.5'`.
|
|
@@ -113,9 +113,21 @@ if (code === null && (CODER === 'codex' || CODER === 'codex-fallback')) {
|
|
|
113
113
|
if (codexCode) { code = { wrote: [FDIR + '/07_code_changes/change_manifest.md'], summary: String(codexCode).slice(0, 500) }; coderUsed = CODER === 'codex' ? 'codex' : 'codex-fallback' }
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
+
// Step 7.5: Codex-landed barrier. Codex applies edits OUT-OF-BAND via its own runtime; without this,
|
|
117
|
+
// Step-8 QE reads the tree before the async write flushes and false-grades "Step 7 never ran" (grade D
|
|
118
|
+
// on real, landed code — observed on the goap-ed25519 crypto fix). Poll git status (excluding pipeline
|
|
119
|
+
// artifacts) up to ~30s until real code changes appear, and hand the confirmed file list to QE so it
|
|
120
|
+
// reviews the ACTUAL landed changes. Claude-coded runs are synchronous → this barrier is skipped.
|
|
121
|
+
let landedNote = ''
|
|
122
|
+
if (coderUsed === 'codex' || coderUsed === 'codex-fallback') {
|
|
123
|
+
const barrierCmd = 'for i in 1 2 3 4 5 6; do n=$(git -C ' + REPO + ' status --porcelain 2>/dev/null | grep -vE "features/|[.]dz/|[.]agentic-qe/|roam/" | wc -l); [ "$n" -gt 0 ] && break; sleep 5; done; echo "changed=$n"; git -C ' + REPO + ' status --porcelain 2>/dev/null | grep -vE "features/|[.]dz/|[.]agentic-qe/|roam/" | head -40'
|
|
124
|
+
const probe = await agent('Confirm the Codex Step-7 edits have LANDED in the working tree BEFORE QE runs (Codex writes out-of-band). Run EXACTLY this via Bash and return its stdout verbatim, nothing else:\n' + barrierCmd, { label: 'code:confirm-landed', phase: 'Code' })
|
|
125
|
+
landedNote = '\n\nCODEX-CODED (out-of-band): review the CONFIRMED landed working-tree changes below — do NOT report "Step 7 never ran" if files are listed. If changed=0 the implementation genuinely did not land, then grade accordingly.\n' + String(probe || '(landed-probe failed)').slice(0, 1500)
|
|
126
|
+
}
|
|
127
|
+
|
|
116
128
|
// Step 8: QE (brutal-honesty, agentic-qe) + MANDATORY teach
|
|
117
129
|
phase('QE')
|
|
118
|
-
const qePrompt = 'Step 8 (QE - brutal-honesty review, agentic-qe) of /feature-adr for "' + DESC + '" (' + SLUG + '). Adversarially review the SHIPPED code (read it): correctness, edge cases, error handling, and the LOAD-BEARING property the ADR named (ASSERT it has a test - the recurring lesson). Grade A/B/C/D honestly. Assess code-test adequacy + doc-test presence. List CONFIRMED gaps with severity. Write ' + FDIR + '/08_qe_report.md. MANDATORY SELF-LEARNING STORE (close the loop, never skip): via Bash run `dz teach "<a durable reusable lesson from this feature - a rule/pattern/pitfall, NOT a checkpoint echo>" --reward <0.7-0.95> --domain <area>` for each genuine lesson (1-3 max, high-signal), then run `' + DZ + ' statusline --fa-record --slug ' + SLUG + ' --step "Step 8 QE" --recalled 3 --stored <count taught> --mode ' + MODE + ' --project ' + REPO + '` (run it verbatim via Bash, do not skip). Do NOT teach trivia or invent gaps. Return {grade, gaps, codeTestsAdequate, docTestsPresent}.'
|
|
130
|
+
const qePrompt = 'Step 8 (QE - brutal-honesty review, agentic-qe) of /feature-adr for "' + DESC + '" (' + SLUG + '). Adversarially review the SHIPPED code (read it): correctness, edge cases, error handling, and the LOAD-BEARING property the ADR named (ASSERT it has a test - the recurring lesson). Grade A/B/C/D honestly. Assess code-test adequacy + doc-test presence. List CONFIRMED gaps with severity. Write ' + FDIR + '/08_qe_report.md. MANDATORY SELF-LEARNING STORE (close the loop, never skip): via Bash run `dz teach "<a durable reusable lesson from this feature - a rule/pattern/pitfall, NOT a checkpoint echo>" --reward <0.7-0.95> --domain <area>` for each genuine lesson (1-3 max, high-signal), then run `' + DZ + ' statusline --fa-record --slug ' + SLUG + ' --step "Step 8 QE" --recalled 3 --stored <count taught> --mode ' + MODE + ' --project ' + REPO + '` (run it verbatim via Bash, do not skip). Do NOT teach trivia or invent gaps. Return {grade, gaps, codeTestsAdequate, docTestsPresent}.' + landedNote
|
|
119
131
|
let qe = null
|
|
120
132
|
let qeReviewerUsed = 'claude'
|
|
121
133
|
if (QE_REVIEWER !== 'codex') {
|