devflow-kit 3.6.0 → 3.7.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 +80 -1
- package/README.md +6 -2
- package/dist/agents/code.md +7 -11
- package/dist/agents/fix.md +5 -6
- package/dist/agents/refactor.md +5 -6
- package/dist/agents/review.md +2 -0
- package/dist/cli/commands/gates.js +276 -0
- package/dist/cli/commands/init-seed.js +9 -1
- package/dist/cli/commands/init.js +31 -8
- package/dist/cli/commands/memory.js +18 -0
- package/dist/cli.js +2 -0
- package/dist/commands/bug-analysis.md +2 -2
- package/dist/commands/code-review.md +52 -44
- package/dist/commands/debug.md +2 -2
- package/dist/commands/dynamic-build.md +53 -61
- package/dist/commands/dynamic-plan.md +2 -2
- package/dist/commands/dynamic-profile.md +2 -2
- package/dist/commands/dynamic-tickets.md +2 -2
- package/dist/commands/explore.md +2 -2
- package/dist/commands/implement.md +26 -31
- package/dist/commands/plan.md +15 -25
- package/dist/commands/release.md +2 -2
- package/dist/commands/research.md +2 -2
- package/dist/commands/resolve.md +2 -2
- package/dist/commands/self-review.md +2 -2
- package/dist/core/echo-value.js +42 -0
- package/dist/core/evidence-policy.js +17 -5
- package/dist/core/gate-level.js +213 -0
- package/dist/core/manifest.js +26 -10
- package/dist/core/model-discovery.js +7 -1
- package/dist/core/tracker.js +5 -33
- package/dist/learning-off/agents/code.md +7 -11
- package/dist/learning-off/agents/fix.md +5 -6
- package/dist/learning-off/agents/refactor.md +5 -6
- package/dist/learning-off/agents/review.md +2 -0
- package/dist/learning-off/commands/code-review.md +52 -44
- package/dist/learning-off/commands/debug.md +2 -2
- package/dist/learning-off/commands/dynamic-build.md +53 -61
- package/dist/learning-off/commands/explore.md +2 -2
- package/dist/learning-off/commands/implement.md +26 -31
- package/dist/learning-off/commands/plan.md +15 -25
- package/dist/learning-off/commands/resolve.md +2 -2
- package/dist/learning-off/commands/self-review.md +2 -2
- package/dist/skills/git/references/tracker/github/ensure-pr-ready.md +7 -9
- package/dist/skills/git/references/tracker/jira/ensure-pr-ready.md +7 -15
- package/dist/skills/git/references/tracker/linear/ensure-pr-ready.md +7 -15
- package/dist/targets/claude-code/learning-install.js +15 -3
- package/package.json +1 -1
- package/src/assets/agents/_partials/_code.mds +5 -6
- package/src/assets/agents/code.mds +2 -5
- package/src/assets/agents/curate.md +4 -6
- package/src/assets/agents/review.mds +2 -0
- package/src/assets/agents/synthesize.md +2 -2
- package/src/assets/commands/_partials/_settings.mds +2 -2
- package/src/assets/commands/_partials/_wave.mds +10 -17
- package/src/assets/commands/code-review.mds +50 -42
- package/src/assets/commands/dynamic-build.mds +41 -42
- package/src/assets/commands/implement.mds +24 -29
- package/src/assets/commands/plan.mds +14 -24
- package/src/assets/mds/git/_ops_steps.mds +3 -3
- package/src/assets/mds/tracker/_common.mds +23 -12
- package/src/assets/mds/tracker/_github.mds +2 -9
- package/src/assets/mds/tracker/_jira.mds +2 -15
- package/src/assets/mds/tracker/_linear.mds +2 -15
- package/src/assets/scripts/ci-wait.cjs +22 -4
- package/src/assets/scripts/claude-md-audit.cjs +66 -51
- package/src/assets/scripts/hooks/background-memory-update +404 -95
- package/src/assets/scripts/hooks/json-helper.cjs +11 -0
- package/src/assets/scripts/hooks/json-parse +18 -3
- package/src/assets/scripts/hooks/memory-permission +358 -0
- package/src/assets/scripts/hooks/session-start-context +2 -2
- package/src/assets/scripts/hooks/session-start-memory +26 -5
- package/src/assets/scripts/lib/project-config.cjs +19 -4
- package/src/assets/scripts/resolve-settings.cjs +200 -32
- package/src/assets/skills/agent-references/SKILL.md +6 -2
- package/src/assets/skills/agent-references/references/commands/code-review-levels.md +19 -0
- package/src/assets/skills/agent-references/references/commands/implement-revalidate.md +2 -2
- package/src/assets/skills/agent-references/references/commands/plan-levels.md +40 -0
- package/src/assets/skills/agent-references/references/synthesize/planning.md +9 -22
- package/src/assets/skills/agent-references/references/synthesize/review.md +11 -11
|
@@ -35,17 +35,17 @@ Run a comprehensive code review of the current branch by spawning parallel revie
|
|
|
35
35
|
- **Exactly one listed:** load neither the skill nor the reference — that worktree is the only candidate, and Step 0c's Git agent validates its branch
|
|
36
36
|
2. **If `--path` flag provided:** use only that worktree, skip discovery
|
|
37
37
|
**`--path` validation**: Before proceeding, verify the path exists as a directory and appears in `git worktree list` output. If not: report error and stop.
|
|
38
|
-
3. **If only 1 reviewable worktree
|
|
38
|
+
3. **If only 1 reviewable worktree**: proceed as single-worktree flow — zero behavior change
|
|
39
39
|
4. **If multiple reviewable worktrees:** report "Found N worktrees with reviewable branches: {list with paths and branches}" and proceed with multi-worktree flow
|
|
40
40
|
|
|
41
|
-
#### Step 0b: Resolve the compliance lens
|
|
41
|
+
#### Step 0b: Resolve the compliance lens and gate level
|
|
42
42
|
|
|
43
|
-
**Produces:** COMPLIANCE_ACTIVE, COMPLIANCE_FRAMEWORKS
|
|
43
|
+
**Produces:** COMPLIANCE_ACTIVE, COMPLIANCE_FRAMEWORKS, GATE_LEVEL
|
|
44
44
|
|
|
45
45
|
{{settings.settings_resolve()}}
|
|
46
46
|
|
|
47
47
|
{{compliance_gate()}}
|
|
48
|
-
Keep each worktree's values for every downstream phase
|
|
48
|
+
Keep each worktree's values for every downstream phase.
|
|
49
49
|
|
|
50
50
|
#### Step 0b-ii: Resolve the evidence policy
|
|
51
51
|
|
|
@@ -87,7 +87,7 @@ Validate branch, commit if needed, push, create PR if needed.
|
|
|
87
87
|
Return: branch, base_branch, branch-slug, PR#"
|
|
88
88
|
```
|
|
89
89
|
|
|
90
|
-
In multi-worktree mode, spawn all pre-flight agents **in a single message
|
|
90
|
+
In multi-worktree mode, spawn all pre-flight agents **in a single message**.
|
|
91
91
|
|
|
92
92
|
**If BLOCKED:** In single-worktree mode, stop and report. In multi-worktree mode, report the failure but continue with other worktrees.
|
|
93
93
|
|
|
@@ -127,7 +127,7 @@ For each worktree, perform a single pass over timestamped directories:
|
|
|
127
127
|
2. Iterate once: accumulate CYCLE_NUMBER count for each directory containing `resolution-summary.md`; capture the first (most-recent) such directory as PRIOR_DIR.
|
|
128
128
|
3. If CYCLE_NUMBER = 0: set PRIOR_RESOLUTIONS=(none), CYCLE_NUMBER=1, proceed.
|
|
129
129
|
4. Otherwise: set CYCLE_NUMBER = count + 1. Read `{PRIOR_DIR}/resolution-summary.md` as PRIOR_RESOLUTIONS.
|
|
130
|
-
5. If `--full`: still load PRIOR_RESOLUTIONS
|
|
130
|
+
5. If `--full`: still load PRIOR_RESOLUTIONS.
|
|
131
131
|
|
|
132
132
|
#### Step 0e-ii: Convergence Assessment
|
|
133
133
|
|
|
@@ -169,7 +169,7 @@ For each reviewable worktree, call:
|
|
|
169
169
|
### Phase 1: Analyze Changed Files
|
|
170
170
|
|
|
171
171
|
**Produces:** REVIEW_FOCUS_LIST, DIFF_CLASS, DIFF_FILES
|
|
172
|
-
**Requires:** DIFF_RANGE, REVIEW_DIR, COMPLIANCE_ACTIVE (from Step 0b)
|
|
172
|
+
**Requires:** DIFF_RANGE, REVIEW_DIR, COMPLIANCE_ACTIVE, GATE_LEVEL (from Step 0b)
|
|
173
173
|
|
|
174
174
|
Per worktree, in order. Each `git` command here writes to a file and prints nothing.
|
|
175
175
|
|
|
@@ -185,7 +185,7 @@ git -C "{WORKTREE_PATH}" diff --name-only --no-renames {DIFF_RANGE} > "{REVIEW_D
|
|
|
185
185
|
wc -l < "{REVIEW_DIR}/paths.txt"
|
|
186
186
|
```
|
|
187
187
|
|
|
188
|
-
Read `paths.txt` once when the count is about 40 or fewer, and in ranges of about 40 lines (Read with offset and limit) when it is more.
|
|
188
|
+
Read `paths.txt` once when the count is about 40 or fewer, and in ranges of about 40 lines (Read with offset and limit) when it is more.
|
|
189
189
|
|
|
190
190
|
Set `DIFF_CLASS` by these rules, in order; the first that decides wins:
|
|
191
191
|
|
|
@@ -202,7 +202,7 @@ Each reduced class runs only its focus set, every member reading `diff.patch`:
|
|
|
202
202
|
- `tests-only`: testing, reliability, consistency, security
|
|
203
203
|
- `lockfile-only`: dependencies, security
|
|
204
204
|
|
|
205
|
-
A mixed non-code diff runs the union of the sets of the classes it holds. Language and conditional triggers inside a reduced class are suppressed
|
|
205
|
+
A mixed non-code diff runs the union of the sets of the classes it holds. Language and conditional triggers inside a reduced class are suppressed.
|
|
206
206
|
|
|
207
207
|
#### Step 1.2: Choose the focuses
|
|
208
208
|
|
|
@@ -226,13 +226,27 @@ When `DIFF_CLASS` is `code`, read the file types from the paths in `paths.txt` t
|
|
|
226
226
|
| Docs or significant code | documentation |
|
|
227
227
|
| COMPLIANCE_ACTIVE AND diff touches regulated surface | compliance |
|
|
228
228
|
|
|
229
|
-
If `COMPLIANCE_ACTIVE` AND the diff touches regulated surface (data models, auth flows, logging/observability, payments, IaC, retention):
|
|
229
|
+
If `COMPLIANCE_ACTIVE` AND the diff touches regulated surface (data models, auth flows, logging/observability, payments, IaC, retention): on a `code` diff, add `compliance`.
|
|
230
230
|
|
|
231
231
|
**Language focus stamp.** The eight language focuses — `typescript`, `react`, `accessibility`, `ui-design`, `go`, `java`, `python`, `rust` — ship with optional plugins, and the installer stamps the ones installed on this machine onto this line, rewriting it on every install and on `uninstall --plugin`:
|
|
232
232
|
|
|
233
233
|
Installed language focuses: (none)
|
|
234
234
|
|
|
235
|
-
A language focus is spawned only when its file-type condition above fires AND its name appears in that stamped line. A focus missing from the line is never spawned, even when its trigger fires.
|
|
235
|
+
A language focus is spawned only when its file-type condition above fires AND its name appears in that stamped line. A focus missing from the line is never spawned, even when its trigger fires. On a `code` diff, REVIEW_FOCUS_LIST starts with the eight core focuses. Step 1.2b may narrow them; they are never stamp-gated.
|
|
236
|
+
|
|
237
|
+
#### Step 1.2b: Narrow by gate level
|
|
238
|
+
|
|
239
|
+
**Produces:** REVIEW_FOCUS_LIST, GATE_LEVEL
|
|
240
|
+
**Requires:** REVIEW_FOCUS_LIST, DIFF_CLASS, CHANGED_PATHS, GATE_LEVEL
|
|
241
|
+
|
|
242
|
+
**Gate level.** Narrow REVIEW_FOCUS_LIST, for every class, by this worktree's `GATE_LEVEL`. `full` keeps it and reads nothing.
|
|
243
|
+
|
|
244
|
+
At `standard` or `lean`, once per run, run `d="${CLAUDE_CONFIG_DIR:-}"; case "$d" in /*) ;; *) d="$HOME/.claude" ;; esac; printf '%s\n' "$d"` in Bash and Read `<that directory>/skills/devflow:agent-references/references/commands/code-review-levels.md` with the Read tool.
|
|
245
|
+
|
|
246
|
+
- Apply each class's row to that class's own set, then take the union of the results. A row only removes focuses.
|
|
247
|
+
- If the Read fails, or a row is missing or malformed, set `GATE_LEVEL` to `full` for every worktree of this run and say `level reference unreadable: full sets applied`.
|
|
248
|
+
- Security runs at every level and in every class.
|
|
249
|
+
- Compliance keeps the trigger above at every level.
|
|
236
250
|
|
|
237
251
|
#### Step 1.3: Write the diff files
|
|
238
252
|
|
|
@@ -297,9 +311,9 @@ Pass `FEATURE_KNOWLEDGE` to all Review agents.
|
|
|
297
311
|
**Requires:** DIFF_RANGE, REVIEW_DIR, TIMESTAMP, FEATURE_KNOWLEDGE, PR_DESCRIPTION, PRIOR_RESOLUTIONS, REVIEW_FOCUS_LIST, DIFF_CLASS, DIFF_FILES
|
|
298
312
|
<!-- learning:end -->
|
|
299
313
|
|
|
300
|
-
Spawn Review agents **in a single message**,
|
|
314
|
+
Spawn Review agents **in a single message**, one per focus in REVIEW_FOCUS_LIST (max 20 per worktree):
|
|
301
315
|
|
|
302
|
-
- `code`: the 8 core reviews on the full `diff.patch
|
|
316
|
+
- `code`: the 8 core reviews on the full `diff.patch` (lean keeps 3), plus the language and conditional focuses Phase 1 added.
|
|
303
317
|
- `docs-only`, `tests-only`, `lockfile-only`: only the reduced set Phase 1 names, each reading `diff.patch`; a mixed non-code diff runs the union. No language or conditional focus is spawned, whatever its trigger.
|
|
304
318
|
|
|
305
319
|
| Focus | Runs | Pattern Skill | DIFF_FILE |
|
|
@@ -325,7 +339,7 @@ Spawn Review agents **in a single message**, for the focus set `DIFF_CLASS` sele
|
|
|
325
339
|
| documentation | conditional | devflow:documentation | diff.patch |
|
|
326
340
|
| compliance | diff-driven | devflow:compliance | diff.patch |
|
|
327
341
|
|
|
328
|
-
Review agent count: `code` runs 8 core
|
|
342
|
+
Review agent count: at `full`, `code` runs 8 core +1-12; `standard` runs up to 2 fewer; lean `code` runs 3-4; a reduced class or a mix runs 2-6.
|
|
329
343
|
|
|
330
344
|
{{compliance_focus_inject()}}
|
|
331
345
|
|
|
@@ -353,16 +367,16 @@ Follow devflow:apply-feature-knowledge for FEATURE_KNOWLEDGE — feature-specifi
|
|
|
353
367
|
IMPORTANT: Write report to {worktree_path}/.devflow/docs/reviews/{branch-slug}/{timestamp}/{focus}.md using Write tool"
|
|
354
368
|
```
|
|
355
369
|
|
|
356
|
-
In multi-worktree mode, process worktrees **sequentially
|
|
370
|
+
In multi-worktree mode, process worktrees **sequentially**: complete Phases 1-4 for one worktree before starting the next, so Review spawns never pile up.
|
|
357
371
|
|
|
358
372
|
### Phase 3: Synthesis → Review Comment (Sequential)
|
|
359
373
|
|
|
360
374
|
**Produces:** REVIEW_SUMMARY, PR_COMMENT
|
|
361
|
-
**Requires:** REVIEW_FOCUS_OUTPUTS, REVIEW_DIR, PR_INFO
|
|
375
|
+
**Requires:** REVIEW_FOCUS_OUTPUTS, REVIEW_DIR, PR_INFO, GATE_LEVEL, REVIEW_FOCUS_LIST
|
|
362
376
|
|
|
363
377
|
**WAIT** for Phase 2. For each worktree, run steps 3a and 3b in sequence:
|
|
364
378
|
|
|
365
|
-
**Step 3a — Synthesize agent** per worktree
|
|
379
|
+
**Step 3a — Synthesize agent** per worktree:
|
|
366
380
|
```
|
|
367
381
|
Agent(subagent_type="Synthesize", run_in_background=false):
|
|
368
382
|
"Mode: review
|
|
@@ -370,6 +384,8 @@ WORKTREE_PATH: {worktree_path} (omit if cwd)
|
|
|
370
384
|
REVIEW_BASE_DIR: {worktree_path}/.devflow/docs/reviews/{branch-slug}/{timestamp}
|
|
371
385
|
TIMESTAMP: {timestamp}
|
|
372
386
|
CYCLE_NUMBER: {cycle_number}
|
|
387
|
+
GATE_LEVEL: {GATE_LEVEL}
|
|
388
|
+
FOCUSES: {REVIEW_FOCUS_LIST}
|
|
373
389
|
PRIOR_RESOLUTIONS: <prior-resolution-summary>{prior_resolutions}</prior-resolution-summary>
|
|
374
390
|
Include Convergence Status section in review-summary.md.
|
|
375
391
|
Aggregate findings, determine merge recommendation.
|
|
@@ -402,8 +418,6 @@ Per worktree, after successful completion:
|
|
|
402
418
|
- Publication status: FULL (private repo) | FULL (config override) | STUB (public repository) | OFF (publication disabled by config) | STUB (visibility undeterminable) | STUB (evidence policy) (from Git agent)
|
|
403
419
|
- Artifact paths
|
|
404
420
|
|
|
405
|
-
In multi-worktree mode, report results per worktree.
|
|
406
|
-
|
|
407
421
|
## Architecture
|
|
408
422
|
|
|
409
423
|
```
|
|
@@ -411,29 +425,27 @@ In multi-worktree mode, report results per worktree.
|
|
|
411
425
|
│
|
|
412
426
|
├─ Phase 0: Worktree Discovery & Pre-flight
|
|
413
427
|
│ ├─ Step 0a: git worktree list → filter reviewable
|
|
414
|
-
│ ├─ Step 0b: Resolve the compliance lens
|
|
428
|
+
│ ├─ Step 0b: Resolve the compliance lens and gate level
|
|
415
429
|
│ ├─ Step 0c: Git agent (ensure-pr-ready) per worktree [parallel]
|
|
416
430
|
│ ├─ Step 0d: Incremental detection + timestamp setup per worktree
|
|
417
431
|
│ ├─ Step 0e-i: Load prior resolution-summary.md
|
|
418
|
-
│ ├─ Step 0e-ii: Convergence assessment (warn
|
|
432
|
+
│ ├─ Step 0e-ii: Convergence assessment (warn only)
|
|
419
433
|
│ └─ Step 0f: Resolve REVIEW_PUBLICATION per worktree (publication gate)
|
|
420
434
|
│
|
|
421
435
|
├─ Per worktree (SEQUENTIAL — one worktree at a time):
|
|
422
436
|
│ │
|
|
423
437
|
│ ├─ Phase 1: Analyze changed files
|
|
424
438
|
│ │ ├─ Classify the diff (paths.txt → DIFF_CLASS)
|
|
425
|
-
│ │ ├─ Choose the focuses (code
|
|
439
|
+
│ │ ├─ Choose the focuses (code: file types + the language stamp; all: the gate level)
|
|
426
440
|
│ │ └─ Write diff.patch and diff-{focus}.patch, by redirect
|
|
427
441
|
│ │
|
|
428
|
-
│ ├─ Phase 2: Reviews (PARALLEL within worktree)
|
|
429
|
-
│ │ ├─ code:
|
|
430
|
-
│ │ │ consistency, regression, testing, reliability (diff.patch)
|
|
431
|
-
│ │ ├─ code: + language (diff-{focus}.patch) and conditional Review agents
|
|
442
|
+
│ ├─ Phase 2: Reviews (PARALLEL within worktree), one per REVIEW_FOCUS_LIST focus
|
|
443
|
+
│ │ ├─ code: core (diff.patch), language (diff-{focus}.patch), conditional
|
|
432
444
|
│ │ └─ docs-only / tests-only / lockfile-only: the reduced set (diff.patch)
|
|
433
445
|
│ │
|
|
434
446
|
│ ├─ Phase 3: Synthesis → Review Comment (SEQUENTIAL within worktree)
|
|
435
447
|
│ │ ├─ Step 3a: Synthesize agent (mode: review, writes review-summary.md)
|
|
436
|
-
│ │ └─ Step 3b: Git agent (post-review-summary
|
|
448
|
+
│ │ └─ Step 3b: Git agent (post-review-summary)
|
|
437
449
|
│ │
|
|
438
450
|
│ └─ Phase 4: Write .last-review-head + display results
|
|
439
451
|
```
|
|
@@ -442,31 +454,27 @@ In multi-worktree mode, report results per worktree.
|
|
|
442
454
|
|
|
443
455
|
| Case | Handling |
|
|
444
456
|
|------|----------|
|
|
445
|
-
| `--full` in multi-worktree mode | Applies to all worktrees (global modifier) |
|
|
457
|
+
| `--full` in multi-worktree mode | Applies to all worktrees (global modifier). It sets the diff range, never the gate level |
|
|
446
458
|
| 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 |
|
|
447
|
-
|
|
|
448
|
-
|
|
|
449
|
-
|
|
|
450
|
-
|
|
|
451
|
-
|
|
|
452
|
-
| A
|
|
453
|
-
|
|
|
454
|
-
| Path listing above about 40 lines | The count is printed; `paths.txt` is read in ranges of about 40 lines |
|
|
459
|
+
| Docs-only diff | Its Step 1.1 set, narrowed by level |
|
|
460
|
+
| Tests-only diff | Its Step 1.1 set, narrowed by level |
|
|
461
|
+
| Lockfile-only diff | Its Step 1.1 set, narrowed by level |
|
|
462
|
+
| Mixed non-code diff | The union of the matching sets |
|
|
463
|
+
| A path matching no class pattern, or an empty path list | `code` (fail-safe) |
|
|
464
|
+
| A file moved across classes | `--no-renames` lists both paths, so a code path makes the diff `code` |
|
|
465
|
+
| Path listing above about 40 lines | Read in ranges (Step 1.1) |
|
|
455
466
|
| Language files changed, plugin not installed | The focus is absent from the stamped line: not spawned |
|
|
456
467
|
| Public repo (`auto` mode) | Git agent probes visibility, posts counts-only STUB comment; full report stays local |
|
|
457
468
|
| `reviewPublication: off` | Git agent skips posting the review comment (OFF) — except that, only when `EVIDENCE_POLICY` is `required`, Step 0f passes `stub` and a counts-only STUB comment posts |
|
|
458
469
|
|
|
459
470
|
## Backwards Compatibility
|
|
460
471
|
|
|
461
|
-
- **
|
|
462
|
-
- **Legacy flat layout**: If `{worktree}/.devflow/docs/reviews/{branch-slug}/` contains flat `*.md` files (no timestamped subdirectories), new runs create timestamped subdirectories. Old flat files remain untouched.
|
|
472
|
+
- **Gate level**: `full` runs the sets named here; the default `standard` and `lean` narrow them. `devflow gates --set full` keeps them.
|
|
463
473
|
|
|
464
474
|
## Principles
|
|
465
475
|
|
|
466
476
|
1. **Orchestration only** - Command spawns agents, doesn't do git/review work itself. The exceptions are the read-only Phase 0 probes (`git worktree list`, `git -C ... branch --show-current`, `git -C ... cat-file -t`), the bounded Phase 1 path listing (a redirect into `paths.txt`, a `wc -l` count and ranged reads) and the redirect-only patch writes (`diff.patch`, `diff-{focus}.patch`). Redirect-only writes print nothing, so no diff content reaches this thread
|
|
467
477
|
2. **Parallel, not background** - Multiple agents in one message, but `run_in_background=false` so phases complete before proceeding
|
|
468
478
|
3. **Git agent for git work** - All git operations go through Git agent, except the exceptions named in Principle 1; redirect-only writes print nothing
|
|
469
|
-
4. **
|
|
470
|
-
5. **
|
|
471
|
-
6. **Incremental by default** - Only review new changes unless `--full` specified
|
|
472
|
-
7. **Auto-discover worktrees** - One command handles all reviewable branches
|
|
479
|
+
4. **Honest reporting** - Display agent outputs directly
|
|
480
|
+
5. **Incremental by default** - Only review new changes unless `--full` specified
|
|
@@ -575,22 +575,49 @@ When WAVE mode is detected, author a workflow that wraps the single-ticket engin
|
|
|
575
575
|
|
|
576
576
|
**Wave workflow structure (author after the SINGLE engine blocks above):**
|
|
577
577
|
|
|
578
|
-
The wave workflow uses the same phases as SINGLE but wraps them in a wave loop. The integration branch is `wave/<initiative>` — the initiative slug, referenced below as `{slug}` — (or the user's current branch).
|
|
578
|
+
The wave workflow uses the same phases as SINGLE but wraps them in a wave loop. The integration branch is `wave/<initiative>` — the initiative slug, referenced below as `{slug}` — (or the user's current branch).
|
|
579
579
|
|
|
580
580
|
Wave skeleton — compact reference (see `wave_loop()` doctrine for full semantics):
|
|
581
581
|
|
|
582
582
|
```js
|
|
583
|
-
// Wave round loop: Design agent reader → per-ticket try/catch → cascade quarantine via next reader
|
|
584
583
|
// runSingleTicketEngine(args) is the SINGLE skeleton above as a function of its OWN args: the wave's
|
|
585
584
|
// args.issueNumber (the tracking issue, Pre-authoring step 5) is never in its scope.
|
|
586
585
|
const WAVE_TICKETS = [...remainingTickets]; // the pre-fetch's refs, in input order — the wave block's row order
|
|
587
|
-
const results = {}; // ticketId → its row of the workflow's return
|
|
586
|
+
const results = {}; // ticketId → its row of the workflow's return
|
|
588
587
|
// A row from an engine result: the fields step 3 after the workflow renders
|
|
589
588
|
const rowOf = (ticketId, r, merged, treeEqual = null) => ({ ticket: ticketId, ran: true, verdict: r?.verdict || r?.overallVerdict || null, merged, treeEqual, issuePrLink: r?.issuePrLink || "(none)", evaluateVerdict: r?.gate2?.evaluateVerdict, testVerdict: r?.gate2?.testVerdict, surviving: r?.survivingFindings?.length, coverageComplete: r?.reviewCoverage?.complete });
|
|
590
589
|
const MAX_ROUNDS = Math.max(10, remainingTickets.length * 2 + 5); // heuristic; always finite
|
|
591
|
-
const MERGE_SHA = /^[0-9a-f]{40}$/; // a
|
|
590
|
+
const MERGE_SHA = /^[0-9a-f]{40}$/; // a SHA as git prints it; with the checked branch, the only Git-reported values that reach a merge, Validate or undo prompt
|
|
591
|
+
const BRANCH_NAME = /^(?![-#]|(?:@|(?:FETCH_|ORIG_|MERGE_)?HEAD)$)(?!.*\.\.)[A-Za-z0-9._/+@,#-]{1,200}$/; // implement's ref allowlist; no leading - or #, no revision name, no ..: the name enters git lines
|
|
592
|
+
// One ticket's merge, post-merge Validate and undo (D-WAVE-MERGE-VALIDATE: Git validates nothing).
|
|
593
|
+
const mergeValidateUndo = async (ticketId, engineResult) => {
|
|
594
|
+
if (typeof engineResult.branch !== "string" || !BRANCH_NAME.test(engineResult.branch)) return { kept: false, reason: "ticket branch name refused: not a plain git ref name", halted: null, treeEqual: null };
|
|
595
|
+
const merge = await agent(`Merge ${engineResult.branch} to ${INTEGRATION_BRANCH} locally. Include ticket ID ${ticketId} in the merge commit message. Do not push, and run no build or test.
|
|
596
|
+
Check out ${INTEGRATION_BRANCH}, run git rev-parse ${INTEGRATION_BRANCH} as baseSha, run git rev-parse --verify --quiet refs/heads/${engineResult.branch} (on a non-zero exit return merged false, reason "no such local branch"), then run git merge --no-ff refs/heads/${engineResult.branch}. If the merge stops after it began (git rev-parse -q --verify MERGE_HEAD succeeds), run git merge --abort; if that abort fails, return merged true with no mergeSha. A merge that did not begin returns merged false with the reason.
|
|
597
|
+
Return: {"merged": true, "mergeSha": "<40-hex merge commit>", "treeEqual": <true when mergeSha^{tree} equals the tree of ${engineResult.branch}'s head>, "baseSha": "<40-hex integration HEAD before the merge>"} — or {"merged": false, "reason": "<why>"} when no merge is kept.`, { agentType: "Git" });
|
|
598
|
+
const treeEqual = merge?.merged === true && typeof merge.treeEqual === "boolean" ? merge.treeEqual : null;
|
|
599
|
+
const done = (kept, reason, halted = null) => ({ kept, reason, halted, treeEqual });
|
|
600
|
+
if (merge?.merged !== true) return done(false, merge?.reason || "merge failed");
|
|
601
|
+
const badSha = ![merge.mergeSha, merge.baseSha].every(v => MERGE_SHA.test(String(v)));
|
|
602
|
+
if (badSha || merge.mergeSha === merge.baseSha) {
|
|
603
|
+
// No usable SHA, or no commit added: stop taking merges. Fixed reasons; no rejected value is copied.
|
|
604
|
+
const reason = badSha ? "merge reported without a 40-hex mergeSha or baseSha; the integration branch may hold an unvalidated merge" : "merge added no commit, so the wave stopped: an unchanged HEAD cannot be checked. Check that the ticket branch holds its commits, then run the wave again.";
|
|
605
|
+
return done(false, reason, { ticket: ticketId, mergeSha: null, baseSha: null, reason, kind: badSha ? "bad-sha" : "unchanged" });
|
|
606
|
+
}
|
|
607
|
+
const post = await agent(`Run build, typecheck, lint, and tests on ${INTEGRATION_BRANCH} after merging ${engineResult.branch} (merge commit ${merge.mergeSha}).
|
|
608
|
+
Follow your Running commands block for every build and test command.
|
|
609
|
+
Return: {"verdict": "PASS" | "FAIL", "details": "..."}`, { agentType: "Validate" });
|
|
610
|
+
if (post?.verdict === "PASS") {
|
|
611
|
+
return done(true, "");
|
|
612
|
+
}
|
|
613
|
+
const undo = await agent(`Undo the merge ${merge.mergeSha} on ${INTEGRATION_BRANCH}, only when no remote branch contains ${merge.mergeSha}. Run these read-only checks in order; a non-zero exit or a different value means not undone: git symbolic-ref --short HEAD must print ${INTEGRATION_BRANCH}; git rev-parse refs/heads/${INTEGRATION_BRANCH} must print ${merge.mergeSha}; git rev-parse ${merge.mergeSha}^1 must print ${merge.baseSha}. Then run exactly this one command and no other that changes a branch or a remote: git reset --keep ${merge.baseSha}
|
|
614
|
+
Return: {"undone": true, "head": "<40-hex from git rev-parse refs/heads/${INTEGRATION_BRANCH}>"} — or {"undone": false, "reason": "<why>"} when you did not undo it.`, { agentType: "Git" });
|
|
615
|
+
if (undo?.undone === true && undo.head === merge.baseSha) return done(false, "post-merge build red; merge undone");
|
|
616
|
+
const reason = `post-merge build red; merge not undone (${undo?.undone === true ? "undo reported a head other than the recorded pre-merge SHA" : undo?.reason || "no reason given"})`;
|
|
617
|
+
return done(false, reason, { ticket: ticketId, mergeSha: merge.mergeSha, baseSha: merge.baseSha, reason, kind: "red" });
|
|
618
|
+
};
|
|
592
619
|
const waveState = { quarantined: [], round: 0, halted: null };
|
|
593
|
-
let reAskedThisDeadlock = false;
|
|
620
|
+
let reAskedThisDeadlock = false;
|
|
594
621
|
while (remainingTickets.length > 0 && waveState.round < MAX_ROUNDS && waveState.halted === null) {
|
|
595
622
|
waveState.round++;
|
|
596
623
|
|
|
@@ -614,56 +641,28 @@ Return: {"ready": [...ticket-ids], "blocked": [{"ticket": "id", "namedBlocker":
|
|
|
614
641
|
reAskedThisDeadlock = true; // re-ask once with vacuous-truth rule quoted verbatim
|
|
615
642
|
continue;
|
|
616
643
|
}
|
|
617
|
-
reAskedThisDeadlock = false;
|
|
644
|
+
reAskedThisDeadlock = false;
|
|
618
645
|
|
|
619
646
|
for (const ticketId of ready) {
|
|
620
647
|
try {
|
|
621
|
-
// ticketId is
|
|
622
|
-
// and its setup-task ISSUE_INPUT; the engine returns the branch that setup-task created, merged below; plans[ticketId] is its own plan, criteria and checked testPlan (Pre-authoring step 4)
|
|
648
|
+
// ticketId is this ticket's OWN ISSUE_REF (pre-fetch heading): the engine's `ticket` and setup-task ISSUE_INPUT; the engine returns the branch setup-task created, merged below; plans[ticketId] is its own plan (Pre-authoring step 4)
|
|
623
649
|
<!-- learning:on -->
|
|
624
650
|
const engineResult = await runSingleTicketEngine({ ticket: ticketId, baseBranch: INTEGRATION_BRANCH, ...(plans[ticketId] || {}), decisionsContext: DECISIONS_CONTEXT, issueRequired: ISSUE_REQUIRED, applyConventions: APPLY_CONVENTIONS, complianceFrameworks: COMPLIANCE_FRAMEWORKS, issueInput: ticketId });
|
|
625
651
|
<!-- learning:off -->
|
|
626
652
|
const engineResult = await runSingleTicketEngine({ ticket: ticketId, baseBranch: INTEGRATION_BRANCH, ...(plans[ticketId] || {}), issueRequired: ISSUE_REQUIRED, applyConventions: APPLY_CONVENTIONS, complianceFrameworks: COMPLIANCE_FRAMEWORKS, issueInput: ticketId });
|
|
627
653
|
<!-- learning:end -->
|
|
628
|
-
//
|
|
629
|
-
// PASS and UNVERIFIED merge; PARTIAL, FAIL, ESCALATED (the ticket-link and branch stops included) or no verdict quarantine.
|
|
654
|
+
// PASS and UNVERIFIED merge (verdict, or overallVerdict as the SINGLE alias); PARTIAL, FAIL, ESCALATED (the ticket-link and branch stops included) or no verdict quarantine.
|
|
630
655
|
if (["PASS", "UNVERIFIED"].includes(engineResult.verdict || engineResult.overallVerdict)) {
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
let kept = false;
|
|
635
|
-
let reason = merge?.reason || "merge failed";
|
|
636
|
-
if (merge?.merged === true && !MERGE_SHA.test(String(merge.mergeSha))) {
|
|
637
|
-
// A merge may sit on the integration branch with no SHA to validate or undo it by: stop taking merges.
|
|
638
|
-
waveState.halted = { ticket: ticketId, mergeSha: null, reason: "merge reported without a 40-hex mergeSha; the integration branch may hold an unvalidated merge" };
|
|
639
|
-
reason = waveState.halted.reason;
|
|
640
|
-
} else if (merge?.merged === true) {
|
|
641
|
-
// A merge counts as kept only when this Validate returns PASS. It always runs: treeEqual is recorded, never a reason to skip.
|
|
642
|
-
const post = await agent(`Run build, typecheck, lint, and tests on ${INTEGRATION_BRANCH} after merging ${engineResult.branch} (merge commit ${merge.mergeSha}).
|
|
643
|
-
Follow your Running commands block for every build and test command.
|
|
644
|
-
Return: {"verdict": "PASS" | "FAIL", "details": "..."}`, { agentType: "Validate" });
|
|
645
|
-
if (post?.verdict === "PASS") {
|
|
646
|
-
kept = true;
|
|
647
|
-
} else {
|
|
648
|
-
const undo = await agent(`Undo the merge ${merge.mergeSha} on ${INTEGRATION_BRANCH}, only when no remote branch contains ${merge.mergeSha} and the HEAD of ${INTEGRATION_BRANCH} still equals ${merge.mergeSha}. On the integration branch run exactly this one command and no other that changes a branch or a remote: git reset --keep ${merge.mergeSha}^1
|
|
649
|
-
Return: {"undone": true} — or {"undone": false, "reason": "<why>"} when you did not undo it.`, { agentType: "Git" });
|
|
650
|
-
if (undo?.undone === true) {
|
|
651
|
-
reason = "post-merge build red; merge undone";
|
|
652
|
-
} else {
|
|
653
|
-
// A merge that stays red would poison every later ticket: stop taking merges and rounds, and name the red HEAD.
|
|
654
|
-
reason = `post-merge build red; merge not undone (${undo?.reason || "no reason given"})`;
|
|
655
|
-
waveState.halted = { ticket: ticketId, mergeSha: merge.mergeSha, reason };
|
|
656
|
-
}
|
|
657
|
-
}
|
|
658
|
-
}
|
|
659
|
-
results[ticketId] = rowOf(ticketId, engineResult, kept, merge?.merged === true && typeof merge.treeEqual === "boolean" ? merge.treeEqual : null);
|
|
656
|
+
const { kept, reason, halted, treeEqual } = await mergeValidateUndo(ticketId, engineResult);
|
|
657
|
+
if (halted !== null) waveState.halted = halted;
|
|
658
|
+
results[ticketId] = rowOf(ticketId, engineResult, kept, treeEqual);
|
|
660
659
|
if (!kept) waveState.quarantined.push({ ticket: ticketId, reason });
|
|
661
660
|
} else {
|
|
662
661
|
results[ticketId] = rowOf(ticketId, engineResult, false);
|
|
663
662
|
waveState.quarantined.push({ ticket: ticketId, reason: engineResult.escalations?.[0]?.description || "engine fail/escalated" });
|
|
664
663
|
}
|
|
665
664
|
} catch (err) {
|
|
666
|
-
//
|
|
665
|
+
// Quarantine the ticket: the cascade reaches its dependents via the next reader round
|
|
667
666
|
results[ticketId] = rowOf(ticketId, null, false);
|
|
668
667
|
waveState.quarantined.push({ ticket: ticketId, reason: `engine crash: ${String(err)}` });
|
|
669
668
|
}
|
|
@@ -697,7 +696,7 @@ A workflow cannot pause mid-run. After the build/wave workflow returns, you (the
|
|
|
697
696
|
In WAVE mode, if no tracking-issue number was resolved in Pre-authoring step 5: state `TRACEABILITY: DEGRADED (no tracking issue for this run)` in the run summary and skip — never skip silently.
|
|
698
697
|
3. **Compose the wave PR inputs** (WAVE mode only — skip this step entirely in SINGLE mode). The workflow returned `tickets`: one entry per wave ticket, in its input order, each `{ticket, ran, verdict, merged, issuePrLink, evaluateVerdict, testVerdict, surviving, coverageComplete}`. Every value in it is agent-reported and treated as untrusted: nothing below is repaired, and no reference is ever composed from a number.
|
|
699
698
|
- **Branch check.** Run `git -C "{integration worktree root}" branch --show-current`. Only a name matching `^wave/[a-z0-9][a-z0-9-]{0,59}$` opens a wave PR, and its part after `wave/` is the `{slug}` below. Any other name: record `TRACEABILITY: DEGRADED (not a wave branch)` and go to step 4 with no wave PR.
|
|
700
|
-
- **Halted** (
|
|
699
|
+
- **Halted** (a non-null `halted`, whose `kind` is `red`, `bad-sha` or `unchanged`): record `Wave PR: skipped (<text>, wave halted at <halted.ticket>)` and go to step 4 with no wave PR. `<text>` is fixed by `kind`, and no other `halted` field is shown. `red` (a post-merge build it could not undo): `integration HEAD red at <halted.mergeSha>`. `bad-sha` (a merge without a usable SHA): `integration branch may hold an unvalidated merge`. `unchanged` (a merge that added no commit): `merge added no commit`, with the remedy to check that the ticket branch holds its commits, then run the wave again.
|
|
701
700
|
- **Nothing merged** (no entry has `merged: true`): record `Wave PR: skipped (nothing merged)` and go to step 4.
|
|
702
701
|
- Otherwise compose (a) and then (b).
|
|
703
702
|
|
|
@@ -807,4 +806,4 @@ cd "{integration worktree root}" && node "$HOME/.devflow/scripts/verify-evidence
|
|
|
807
806
|
|
|
808
807
|
### Maintenance note
|
|
809
808
|
|
|
810
|
-
This recipe
|
|
809
|
+
This recipe mirrors the `/implement` + `/code-review` + `/resolve` orchestration as of 2026-06-12. When those commands change, update it. No tooling detects drift (the LLM-vs-plumbing Iron Rule).
|
|
@@ -46,7 +46,7 @@ $ARGUMENTS
|
|
|
46
46
|
|
|
47
47
|
### Re-validation Continuation Path
|
|
48
48
|
|
|
49
|
-
When the user explicitly asks to re-validate, re-check, or re-run quality gates after making their own changes,
|
|
49
|
+
When the user explicitly asks to re-validate, re-check, or re-run quality gates after making their own changes, run `d="${CLAUDE_CONFIG_DIR:-}"; case "$d" in /*) ;; *) d="$HOME/.claude" ;; esac; printf '%s\n' "$d"` in Bash, Read `<that directory>/skills/devflow:agent-references/references/commands/implement-revalidate.md` with the Read tool and follow it. Otherwise proceed with the full pipeline below.
|
|
50
50
|
|
|
51
51
|
### Phase 1: Setup
|
|
52
52
|
|
|
@@ -56,7 +56,7 @@ When the user explicitly asks to re-validate, re-check, or re-run quality gates
|
|
|
56
56
|
**Produces:** TASK_ID, BASE_BRANCH, EXECUTION_PLAN, FEATURE_KNOWLEDGE, FEATURE_KNOWLEDGE_RULES, PR_DESCRIPTION_GUIDANCE, ISSUE_NUMBER, ISSUE_PR_LINK, EVIDENCE_POLICY, ISSUE_REQUIRED, APPLY_CONVENTIONS, REQUIRE_NON_AUTHOR_APPROVAL, PR_EXCEPTIONS, TEST_PLAN, EVIDENCE_FILE, PR_TEST_PLAN_BLOCK, REVIEW_PUBLICATION
|
|
57
57
|
<!-- learning:end -->
|
|
58
58
|
|
|
59
|
-
Record the current branch name as `BASE_BRANCH
|
|
59
|
+
Record the current branch name as `BASE_BRANCH`. Stop the run unless it matches `^[A-Za-z0-9._/+@,#-]{1,200}$`, telling the user it allows only ASCII letters, digits and `._/+@,#-`, at most 200.
|
|
60
60
|
|
|
61
61
|
{{docs_root()}}
|
|
62
62
|
|
|
@@ -114,11 +114,6 @@ The two tests this command does make are its own under every provider:
|
|
|
114
114
|
`setup-task` fetches whatever it is handed — so the command would derive a
|
|
115
115
|
branch from a failed lookup and drop the request on the floor.
|
|
116
116
|
|
|
117
|
-
The cost of the count gate is a one-word task description (`/implement refactor`)
|
|
118
|
-
reaching `setup-task` as an issue reference, where it fails the lookup and is
|
|
119
|
-
reported. That is the direction the failure has to fall: an unfetched issue is
|
|
120
|
-
visible, a silently discarded request is not.
|
|
121
|
-
|
|
122
117
|
**Capture from Git agent output** (used throughout flow):
|
|
123
118
|
- `TASK_ID`: The branch name created by Git agent (use as TASK_ID for rest of flow)
|
|
124
119
|
- `BASE_BRANCH`: Branch this feature was created from (for PR target)
|
|
@@ -127,7 +122,7 @@ visible, a silently discarded request is not.
|
|
|
127
122
|
|
|
128
123
|
{{issue_capture_contract()}}
|
|
129
124
|
|
|
130
|
-
**Ticket link, only when `ISSUE_REQUIRED` is `true`:** when the capture above holds no `ISSUE_PR_LINK` (absent, or `(none)`),
|
|
125
|
+
**Ticket link, only when `ISSUE_REQUIRED` is `true`:** when the capture above holds no `ISSUE_PR_LINK` (absent, or `(none)`), run `d="${CLAUDE_CONFIG_DIR:-}"; case "$d" in /*) ;; *) d="$HOME/.claude" ;; esac; printf '%s\n' "$d"` in Bash, Read `<that directory>/skills/devflow:agent-references/references/commands/implement-evidence-asks.md` with the Read tool (once per run), then run its ticket link ask and **Record the exception at once** as it directs, before any Code spawn. `PR_EXCEPTIONS` is `(none)` until an exception is recorded.
|
|
131
126
|
|
|
132
127
|
**Test plan.** Before any Code spawn, give the task a test plan in the evidence file `{worktree}/.devflow/docs/evidence-{branch_slug}.md` (`EVIDENCE_FILE`) — unlike the handoff file, it stays after the PR exists. It holds up to three sections, in this order and nothing else: `## Test Plan`; `## Evidence Exceptions`, a byte copy of `PR_EXCEPTIONS` present only while that is not `(none)`; and `## Claims`, always last, so every claim is appended at the end of the file. Create the file if absent; if it exists, replace its `## Test Plan` and `## Evidence Exceptions` sections and keep `## Claims` byte-identical.
|
|
133
128
|
|
|
@@ -181,14 +176,14 @@ Pass `DECISIONS_CONTEXT` to Code agent (Phase 2) and Harden agent (Phase 4).
|
|
|
181
176
|
Based on Setup context (plan document, issue body, or conversation context), use the three-strategy framework:
|
|
182
177
|
|
|
183
178
|
**Strategy Selection**:
|
|
184
|
-
- If plan document provided: use `execution-strategy` from frontmatter (
|
|
185
|
-
- Otherwise:
|
|
179
|
+
- If plan document provided: use `execution-strategy` from frontmatter (if absent, use the table below)
|
|
180
|
+
- Otherwise: SINGLE_CODE_AGENT, because there is no Subtask Breakdown to split
|
|
186
181
|
|
|
187
|
-
| Strategy | When |
|
|
188
|
-
|
|
189
|
-
| **SINGLE_CODE_AGENT** | Default. Coherent A→Z implementation |
|
|
190
|
-
| **SEQUENTIAL_CODE_AGENTS** |
|
|
191
|
-
| **PARALLEL_CODE_AGENTS** | True artifact independence (rare) |
|
|
182
|
+
| Strategy | When |
|
|
183
|
+
|----------|------|
|
|
184
|
+
| **SINGLE_CODE_AGENT** | Default. Coherent A→Z implementation |
|
|
185
|
+
| **SEQUENTIAL_CODE_AGENTS** | The plan writes >= 10 files or has >= 7 steps |
|
|
186
|
+
| **PARALLEL_CODE_AGENTS** | True artifact independence (rare) |
|
|
192
187
|
|
|
193
188
|
---
|
|
194
189
|
|
|
@@ -211,7 +206,7 @@ DECISIONS_CONTEXT: {decisions_context}
|
|
|
211
206
|
|
|
212
207
|
---
|
|
213
208
|
|
|
214
|
-
**SEQUENTIAL_CODE_AGENTS** (
|
|
209
|
+
**SEQUENTIAL_CODE_AGENTS** (>= 10 files or >= 7 steps):
|
|
215
210
|
|
|
216
211
|
Spawn Code agents one at a time. Each appends its own phase section to the handoff file, and the next reads only the section before it:
|
|
217
212
|
|
|
@@ -298,15 +293,15 @@ DECISIONS_CONTEXT: {decisions_context}
|
|
|
298
293
|
### Phase 3: Polish
|
|
299
294
|
|
|
300
295
|
**Produces:** POLISH_OUTPUT
|
|
301
|
-
**Requires:**
|
|
296
|
+
**Requires:** BASE_BRANCH
|
|
302
297
|
|
|
303
|
-
After the Code agent completes, spawn Polish agent to polish the code. The Phase 6 Validate covers its commits.
|
|
298
|
+
After the Code agent completes, spawn Polish agent to polish the code. The Phase 6 Validate covers its commits. `{branch_diff}` is the output of `git diff --name-only --diff-filter=d {BASE_BRANCH}...HEAD`, run again at each spawn.
|
|
304
299
|
|
|
305
300
|
```
|
|
306
301
|
Agent(subagent_type="Polish"):
|
|
307
302
|
"Polish recently implemented code
|
|
308
303
|
Task: {task description}
|
|
309
|
-
FILES_CHANGED: {
|
|
304
|
+
FILES_CHANGED: {branch_diff}
|
|
310
305
|
Focus on code modified by Code agent, apply project standards, enhance clarity
|
|
311
306
|
Commit any improvements with a conventional-commit message."
|
|
312
307
|
```
|
|
@@ -314,14 +309,14 @@ Commit any improvements with a conventional-commit message."
|
|
|
314
309
|
### Phase 4: Self-Review
|
|
315
310
|
|
|
316
311
|
**Produces:** HARDEN_OUTPUT
|
|
317
|
-
**Requires:**
|
|
312
|
+
**Requires:** BASE_BRANCH
|
|
318
313
|
|
|
319
314
|
After Polish agent completes, spawn Harden agent as the quality gate:
|
|
320
315
|
|
|
321
316
|
```
|
|
322
317
|
Agent(subagent_type="Harden"):
|
|
323
318
|
"TASK_DESCRIPTION: {task description}
|
|
324
|
-
FILES_CHANGED: {
|
|
319
|
+
FILES_CHANGED: {branch_diff}
|
|
325
320
|
<!-- learning:on -->
|
|
326
321
|
DECISIONS_CONTEXT: {decisions_context}
|
|
327
322
|
<!-- learning:end -->
|
|
@@ -334,7 +329,7 @@ Harden agent reports `### Status: PASS | FIXED | BLOCKED`. **If BLOCKED:** repor
|
|
|
334
329
|
### Phase 5: Alignment Check
|
|
335
330
|
|
|
336
331
|
**Produces:** ALIGNMENT_RESULT
|
|
337
|
-
**Requires:**
|
|
332
|
+
**Requires:** BASE_BRANCH, EXECUTION_PLAN
|
|
338
333
|
|
|
339
334
|
After Harden agent passes, spawn Evaluate agent to validate alignment. Evaluate agent receives `FEATURE_KNOWLEDGE_RULES` as acceptance context only; pattern and anti-pattern judgments belong to Harden agent:
|
|
340
335
|
|
|
@@ -342,7 +337,7 @@ After Harden agent passes, spawn Evaluate agent to validate alignment. Evaluate
|
|
|
342
337
|
Agent(subagent_type="Evaluate"):
|
|
343
338
|
"ORIGINAL_REQUEST: {task description or issue content}
|
|
344
339
|
EXECUTION_PLAN: {execution plan from Phase 1}
|
|
345
|
-
FILES_CHANGED: {
|
|
340
|
+
FILES_CHANGED: {branch_diff}
|
|
346
341
|
ACCEPTANCE_CRITERIA: {extracted criteria if available}
|
|
347
342
|
FEATURE_KNOWLEDGE: {feature_knowledge_rules}
|
|
348
343
|
Validate alignment with request and plan. Report ALIGNED or MISALIGNED with details."
|
|
@@ -375,11 +370,11 @@ Validate alignment with request and plan. Report ALIGNED or MISALIGNED with deta
|
|
|
375
370
|
**Produces:** VALIDATION_RESULT, VALIDATED_HEAD
|
|
376
371
|
**Requires:** BASE_BRANCH
|
|
377
372
|
|
|
378
|
-
Validate takes the one full-suite slot, after every commit it must cover: Code, Polish, Harden and the alignment fixes. After Evaluate agent passes, spawn Validate agent. `FILES_CHANGED` is the branch diff
|
|
373
|
+
Validate takes the one full-suite slot, after every commit it must cover: Code, Polish, Harden and the alignment fixes. After Evaluate agent passes, spawn Validate agent. `FILES_CHANGED` is the branch diff:
|
|
379
374
|
|
|
380
375
|
```
|
|
381
376
|
Agent(subagent_type="Validate"):
|
|
382
|
-
"FILES_CHANGED: {
|
|
377
|
+
"FILES_CHANGED: {branch_diff}
|
|
383
378
|
VALIDATION_SCOPE: full
|
|
384
379
|
Run build, typecheck, lint, test. Report pass/fail with failure details."
|
|
385
380
|
```
|
|
@@ -420,7 +415,7 @@ Run build, typecheck, lint, test. Report pass/fail with failure details."
|
|
|
420
415
|
### Phase 7: QA Testing
|
|
421
416
|
|
|
422
417
|
**Produces:** QA_RESULT
|
|
423
|
-
**Requires:**
|
|
418
|
+
**Requires:** BASE_BRANCH, EXECUTION_PLAN, TEST_PLAN, VALIDATED_HEAD
|
|
424
419
|
|
|
425
420
|
After Phase 6 passes, spawn Test agent for scenario-based acceptance testing:
|
|
426
421
|
|
|
@@ -428,7 +423,7 @@ After Phase 6 passes, spawn Test agent for scenario-based acceptance testing:
|
|
|
428
423
|
Agent(subagent_type="Test"):
|
|
429
424
|
"ORIGINAL_REQUEST: {task description or issue content}
|
|
430
425
|
EXECUTION_PLAN: {execution plan from Phase 1}
|
|
431
|
-
FILES_CHANGED: {
|
|
426
|
+
FILES_CHANGED: {branch_diff}
|
|
432
427
|
ACCEPTANCE_CRITERIA: {extracted criteria if available}
|
|
433
428
|
TEST_PLAN: {the TP lines of the evidence file's ## Test Plan section, or (none)}
|
|
434
429
|
Design and execute scenario-based acceptance tests. Report PASS or FAIL with evidence."
|
|
@@ -467,7 +462,7 @@ Run this phase only if a qa-fix committed (`git rev-parse HEAD` differs from `VA
|
|
|
467
462
|
|
|
468
463
|
```
|
|
469
464
|
Agent(subagent_type="Validate"):
|
|
470
|
-
"FILES_CHANGED: {output of `git diff --name-only VALIDATED_HEAD..HEAD`}
|
|
465
|
+
"FILES_CHANGED: {output of `git diff --name-only --diff-filter=d VALIDATED_HEAD..HEAD`}
|
|
471
466
|
VALIDATION_SCOPE: changed-only
|
|
472
467
|
Verify the qa-fix commits did not break anything."
|
|
473
468
|
```
|
|
@@ -575,7 +570,7 @@ If Phase 1 recorded an evidence exception, show its `## Evidence Exceptions` lin
|
|
|
575
570
|
/implement (orchestrator - spawns agents only)
|
|
576
571
|
│
|
|
577
572
|
├─ Re-validation Path (when user says "re-validate"/"re-check"/"re-run gates")
|
|
578
|
-
│ └─ Branch safety → skip Phase 2 →
|
|
573
|
+
│ └─ Branch safety → skip Phase 2 → record BASE_BRANCH → Phases 3-8 → Phase 9, 11, 12
|
|
579
574
|
│
|
|
580
575
|
├─ Phase 1: Setup
|
|
581
576
|
├─ Phase 2: Implement (3-strategy framework)
|