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.
Files changed (158) hide show
  1. package/CHANGELOG.md +73 -0
  2. package/README.md +44 -19
  3. package/dist/agents/git.md +13 -15
  4. package/dist/cli/commands/ambient.js +160 -145
  5. package/dist/cli/commands/capture.js +29 -55
  6. package/dist/cli/commands/compliance.js +32 -61
  7. package/dist/cli/commands/context.js +17 -32
  8. package/dist/cli/commands/debug.js +65 -26
  9. package/dist/cli/commands/flags.js +3 -3
  10. package/dist/cli/commands/hud.js +34 -10
  11. package/dist/cli/commands/init-seed.js +40 -4
  12. package/dist/cli/commands/init.js +249 -271
  13. package/dist/cli/commands/install-report.js +10 -15
  14. package/dist/cli/commands/knowledge/index.js +1 -1
  15. package/dist/cli/commands/knowledge/toggle.js +11 -3
  16. package/dist/cli/commands/learning.js +52 -37
  17. package/dist/cli/commands/legacy-hooks.js +11 -14
  18. package/dist/cli/commands/memory.js +67 -78
  19. package/dist/cli/commands/proxy.js +23 -41
  20. package/dist/cli/commands/security.js +5 -13
  21. package/dist/cli/commands/skills.js +21 -3
  22. package/dist/cli/commands/tracker.js +100 -228
  23. package/dist/cli/commands/uninstall.js +343 -138
  24. package/dist/commands/bug-analysis.md +38 -12
  25. package/dist/commands/code-review.md +70 -21
  26. package/dist/commands/debug.md +37 -7
  27. package/dist/commands/dynamic-build.md +66 -17
  28. package/dist/commands/dynamic-plan.md +19 -8
  29. package/dist/commands/dynamic-profile.md +24 -10
  30. package/dist/commands/dynamic-tickets.md +22 -11
  31. package/dist/commands/explore.md +37 -7
  32. package/dist/commands/implement.md +96 -32
  33. package/dist/commands/plan.md +62 -19
  34. package/dist/commands/release.md +2 -2
  35. package/dist/commands/research.md +34 -8
  36. package/dist/commands/resolve.md +65 -17
  37. package/dist/commands/self-review.md +45 -9
  38. package/dist/core/compliance-compose.js +27 -27
  39. package/dist/core/evidence-policy.js +240 -24
  40. package/dist/core/feature-config.js +94 -25
  41. package/dist/core/feature-switch.js +1 -1
  42. package/dist/core/flags.js +30 -2
  43. package/dist/core/fs-atomic.js +27 -0
  44. package/dist/core/hook-log-dirs.js +104 -0
  45. package/dist/core/learning-tuning-config.js +5 -3
  46. package/dist/core/ledger-root.js +102 -0
  47. package/dist/core/manifest.js +6 -4
  48. package/dist/core/mds-variants.js +34 -97
  49. package/dist/core/migrations.js +49 -23
  50. package/dist/core/plugins.js +5 -4
  51. package/dist/core/project-paths.js +0 -17
  52. package/dist/core/same-location.js +25 -0
  53. package/dist/core/tracker.js +226 -139
  54. package/dist/hud/components/config-counts.js +15 -4
  55. package/dist/hud/components/learning-counts.js +14 -0
  56. package/dist/hud/config.js +2 -1
  57. package/dist/hud/cost-history.js +2 -4
  58. package/dist/hud/git.js +52 -7
  59. package/dist/hud/index.js +7 -9
  60. package/dist/skills/git/references/pr/check-merge-readiness.md +1 -1
  61. package/dist/skills/git/references/pr/ensure-pr-ready.md +1 -1
  62. package/dist/skills/git/references/pr/update-pr-evidence.md +1 -1
  63. package/dist/skills/git/references/tracker/_mcp.md +1 -1
  64. package/dist/skills/git/references/tracker/github/backlink-shipped-issues.md +1 -1
  65. package/dist/skills/git/references/tracker/github/ensure-traceable-issue.md +1 -1
  66. package/dist/skills/git/references/tracker/github/gather-release-evidence.md +2 -2
  67. package/dist/skills/git/references/tracker/github/manage-debt.md +3 -3
  68. package/dist/skills/git/references/tracker/jira/backlink-shipped-issues.md +1 -1
  69. package/dist/skills/git/references/tracker/jira/ensure-traceable-issue.md +1 -1
  70. package/dist/skills/git/references/tracker/jira/gather-release-evidence.md +2 -2
  71. package/dist/skills/git/references/tracker/jira/manage-debt.md +1 -1
  72. package/dist/skills/git/references/tracker/jira/post-wave-report.md +1 -1
  73. package/dist/skills/git/references/tracker/jira/setup-task.md +1 -1
  74. package/dist/skills/git/references/tracker/linear/backlink-shipped-issues.md +1 -1
  75. package/dist/skills/git/references/tracker/linear/ensure-traceable-issue.md +1 -1
  76. package/dist/skills/git/references/tracker/linear/gather-release-evidence.md +2 -2
  77. package/dist/skills/git/references/tracker/linear/manage-debt.md +1 -1
  78. package/dist/skills/git/references/tracker/linear/post-wave-report.md +1 -1
  79. package/dist/skills/git/references/tracker/linear/setup-task.md +1 -1
  80. package/dist/targets/claude-code/claude-paths.js +59 -57
  81. package/dist/targets/claude-code/compliance-install.js +49 -65
  82. package/dist/targets/claude-code/hooks.js +108 -3
  83. package/dist/targets/claude-code/installer.js +30 -57
  84. package/dist/targets/claude-code/post-install.js +232 -139
  85. package/dist/targets/claude-code/tracker-install.js +38 -65
  86. package/package.json +5 -4
  87. package/src/assets/agents/code.md +4 -3
  88. package/src/assets/agents/design.md +1 -0
  89. package/src/assets/agents/git.mds +55 -57
  90. package/src/assets/agents/knowledge.md +2 -2
  91. package/src/assets/agents/review.md +3 -1
  92. package/src/assets/agents/tracker.md +37 -30
  93. package/src/assets/commands/_partials/_compliance.mds +19 -1
  94. package/src/assets/commands/_partials/_decisions.mds +15 -3
  95. package/src/assets/commands/_partials/_docs_root.mds +35 -0
  96. package/src/assets/commands/_partials/_engine.mds +2 -2
  97. package/src/assets/commands/_partials/_evidence_policy.mds +3 -3
  98. package/src/assets/commands/_partials/_factory.mds +1 -1
  99. package/src/assets/commands/_partials/_knowledge.mds +27 -9
  100. package/src/assets/commands/_partials/_plan_contract.mds +2 -2
  101. package/src/assets/commands/_partials/_preamble.mds +1 -1
  102. package/src/assets/commands/_partials/_publication.mds +6 -2
  103. package/src/assets/commands/_partials/_settings.mds +28 -0
  104. package/src/assets/commands/_partials/_ticket_template.mds +3 -3
  105. package/src/assets/commands/_partials/_tracker.mds +4 -4
  106. package/src/assets/commands/_partials/_wave.mds +4 -4
  107. package/src/assets/commands/bug-analysis.mds +19 -17
  108. package/src/assets/commands/code-review.mds +39 -33
  109. package/src/assets/commands/debug.mds +4 -5
  110. package/src/assets/commands/dynamic-build.mds +75 -53
  111. package/src/assets/commands/dynamic-plan.mds +20 -15
  112. package/src/assets/commands/dynamic-profile.mds +24 -11
  113. package/src/assets/commands/dynamic-tickets.mds +25 -20
  114. package/src/assets/commands/explore.mds +4 -5
  115. package/src/assets/commands/implement.mds +58 -45
  116. package/src/assets/commands/plan.mds +34 -29
  117. package/src/assets/commands/release.md +2 -2
  118. package/src/assets/commands/research.mds +11 -9
  119. package/src/assets/commands/resolve.mds +41 -39
  120. package/src/assets/commands/self-review.mds +24 -25
  121. package/src/assets/mds/git/_pr.mds +61 -61
  122. package/src/assets/mds/git/_references.mds +19 -19
  123. package/src/assets/mds/tracker/_common.mds +8 -8
  124. package/src/assets/mds/tracker/_github.mds +71 -71
  125. package/src/assets/mds/tracker/_jira.mds +74 -74
  126. package/src/assets/mds/tracker/_linear.mds +75 -75
  127. package/src/assets/mds/tracker/_mcp.mds +23 -17
  128. package/src/assets/scripts/hooks/background-memory-update +35 -19
  129. package/src/assets/scripts/hooks/capture-prompt +18 -12
  130. package/src/assets/scripts/hooks/capture-question +18 -12
  131. package/src/assets/scripts/hooks/capture-turn +27 -17
  132. package/src/assets/scripts/hooks/debug-trace +11 -6
  133. package/src/assets/scripts/hooks/ensure-devflow-init +33 -6
  134. package/src/assets/scripts/hooks/ensure-proxy +9 -8
  135. package/src/assets/scripts/hooks/ensure-root-gitignore +111 -36
  136. package/src/assets/scripts/hooks/git-marker +48 -0
  137. package/src/assets/scripts/hooks/json-helper.cjs +6 -1
  138. package/src/assets/scripts/hooks/lib/project-paths.cjs +0 -19
  139. package/src/assets/scripts/hooks/log-paths +80 -0
  140. package/src/assets/scripts/hooks/memory-worker +17 -15
  141. package/src/assets/scripts/hooks/pre-compact-memory +41 -16
  142. package/src/assets/scripts/hooks/queue-append +104 -30
  143. package/src/assets/scripts/hooks/resolve-project-root +101 -7
  144. package/src/assets/scripts/hooks/session-start-context +289 -122
  145. package/src/assets/scripts/hooks/session-start-memory +35 -16
  146. package/src/assets/scripts/lib/project-config.cjs +633 -0
  147. package/src/assets/scripts/resolve-evidence-policy.cjs +300 -220
  148. package/src/assets/scripts/resolve-settings.cjs +1054 -0
  149. package/src/assets/scripts/verify-evidence.cjs +1 -1
  150. package/src/assets/skills/compliance/SKILL.md +2 -2
  151. package/src/assets/skills/docs-framework/SKILL.md +6 -7
  152. package/src/assets/skills/docs-framework/references/patterns.md +10 -17
  153. package/src/assets/skills/gap-analysis/SKILL.md +2 -2
  154. package/src/assets/skills/git/references/github-api.md +9 -9
  155. package/src/assets/skills/git/references/patterns.md +1 -1
  156. package/src/assets/skills/worktree-support/SKILL.md +1 -1
  157. package/src/assets/skills/worktree-support/references/roots.md +29 -0
  158. package/src/targets/claude-code/templates/managed-settings.json +25 -9
