devflow-kit 3.5.0 → 3.6.0
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 +98 -0
- package/README.md +4 -4
- package/dist/agents/{diagnose.md → debug.md} +4 -4
- package/dist/agents/{code-fix.md → fix.md} +2 -2
- package/dist/agents/{scrutinize.md → harden.md} +6 -6
- package/dist/agents/{code-edit.md → refactor.md} +3 -3
- package/dist/cli/agents-view/render.js +1 -1
- package/dist/cli/commands/init.js +3 -3
- package/dist/cli/commands/learning.js +12 -12
- package/dist/cli/commands/legacy-hooks.js +1 -1
- package/dist/cli/commands/uninstall.js +111 -5
- package/dist/commands/bug-analysis.md +19 -15
- package/dist/commands/code-review.md +13 -22
- package/dist/commands/debug.md +15 -15
- package/dist/commands/dynamic-build.md +51 -55
- package/dist/commands/dynamic-plan.md +11 -9
- package/dist/commands/dynamic-profile.md +7 -5
- package/dist/commands/dynamic-tickets.md +11 -9
- package/dist/commands/explore.md +13 -13
- package/dist/commands/implement.md +58 -127
- package/dist/commands/plan.md +19 -41
- package/dist/commands/release.md +9 -5
- package/dist/commands/research.md +12 -8
- package/dist/commands/resolve.md +42 -86
- package/dist/commands/self-review.md +42 -42
- package/dist/core/agent-models.js +47 -11
- package/dist/core/{learning-tuning-config.js → curate-tuning-config.js} +14 -14
- package/dist/core/learning-queue-cleanup.js +1 -1
- package/dist/core/migrations.js +63 -44
- package/dist/core/plugins.js +14 -12
- package/dist/core/project-paths.js +3 -3
- package/dist/hud/codex-usage.js +247 -0
- package/dist/hud/components/codex-quota.js +37 -0
- package/dist/hud/components/usage-quota.js +1 -1
- package/dist/hud/config.js +1 -0
- package/dist/hud/index.js +16 -3
- package/dist/hud/render.js +3 -1
- package/dist/learning-off/agents/{diagnose.md → debug.md} +4 -4
- package/dist/learning-off/agents/{code-fix.md → fix.md} +2 -2
- package/dist/learning-off/agents/{scrutinize.md → harden.md} +6 -6
- package/dist/learning-off/agents/{code-edit.md → refactor.md} +3 -3
- package/dist/learning-off/commands/bug-analysis.md +9 -9
- package/dist/learning-off/commands/code-review.md +2 -15
- package/dist/learning-off/commands/debug.md +4 -8
- package/dist/learning-off/commands/dynamic-build.md +45 -51
- package/dist/learning-off/commands/dynamic-plan.md +5 -5
- package/dist/learning-off/commands/dynamic-profile.md +1 -1
- package/dist/learning-off/commands/dynamic-tickets.md +5 -5
- package/dist/learning-off/commands/explore.md +2 -6
- package/dist/learning-off/commands/implement.md +46 -119
- package/dist/learning-off/commands/plan.md +8 -33
- package/dist/learning-off/commands/release.md +4 -2
- package/dist/learning-off/commands/research.md +2 -2
- package/dist/learning-off/commands/resolve.md +31 -79
- package/dist/learning-off/commands/self-review.md +30 -34
- package/dist/skills/git/references/pr/check-merge-readiness.md +2 -0
- package/dist/skills/git/references/pr/update-pr-evidence.md +4 -6
- package/dist/targets/claude-code/installer.js +117 -84
- package/dist/targets/claude-code/tracker-servers.js +1 -1
- package/package.json +1 -1
- package/src/assets/agents/_partials/_code.mds +2 -2
- package/src/assets/agents/code.mds +2 -2
- package/src/assets/agents/{learning.md → curate.md} +4 -4
- package/src/assets/agents/{diagnose.mds → debug.mds} +4 -4
- package/src/assets/agents/evaluate.md +4 -4
- package/src/assets/agents/{code-fix.mds → fix.mds} +5 -5
- package/src/assets/agents/{scrutinize.mds → harden.mds} +6 -6
- package/src/assets/agents/{simplify.md → polish.md} +4 -4
- package/src/assets/agents/{code-edit.mds → refactor.mds} +6 -6
- package/src/assets/agents/test.md +2 -2
- package/src/assets/commands/_partials/_compliance.mds +1 -1
- package/src/assets/commands/_partials/_decisions.mds +26 -6
- package/src/assets/commands/_partials/_engine.mds +15 -15
- package/src/assets/commands/_partials/_evidence_policy.mds +0 -17
- package/src/assets/commands/_partials/_knowledge.mds +14 -9
- package/src/assets/commands/_partials/_preamble.mds +4 -2
- package/src/assets/commands/_partials/_roster.mds +4 -4
- package/src/assets/commands/bug-analysis.mds +7 -7
- package/src/assets/commands/code-review.mds +1 -14
- package/src/assets/commands/debug.mds +2 -2
- package/src/assets/commands/dynamic-build.mds +26 -32
- package/src/assets/commands/implement.mds +45 -102
- package/src/assets/commands/plan.mds +7 -37
- package/src/assets/commands/release.mds +5 -1
- package/src/assets/commands/resolve.mds +28 -76
- package/src/assets/commands/self-review.mds +27 -27
- package/src/assets/mds/git/_pr.mds +6 -6
- package/src/assets/scripts/hooks/assets/orchestrator-charter.md +4 -3
- package/src/assets/scripts/hooks/capture-prompt +1 -1
- package/src/assets/scripts/hooks/capture-question +1 -1
- package/src/assets/scripts/hooks/capture-turn +1 -1
- package/src/assets/scripts/hooks/json-helper.cjs +2 -2
- package/src/assets/scripts/hooks/lib/learning-store.cjs +1 -1
- package/src/assets/scripts/hooks/lib/project-paths.cjs +4 -4
- package/src/assets/scripts/hooks/preamble +1 -1
- package/src/assets/scripts/hooks/session-start-context +58 -45
- package/src/assets/scripts/verify-evidence.cjs +726 -9
- package/src/assets/skills/agent-references/SKILL.md +9 -5
- package/src/assets/skills/agent-references/references/commands/implement-evidence-asks.md +35 -0
- package/src/assets/skills/agent-references/references/commands/implement-revalidate.md +15 -0
- package/src/assets/skills/agent-references/references/synthesize/bug-analysis.md +1 -1
- package/src/assets/skills/apply-decisions/SKILL.md +6 -4
- package/src/assets/skills/docs-framework/SKILL.md +3 -3
- package/src/assets/skills/qa/SKILL.md +1 -1
- package/src/assets/skills/quality-gates/SKILL.md +7 -7
- package/src/assets/skills/quality-gates/references/report-template.md +7 -7
- /package/src/assets/skills/agent-references/references/{learning → curate}/maintain.md +0 -0
|
@@ -195,19 +195,19 @@ The accepted line is the only source of these values: the script alone folds the
|
|
|
195
195
|
|
|
196
196
|
When the settings line says `LEARNING=off`, set `DECISIONS_CONTEXT` to `(none)` and skip this step, locating no ledger and reading no index.
|
|
197
197
|
|
|
198
|
-
The decisions ledger belongs to the repository, not to one checkout:
|
|
198
|
+
The decisions ledger belongs to the repository, not to one checkout: a linked worktree reads the main worktree's copy, a subdirectory session the repository root's. Locate it with ONE git call, run from the start directory — `WORKTREE_PATH` if provided, otherwise cwd (`devflow:worktree-support`):
|
|
199
199
|
|
|
200
200
|
```bash
|
|
201
201
|
git -C "{start}" rev-parse --path-format=absolute --show-toplevel --git-common-dir
|
|
202
202
|
```
|
|
203
203
|
|
|
204
|
-
Line 1 is the checkout's toplevel, line 2 the
|
|
204
|
+
Line 1 is the checkout's toplevel, line 2 the common git directory. A git older than 2.31 echoes `--path-format=absolute` back as a line of its own first. `{ledger}` is the first that applies:
|
|
205
205
|
|
|
206
206
|
1. **The main worktree** — line 2 without its trailing `/.git`, when the output is exactly two lines each beginning with `/`, line 2 ends in `/.git`, and the directory left once it is removed is not your home directory and contains a `.devflow/` directory.
|
|
207
207
|
2. **The toplevel** — line 1, or on an older git the line after the echoed flag.
|
|
208
208
|
3. **The start directory itself** — when the command failed or printed no absolute toplevel (outside a git repository).
|
|
209
209
|
|
|
210
|
-
This is the rule the learning hooks apply
|
|
210
|
+
This is the rule the learning hooks apply, so you read the index the Curate agent writes.
|
|
211
211
|
|
|
212
212
|
**Step 1 — Read the pre-rendered index:**
|
|
213
213
|
|
|
@@ -216,11 +216,15 @@ Attempt to read `{ledger}/.devflow/learning/index.md`.
|
|
|
216
216
|
- If the file exists and contains non-empty content: use that content as `DECISIONS_CONTEXT`.
|
|
217
217
|
- If the file is absent or empty: set `DECISIONS_CONTEXT` to `(none)`.
|
|
218
218
|
|
|
219
|
-
The index is one direct file read, written at render time by `render-decisions.cjs`
|
|
219
|
+
The index is one direct file read, written at render time by `render-decisions.cjs` — no `.cjs` script runs here.
|
|
220
220
|
|
|
221
|
-
**Step 2 —
|
|
221
|
+
**Step 2 — Slice the index, then hand it on:**
|
|
222
222
|
|
|
223
|
-
When `DECISIONS_CONTEXT` is not `(none)`, hand it only to the agents whose contract declares it.
|
|
223
|
+
When `DECISIONS_CONTEXT` is not `(none)`, hand it only to the agents whose contract declares it.
|
|
224
|
+
|
|
225
|
+
Hand each agent that takes `DECISIONS_CONTEXT` a slice, not the whole index: the index lines whose title, scope or area touch the files and task it works on, verbatim, led by `(slice: N of M entries — full index: <absolute index path>)` and closed by the index footer. When unsure, include the line. Siblings over one diff share ONE slice.
|
|
226
|
+
|
|
227
|
+
Those agents follow `devflow:apply-decisions`. A host that uses the index in its own thread says so in its own step.
|
|
224
228
|
|
|
225
229
|
#### Feature Knowledge
|
|
226
230
|
|
|
@@ -246,7 +250,7 @@ If `index.md` exists and contains at least one entry line, use it for relevance
|
|
|
246
250
|
|
|
247
251
|
**Step 2 — Fallback: glob frontmatter (if `index.md` is absent or empty):**
|
|
248
252
|
|
|
249
|
-
Glob `{worktree}/.devflow/features/*/KNOWLEDGE.md`. For each file found, read only its YAML frontmatter block (between the opening and closing `---` delimiters).
|
|
253
|
+
Glob `{worktree}/.devflow/features/*/KNOWLEDGE.md`. For each file found, read only its YAML frontmatter block (between the opening and closing `---` delimiters).
|
|
250
254
|
|
|
251
255
|
**Step 3 — Pick relevant KBs:**
|
|
252
256
|
|
|
@@ -277,7 +281,7 @@ Headings: L5 Rules · L40 Overview · L62 Anti-Patterns · L118 Key Files
|
|
|
277
281
|
|
|
278
282
|
A KB with no Rules section labels its entries `Rules ({section name}):` and gives them no ID. `FEATURE_KNOWLEDGE` is these blocks; `FEATURE_KNOWLEDGE_RULES` is the same blocks without the `Headings:` line. Both come from this one selection, and each spawn names the variable its recipient takes. If no KBs exist, no KBs are relevant, or `.devflow/features/` is absent, set both to `(none)`.
|
|
279
283
|
|
|
280
|
-
**One git call, then direct reads — no `.cjs` script.**
|
|
284
|
+
**One git call, then direct reads — no `.cjs` script.**
|
|
281
285
|
|
|
282
286
|
#### Plan Artifact
|
|
283
287
|
|
|
@@ -306,11 +310,11 @@ Determine which focus analyzers to run using `CHANGED_FILES` (already computed i
|
|
|
306
310
|
**Produces:** ANALYZER_OUTPUTS
|
|
307
311
|
**Requires:** DIFF_RANGE, ANALYSIS_DIR, ACTIVE_FOCUSES, STATIC_FINDINGS, ACCEPTANCE_RULES, PLAN_CONTEXT, DECISIONS_CONTEXT, FEATURE_KNOWLEDGE
|
|
308
312
|
|
|
309
|
-
Spawn ALL active
|
|
313
|
+
Spawn ALL active Debug agents **in a single message** (parallel, NOT background):
|
|
310
314
|
|
|
311
315
|
For each active focus, spawn:
|
|
312
316
|
```
|
|
313
|
-
Agent(subagent_type="
|
|
317
|
+
Agent(subagent_type="Debug", run_in_background=false):
|
|
314
318
|
"Analyze focusing on {focus}.
|
|
315
319
|
FOCUS: {focus}
|
|
316
320
|
DIFF_COMMAND: git diff {DIFF_RANGE}
|
|
@@ -408,10 +412,10 @@ Run `/resolve` to process and fix these findings.
|
|
|
408
412
|
│ └─ Detect active focuses (security + functional always; integration + usability conditional)
|
|
409
413
|
│
|
|
410
414
|
├─ Phase 5: Bug Analysis (PARALLEL)
|
|
411
|
-
│ ├─
|
|
412
|
-
│ ├─
|
|
413
|
-
│ ├─
|
|
414
|
-
│ └─
|
|
415
|
+
│ ├─ Debug agent: security (+ STATIC_FINDINGS)
|
|
416
|
+
│ ├─ Debug agent: functional
|
|
417
|
+
│ ├─ Debug agent: integration (conditional)
|
|
418
|
+
│ └─ Debug agent: usability (conditional)
|
|
415
419
|
│
|
|
416
420
|
├─ Phase 6: Synthesis
|
|
417
421
|
│ └─ Synthesize agent (mode: bug-analysis)
|
|
@@ -448,7 +452,7 @@ Run `/resolve` after `/bug-analysis` to fix identified bugs. `/resolve` automati
|
|
|
448
452
|
2. **Parallel, not background** — Analyzers spawn in one message with `run_in_background=false`
|
|
449
453
|
3. **Static + semantic** — Two complementary tracks, each validates the other
|
|
450
454
|
4. **Incremental by default** — Only analyze new changes unless `--full` specified
|
|
451
|
-
5. **Verify before reporting** —
|
|
455
|
+
5. **Verify before reporting** — Debug agents self-verify every finding
|
|
452
456
|
6. **Honest reporting** — Display risk level and counts directly from synthesis
|
|
453
457
|
|
|
454
458
|
## Phase Completion Checklist
|
|
@@ -288,19 +288,19 @@ The core, database, dependencies, documentation and compliance focuses, and ever
|
|
|
288
288
|
|
|
289
289
|
When the settings line says `LEARNING=off`, set `DECISIONS_CONTEXT` to `(none)` and skip this step, locating no ledger and reading no index.
|
|
290
290
|
|
|
291
|
-
The decisions ledger belongs to the repository, not to one checkout:
|
|
291
|
+
The decisions ledger belongs to the repository, not to one checkout: a linked worktree reads the main worktree's copy, a subdirectory session the repository root's. Locate it with ONE git call, run from the start directory — `WORKTREE_PATH` if provided, otherwise cwd (`devflow:worktree-support`):
|
|
292
292
|
|
|
293
293
|
```bash
|
|
294
294
|
git -C "{start}" rev-parse --path-format=absolute --show-toplevel --git-common-dir
|
|
295
295
|
```
|
|
296
296
|
|
|
297
|
-
Line 1 is the checkout's toplevel, line 2 the
|
|
297
|
+
Line 1 is the checkout's toplevel, line 2 the common git directory. A git older than 2.31 echoes `--path-format=absolute` back as a line of its own first. `{ledger}` is the first that applies:
|
|
298
298
|
|
|
299
299
|
1. **The main worktree** — line 2 without its trailing `/.git`, when the output is exactly two lines each beginning with `/`, line 2 ends in `/.git`, and the directory left once it is removed is not your home directory and contains a `.devflow/` directory.
|
|
300
300
|
2. **The toplevel** — line 1, or on an older git the line after the echoed flag.
|
|
301
301
|
3. **The start directory itself** — when the command failed or printed no absolute toplevel (outside a git repository).
|
|
302
302
|
|
|
303
|
-
This is the rule the learning hooks apply
|
|
303
|
+
This is the rule the learning hooks apply, so you read the index the Curate agent writes.
|
|
304
304
|
|
|
305
305
|
**Step 1 — Read the pre-rendered index:**
|
|
306
306
|
|
|
@@ -309,13 +309,17 @@ Attempt to read `{ledger}/.devflow/learning/index.md`.
|
|
|
309
309
|
- If the file exists and contains non-empty content: use that content as `DECISIONS_CONTEXT`.
|
|
310
310
|
- If the file is absent or empty: set `DECISIONS_CONTEXT` to `(none)`.
|
|
311
311
|
|
|
312
|
-
The index is one direct file read, written at render time by `render-decisions.cjs`
|
|
312
|
+
The index is one direct file read, written at render time by `render-decisions.cjs` — no `.cjs` script runs here.
|
|
313
313
|
|
|
314
|
-
**Step 2 —
|
|
314
|
+
**Step 2 — Slice the index, then hand it on:**
|
|
315
315
|
|
|
316
|
-
When `DECISIONS_CONTEXT` is not `(none)`, hand it only to the agents whose contract declares it.
|
|
316
|
+
When `DECISIONS_CONTEXT` is not `(none)`, hand it only to the agents whose contract declares it.
|
|
317
317
|
|
|
318
|
-
|
|
318
|
+
Hand each agent that takes `DECISIONS_CONTEXT` a slice, not the whole index: the index lines whose title, scope or area touch the files and task it works on, verbatim, led by `(slice: N of M entries — full index: <absolute index path>)` and closed by the index footer. When unsure, include the line. Siblings over one diff share ONE slice.
|
|
319
|
+
|
|
320
|
+
Those agents follow `devflow:apply-decisions`. A host that uses the index in its own thread says so in its own step.
|
|
321
|
+
|
|
322
|
+
This produces a compact index of active ADR/PF entries. Pass `DECISIONS_CONTEXT` to all Review agents as one shared slice, cut over the diff's files. Review agents use `devflow:apply-decisions` to Read full entry bodies on demand.
|
|
319
323
|
|
|
320
324
|
### Load Feature Knowledge
|
|
321
325
|
|
|
@@ -339,7 +343,7 @@ If `index.md` exists and contains at least one entry line, use it for relevance
|
|
|
339
343
|
|
|
340
344
|
**Step 2 — Fallback: glob frontmatter (if `index.md` is absent or empty):**
|
|
341
345
|
|
|
342
|
-
Glob `{worktree}/.devflow/features/*/KNOWLEDGE.md`. For each file found, read only its YAML frontmatter block (between the opening and closing `---` delimiters).
|
|
346
|
+
Glob `{worktree}/.devflow/features/*/KNOWLEDGE.md`. For each file found, read only its YAML frontmatter block (between the opening and closing `---` delimiters).
|
|
343
347
|
|
|
344
348
|
**Step 3 — Pick relevant KBs:**
|
|
345
349
|
|
|
@@ -370,7 +374,7 @@ Headings: L5 Rules · L40 Overview · L62 Anti-Patterns · L118 Key Files
|
|
|
370
374
|
|
|
371
375
|
A KB with no Rules section labels its entries `Rules ({section name}):` and gives them no ID. `FEATURE_KNOWLEDGE` is these blocks; `FEATURE_KNOWLEDGE_RULES` is the same blocks without the `Headings:` line. Both come from this one selection, and each spawn names the variable its recipient takes. If no KBs exist, no KBs are relevant, or `.devflow/features/` is absent, set both to `(none)`.
|
|
372
376
|
|
|
373
|
-
**One git call, then direct reads — no `.cjs` script.**
|
|
377
|
+
**One git call, then direct reads — no `.cjs` script.**
|
|
374
378
|
|
|
375
379
|
Pass `FEATURE_KNOWLEDGE` to all Review agents alongside `DECISIONS_CONTEXT`.
|
|
376
380
|
|
|
@@ -522,21 +526,8 @@ In multi-worktree mode, report results per worktree.
|
|
|
522
526
|
|
|
523
527
|
| Case | Handling |
|
|
524
528
|
|------|----------|
|
|
525
|
-
| No new commits since last review | Skip review, report: "No new commits since last review. Use --full for a full re-review." |
|
|
526
|
-
| Rebase invalidates `.last-review-head` SHA | `git cat-file -t` check fails → fallback to full diff |
|
|
527
|
-
| Same-minute review collision | `mkdir` fails → retry with seconds appended (`YYYY-MM-DD_HHMMSS`) |
|
|
528
|
-
| Worktree in detached HEAD | Filtered out (no branch name → not reviewable) |
|
|
529
|
-
| Worktree mid-rebase or mid-merge | Filtered out by status check |
|
|
530
|
-
| Two worktrees on same branch | Deduplicate by branch — review once, use first worktree's path |
|
|
531
|
-
| Worktree on protected branch | Filtered out (not reviewable) |
|
|
532
|
-
| Worktree pre-flight fails | Report failure, continue with other worktrees |
|
|
533
529
|
| `--full` in multi-worktree mode | Applies to all worktrees (global modifier) |
|
|
534
|
-
| Many worktrees (5+) | Report count and proceed — user manages their worktree count |
|
|
535
530
|
| Review comment already posted | Git agent matches its own marker on the `{cycle, timestamp}` pair → skip silently (D7); a re-review in the same cycle (different timestamp) posts its own comment. The marker's format belongs to the operation; this caller passes the pair and never restates the literal |
|
|
536
|
-
| First review (no prior resolution) | PRIOR_RESOLUTIONS=(none), no convergence check |
|
|
537
|
-
| fp_ratio denominator = 0 | fp_ratio = 0, no warning |
|
|
538
|
-
| `--full` flag | Bypass incremental detection (Step 0d), still load PRIOR_RESOLUTIONS for cross-cycle awareness |
|
|
539
|
-
| Parsing failure on resolution-summary.md | fp_ratio = 0, convergence tracking degraded (see Step 0e-ii) |
|
|
540
531
|
| Concurrent sessions | Advisory only, each session computes independently |
|
|
541
532
|
| Docs-only diff | `docs-only`: documentation, consistency, security on `diff.patch`; no language or conditional focus |
|
|
542
533
|
| Tests-only diff | `tests-only`: testing, reliability, consistency, security on `diff.patch`; no language or conditional focus |
|
package/dist/commands/debug.md
CHANGED
|
@@ -54,19 +54,19 @@ Phase 7 passes `COMPLIANCE_DIRECTIVE` to the Code agent that implements the fix,
|
|
|
54
54
|
|
|
55
55
|
When the settings line says `LEARNING=off`, set `DECISIONS_CONTEXT` to `(none)` and skip this step, locating no ledger and reading no index.
|
|
56
56
|
|
|
57
|
-
The decisions ledger belongs to the repository, not to one checkout:
|
|
57
|
+
The decisions ledger belongs to the repository, not to one checkout: a linked worktree reads the main worktree's copy, a subdirectory session the repository root's. Locate it with ONE git call, run from the start directory — `WORKTREE_PATH` if provided, otherwise cwd (`devflow:worktree-support`):
|
|
58
58
|
|
|
59
59
|
```bash
|
|
60
60
|
git -C "{start}" rev-parse --path-format=absolute --show-toplevel --git-common-dir
|
|
61
61
|
```
|
|
62
62
|
|
|
63
|
-
Line 1 is the checkout's toplevel, line 2 the
|
|
63
|
+
Line 1 is the checkout's toplevel, line 2 the common git directory. A git older than 2.31 echoes `--path-format=absolute` back as a line of its own first. `{ledger}` is the first that applies:
|
|
64
64
|
|
|
65
65
|
1. **The main worktree** — line 2 without its trailing `/.git`, when the output is exactly two lines each beginning with `/`, line 2 ends in `/.git`, and the directory left once it is removed is not your home directory and contains a `.devflow/` directory.
|
|
66
66
|
2. **The toplevel** — line 1, or on an older git the line after the echoed flag.
|
|
67
67
|
3. **The start directory itself** — when the command failed or printed no absolute toplevel (outside a git repository).
|
|
68
68
|
|
|
69
|
-
This is the rule the learning hooks apply
|
|
69
|
+
This is the rule the learning hooks apply, so you read the index the Curate agent writes.
|
|
70
70
|
|
|
71
71
|
**Step 1 — Read the pre-rendered index:**
|
|
72
72
|
|
|
@@ -75,11 +75,15 @@ Attempt to read `{ledger}/.devflow/learning/index.md`.
|
|
|
75
75
|
- If the file exists and contains non-empty content: use that content as `DECISIONS_CONTEXT`.
|
|
76
76
|
- If the file is absent or empty: set `DECISIONS_CONTEXT` to `(none)`.
|
|
77
77
|
|
|
78
|
-
The index is one direct file read, written at render time by `render-decisions.cjs`
|
|
78
|
+
The index is one direct file read, written at render time by `render-decisions.cjs` — no `.cjs` script runs here.
|
|
79
79
|
|
|
80
|
-
**Step 2 —
|
|
80
|
+
**Step 2 — Slice the index, then hand it on:**
|
|
81
81
|
|
|
82
|
-
When `DECISIONS_CONTEXT` is not `(none)`, hand it only to the agents whose contract declares it.
|
|
82
|
+
When `DECISIONS_CONTEXT` is not `(none)`, hand it only to the agents whose contract declares it.
|
|
83
|
+
|
|
84
|
+
Hand each agent that takes `DECISIONS_CONTEXT` a slice, not the whole index: the index lines whose title, scope or area touch the files and task it works on, verbatim, led by `(slice: N of M entries — full index: <absolute index path>)` and closed by the index footer. When unsure, include the line. Siblings over one diff share ONE slice.
|
|
85
|
+
|
|
86
|
+
Those agents follow `devflow:apply-decisions`. A host that uses the index in its own thread says so in its own step.
|
|
83
87
|
|
|
84
88
|
The orchestrator uses `DECISIONS_CONTEXT` locally when generating hypotheses (Phase 2) — prior pitfalls and decisions can suggest specific root causes to investigate. Follow `devflow:apply-decisions` to Read full entry bodies on demand. **Do NOT pass `DECISIONS_CONTEXT` to Explore investigators** — decisions context stays in the orchestrator; investigators examine code directly.
|
|
85
89
|
|
|
@@ -234,7 +238,7 @@ Produce the final report:
|
|
|
234
238
|
|
|
235
239
|
Ask user via AskUserQuestion: "Want me to implement this fix?"
|
|
236
240
|
|
|
237
|
-
- **YES** → implement the fix through the Code agent, never in this thread, then spawn `Agent(subagent_type="
|
|
241
|
+
- **YES** → implement the fix through the Code agent, never in this thread, then spawn `Agent(subagent_type="Polish")` on the changed files. /debug loads no feature knowledge, so the fix gets none:
|
|
238
242
|
|
|
239
243
|
```
|
|
240
244
|
Agent(subagent_type="Code"):
|
|
@@ -282,21 +286,17 @@ FEATURE_SLUG: {slug derived from primary changed directory, kebab-case}
|
|
|
282
286
|
FEATURE_NAME: {human-readable name}
|
|
283
287
|
DIRECTORIES: {list of primary directories touched by this workflow}
|
|
284
288
|
FILES_CHANGED: {list of files changed}
|
|
285
|
-
DECISIONS_CONTEXT: {
|
|
289
|
+
DECISIONS_CONTEXT: {the slice for these directories, else (none)}
|
|
286
290
|
|
|
287
291
|
Write the knowledge base to:
|
|
288
292
|
{worktree}/.devflow/features/{slug}/KNOWLEDGE.md
|
|
289
293
|
|
|
290
|
-
Then update the index cache
|
|
294
|
+
Then update the index cache:
|
|
291
295
|
{worktree}/.devflow/features/index.md
|
|
292
296
|
|
|
293
297
|
Index line format: `- **{slug}** — {areas} — {Use-when description}` — at most 300 characters, the description at most 220; reword a longer one, never cut it.
|
|
294
298
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
The frontmatter in KNOWLEDGE.md is the source of truth — index.md is only a cache. Write the two files directly — no intermediate result JSON files, no external scripts.
|
|
298
|
-
|
|
299
|
-
After writing, commit the two files to the current worktree branch yourself by running git via your Bash tool (do not use a script). Stage ONLY .devflow/features/index.md and .devflow/features/{slug}/KNOWLEDGE.md, then commit just those paths with a docs(knowledge): message. Do NOT push, do NOT force, do NOT stage anything else. Follow your Commit Protocol — it is non-blocking, so if any git step fails, report KB_COMMIT and finish normally."
|
|
299
|
+
Then commit the two files as your Commit Protocol directs."
|
|
300
300
|
```
|
|
301
301
|
|
|
302
302
|
**Step 4 — Surface an uncommitted knowledge base:**
|
|
@@ -328,7 +328,7 @@ When the Knowledge agent reports `KB_COMMIT: skipped (detached HEAD)`, the files
|
|
|
328
328
|
├─ Phase 6: Root cause report with confidence level
|
|
329
329
|
│
|
|
330
330
|
├─ Phase 7: Offer Fix
|
|
331
|
-
│ └─ AskUserQuestion → Code agent (fix) +
|
|
331
|
+
│ └─ AskUserQuestion → Code agent (fix) + Polish agent, or done
|
|
332
332
|
│
|
|
333
333
|
└─ Feature Knowledge Write-Back (Conditional)
|
|
334
334
|
└─ Knowledge agent (if investigation surfaced durable cross-cutting knowledge)
|
|
@@ -41,7 +41,7 @@ Spawn devflow agents with:
|
|
|
41
41
|
agent("your prompt here", { agentType: "Code" })
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
Valid `agentType` values: Code,
|
|
44
|
+
Valid `agentType` values: Code, Fix, Validate, Polish, Harden, Evaluate, Test, Review, Git, Synthesize, Knowledge, Design.
|
|
45
45
|
|
|
46
46
|
**OMIT `opts.model` whenever `agentType` is set.** The agent frontmatter carries its own model tier (Code→sonnet, Validate→haiku, Review→opus, etc.) and that tier is honored automatically. Passing `opts.model` overrides it — always a mistake.
|
|
47
47
|
|
|
@@ -91,23 +91,25 @@ The accepted line is the only source of these values: the script alone folds the
|
|
|
91
91
|
|
|
92
92
|
When the settings line says `LEARNING=off`, set `DECISIONS_CONTEXT` to `(none)` and skip this step, locating no ledger and reading no index.
|
|
93
93
|
|
|
94
|
-
The decisions ledger belongs to the repository, not to one checkout:
|
|
94
|
+
The decisions ledger belongs to the repository, not to one checkout: a linked worktree reads the main worktree's copy, a subdirectory session the repository root's. Locate it with ONE git call, run from the start directory — `WORKTREE_PATH` if provided, otherwise cwd (`devflow:worktree-support`):
|
|
95
95
|
|
|
96
96
|
```bash
|
|
97
97
|
git -C "{start}" rev-parse --path-format=absolute --show-toplevel --git-common-dir
|
|
98
98
|
```
|
|
99
99
|
|
|
100
|
-
Line 1 is the checkout's toplevel, line 2 the
|
|
100
|
+
Line 1 is the checkout's toplevel, line 2 the common git directory. A git older than 2.31 echoes `--path-format=absolute` back as a line of its own first. `{ledger}` is the first that applies:
|
|
101
101
|
|
|
102
102
|
1. **The main worktree** — line 2 without its trailing `/.git`, when the output is exactly two lines each beginning with `/`, line 2 ends in `/.git`, and the directory left once it is removed is not your home directory and contains a `.devflow/` directory.
|
|
103
103
|
2. **The toplevel** — line 1, or on an older git the line after the echoed flag.
|
|
104
104
|
3. **The start directory itself** — when the command failed or printed no absolute toplevel (outside a git repository).
|
|
105
105
|
|
|
106
|
-
This is the rule the learning hooks apply
|
|
106
|
+
This is the rule the learning hooks apply, so you read the index the Curate agent writes.
|
|
107
107
|
|
|
108
108
|
Before you author the workflow script, read `{ledger}/.devflow/learning/index.md`. If the file is absent or empty, set `DECISIONS_CONTEXT` to `(none)`; otherwise use the file content as `DECISIONS_CONTEXT`.
|
|
109
109
|
|
|
110
|
-
The script body cannot perform this read — you (the main model) do it before authoring. Then inject the relevant DECISIONS_CONTEXT into the prompts of the Code,
|
|
110
|
+
The script body cannot perform this read — you (the main model) do it before authoring. Then inject the relevant DECISIONS_CONTEXT into the prompts of the Code, Fix, Design, Knowledge, Review and Harden agents, which follow `devflow:apply-decisions`. Those are the agent types above whose contract declares it; every other agent type gets no decisions context.
|
|
111
|
+
|
|
112
|
+
Hand each agent that takes `DECISIONS_CONTEXT` a slice, not the whole index: the index lines whose title, scope or area touch the files and task it works on, verbatim, led by `(slice: N of M entries — full index: <absolute index path>)` and closed by the index footer. When unsure, include the line. Siblings over one diff share ONE slice. The script carries one `DECISIONS_CONTEXT` for every agent, so cut it once, over the whole run.
|
|
111
113
|
|
|
112
114
|
---
|
|
113
115
|
|
|
@@ -122,10 +124,10 @@ The following agentType values are valid. Model tiers are shown for reference
|
|
|
122
124
|
| agentType | Model tier | Role |
|
|
123
125
|
|-----------|-----------|------|
|
|
124
126
|
| Code | sonnet | Implements the plan and fixes review findings — the Code family is the ONLY one that writes code |
|
|
125
|
-
|
|
|
127
|
+
| Fix | sonnet | Fixes the listed validation, alignment and QA failures — part of the Code family |
|
|
126
128
|
| Validate | haiku | Build / typecheck / lint / test — fast correctness gate |
|
|
127
|
-
|
|
|
128
|
-
|
|
|
129
|
+
| Polish | sonnet | Reduces complexity, removes duplication, improves readability |
|
|
130
|
+
| Harden | opus | 9-pillar self-review — deep structural analysis |
|
|
129
131
|
| Evaluate | sonnet | Plan-fidelity / alignment — "was the plan implemented correctly?" |
|
|
130
132
|
| Test | sonnet | Scenario-based acceptance tests against acceptance criteria |
|
|
131
133
|
| Review | opus | Focus-parameterized code review — spawn ONE agent() per focus area |
|
|
@@ -136,7 +138,7 @@ The following agentType values are valid. Model tiers are shown for reference
|
|
|
136
138
|
|
|
137
139
|
### Agent caveats
|
|
138
140
|
|
|
139
|
-
- **The Code family writes every fix** — Code for review findings,
|
|
141
|
+
- **The Code family writes every fix** — Code for review findings, Fix for gate failures; no other agent type writes code. Finding-verification uses adversarial Review agent-style passes (§6.3 of design doc). Risk-assessment and tech-debt routing live in the post-code pipeline + escalation doctrine.
|
|
140
142
|
- **Always omit `opts.model` with `agentType`.** Each agent honors its own frontmatter model tier; overriding it defeats the per-agent specialization.
|
|
141
143
|
- **Review agents are focus-parameterized.** Each focus is a SEPARATE `agent()` call with `agentType: "Review"` and the focus baked into the prompt. Do NOT batch multiple focuses into one Review agent call — that defeats parallel specialization.
|
|
142
144
|
- **Do not depend on agents enumerating their own skills.** Skills are loaded (spike F5 confirmed) but self-reporting is imperfect. Write agent prompts that give the agent full context directly.
|
|
@@ -187,7 +189,7 @@ Author the resolved `ISSUE_REQUIRED` and `APPLY_CONVENTIONS` into the workflow s
|
|
|
187
189
|
|
|
188
190
|
**Set the compliance lens** from that line: `COMPLIANCE_FRAMEWORKS` is the settings line's `COMPLIANCE` with `generic` written `none`: `off`, `none`, or the framework ids the machine and this repository declare.
|
|
189
191
|
|
|
190
|
-
Pass it as `complianceFrameworks` when invoking the workflow; the engine builds `COMPLIANCE_DIRECTIVE` from it and hands that to every Code and
|
|
192
|
+
Pass it as `complianceFrameworks` when invoking the workflow; the engine builds `COMPLIANCE_DIRECTIVE` from it and hands that to every Code and Fix agent.
|
|
191
193
|
|
|
192
194
|
**0c. Resolve the docs root**
|
|
193
195
|
|
|
@@ -295,7 +297,7 @@ const ISSUE_INPUT = args.issueInput || args.issueNumber || "(none)"; // this ti
|
|
|
295
297
|
const ISSUE_REQUIRED = String(args.issueRequired) === "false" ? "false" : "true"; // Pre-authoring step 0; only an explicit false turns it off — absent or unrecognised fails closed, like the resolver
|
|
296
298
|
const APPLY_CONVENTIONS = String(args.applyConventions) === "false" ? "false" : "true";
|
|
297
299
|
const COMPLIANCE_FRAMEWORKS = /^(?:off|none|[a-z][a-z0-9-]{0,15}(?:,[a-z][a-z0-9-]{0,15}){0,7})$/.test(String(args.complianceFrameworks)) ? String(args.complianceFrameworks) : "off"; // Pre-authoring step 0b; any other shape is no lens
|
|
298
|
-
const COMPLIANCE_DIRECTIVE = COMPLIANCE_FRAMEWORKS === "off" ? "" : `When the task touches regulated surface (data models, auth flows, logging/observability, payments, IaC, retention), invoke Skill(skill="devflow:compliance") and load references/{id}.md only for the ids in ${COMPLIANCE_FRAMEWORKS} (none: generic controls only); never fabricate guidance for a framework you were not given.`; // D-COMPLIANCE-INJECT: empty when the lens is off, so a Code or
|
|
300
|
+
const COMPLIANCE_DIRECTIVE = COMPLIANCE_FRAMEWORKS === "off" ? "" : `When the task touches regulated surface (data models, auth flows, logging/observability, payments, IaC, retention), invoke Skill(skill="devflow:compliance") and load references/{id}.md only for the ids in ${COMPLIANCE_FRAMEWORKS} (none: generic controls only); never fabricate guidance for a framework you were not given.`; // D-COMPLIANCE-INJECT: empty when the lens is off, so a Code or Fix spawn then carries nothing about compliance; otherwise the one line _compliance.mds renders as compliance_directive(), with the validated ids in place of <ids>
|
|
299
301
|
|
|
300
302
|
// Phase 1: Git setup — declare the operation; the agent owns the process, the branch name included
|
|
301
303
|
const setup = await phase("setup", () =>
|
|
@@ -348,16 +350,16 @@ After implementing, commit your changes with a conventional-commit message and r
|
|
|
348
350
|
- Any open questions or blockers`, { agentType: "Code" })
|
|
349
351
|
);
|
|
350
352
|
|
|
351
|
-
// Phase 3: Gate 1 #1 — post-code pipeline:
|
|
353
|
+
// Phase 3: Gate 1 #1 — post-code pipeline: Polish agent → Harden agent → Validate agent.
|
|
352
354
|
// Validate runs last and unconditionally, so its one full run covers every commit the pass made (see gate1_postcode()).
|
|
353
355
|
const gate1 = await phase("gate1", async () => {
|
|
354
|
-
await agent(`
|
|
356
|
+
await agent(`Polish and reduce complexity of recent changes on branch ${BRANCH}. Commit any improvements.`, { agentType: "Polish" });
|
|
355
357
|
|
|
356
|
-
const
|
|
357
|
-
Return: {"status": "PASS" | "FIXED" | "BLOCKED"}`, { agentType: "
|
|
358
|
-
// Anything but an explicit PASS or FIXED is a stop: a
|
|
359
|
-
if (!["PASS", "FIXED"].includes(
|
|
360
|
-
return { verdict: "ESCALATED", type: "
|
|
358
|
+
const harden = await agent(`9-pillar self-review of recent changes on branch ${BRANCH}. Fix P0/P1 issues and commit the fixes.
|
|
359
|
+
Return: {"status": "PASS" | "FIXED" | "BLOCKED"}`, { agentType: "Harden" });
|
|
360
|
+
// Anything but an explicit PASS or FIXED is a stop: a Harden that returned no status, or one this skeleton does not know, has not accepted the code.
|
|
361
|
+
if (!["PASS", "FIXED"].includes(harden?.status)) {
|
|
362
|
+
return { verdict: "ESCALATED", type: "harden-blocked", reason: harden?.status === "BLOCKED" ? "Harden agent returned BLOCKED: a P0 issue cannot be fixed in scope" : "Harden agent returned no recognised status: counted as BLOCKED" };
|
|
361
363
|
}
|
|
362
364
|
|
|
363
365
|
const validation = await agent(`Run build, typecheck, lint, and tests on branch ${BRANCH}.
|
|
@@ -374,19 +376,19 @@ Fix the validation failures on branch ${BRANCH}:
|
|
|
374
376
|
${failureDetails}
|
|
375
377
|
DECISIONS_CONTEXT: ${DECISIONS_CONTEXT}
|
|
376
378
|
${COMPLIANCE_DIRECTIVE}
|
|
377
|
-
Commit fixes with conventional-commit message.`, { agentType: "
|
|
379
|
+
Commit fixes with conventional-commit message.`, { agentType: "Fix" });
|
|
378
380
|
const recheck = await agent(`Re-run build, typecheck, lint, tests on branch ${BRANCH} after fix attempt ${attempt} (follow your Running commands block).
|
|
379
381
|
Return: {"verdict": "PASS" | "FAIL", "details": "..."}`, { agentType: "Validate" });
|
|
380
382
|
if (recheck?.verdict === "PASS") break;
|
|
381
383
|
failureDetails = recheck?.details || failureDetails;
|
|
382
|
-
if (attempt === 2) return { verdict: "ESCALATED", type: "validation-exhausted", reason: "Validation exhausted after 2
|
|
384
|
+
if (attempt === 2) return { verdict: "ESCALATED", type: "validation-exhausted", reason: "Validation exhausted after 2 Fix agent attempts" };
|
|
383
385
|
}
|
|
384
386
|
}
|
|
385
387
|
|
|
386
388
|
return { verdict: "PASS" };
|
|
387
389
|
});
|
|
388
390
|
|
|
389
|
-
// Gate 1 #1 stop, before Gate 2: an exhausted Validate or a BLOCKED
|
|
391
|
+
// Gate 1 #1 stop, before Gate 2: an exhausted Validate or a BLOCKED Harden leaves a broken or unfinished build,
|
|
390
392
|
// so Gate 2 and the review pass never run on it — a correctness stop, like the ticket-link and branch stops.
|
|
391
393
|
if (gate1.verdict === "ESCALATED") {
|
|
392
394
|
return { ticket: TICKET, branch: BRANCH, verdict: "ESCALATED", issueId: ISSUE_NUMBER, issuePrLink: ISSUE_PR_LINK, escalations: [{ type: gate1.type, description: gate1.reason }] };
|
|
@@ -415,7 +417,7 @@ Fix the alignment issues identified by the Evaluate agent on branch ${BRANCH}:
|
|
|
415
417
|
${evaluation?.rationale || "see the Evaluate agent's report"}
|
|
416
418
|
DECISIONS_CONTEXT: ${DECISIONS_CONTEXT}
|
|
417
419
|
${COMPLIANCE_DIRECTIVE}
|
|
418
|
-
Self-verify your fix compiles, following your Running commands block. Commit fixes.`, { agentType: "
|
|
420
|
+
Self-verify your fix compiles, following your Running commands block. Commit fixes.`, { agentType: "Fix" });
|
|
419
421
|
evalVerdict = "FAIL-FIXED"; // issues found, fixes applied, not re-evaluated by design
|
|
420
422
|
}
|
|
421
423
|
}
|
|
@@ -435,7 +437,7 @@ Fix the failing acceptance test scenarios on branch ${BRANCH}:
|
|
|
435
437
|
${testResult.failures}
|
|
436
438
|
DECISIONS_CONTEXT: ${DECISIONS_CONTEXT}
|
|
437
439
|
${COMPLIANCE_DIRECTIVE}
|
|
438
|
-
Self-verify your fix compiles and the scenarios pass, following your Running commands block. Commit fixes.`, { agentType: "
|
|
440
|
+
Self-verify your fix compiles and the scenarios pass, following your Running commands block. Commit fixes.`, { agentType: "Fix" });
|
|
439
441
|
testVerdict = "FAIL-FIXED"; // issues found, fixes applied, not re-evaluated by design
|
|
440
442
|
}
|
|
441
443
|
}
|
|
@@ -588,16 +590,16 @@ Return: {"status": "fixed"|"blocked", "commitShas": ["<sha>"], "unresolved": ["<
|
|
|
588
590
|
return { survivingFindings: notAddressed, fixedFindings, coverageGaps };
|
|
589
591
|
});
|
|
590
592
|
|
|
591
|
-
// Phase 5.5: Gate 1 #2 — FINAL post-fix gate (
|
|
593
|
+
// Phase 5.5: Gate 1 #2 — FINAL post-fix gate (Polish agent → Harden agent → full Validate agent, Validate last and unconditional).
|
|
592
594
|
// Runs ONCE, after the review pass. Inside the pass the Code agent self-verified its own fixes;
|
|
593
595
|
// this is the build gate before the branch is handed back. See gate1_postcode() cadence.
|
|
594
596
|
const gate1Final = await phase("gate1-final", async () => {
|
|
595
|
-
await agent(`
|
|
597
|
+
await agent(`Polish and reduce complexity of recent changes on branch ${BRANCH}. Commit any improvements.`, { agentType: "Polish" });
|
|
596
598
|
|
|
597
|
-
const
|
|
598
|
-
Return: {"status": "PASS" | "FIXED" | "BLOCKED"}`, { agentType: "
|
|
599
|
-
if (!["PASS", "FIXED"].includes(
|
|
600
|
-
return { verdict: "ESCALATED", type: "
|
|
599
|
+
const harden = await agent(`9-pillar self-review of recent changes on branch ${BRANCH}. Fix P0/P1 issues and commit the fixes.
|
|
600
|
+
Return: {"status": "PASS" | "FIXED" | "BLOCKED"}`, { agentType: "Harden" });
|
|
601
|
+
if (!["PASS", "FIXED"].includes(harden?.status)) {
|
|
602
|
+
return { verdict: "ESCALATED", type: "harden-blocked", reason: harden?.status === "BLOCKED" ? "Final Gate 1 Harden agent returned BLOCKED: a P0 issue cannot be fixed in scope" : "Final Gate 1 Harden agent returned no recognised status: counted as BLOCKED" };
|
|
601
603
|
}
|
|
602
604
|
|
|
603
605
|
const validation = await agent(`Run build, typecheck, lint, and tests on branch ${BRANCH} (final gate after all fixing).
|
|
@@ -612,12 +614,12 @@ Fix the final validation failures on branch ${BRANCH}:
|
|
|
612
614
|
${failureDetails}
|
|
613
615
|
DECISIONS_CONTEXT: ${DECISIONS_CONTEXT}
|
|
614
616
|
${COMPLIANCE_DIRECTIVE}
|
|
615
|
-
Self-verify your fix compiles. Commit fixes with conventional-commit message.`, { agentType: "
|
|
617
|
+
Self-verify your fix compiles. Commit fixes with conventional-commit message.`, { agentType: "Fix" });
|
|
616
618
|
const recheck = await agent(`Re-run build, typecheck, lint, tests on branch ${BRANCH} (final gate, after fix attempt ${attempt}; follow your Running commands block).
|
|
617
619
|
Return: {"verdict": "PASS" | "FAIL", "details": "..."}`, { agentType: "Validate" });
|
|
618
620
|
if (recheck?.verdict === "PASS") break;
|
|
619
621
|
failureDetails = recheck?.details || failureDetails;
|
|
620
|
-
if (attempt === 2) return { verdict: "ESCALATED", type: "validation-exhausted", reason: "Final Gate 1 validation exhausted after 2
|
|
622
|
+
if (attempt === 2) return { verdict: "ESCALATED", type: "validation-exhausted", reason: "Final Gate 1 validation exhausted after 2 Fix agent attempts" };
|
|
621
623
|
}
|
|
622
624
|
}
|
|
623
625
|
|
|
@@ -702,7 +704,7 @@ Code(agentType:"Code", prompt: "OPERATION: implement" first line, then full task
|
|
|
702
704
|
→ gate2_acceptance() ← Gate 2 runs HERE — before the review pass, not after
|
|
703
705
|
```
|
|
704
706
|
|
|
705
|
-
Every Code-family agent prompt opens with `OPERATION: <mode>` as its first line: `implement` and `issue-fix` go to `agentType:"Code"`, `validation-fix`, `alignment-fix` and `qa-fix` go to `agentType:"
|
|
707
|
+
Every Code-family agent prompt opens with `OPERATION: <mode>` as its first line: `implement` and `issue-fix` go to `agentType:"Code"`, `validation-fix`, `alignment-fix` and `qa-fix` go to `agentType:"Fix"`. It must include: task description, implementation plan (if one exists), relevant DECISIONS_CONTEXT (the index you loaded before authoring), the compliance directive (`COMPLIANCE_DIRECTIVE` — every Code prompt carries it when it is not empty, fix prompts included), and any PRIOR_PHASE_SUMMARY / HANDOFF_FILE for sequential multi-phase tickets.
|
|
706
708
|
|
|
707
709
|
Gate 2 runs at implementation acceptance — this matches devflow's deliberate placement: "evaluation is part of implementation acceptance, not post-review" (§6.1).
|
|
708
710
|
|
|
@@ -710,12 +712,12 @@ Gate 2 runs at implementation acceptance — this matches devflow's deliberate p
|
|
|
710
712
|
|
|
711
713
|
ORDER IS LOAD-BEARING. Run exactly in this sequence:
|
|
712
714
|
|
|
713
|
-
1. **
|
|
714
|
-
2. **
|
|
715
|
-
- BLOCKED (a P0 issue cannot be fixed in scope), or a missing or unrecognised status, which counts as BLOCKED → stop the pass and escalate as `
|
|
716
|
-
3. **Validate agent** — build / typecheck / lint / test; returns `{"verdict": "PASS" | "FAIL", "details": "..."}`. It runs LAST and UNCONDITIONALLY: one full run over the HEAD that
|
|
715
|
+
1. **Polish agent** — reduce complexity, remove duplication
|
|
716
|
+
2. **Harden agent** — 9-pillar self-review (deep structural analysis); returns `{"status": "PASS" | "FIXED" | "BLOCKED"}`
|
|
717
|
+
- BLOCKED (a P0 issue cannot be fixed in scope), or a missing or unrecognised status, which counts as BLOCKED → stop the pass and escalate as `harden-blocked`; Validate does not run on code Harden could not accept
|
|
718
|
+
3. **Validate agent** — build / typecheck / lint / test; returns `{"verdict": "PASS" | "FAIL", "details": "..."}`. It runs LAST and UNCONDITIONALLY: one full run over the HEAD that Polish and Harden left, so it covers their commits whether or not Harden changed code
|
|
717
719
|
- Build/test commands follow `build_execution_doctrine()`: the Validate agent's Running commands block, foreground under an explicit Bash timeout.
|
|
718
|
-
- FAIL →
|
|
720
|
+
- FAIL → Fix agent fix (max 2 retries), each followed by a Validate agent re-run
|
|
719
721
|
- If still FAIL after 2 retries → escalate as `validation-exhausted` (do not loop endlessly)
|
|
720
722
|
|
|
721
723
|
**Gate 1 contains NO Evaluate agent and NO Test agent.** Those are Gate 2 only.
|
|
@@ -723,8 +725,8 @@ ORDER IS LOAD-BEARING. Run exactly in this sequence:
|
|
|
723
725
|
Depth scales to change size + budget: a trivial one-line fix warrants a lighter pass; a multi-file refactor warrants the full depth.
|
|
724
726
|
|
|
725
727
|
**Cadence — Gate 1 runs at exactly TWO points per ticket:**
|
|
726
|
-
1. **Gate 1 #1** — immediately after the initial Code agent implementation (inside `implement_bundle()`). An escalated result — Validate exhausted, or
|
|
727
|
-
2. **Gate 1 #2** — the FINAL gate, after ALL Gate-2 fixes AND the entire review pass have completed.
|
|
728
|
+
1. **Gate 1 #1** — immediately after the initial Code agent implementation (inside `implement_bundle()`). An escalated result — Validate exhausted, or Harden BLOCKED — returns early: the ticket's engine returns `ESCALATED` with one escalation, and Gate 2 and the review pass never run on a broken or unfinished build.
|
|
729
|
+
2. **Gate 1 #2** — the FINAL gate, after ALL Gate-2 fixes AND the entire review pass have completed. Harden BLOCKED here is `ESCALATED` as well.
|
|
728
730
|
|
|
729
731
|
It does NOT run inside the review pass, nor after each individual Gate-2 / review / QA fix. At those points the fixing Code agent self-verifies its OWN build compiles (see `review_pass()` and the Code agent's Running commands block). The final Gate 1 #2 is the invariant that all written code passes before merge.
|
|
730
732
|
|
|
@@ -736,11 +738,11 @@ Gate 2 inputs are produced by `/devflow:dynamic-plan`'s plan-challenge step —
|
|
|
736
738
|
|
|
737
739
|
**Evaluate agent** (only if a plan exists):
|
|
738
740
|
- Run `evaluator_panel()` — see that block for the one spawn and the two lenses it names
|
|
739
|
-
- If the Evaluate agent returns FAIL (either lens failed): fix-and-continue — the demanded fixes are applied by a
|
|
741
|
+
- If the Evaluate agent returns FAIL (either lens failed): fix-and-continue — the demanded fixes are applied by a Fix agent that self-verifies its own build (batched per the review-pass batching doctrine if numerous). The recorded verdict becomes `FAIL-FIXED` (issues found, fixes applied, not re-evaluated by design); Gate 2 then proceeds. In SINGLE mode the run reports it as `UNVERIFIED`, never PASS.
|
|
740
742
|
|
|
741
743
|
**Test agent** (only if acceptance criteria or a test plan exist):
|
|
742
744
|
- Scenario-based acceptance tests covering functionality, API contracts, performance
|
|
743
|
-
- FAIL → fix-and-continue — a
|
|
745
|
+
- FAIL → fix-and-continue — a Fix agent applies the demanded fixes and self-verifies its own build. The recorded verdict becomes `FAIL-FIXED`; Gate 2 then proceeds. In SINGLE mode the run reports it as `UNVERIFIED`, never PASS.
|
|
744
746
|
|
|
745
747
|
**When Gate 2 inputs are absent:**
|
|
746
748
|
- No plan → skip the Evaluate agent silently (note in output: "Gate 2 Evaluate agent skipped — no plan available")
|
|
@@ -855,13 +857,13 @@ Majority-survives: a finding needs >50% of verification lenses to confirm it. St
|
|
|
855
857
|
|
|
856
858
|
If no surviving findings: return early (no fixes needed). Any coverageGaps are carried in the return — they block a PASS verdict downstream, not the early exit.
|
|
857
859
|
|
|
858
|
-
If survivors remain: batch the confirmed findings for fixing: group findings by file — one file per set of sub-batches, chunked at max 5 findings per sub-batch; never mix two files in one batch. A finding with no `file` field is its own singleton batch. Sub-batches for the SAME file run sequentially (never two Code agents editing the same file concurrently — same-file edits in `parallel()` cause index contention and lost fixes); sub-batches for DISTINCT files run via `parallel()` in staggered chunks of ~5, same pacing bar as the Review spawn path (different code areas — safe per concurrency doctrine). Each Code agent's prompt pins a return contract: `{"status": "fixed"|"blocked", "commitShas": [...], "unresolved": [...]}` — a chunk is FIXED only when `result.status === "fixed"` AND `commitShas` is non-empty AND `result.unresolved` is empty; never decide disposition from status alone. A non-empty `unresolved` list means the agent named work it could not complete — carry the whole chunk into `survivingFindings` rather than guessing which findings the strings map to. `survivingFindings` = findings NOT addressed: fix Code agent dead/failed/blocked/deferred OR committed but left work named in `unresolved`. The fixing Code agent **self-verifies its own fix builds** (build/typecheck per the Code agent's Running commands block, once over its whole batch). Do **NOT** run Gate 1 or Gate 2 inside the pass (no Validate agent, no
|
|
860
|
+
If survivors remain: batch the confirmed findings for fixing: group findings by file — one file per set of sub-batches, chunked at max 5 findings per sub-batch; never mix two files in one batch. A finding with no `file` field is its own singleton batch. Sub-batches for the SAME file run sequentially (never two Code agents editing the same file concurrently — same-file edits in `parallel()` cause index contention and lost fixes); sub-batches for DISTINCT files run via `parallel()` in staggered chunks of ~5, same pacing bar as the Review spawn path (different code areas — safe per concurrency doctrine). Each Code agent's prompt pins a return contract: `{"status": "fixed"|"blocked", "commitShas": [...], "unresolved": [...]}` — a chunk is FIXED only when `result.status === "fixed"` AND `commitShas` is non-empty AND `result.unresolved` is empty; never decide disposition from status alone. A non-empty `unresolved` list means the agent named work it could not complete — carry the whole chunk into `survivingFindings` rather than guessing which findings the strings map to. `survivingFindings` = findings NOT addressed: fix Code agent dead/failed/blocked/deferred OR committed but left work named in `unresolved`. The fixing Code agent **self-verifies its own fix builds** (build/typecheck per the Code agent's Running commands block, once over its whole batch). Do **NOT** run Gate 1 or Gate 2 inside the pass (no Validate agent, no Polish agent, no Harden agent, no Evaluate agent, no Test agent). The engine runs ONE final Gate 1 after the pass exits — see the `gate1_postcode()` cadence (Gate 1 #2).
|
|
859
861
|
|
|
860
862
|
### Engine invariants (non-negotiable)
|
|
861
863
|
|
|
862
|
-
1. **Code is written ONLY by the Code family (Code,
|
|
864
|
+
1. **Code is written ONLY by the Code family (Code, Fix).** No other agent type writes code — not Review agent, not Evaluate agent.
|
|
863
865
|
2. **Findings are verified before any fix is written.** The adversarial verification step is not optional; unverified findings are not passed to the Code agent.
|
|
864
|
-
3. **All written code passes Gate 1.** No code merge, commit, or handoff before
|
|
866
|
+
3. **All written code passes Gate 1.** No code merge, commit, or handoff before Polish agent + Harden agent + Validate agent (in that order — Validate last, so its one run covers the commits of the two before it).
|
|
865
867
|
4. **Gate 2 runs once, at implementation acceptance.** It does not re-run after review-fixes.
|
|
866
868
|
5. **NEVER auto-merge to main or master.** All merges target the integration branch. The user merges to main themselves.
|
|
867
869
|
6. **No unauthorized tracker or remote side-effects.** Sub-agents NEVER create issues/PRs on the tracker, comment on them, or push beyond the ticket-authorized branch unless the ticket, plan, or user explicitly authorizes that exact action. This applies to whatever tracker is resolved, not to one vendor. Proposed follow-ups go in the run report.
|
|
@@ -903,7 +905,7 @@ Each ticket engine run returns a structured result. The Synthesize agent or the
|
|
|
903
905
|
},
|
|
904
906
|
"escalations": [
|
|
905
907
|
{
|
|
906
|
-
"type": "merge-conflict | gate2-fail | validation-exhausted |
|
|
908
|
+
"type": "merge-conflict | gate2-fail | validation-exhausted | harden-blocked | ambiguous-resolution | review-coverage-incomplete | dependency-blocked | engine-crash | ticket-link-missing | branch-missing",
|
|
907
909
|
"description": "string"
|
|
908
910
|
}
|
|
909
911
|
],
|
|
@@ -1262,19 +1264,13 @@ git -C "{integration worktree root}" push origin HEAD; echo "exit=$?"
|
|
|
1262
1264
|
|
|
1263
1265
|
Note: `auto` is NOT fail-open — under `auto`, the Git agent probes the repository visibility and treats any error or unrecognised value as PUBLIC (mode STUB). What each value does is decided by the Git agent's publication gate (`references/publication-gate.md` step 2); this partial only resolves the value.
|
|
1264
1266
|
|
|
1265
|
-
Then spawn:
|
|
1267
|
+
Then run the script inline — it is the whole `update-pr-evidence` operation, with no Git agent spawn — through the Bash tool with `timeout: 180000`:
|
|
1266
1268
|
|
|
1267
|
-
```
|
|
1268
|
-
|
|
1269
|
-
"OPERATION: update-pr-evidence
|
|
1270
|
-
PR_NUMBER: {n}
|
|
1271
|
-
EVIDENCE_FILE: .devflow/docs/evidence-wave-{slug}.md
|
|
1272
|
-
REVIEW_PUBLICATION: {REVIEW_PUBLICATION resolved above, or auto}
|
|
1273
|
-
WORKTREE_PATH: {integration worktree root}
|
|
1274
|
-
Update the wave PR's test-plan block and post its evidence comment."
|
|
1269
|
+
```bash
|
|
1270
|
+
cd "{integration worktree root}" && node "$HOME/.devflow/scripts/verify-evidence.cjs" publish --pr {n} --evidence ".devflow/docs/evidence-wave-{slug}.md" --publication {REVIEW_PUBLICATION resolved above, or auto}; echo "exit=$?"
|
|
1275
1271
|
```
|
|
1276
1272
|
|
|
1277
|
-
`
|
|
1273
|
+
`{n}` is the number admitted above, and the publication value is `auto`, `full`, `off` or `stub`. `publish` decides what each publication value means for the evidence comment. Report its `## PR Evidence` block — its `EVIDENCE` line and its `**Body**:` / `**Comment**:` line — with any `TRACEABILITY: DEGRADED ({reason})` lines after it, or its `TRACEABILITY: DEGRADED (evidence unavailable)` line; empty stdout or any other exit ⇒ `TRACEABILITY: DEGRADED (evidence refresh failed)`. Whatever it returns, the run ends here.
|
|
1278
1274
|
|
|
1279
1275
|
---
|
|
1280
1276
|
|