@dzhechkov/skills-feature-adr 1.3.38 → 1.3.40
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.40",
|
|
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"
|
|
@@ -414,6 +414,30 @@ Codex on limit-exhaustion) stays a knob-only behavior; a direct `models.code='co
|
|
|
414
414
|
'L', models: { code: 'opus', qe: 'codex:gpt-5.6:high', architecture: 'opus', router: 'fable' } } })` —
|
|
415
415
|
Claude writes the code, Codex independently QEs it.
|
|
416
416
|
|
|
417
|
+
**Usage-adaptive routing (pre-emptive Codex switch under limit pressure).** When routing is opted into,
|
|
418
|
+
the workflow probes Claude SESSION (active 5h-block) and WEEKLY (rolling 7d) usage at EACH phase boundary
|
|
419
|
+
via a minimal `dz usage --json` agent. When either metric is `>= usageThreshold` (default `70`) BEFORE a
|
|
420
|
+
phase launches — OR the probe output is missing (agent-null, which often MEANS the limit was hit) — ALL
|
|
421
|
+
remaining stages switch to `codex:<top>` (design/code/plan at `xhigh`, router/qe/fleet at `high`). When a
|
|
422
|
+
later probe reads BOTH metrics below the threshold (positive numbers, not nulls), the normal Claude+Codex
|
|
423
|
+
mix is RESTORED. Null percentages (unconfigured limits) change NOTHING in either direction. Switched
|
|
424
|
+
stages are tagged ` (usage-switched)` in `modelsUsed`, and every flip is recorded in the result's
|
|
425
|
+
`usageEvents` array (the audit trail — never trust promiseTags for this). Args:
|
|
426
|
+
|
|
427
|
+
| `args.*` | Default | Effect |
|
|
428
|
+
|---|---|---|
|
|
429
|
+
| `usageAdaptive` | `true` when routing is requested (any `args.models` key or Codex knob); `false` otherwise | `true` forces it on even without other routing; `false` disables all probes (byte-identical to today) |
|
|
430
|
+
| `usageThreshold` | `70` | the `>=` percent (either metric) that triggers the pre-emptive switch |
|
|
431
|
+
| `usageReasoning` | the `OVERRIDE_REASONING` map | per-stage reasoning under the override (merge over the default: design/code/plan → `xhigh`, router/qe/fleet → `high`) |
|
|
432
|
+
|
|
433
|
+
Configure the limits the probe measures against in `.dz/config.json` — `memory.usage.sessionTokenLimit`
|
|
434
|
+
and `memory.usage.weeklyTokenLimit` (OPTIONAL; absent ⇒ `pct` is `null` and no switch fires). The
|
|
435
|
+
percentages are **ESTIMATES** from local transcript aggregation (there is no official usage API);
|
|
436
|
+
**calibrate** by scaling a limit by `X/100` when a real limit-hit lands at an estimated `X%`.
|
|
437
|
+
**Honest caveat (the wrapper lesson):** at TRUE exhaustion even the Codex dispatch dies because
|
|
438
|
+
`codex:codex-rescue` is a Claude wrapper subagent — so the switch MUST happen BEFORE, which is why the
|
|
439
|
+
70% pre-emptive probe (not just reactive null-detection) is the real defense.
|
|
440
|
+
|
|
417
441
|
### Pattern memory loop (self-learning — runs in ALL modes)
|
|
418
442
|
|
|
419
443
|
**Self-learning is MANDATORY on EVERY `/feature-adr` run — including plain `/feature-adr` without any
|
|
@@ -67,9 +67,76 @@ const MODELS = (A.models && typeof A.models === 'object') ? A.models : {}
|
|
|
67
67
|
const KNOWN_CODEX = { 'auto': 1, 'gpt-5.5': 1, 'gpt-5.6': 1 }
|
|
68
68
|
const CLAUDE_NAMES = { fable: 1, opus: 1, sonnet: 1, haiku: 1 }
|
|
69
69
|
const DEFAULT_MODELS = { router: 'fable', requirements: 'sonnet', research: 'sonnet', adr: 'opus', ideation: 'sonnet', ddd: 'opus', architecture: 'opus', plan: 'sonnet', code: null, qe: null, fleet: 'sonnet' }
|
|
70
|
-
const routingRequested = (Object.keys(MODELS).length > 0) || (PLANNER === 'codex') || (CODER === 'codex' || CODER === 'codex-fallback') || (QE_REVIEWER === 'codex' || QE_REVIEWER === 'codex-fallback')
|
|
70
|
+
const routingRequested = (Object.keys(MODELS).length > 0) || (PLANNER === 'codex') || (CODER === 'codex' || CODER === 'codex-fallback') || (QE_REVIEWER === 'codex' || QE_REVIEWER === 'codex-fallback') || (A.usageAdaptive === true)
|
|
71
71
|
const modelsUsed = {}
|
|
72
72
|
|
|
73
|
+
// ── USAGE-ADAPTIVE ROUTING (pre-emptive codex switch at >= usageThreshold, default 70%) ──
|
|
74
|
+
// At every phase boundary a minimal haiku probe runs 'dz usage --json'; when SESSION or WEEKLY
|
|
75
|
+
// usage crosses the threshold BEFORE a phase launches, ALL remaining stages switch to
|
|
76
|
+
// codex:<topCodexId> (design/code/plan at xhigh, router/qe/fleet at high). When a later probe reads
|
|
77
|
+
// BOTH metrics below threshold (positive numbers, not nulls) the normal mix is RESTORED. The
|
|
78
|
+
// load-bearing asymmetry: an agent-null probe (dispatch died — often MEANS limits) fail-safe-switches
|
|
79
|
+
// TO codex; a value-null (unconfigured limits) flips NOTHING. All additive behind USAGE_ADAPTIVE:
|
|
80
|
+
// usageAdaptive:false OR no routing requested ⇒ zero probes, byte-identical to today.
|
|
81
|
+
// The single mutable routing bit usageOverride lives HERE (the workflow is its own environment);
|
|
82
|
+
// the pure library mirror (feature-adr-routing.ts) threads it via RoutingEnv — never a global.
|
|
83
|
+
const USAGE_THRESHOLD = Number(A.usageThreshold) > 0 ? Number(A.usageThreshold) : 70
|
|
84
|
+
const USAGE_ADAPTIVE = (A.usageAdaptive !== false) && (routingRequested || A.usageAdaptive === true)
|
|
85
|
+
const OVERRIDE_REASONING = mergeOpts({ router: 'high', requirements: 'xhigh', research: 'xhigh', adr: 'xhigh', ideation: 'xhigh', ddd: 'xhigh', architecture: 'xhigh', plan: 'xhigh', code: 'xhigh', qe: 'high', fleet: 'high' }, (A.usageReasoning && typeof A.usageReasoning === 'object') ? A.usageReasoning : {})
|
|
86
|
+
const usageReasoning = OVERRIDE_REASONING
|
|
87
|
+
let usageOverride = false
|
|
88
|
+
const usageEvents = []
|
|
89
|
+
|
|
90
|
+
// decideUsageAction: the PURE hysteresis core (byte-equivalent to feature-adr-routing.ts). Given the
|
|
91
|
+
// previous override bit, a probe signal (or null when the probe agent DIED), and the threshold,
|
|
92
|
+
// decide the new override bit + the LOCKED 6-value action. Total function.
|
|
93
|
+
function decideUsageAction(prevOverride, signal, threshold) {
|
|
94
|
+
if (signal === null || signal === undefined) {
|
|
95
|
+
if (prevOverride) return { override: true, action: 'keep' }
|
|
96
|
+
return { override: true, action: 'fail-safe-switch' }
|
|
97
|
+
}
|
|
98
|
+
const s = signal.sessionPct
|
|
99
|
+
const w = signal.weeklyPct
|
|
100
|
+
const sKnown = typeof s === 'number' && isFinite(s) && s >= 0
|
|
101
|
+
const wKnown = typeof w === 'number' && isFinite(w) && w >= 0
|
|
102
|
+
if ((sKnown && s >= threshold) || (wKnown && w >= threshold)) {
|
|
103
|
+
return { override: true, action: prevOverride ? 'keep' : 'switch' }
|
|
104
|
+
}
|
|
105
|
+
if (sKnown && wKnown) {
|
|
106
|
+
return { override: false, action: prevOverride ? 'restore' : 'none' }
|
|
107
|
+
}
|
|
108
|
+
return { override: prevOverride, action: prevOverride ? 'keep' : 'none' }
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const PROBE_SCHEMA = { type: 'object', additionalProperties: false, required: ['sessionPct', 'weeklyPct'], properties: { sessionPct: { type: ['number', 'null'] }, weeklyPct: { type: ['number', 'null'] } } }
|
|
112
|
+
|
|
113
|
+
// usageProbe: at each phase boundary, dispatch a minimal haiku/effort-low agent that runs EXACTLY
|
|
114
|
+
// one shell command ('dz usage --json') — the same guaranteed-single-command shape as fa-record:step0.
|
|
115
|
+
// Feed the reading to decideUsageAction, flip usageOverride, record a usageEvents entry. First
|
|
116
|
+
// statement is the BC guard: when USAGE_ADAPTIVE is off, ZERO probe agents are dispatched (AC-4).
|
|
117
|
+
async function usageProbe(phaseName) {
|
|
118
|
+
if (!USAGE_ADAPTIVE) return
|
|
119
|
+
const probePrompt = 'Run EXACTLY this one shell command via your Bash tool and return ONLY its parsed JSON fields sessionPct and weeklyPct (numbers or null), nothing else, do not summarize: ' + DZ + ' usage --json --project ' + REPO
|
|
120
|
+
const r = await agent(probePrompt, { label: 'usage:probe', phase: phaseName, model: 'haiku', effort: 'low', schema: PROBE_SCHEMA })
|
|
121
|
+
const d = decideUsageAction(usageOverride, r, USAGE_THRESHOLD)
|
|
122
|
+
if (d.action === 'switch') log('usage: session ' + (r ? r.sessionPct : null) + '% / week ' + (r ? r.weeklyPct : null) + '% >= ' + USAGE_THRESHOLD + '% — switching remaining stages to codex:' + topCodexId())
|
|
123
|
+
if (d.action === 'fail-safe-switch') log('usage: probe died (agent-null — often MEANS limits) — fail-safe switching remaining stages to codex:' + topCodexId())
|
|
124
|
+
if (d.action === 'restore') log('usage: back to ' + (r ? r.sessionPct : null) + '%/' + (r ? r.weeklyPct : null) + '% — restoring normal routing')
|
|
125
|
+
usageOverride = d.override
|
|
126
|
+
usageEvents.push({ phase: phaseName, sessionPct: r ? r.sessionPct : null, weeklyPct: r ? r.weeklyPct : null, action: d.action })
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// reactiveBelt: generalizes today's codex-fallback. When a stage agent returns null while NOT already
|
|
130
|
+
// overridden (a possible limit event), flip the override so the REMAINING stages don't walk into the
|
|
131
|
+
// same wall. The legacy codex-fallback same-stage retry is untouched. Best-effort: at TRUE exhaustion
|
|
132
|
+
// even codex dispatch dies (codex:codex-rescue is a Claude wrapper) — the 70% pre-emptive probe is the real defense.
|
|
133
|
+
function reactiveBelt(phaseName) {
|
|
134
|
+
if (!USAGE_ADAPTIVE || usageOverride) return
|
|
135
|
+
usageOverride = true
|
|
136
|
+
usageEvents.push({ phase: phaseName, sessionPct: null, weeklyPct: null, action: 'reactive-switch' })
|
|
137
|
+
log('usage: stage agent returned null while not overridden — possible limit event, switching remaining stages to codex:' + topCodexId())
|
|
138
|
+
}
|
|
139
|
+
|
|
73
140
|
function specToOpts(spec) {
|
|
74
141
|
if (!spec) return {}
|
|
75
142
|
const parts = String(spec).split(':')
|
|
@@ -96,16 +163,20 @@ function coderIsCodex() {
|
|
|
96
163
|
return false
|
|
97
164
|
}
|
|
98
165
|
|
|
99
|
-
function
|
|
100
|
-
if (coderIsCodex()) return 'opus'
|
|
101
|
-
const CODEX_AVAILABLE = A.codexAvailable !== false
|
|
102
|
-
if (!CODEX_AVAILABLE) return 'opus'
|
|
166
|
+
function topCodexId() {
|
|
103
167
|
let top = CODEX_MODEL
|
|
104
168
|
if (top === 'auto') {
|
|
105
169
|
const ids = Object.keys(KNOWN_CODEX)
|
|
106
170
|
for (let i = 0; i < ids.length; i++) { if (ids[i] !== 'auto') top = ids[i] || top }
|
|
107
171
|
}
|
|
108
|
-
return
|
|
172
|
+
return top
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function resolveQeSpec() {
|
|
176
|
+
if (coderIsCodex()) return 'opus'
|
|
177
|
+
const CODEX_AVAILABLE = A.codexAvailable !== false
|
|
178
|
+
if (!CODEX_AVAILABLE) return 'opus'
|
|
179
|
+
return 'codex:' + topCodexId() + ':high'
|
|
109
180
|
}
|
|
110
181
|
|
|
111
182
|
// qeShouldUseCodex: the load-bearing cross-model gate — the model that wrote the code must NEVER self-QE.
|
|
@@ -121,6 +192,12 @@ function qeShouldUseCodex() {
|
|
|
121
192
|
}
|
|
122
193
|
|
|
123
194
|
function resolveStageModel(stage) {
|
|
195
|
+
if (usageOverride) {
|
|
196
|
+
const r = (usageReasoning && usageReasoning[stage]) || OVERRIDE_REASONING[stage] || 'high'
|
|
197
|
+
const o = specToOpts('codex:' + topCodexId() + ':' + r)
|
|
198
|
+
o._usageSwitched = true
|
|
199
|
+
return o
|
|
200
|
+
}
|
|
124
201
|
let spec = MODELS[stage]
|
|
125
202
|
if (spec === undefined) {
|
|
126
203
|
if (!routingRequested) return {}
|
|
@@ -140,7 +217,11 @@ function mergeOpts(base, extra) {
|
|
|
140
217
|
|
|
141
218
|
// modelLabel: record the resolved spec for a stage in modelsUsed (for the run report / who-did-what).
|
|
142
219
|
function modelLabel(opts) {
|
|
143
|
-
if (opts && opts.agentType === 'codex:codex-rescue')
|
|
220
|
+
if (opts && opts.agentType === 'codex:codex-rescue') {
|
|
221
|
+
const base = 'codex:' + opts.codexModel + ':' + opts._reasoning
|
|
222
|
+
if (opts._usageSwitched) return base + ' (usage-switched)'
|
|
223
|
+
return base
|
|
224
|
+
}
|
|
144
225
|
if (opts && opts.model) return opts.model
|
|
145
226
|
return 'session'
|
|
146
227
|
}
|
|
@@ -151,7 +232,8 @@ const QE = { type: 'object', additionalProperties: false, required: ['grade', 'g
|
|
|
151
232
|
|
|
152
233
|
// Step 0: Router + MANDATORY self-learning recall
|
|
153
234
|
phase('Router')
|
|
154
|
-
|
|
235
|
+
await usageProbe('Router')
|
|
236
|
+
const routerPrompt = 'You are Step 0 (Complexity Router) of the /feature-adr pipeline. TWO jobs. (1) MANDATORY SELF-LEARNING RECALL (never skip — run BOTH Bash commands VERBATIM, do not summarize instead of running them): the learned patterns live in the CANONICAL BRAIN store at `' + BRAIN + '` — pin every recall to it. Via your Bash tool run EXACTLY `' + DZ_RECALL('<the key domain terms of this feature>') + '` (and `' + DZ_RECALL('<the key domain terms of this feature>') + ' --all` if narrow) to load relevant LEARNED PATTERNS from the brain. Preserve recalled pattern TEXT, reward, domain, and any visible id in the rationale as a concrete list so Step 8 can compare candidate lessons against it. Then run `dz statusline --fa-record --slug ' + SLUG + ' --step "Step 0 recall" --recalled <count> --mode ' + MODE + ' --project ' + REPO + '`. Summarize the top 3 applicable patterns in the rationale. (2) Classify S/M/L/XL + active steps. Feature: "' + DESC + '". Code: ' + CODE_HINT + '. S=1-3 files (0,1,6,7,8); M=4-10 (0,1,3,3.5,5,6,7,8); L=11-30 (all+9); XL=30+ (full+9). Return {tier, activeSteps, rationale} with the recalled patterns folded into rationale.'
|
|
155
237
|
const routerOpts = mergeOpts({ label: 'router+recall', phase: 'Router', schema: ROUTER, effort: 'low' }, resolveStageModel('router'))
|
|
156
238
|
modelsUsed.router = modelLabel(routerOpts)
|
|
157
239
|
const router = await agent(routerPrompt, routerOpts)
|
|
@@ -168,6 +250,7 @@ await agent('Run EXACTLY this one shell command via your Bash tool and report it
|
|
|
168
250
|
|
|
169
251
|
// Steps 1-5: Design (tier-gated thunks built explicitly - no inline ternary-null)
|
|
170
252
|
phase('Design')
|
|
253
|
+
await usageProbe('Design')
|
|
171
254
|
const designThunks = []
|
|
172
255
|
const reqExtra = isLplus ? ' Also write ' + FDIR + '/02_research.md (codebase patterns + external analogues; read the repo for the closest existing implementation to mirror).' : ''
|
|
173
256
|
// Resolve per-stage model opts up-front (parser-safe: no inline resolveStageModel inside the thunk arrays).
|
|
@@ -196,6 +279,7 @@ const design = await parallel(designThunks)
|
|
|
196
279
|
// the codex:codex-rescue runtime and GRACEFULLY FALL BACK to the default (Claude) planner if Codex is
|
|
197
280
|
// unavailable/errors — the pipeline never blocks on Codex.
|
|
198
281
|
phase('Plan')
|
|
282
|
+
await usageProbe('Plan')
|
|
199
283
|
const planPrompt = 'Step 6 (SPARC-GOAP implementation plan) of /feature-adr for "' + DESC + '" (' + SLUG + ', tier ' + tier + '). Given the requirements + ADR + architecture in ' + FDIR + ', decompose into milestones + concrete tasks with success metrics. Write ' + FDIR + '/06_implementation_plan.md. Return wrote[] + summary.'
|
|
200
284
|
// Resolve the plan model. args.models.plan wins; else the planner:'codex' knob (via routingRequested +
|
|
201
285
|
// DEFAULT_MODELS/coder-fold) or the DEFAULT_MODELS.plan ('sonnet') under routing; else {} (BC).
|
|
@@ -213,6 +297,7 @@ if (planIsCodex) {
|
|
|
213
297
|
log('Plan: Codex unavailable — falling back to the default planner')
|
|
214
298
|
}
|
|
215
299
|
}
|
|
300
|
+
if (plan === null && planIsCodex) reactiveBelt('Plan')
|
|
216
301
|
if (plan === null) {
|
|
217
302
|
const claudePlanOpts = mergeOpts({ label: 'plan', phase: 'Plan', schema: ARTIFACT }, planIsCodex ? {} : planModel)
|
|
218
303
|
modelsUsed.plan = planIsCodex ? 'claude-fallback' : modelLabel(claudePlanOpts)
|
|
@@ -230,11 +315,12 @@ if (stopHere) {
|
|
|
230
315
|
const qePlanned = qeShouldUseCodex() ? modelLabel(resolveStageModel('qe')) : modelLabel(mergeOpts({ agentType: 'qe-code-reviewer' }, resolveStageModel('qe')))
|
|
231
316
|
const plannedModels = mergeOpts(modelsUsed, { code: codePlanned + ' (planned)', qe: qePlanned + ' (planned)' })
|
|
232
317
|
if (isLplus) plannedModels.fleet = modelLabel(resolveStageModel('fleet')) + ' (planned)'
|
|
233
|
-
return { tier: tier, phase: 'checkpoint-after-plan', artifactsDir: FDIR, planner: (plan ? plan.planner : null), plan: (plan ? plan.summary : null), modelsUsed: plannedModels, note: 'L/XL checkpoint - review the ADR + plan (+ the planned code/qe/fleet models), then re-invoke with args.stopAfter="none" to implement + QE.' }
|
|
318
|
+
return { tier: tier, phase: 'checkpoint-after-plan', artifactsDir: FDIR, planner: (plan ? plan.planner : null), plan: (plan ? plan.summary : null), modelsUsed: plannedModels, usageEvents: usageEvents, usageThreshold: USAGE_THRESHOLD, note: 'L/XL checkpoint - review the ADR + plan (+ the planned code/qe/fleet models), then re-invoke with args.stopAfter="none" to implement + QE.' }
|
|
234
319
|
}
|
|
235
320
|
|
|
236
321
|
// Step 7: Code (optional Codex fallback on Claude-limit exhaustion)
|
|
237
322
|
phase('Code')
|
|
323
|
+
await usageProbe('Code')
|
|
238
324
|
const codePrompt = 'Step 7 (Code) of /feature-adr for "' + DESC + '" (' + SLUG + '). Implement the feature per the plan + ADR + architecture in ' + FDIR + '. Write the ACTUAL production code + its tests (mirror the closest existing implementation named in research/architecture). Follow repo conventions; build must pass. Write a change manifest ' + FDIR + '/07_code_changes/change_manifest.md listing every file touched. Return wrote[] (incl. real source files) + summary.'
|
|
239
325
|
// Resolve the coder model. args.models.code wins (a direct 'codex' spec = codex-first); else the legacy
|
|
240
326
|
// CODER knob drives it (with its codex-fallback null-guard). resolveStageModel('code') folds both via the
|
|
@@ -249,6 +335,7 @@ if (!codeIsCodexFirst) {
|
|
|
249
335
|
code = await agent(codePrompt, codeClaudeOpts)
|
|
250
336
|
if (code) { coderUsed = 'claude'; modelsUsed.code = modelLabel(codeClaudeOpts) }
|
|
251
337
|
}
|
|
338
|
+
if (code === null && !codeIsCodexFirst) reactiveBelt('Code')
|
|
252
339
|
if (code === null && (codeIsCodexFirst || CODER === 'codex-fallback')) {
|
|
253
340
|
if (CODER === 'codex-fallback' && !codeIsCodexFirst) log('Code: Claude unavailable (limit?) — falling back to Codex ' + CODEX_MODEL)
|
|
254
341
|
const codeCodexOpts = mergeOpts({ label: 'code:codex', phase: 'Code', agentType: 'codex:codex-rescue' }, codeModel.agentType ? codeModel : {})
|
|
@@ -270,7 +357,8 @@ if (coderUsed === 'codex' || coderUsed === 'codex-fallback') {
|
|
|
270
357
|
|
|
271
358
|
// Step 8: QE (brutal-honesty, agentic-qe) + MANDATORY teach
|
|
272
359
|
phase('QE')
|
|
273
|
-
|
|
360
|
+
await usageProbe('QE')
|
|
361
|
+
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): compare every candidate lesson against the Step-0 recalled LEARNED patterns above. Teach ONLY lessons NOT covered by Step-0 recall. On overlap, run `dz teach --reinforce "<recalled pattern id or exact text>" --project ' + BRAIN + '` instead of minting a near-duplicate; if --reinforce is unavailable, skip the duplicate teach and report `reinforced existing pattern <id>` in the QE report. Store every genuinely new lesson in the CANONICAL BRAIN store at `' + BRAIN + '` so it is NOT lost to a target repo you may have cd`d into. Via Bash run EXACTLY `' + DZ_TEACH('<a durable reusable lesson from this feature - a rule/pattern/pitfall, NOT a checkpoint echo>', '<0.7-0.95>', '<area>') + '` for each genuine NEW lesson (1-3 max, high-signal) — the `cd ' + BRAIN + ' &&` prefix + `--project ' + BRAIN + '` pin guarantee the lesson lands in the brain regardless of your CWD. Then run `' + DZ + ' statusline --fa-record --slug ' + SLUG + ' --step "Step 8 QE" --recalled 3 --stored <count taught> --reinforced <count reinforced> --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
|
|
274
362
|
// CROSS-MODEL QE (load-bearing): resolveStageModel('qe') derives the OTHER family than the resolved
|
|
275
363
|
// coder when args.models.qe is unset (coder-codex ⇒ opus; coder-Claude ⇒ codex, or opus if codex absent).
|
|
276
364
|
// An explicit args.models.qe wins. A Claude qe spec is merged onto the qe-code-reviewer base (role
|
|
@@ -288,6 +376,7 @@ if (!qeIsCodex) {
|
|
|
288
376
|
qe = await agent(qePrompt, qeClaudeOpts)
|
|
289
377
|
if (qe) { qeReviewerUsed = 'claude'; modelsUsed.qe = modelLabel(qeClaudeOpts) }
|
|
290
378
|
}
|
|
379
|
+
if (qe === null && !qeIsCodex) reactiveBelt('QE')
|
|
291
380
|
if (qe === null && (qeIsCodex || QE_REVIEWER === 'codex-fallback')) {
|
|
292
381
|
if (QE_REVIEWER === 'codex-fallback' && !qeIsCodex) log('QE: Claude unavailable (limit?) — falling back to Codex ' + CODEX_MODEL)
|
|
293
382
|
const qeCodexOpts = mergeOpts({ label: 'qe:codex', phase: 'QE', agentType: 'codex:codex-rescue' }, qeModel.agentType ? qeModel : {})
|
|
@@ -306,6 +395,7 @@ if (qe === null && qeIsCodex) {
|
|
|
306
395
|
let fleet = 'skipped (S/M)'
|
|
307
396
|
if (isLplus) {
|
|
308
397
|
phase('FleetQE')
|
|
398
|
+
await usageProbe('FleetQE')
|
|
309
399
|
const fleetModel = resolveStageModel('fleet')
|
|
310
400
|
modelsUsed.fleet = modelLabel(mergeOpts({}, fleetModel))
|
|
311
401
|
const fleetTraceOpts = mergeOpts({ label: 'fleet:trace', phase: 'FleetQE', agentType: 'qe-requirements-validator' }, fleetModel)
|
|
@@ -334,6 +424,8 @@ return {
|
|
|
334
424
|
qeReviewerUsed: qeReviewerUsed,
|
|
335
425
|
codexModel: CODEX_MODEL,
|
|
336
426
|
modelsUsed: modelsUsed,
|
|
427
|
+
usageEvents: usageEvents,
|
|
428
|
+
usageThreshold: USAGE_THRESHOLD,
|
|
337
429
|
selfLearning: 'recall@Step0 + teach@Step8 (mandatory)',
|
|
338
430
|
brain: BRAIN,
|
|
339
431
|
promiseTags: tags,
|