@@ -22,19 +22,27 @@ Run a proactive bug analysis on the current branch by combining static analysis
22
22
  **Resolve the evidence policy once per run**, from the repository root, before any step reads the values:
23
23
 
24
24
  ```bash
25
- node "${DEVFLOW_DIR:-$HOME/.devflow}/scripts/resolve-evidence-policy.cjs" 2>/dev/null; echo "exit=$?"
25
+ node "$HOME/.devflow/scripts/resolve-evidence-policy.cjs" 2>/dev/null; echo "exit=$?"
26
26
  ```
27
27
 
28
28
  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.
29
29
 
30
30
  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.
31
31
 
32
+ **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
33
+
34
+ ```bash
35
+ git -C "{start}" rev-parse --show-toplevel
36
+ ```
37
+
38
+ 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.
39
+
32
40
  Render the test-plan block from `/implement`'s evidence file, and from nothing else:
33
41
  1. `branch_slug` is `git branch --show-current` with every `/` replaced by `-`.
34
42
  2. Only when `branch_slug` matches `^[A-Za-z0-9._-]{1,200}$` and the file exists, run (the path double-quoted):
35
43
 
36
44
  ```bash
37
- node "${DEVFLOW_DIR:-$HOME/.devflow}/scripts/verify-evidence.cjs" render --plan ".devflow/docs/evidence-{branch_slug}.md"; echo "exit=$?"
45
+ node "$HOME/.devflow/scripts/verify-evidence.cjs" render --plan "{worktree}/.devflow/docs/evidence-{branch_slug}.md"; echo "exit=$?"
38
46
  ```
