@dzhechkov/skills-feature-adr 1.3.52 → 1.3.53
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.53",
|
|
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"
|
|
@@ -570,6 +570,36 @@ const isMplus = tier === 'M' || tier === 'L' || tier === 'XL'
|
|
|
570
570
|
const isLplus = tier === 'L' || tier === 'XL'
|
|
571
571
|
log('Router: tier ' + tier)
|
|
572
572
|
|
|
573
|
+
// ── AUTO-COST pre-resolution (feature learned-cost-routing) ──
|
|
574
|
+
// A stage whose spec is 'auto-cost' is resolved HERE (tier is now known) to a concrete model via
|
|
575
|
+
// `dz routing --select` — the workflow is sandboxed (no fs), so selection I/O shells out to dz. Byte-identical
|
|
576
|
+
// no-op (ZERO agent calls) when no stage is 'auto-cost'. Order matters: resolve `code` FIRST so `qe` can be
|
|
577
|
+
// forced to the CROSS-family of the coder (the named cross-model-QE guard). Escalate-on-fail across runs is
|
|
578
|
+
// automatic: a gate-FAIL recorded below down-ranks the model so the NEXT run's select picks the next rung.
|
|
579
|
+
const AUTOCOST = {}
|
|
580
|
+
function acFamOf(spec) { return /codex|gpt|openai/i.test(String(spec)) ? 'openai' : 'claude' }
|
|
581
|
+
function acConcrete(model) { return CLAUDE_NAMES[model] ? model : ('codex:' + model + ':high') }
|
|
582
|
+
function acBareId(spec) { var s = String(spec || ''); return s.indexOf('codex:') === 0 ? (s.split(':')[1] || s) : s }
|
|
583
|
+
async function resolveAutoCost(stage, familyArg) {
|
|
584
|
+
const famFlag = familyArg ? (' --family ' + familyArg) : ''
|
|
585
|
+
const out = await agent('Run EXACTLY this via Bash and reply with ONLY its stdout (a single JSON line), nothing else: ' + DZ + ' routing --select --stage ' + stage + ' --tier ' + tier + famFlag, { label: 'auto-cost:select:' + stage, phase: 'Route', effort: 'low' })
|
|
586
|
+
let pick = null
|
|
587
|
+
try { pick = JSON.parse(String(out).replace(/^[^{]*/, '').replace(/[^}]*$/, '')) } catch { pick = null }
|
|
588
|
+
if (!pick || !pick.model) { log('auto-cost ' + stage + ': no candidate model — leaving session-inherited'); MODELS[stage] = undefined; return }
|
|
589
|
+
MODELS[stage] = acConcrete(pick.model)
|
|
590
|
+
AUTOCOST[stage] = { chain: (pick.chain || []), tier: tier, evidence: pick.evidence || '' }
|
|
591
|
+
log('auto-cost ' + stage + ' → ' + MODELS[stage] + ' [' + (pick.metBar ? 'learned' : 'cold-start') + ']')
|
|
592
|
+
}
|
|
593
|
+
const autoCostStages = Object.keys(MODELS).filter(function (s) { return MODELS[s] === 'auto-cost' })
|
|
594
|
+
if (autoCostStages.length > 0) {
|
|
595
|
+
for (const s of autoCostStages) { if (s !== 'qe') await resolveAutoCost(s, null) }
|
|
596
|
+
if (MODELS.qe === 'auto-cost') {
|
|
597
|
+
// cross-family of the resolved coder (guard): coder codex → qe claude; coder claude → qe openai.
|
|
598
|
+
const coderSpec = (MODELS.code !== undefined && MODELS.code !== null && MODELS.code !== 'auto-cost') ? MODELS.code : ((CODER === 'codex' || CODER === 'codex-fallback') ? 'codex' : 'opus')
|
|
599
|
+
await resolveAutoCost('qe', acFamOf(coderSpec) === 'openai' ? 'claude' : 'openai')
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
|
|
573
603
|
// GUARANTEED fa-panel write (the router, being low-effort + multi-job, tends to skip the fa-record
|
|
574
604
|
// Bash call). A dedicated single-command agent reliably lights up the live /feature-adr panel at the
|
|
575
605
|
// most visible moment. Uses the workspace bin (PATH-independent). Best-effort — never blocks.
|
|
@@ -845,6 +875,55 @@ if (qe === null && qeIsCodex) {
|
|
|
845
875
|
const claimGate = step8ClaimGate(qe && qe.claimCheck ? qe.claimCheck : null)
|
|
846
876
|
log(claimGate.note)
|
|
847
877
|
|
|
878
|
+
// ── AUTO-COST outcome recording (feature learned-cost-routing) ──
|
|
879
|
+
// The two-phase label lands here: every auto-cost stage that produced an artifact records a PROVISIONAL (i);
|
|
880
|
+
// the CODE stage's authoritative gate (ii) is the Step-8 QE grade (A/B = pass) — a produced-but-gate-FAILED
|
|
881
|
+
// run is recorded as a FAILURE, down-ranking that model for the next run (ADR §2). Byte-identical no-op when
|
|
882
|
+
// nothing was auto-cost. Gate-less stages get weak provisional credit; richer per-stage gates are Phase-2.
|
|
883
|
+
if (Object.keys(AUTOCOST).length > 0) {
|
|
884
|
+
const recPhase = isLplus ? 'FleetQE' : 'QE'
|
|
885
|
+
// Record ONLY stages that ACTUALLY RAN and produced an artifact (QE finding: a blanket loop over configured
|
|
886
|
+
// auto-cost stages credited skipped/failed/fallback stages). `code`/`plan` are guarded by their result var.
|
|
887
|
+
// ATTRIBUTION guard (QE #2): the auto-cost pick's outcome must be attributed to the PICK's model — but a
|
|
888
|
+
// codex-FALLBACK produces the code on a DIFFERENT model when the picked model returned null. So:
|
|
889
|
+
// • the picked model ran & produced → provisional + finalize by the QE gate.
|
|
890
|
+
// • a fallback fired (pick returned null) → the PICK FAILED to deliver → finalize(pick, false), NOT the
|
|
891
|
+
// fallback model (which was not auto-cost-selected). This down-ranks the pick honestly.
|
|
892
|
+
const codeMid = acBareId(MODELS.code)
|
|
893
|
+
if (AUTOCOST.code && codeMid) {
|
|
894
|
+
const pickIsCodex = /codex|gpt/i.test(String(MODELS.code))
|
|
895
|
+
const pickRan = pickIsCodex ? (coderUsed === 'codex') : (coderUsed === 'claude')
|
|
896
|
+
if (pickRan && code) {
|
|
897
|
+
const codePassed = !!(qe && /^[AB]$/i.test(String(qe.grade || '').trim()))
|
|
898
|
+
await agent('Run EXACTLY this via Bash and reply with ONLY its stdout: ' + DZ + ' routing --record-provisional --stage code --tier ' + AUTOCOST.code.tier + ' --model ' + codeMid, { label: 'auto-cost:record:code', phase: recPhase, effort: 'low' })
|
|
899
|
+
await agent('Run EXACTLY this via Bash and reply with ONLY its stdout: ' + DZ + ' routing --finalize --stage code --tier ' + AUTOCOST.code.tier + ' --model ' + codeMid + ' --success ' + (codePassed ? 'true' : 'false'), { label: 'auto-cost:finalize:code', phase: recPhase, effort: 'low' })
|
|
900
|
+
} else {
|
|
901
|
+
// the picked model did not deliver (fallback fired or produced nothing) → record it as a failure.
|
|
902
|
+
log('auto-cost code: picked model ' + codeMid + ' did not deliver (coderUsed=' + coderUsed + ') — recording a failure')
|
|
903
|
+
await agent('Run EXACTLY this via Bash and reply with ONLY its stdout: ' + DZ + ' routing --finalize --stage code --tier ' + AUTOCOST.code.tier + ' --model ' + codeMid + ' --success false', { label: 'auto-cost:finalize:code-fail', phase: recPhase, effort: 'low' })
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
// PLAN: provisional only (its gate is landing, already enforced upstream); guarded by the plan result var.
|
|
907
|
+
const planMid = acBareId(MODELS.plan)
|
|
908
|
+
if (AUTOCOST.plan && plan && planMid) {
|
|
909
|
+
await agent('Run EXACTLY this via Bash and reply with ONLY its stdout: ' + DZ + ' routing --record-provisional --stage plan --tier ' + AUTOCOST.plan.tier + ' --model ' + planMid, { label: 'auto-cost:record:plan', phase: recPhase, effort: 'low' })
|
|
910
|
+
}
|
|
911
|
+
// QE: gate (ii) = produced a PARSEABLE verdict with a grade (qe non-null). A qe that named no grade fell back
|
|
912
|
+
// and is not the auto-cost pick, so record only when the picked reviewer actually delivered a verdict. Its
|
|
913
|
+
// model ran iff qeReviewerUsed matches the pick's family (else a belt/fallback reviewer ran).
|
|
914
|
+
const qeMid = acBareId(MODELS.qe)
|
|
915
|
+
if (AUTOCOST.qe && qeMid) {
|
|
916
|
+
const qePickIsCodex = /codex|gpt/i.test(String(MODELS.qe))
|
|
917
|
+
const qePickRan = qePickIsCodex ? (qeReviewerUsed === 'codex') : (qeReviewerUsed === 'claude')
|
|
918
|
+
if (qePickRan && qe && String(qe.grade || '').trim() !== '') {
|
|
919
|
+
await agent('Run EXACTLY this via Bash and reply with ONLY its stdout: ' + DZ + ' routing --record-provisional --stage qe --tier ' + AUTOCOST.qe.tier + ' --model ' + qeMid, { label: 'auto-cost:record:qe', phase: recPhase, effort: 'low' })
|
|
920
|
+
await agent('Run EXACTLY this via Bash and reply with ONLY its stdout: ' + DZ + ' routing --finalize --stage qe --tier ' + AUTOCOST.qe.tier + ' --model ' + qeMid + ' --success true', { label: 'auto-cost:finalize:qe', phase: recPhase, effort: 'low' })
|
|
921
|
+
} else {
|
|
922
|
+
await agent('Run EXACTLY this via Bash and reply with ONLY its stdout: ' + DZ + ' routing --finalize --stage qe --tier ' + AUTOCOST.qe.tier + ' --model ' + qeMid + ' --success false', { label: 'auto-cost:finalize:qe-fail', phase: recPhase, effort: 'low' })
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
|
|
848
927
|
// Step 9: Fleet QE (L/XL)
|
|
849
928
|
let fleet = 'skipped (S/M)'
|
|
850
929
|
if (isLplus) {
|
|
@@ -889,5 +968,6 @@ return {
|
|
|
889
968
|
brain: BRAIN,
|
|
890
969
|
polymorphism: POLY.hasManifest ? POLY.report : null,
|
|
891
970
|
claimGate: claimGate,
|
|
971
|
+
autoCost: Object.keys(AUTOCOST).length ? AUTOCOST : null,
|
|
892
972
|
promiseTags: tags,
|
|
893
973
|
}
|