devflow-kit 3.7.0 → 3.9.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 +479 -1
- package/README.md +15 -15
- package/dist/agents/code.md +6 -8
- package/dist/agents/design.md +1 -1
- package/dist/agents/fix.md +7 -8
- package/dist/agents/git.md +3 -3
- package/dist/agents/harden.md +1 -1
- package/dist/agents/refactor.md +2 -4
- package/dist/agents/review.md +4 -4
- package/dist/agents/skim.md +2 -2
- package/dist/agents/triage.md +9 -2
- package/dist/cli/commands/capture.js +1 -1
- package/dist/cli/commands/curation-move-io.js +102 -0
- package/dist/cli/commands/curation-move-step.js +374 -0
- package/dist/cli/commands/curation.js +808 -0
- package/dist/cli/commands/gate-level-prompts.js +428 -0
- package/dist/cli/commands/gates.js +35 -11
- package/dist/cli/commands/init-seed.js +11 -8
- package/dist/cli/commands/init.js +244 -57
- package/dist/cli/commands/memory.js +60 -13
- package/dist/cli/commands/prompt-io.js +37 -0
- package/dist/cli/commands/uninstall.js +157 -17
- package/dist/cli.js +2 -2
- package/dist/commands/bug-analysis.md +25 -36
- package/dist/commands/code-review.md +40 -44
- package/dist/commands/debug.md +5 -5
- package/dist/commands/dynamic-build.md +26 -25
- package/dist/commands/dynamic-plan.md +5 -5
- package/dist/commands/dynamic-profile.md +5 -5
- package/dist/commands/dynamic-tickets.md +5 -5
- package/dist/commands/explore.md +6 -6
- package/dist/commands/implement.md +53 -82
- package/dist/commands/plan.md +6 -6
- package/dist/commands/release.md +5 -5
- package/dist/commands/research.md +6 -6
- package/dist/commands/resolve.md +39 -41
- package/dist/commands/self-review.md +5 -13
- package/dist/core/area-pause-notice.js +44 -0
- package/dist/core/assets.js +20 -20
- package/dist/core/curate-tuning-config.js +5 -6
- package/dist/core/curation-move-notice.js +84 -0
- package/dist/core/curation-move-skip.js +35 -0
- package/dist/core/curation-move.js +35 -0
- package/dist/core/curation-queue-cleanup.js +135 -0
- package/dist/core/curation-store.js +99 -0
- package/dist/core/{learning-variants.js → curation-variants.js} +65 -41
- package/dist/core/echo-value.js +11 -5
- package/dist/core/evidence-policy.js +11 -9
- package/dist/core/feature-switch.js +95 -19
- package/dist/core/fs-atomic.js +1 -1
- package/dist/core/gate-level.js +10 -2
- package/dist/core/git.js +16 -14
- package/dist/core/ledger-root.js +82 -22
- package/dist/core/linked-path.js +4 -4
- package/dist/core/manifest-lock.js +238 -0
- package/dist/core/manifest.js +58 -14
- package/dist/core/migrations.js +1 -13
- package/dist/core/observations.js +2 -2
- package/dist/core/plugins.js +19 -19
- package/dist/core/pool.js +26 -0
- package/dist/core/project-paths.js +103 -34
- package/dist/core/queue-drain.js +2 -2
- package/dist/core/tracked-areas.js +159 -0
- package/dist/core/tracker.js +1 -1
- package/dist/{learning-off → curation-off}/agents/code.md +6 -8
- package/dist/{learning-off → curation-off}/agents/fix.md +7 -8
- package/dist/{learning-off → curation-off}/agents/refactor.md +2 -4
- package/dist/{learning-off → curation-off}/agents/review.md +3 -3
- package/dist/{learning-off → curation-off}/agents/triage.md +8 -1
- package/dist/{learning-off → curation-off}/commands/bug-analysis.md +20 -31
- package/dist/{learning-off → curation-off}/commands/code-review.md +37 -41
- package/dist/{learning-off → curation-off}/commands/debug.md +2 -2
- package/dist/{learning-off → curation-off}/commands/dynamic-build.md +23 -22
- package/dist/{learning-off → curation-off}/commands/explore.md +2 -2
- package/dist/{learning-off → curation-off}/commands/implement.md +50 -79
- package/dist/{learning-off → curation-off}/commands/plan.md +2 -2
- package/dist/{learning-off → curation-off}/commands/resolve.md +36 -38
- package/dist/{learning-off → curation-off}/commands/self-review.md +2 -10
- package/dist/hud/components/{learning-counts.js → curation-counts.js} +63 -17
- package/dist/hud/config.js +1 -1
- package/dist/hud/index.js +6 -6
- package/dist/hud/render.js +3 -3
- package/dist/skills/git/references/pr/post-resolution-summary.md +12 -11
- package/dist/skills/git/references/pr/post-review-summary.md +12 -11
- package/dist/skills/git/references/pr/update-pr-evidence.md +2 -2
- package/dist/skills/git/references/pr/validate-branch.md +8 -5
- package/dist/skills/git/references/publication-gate.md +6 -7
- package/dist/skills/git/references/tracker/github/ensure-pr-ready.md +13 -5
- package/dist/skills/git/references/tracker/github/manage-debt.md +6 -2
- package/dist/skills/git/references/tracker/jira/ensure-pr-ready.md +13 -5
- package/dist/skills/git/references/tracker/jira/manage-debt.md +6 -2
- package/dist/skills/git/references/tracker/linear/ensure-pr-ready.md +13 -5
- package/dist/skills/git/references/tracker/linear/manage-debt.md +6 -2
- package/dist/targets/claude-code/{learning-install.js → curation-install.js} +85 -65
- package/dist/targets/claude-code/installer.js +15 -15
- package/dist/targets/claude-code/language-stamp.js +5 -5
- package/dist/targets/claude-code/post-install.js +2 -2
- package/dist/targets/claude-code/tracker-servers.js +1 -1
- package/package.json +3 -2
- package/src/assets/agents/_partials/_code.mds +11 -11
- package/src/assets/agents/code.mds +6 -6
- package/src/assets/agents/curate.md +8 -8
- package/src/assets/agents/debug.mds +6 -6
- package/src/assets/agents/design.mds +18 -18
- package/src/assets/agents/evaluate.md +6 -12
- package/src/assets/agents/fix.mds +7 -6
- package/src/assets/agents/git.mds +3 -3
- package/src/assets/agents/harden.mds +7 -7
- package/src/assets/agents/knowledge.mds +23 -23
- package/src/assets/agents/refactor.mds +2 -2
- package/src/assets/agents/research.mds +15 -15
- package/src/assets/agents/review.mds +43 -43
- package/src/assets/agents/skim.mds +11 -11
- package/src/assets/agents/triage.mds +29 -22
- package/src/assets/agents/validate.md +30 -50
- package/src/assets/commands/_partials/_decisions.mds +22 -20
- package/src/assets/commands/_partials/_engine.mds +8 -8
- package/src/assets/commands/_partials/_knowledge.mds +29 -15
- package/src/assets/commands/_partials/_preamble.mds +4 -4
- package/src/assets/commands/_partials/_settings.mds +3 -3
- package/src/assets/commands/_partials/_wave.mds +7 -7
- package/src/assets/commands/bug-analysis.mds +37 -48
- package/src/assets/commands/code-review.mds +53 -57
- package/src/assets/commands/debug.mds +14 -14
- package/src/assets/commands/dynamic-build.mds +38 -37
- package/src/assets/commands/dynamic-plan.mds +22 -22
- package/src/assets/commands/dynamic-profile.mds +2 -2
- package/src/assets/commands/dynamic-tickets.mds +8 -8
- package/src/assets/commands/explore.mds +20 -20
- package/src/assets/commands/implement.mds +77 -98
- package/src/assets/commands/plan.mds +27 -27
- package/src/assets/commands/release.mds +12 -12
- package/src/assets/commands/research.mds +19 -19
- package/src/assets/commands/resolve.mds +66 -60
- package/src/assets/commands/self-review.mds +20 -20
- package/src/assets/mds/git/_ops.mds +9 -2
- package/src/assets/mds/git/_ops_pr.mds +21 -11
- package/src/assets/mds/git/_ops_steps.mds +20 -4
- package/src/assets/mds/git/_pr.mds +21 -18
- package/src/assets/mds/git/_references.mds +6 -7
- package/src/assets/mds/tracker/_github.mds +1 -4
- package/src/assets/mds/tracker/_jira.mds +1 -4
- package/src/assets/mds/tracker/_linear.mds +1 -4
- package/src/assets/rules/quality.md +1 -0
- package/src/assets/scripts/ci-wait.cjs +389 -92
- package/src/assets/scripts/hooks/background-memory-update +81 -3
- package/src/assets/scripts/hooks/capture-prompt +12 -12
- package/src/assets/scripts/hooks/capture-question +11 -11
- package/src/assets/scripts/hooks/capture-turn +12 -12
- package/src/assets/scripts/hooks/{learning-lock → curation-lock} +2 -2
- package/src/assets/scripts/hooks/curation-move +293 -0
- package/src/assets/scripts/hooks/ensure-devflow-init +45 -13
- package/src/assets/scripts/hooks/ensure-proxy +4 -4
- package/src/assets/scripts/hooks/ensure-root-gitignore +4 -4
- package/src/assets/scripts/hooks/git-marker +81 -0
- package/src/assets/scripts/hooks/json-helper.cjs +176 -51
- package/src/assets/scripts/hooks/json-parse +1 -1
- package/src/assets/scripts/hooks/lib/curation-move.cjs +1582 -0
- package/src/assets/scripts/hooks/lib/{learning-store.cjs → curation-store.cjs} +308 -122
- package/src/assets/scripts/hooks/lib/decisions-format.cjs +3 -3
- package/src/assets/scripts/hooks/lib/mkdir-lock.cjs +24 -7
- package/src/assets/scripts/hooks/lib/project-paths.cjs +132 -39
- package/src/assets/scripts/hooks/lib/render-decisions.cjs +42 -22
- package/src/assets/scripts/hooks/lib/tracked-areas.cjs +452 -0
- package/src/assets/scripts/hooks/memory-permission +10 -2
- package/src/assets/scripts/hooks/memory-worker +12 -1
- package/src/assets/scripts/hooks/pre-compact-memory +17 -16
- package/src/assets/scripts/hooks/queue-append +444 -102
- package/src/assets/scripts/hooks/resolve-project-root +2 -2
- package/src/assets/scripts/hooks/session-start-context +198 -72
- package/src/assets/scripts/hooks/session-start-memory +42 -43
- package/src/assets/scripts/lib/project-config.cjs +12 -5
- package/src/assets/scripts/pr-evidence.cjs +5 -2
- package/src/assets/scripts/resolve-base.cjs +1043 -0
- package/src/assets/scripts/resolve-settings.cjs +283 -45
- package/src/assets/scripts/verify-evidence.cjs +307 -75
- package/src/assets/skills/agent-references/SKILL.md +11 -2
- package/src/assets/skills/agent-references/references/commands/implement-levels.md +29 -0
- package/src/assets/skills/agent-references/references/commands/implement-revalidate.md +6 -4
- package/src/assets/skills/agent-references/references/commands/resolve-levels.md +25 -0
- package/src/assets/skills/agent-references/references/synthesize/review.md +4 -4
- package/src/assets/skills/agent-references/references/triage/severity-tiers.md +43 -0
- package/src/assets/skills/agent-references/references/validate/passed-alone.md +14 -0
- package/src/assets/skills/apply-decisions/SKILL.md +1 -1
- package/src/assets/skills/docs-framework/SKILL.md +7 -7
- package/src/assets/skills/docs-framework/references/patterns.md +3 -4
- package/src/assets/skills/quality-gates/SKILL.md +1 -1
- package/src/assets/skills/worktree-support/references/roots.md +2 -2
- package/templates/lint-pack/.lint-pack.conf +86 -0
- package/templates/lint-pack/README.md +190 -0
- package/templates/lint-pack/lint-pack.sh +905 -0
- package/dist/cli/commands/learning.js +0 -554
- package/dist/core/learning-queue-cleanup.js +0 -27
- package/dist/core/learning-store.js +0 -61
- /package/dist/{learning-off → curation-off}/agents/debug.md +0 -0
- /package/dist/{learning-off → curation-off}/agents/design.md +0 -0
- /package/dist/{learning-off → curation-off}/agents/harden.md +0 -0
- /package/dist/{learning-off → curation-off}/agents/knowledge.md +0 -0
- /package/dist/{learning-off → curation-off}/agents/research.md +0 -0
- /package/dist/{learning-off → curation-off}/agents/skim.md +0 -0
- /package/dist/{learning-off → curation-off}/commands/dynamic-plan.md +0 -0
- /package/dist/{learning-off → curation-off}/commands/dynamic-profile.md +0 -0
- /package/dist/{learning-off → curation-off}/commands/dynamic-tickets.md +0 -0
- /package/dist/{learning-off → curation-off}/commands/release.md +0 -0
- /package/dist/{learning-off → curation-off}/commands/research.md +0 -0
|
@@ -10,7 +10,7 @@ output-dir: dist/commands
|
|
|
10
10
|
@import "./_partials/_settings.mds" as settings
|
|
11
11
|
# Code Review Command
|
|
12
12
|
|
|
13
|
-
Run a comprehensive code review of the current branch by spawning parallel review agents, then synthesizing results into PR comments.
|
|
13
|
+
Run a comprehensive code review of the current branch by spawning parallel review agents, then synthesizing results into PR comments.
|
|
14
14
|
|
|
15
15
|
## Usage
|
|
16
16
|
|
|
@@ -34,8 +34,8 @@ Run a comprehensive code review of the current branch by spawning parallel revie
|
|
|
34
34
|
- **More than one listed:** Invoke the `devflow:worktree-support` skill, then Read its `references/discovery.md` from the skill's base directory for the full 7-step algorithm; the canonical protected branch list stays in the skill. Parse the list, filter (skip protected/detached/mid-rebase), dedup by branch, sort by recent commit
|
|
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
|
-
**`--path` validation**:
|
|
38
|
-
3. **If only 1 reviewable worktree**: proceed as single-worktree flow
|
|
37
|
+
**`--path` validation**: the path must be a directory in `git worktree list` output; if not, report an error and stop.
|
|
38
|
+
3. **If only 1 reviewable worktree**: proceed as single-worktree flow
|
|
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
41
|
#### Step 0b: Resolve the compliance lens and gate level
|
|
@@ -84,20 +84,20 @@ PR_DESCRIPTION_GUIDANCE: {pr_description_guidance}
|
|
|
84
84
|
PR_TEST_PLAN_BLOCK: {PR_TEST_PLAN_BLOCK verbatim, or (none)}
|
|
85
85
|
APPLY_CONVENTIONS: {APPLY_CONVENTIONS}
|
|
86
86
|
Validate branch, commit if needed, push, create PR if needed.
|
|
87
|
-
Return: branch, base_branch, branch-slug, PR#"
|
|
87
|
+
Return: branch, base_branch, base_ref, branch-slug, PR#"
|
|
88
88
|
```
|
|
89
89
|
|
|
90
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
|
|
|
94
|
-
**Extract from response:** `branch`, `base_branch`, `branch_slug`, `pr_number` per worktree.
|
|
94
|
+
**Extract from response:** `branch`, `base_branch`, `base_ref`, `branch_slug`, `pr_number` per worktree. Stop with cause and fix when the Base line reads (rejected) or `branch_slug` does not match the slug pattern above; name the Git agent's fix, never your own, and for the slug the allowed characters, never its value. In multi-worktree mode this blocks only that worktree.
|
|
95
95
|
|
|
96
96
|
**Fetch PR body** (after extracting `pr_number`):
|
|
97
97
|
```bash
|
|
98
98
|
PR_DESCRIPTION=$(gh pr view {pr_number} --json body --jq '.body' 2>/dev/null || echo "(none)")
|
|
99
99
|
```
|
|
100
|
-
If `pr_number` is absent
|
|
100
|
+
If `pr_number` is absent, set `PR_DESCRIPTION` to `(none)`.
|
|
101
101
|
|
|
102
102
|
#### Step 0d: Incremental Detection & Timestamp Setup
|
|
103
103
|
|
|
@@ -107,26 +107,27 @@ If `pr_number` is absent or the command fails, set `PR_DESCRIPTION` to `(none)`.
|
|
|
107
107
|
For each worktree:
|
|
108
108
|
|
|
109
109
|
1. Generate timestamp: `YYYY-MM-DD_HHMM`. If directory already exists (same-minute collision), append seconds (`YYYY-MM-DD_HHMMSS`).
|
|
110
|
-
2.
|
|
111
|
-
3. Check if `{worktree}/.devflow/docs/reviews/{branch-slug}/.last-review-head` exists:
|
|
110
|
+
2. Check if `{gd}/devflow/reviews/{branch-slug}/.last-review-head` exists, `{gd}` being what `git -C "{worktree}" rev-parse --absolute-git-dir` prints:
|
|
112
111
|
- **If yes AND `--full` NOT set:**
|
|
113
|
-
-
|
|
114
|
-
- Verify reachable: `git -C {worktree} cat-file -t {sha}`
|
|
112
|
+
- The stored review head is checked as a commit ID: use it only when it is exactly 40 or 64 lowercase hex, else take the full-range path
|
|
113
|
+
- Verify reachable: `git -C "{worktree}" cat-file -t {sha}` must print `commit` (else take the full-range path)
|
|
115
114
|
- Check if SHA == current HEAD → if so, skip review: "No new commits since last review. Use --full for a full re-review."
|
|
116
115
|
- Set `DIFF_RANGE` to `{last-review-sha}...HEAD`
|
|
117
|
-
- **
|
|
118
|
-
-
|
|
116
|
+
- **Full-range path (no marker, or `--full`):**
|
|
117
|
+
- Stop as for a (rejected) Base line unless `base_ref` is 40 or 64 hex.
|
|
118
|
+
- Set `DIFF_RANGE` to `{base_ref}...HEAD`
|
|
119
|
+
3. Create timestamped review directory: `mkdir -p {worktree}/.devflow/docs/reviews/{branch-slug}/{timestamp}/`
|
|
119
120
|
|
|
120
121
|
#### Step 0e-i: Load Prior Resolution and Count Cycles
|
|
121
122
|
|
|
122
123
|
**Produces:** PRIOR_RESOLUTIONS, CYCLE_NUMBER
|
|
123
124
|
**Requires:** BRANCH_INFO
|
|
124
125
|
|
|
125
|
-
For each worktree
|
|
126
|
-
1. List timestamped directories
|
|
127
|
-
2. Iterate once:
|
|
126
|
+
For each worktree:
|
|
127
|
+
1. List the timestamped directories: `ls -1d {worktree}/.devflow/docs/reviews/{branch-slug}/20* 2>/dev/null | sort -r`
|
|
128
|
+
2. Iterate once: count each directory containing `resolution-summary.md` as CYCLE_NUMBER; capture the first (newest) as PRIOR_DIR.
|
|
128
129
|
3. If CYCLE_NUMBER = 0: set PRIOR_RESOLUTIONS=(none), CYCLE_NUMBER=1, proceed.
|
|
129
|
-
4. Otherwise: set CYCLE_NUMBER = count + 1. Read `{PRIOR_DIR}/resolution-summary.md` as PRIOR_RESOLUTIONS.
|
|
130
|
+
4. Otherwise: set CYCLE_NUMBER = count + 1. Read `{PRIOR_DIR}/resolution-summary.md` as PRIOR_RESOLUTIONS minus each section from a heading line (fenced or not) with the word `Private` (any case) not followed by a letter or digit, to the next unfenced heading with as many `#` as its start or fewer, else at end of file. Close any fence it leaves open. When unsure, cut more; if the cut fails, PRIOR_RESOLUTIONS=(none).
|
|
130
131
|
5. If `--full`: still load PRIOR_RESOLUTIONS.
|
|
131
132
|
|
|
132
133
|
#### Step 0e-ii: Convergence Assessment
|
|
@@ -144,7 +145,7 @@ MAX_REVIEW_CYCLES = 10
|
|
|
144
145
|
- `deferred_count` = the Deferred row value (= FIX_SEPARATE + TECH_DEBT); By Design and Escalated are excluded from the fp_ratio denominator
|
|
145
146
|
- fp_ratio = fp_count / (fp_count + fixed_count + deferred_count)
|
|
146
147
|
- If denominator = 0: fp_ratio = 0, skip warning
|
|
147
|
-
- If parsing fails: fp_ratio = 0, skip warning; note in output: "Warning: Could not parse Statistics table
|
|
148
|
+
- If parsing fails: fp_ratio = 0, skip warning; note in output: "Warning: Could not parse Statistics table. Convergence tracking degraded."
|
|
148
149
|
3. If fp_ratio > 0.7 AND CYCLE_NUMBER >= 3:
|
|
149
150
|
Warn in output: "⚠️ Convergence: {ratio}% false positives in cycle {N-1}. Consider merging or manual inspection."
|
|
150
151
|
Continue with review.
|
|
@@ -182,10 +183,11 @@ List the changed paths into `{REVIEW_DIR}/paths.txt` and print only the line cou
|
|
|
182
183
|
|
|
183
184
|
```bash
|
|
184
185
|
git -C "{WORKTREE_PATH}" diff --name-only --no-renames {DIFF_RANGE} > "{REVIEW_DIR}/paths.txt"
|
|
186
|
+
echo "exit=$?"
|
|
185
187
|
wc -l < "{REVIEW_DIR}/paths.txt"
|
|
186
188
|
```
|
|
187
189
|
|
|
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.
|
|
190
|
+
The `exit=` line is the diff's. A non-zero diff exit stops. 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
191
|
|
|
190
192
|
Set `DIFF_CLASS` by these rules, in order; the first that decides wins:
|
|
191
193
|
|
|
@@ -259,7 +261,7 @@ Write `diff.patch` once per worktree, by redirect:
|
|
|
259
261
|
git -C "{WORKTREE_PATH}" diff --no-color --no-ext-diff --no-textconv {DIFF_RANGE} > "{REVIEW_DIR}/diff.patch"
|
|
260
262
|
```
|
|
261
263
|
|
|
262
|
-
It holds the whole diff of `DIFF_RANGE`. On a `code` diff, add one patch for each language focus in REVIEW_FOCUS_LIST, by the same command with quoted pathspecs from this table:
|
|
264
|
+
It holds the whole diff of `DIFF_RANGE`. A non-zero exit of any patch write stops. On a `code` diff, add one patch for each language focus in REVIEW_FOCUS_LIST, by the same command with quoted pathspecs from this table:
|
|
263
265
|
|
|
264
266
|
```bash
|
|
265
267
|
git -C "{WORKTREE_PATH}" diff --no-color --no-ext-diff --no-textconv {DIFF_RANGE} -- '<pathspec>' ... > "{REVIEW_DIR}/diff-{focus}.patch"
|
|
@@ -277,39 +279,39 @@ git -C "{WORKTREE_PATH}" diff --no-color --no-ext-diff --no-textconv {DIFF_RANGE
|
|
|
277
279
|
|
|
278
280
|
The core, database, dependencies, documentation and compliance focuses, and every reduced-class focus, read `diff.patch`. A language focus sees only its own extensions and reaches anything else through `DIFF_RANGE`. Set `DIFF_FILES` to the files written. They live in `REVIEW_DIR`, under the gitignored `.devflow/` tree, with `paths.txt`: never committed, posted or passed to the Git agent.
|
|
279
281
|
|
|
280
|
-
<!--
|
|
282
|
+
<!-- curation:on -->
|
|
281
283
|
### Phase 1b: Load Decisions Index
|
|
282
|
-
<!--
|
|
284
|
+
<!-- curation:off -->
|
|
283
285
|
### Phase 1b: Load Context
|
|
284
|
-
<!--
|
|
286
|
+
<!-- curation:end -->
|
|
285
287
|
|
|
286
|
-
<!--
|
|
288
|
+
<!-- curation:on -->
|
|
287
289
|
**Produces:** DECISIONS_CONTEXT, FEATURE_KNOWLEDGE, FEATURE_KNOWLEDGE_RULES, COMPLIANCE_FRAMEWORKS (carried from Step 0b)
|
|
288
|
-
<!--
|
|
290
|
+
<!-- curation:off -->
|
|
289
291
|
**Produces:** FEATURE_KNOWLEDGE, FEATURE_KNOWLEDGE_RULES, COMPLIANCE_FRAMEWORKS (carried from Step 0b)
|
|
290
|
-
<!--
|
|
292
|
+
<!-- curation:end -->
|
|
291
293
|
|
|
292
294
|
{{decisions_load()}}
|
|
293
|
-
<!--
|
|
295
|
+
<!-- curation:on -->
|
|
294
296
|
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.
|
|
295
297
|
|
|
296
|
-
<!--
|
|
298
|
+
<!-- curation:end -->
|
|
297
299
|
{{knowledge_load()}}
|
|
298
300
|
|
|
299
|
-
<!--
|
|
301
|
+
<!-- curation:on -->
|
|
300
302
|
Pass `FEATURE_KNOWLEDGE` to all Review agents alongside `DECISIONS_CONTEXT`.
|
|
301
|
-
<!--
|
|
303
|
+
<!-- curation:off -->
|
|
302
304
|
Pass `FEATURE_KNOWLEDGE` to all Review agents.
|
|
303
|
-
<!--
|
|
305
|
+
<!-- curation:end -->
|
|
304
306
|
|
|
305
307
|
### Phase 2: Run Reviews (Parallel)
|
|
306
308
|
|
|
307
309
|
**Produces:** REVIEW_FOCUS_OUTPUTS
|
|
308
|
-
<!--
|
|
310
|
+
<!-- curation:on -->
|
|
309
311
|
**Requires:** DIFF_RANGE, REVIEW_DIR, TIMESTAMP, DECISIONS_CONTEXT, FEATURE_KNOWLEDGE, PR_DESCRIPTION, PRIOR_RESOLUTIONS, REVIEW_FOCUS_LIST, DIFF_CLASS, DIFF_FILES
|
|
310
|
-
<!--
|
|
312
|
+
<!-- curation:off -->
|
|
311
313
|
**Requires:** DIFF_RANGE, REVIEW_DIR, TIMESTAMP, FEATURE_KNOWLEDGE, PR_DESCRIPTION, PRIOR_RESOLUTIONS, REVIEW_FOCUS_LIST, DIFF_CLASS, DIFF_FILES
|
|
312
|
-
<!--
|
|
314
|
+
<!-- curation:end -->
|
|
313
315
|
|
|
314
316
|
Spawn Review agents **in a single message**, one per focus in REVIEW_FOCUS_LIST (max 20 per worktree):
|
|
315
317
|
|
|
@@ -339,7 +341,7 @@ Spawn Review agents **in a single message**, one per focus in REVIEW_FOCUS_LIST
|
|
|
339
341
|
| documentation | conditional | devflow:documentation | diff.patch |
|
|
340
342
|
| compliance | diff-driven | devflow:compliance | diff.patch |
|
|
341
343
|
|
|
342
|
-
Review agent count:
|
|
344
|
+
Review agent count: `code` runs 8 core +1-12 at `full`, up to 2 fewer at `standard`, 3-4 at lean; a reduced class or a mix runs 2-6.
|
|
343
345
|
|
|
344
346
|
{{compliance_focus_inject()}}
|
|
345
347
|
|
|
@@ -352,22 +354,22 @@ PR: #{pr_number}, Base: {base_branch}
|
|
|
352
354
|
WORKTREE_PATH: {worktree_path} (omit if cwd)
|
|
353
355
|
DIFF_FILE: {diff_file} (absolute: {REVIEW_DIR}/diff.patch, or {REVIEW_DIR}/diff-{focus}.patch for a language focus, per the table)
|
|
354
356
|
DIFF_RANGE: {DIFF_RANGE} (information only)
|
|
355
|
-
<!--
|
|
357
|
+
<!-- curation:on -->
|
|
356
358
|
DECISIONS_CONTEXT: {decisions_context}
|
|
357
|
-
<!--
|
|
359
|
+
<!-- curation:end -->
|
|
358
360
|
FEATURE_KNOWLEDGE: {feature_knowledge}
|
|
359
361
|
PR_DESCRIPTION: <pr-description>{pr_description}</pr-description>
|
|
360
362
|
PRIOR_RESOLUTIONS: <prior-resolution-summary>{prior_resolutions}</prior-resolution-summary>
|
|
361
363
|
{COMPLIANCE_FOCUS_DIRECTIVE} (compliance focus only)
|
|
362
364
|
If PRIOR_RESOLUTIONS is not (none), follow Cross-Cycle Awareness in review.md.
|
|
363
|
-
<!--
|
|
365
|
+
<!-- curation:on -->
|
|
364
366
|
Follow devflow:apply-decisions to scan the index and Read full ADR/PF bodies on demand.
|
|
365
|
-
<!--
|
|
367
|
+
<!-- curation:end -->
|
|
366
368
|
Follow devflow:apply-feature-knowledge for FEATURE_KNOWLEDGE — feature-specific patterns and anti-patterns inform findings.
|
|
367
369
|
IMPORTANT: Write report to {worktree_path}/.devflow/docs/reviews/{branch-slug}/{timestamp}/{focus}.md using Write tool"
|
|
368
370
|
```
|
|
369
371
|
|
|
370
|
-
In multi-worktree mode, process worktrees **sequentially**:
|
|
372
|
+
In multi-worktree mode, process worktrees **sequentially**: Phases 1-4 for each.
|
|
371
373
|
|
|
372
374
|
### Phase 3: Synthesis → Review Comment (Sequential)
|
|
373
375
|
|
|
@@ -402,7 +404,7 @@ CYCLE_NUMBER: {cycle_number}
|
|
|
402
404
|
REVIEW_TIMESTAMP: {timestamp}
|
|
403
405
|
REVIEW_PUBLICATION: {REVIEW_PUBLICATION}
|
|
404
406
|
WORKTREE_PATH: {worktree_path} (omit if cwd)
|
|
405
|
-
Posts the consolidated review-summary comment (marker-deduped
|
|
407
|
+
Posts the consolidated review-summary comment (marker-deduped on the cycle+timestamp pair)."
|
|
406
408
|
```
|
|
407
409
|
|
|
408
410
|
### Phase 4: Write Review Head Marker & Report
|
|
@@ -410,34 +412,29 @@ Posts the consolidated review-summary comment (marker-deduped by the operation o
|
|
|
410
412
|
**Requires:** BRANCH_INFO, REVIEW_DIR
|
|
411
413
|
|
|
412
414
|
Per worktree, after successful completion:
|
|
413
|
-
1.
|
|
415
|
+
1. In one Bash call run `M="$(git -C "{worktree_path}" rev-parse --absolute-git-dir)/devflow/reviews/{branch-slug}" && mkdir -p "$M" && git -C "{worktree_path}" rev-parse HEAD > "$M/.last-review-head"`. A failed or refused write never stops the run and is not retried another way.
|
|
414
416
|
2. Display results from all agents:
|
|
415
417
|
- Merge recommendation (from Synthesize agent)
|
|
416
418
|
- Issue counts by category (🔴 blocking / ⚠️ should-fix / ℹ️ pre-existing)
|
|
417
419
|
- Review comment status: POSTED / POSTED+TRUNCATED (body exceeded 60k after redaction) / SKIPPED (D7 dedup) / DEGRADED (from Git)
|
|
418
420
|
- 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)
|
|
421
|
+
- Any base `TRACEABILITY: DEGRADED` line from Step 0c, as returned
|
|
419
422
|
- Artifact paths
|
|
420
423
|
|
|
421
424
|
## Architecture
|
|
422
425
|
|
|
423
426
|
```
|
|
424
|
-
/code-review
|
|
427
|
+
/code-review
|
|
425
428
|
│
|
|
426
|
-
├─ Phase 0: Worktree Discovery & Pre-flight
|
|
427
|
-
│ ├─ Step 0a: git worktree list → filter reviewable
|
|
429
|
+
├─ Phase 0: Worktree Discovery & Pre-flight, Steps 0a-0f (Git agent per worktree, parallel)
|
|
428
430
|
│ ├─ Step 0b: Resolve the compliance lens and gate level
|
|
429
|
-
│ ├─ Step 0c: Git agent (ensure-pr-ready) per worktree [parallel]
|
|
430
|
-
│ ├─ Step 0d: Incremental detection + timestamp setup per worktree
|
|
431
|
-
│ ├─ Step 0e-i: Load prior resolution-summary.md
|
|
432
|
-
│ ├─ Step 0e-ii: Convergence assessment (warn only)
|
|
433
|
-
│ └─ Step 0f: Resolve REVIEW_PUBLICATION per worktree (publication gate)
|
|
434
431
|
│
|
|
435
|
-
├─ Per worktree (SEQUENTIAL
|
|
432
|
+
├─ Per worktree (SEQUENTIAL):
|
|
436
433
|
│ │
|
|
437
434
|
│ ├─ Phase 1: Analyze changed files
|
|
438
435
|
│ │ ├─ Classify the diff (paths.txt → DIFF_CLASS)
|
|
439
|
-
│ │ ├─ Choose the focuses
|
|
440
|
-
│ │ └─ Write diff.patch and diff-{focus}.patch
|
|
436
|
+
│ │ ├─ Choose the focuses
|
|
437
|
+
│ │ └─ Write diff.patch and diff-{focus}.patch
|
|
441
438
|
│ │
|
|
442
439
|
│ ├─ Phase 2: Reviews (PARALLEL within worktree), one per REVIEW_FOCUS_LIST focus
|
|
443
440
|
│ │ ├─ code: core (diff.patch), language (diff-{focus}.patch), conditional
|
|
@@ -455,7 +452,7 @@ Per worktree, after successful completion:
|
|
|
455
452
|
| Case | Handling |
|
|
456
453
|
|------|----------|
|
|
457
454
|
| `--full` in multi-worktree mode | Applies to all worktrees (global modifier). It sets the diff range, never the gate level |
|
|
458
|
-
| Review comment already posted | Git agent matches its own marker on the `{cycle, timestamp}` pair → skip silently (D7)
|
|
455
|
+
| Review comment already posted | Git agent matches its own marker on the `{cycle, timestamp}` pair → skip silently (D7) |
|
|
459
456
|
| Docs-only diff | Its Step 1.1 set, narrowed by level |
|
|
460
457
|
| Tests-only diff | Its Step 1.1 set, narrowed by level |
|
|
461
458
|
| Lockfile-only diff | Its Step 1.1 set, narrowed by level |
|
|
@@ -464,8 +461,7 @@ Per worktree, after successful completion:
|
|
|
464
461
|
| A file moved across classes | `--no-renames` lists both paths, so a code path makes the diff `code` |
|
|
465
462
|
| Path listing above about 40 lines | Read in ranges (Step 1.1) |
|
|
466
463
|
| Language files changed, plugin not installed | The focus is absent from the stamped line: not spawned |
|
|
467
|
-
|
|
|
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 |
|
|
464
|
+
| `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 unless no public text remains |
|
|
469
465
|
|
|
470
466
|
## Backwards Compatibility
|
|
471
467
|
|
|
@@ -473,8 +469,8 @@ Per worktree, after successful completion:
|
|
|
473
469
|
|
|
474
470
|
## Principles
|
|
475
471
|
|
|
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
|
|
472
|
+
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`, `git -C ... rev-parse`), the bounded Phase 1 path listing and the writes (`diff.patch`, `diff-{focus}.patch`, the marker and its `mkdir -p`). These writes print nothing
|
|
477
473
|
2. **Parallel, not background** - Multiple agents in one message, but `run_in_background=false` so phases complete before proceeding
|
|
478
|
-
3. **Git agent for git work** - All git operations go through Git agent, except the exceptions named in Principle 1;
|
|
474
|
+
3. **Git agent for git work** - All git operations go through Git agent, except the exceptions named in Principle 1; its writes print nothing
|
|
479
475
|
4. **Honest reporting** - Display agent outputs directly
|
|
480
476
|
5. **Incremental by default** - Only review new changes unless `--full` specified
|
|
@@ -34,16 +34,16 @@ $ARGUMENTS
|
|
|
34
34
|
|
|
35
35
|
## Phases
|
|
36
36
|
|
|
37
|
-
<!--
|
|
37
|
+
<!-- curation:on -->
|
|
38
38
|
### Phase 1: Load Decisions Index (Orchestrator-Local)
|
|
39
|
-
<!--
|
|
39
|
+
<!-- curation:off -->
|
|
40
40
|
### Phase 1: Resolve Settings
|
|
41
|
-
<!--
|
|
41
|
+
<!-- curation:end -->
|
|
42
42
|
|
|
43
|
-
<!--
|
|
43
|
+
<!-- curation:on -->
|
|
44
44
|
**Produces:** DECISIONS_CONTEXT
|
|
45
45
|
|
|
46
|
-
<!--
|
|
46
|
+
<!-- curation:end -->
|
|
47
47
|
{{settings.settings_resolve()}}
|
|
48
48
|
|
|
49
49
|
From the same line: {{compliance.compliance_frameworks()}}
|
|
@@ -53,18 +53,18 @@ From the same line: {{compliance.compliance_frameworks()}}
|
|
|
53
53
|
Phase 7 passes `COMPLIANCE_DIRECTIVE` to the Code agent that implements the fix, on a line of its own.
|
|
54
54
|
|
|
55
55
|
{{decisions_load()}}
|
|
56
|
-
<!--
|
|
56
|
+
<!-- curation:on -->
|
|
57
57
|
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.
|
|
58
58
|
|
|
59
|
-
<!--
|
|
59
|
+
<!-- curation:end -->
|
|
60
60
|
**No up-front feature knowledge load** — debug investigation workers read code directly to avoid confirmation bias. Feature knowledge is only written back at the end if the investigation surfaced durable, cross-cutting knowledge.
|
|
61
61
|
|
|
62
62
|
### Phase 2: Context Gathering
|
|
63
63
|
|
|
64
64
|
**Produces:** HYPOTHESES, BUG_CONTEXT
|
|
65
|
-
<!--
|
|
65
|
+
<!-- curation:on -->
|
|
66
66
|
**Requires:** DECISIONS_CONTEXT
|
|
67
|
-
<!--
|
|
67
|
+
<!-- curation:end -->
|
|
68
68
|
|
|
69
69
|
If `COMMAND_INPUT` opens with a candidate issue reference, fetch the issue:
|
|
70
70
|
|
|
@@ -211,9 +211,9 @@ Ask user via AskUserQuestion: "Want me to implement this fix?"
|
|
|
211
211
|
TASK_DESCRIPTION: Implement the fix for this root cause: {bug description}
|
|
212
212
|
EXECUTION_PLAN: {Root Cause, Key Findings and Recommended Fix from Phase 6, with their file:line references}
|
|
213
213
|
PUSH: false
|
|
214
|
-
<!--
|
|
214
|
+
<!-- curation:on -->
|
|
215
215
|
DECISIONS_CONTEXT: {decisions_context}
|
|
216
|
-
<!--
|
|
216
|
+
<!-- curation:end -->
|
|
217
217
|
FEATURE_KNOWLEDGE: (none)
|
|
218
218
|
{COMPLIANCE_DIRECTIVE}"
|
|
219
219
|
```
|
|
@@ -227,11 +227,11 @@ Ask user via AskUserQuestion: "Want me to implement this fix?"
|
|
|
227
227
|
```
|
|
228
228
|
/debug (orchestrator)
|
|
229
229
|
│
|
|
230
|
-
<!--
|
|
230
|
+
<!-- curation:on -->
|
|
231
231
|
├─ Phase 1: Load Decisions Index (Orchestrator-Local)
|
|
232
|
-
<!--
|
|
232
|
+
<!-- curation:off -->
|
|
233
233
|
├─ Phase 1: Resolve Settings
|
|
234
|
-
<!--
|
|
234
|
+
<!-- curation:end -->
|
|
235
235
|
│ └─ No up-front feature knowledge load (avoids confirmation bias in investigators)
|
|
236
236
|
│
|
|
237
237
|
├─ Phase 2: Context gathering
|
|
@@ -75,12 +75,12 @@ Pass it as `complianceFrameworks` when invoking the workflow; the engine builds
|
|
|
75
75
|
|
|
76
76
|
`{integration worktree root}` is the toplevel of the checkout the integration branch is checked out in: `{worktree}` unless the wave runs in a linked worktree.
|
|
77
77
|
|
|
78
|
-
<!--
|
|
78
|
+
<!-- curation:on -->
|
|
79
79
|
**1. Apply decisions context**
|
|
80
80
|
|
|
81
81
|
Apply the `devflow:apply-decisions` algorithm to the DECISIONS_CONTEXT loaded by the decisions step above: scan the index, Read relevant entries, note the verbatim ADR/PF IDs you will inject into Code agent prompts.
|
|
82
82
|
|
|
83
|
-
<!--
|
|
83
|
+
<!-- curation:end -->
|
|
84
84
|
**2. Read budget**
|
|
85
85
|
|
|
86
86
|
Note the `budget` value from the Workflow tool context (or default to "medium" if not provided). This governs Review agent roster size and verification vote count.
|
|
@@ -158,9 +158,9 @@ const TICKET = args.ticket || args[0] || "see task description";
|
|
|
158
158
|
const PLAN = args.plan || null;
|
|
159
159
|
const CRITERIA = args.criteria || null;
|
|
160
160
|
const TEST_PLAN = args.testPlan || null; // the plan's checked TP lines, one string (Pre-authoring step 4)
|
|
161
|
-
<!--
|
|
161
|
+
<!-- curation:on -->
|
|
162
162
|
const DECISIONS_CONTEXT = args.decisionsContext || ""; // injected before authoring
|
|
163
|
-
<!--
|
|
163
|
+
<!-- curation:end -->
|
|
164
164
|
const ISSUE_INPUT = args.issueInput || args.issueNumber || "(none)"; // this ticket's OWN raw reference (Pre-authoring step 5; a wave passes issueInput) — setup-task's input, never a Code agent's
|
|
165
165
|
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
|
|
166
166
|
const APPLY_CONVENTIONS = String(args.applyConventions) === "false" ? "false" : "true";
|
|
@@ -175,7 +175,7 @@ TASK_DESCRIPTION: ${TICKET}
|
|
|
175
175
|
ISSUE_REQUIRED: ${ISSUE_REQUIRED}
|
|
176
176
|
APPLY_CONVENTIONS: ${APPLY_CONVENTIONS}
|
|
177
177
|
${ISSUE_INPUT !== "(none)" ? "ISSUE_INPUT: " + ISSUE_INPUT : ""}
|
|
178
|
-
Return: {"branch": "<the - **Branch name**: value under your ### Branch, or (none)>", "issueId": "<the - **Issue ID**: value under your ### Handoff Values, or (none)>", "prLinkLine": "<the - **PR link line**: value, or (none)>"}`, { agentType: "Git" })
|
|
178
|
+
Return: {"branch": "<the - **Branch name**: value under your ### Branch, or (none)>", "issueId": "<the - **Issue ID**: value under your ### Handoff Values, or (none)>", "prLinkLine": "<the - **PR link line**: value, or (none)>", "baseSha": "<the 40 or 64 hex git rev-parse HEAD prints before step 4>"}`, { agentType: "Git" })
|
|
179
179
|
);
|
|
180
180
|
|
|
181
181
|
// The ticket's own Handoff Values, read from setup-task's Output — never derived from ISSUE_INPUT.
|
|
@@ -185,6 +185,7 @@ const ISSUE_NUMBER = ISSUE_ID_SHAPE.test(String(setup?.issueId ?? "")) ? setup.i
|
|
|
185
185
|
const ISSUE_PR_LINK = setup?.prLinkLine || "(none)"; // "(none)" ⇒ the wave PR carries no closing reference for this ticket
|
|
186
186
|
// The branch setup-task created, as it reported it: every later phase and the merge use it. The engine never names one.
|
|
187
187
|
const BRANCH = typeof setup?.branch === "string" && setup.branch.trim() !== "" && setup.branch.trim() !== "(none)" ? setup.branch : "(none)";
|
|
188
|
+
const BASE_SHA = /^(?:[0-9a-f]{40}|[0-9a-f]{64})$/.test(String(setup?.baseSha ?? "")) ? setup.baseSha : "(none)"; // the commit the ticket branch was forked from
|
|
188
189
|
|
|
189
190
|
// Ticket-link stop, before implement. The workflow cannot ask, so it never records an exception: it stops.
|
|
190
191
|
if (ISSUE_REQUIRED === "true" && ISSUE_NUMBER === "(none)") {
|
|
@@ -196,6 +197,11 @@ if (BRANCH === "(none)") {
|
|
|
196
197
|
return { ticket: TICKET, branch: BRANCH, verdict: "ESCALATED", issueId: ISSUE_NUMBER, issuePrLink: ISSUE_PR_LINK, escalations: [{ type: "branch-missing", description: "setup-task reported no branch name — check its Output, then re-run" }] };
|
|
197
198
|
}
|
|
198
199
|
|
|
200
|
+
// Base stop: every review range starts at the commit the ticket branch was forked from.
|
|
201
|
+
if (BASE_SHA === "(none)") {
|
|
202
|
+
return { ticket: TICKET, branch: BRANCH, verdict: "ESCALATED", issueId: ISSUE_NUMBER, issuePrLink: ISSUE_PR_LINK, escalations: [{ type: "base-missing", description: "setup-task reported no base commit — check its Output, then re-run" }] };
|
|
203
|
+
}
|
|
204
|
+
|
|
199
205
|
// Phase 2: Implement
|
|
200
206
|
await phase("implement", () =>
|
|
201
207
|
agent(`OPERATION: implement
|
|
@@ -205,11 +211,11 @@ ${TICKET}
|
|
|
205
211
|
|
|
206
212
|
${PLAN ? `Implementation plan:\n${PLAN}` : "No plan provided — use best judgment."}
|
|
207
213
|
|
|
208
|
-
<!--
|
|
214
|
+
<!-- curation:on -->
|
|
209
215
|
Relevant architectural decisions (apply devflow:apply-decisions algorithm):
|
|
210
216
|
${DECISIONS_CONTEXT}
|
|
211
217
|
|
|
212
|
-
<!--
|
|
218
|
+
<!-- curation:end -->
|
|
213
219
|
${COMPLIANCE_DIRECTIVE}
|
|
214
220
|
|
|
215
221
|
When you build or run tests to verify your work, follow your Running commands block.
|
|
@@ -244,9 +250,9 @@ Return: {"verdict": "PASS" | "FAIL", "details": "..."}`, { agentType: "Validate"
|
|
|
244
250
|
await agent(`OPERATION: validation-fix
|
|
245
251
|
Fix the validation failures on branch ${BRANCH}:
|
|
246
252
|
${failureDetails}
|
|
247
|
-
<!--
|
|
253
|
+
<!-- curation:on -->
|
|
248
254
|
DECISIONS_CONTEXT: ${DECISIONS_CONTEXT}
|
|
249
|
-
<!--
|
|
255
|
+
<!-- curation:end -->
|
|
250
256
|
${COMPLIANCE_DIRECTIVE}
|
|
251
257
|
Commit fixes with conventional-commit message.`, { agentType: "Fix" });
|
|
252
258
|
const recheck = await agent(`Re-run build, typecheck, lint, tests on branch ${BRANCH} after fix attempt ${attempt} (follow your Running commands block).
|
|
@@ -287,9 +293,9 @@ Return: {"verdict": "PASS" | "FAIL", "rationale": "..."} — FAIL if either answ
|
|
|
287
293
|
await agent(`OPERATION: alignment-fix
|
|
288
294
|
Fix the alignment issues identified by the Evaluate agent on branch ${BRANCH}:
|
|
289
295
|
${evaluation?.rationale || "see the Evaluate agent's report"}
|
|
290
|
-
<!--
|
|
296
|
+
<!-- curation:on -->
|
|
291
297
|
DECISIONS_CONTEXT: ${DECISIONS_CONTEXT}
|
|
292
|
-
<!--
|
|
298
|
+
<!-- curation:end -->
|
|
293
299
|
${COMPLIANCE_DIRECTIVE}
|
|
294
300
|
Self-verify your fix compiles, following your Running commands block. Commit fixes.`, { agentType: "Fix" });
|
|
295
301
|
evalVerdict = "FAIL-FIXED"; // issues found, fixes applied, not re-evaluated by design
|
|
@@ -309,9 +315,9 @@ Cover: functionality, API contracts, performance, and cover every TEST_PLAN scen
|
|
|
309
315
|
await agent(`OPERATION: qa-fix
|
|
310
316
|
Fix the failing acceptance test scenarios on branch ${BRANCH}:
|
|
311
317
|
${testResult.failures}
|
|
312
|
-
<!--
|
|
318
|
+
<!-- curation:on -->
|
|
313
319
|
DECISIONS_CONTEXT: ${DECISIONS_CONTEXT}
|
|
314
|
-
<!--
|
|
320
|
+
<!-- curation:end -->
|
|
315
321
|
${COMPLIANCE_DIRECTIVE}
|
|
316
322
|
Self-verify your fix compiles and the scenarios pass, following your Running commands block. Commit fixes.`, { agentType: "Fix" });
|
|
317
323
|
testVerdict = "FAIL-FIXED"; // issues found, fixes applied, not re-evaluated by design
|
|
@@ -323,10 +329,9 @@ Self-verify your fix compiles and the scenarios pass, following your Running com
|
|
|
323
329
|
|
|
324
330
|
// Phase 5: Review → verify → fix (single pass)
|
|
325
331
|
const reviewResult = await phase("review", async () => {
|
|
326
|
-
// Review scope: the entire branch diff from the
|
|
327
|
-
// Review agents diff the branch against its merge-base with the default branch.
|
|
332
|
+
// Review scope: the entire branch diff, from the commit the ticket branch was forked from to HEAD.
|
|
328
333
|
// The pass runs exactly ONCE.
|
|
329
|
-
const reviewScope = `Review the full branch diff on branch ${BRANCH}
|
|
334
|
+
const reviewScope = `Review the full branch diff on branch ${BRANCH}.\nDIFF_RANGE: ${BASE_SHA}...HEAD\n`;
|
|
330
335
|
|
|
331
336
|
// Review agent focus list (order = index mapping for dead-reviewer detection)
|
|
332
337
|
const reviewFocuses = ["security", "architecture", "performance", "complexity", "consistency", "regression", "testing", "reliability"];
|
|
@@ -370,13 +375,12 @@ Focus discipline: ${focus}. Return: {"focus": "${focus}", "reviewed": true, "fil
|
|
|
370
375
|
return { survivingFindings: [], fixedFindings: [], coverageGaps };
|
|
371
376
|
}
|
|
372
377
|
|
|
373
|
-
// Adversarial
|
|
374
|
-
// Panel asks perspective-diverse questions over the WHOLE finding set (not one agent per finding).
|
|
375
|
-
// A finding survives if >50% of panel agents CONFIRM it.
|
|
378
|
+
// Adversarial panel over the WHOLE finding set (not one agent per finding): >50% CONFIRMED survives
|
|
376
379
|
const VERIFY_PANEL = 3;
|
|
377
380
|
const panels = await parallel(
|
|
378
381
|
Array.from({ length: VERIFY_PANEL }, (_, lens) => () =>
|
|
379
382
|
agent(`Adversarially verify all ${allFindings.length} findings on branch ${BRANCH}.
|
|
383
|
+
DIFF_RANGE: ${BASE_SHA}...HEAD
|
|
380
384
|
Lens ${lens + 1} of ${VERIFY_PANEL}:
|
|
381
385
|
${["Does each finding actually reproduce in the current code? Hunt for findings that describe patterns not present in the diff.",
|
|
382
386
|
"Is each finding a real issue or a false positive in context? Consider intent, surrounding code, and project conventions.",
|
|
@@ -394,16 +398,13 @@ ${JSON.stringify(allFindings.map((f, i) => ({ index: i, description: f.descripti
|
|
|
394
398
|
panels.filter(p => (p.verdicts || []).find(v => v.index === i)?.verdict === "CONFIRMED").length > VERIFY_PANEL / 2
|
|
395
399
|
);
|
|
396
400
|
|
|
397
|
-
// No confirmed findings
|
|
401
|
+
// No confirmed findings: coverageGaps carry forward and block PASS downstream
|
|
398
402
|
if (confirmedFindings.length === 0) {
|
|
399
403
|
return { survivingFindings: [], fixedFindings: [], coverageGaps };
|
|
400
404
|
}
|
|
401
405
|
|
|
402
|
-
//
|
|
403
|
-
//
|
|
404
|
-
// concurrent same-file edits cause index contention and lost fixes).
|
|
405
|
-
// Sub-batches for DISTINCT files run in parallel (different code areas — safe per concurrency doctrine).
|
|
406
|
-
// A finding with no file field gets its own singleton group (unknown scope — never mix with known files).
|
|
406
|
+
// Sub-batches (max 5 findings): same file in sequence, distinct files in parallel.
|
|
407
|
+
// A finding with no file is a singleton group.
|
|
407
408
|
const MAX_BATCH = 5; // max 5 findings per sub-batch
|
|
408
409
|
const fileGroups = {};
|
|
409
410
|
for (let fi = 0; fi < confirmedFindings.length; fi++) {
|
|
@@ -413,9 +414,7 @@ ${JSON.stringify(allFindings.map((f, i) => ({ index: i, description: f.descripti
|
|
|
413
414
|
fileGroups[key].push(f);
|
|
414
415
|
}
|
|
415
416
|
|
|
416
|
-
// One entry per
|
|
417
|
-
// Distinct-file groups are paced in chunks of FIX_CHUNK — same pacing bar as the Review spawn
|
|
418
|
-
// path — to avoid launching all Code agents at once on a large branch (reliability: explicit bound).
|
|
417
|
+
// One entry per file; FIX_CHUNK chunks bound concurrent Code agents
|
|
419
418
|
const FIX_CHUNK = 5;
|
|
420
419
|
// issue-fix SCOPE per finding: CRITICAL or HIGH takes the Careful protocol (failing regression test first); anything else is Standard.
|
|
421
420
|
const CAREFUL_SEVERITIES = new Set(["critical", "high"]);
|
|
@@ -429,9 +428,9 @@ ISSUES:
|
|
|
429
428
|
${chunk.map((f, n) => `${n + 1}. ${f.file ? `${f.file}${f.line ? `:${f.line}` : ""} — ` : ""}${f.description} (${f.severity})`).join("\n")}
|
|
430
429
|
SCOPE: ${chunk.map((f, n) => `${n + 1}=${CAREFUL_SEVERITIES.has(String(f.severity).toLowerCase()) ? "Careful" : "Standard"}`).join(", ")}
|
|
431
430
|
PUSH: false
|
|
432
|
-
<!--
|
|
431
|
+
<!-- curation:on -->
|
|
433
432
|
DECISIONS_CONTEXT: ${DECISIONS_CONTEXT}
|
|
434
|
-
<!--
|
|
433
|
+
<!-- curation:end -->
|
|
435
434
|
${COMPLIANCE_DIRECTIVE}
|
|
436
435
|
Fix all findings in this batch. Self-verify your fix compiles, following your Running commands block. Commit with conventional-commit message.
|
|
437
436
|
Return: {"status": "fixed"|"blocked", "commitShas": ["<sha>"], "unresolved": ["<description of any finding that could not be fixed>"]}`, { agentType: "Code" });
|
|
@@ -490,9 +489,9 @@ Return: {"verdict": "PASS" | "FAIL", "details": "..."}`, { agentType: "Validate"
|
|
|
490
489
|
await agent(`OPERATION: validation-fix
|
|
491
490
|
Fix the final validation failures on branch ${BRANCH}:
|
|
492
491
|
${failureDetails}
|
|
493
|
-
<!--
|
|
492
|
+
<!-- curation:on -->
|
|
494
493
|
DECISIONS_CONTEXT: ${DECISIONS_CONTEXT}
|
|
495
|
-
<!--
|
|
494
|
+
<!-- curation:end -->
|
|
496
495
|
${COMPLIANCE_DIRECTIVE}
|
|
497
496
|
Self-verify your fix compiles. Commit fixes with conventional-commit message.`, { agentType: "Fix" });
|
|
498
497
|
const recheck = await agent(`Re-run build, typecheck, lint, tests on branch ${BRANCH} (final gate, after fix attempt ${attempt}; follow your Running commands block).
|
|
@@ -588,7 +587,7 @@ const results = {}; // ticketId → its row of the workflow's return
|
|
|
588
587
|
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 });
|
|
589
588
|
const MAX_ROUNDS = Math.max(10, remainingTickets.length * 2 + 5); // heuristic; always finite
|
|
590
589
|
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}$/; //
|
|
590
|
+
const BRANCH_NAME = /^(?![-#]|(?:@|(?:FETCH_|ORIG_|MERGE_)?HEAD)$)(?!.*\.\.)[A-Za-z0-9._/+@,#-]{1,200}$/; // STRICT_NAME_RE's deliberate variant, less its origin/ refusal; the name enters git lines
|
|
592
591
|
// One ticket's merge, post-merge Validate and undo (D-WAVE-MERGE-VALIDATE: Git validates nothing).
|
|
593
592
|
const mergeValidateUndo = async (ticketId, engineResult) => {
|
|
594
593
|
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 };
|
|
@@ -646,11 +645,11 @@ Return: {"ready": [...ticket-ids], "blocked": [{"ticket": "id", "namedBlocker":
|
|
|
646
645
|
for (const ticketId of ready) {
|
|
647
646
|
try {
|
|
648
647
|
// 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)
|
|
649
|
-
<!--
|
|
648
|
+
<!-- curation:on -->
|
|
650
649
|
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 });
|
|
651
|
-
<!--
|
|
650
|
+
<!-- curation:off -->
|
|
652
651
|
const engineResult = await runSingleTicketEngine({ ticket: ticketId, baseBranch: INTEGRATION_BRANCH, ...(plans[ticketId] || {}), issueRequired: ISSUE_REQUIRED, applyConventions: APPLY_CONVENTIONS, complianceFrameworks: COMPLIANCE_FRAMEWORKS, issueInput: ticketId });
|
|
653
|
-
<!--
|
|
652
|
+
<!-- curation:end -->
|
|
654
653
|
// 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.
|
|
655
654
|
if (["PASS", "UNVERIFIED"].includes(engineResult.verdict || engineResult.overallVerdict)) {
|
|
656
655
|
const { kept, reason, halted, treeEqual } = await mergeValidateUndo(ticketId, engineResult);
|
|
@@ -761,12 +760,14 @@ Do NOT ask questions mid-workflow — that is impossible (F4). The workflow only
|
|
|
761
760
|
|
|
762
761
|
7. **Wave PR evidence** — only when step 6 reported the wave PR, after it; it never blocks, and every outcome below goes into the run summary. Take `{n}` from step 6's `- **PR**: #{n}` line when `{n}` matches `^[1-9][0-9]{0,9}$` as a whole; no such line ⇒ record `TRACEABILITY: DEGRADED (wave PR number not captured)` and skip this step. `PR_TEST_PLAN_BLOCK` `(none)` ⇒ record `Wave evidence: skipped (no wave test plan)` and skip it.
|
|
763
762
|
|
|
763
|
+
**Changed files.** Take `{base_ref}` from step 6's `- **Base ref**:` line; only when it is 40 or 64 lowercase hex, run `git -C "{integration worktree root}" diff --name-only --diff-filter=d {base_ref}...HEAD; echo "exit=$?"`. Unless it ran and printed `exit=0`, record `TRACEABILITY: DEGRADED (wave base unusable)` and skip this step.
|
|
764
|
+
|
|
764
765
|
**(a) Test the wave.** Spawn one Test agent on the integration worktree with the wave test plan — the TP lines of the `## Test Plan` section step 3(b) wrote to `{integration worktree root}/.devflow/docs/evidence-wave-{slug}.md`:
|
|
765
766
|
|
|
766
767
|
```
|
|
767
768
|
Agent(subagent_type="Test"):
|
|
768
769
|
"ORIGINAL_REQUEST: the merged tickets of wave/{slug}, as the wave test plan names them
|
|
769
|
-
FILES_CHANGED: {the
|
|
770
|
+
FILES_CHANGED: {the file list that diff printed}
|
|
770
771
|
TEST_PLAN: {the TP lines of the wave evidence file's ## Test Plan section}
|
|
771
772
|
WORKTREE_PATH: {integration worktree root}
|
|
772
773
|
Cover every TEST_PLAN line on the integration branch as it stands. Report PASS or FAIL with evidence."
|