39
47
 
40
48
  3. On `exit=0`, `PR_TEST_PLAN_BLOCK` is its stdout byte for byte without that `exit=` line; in every other case it is `(none)`. Nothing here waits on it: the Git agent pastes it only behind its own check, and only into a PR it creates.
@@ -67,7 +75,7 @@ If `pr_number` is absent or the command fails, set `PR_DESCRIPTION` to `(none)`.
67
75
  **Produces:** DIFF_RANGE, ANALYSIS_DIR
68
76
  **Requires:** BRANCH_INFO
69
77
 
70
- 1. Check `.devflow/docs/bug-analysis/{branch-slug}/.last-analysis-head`:
78
+ 1. Check `{worktree}/.devflow/docs/bug-analysis/{branch-slug}/.last-analysis-head`:
71
79
  - **If exists AND `--full` NOT set:**
72
80
  - Read the SHA from the file
73
81
  - Verify reachable: `git cat-file -t {sha}` — if exit code non-zero (rebase invalidated SHA), fall through to full
@@ -76,7 +84,7 @@ If `pr_number` is absent or the command fails, set `PR_DESCRIPTION` to `(none)`.
76
84
  - **If not exists, unreachable SHA, or `--full`:**
77
85
  - Set `DIFF_RANGE` to `{base_branch}...HEAD`
78
86
  2. Generate timestamp: `YYYY-MM-DD_HHMM`. If directory already exists (same-minute collision), append seconds (`YYYY-MM-DD_HHMMSS`).
