devflow-kit 2.5.0 → 3.0.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 +73 -0
- package/README.md +44 -19
- package/dist/agents/git.md +13 -15
- package/dist/cli/commands/ambient.js +160 -145
- package/dist/cli/commands/capture.js +29 -55
- package/dist/cli/commands/compliance.js +32 -61
- package/dist/cli/commands/context.js +17 -32
- package/dist/cli/commands/debug.js +65 -26
- package/dist/cli/commands/flags.js +3 -3
- package/dist/cli/commands/hud.js +34 -10
- package/dist/cli/commands/init-seed.js +40 -4
- package/dist/cli/commands/init.js +249 -271
- package/dist/cli/commands/install-report.js +10 -15
- package/dist/cli/commands/knowledge/index.js +1 -1
- package/dist/cli/commands/knowledge/toggle.js +11 -3
- package/dist/cli/commands/learning.js +52 -37
- package/dist/cli/commands/legacy-hooks.js +11 -14
- package/dist/cli/commands/memory.js +67 -78
- package/dist/cli/commands/proxy.js +23 -41
- package/dist/cli/commands/security.js +5 -13
- package/dist/cli/commands/skills.js +21 -3
- package/dist/cli/commands/tracker.js +100 -228
- package/dist/cli/commands/uninstall.js +343 -138
- package/dist/commands/bug-analysis.md +38 -12
- package/dist/commands/code-review.md +70 -21
- package/dist/commands/debug.md +37 -7
- package/dist/commands/dynamic-build.md +66 -17
- package/dist/commands/dynamic-plan.md +19 -8
- package/dist/commands/dynamic-profile.md +24 -10
- package/dist/commands/dynamic-tickets.md +22 -11
- package/dist/commands/explore.md +37 -7
- package/dist/commands/implement.md +96 -32
- package/dist/commands/plan.md +62 -19
- package/dist/commands/release.md +2 -2
- package/dist/commands/research.md +34 -8
- package/dist/commands/resolve.md +65 -17
- package/dist/commands/self-review.md +45 -9
- package/dist/core/compliance-compose.js +27 -27
- package/dist/core/evidence-policy.js +240 -24
- package/dist/core/feature-config.js +94 -25
- package/dist/core/feature-switch.js +1 -1
- package/dist/core/flags.js +30 -2
- package/dist/core/fs-atomic.js +27 -0
- package/dist/core/hook-log-dirs.js +104 -0
- package/dist/core/learning-tuning-config.js +5 -3
- package/dist/core/ledger-root.js +102 -0
- package/dist/core/manifest.js +6 -4
- package/dist/core/mds-variants.js +34 -97
- package/dist/core/migrations.js +49 -23
- package/dist/core/plugins.js +5 -4
- package/dist/core/project-paths.js +0 -17
- package/dist/core/same-location.js +25 -0
- package/dist/core/tracker.js +226 -139
- package/dist/hud/components/config-counts.js +15 -4
- package/dist/hud/components/learning-counts.js +14 -0
- package/dist/hud/config.js +2 -1
- package/dist/hud/cost-history.js +2 -4
- package/dist/hud/git.js +52 -7
- package/dist/hud/index.js +7 -9
- package/dist/skills/git/references/pr/check-merge-readiness.md +1 -1
- package/dist/skills/git/references/pr/ensure-pr-ready.md +1 -1
- package/dist/skills/git/references/pr/update-pr-evidence.md +1 -1
- package/dist/skills/git/references/tracker/_mcp.md +1 -1
- package/dist/skills/git/references/tracker/github/backlink-shipped-issues.md +1 -1
- package/dist/skills/git/references/tracker/github/ensure-traceable-issue.md +1 -1
- package/dist/skills/git/references/tracker/github/gather-release-evidence.md +2 -2
- package/dist/skills/git/references/tracker/github/manage-debt.md +3 -3
- package/dist/skills/git/references/tracker/jira/backlink-shipped-issues.md +1 -1
- package/dist/skills/git/references/tracker/jira/ensure-traceable-issue.md +1 -1
- package/dist/skills/git/references/tracker/jira/gather-release-evidence.md +2 -2
- package/dist/skills/git/references/tracker/jira/manage-debt.md +1 -1
- package/dist/skills/git/references/tracker/jira/post-wave-report.md +1 -1
- package/dist/skills/git/references/tracker/jira/setup-task.md +1 -1
- package/dist/skills/git/references/tracker/linear/backlink-shipped-issues.md +1 -1
- package/dist/skills/git/references/tracker/linear/ensure-traceable-issue.md +1 -1
- package/dist/skills/git/references/tracker/linear/gather-release-evidence.md +2 -2
- package/dist/skills/git/references/tracker/linear/manage-debt.md +1 -1
- package/dist/skills/git/references/tracker/linear/post-wave-report.md +1 -1
- package/dist/skills/git/references/tracker/linear/setup-task.md +1 -1
- package/dist/targets/claude-code/claude-paths.js +59 -57
- package/dist/targets/claude-code/compliance-install.js +49 -65
- package/dist/targets/claude-code/hooks.js +108 -3
- package/dist/targets/claude-code/installer.js +30 -57
- package/dist/targets/claude-code/post-install.js +232 -139
- package/dist/targets/claude-code/tracker-install.js +38 -65
- package/package.json +5 -4
- package/src/assets/agents/code.md +4 -3
- package/src/assets/agents/design.md +1 -0
- package/src/assets/agents/git.mds +55 -57
- package/src/assets/agents/knowledge.md +2 -2
- package/src/assets/agents/review.md +3 -1
- package/src/assets/agents/tracker.md +37 -30
- package/src/assets/commands/_partials/_compliance.mds +19 -1
- package/src/assets/commands/_partials/_decisions.mds +15 -3
- package/src/assets/commands/_partials/_docs_root.mds +35 -0
- package/src/assets/commands/_partials/_engine.mds +2 -2
- package/src/assets/commands/_partials/_evidence_policy.mds +3 -3
- package/src/assets/commands/_partials/_factory.mds +1 -1
- package/src/assets/commands/_partials/_knowledge.mds +27 -9
- package/src/assets/commands/_partials/_plan_contract.mds +2 -2
- package/src/assets/commands/_partials/_preamble.mds +1 -1
- package/src/assets/commands/_partials/_publication.mds +6 -2
- package/src/assets/commands/_partials/_settings.mds +28 -0
- package/src/assets/commands/_partials/_ticket_template.mds +3 -3
- package/src/assets/commands/_partials/_tracker.mds +4 -4
- package/src/assets/commands/_partials/_wave.mds +4 -4
- package/src/assets/commands/bug-analysis.mds +19 -17
- package/src/assets/commands/code-review.mds +39 -33
- package/src/assets/commands/debug.mds +4 -5
- package/src/assets/commands/dynamic-build.mds +75 -53
- package/src/assets/commands/dynamic-plan.mds +20 -15
- package/src/assets/commands/dynamic-profile.mds +24 -11
- package/src/assets/commands/dynamic-tickets.mds +25 -20
- package/src/assets/commands/explore.mds +4 -5
- package/src/assets/commands/implement.mds +58 -45
- package/src/assets/commands/plan.mds +34 -29
- package/src/assets/commands/release.md +2 -2
- package/src/assets/commands/research.mds +11 -9
- package/src/assets/commands/resolve.mds +41 -39
- package/src/assets/commands/self-review.mds +24 -25
- package/src/assets/mds/git/_pr.mds +61 -61
- package/src/assets/mds/git/_references.mds +19 -19
- package/src/assets/mds/tracker/_common.mds +8 -8
- package/src/assets/mds/tracker/_github.mds +71 -71
- package/src/assets/mds/tracker/_jira.mds +74 -74
- package/src/assets/mds/tracker/_linear.mds +75 -75
- package/src/assets/mds/tracker/_mcp.mds +23 -17
- package/src/assets/scripts/hooks/background-memory-update +35 -19
- package/src/assets/scripts/hooks/capture-prompt +18 -12
- package/src/assets/scripts/hooks/capture-question +18 -12
- package/src/assets/scripts/hooks/capture-turn +27 -17
- package/src/assets/scripts/hooks/debug-trace +11 -6
- package/src/assets/scripts/hooks/ensure-devflow-init +33 -6
- package/src/assets/scripts/hooks/ensure-proxy +9 -8
- package/src/assets/scripts/hooks/ensure-root-gitignore +111 -36
- package/src/assets/scripts/hooks/git-marker +48 -0
- package/src/assets/scripts/hooks/json-helper.cjs +6 -1
- package/src/assets/scripts/hooks/lib/project-paths.cjs +0 -19
- package/src/assets/scripts/hooks/log-paths +80 -0
- package/src/assets/scripts/hooks/memory-worker +17 -15
- package/src/assets/scripts/hooks/pre-compact-memory +41 -16
- package/src/assets/scripts/hooks/queue-append +104 -30
- package/src/assets/scripts/hooks/resolve-project-root +101 -7
- package/src/assets/scripts/hooks/session-start-context +289 -122
- package/src/assets/scripts/hooks/session-start-memory +35 -16
- package/src/assets/scripts/lib/project-config.cjs +633 -0
- package/src/assets/scripts/resolve-evidence-policy.cjs +300 -220
- package/src/assets/scripts/resolve-settings.cjs +1054 -0
- package/src/assets/scripts/verify-evidence.cjs +1 -1
- package/src/assets/skills/compliance/SKILL.md +2 -2
- package/src/assets/skills/docs-framework/SKILL.md +6 -7
- package/src/assets/skills/docs-framework/references/patterns.md +10 -17
- package/src/assets/skills/gap-analysis/SKILL.md +2 -2
- package/src/assets/skills/git/references/github-api.md +9 -9
- package/src/assets/skills/git/references/patterns.md +1 -1
- package/src/assets/skills/worktree-support/SKILL.md +1 -1
- package/src/assets/skills/worktree-support/references/roots.md +29 -0
- package/src/targets/claude-code/templates/managed-settings.json +25 -9
|
@@ -71,7 +71,7 @@ The script body cannot perform this read — you (the main model) do it before a
|
|
|
71
71
|
|
|
72
72
|
### Handoff convention for sequential Code agents within a ticket
|
|
73
73
|
|
|
74
|
-
When a ticket requires multiple sequential Code agent phases, each Code agent writes
|
|
74
|
+
When a ticket requires multiple sequential Code agent phases, each Code agent writes `{toplevel}/.devflow/docs/handoff-{branch_slug}.md` (branch-scoped to prevent concurrent session clobber), `{toplevel}` being `git rev-parse --show-toplevel` in the checkout the ticket's branch is in — never a subdirectory. The next Code agent reads it via HANDOFF_FILE input. PRIOR_PHASE_SUMMARY is the compact in-context form; the handoff file is the durable form that survives context compaction. Always read the handoff file directly — code is authoritative, summaries are supplementary.
|
|
75
75
|
|
|
76
76
|
### IRON RULE (ADR-008: LLM-vs-plumbing)
|
|
77
77
|
|
|
@@ -115,7 +115,7 @@ The following agentType values are valid. Model tiers are shown for reference
|
|
|
115
115
|
---
|
|
116
116
|
|
|
117
117
|
**Requires:** ticket or task description; optional plan document and acceptance criteria from `/devflow:dynamic-plan`
|
|
118
|
-
**Produces:** implemented and reviewed branch per ticket; wave run report at
|
|
118
|
+
**Produces:** implemented and reviewed branch per ticket; wave run report at `{integration worktree root}/.devflow/docs/waves/{slug}/{ts}/wave-report.md`
|
|
119
119
|
|
|
120
120
|
---
|
|
121
121
|
|
|
@@ -141,7 +141,7 @@ Before you write the workflow script:
|
|
|
141
141
|
**Resolve the evidence policy once per run**, from the repository root, before any step reads the values:
|
|
142
142
|
|
|
143
143
|
```bash
|
|
144
|
-
node "$
|
|
144
|
+
node "$HOME/.devflow/scripts/resolve-evidence-policy.cjs" 2>/dev/null; echo "exit=$?"
|
|
145
145
|
```
|
|
146
146
|
|
|
147
147
|
Accept the output only when it is exactly two lines: `exit=0` last and, before it, one line of the form `EVIDENCE_POLICY=<required|standard> SOURCE=<file|worktree|default|invalid|error> REF=<branch|none>[ WARN=<remote-unavailable|invalid-file|raised-by-compliance|pr-changes-policy>[,…]] ISSUE_REQUIRED=<true|false> APPLY_CONVENTIONS=<true|false> REQUIRE_NON_AUTHOR_APPROVAL=<true|false>` — these fields, in this order, nothing else, where `<branch>` is a branch name such as `main`. **Anything else** (a non-zero exit, no line, extra text, or a missing, reordered or unlisted field or value) ⇒ use `EVIDENCE_POLICY=required SOURCE=error REF=none ISSUE_REQUIRED=true APPLY_CONVENTIONS=true REQUIRE_NON_AUTHOR_APPROVAL=true` instead.
|
|
@@ -150,6 +150,38 @@ Set `EVIDENCE_POLICY`, `ISSUE_REQUIRED`, `APPLY_CONVENTIONS` and `REQUIRE_NON_AU
|
|
|
150
150
|
|
|
151
151
|
Author the resolved `ISSUE_REQUIRED` and `APPLY_CONVENTIONS` into the workflow script as constants — pass them as `issueRequired` and `applyConventions` when invoking the workflow — and pass both to the Git `setup-task` spawn.
|
|
152
152
|
|
|
153
|
+
**0b. Resolve the compliance lens**
|
|
154
|
+
|
|
155
|
+
**Produces:** COMPLIANCE_FRAMEWORKS
|
|
156
|
+
|
|
157
|
+
**Resolve the compliance lens** for each worktree root, from its settings line (every framework reference is installed on every machine, so no file check decides it):
|
|
158
|
+
|
|
159
|
+
**Resolve the settings line** once per worktree root, reusing a line this run already resolved for the same root. `{root}` is the worktree the values are for — the repository root when the run has one worktree:
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
node "$HOME/.devflow/scripts/resolve-settings.cjs" "{root}" 2>/dev/null; echo "exit=$?"
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Accept the output only when it is exactly two lines: `exit=0` last and, before it, one line of the form `TRACKER=<github|jira|linear> TRACKER_SOURCE=<project|personal|machine|default> TRACKER_WARN=<none|mismatch|invalid> SITE=<none|https://<host>> KEY=<none|<key>> REVIEW_PUBLICATION=<off|auto|full> COMPLIANCE=<off|generic|<id>[,<id>…]> MEMORY=<on|off> LEARNING=<on|off> KNOWLEDGE=<on|off>` — these fields, in this order, nothing else, where `<host>` is a lowercase dotted host name alone, `<key>` is 2–10 of `A-Z`, `0-9` and `_` starting with a letter, and each `<id>` is one of `gdpr`, `hipaa`, `pci-dss`, `soc2`, `iso-27001`, `sox`. **Anything else** (a non-zero exit, no line, extra text, or a missing, reordered or unlisted field or value) ⇒ use `TRACKER=github TRACKER_SOURCE=default TRACKER_WARN=invalid SITE=none KEY=none REVIEW_PUBLICATION=off COMPLIANCE=generic MEMORY=on LEARNING=on KNOWLEDGE=off` instead.
|
|
166
|
+
|
|
167
|
+
The accepted line is the only source of these values: the script alone folds the committed `.devflow/project.json`, the personal `.devflow/config.json` and the machine manifest.
|
|
168
|
+
|
|
169
|
+
**Set the compliance lens** from that line: `COMPLIANCE_FRAMEWORKS` is the settings line's `COMPLIANCE` with `generic` written `none`: `off`, `none`, or the framework ids the machine and this repository declare.
|
|
170
|
+
|
|
171
|
+
Pass it as `complianceFrameworks` when invoking the workflow; the engine hands it to every Code agent.
|
|
172
|
+
|
|
173
|
+
**0c. Resolve the docs root**
|
|
174
|
+
|
|
175
|
+
**Docs root (D-DOCS-ROOT).** Every `.devflow/docs/` path this command reads or writes lives at the checkout's toplevel, never under the directory the session started in. Resolve `{worktree}` from the start directory — `WORKTREE_PATH` if provided, otherwise cwd (`devflow:worktree-support`) — by running
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
git -C "{start}" rev-parse --show-toplevel
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
and using its one-line output. If the command fails (outside a git repository), `{worktree}` is the start directory itself. Every docs path below is written `{worktree}/.devflow/docs/…`; a repo-relative docs path handed to an agent always travels with a `WORKTREE_PATH` naming the checkout it is relative to.
|
|
182
|
+
|
|
183
|
+
`{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.
|
|
184
|
+
|
|
153
185
|
**1. Apply decisions context**
|
|
154
186
|
|
|
155
187
|
Apply the `devflow:apply-decisions` algorithm to the DECISIONS_CONTEXT loaded per the preamble above: scan the index, Read relevant entries, note the verbatim ADR/PF IDs you will inject into Code agent and Evaluate agent prompts.
|
|
@@ -162,7 +194,7 @@ Note the `budget` value from the Workflow tool context (or default to "medium" i
|
|
|
162
194
|
|
|
163
195
|
- **SINGLE mode:** input is one ticket, one issue, one task description, or one plan document
|
|
164
196
|
- **WAVE mode:** input is a set of tracker issues (wave labels, milestone, issue list), or the user says "wave" / "all tickets in wave N"
|
|
165
|
-
- **A `/devflow:dynamic-tickets` ticket directory** (
|
|
197
|
+
- **A `/devflow:dynamic-tickets` ticket directory** (`{worktree}/.devflow/docs/tickets/{slug}/{ts}/`) is WAVE input: in each ticket file (every `.md` there but `tracking-issue.md`), the `**Issue:**` line directly after `**Depends on:**` is one raw `ISSUE_REFS` token, forwarded to the wave's pre-fetch verbatim — never rendered, normalised or re-derived. A ticket file with no `**Issue:**` line, or more than one, contributes no token; name it in the run summary as `not filed`.
|
|
166
198
|
|
|
167
199
|
When ambiguous, ask the user before authoring: "Is this a single ticket or a wave of tickets?"
|
|
168
200
|
|
|
@@ -186,7 +218,7 @@ Extract or note:
|
|
|
186
218
|
- The test plan (for Gate 2) — a plan's TP lines, passed only once they pass this check. Copy the plan's `## Test Plan` section byte for byte into a fresh `mktemp` file with the Write tool, never through an interpolated shell string, and run:
|
|
187
219
|
|
|
188
220
|
```bash
|
|
189
|
-
node "$
|
|
221
|
+
node "$HOME/.devflow/scripts/verify-evidence.cjs" check tp <that file>; echo "exit=$?"
|
|
190
222
|
```
|
|
191
223
|
|
|
192
224
|
Only `exit=0` passes it: pass the section's TP lines, as one string, as `testPlan` when invoking the workflow — a test plan alone still runs the Test agent. Any other result, or a plan with no `## Test Plan` section: omit `testPlan` and note `Test plan: missing or malformed` in the run summary. Nothing is repaired, and a test plan in any other shape — an older JSON one included — is never passed.
|
|
@@ -199,7 +231,7 @@ If none found: build proceeds Gate-1-only (Gate 2 skipped with a note). Never re
|
|
|
199
231
|
|
|
200
232
|
Check, in priority order:
|
|
201
233
|
- An explicit candidate issue reference or issue URL in the user's input (e.g. `#42`, `42`, or `https://github.com/…/issues/42`)
|
|
202
|
-
- The `**Issue:**` line directly after the H1 of the ticket set's `tracking-issue.md` (written by `/devflow:dynamic-tickets`' filing step; the file is at
|
|
234
|
+
- The `**Issue:**` line directly after the H1 of the ticket set's `tracking-issue.md` (written by `/devflow:dynamic-tickets`' filing step; the file is at `{worktree}/.devflow/docs/tickets/{slug}/{ts}/tracking-issue.md`), as a raw token — only when the file holds exactly one `**Issue:**` line
|
|
203
235
|
- Otherwise: none
|
|
204
236
|
|
|
205
237
|
**Issue-reference grammar (L1 — command layer, permissive and provider-blind):** scan `$ARGUMENTS` for candidate issue references — a `#`-prefixed token and a bare digit run are both candidates — and collect them in source order as the raw token list `ISSUE_REFS`. Forward that list to the Git agent **verbatim**: the command never renders, normalises, pads, strips or coerces a token, and never rules a candidate out. Under `github` a token matching `^#?[1-9][0-9]{0,8}$` **is** a reference and the Git agent renders it as `#{n}`.
|
|
@@ -237,6 +269,7 @@ const DECISIONS_CONTEXT = args.decisionsContext || ""; // injected before autho
|
|
|
237
269
|
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
|
|
238
270
|
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
|
|
239
271
|
const APPLY_CONVENTIONS = String(args.applyConventions) === "false" ? "false" : "true";
|
|
272
|
+
const COMPLIANCE_FRAMEWORKS = /^(?:off|none|[a-z][a-z0-9-]{0,15}(?:,[a-z][a-z0-9-]{0,15}){0,7})$/.test(String(args.complianceFrameworks)) ? String(args.complianceFrameworks) : "off"; // Pre-authoring step 0b; any other shape is no lens
|
|
240
273
|
|
|
241
274
|
// Phase 1: Git setup — declare the operation; the agent owns the process, the branch name included
|
|
242
275
|
const setup = await phase("setup", () =>
|
|
@@ -280,6 +313,7 @@ ${DECISIONS_CONTEXT}
|
|
|
280
313
|
|
|
281
314
|
ISSUE_NUMBER: ${ISSUE_NUMBER}
|
|
282
315
|
ISSUE_PR_LINK: ${ISSUE_PR_LINK}
|
|
316
|
+
COMPLIANCE_FRAMEWORKS: ${COMPLIANCE_FRAMEWORKS}
|
|
283
317
|
|
|
284
318
|
When you build or run tests to verify your work, use your "Long-running commands" discipline (background-Bash + Monitor poll) for anything that may run silent >120s, and prefer package-scoped commands.
|
|
285
319
|
|
|
@@ -303,6 +337,7 @@ Report: PASS or FAIL with details.`, { agentType: "Validate" });
|
|
|
303
337
|
${validation.details}
|
|
304
338
|
ISSUE_NUMBER: ${ISSUE_NUMBER}
|
|
305
339
|
ISSUE_PR_LINK: ${ISSUE_PR_LINK}
|
|
340
|
+
COMPLIANCE_FRAMEWORKS: ${COMPLIANCE_FRAMEWORKS}
|
|
306
341
|
Commit fixes with conventional-commit message.`, { agentType: "Code" });
|
|
307
342
|
const recheck = await agent(`Re-run build, typecheck, lint, tests on branch ${BRANCH}. Report: PASS or FAIL.`, { agentType: "Validate" });
|
|
308
343
|
if (recheck.verdict === "PASS") break;
|
|
@@ -346,6 +381,7 @@ Report: PASS or FAIL with rationale.`, { agentType: "Evaluate" }),
|
|
|
346
381
|
${panel.filter(p => p.verdict === "FAIL").map(p => p.rationale).join("\n")}
|
|
347
382
|
ISSUE_NUMBER: ${ISSUE_NUMBER}
|
|
348
383
|
ISSUE_PR_LINK: ${ISSUE_PR_LINK}
|
|
384
|
+
COMPLIANCE_FRAMEWORKS: ${COMPLIANCE_FRAMEWORKS}
|
|
349
385
|
Self-verify your fix compiles (background-Bash + Monitor for any build >120s — see your "Long-running commands" discipline). Commit fixes.`, { agentType: "Code" });
|
|
350
386
|
evalVerdict = "FAIL-FIXED"; // issues found, fixes applied, not re-evaluated by design
|
|
351
387
|
}
|
|
@@ -365,6 +401,7 @@ Cover: functionality, API contracts, performance, and cover every TEST_PLAN scen
|
|
|
365
401
|
${testResult.failures}
|
|
366
402
|
ISSUE_NUMBER: ${ISSUE_NUMBER}
|
|
367
403
|
ISSUE_PR_LINK: ${ISSUE_PR_LINK}
|
|
404
|
+
COMPLIANCE_FRAMEWORKS: ${COMPLIANCE_FRAMEWORKS}
|
|
368
405
|
Self-verify your fix compiles and the scenarios pass (background-Bash + Monitor for any build/test >120s). Commit fixes.`, { agentType: "Code" });
|
|
369
406
|
testVerdict = "FAIL-FIXED"; // issues found, fixes applied, not re-evaluated by design
|
|
370
407
|
}
|
|
@@ -478,6 +515,7 @@ ${chunk.map(f => `- ${f.description} (${f.severity})`).join("\n")}
|
|
|
478
515
|
|
|
479
516
|
ISSUE_NUMBER: ${ISSUE_NUMBER}
|
|
480
517
|
ISSUE_PR_LINK: ${ISSUE_PR_LINK}
|
|
518
|
+
COMPLIANCE_FRAMEWORKS: ${COMPLIANCE_FRAMEWORKS}
|
|
481
519
|
Fix all findings in this batch. Self-verify your fix compiles (background-Bash + Monitor for any build >120s — see your "Long-running commands" discipline). Commit with conventional-commit message.
|
|
482
520
|
Return: {"status": "fixed"|"blocked", "commitShas": ["<sha>"], "unresolved": ["<description of any finding that could not be fixed>"]}`, { agentType: "Code" });
|
|
483
521
|
chunkResults.push({ chunk, result: r });
|
|
@@ -528,6 +566,7 @@ Report: PASS or FAIL with details.`, { agentType: "Validate" });
|
|
|
528
566
|
${failureDetails}
|
|
529
567
|
ISSUE_NUMBER: ${ISSUE_NUMBER}
|
|
530
568
|
ISSUE_PR_LINK: ${ISSUE_PR_LINK}
|
|
569
|
+
COMPLIANCE_FRAMEWORKS: ${COMPLIANCE_FRAMEWORKS}
|
|
531
570
|
Self-verify your fix compiles. Commit fixes with conventional-commit message.`, { agentType: "Code" });
|
|
532
571
|
const recheck = await agent(`Re-run build, typecheck, lint, tests on branch ${BRANCH} (background+Monitor for long commands). Report: PASS or FAIL.`, { agentType: "Validate" });
|
|
533
572
|
if (recheck.verdict === "PASS") break;
|
|
@@ -641,7 +680,7 @@ Code(agentType:"Code", prompt: full task + plan + DECISIONS_CONTEXT + handoff if
|
|
|
641
680
|
→ gate2_acceptance() ← Gate 2 runs HERE — before the review pass, not after
|
|
642
681
|
```
|
|
643
682
|
|
|
644
|
-
The Code agent prompt must include: task description, implementation plan (if one exists), relevant DECISIONS_CONTEXT (from `.devflow/learning/index.md`), and any PRIOR_PHASE_SUMMARY / HANDOFF_FILE for sequential multi-phase tickets.
|
|
683
|
+
The Code agent prompt must include: task description, implementation plan (if one exists), relevant DECISIONS_CONTEXT (from `.devflow/learning/index.md`), the compliance lens (`COMPLIANCE_FRAMEWORKS` — every Code prompt carries it, fix prompts included), and any PRIOR_PHASE_SUMMARY / HANDOFF_FILE for sequential multi-phase tickets.
|
|
645
684
|
|
|
646
685
|
Gate 2 runs at implementation acceptance — this matches devflow's deliberate placement: "evaluation is part of implementation acceptance, not post-review" (§6.1).
|
|
647
686
|
|
|
@@ -1026,7 +1065,7 @@ Return: {"ready": [...ticket-ids], "blocked": [{"ticket": "id", "namedBlocker":
|
|
|
1026
1065
|
try {
|
|
1027
1066
|
// ticketId is the ISSUE_REF the pre-fetch heading printed — this ticket's OWN reference: the engine's `ticket` (its TICKET)
|
|
1028
1067
|
// and its setup-task ISSUE_INPUT; the engine returns the branch that setup-task created, merged below; plans[ticketId] is its own plan, criteria and checked testPlan (Pre-authoring step 4)
|
|
1029
|
-
const engineResult = await runSingleTicketEngine({ ticket: ticketId, baseBranch: INTEGRATION_BRANCH, ...(plans[ticketId] || {}), decisionsContext: DECISIONS_CONTEXT, issueRequired: ISSUE_REQUIRED, applyConventions: APPLY_CONVENTIONS, issueInput: ticketId });
|
|
1068
|
+
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 });
|
|
1030
1069
|
// Check both verdict (engine_output_schema) and overallVerdict (SINGLE skeleton alias).
|
|
1031
1070
|
// PASS and UNVERIFIED merge; PARTIAL, FAIL, ESCALATED (the ticket-link and branch stops included) or no verdict quarantine.
|
|
1032
1071
|
if (["PASS", "UNVERIFIED"].includes(engineResult.verdict || engineResult.overallVerdict)) {
|
|
@@ -1057,15 +1096,15 @@ return { tickets: WAVE_TICKETS.map(t => results[t] || { ticket: t, ran: false, v
|
|
|
1057
1096
|
|
|
1058
1097
|
A workflow cannot pause mid-run. After the build/wave workflow returns, you (the main model) surface anything that needs a human decision — all at once:
|
|
1059
1098
|
|
|
1060
|
-
1. Read the wave report (
|
|
1061
|
-
2. **Post wave-report as tracking-issue comment** (WAVE mode only — skip this step entirely in SINGLE mode; SINGLE runs produce no wave report): In WAVE mode, if a tracking-issue number was resolved in Pre-authoring step 5 (`ISSUE_NUMBER` is not `(none)`) AND
|
|
1099
|
+
1. Read the wave report (`{integration worktree root}/.devflow/docs/waves/{slug}/{ts}/wave-report.md`) for its **escalations** (quarantined/blocked tickets and why), and read any `DECISIONS-NEEDED.md` left by a prior `/devflow:dynamic-plan` run for this initiative.
|
|
1100
|
+
2. **Post wave-report as tracking-issue comment** (WAVE mode only — skip this step entirely in SINGLE mode; SINGLE runs produce no wave report): In WAVE mode, if a tracking-issue number was resolved in Pre-authoring step 5 (`ISSUE_NUMBER` is not `(none)`) AND `{integration worktree root}/.devflow/docs/waves/{slug}/{ts}/wave-report.md` exists, define `WAVE_ID` as the timestamped wave directory slug (the `{ts}` component, e.g. `2026-08-20_1730`), then spawn:
|
|
1062
1101
|
```
|
|
1063
1102
|
Agent(subagent_type="Git"):
|
|
1064
1103
|
"OPERATION: post-wave-report
|
|
1065
1104
|
TRACKING_ISSUE: {ISSUE_NUMBER}
|
|
1066
1105
|
WAVE_REPORT_PATH: .devflow/docs/waves/{slug}/{ts}/wave-report.md
|
|
1067
1106
|
WAVE_ID: {WAVE_ID}
|
|
1068
|
-
WORKTREE_PATH: {integration worktree root
|
|
1107
|
+
WORKTREE_PATH: {integration worktree root}"
|
|
1069
1108
|
```
|
|
1070
1109
|
The Git agent deduplicates via its own marker — it skips if a report for this `WAVE_ID` is already posted. The marker's format belongs to the operation; this caller passes `WAVE_ID` and never restates the literal. On API failure it degrades gracefully (`TRACEABILITY: DEGRADED ({reason})`) and continues — never blocks the post-wave step. This comment is the evidence surface for the PR-less integration-branch path; no other PR machinery is invented.
|
|
1071
1110
|
|
|
@@ -1098,7 +1137,7 @@ Refs {tracking ref}
|
|
|
1098
1137
|
Then check it:
|
|
1099
1138
|
|
|
1100
1139
|
```bash
|
|
1101
|
-
node "$
|
|
1140
|
+
node "$HOME/.devflow/scripts/verify-evidence.cjs" check wave <that file>; echo "exit=$?"
|
|
1102
1141
|
```
|
|
1103
1142
|
|
|
1104
1143
|
Only `exit=0` admits the file's text, verbatim, as `PR_WAVE_BLOCK`. Any other result: no wave PR — record `Wave PR: not opened (wave block refused: <the code on stderr>)` and go to step 4.
|
|
@@ -1108,8 +1147,8 @@ node "${DEVFLOW_DIR:-$HOME/.devflow}/scripts/verify-evidence.cjs" check wave <th
|
|
|
1108
1147
|
**(b) The wave test plan.** Take the checked TP lines each merged row's ticket was given in Pre-authoring step 4, in row order; renumber them `TP-1`, `TP-2`, … and prefix each scenario with its row's `T<k>: `. A line is never shortened or reworded: one whose prefixed scenario would pass 200 characters leaves its ticket with no usable test plan. Write `## Test Plan` and those lines, and nothing else, to `"{integration worktree root}/.devflow/docs/evidence-wave-{slug}.md"` with the Write tool, then run (the path double-quoted; one rewrite from the same lines after a refusal, never a second):
|
|
1109
1148
|
|
|
1110
1149
|
```bash
|
|
1111
|
-
node "$
|
|
1112
|
-
node "$
|
|
1150
|
+
node "$HOME/.devflow/scripts/verify-evidence.cjs" check tp "{integration worktree root}/.devflow/docs/evidence-wave-{slug}.md"; echo "exit=$?"
|
|
1151
|
+
node "$HOME/.devflow/scripts/verify-evidence.cjs" render --plan "{integration worktree root}/.devflow/docs/evidence-wave-{slug}.md"; echo "exit=$?"
|
|
1113
1152
|
```
|
|
1114
1153
|
|
|
1115
1154
|
Only when both exit 0 is `PR_TEST_PLAN_BLOCK` the render's stdout, byte for byte without its `exit=` line; in every other case it is `(none)`.
|
|
@@ -1136,7 +1175,7 @@ Do NOT ask questions mid-workflow — that is impossible (F4). The workflow only
|
|
|
1136
1175
|
|
|
1137
1176
|
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.
|
|
1138
1177
|
|
|
1139
|
-
**(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
|
|
1178
|
+
**(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`:
|
|
1140
1179
|
|
|
1141
1180
|
```
|
|
1142
1181
|
Agent(subagent_type="Test"):
|
|
@@ -1167,9 +1206,19 @@ git -C "{integration worktree root}" push origin HEAD; echo "exit=$?"
|
|
|
1167
1206
|
|
|
1168
1207
|
**(d) Refresh.** Resolve the publication value for the integration worktree:
|
|
1169
1208
|
|
|
1170
|
-
**Resolve
|
|
1209
|
+
**Resolve the settings line** once per worktree root, reusing a line this run already resolved for the same root. `{root}` is the worktree the values are for — the repository root when the run has one worktree:
|
|
1210
|
+
|
|
1211
|
+
```bash
|
|
1212
|
+
node "$HOME/.devflow/scripts/resolve-settings.cjs" "{root}" 2>/dev/null; echo "exit=$?"
|
|
1213
|
+
```
|
|
1214
|
+
|
|
1215
|
+
Accept the output only when it is exactly two lines: `exit=0` last and, before it, one line of the form `TRACKER=<github|jira|linear> TRACKER_SOURCE=<project|personal|machine|default> TRACKER_WARN=<none|mismatch|invalid> SITE=<none|https://<host>> KEY=<none|<key>> REVIEW_PUBLICATION=<off|auto|full> COMPLIANCE=<off|generic|<id>[,<id>…]> MEMORY=<on|off> LEARNING=<on|off> KNOWLEDGE=<on|off>` — these fields, in this order, nothing else, where `<host>` is a lowercase dotted host name alone, `<key>` is 2–10 of `A-Z`, `0-9` and `_` starting with a letter, and each `<id>` is one of `gdpr`, `hipaa`, `pci-dss`, `soc2`, `iso-27001`, `sox`. **Anything else** (a non-zero exit, no line, extra text, or a missing, reordered or unlisted field or value) ⇒ use `TRACKER=github TRACKER_SOURCE=default TRACKER_WARN=invalid SITE=none KEY=none REVIEW_PUBLICATION=off COMPLIANCE=generic MEMORY=on LEARNING=on KNOWLEDGE=off` instead.
|
|
1216
|
+
|
|
1217
|
+
The accepted line is the only source of these values: the script alone folds the committed `.devflow/project.json`, the personal `.devflow/config.json` and the machine manifest.
|
|
1218
|
+
|
|
1219
|
+
**Resolve `REVIEW_PUBLICATION` per worktree:** take `REVIEW_PUBLICATION` from that worktree's settings line, with `{root}` the worktree's root — multi-worktree repos may resolve different values per worktree. The line already caps the personal choice at the team's (D-PUBLICATION-CEILING), so it is `off`, `auto` or `full`, and `off` when the line was unresolvable.
|
|
1171
1220
|
|
|
1172
|
-
**Evidence stub:** only when `EVIDENCE_POLICY` is `required`, a resolved `off` becomes `stub`, so a counts-only record still reaches the PR. `stub` is never a config value:
|
|
1221
|
+
**Evidence stub:** only when `EVIDENCE_POLICY` is `required`, a resolved `off` becomes `stub`, so a counts-only record still reaches the PR. `stub` is never a config value: the settings line never carries it.
|
|
1173
1222
|
|
|
1174
1223
|
Note: `auto` is NOT fail-open — under `auto`, the Git agent probes the repository visibility and treats any error or unrecognised value as PUBLIC (mode STUB). What each value does is decided by the Git agent's publication gate (`references/publication-gate.md` step 2); this partial only resolves the value.
|
|
1175
1224
|
|
|
@@ -71,7 +71,7 @@ The script body cannot perform this read — you (the main model) do it before a
|
|
|
71
71
|
|
|
72
72
|
### Handoff convention for sequential Code agents within a ticket
|
|
73
73
|
|
|
74
|
-
When a ticket requires multiple sequential Code agent phases, each Code agent writes
|
|
74
|
+
When a ticket requires multiple sequential Code agent phases, each Code agent writes `{toplevel}/.devflow/docs/handoff-{branch_slug}.md` (branch-scoped to prevent concurrent session clobber), `{toplevel}` being `git rev-parse --show-toplevel` in the checkout the ticket's branch is in — never a subdirectory. The next Code agent reads it via HANDOFF_FILE input. PRIOR_PHASE_SUMMARY is the compact in-context form; the handoff file is the durable form that survives context compaction. Always read the handoff file directly — code is authoritative, summaries are supplementary.
|
|
75
75
|
|
|
76
76
|
### IRON RULE (ADR-008: LLM-vs-plumbing)
|
|
77
77
|
|
|
@@ -115,7 +115,7 @@ The following agentType values are valid. Model tiers are shown for reference
|
|
|
115
115
|
---
|
|
116
116
|
|
|
117
117
|
**Requires:** ticket files directory or tracker issue list; optional `~/.devflow/preference-profile.md`
|
|
118
|
-
**Produces:** per-ticket plan files + `DECISIONS-NEEDED.md` at
|
|
118
|
+
**Produces:** per-ticket plan files + `DECISIONS-NEEDED.md` at `{worktree}/.devflow/docs/design/{slug}/{ts}/`
|
|
119
119
|
|
|
120
120
|
---
|
|
121
121
|
|
|
@@ -132,6 +132,16 @@ Before authoring, verify:
|
|
|
132
132
|
|
|
133
133
|
### Pre-authoring setup
|
|
134
134
|
|
|
135
|
+
**Docs root (D-DOCS-ROOT).** Every `.devflow/docs/` path this command reads or writes lives at the checkout's toplevel, never under the directory the session started in. Resolve `{worktree}` from the start directory — `WORKTREE_PATH` if provided, otherwise cwd (`devflow:worktree-support`) — by running
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
git -C "{start}" rev-parse --show-toplevel
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
and using its one-line output. If the command fails (outside a git repository), `{worktree}` is the start directory itself. Every docs path below is written `{worktree}/.devflow/docs/…`; a repo-relative docs path handed to an agent always travels with a `WORKTREE_PATH` naming the checkout it is relative to.
|
|
142
|
+
|
|
143
|
+
Pass `{worktree}` to the workflow as its `root` argument.
|
|
144
|
+
|
|
135
145
|
**1. Apply decisions context**
|
|
136
146
|
|
|
137
147
|
Apply the `devflow:apply-decisions` algorithm to the DECISIONS_CONTEXT loaded per the preamble above: scan the index, Read relevant entries, note verbatim ADR/PF IDs to inject into Design agent and Evaluate agent prompts.
|
|
@@ -176,11 +186,11 @@ After the workflow completes:
|
|
|
176
186
|
1. **Check each plan's test plan.** For every path in `planPaths`, copy that plan's `## Test Plan` section — the heading and its TP lines, up to the next `## ` heading — byte for byte into a fresh `mktemp` file with the Write tool, never through an interpolated shell string, and run:
|
|
177
187
|
|
|
178
188
|
```bash
|
|
179
|
-
node "$
|
|
189
|
+
node "$HOME/.devflow/scripts/verify-evidence.cjs" check tp <that file>; echo "exit=$?"
|
|
180
190
|
```
|
|
181
191
|
|
|
182
192
|
Check the section, never the whole plan file: the plan's other `## ` headings are not evidence-file sections, so the script would parse the whole document as the plan. `exit=0` passes. Any other result names that plan `test plan malformed (<code>)` in your summary, `<code>` being the code the script printed on stderr; a plan with no `## Test Plan` section copies as an empty file, which the script refuses. Nothing is repaired: `/devflow:dynamic-build` passes no test plan from that plan.
|
|
183
|
-
2. Read the `decisionsNeededPath` returned by the workflow (e.g.
|
|
193
|
+
2. Read the `decisionsNeededPath` returned by the workflow (e.g. `{worktree}/.devflow/docs/design/<slug>/<ts>/DECISIONS-NEEDED.md`). Always use the OUTDIR-scoped path the workflow wrote — never the flat `{worktree}/.devflow/docs/design/DECISIONS-NEEDED.md`.
|
|
184
194
|
3. First surface the **Auto-Resolved Decisions** section (decision → resolution → source) for audit, then surface ALL open **Decisions Needed** to the user in ONE batched `AskUserQuestion` (never one-at-a-time).
|
|
185
195
|
4. The user's answers feed into their own plan edits or a follow-up `/devflow:dynamic-plan` run.
|
|
186
196
|
|
|
@@ -207,7 +217,8 @@ const PREFERENCE_PROFILE = args.preferenceProfile || ""; // injected before aut
|
|
|
207
217
|
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)
|
|
208
218
|
const slug = args.slug || "wave";
|
|
209
219
|
const ts = new Date().toISOString().slice(0,16).replace(/[-:T]/g, (c) => c === 'T' ? '_' : c === ':' ? '' : c);
|
|
210
|
-
const
|
|
220
|
+
const ROOT = args.root; // {worktree} from Pre-authoring setup: the checkout's toplevel, never cwd
|
|
221
|
+
const OUTDIR = `${ROOT}/.devflow/docs/design/${slug}/${ts}`;
|
|
211
222
|
|
|
212
223
|
// Phase 1: Read all tickets
|
|
213
224
|
const tickets = await phase("read-tickets", () =>
|
|
@@ -392,11 +403,11 @@ Challenge every criterion against these three disqualifiers before accepting the
|
|
|
392
403
|
|
|
393
404
|
### Artifact paths
|
|
394
405
|
|
|
395
|
-
Per-ticket plans →
|
|
406
|
+
Per-ticket plans → `{worktree}/.devflow/docs/design/{slug}/{ts}/{ticket-slug}-plan.md`
|
|
396
407
|
|
|
397
|
-
Decisions needed →
|
|
408
|
+
Decisions needed → `{worktree}/.devflow/docs/design/{slug}/{ts}/DECISIONS-NEEDED.md`
|
|
398
409
|
|
|
399
|
-
|
|
410
|
+
`{worktree}` is the docs root resolved in Pre-authoring setup (it honours `WORKTREE_PATH` when provided).
|
|
400
411
|
|
|
401
412
|
---
|
|
402
413
|
|
|
@@ -71,7 +71,7 @@ The script body cannot perform this read — you (the main model) do it before a
|
|
|
71
71
|
|
|
72
72
|
### Handoff convention for sequential Code agents within a ticket
|
|
73
73
|
|
|
74
|
-
When a ticket requires multiple sequential Code agent phases, each Code agent writes
|
|
74
|
+
When a ticket requires multiple sequential Code agent phases, each Code agent writes `{toplevel}/.devflow/docs/handoff-{branch_slug}.md` (branch-scoped to prevent concurrent session clobber), `{toplevel}` being `git rev-parse --show-toplevel` in the checkout the ticket's branch is in — never a subdirectory. The next Code agent reads it via HANDOFF_FILE input. PRIOR_PHASE_SUMMARY is the compact in-context form; the handoff file is the durable form that survives context compaction. Always read the handoff file directly — code is authoritative, summaries are supplementary.
|
|
75
75
|
|
|
76
76
|
### IRON RULE (ADR-008: LLM-vs-plumbing)
|
|
77
77
|
|
|
@@ -93,14 +93,26 @@ The profile is then consumed by `/devflow:dynamic-plan` to pre-resolve design de
|
|
|
93
93
|
|
|
94
94
|
---
|
|
95
95
|
|
|
96
|
-
**Requires:** read access to
|
|
96
|
+
**Requires:** read access to `{claude_dir}/projects/*/` session transcripts and `{claude_dir}/rules/`
|
|
97
97
|
**Produces:** `~/.devflow/preference-profile.md` — plain-prose decision-preference profile
|
|
98
98
|
|
|
99
99
|
---
|
|
100
100
|
|
|
101
|
+
### Claude Code's directory
|
|
102
|
+
|
|
103
|
+
`{claude_dir}` is Claude Code's directory, resolved once, the way the installer resolves it (D-CLAUDE-DIR-PROMPTS): `CLAUDE_CONFIG_DIR` when that is set to an absolute path, else `$HOME/.claude`. Run
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
d="${CLAUDE_CONFIG_DIR:-}"; case "$d" in /*) ;; *) d="$HOME/.claude" ;; esac; printf '%s\n' "$d"
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
and use its one-line output. Pass it to the agent below as `CLAUDE_DIR`.
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
101
113
|
### Privacy note
|
|
102
114
|
|
|
103
|
-
This command mines session transcripts across **all projects** on this machine —
|
|
115
|
+
This command mines session transcripts across **all projects** on this machine — `{claude_dir}/projects/*/*.jsonl`, `{claude_dir}/history.jsonl`, and feedback memories. The resulting profile is then injected into planning prompts as context. This is a cross-project surface: patterns from one project's decisions may influence planning in another.
|
|
104
116
|
|
|
105
117
|
Mitigation: the profile is plain prose that you review and edit before use. You can trim, redact, or rewrite any section. The profile is at `~/.devflow/preference-profile.md` — open it, read it, adjust it. It is never committed to any repo.
|
|
106
118
|
|
|
@@ -112,8 +124,8 @@ Session transcripts on a typical machine are gigabytes. **The agent MUST NOT ful
|
|
|
112
124
|
|
|
113
125
|
1. Use `rg` (ripgrep) or `grep` to search for `AskUserQuestion` occurrences across transcript files — extracting just the question text and the surrounding user response (a few lines each).
|
|
114
126
|
2. Sample the results — take up to ~200 instances spread across projects and time; do not feed everything into context at once.
|
|
115
|
-
3. Read
|
|
116
|
-
4. Read existing feedback memory files (
|
|
127
|
+
3. Read `{claude_dir}/rules/` files (these are small) to supplement with explicitly stated preferences.
|
|
128
|
+
4. Read existing feedback memory files (`{claude_dir}/projects/*/memory/*.md`) — these are small and already distilled.
|
|
117
129
|
|
|
118
130
|
This grep-and-sample approach is both efficient and Iron-Rule-safe: the agent uses `rg`/`grep` as tools — no extractor or clustering logic is authored.
|
|
119
131
|
|
|
@@ -121,7 +133,7 @@ This grep-and-sample approach is both efficient and Iron-Rule-safe: the agent us
|
|
|
121
133
|
|
|
122
134
|
### When --dry-run is passed
|
|
123
135
|
|
|
124
|
-
Print what the agent would do (a summary of which paths it would search, what it would write) and STOP — do not spawn the agent.
|
|
136
|
+
Print what the agent would do (a summary of which paths under the resolved `{claude_dir}` it would search, what it would write) and STOP — do not spawn the agent.
|
|
125
137
|
|
|
126
138
|
---
|
|
127
139
|
|
|
@@ -132,15 +144,17 @@ Spawn a single Knowledge agent with this task:
|
|
|
132
144
|
```
|
|
133
145
|
You are distilling a decision-preference profile from past session history.
|
|
134
146
|
|
|
147
|
+
CLAUDE_DIR: {claude_dir} — Claude Code's directory, already resolved; every path below is under it.
|
|
148
|
+
|
|
135
149
|
BOUNDED READING — MANDATORY: transcripts are gigabytes; never full-read them.
|
|
136
|
-
1. Run: rg -l "AskUserQuestion"
|
|
150
|
+
1. Run: rg -l "AskUserQuestion" "{claude_dir}/projects/" 2>/dev/null | head -50
|
|
137
151
|
to find transcript files that contain AskUserQuestion moments.
|
|
138
152
|
2. For each found file, run: rg -A 5 "AskUserQuestion" <file> | head -200
|
|
139
153
|
to extract the question + nearby user response context. Sample broadly —
|
|
140
154
|
aim for ~150-200 instances spread across projects and time windows.
|
|
141
|
-
3. Read
|
|
142
|
-
4. Read all files in
|
|
143
|
-
5. Read all *.md files in
|
|
155
|
+
3. Read {claude_dir}/history.jsonl if it exists (rg "AskUserQuestion" ... similarly).
|
|
156
|
+
4. Read all files in {claude_dir}/rules/ (small — read fully).
|
|
157
|
+
5. Read all *.md files in {claude_dir}/projects/*/memory/ (small — read fully).
|
|
144
158
|
|
|
145
159
|
From this evidence, identify the recurring patterns in how the user answers design
|
|
146
160
|
questions. Look for preferences about:
|
|
@@ -71,7 +71,7 @@ The script body cannot perform this read — you (the main model) do it before a
|
|
|
71
71
|
|
|
72
72
|
### Handoff convention for sequential Code agents within a ticket
|
|
73
73
|
|
|
74
|
-
When a ticket requires multiple sequential Code agent phases, each Code agent writes
|
|
74
|
+
When a ticket requires multiple sequential Code agent phases, each Code agent writes `{toplevel}/.devflow/docs/handoff-{branch_slug}.md` (branch-scoped to prevent concurrent session clobber), `{toplevel}` being `git rev-parse --show-toplevel` in the checkout the ticket's branch is in — never a subdirectory. The next Code agent reads it via HANDOFF_FILE input. PRIOR_PHASE_SUMMARY is the compact in-context form; the handoff file is the durable form that survives context compaction. Always read the handoff file directly — code is authoritative, summaries are supplementary.
|
|
75
75
|
|
|
76
76
|
### IRON RULE (ADR-008: LLM-vs-plumbing)
|
|
77
77
|
|
|
@@ -115,7 +115,7 @@ The following agentType values are valid. Model tiers are shown for reference
|
|
|
115
115
|
---
|
|
116
116
|
|
|
117
117
|
**Requires:** initiative description or spec document path; tracker access only for filing the issues, which the Git agent resolves
|
|
118
|
-
**Produces:** ticket `.md` files at
|
|
118
|
+
**Produces:** ticket `.md` files at `{worktree}/.devflow/docs/tickets/{slug}/{ts}/`, `tracking-issue.md`
|
|
119
119
|
|
|
120
120
|
---
|
|
121
121
|
|
|
@@ -126,7 +126,7 @@ Before authoring, verify:
|
|
|
126
126
|
1. **Workflow tool available:** if the `Workflow` tool is not in your available tools, STOP and tell the user: "The Workflow tool is not available in this session. dynamic-tickets requires Claude Code's dynamic workflow runtime."
|
|
127
127
|
2. **`agentType` support:** confirmed available (spike F5, 2026-06-11). If spawned agents return no results, check that devflow is installed (`devflow init` has been run).
|
|
128
128
|
3. **Tracker paths:** filing, when it runs, happens after the workflow and through the Git agent, which resolves the configured tracker and its access itself and reports `TRACEABILITY: DEGRADED ({reason})` for an issue it cannot file — that ticket stays a local `.md` file. No tracker CLI is checked here.
|
|
129
|
-
4. **No-remote path:** with no remote, the ticket files are still written to
|
|
129
|
+
4. **No-remote path:** with no remote, the ticket files are still written to `{worktree}/.devflow/docs/tickets/{slug}/{ts}/`; whatever the Git agent cannot file without one, it reports as DEGRADED.
|
|
130
130
|
|
|
131
131
|
---
|
|
132
132
|
|
|
@@ -141,13 +141,23 @@ Before you write the workflow script:
|
|
|
141
141
|
**Resolve the evidence policy once per run**, from the repository root, before any step reads the values:
|
|
142
142
|
|
|
143
143
|
```bash
|
|
144
|
-
node "$
|
|
144
|
+
node "$HOME/.devflow/scripts/resolve-evidence-policy.cjs" 2>/dev/null; echo "exit=$?"
|
|
145
145
|
```
|
|
146
146
|
|
|
147
147
|
Accept the output only when it is exactly two lines: `exit=0` last and, before it, one line of the form `EVIDENCE_POLICY=<required|standard> SOURCE=<file|worktree|default|invalid|error> REF=<branch|none>[ WARN=<remote-unavailable|invalid-file|raised-by-compliance|pr-changes-policy>[,…]] ISSUE_REQUIRED=<true|false> APPLY_CONVENTIONS=<true|false> REQUIRE_NON_AUTHOR_APPROVAL=<true|false>` — these fields, in this order, nothing else, where `<branch>` is a branch name such as `main`. **Anything else** (a non-zero exit, no line, extra text, or a missing, reordered or unlisted field or value) ⇒ use `EVIDENCE_POLICY=required SOURCE=error REF=none ISSUE_REQUIRED=true APPLY_CONVENTIONS=true REQUIRE_NON_AUTHOR_APPROVAL=true` instead.
|
|
148
148
|
|
|
149
149
|
Set `EVIDENCE_POLICY`, `ISSUE_REQUIRED`, `APPLY_CONVENTIONS` and `REQUIRE_NON_AUTHOR_APPROVAL` from the accepted line. Pass agents only the three mechanism inputs, never `EVIDENCE_POLICY`. Report `Evidence policy: {EVIDENCE_POLICY} (source: {SOURCE})`, plus any `WARN` tokens as advisory, once in the final report.
|
|
150
150
|
|
|
151
|
+
**Docs root (D-DOCS-ROOT).** Every `.devflow/docs/` path this command reads or writes lives at the checkout's toplevel, never under the directory the session started in. Resolve `{worktree}` from the start directory — `WORKTREE_PATH` if provided, otherwise cwd (`devflow:worktree-support`) — by running
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
git -C "{start}" rev-parse --show-toplevel
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
and using its one-line output. If the command fails (outside a git repository), `{worktree}` is the start directory itself. Every docs path below is written `{worktree}/.devflow/docs/…`; a repo-relative docs path handed to an agent always travels with a `WORKTREE_PATH` naming the checkout it is relative to.
|
|
158
|
+
|
|
159
|
+
Pass `{worktree}` to the workflow as its `root` argument.
|
|
160
|
+
|
|
151
161
|
**1. Apply decisions context**
|
|
152
162
|
|
|
153
163
|
Apply the `devflow:apply-decisions` algorithm to the DECISIONS_CONTEXT loaded per the preamble above: scan the index, Read relevant entries, note the verbatim ADR/PF IDs you will inject into Design agent and Review agent prompts.
|
|
@@ -191,7 +201,8 @@ const constraints = args.constraints || "";
|
|
|
191
201
|
const DECISIONS_CONTEXT = args.decisionsContext || ""; // injected before authoring
|
|
192
202
|
const slug = args.slug || initiative.toLowerCase().replace(/[^a-z0-9]+/g, '-').slice(0, 40);
|
|
193
203
|
const ts = new Date().toISOString().slice(0,16).replace(/[-:T]/g, (c) => c === 'T' ? '_' : c === ':' ? '' : c);
|
|
194
|
-
const
|
|
204
|
+
const ROOT = args.root; // {worktree} from Pre-authoring setup: the checkout's toplevel, never cwd
|
|
205
|
+
const OUTDIR = `${ROOT}/.devflow/docs/tickets/${slug}/${ts}`;
|
|
195
206
|
|
|
196
207
|
// Phase 1: Draft — one Design agent per ticket, all in parallel
|
|
197
208
|
const drafts = await phase("draft", () =>
|
|
@@ -302,8 +313,8 @@ Agent(subagent_type="Git"):
|
|
|
302
313
|
"OPERATION: ensure-traceable-issue
|
|
303
314
|
TASK_DESCRIPTION: {the ticket's title, or the tracking issue's H1}
|
|
304
315
|
REQUIREMENTS: {the ticket's **Wave:** and **Depends on:** lines, then its ## Summary paragraph; or the tracking issue's ## Context}
|
|
305
|
-
PLAN_ARTIFACT_PATH: {the ticket or tracking-issue file path}
|
|
306
|
-
WORKTREE_PATH: {
|
|
316
|
+
PLAN_ARTIFACT_PATH: {the ticket or tracking-issue file path, relative to {worktree}}
|
|
317
|
+
WORKTREE_PATH: {worktree}"
|
|
307
318
|
```
|
|
308
319
|
|
|
309
320
|
3. **Capture** `**Issue**: {ISSUE_REF}` and `**Status**:` from the spawn's `## Issue Traced` Output.
|
|
@@ -593,18 +604,18 @@ Output: write to the artifact path and return { path, title }.`, {
|
|
|
593
604
|
- The `initiative` variable is the raw user input (a description, a spec doc path, or inline text) — read it and distill before passing to agents.
|
|
594
605
|
- The `constraints` variable is optional: any cross-cutting rules (naming discipline, scope filters, authority order) the user supplied.
|
|
595
606
|
- Emit artifact files using the `ticket_body_template()` shape (from `_ticket_template.mds`) for each ticket — write inside agents, since the script body has no filesystem access.
|
|
596
|
-
- Tracking-issue doc goes to
|
|
607
|
+
- Tracking-issue doc goes to `${ROOT}/.devflow/docs/tickets/{slug}/{ts}/tracking-issue.md`, `ROOT` being the workflow's `root` argument (agents do the writing).
|
|
597
608
|
- For large initiatives (more than ~8 tickets), chunk the `parallel(map())` fan-outs into batches (e.g. `for` loop over slices, `await`-ing each batch) so agent concurrency stays bounded and provider rate limits are respected.
|
|
598
609
|
|
|
599
610
|
---
|
|
600
611
|
|
|
601
612
|
### Artifact paths
|
|
602
613
|
|
|
603
|
-
Tickets →
|
|
614
|
+
Tickets → `{worktree}/.devflow/docs/tickets/{slug}/{ts}/{ticket-slug}.md`
|
|
604
615
|
|
|
605
|
-
Tracking issue →
|
|
616
|
+
Tracking issue → `{worktree}/.devflow/docs/tickets/{slug}/{ts}/tracking-issue.md`
|
|
606
617
|
|
|
607
|
-
|
|
618
|
+
`{worktree}` is the docs root resolved in Pre-authoring setup (it honours `WORKTREE_PATH` when provided).
|
|
608
619
|
|
|
609
620
|
Timestamps follow the devflow `YYYY-MM-DD_HHMM` convention (date and time separated by an underscore, e.g. `2026-06-12_1148`). The `ts` variable in the workflow script generates this format.
|
|
610
621
|
|
package/dist/commands/explore.md
CHANGED
|
@@ -28,16 +28,28 @@ Explore a codebase area by spawning parallel agents for flow tracing, dependency
|
|
|
28
28
|
|
|
29
29
|
### Load DECISIONS_CONTEXT
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
The decisions ledger belongs to the repository, not to one checkout: in a linked worktree it lives in the main worktree, and a session started in a subdirectory reads the copy at the repository root. Locate it with ONE git call, run from the start directory — `WORKTREE_PATH` if provided, otherwise cwd (`devflow:worktree-support`):
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
git -C "{start}" rev-parse --path-format=absolute --show-toplevel --git-common-dir
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Line 1 is the checkout's toplevel, line 2 the repository's common git directory. A git older than 2.31 echoes `--path-format=absolute` back as a line of its own first. `{ledger}` is the first of these that applies:
|
|
38
|
+
|
|
39
|
+
1. **The main worktree** — line 2 without its trailing `/.git`, when the output is exactly two lines each beginning with `/`, line 2 ends in `/.git`, and the directory left once it is removed is not your home directory and contains a `.devflow/` directory.
|
|
40
|
+
2. **The toplevel** — line 1, or on an older git the line after the echoed flag.
|
|
41
|
+
3. **The start directory itself** — when the command failed or printed no absolute toplevel (outside a git repository).
|
|
42
|
+
|
|
43
|
+
This is the rule the learning hooks apply (D-LEDGER-MAIN-WORKTREE, D-PROMPT-ROOT), so you read the index the Learning agent writes.
|
|
32
44
|
|
|
33
45
|
**Step 1 — Read the pre-rendered index:**
|
|
34
46
|
|
|
35
|
-
Attempt to read `{
|
|
47
|
+
Attempt to read `{ledger}/.devflow/learning/index.md`.
|
|
36
48
|
|
|
37
49
|
- If the file exists and contains non-empty content: use that content as `DECISIONS_CONTEXT`.
|
|
38
50
|
- If the file is absent or empty: set `DECISIONS_CONTEXT` to `(none)`.
|
|
39
51
|
|
|
40
|
-
|
|
52
|
+
The index is one direct file read, written at render time by `render-decisions.cjs` alongside `decisions.md`/`pitfalls.md` — no `.cjs` script runs here, and the index's own footer names the files that hold each entry's full body.
|
|
41
53
|
|
|
42
54
|
**Step 2 — Apply decisions using `devflow:apply-decisions`:**
|
|
43
55
|
|
|
@@ -105,13 +117,27 @@ Present findings to user. Use AskUserQuestion to offer focused follow-up explora
|
|
|
105
117
|
|
|
106
118
|
### Feature Knowledge Write-Back (Conditional)
|
|
107
119
|
|
|
108
|
-
Resolve the
|
|
120
|
+
Resolve `{worktree}` as the checkout's toplevel, because feature knowledge bases are committed with the branch (D-PROMPT-ROOT): from the start directory — `WORKTREE_PATH` if provided, otherwise cwd (`devflow:worktree-support`) — run
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
git -C "{start}" rev-parse --show-toplevel
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
and use its one-line output. If the command fails (outside a git repository), `{worktree}` is the start directory itself. All paths below are relative to `{worktree}`.
|
|
127
|
+
|
|
128
|
+
**Step 1 — Check the opt-out gate, with `{root}` = `{worktree}`:**
|
|
109
129
|
|
|
110
|
-
**
|
|
130
|
+
**Resolve the settings line** once per worktree root, reusing a line this run already resolved for the same root. `{root}` is the worktree the values are for — the repository root when the run has one worktree:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
node "$HOME/.devflow/scripts/resolve-settings.cjs" "{root}" 2>/dev/null; echo "exit=$?"
|
|
134
|
+
```
|
|
111
135
|
|
|
112
|
-
|
|
136
|
+
Accept the output only when it is exactly two lines: `exit=0` last and, before it, one line of the form `TRACKER=<github|jira|linear> TRACKER_SOURCE=<project|personal|machine|default> TRACKER_WARN=<none|mismatch|invalid> SITE=<none|https://<host>> KEY=<none|<key>> REVIEW_PUBLICATION=<off|auto|full> COMPLIANCE=<off|generic|<id>[,<id>…]> MEMORY=<on|off> LEARNING=<on|off> KNOWLEDGE=<on|off>` — these fields, in this order, nothing else, where `<host>` is a lowercase dotted host name alone, `<key>` is 2–10 of `A-Z`, `0-9` and `_` starting with a letter, and each `<id>` is one of `gdpr`, `hipaa`, `pci-dss`, `soc2`, `iso-27001`, `sox`. **Anything else** (a non-zero exit, no line, extra text, or a missing, reordered or unlisted field or value) ⇒ use `TRACKER=github TRACKER_SOURCE=default TRACKER_WARN=invalid SITE=none KEY=none REVIEW_PUBLICATION=off COMPLIANCE=generic MEMORY=on LEARNING=on KNOWLEDGE=off` instead.
|
|
113
137
|
|
|
114
|
-
|
|
138
|
+
The accepted line is the only source of these values: the script alone folds the committed `.devflow/project.json`, the personal `.devflow/config.json` and the machine manifest.
|
|
139
|
+
|
|
140
|
+
If the settings line says `KNOWLEDGE=off`, skip write-back entirely. The machine switch (`devflow knowledge --disable`), the repository and the personal settings can each turn knowledge off, and none can turn it back on (D-FEATURES-NARROW-ONLY). The fail-closed line says `KNOWLEDGE=off` too, so an unresolvable line skips write-back.
|
|
115
141
|
|
|
116
142
|
**Step 2 — Evaluate whether write-back is warranted:**
|
|
117
143
|
|
|
@@ -150,6 +176,10 @@ The frontmatter in KNOWLEDGE.md is the source of truth — index.md is only a ca
|
|
|
150
176
|
After writing, commit the two files to the current worktree branch yourself by running git via your Bash tool (do not use a script). Stage ONLY .devflow/features/index.md and .devflow/features/{slug}/KNOWLEDGE.md, then commit just those paths with a docs(knowledge): message. Do NOT push, do NOT force, do NOT stage anything else. Follow your Commit Protocol — it is non-blocking, so if any git step fails, report KB_COMMIT and finish normally."
|
|
151
177
|
```
|
|
152
178
|
|
|
179
|
+
**Step 4 — Surface an uncommitted knowledge base:**
|
|
180
|
+
|
|
181
|
+
When the Knowledge agent reports `KB_COMMIT: skipped (detached HEAD)`, the files were written but deliberately not committed — a commit on a detached HEAD becomes unreachable once HEAD moves. Tell the user in the workflow's final report, in one line, that the knowledge base was written but not committed, and name the uncommitted paths the agent listed, so they can commit them on a branch before the worktree is removed. Never commit them yourself.
|
|
182
|
+
|
|
153
183
|
**Failure handling**: Non-blocking. If the Knowledge agent fails, log the failure and continue — the workflow outcome is not affected by write-back success.
|
|
154
184
|
|
|
155
185
|
Set FEATURE_KNOWLEDGE_STATUS = created (if agent spawned) or skipped.
|