devflow-kit 3.7.0 → 3.8.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 +359 -1
- package/README.md +11 -11
- package/dist/agents/code.md +2 -4
- package/dist/agents/design.md +1 -1
- package/dist/agents/fix.md +6 -7
- package/dist/agents/git.md +1 -1
- 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 +2 -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/{learning.js → curation.js} +302 -99
- package/dist/cli/commands/gate-level-prompts.js +426 -0
- package/dist/cli/commands/gates.js +34 -11
- package/dist/cli/commands/init-seed.js +11 -8
- package/dist/cli/commands/init.js +240 -54
- package/dist/cli/commands/memory.js +2 -2
- package/dist/cli/commands/prompt-io.js +37 -0
- package/dist/cli/commands/uninstall.js +81 -9
- package/dist/cli.js +2 -2
- package/dist/commands/bug-analysis.md +24 -35
- package/dist/commands/code-review.md +32 -36
- package/dist/commands/debug.md +4 -4
- package/dist/commands/dynamic-build.md +25 -24
- package/dist/commands/dynamic-plan.md +4 -4
- package/dist/commands/dynamic-profile.md +4 -4
- package/dist/commands/dynamic-tickets.md +4 -4
- package/dist/commands/explore.md +5 -5
- package/dist/commands/implement.md +52 -81
- package/dist/commands/plan.md +5 -5
- package/dist/commands/release.md +4 -4
- package/dist/commands/research.md +5 -5
- package/dist/commands/resolve.md +28 -30
- package/dist/commands/self-review.md +4 -12
- 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 +36 -0
- package/dist/core/curation-move.js +35 -0
- package/dist/core/curation-queue-cleanup.js +134 -0
- package/dist/core/curation-store.js +98 -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 +1 -1
- 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 +15 -15
- 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 +35 -0
- package/dist/core/tracker.js +1 -1
- package/dist/{learning-off → curation-off}/agents/code.md +2 -4
- package/dist/{learning-off → curation-off}/agents/fix.md +6 -7
- 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 +1 -1
- package/dist/{learning-off → curation-off}/commands/bug-analysis.md +20 -31
- package/dist/{learning-off → curation-off}/commands/code-review.md +29 -33
- package/dist/{learning-off → curation-off}/commands/debug.md +1 -1
- package/dist/{learning-off → curation-off}/commands/dynamic-build.md +22 -21
- package/dist/{learning-off → curation-off}/commands/explore.md +1 -1
- package/dist/{learning-off → curation-off}/commands/implement.md +49 -78
- package/dist/{learning-off → curation-off}/commands/plan.md +1 -1
- package/dist/{learning-off → curation-off}/commands/resolve.md +25 -27
- package/dist/{learning-off → curation-off}/commands/self-review.md +1 -9
- package/dist/hud/components/{learning-counts.js → curation-counts.js} +36 -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/validate-branch.md +8 -5
- package/dist/skills/git/references/tracker/github/ensure-pr-ready.md +13 -5
- package/dist/skills/git/references/tracker/jira/ensure-pr-ready.md +13 -5
- package/dist/skills/git/references/tracker/linear/ensure-pr-ready.md +13 -5
- 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 +2 -2
- 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/fix.mds +6 -5
- package/src/assets/agents/git.mds +1 -1
- 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 +22 -22
- package/src/assets/agents/validate.md +13 -26
- package/src/assets/commands/_partials/_decisions.mds +13 -13
- 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 +2 -2
- 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 +46 -50
- 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 +56 -50
- package/src/assets/commands/self-review.mds +20 -20
- package/src/assets/mds/git/_ops.mds +3 -1
- package/src/assets/mds/git/_ops_pr.mds +1 -1
- package/src/assets/mds/git/_ops_steps.mds +10 -4
- package/src/assets/mds/git/_pr.mds +7 -4
- package/src/assets/rules/quality.md +1 -0
- package/src/assets/scripts/hooks/background-memory-update +2 -2
- 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 +134 -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} +242 -118
- 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 +34 -22
- package/src/assets/scripts/hooks/lib/tracked-areas.cjs +259 -0
- package/src/assets/scripts/hooks/memory-worker +1 -1
- package/src/assets/scripts/hooks/pre-compact-memory +6 -16
- package/src/assets/scripts/hooks/queue-append +228 -103
- package/src/assets/scripts/hooks/resolve-project-root +2 -2
- package/src/assets/scripts/hooks/session-start-context +143 -69
- package/src/assets/scripts/hooks/session-start-memory +3 -43
- package/src/assets/scripts/lib/project-config.cjs +12 -5
- package/src/assets/scripts/resolve-base.cjs +1043 -0
- package/src/assets/scripts/resolve-settings.cjs +42 -18
- package/src/assets/skills/agent-references/SKILL.md +5 -2
- package/src/assets/skills/agent-references/references/commands/implement-levels.md +27 -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 +24 -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/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
|
@@ -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."
|
|
@@ -11,12 +11,12 @@ output-dir: dist/commands
|
|
|
11
11
|
@import "./_partials/_settings.mds" as settings
|
|
12
12
|
{{authoring_preamble()}}
|
|
13
13
|
|
|
14
|
-
<!--
|
|
14
|
+
<!-- curation:on -->
|
|
15
15
|
### Settings line
|
|
16
16
|
|
|
17
17
|
{{settings.settings_resolve()}}
|
|
18
18
|
|
|
19
|
-
<!--
|
|
19
|
+
<!-- curation:end -->
|
|
20
20
|
{{authoring_decisions()}}
|
|
21
21
|
---
|
|
22
22
|
|
|
@@ -52,12 +52,12 @@ Before authoring, verify:
|
|
|
52
52
|
|
|
53
53
|
Pass `{worktree}` to the workflow as its `root` argument, and its `slug` argument: the `{slug}` of the ticket directory (`tickets/{slug}/{ts}/`) when that is the ticket source, otherwise `wave`.
|
|
54
54
|
|
|
55
|
-
<!--
|
|
55
|
+
<!-- curation:on -->
|
|
56
56
|
**1. Apply decisions context**
|
|
57
57
|
|
|
58
58
|
Apply the `devflow:apply-decisions` algorithm to the DECISIONS_CONTEXT loaded by the decisions step above: scan the index, Read relevant entries, note verbatim ADR/PF IDs to inject into Design agent prompts.
|
|
59
59
|
|
|
60
|
-
<!--
|
|
60
|
+
<!-- curation:end -->
|
|
61
61
|
**2. Read the preference profile**
|
|
62
62
|
|
|
63
63
|
Check whether `~/.devflow/preference-profile.md` exists:
|
|
@@ -122,9 +122,9 @@ export const meta = {
|
|
|
122
122
|
// AskUserQuestion happens at the command boundary after this workflow returns — NOT here.
|
|
123
123
|
|
|
124
124
|
const ticketSource = args.ticketSource || args[0] || "see task description";
|
|
125
|
-
<!--
|
|
125
|
+
<!-- curation:on -->
|
|
126
126
|
const DECISIONS_CONTEXT = args.decisionsContext || ""; // injected before authoring
|
|
127
|
-
<!--
|
|
127
|
+
<!-- curation:end -->
|
|
128
128
|
const PREFERENCE_PROFILE = args.preferenceProfile || ""; // injected before authoring
|
|
129
129
|
const TP_CONTRACT = args.tpContract || ""; // the "Test-plan line (TP)" contract below — its paragraph and four bullets — passed verbatim as tpContract when invoking the workflow, never pasted into this script (it holds backticks)
|
|
130
130
|
const slug = args.slug || "wave";
|
|
@@ -146,9 +146,9 @@ const plans = await phase("plan-parallel", () =>
|
|
|
146
146
|
parallel((tickets || []).map(ticket => () =>
|
|
147
147
|
agent(`Write an implementation plan for this ticket.
|
|
148
148
|
Ticket: ${JSON.stringify(ticket)}
|
|
149
|
-
<!--
|
|
149
|
+
<!-- curation:on -->
|
|
150
150
|
Decisions context (apply devflow:apply-decisions; a plan file can be posted to the tracker, so state each decision in words, never by ID): ${DECISIONS_CONTEXT}
|
|
151
|
-
<!--
|
|
151
|
+
<!-- curation:end -->
|
|
152
152
|
The plan must cover: approach overview, affected files and modules, key design decisions, implementation sequence (what to build first), risks and mitigations, and any open questions you cannot resolve from the ticket alone.
|
|
153
153
|
Write a thorough but tight plan — every section must earn its place for a Code agent who has no other context.
|
|
154
154
|
Return: { ticketTitle, planMarkdown, openDecisions (array of genuine unknowns requiring user input) }.`, { agentType: "Design" })
|
|
@@ -192,9 +192,9 @@ Return: { ticketTitle, improvements (array), acceptanceCriteria (array of number
|
|
|
192
192
|
const crossCritic = await phase("cross-plan-critic", () =>
|
|
193
193
|
agent(`Cross-plan conflict audit.
|
|
194
194
|
All ticket plans + challenged criteria: ${JSON.stringify(challenged)}
|
|
195
|
-
<!--
|
|
195
|
+
<!-- curation:on -->
|
|
196
196
|
Decisions context: ${DECISIONS_CONTEXT}
|
|
197
|
-
<!--
|
|
197
|
+
<!-- curation:end -->
|
|
198
198
|
|
|
199
199
|
Audit:
|
|
200
200
|
1. API conflicts: two tickets defining the same API differently (different signatures, return types, error codes).
|
|
@@ -202,11 +202,11 @@ Audit:
|
|
|
202
202
|
3. Undeclared dependencies: ticket A's plan implicitly requires something ticket B provides, but no dependency is declared.
|
|
203
203
|
4. Scope overlap: two tickets both claim ownership of the same module or behavior.
|
|
204
204
|
|
|
205
|
-
<!--
|
|
205
|
+
<!-- curation:on -->
|
|
206
206
|
For each conflict found: state which two tickets are involved, describe the conflict precisely, and propose a resolution aligned with the decisions ledger.
|
|
207
|
-
<!--
|
|
207
|
+
<!-- curation:off -->
|
|
208
208
|
For each conflict found: state which two tickets are involved, describe the conflict precisely, and propose a resolution.
|
|
209
|
-
<!--
|
|
209
|
+
<!-- curation:end -->
|
|
210
210
|
|
|
211
211
|
Return: { conflicts (array of {tickets, conflictDescription, proposedResolution}), planAmendments (array of {ticketTitle, amendment}) }.`, { agentType: "Design" })
|
|
212
212
|
);
|
|
@@ -243,26 +243,26 @@ For each ticket, write ${OUTDIR}/{ticket-slug}-plan.md, {ticket-slug} being the
|
|
|
243
243
|
- ## Acceptance Criteria (numbered, positive + negative)
|
|
244
244
|
- ## Test Plan — the challenger's testPlan lines, verbatim, one per line, and nothing else: no prose, no blank line between them, no setup or outcome
|
|
245
245
|
- ## Test Scenarios — one line per TP, in TP order: TP-n: its setup, then its expected outcome, from testScenarios
|
|
246
|
-
<!--
|
|
246
|
+
<!-- curation:on -->
|
|
247
247
|
- ## Auto-Resolved Decisions (if any — list each as: decision → resolution → source, naming a recorded decision in words, never by ID)
|
|
248
|
-
<!--
|
|
248
|
+
<!-- curation:off -->
|
|
249
249
|
- ## Auto-Resolved Decisions (if any — list each as: decision → resolution → source)
|
|
250
|
-
<!--
|
|
250
|
+
<!-- curation:end -->
|
|
251
251
|
|
|
252
252
|
Then write ${OUTDIR}/DECISIONS-NEEDED.md:
|
|
253
|
-
<!--
|
|
253
|
+
<!-- curation:on -->
|
|
254
254
|
- ## Auto-Resolved Decisions — list each silently-resolved decision as: decision → resolution → source (preference profile / ADR-NNN), so auto-resolution is auditable and reversible. If none, write "None."
|
|
255
|
-
<!--
|
|
255
|
+
<!-- curation:off -->
|
|
256
256
|
- ## Auto-Resolved Decisions — list each silently-resolved decision as: decision → resolution → source (preference profile), so auto-resolution is auditable and reversible. If none, write "None."
|
|
257
|
-
<!--
|
|
257
|
+
<!-- curation:end -->
|
|
258
258
|
- ## Decisions Needed
|
|
259
259
|
- One section per open decision: what the decision is, why it matters, what options exist.
|
|
260
260
|
- Include cross-plan conflicts that were not auto-resolved.
|
|
261
|
-
<!--
|
|
261
|
+
<!-- curation:on -->
|
|
262
262
|
- If no decisions needed, write: "No open decisions — all settled by preference profile or existing ADRs."
|
|
263
|
-
<!--
|
|
263
|
+
<!-- curation:off -->
|
|
264
264
|
- If no decisions needed, write: "No open decisions — all settled by the preference profile."
|
|
265
|
-
<!--
|
|
265
|
+
<!-- curation:end -->
|
|
266
266
|
|
|
267
267
|
Return: { planPaths (array), decisionsNeededPath (string), decisionsNeededCount (number) }.`, { agentType: "Synthesize" })
|
|
268
268
|
);
|
|
@@ -7,12 +7,12 @@ output-dir: dist/commands
|
|
|
7
7
|
@import "./_partials/_settings.mds" as settings
|
|
8
8
|
{{authoring_preamble()}}
|
|
9
9
|
|
|
10
|
-
<!--
|
|
10
|
+
<!-- curation:on -->
|
|
11
11
|
### Settings line
|
|
12
12
|
|
|
13
13
|
{{settings.settings_resolve()}}
|
|
14
14
|
|
|
15
|
-
<!--
|
|
15
|
+
<!-- curation:end -->
|
|
16
16
|
{{authoring_decisions()}}
|
|
17
17
|
---
|
|
18
18
|
|
|
@@ -12,12 +12,12 @@ output-dir: dist/commands
|
|
|
12
12
|
@import "./_partials/_settings.mds" as settings
|
|
13
13
|
{{authoring_preamble()}}
|
|
14
14
|
|
|
15
|
-
<!--
|
|
15
|
+
<!-- curation:on -->
|
|
16
16
|
### Settings line
|
|
17
17
|
|
|
18
18
|
{{settings.settings_resolve()}}
|
|
19
19
|
|
|
20
|
-
<!--
|
|
20
|
+
<!-- curation:end -->
|
|
21
21
|
{{authoring_decisions()}}
|
|
22
22
|
---
|
|
23
23
|
|
|
@@ -61,12 +61,12 @@ Before you write the workflow script:
|
|
|
61
61
|
|
|
62
62
|
Pass `{worktree}` to the workflow as its `root` argument.
|
|
63
63
|
|
|
64
|
-
<!--
|
|
64
|
+
<!-- curation:on -->
|
|
65
65
|
**1. Apply decisions context**
|
|
66
66
|
|
|
67
67
|
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 Design agent prompts.
|
|
68
68
|
|
|
69
|
-
<!--
|
|
69
|
+
<!-- curation:end -->
|
|
70
70
|
**2. Read and distill the initiative**
|
|
71
71
|
|
|
72
72
|
Read or note the user's input:
|
|
@@ -103,9 +103,9 @@ export const meta = {
|
|
|
103
103
|
const candidates = args.candidates || []; // [{title, summary, wave, dependsOn}]
|
|
104
104
|
const initiative = args.initiative || args[0] || "see task description";
|
|
105
105
|
const constraints = args.constraints || "";
|
|
106
|
-
<!--
|
|
106
|
+
<!-- curation:on -->
|
|
107
107
|
const DECISIONS_CONTEXT = args.decisionsContext || ""; // injected before authoring
|
|
108
|
-
<!--
|
|
108
|
+
<!-- curation:end -->
|
|
109
109
|
const slug = args.slug || initiative.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+/, '').slice(0, 50).replace(/-+$/, '') || 'untitled';
|
|
110
110
|
const now = new Date(), two = (n) => String(n).padStart(2, '0');
|
|
111
111
|
const ts = `${now.getFullYear()}-${two(now.getMonth() + 1)}-${two(now.getDate())}_${two(now.getHours())}${two(now.getMinutes())}`;
|
|
@@ -118,9 +118,9 @@ const drafts = await phase("draft", () =>
|
|
|
118
118
|
agent(`Draft ticket for initiative: "${initiative}"
|
|
119
119
|
Ticket: ${JSON.stringify(c)}
|
|
120
120
|
Constraints: ${constraints}
|
|
121
|
-
<!--
|
|
121
|
+
<!-- curation:on -->
|
|
122
122
|
Decisions context (apply devflow:apply-decisions; the ticket is filed to the tracker, so state each decision in words, never by ID): ${DECISIONS_CONTEXT}
|
|
123
|
-
<!--
|
|
123
|
+
<!-- curation:end -->
|
|
124
124
|
Write the ticket body following the ticket_body_template structure (Wave/Depends-on header, Summary, Scope with In/Out + anti-features, Invariants, numbered Acceptance Criteria with at least one negative criterion, Open Questions).
|
|
125
125
|
Return a JSON object with: title (string), summary (string), wave (number), dependsOn (array), bodyMarkdown (string), openQuestions (array).`, { agentType: "Design" })
|
|
126
126
|
))
|
|
@@ -32,34 +32,34 @@ $ARGUMENTS
|
|
|
32
32
|
|
|
33
33
|
## Phases
|
|
34
34
|
|
|
35
|
-
<!--
|
|
35
|
+
<!-- curation:on -->
|
|
36
36
|
### Phase 1: Load Decisions (Orchestrator-Local)
|
|
37
|
-
<!--
|
|
37
|
+
<!-- curation:off -->
|
|
38
38
|
### Phase 1: Resolve Settings
|
|
39
|
-
<!--
|
|
39
|
+
<!-- curation:end -->
|
|
40
40
|
|
|
41
|
-
<!--
|
|
41
|
+
<!-- curation:on -->
|
|
42
42
|
**Produces:** DECISIONS_CONTEXT
|
|
43
43
|
|
|
44
|
-
<!--
|
|
44
|
+
<!-- curation:end -->
|
|
45
45
|
{{settings.settings_resolve()}}
|
|
46
46
|
|
|
47
47
|
{{decisions_load()}}
|
|
48
|
-
<!--
|
|
48
|
+
<!-- curation:on -->
|
|
49
49
|
The orchestrator uses `DECISIONS_CONTEXT` locally when framing exploration — prior decisions and pitfalls suggest specific areas to investigate. Follow `devflow:apply-decisions` to Read full entry bodies on demand. **Do NOT pass `DECISIONS_CONTEXT` to Explore sub-agents** — decisions context stays in the orchestrator, not in the investigation workers.
|
|
50
50
|
|
|
51
|
-
<!--
|
|
51
|
+
<!-- curation:end -->
|
|
52
52
|
**No up-front feature knowledge load** — explore investigation workers read code directly to avoid confirmation bias. Feature knowledge is only created as a write-back at the end, after exploration is complete.
|
|
53
53
|
|
|
54
54
|
### Phase 2: Orient
|
|
55
55
|
|
|
56
56
|
**Produces:** ORIENT_OUTPUT
|
|
57
57
|
|
|
58
|
-
<!--
|
|
59
|
-
Spawn `Agent(subagent_type="Skim")` with `
|
|
60
|
-
<!--
|
|
58
|
+
<!-- curation:on -->
|
|
59
|
+
Spawn `Agent(subagent_type="Skim")` with `CURATION` from the settings line, to get codebase overview relevant to the exploration question:
|
|
60
|
+
<!-- curation:off -->
|
|
61
61
|
Spawn `Agent(subagent_type="Skim")` to get codebase overview relevant to the exploration question:
|
|
62
|
-
<!--
|
|
62
|
+
<!-- curation:end -->
|
|
63
63
|
|
|
64
64
|
- File structure and module boundaries in the target area
|
|
65
65
|
- Entry points and key abstractions
|
|
@@ -105,11 +105,11 @@ Present findings to user. Use AskUserQuestion to offer focused follow-up explora
|
|
|
105
105
|
|
|
106
106
|
### Phase 6: Suggest Feature Knowledge Creation (Conditional)
|
|
107
107
|
|
|
108
|
-
<!--
|
|
108
|
+
<!-- curation:on -->
|
|
109
109
|
**Requires:** MERGED_FINDINGS, DECISIONS_CONTEXT
|
|
110
|
-
<!--
|
|
110
|
+
<!-- curation:off -->
|
|
111
111
|
**Requires:** MERGED_FINDINGS
|
|
112
|
-
<!--
|
|
112
|
+
<!-- curation:end -->
|
|
113
113
|
**Produces:** FEATURE_KNOWLEDGE_STATUS (created | skipped)
|
|
114
114
|
|
|
115
115
|
1. Check if matching feature knowledge already exists by reading `{worktree}/.devflow/features/index.md` (or globbing frontmatter if absent). If covered → skip
|
|
@@ -143,11 +143,11 @@ Structured exploration findings with concrete code references:
|
|
|
143
143
|
```
|
|
144
144
|
/explore (orchestrator)
|
|
145
145
|
│
|
|
146
|
-
<!--
|
|
146
|
+
<!-- curation:on -->
|
|
147
147
|
├─ Phase 1: Load Decisions (Orchestrator-Local)
|
|
148
|
-
<!--
|
|
148
|
+
<!-- curation:off -->
|
|
149
149
|
├─ Phase 1: Resolve Settings
|
|
150
|
-
<!--
|
|
150
|
+
<!-- curation:end -->
|
|
151
151
|
│
|
|
152
152
|
├─ Phase 2: Orient
|
|
153
153
|
│ └─ Skim agent (codebase overview)
|
|
@@ -168,11 +168,11 @@ Structured exploration findings with concrete code references:
|
|
|
168
168
|
|
|
169
169
|
1. **Structure over browsing** - Every claim must cite file:line references
|
|
170
170
|
2. **Parallel execution** - All explorers run simultaneously for speed
|
|
171
|
-
<!--
|
|
171
|
+
<!-- curation:on -->
|
|
172
172
|
3. **Knowledge-informed** - Prior decisions guide where to look; NO pre-loaded feature knowledge in sub-agents (avoids confirmation bias)
|
|
173
|
-
<!--
|
|
173
|
+
<!-- curation:off -->
|
|
174
174
|
3. **Knowledge-informed** - NO pre-loaded feature knowledge in sub-agents (avoids confirmation bias)
|
|
175
|
-
<!--
|
|
175
|
+
<!-- curation:end -->
|
|
176
176
|
4. **User-driven depth** - Present findings, then offer drill-down into specific areas
|
|
177
177
|
|
|
178
178
|
## Error Handling
|