79
- 3. Create timestamped analysis directory: `mkdir -p .devflow/docs/bug-analysis/{branch-slug}/{timestamp}/`
87
+ 3. Create timestamped analysis directory: `mkdir -p "{worktree}/.devflow/docs/bug-analysis/{branch-slug}/{timestamp}/"`
80
88
  4. Set `ANALYSIS_DIR` to that path.
81
89
 
82
90
  #### Step 2b: Check Changed Files
@@ -175,16 +183,28 @@ If no tool produced findings: set `STATIC_FINDINGS` to `(none)`.
175
183
 
176
184
  ### Load DECISIONS_CONTEXT
177
185
 
178
- Resolve the worktree root using the `devflow:worktree-support` algorithm (use WORKTREE_PATH if provided, otherwise cwd). All paths below are relative to `{worktree}`.
186
+ 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`):
187
+
188
+ ```bash
189
+ git -C "{start}" rev-parse --path-format=absolute --show-toplevel --git-common-dir
190
+ ```
191
+
192
+ 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:
193
+
194
+ 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.
195
+ 2. **The toplevel** — line 1, or on an older git the line after the echoed flag.
196
+ 3. **The start directory itself** — when the command failed or printed no absolute toplevel (outside a git repository).
197
+
198
+ This is the rule the learning hooks apply (D-LEDGER-MAIN-WORKTREE, D-PROMPT-ROOT), so you read the index the Learning agent writes.
179
199
 
180
200
  **Step 1 — Read the pre-rendered index:**
181
201
 
182
- Attempt to read `{worktree}/.devflow/learning/index.md`.
202
+ Attempt to read `{ledger}/.devflow/learning/index.md`.
183
203
 
184
204
  - If the file exists and contains non-empty content: use that content as `DECISIONS_CONTEXT`.
185
205
  - If the file is absent or empty: set `DECISIONS_CONTEXT` to `(none)`.
186
206
 
187
- **No subprocess, no `.cjs` script.** This is a single direct file read — the index is written at render time by `render-decisions.cjs` alongside `decisions.md`/`pitfalls.md`.
207
+ 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.
188
208
 
189
209
  **Step 2 — Apply decisions using `devflow:apply-decisions`:**
190
210
 
@@ -194,7 +214,13 @@ When `DECISIONS_CONTEXT` is not `(none)`, follow `devflow:apply-decisions` to sc
194
214
 
195
215
  ### Load Feature Knowledge
196
216
 
197
- Resolve the worktree root using the `devflow:worktree-support` algorithm (use WORKTREE_PATH if provided, otherwise cwd). All paths below are relative to `{worktree}`.
217
+ 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
218
+
219
+ ```bash
220
+ git -C "{start}" rev-parse --show-toplevel
221
+ ```
222
+
223
+ 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}`.
198
224
 
199
225
  **Step 1 — Read the index cache:**
200
226
 
@@ -229,11 +255,11 @@ Concatenate the selected KNOWLEDGE.md files under slug headers:
229
255
 
230
256
  If no KBs exist, no KBs are relevant, or `.devflow/features/` is absent, set `FEATURE_KNOWLEDGE` to `(none)`.
231
257
 
232
- **No subprocess, no git calls, no `.cjs` script.** This entire step is direct file reads — 1 index read (or N frontmatter reads on fallback), bounded by KB count.
258
+ **One git call, then direct file reads — no `.cjs` script.** After resolving `{worktree}`, this step is 1 index read (or N frontmatter reads on fallback), bounded by KB count.
233
259
 
234
260
  #### Plan Artifact
235
261
 
236
- 1. List `.devflow/docs/design/*.md` — sort descending by filename (timestamps are naturally sortable), scan the 10 most recent
262
+ 1. List `{worktree}/.devflow/docs/design/*.md` — sort descending by filename (timestamps are naturally sortable), scan the 10 most recent
237
263
  2. Read the most recent file if it exists
238
264
  3. Extract `## Acceptance Criteria` section → parse into table: `| ID | Criterion | Type | Testable Condition |`
239
265
  4. Set `PLAN_CONTEXT` to plan summary; `ACCEPTANCE_RULES` to the table
@@ -303,7 +329,7 @@ Output: {ANALYSIS_DIR}/bug-analysis-summary.md"
303
329
 
304
330
  **Requires:** BRANCH_INFO, ANALYSIS_DIR
305
331
 
306
- 1. Write current HEAD SHA to `.devflow/docs/bug-analysis/{branch-slug}/.last-analysis-head`
332
+ 1. Write current HEAD SHA to `{worktree}/.devflow/docs/bug-analysis/{branch-slug}/.last-analysis-head`
307
333
  2. Report to user:
308
334
 
309
335
  ```
@@ -354,7 +380,7 @@ Run `/resolve` to process and fix these findings.
354
380
  ├─ Phase 3: Context Loading
355
381
  │ ├─ index.md (pre-rendered) → DECISIONS_CONTEXT
356
382
  │ ├─ Feature knowledge load → FEATURE_KNOWLEDGE
357
- │ └─ .devflow/docs/design/*.md → PLAN_CONTEXT + ACCEPTANCE_RULES
383
+ │ └─ {worktree}/.devflow/docs/design/*.md → PLAN_CONTEXT + ACCEPTANCE_RULES
358
384
  │
359
385
  ├─ Phase 4: File Analysis
360
386
  │ └─ Detect active focuses (security + functional always; integration + usability conditional)
@@ -24,18 +24,32 @@ Run a comprehensive code review of the current branch by spawning parallel revie
24
24
 
25
25
  1. **Discover reviewable worktrees** using the `devflow:worktree-support` skill discovery algorithm:
26
26
  - Run `git worktree list --porcelain` → parse, filter (skip protected/detached/mid-rebase), dedup by branch, sort by recent commit
27
- - See `~/.claude/skills/devflow:worktree-support/SKILL.md` for the full 7-step algorithm and canonical protected branch list
27
+ - See the `devflow:worktree-support` skill for the full 7-step algorithm and canonical protected branch list
28
28
  2. **If `--path` flag provided:** use only that worktree, skip discovery
29
29
  **`--path` validation**: Before proceeding, verify the path exists as a directory and appears in `git worktree list` output. If not: report error and stop.
30
30
  3. **If only 1 reviewable worktree** (the common case): proceed as single-worktree flow — zero behavior change
31
31
  4. **If multiple reviewable worktrees:** report "Found N worktrees with reviewable branches: {list with paths and branches}" and proceed with multi-worktree flow
32
32
 
33
- #### Step 0b: Resolve COMPLIANCE_SKILL_INSTALLED
33
+ #### Step 0b: Resolve the compliance lens
34
34
 
35
- **Produces:** COMPLIANCE_SKILL_INSTALLED
35
+ **Produces:** COMPLIANCE_ACTIVE, COMPLIANCE_FRAMEWORKS
36
36
 
37
- **Resolve `COMPLIANCE_SKILL_INSTALLED` once per run:** Check whether `~/.claude/skills/devflow:compliance/SKILL.md` exists (one file-existence check, read-only, silent). Set `COMPLIANCE_SKILL_INSTALLED = true` if the file exists, `false` otherwise.
38
- Reuse this result for every worktree and every downstream phase.
37
+ **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):
38
+
39
+ **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:
40
+
41
+ ```bash
42
+ node "$HOME/.devflow/scripts/resolve-settings.cjs" "{root}" 2>/dev/null; echo "exit=$?"
43
+ ```
44
+
45
+ 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.
46
+
47
+ 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.
48
+
49
+ **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.
50
+
51
+ `COMPLIANCE_ACTIVE` is `true` unless `COMPLIANCE_FRAMEWORKS` is `off`.
52
+ Keep each worktree's values for every downstream phase of that worktree.
39
53
 
40
54
  #### Step 0b-ii: Resolve the evidence policy
41
55
 
@@ -44,7 +58,7 @@ Reuse this result for every worktree and every downstream phase.
44
58
  **Resolve the evidence policy once per run**, from the repository root, before any step reads the values:
45
59
 
46
60
  ```bash
47
- node "${DEVFLOW_DIR:-$HOME/.devflow}/scripts/resolve-evidence-policy.cjs" 2>/dev/null; echo "exit=$?"
61
+ node "$HOME/.devflow/scripts/resolve-evidence-policy.cjs" 2>/dev/null; echo "exit=$?"
48
62
  ```
49
63
 
50
64
  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.
@@ -67,7 +81,7 @@ Render the test-plan block (per worktree) from `/implement`'s evidence file, and
67
81
  2. Only when `branch_slug` matches `^[A-Za-z0-9._-]{1,200}$` and the file exists, run (the path double-quoted):
68
82
 
69
83
  ```bash
70
- node "${DEVFLOW_DIR:-$HOME/.devflow}/scripts/verify-evidence.cjs" render --plan "{worktree}/.devflow/docs/evidence-{branch_slug}.md"; echo "exit=$?"
84
+ node "$HOME/.devflow/scripts/verify-evidence.cjs" render --plan "{worktree}/.devflow/docs/evidence-{branch_slug}.md"; echo "exit=$?"
71
85
  ```
72
86
 
73
87
  3. On `exit=0`, `PR_TEST_PLAN_BLOCK` is its stdout byte for byte without that `exit=` line; in every other case it is `(none)`. Nothing here waits on it: the Git agent pastes it only behind its own check, and only into a PR it creates.
@@ -162,16 +176,26 @@ MAX_REVIEW_CYCLES = 10
162
176
 
163
177
  For each reviewable worktree, call:
164
178
 
165
- **Resolve `REVIEW_PUBLICATION` per worktree:** Read the current worktree's `.devflow/config.json` (a single, direct file read — multi-worktree repos may have different publication settings per worktree root). If the file exists and `reviewPublication` is one of `auto`, `full`, or `off`, set `REVIEW_PUBLICATION` to that value; otherwise set `REVIEW_PUBLICATION = "auto"`.
179
+ **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:
180
+
181
+ ```bash
182
+ node "$HOME/.devflow/scripts/resolve-settings.cjs" "{root}" 2>/dev/null; echo "exit=$?"
183
+ ```
184
+
185
+ 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.
186
+
187
+ 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.
188
+
189
+ **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.
166
190
 
167
- **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: a configured `stub` is unrecognised and resolves to `auto` like any other.
191
+ **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.
168
192
 
169
193
  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.
170
194
 
171
195
  ### Phase 1: Analyze Changed Files
172
196
 
173
197
  **Produces:** REVIEW_FOCUS_LIST
174
- **Requires:** DIFF_RANGE, COMPLIANCE_SKILL_INSTALLED (from Step 0b)
198
+ **Requires:** DIFF_RANGE, COMPLIANCE_ACTIVE (from Step 0b)
175
199
 
176
200
  Per worktree, detect file types in diff using `DIFF_RANGE` to determine conditional reviews.
177
201
 
@@ -188,30 +212,48 @@ Per worktree, detect file types in diff using `DIFF_RANGE` to determine conditio
188
212
  | DB/migration files | database |
189
213
  | Dependency files changed | dependencies |
190
214
  | Docs or significant code | documentation |
191
- | COMPLIANCE_SKILL_INSTALLED AND diff touches regulated surface | compliance |
215
+ | COMPLIANCE_ACTIVE AND diff touches regulated surface | compliance |
192
216
 
193
- If `COMPLIANCE_SKILL_INSTALLED` AND the diff touches regulated surface (data models, auth flows, logging/observability, payments, IaC, retention): add `compliance` to REVIEW_FOCUS_LIST for this worktree.
217
+ If `COMPLIANCE_ACTIVE` AND the diff touches regulated surface (data models, auth flows, logging/observability, payments, IaC, retention): add `compliance` to REVIEW_FOCUS_LIST for this worktree.
194
218
 
195
- **Language focus presence gate.** The eight language focuses — `typescript`, `react`, `accessibility`, `ui-design`, `go`, `java`, `python`, `rust` — ship with optional plugins, so their pattern skills are installed only when the user selected that plugin. Gate them exactly as `compliance` is gated: for each language focus the table above would add, check whether `~/.claude/skills/devflow:{focus}/SKILL.md` exists (one file-existence check per candidate focus, read-only, silent). If it does not exist, do NOT add that focus to `REVIEW_FOCUS_LIST` and do NOT spawn a Review agent for it — the file-type condition alone never spawns a language focus. The eight core focuses are unconditional and are never presence-gated.
219
+ **Language focus presence gate.** The eight language focuses — `typescript`, `react`, `accessibility`, `ui-design`, `go`, `java`, `python`, `rust` — ship with optional plugins, so their pattern skills are installed only when the user selected that plugin. Gate them by presence: for each language focus the table above would add, check whether `{claude_dir}/skills/devflow:{focus}/SKILL.md` exists, `{claude_dir}` being Claude Code's directory as the installer resolves it — `CLAUDE_CONFIG_DIR` when that is set to an absolute path, else `$HOME/.claude` (D-CLAUDE-DIR-PROMPTS). Run one read-only, silent check per candidate focus:
220
+
221
+ ```bash
222
+ d="${CLAUDE_CONFIG_DIR:-}"; case "$d" in /*) ;; *) d="$HOME/.claude" ;; esac; test -f "$d/skills/devflow:{focus}/SKILL.md"; echo "exit=$?"
223
+ ```
224
+
225
+ Only `exit=0` means the skill is installed. On any other result, do NOT add that focus to `REVIEW_FOCUS_LIST` and do NOT spawn a Review agent for it — the file-type condition alone never spawns a language focus. The eight core focuses are unconditional and are never presence-gated.
196
226
 
197
227
  ### Phase 1b: Load Decisions Index
198
228
 
199
- **Produces:** DECISIONS_CONTEXT, FEATURE_KNOWLEDGE, COMPLIANCE_SKILL_INSTALLED (carried from Step 0b)
229
+ **Produces:** DECISIONS_CONTEXT, FEATURE_KNOWLEDGE, COMPLIANCE_FRAMEWORKS (carried from Step 0b)
200
230
 
201
231
  **Load Companion Skills** — Load via Skill tool: `devflow:quality-gates`, `devflow:software-design`. If a skill fails to load, continue without it.
202
232
 
203
233
  ### Load DECISIONS_CONTEXT
204
234
 
205
- Resolve the worktree root using the `devflow:worktree-support` algorithm (use WORKTREE_PATH if provided, otherwise cwd). All paths below are relative to `{worktree}`.
235
+ 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`):
236
+
237
+ ```bash
238
+ git -C "{start}" rev-parse --path-format=absolute --show-toplevel --git-common-dir
239
+ ```
240
+
241
+ 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:
242
+
243
+ 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.
244
+ 2. **The toplevel** — line 1, or on an older git the line after the echoed flag.
245
+ 3. **The start directory itself** — when the command failed or printed no absolute toplevel (outside a git repository).
246
+
247
+ This is the rule the learning hooks apply (D-LEDGER-MAIN-WORKTREE, D-PROMPT-ROOT), so you read the index the Learning agent writes.
206
248
 
207
249
  **Step 1 — Read the pre-rendered index:**
208
250
 
209
- Attempt to read `{worktree}/.devflow/learning/index.md`.
251
+ Attempt to read `{ledger}/.devflow/learning/index.md`.
210
252
 
211
253
  - If the file exists and contains non-empty content: use that content as `DECISIONS_CONTEXT`.
212
254
  - If the file is absent or empty: set `DECISIONS_CONTEXT` to `(none)`.
213
255
 
214
- **No subprocess, no `.cjs` script.** This is a single direct file read — the index is written at render time by `render-decisions.cjs` alongside `decisions.md`/`pitfalls.md`.
256
+ 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.
215
257
 
216
258
  **Step 2 — Apply decisions using `devflow:apply-decisions`:**
217
259
 
@@ -221,7 +263,13 @@ This produces a compact index of active ADR/PF entries. Pass `DECISIONS_CONTEXT`
221
263
 
222
264
  ### Load Feature Knowledge
223
265
 
224
- Resolve the worktree root using the `devflow:worktree-support` algorithm (use WORKTREE_PATH if provided, otherwise cwd). All paths below are relative to `{worktree}`.
266
+ 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
267
+
268
+ ```bash
269
+ git -C "{start}" rev-parse --show-toplevel
270
+ ```
271
+
272
+ 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}`.
225
273
 
226
274
  **Step 1 — Read the index cache:**
227
275
 
@@ -256,7 +304,7 @@ Concatenate the selected KNOWLEDGE.md files under slug headers:
256
304
 
257
305
  If no KBs exist, no KBs are relevant, or `.devflow/features/` is absent, set `FEATURE_KNOWLEDGE` to `(none)`.
258
306
 
259
- **No subprocess, no git calls, no `.cjs` script.** This entire step is direct file reads — 1 index read (or N frontmatter reads on fallback), bounded by KB count.
307
+ **One git call, then direct file reads — no `.cjs` script.** After resolving `{worktree}`, this step is 1 index read (or N frontmatter reads on fallback), bounded by KB count.
260
308
 
261
309
  Pass `FEATURE_KNOWLEDGE` to all Review agents alongside `DECISIONS_CONTEXT`.
262
310
 
@@ -304,6 +352,7 @@ DECISIONS_CONTEXT: {decisions_context}
304
352
  FEATURE_KNOWLEDGE: {feature_knowledge}
305
353
  PR_DESCRIPTION: <pr-description>{pr_description}</pr-description>
306
354
  PRIOR_RESOLUTIONS: <prior-resolution-summary>{prior_resolutions}</prior-resolution-summary>
355
+ COMPLIANCE_FRAMEWORKS: {COMPLIANCE_FRAMEWORKS} (compliance focus only)
307
356
  If PRIOR_RESOLUTIONS is not (none), follow Cross-Cycle Awareness in review.md.
308
357
  Follow devflow:apply-decisions to scan the index and Read full ADR/PF bodies on demand.
309
358
  Follow devflow:apply-feature-knowledge for FEATURE_KNOWLEDGE — feature-specific patterns and anti-patterns inform findings.
@@ -368,7 +417,7 @@ In multi-worktree mode, report results per worktree.
368
417
  │
369
418
  ├─ Phase 0: Worktree Discovery & Pre-flight
370
419
  │ ├─ Step 0a: git worktree list → filter reviewable
371
- │ ├─ Step 0b: Resolve COMPLIANCE_SKILL_INSTALLED
420
+ │ ├─ Step 0b: Resolve the compliance lens
372
421
  │ ├─ Step 0c: Git agent (ensure-pr-ready) per worktree [parallel]
373
422
  │ ├─ Step 0d: Incremental detection + timestamp setup per worktree
374
423
  │ ├─ Step 0e-i: Load prior resolution-summary.md
@@ -419,7 +468,7 @@ In multi-worktree mode, report results per worktree.
419
468
  ## Backwards Compatibility
420
469
 
421
470
  - **Single worktree**: Auto-discovery finds only one worktree → proceeds exactly as before. Zero behavior change.
422
- - **Legacy flat layout**: If `.devflow/docs/reviews/{branch-slug}/` contains flat `*.md` files (no timestamped subdirectories), new runs create timestamped subdirectories. Old flat files remain untouched.
471
+ - **Legacy flat layout**: If `{worktree}/.devflow/docs/reviews/{branch-slug}/` contains flat `*.md` files (no timestamped subdirectories), new runs create timestamped subdirectories. Old flat files remain untouched.
423
472
 
424
473
  ## Principles
425
474
 
@@ -30,16 +30,28 @@ Investigate bugs by spawning parallel agents, each pursuing a different hypothes
30
30
 
31
31
  ### Load DECISIONS_CONTEXT
32
32
 
33
- Resolve the worktree root using the `devflow:worktree-support` algorithm (use WORKTREE_PATH if provided, otherwise cwd). All paths below are relative to `{worktree}`.
33
+ 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`):
34
+
35
+ ```bash
36
+ git -C "{start}" rev-parse --path-format=absolute --show-toplevel --git-common-dir
37
+ ```
38
+
39
+ 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:
40
+
41
+ 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.
42
+ 2. **The toplevel** — line 1, or on an older git the line after the echoed flag.
43
+ 3. **The start directory itself** — when the command failed or printed no absolute toplevel (outside a git repository).
44
+
45
+ This is the rule the learning hooks apply (D-LEDGER-MAIN-WORKTREE, D-PROMPT-ROOT), so you read the index the Learning agent writes.
34
46
 
35
47
  **Step 1 — Read the pre-rendered index:**
36
48
 
37
- Attempt to read `{worktree}/.devflow/learning/index.md`.
49
+ Attempt to read `{ledger}/.devflow/learning/index.md`.
38
50
 
39
51
  - If the file exists and contains non-empty content: use that content as `DECISIONS_CONTEXT`.
40
52
  - If the file is absent or empty: set `DECISIONS_CONTEXT` to `(none)`.
41
53
 
42
- **No subprocess, no `.cjs` script.** This is a single direct file read — the index is written at render time by `render-decisions.cjs` alongside `decisions.md`/`pitfalls.md`.
54
+ 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.
43
55
 
44
56
  **Step 2 — Apply decisions using `devflow:apply-decisions`:**
45
57
 
@@ -202,13 +214,27 @@ Ask user via AskUserQuestion: "Want me to implement this fix?"
202
214
 
203
215
  ### Feature Knowledge Write-Back (Conditional)
204
216
 
205
- Resolve the worktree root using the `devflow:worktree-support` algorithm (use WORKTREE_PATH if provided, otherwise cwd). All paths below are relative to `{worktree}`.
217
+ 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
218
+
219
+ ```bash
220
+ git -C "{start}" rev-parse --show-toplevel
221
+ ```
222
+
223
+ 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}`.
224
+
225
+ **Step 1 — Check the opt-out gate, with `{root}` = `{worktree}`:**
206
226
 
207
- **Step 1 — Check the opt-out gate:**
227
+ **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:
228
+
229
+ ```bash
230
+ node "$HOME/.devflow/scripts/resolve-settings.cjs" "{root}" 2>/dev/null; echo "exit=$?"
231
+ ```
208
232
 
209
- Read `~/.devflow/manifest.json`. If `features.knowledge` is `false`, skip write-back entirely — the user disabled knowledge bases for every project (`devflow init --no-knowledge` or `devflow knowledge --disable`). The project's `.devflow/config.json` is not a gate: knowledge is switched machine-wide only.
233
+ 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.
210
234
 
211
- A missing file or a missing field means write-back is allowed (default is enabled).
235
+ 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.
236
+
237
+ 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.
212
238
 
213
239
  **Step 2 — Evaluate whether write-back is warranted:**
214
240
 
@@ -247,6 +273,10 @@ The frontmatter in KNOWLEDGE.md is the source of truth — index.md is only a ca
247
273
  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."
248
274
  ```
249
275
 
276
+ **Step 4 — Surface an uncommitted knowledge base:**
277
+
278
+ 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.
279
+
250
280
  **Failure handling**: Non-blocking. If the Knowledge agent fails, log the failure and continue — the workflow outcome is not affected by write-back success.
251
281
 
252
282
  ## Architecture