devflow-kit 3.3.0 → 3.4.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 (138) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/agents/code.md +330 -0
  3. package/{src/assets → dist}/agents/design.md +1 -1
  4. package/{src/assets → dist}/agents/diagnose.md +1 -2
  5. package/dist/agents/git.md +29 -56
  6. package/{src/assets → dist}/agents/knowledge.md +4 -3
  7. package/{src/assets → dist}/agents/research.md +2 -2
  8. package/{src/assets → dist}/agents/review.md +8 -7
  9. package/{src/assets → dist}/agents/scrutinize.md +1 -1
  10. package/dist/agents/skim.md +148 -0
  11. package/{src/assets → dist}/agents/triage.md +1 -1
  12. package/dist/cli/commands/init.js +62 -0
  13. package/dist/cli/commands/learning.js +38 -3
  14. package/dist/cli/commands/uninstall.js +42 -1
  15. package/dist/commands/bug-analysis.md +30 -8
  16. package/dist/commands/code-review.md +141 -60
  17. package/dist/commands/debug.md +14 -12
  18. package/dist/commands/dynamic-build.md +37 -38
  19. package/dist/commands/dynamic-plan.md +30 -18
  20. package/dist/commands/dynamic-profile.md +27 -13
  21. package/dist/commands/dynamic-tickets.md +28 -14
  22. package/dist/commands/explore.md +15 -13
  23. package/dist/commands/implement.md +33 -28
  24. package/dist/commands/plan.md +37 -24
  25. package/dist/commands/release.md +69 -4
  26. package/dist/commands/research.md +33 -11
  27. package/dist/commands/resolve.md +35 -32
  28. package/dist/commands/self-review.md +36 -23
  29. package/dist/core/agent-models.js +43 -0
  30. package/dist/core/assets.js +55 -10
  31. package/dist/core/claude-md-audit.js +190 -0
  32. package/dist/core/feature-switch.js +20 -1
  33. package/dist/core/flags.js +28 -0
  34. package/dist/core/fs-atomic.js +8 -3
  35. package/dist/core/learning-variants.js +213 -0
  36. package/dist/core/manifest.js +62 -0
  37. package/dist/core/mds-variants.js +38 -1
  38. package/dist/core/plugins.js +71 -9
  39. package/{src/assets → dist/learning-off}/agents/code.md +6 -10
  40. package/dist/learning-off/agents/design.md +119 -0
  41. package/dist/learning-off/agents/diagnose.md +210 -0
  42. package/dist/learning-off/agents/knowledge.md +90 -0
  43. package/dist/learning-off/agents/research.md +149 -0
  44. package/dist/learning-off/agents/review.md +228 -0
  45. package/dist/learning-off/agents/scrutinize.md +117 -0
  46. package/{src/assets → dist/learning-off}/agents/skim.md +1 -8
  47. package/dist/learning-off/agents/triage.md +163 -0
  48. package/dist/learning-off/commands/bug-analysis.md +420 -0
  49. package/dist/learning-off/commands/code-review.md +525 -0
  50. package/dist/learning-off/commands/debug.md +294 -0
  51. package/dist/learning-off/commands/dynamic-build.md +1255 -0
  52. package/dist/learning-off/commands/dynamic-plan.md +424 -0
  53. package/dist/learning-off/commands/dynamic-profile.md +214 -0
  54. package/dist/learning-off/commands/dynamic-tickets.md +632 -0
  55. package/dist/learning-off/commands/explore.md +210 -0
  56. package/dist/learning-off/commands/implement.md +808 -0
  57. package/dist/learning-off/commands/plan.md +664 -0
  58. package/dist/learning-off/commands/release.md +310 -0
  59. package/dist/learning-off/commands/research.md +222 -0
  60. package/dist/learning-off/commands/resolve.md +837 -0
  61. package/dist/learning-off/commands/self-review.md +266 -0
  62. package/dist/skills/git/references/tracker/_contract.md +33 -0
  63. package/dist/skills/git/references/tracker/github/fetch-issue.md +2 -0
  64. package/dist/skills/git/references/tracker/github/fetch-issues-batch.md +2 -0
  65. package/dist/skills/git/references/tracker/github/gather-release-evidence.md +4 -0
  66. package/dist/skills/git/references/tracker/github/post-wave-report.md +2 -0
  67. package/dist/skills/git/references/tracker/github/setup-task.md +12 -0
  68. package/dist/skills/git/references/tracker/jira/associate-release.md +1 -1
  69. package/dist/skills/git/references/tracker/jira/fetch-issue.md +2 -0
  70. package/dist/skills/git/references/tracker/jira/fetch-issues-batch.md +2 -0
  71. package/dist/skills/git/references/tracker/jira/gather-release-evidence.md +4 -0
  72. package/dist/skills/git/references/tracker/jira/post-wave-report.md +2 -0
  73. package/dist/skills/git/references/tracker/jira/setup-task.md +14 -2
  74. package/dist/skills/git/references/tracker/linear/associate-release.md +1 -1
  75. package/dist/skills/git/references/tracker/linear/fetch-issue.md +2 -0
  76. package/dist/skills/git/references/tracker/linear/fetch-issues-batch.md +2 -0
  77. package/dist/skills/git/references/tracker/linear/gather-release-evidence.md +4 -0
  78. package/dist/skills/git/references/tracker/linear/post-wave-report.md +2 -0
  79. package/dist/skills/git/references/tracker/linear/setup-task.md +14 -2
  80. package/dist/targets/claude-code/installer.js +72 -36
  81. package/dist/targets/claude-code/language-stamp.js +185 -0
  82. package/dist/targets/claude-code/learning-install.js +489 -0
  83. package/package.json +1 -1
  84. package/src/assets/agents/code.mds +339 -0
  85. package/src/assets/agents/design.mds +149 -0
  86. package/src/assets/agents/diagnose.mds +225 -0
  87. package/src/assets/agents/evaluate.md +1 -3
  88. package/src/assets/agents/git.mds +29 -56
  89. package/src/assets/agents/knowledge.mds +125 -0
  90. package/src/assets/agents/research.mds +176 -0
  91. package/src/assets/agents/review.mds +286 -0
  92. package/src/assets/agents/scrutinize.mds +132 -0
  93. package/src/assets/agents/skim.mds +161 -0
  94. package/src/assets/agents/triage.mds +194 -0
  95. package/src/assets/agents/validate.md +8 -6
  96. package/src/assets/commands/_partials/_compliance.mds +5 -4
  97. package/src/assets/commands/_partials/_decisions.mds +31 -0
  98. package/src/assets/commands/_partials/_engine.mds +9 -1
  99. package/src/assets/commands/_partials/_knowledge.mds +25 -12
  100. package/src/assets/commands/_partials/_preamble.mds +33 -9
  101. package/src/assets/commands/_partials/_publication.mds +5 -4
  102. package/src/assets/commands/_partials/_settings.mds +13 -5
  103. package/src/assets/commands/_partials/_wave.mds +8 -0
  104. package/src/assets/commands/bug-analysis.mds +24 -2
  105. package/src/assets/commands/code-review.mds +147 -44
  106. package/src/assets/commands/debug.mds +17 -1
  107. package/src/assets/commands/dynamic-build.mds +33 -2
  108. package/src/assets/commands/dynamic-plan.mds +36 -6
  109. package/src/assets/commands/dynamic-profile.mds +9 -1
  110. package/src/assets/commands/dynamic-tickets.mds +16 -2
  111. package/src/assets/commands/explore.mds +27 -1
  112. package/src/assets/commands/implement.mds +41 -8
  113. package/src/assets/commands/plan.mds +47 -8
  114. package/src/assets/commands/{release.md → release.mds} +27 -24
  115. package/src/assets/commands/research.mds +28 -4
  116. package/src/assets/commands/resolve.mds +43 -2
  117. package/src/assets/commands/self-review.mds +30 -5
  118. package/src/assets/mds/tracker/_contract.mds +72 -0
  119. package/src/assets/mds/tracker/_github.mds +13 -2
  120. package/src/assets/mds/tracker/_jira.mds +17 -5
  121. package/src/assets/mds/tracker/_linear.mds +17 -5
  122. package/src/assets/mds/tracker/_mcp.mds +2 -2
  123. package/src/assets/mds/tracker/_steps.mds +97 -0
  124. package/src/assets/rules/context-economy.md +10 -0
  125. package/src/assets/rules/go.md +1 -0
  126. package/src/assets/rules/java.md +1 -0
  127. package/src/assets/rules/python.md +1 -0
  128. package/src/assets/rules/rust.md +1 -0
  129. package/src/assets/rules/typescript.md +1 -0
  130. package/src/assets/scripts/claude-md-audit.cjs +611 -0
  131. package/src/assets/scripts/hooks/assets/orchestrator-charter.md +1 -2
  132. package/src/assets/scripts/hooks/json-helper.cjs +13 -5
  133. package/src/assets/scripts/hooks/json-parse +34 -10
  134. package/src/assets/scripts/hooks/session-start-context +315 -7
  135. package/src/assets/skills/apply-decisions/SKILL.md +1 -1
  136. package/src/assets/skills/apply-feature-knowledge/SKILL.md +5 -5
  137. package/src/assets/skills/feature-knowledge/SKILL.md +43 -12
  138. package/src/assets/skills/quality-gates/SKILL.md +1 -1
@@ -34,8 +34,6 @@ Run a comprehensive code review of the current branch by spawning parallel revie
34
34
 
35
35
  **Produces:** COMPLIANCE_ACTIVE, COMPLIANCE_FRAMEWORKS
36
36
 
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
37
  **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
38
 
41
39
  ```bash
@@ -46,6 +44,8 @@ Accept the output only when it is exactly two lines: `exit=0` last and, before i
46
44
 
47
45
  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
46
 
47
+ **Resolve the compliance lens** for each worktree root, from its settings line — the line resolved above for that root, by the settings block when this run has not yet resolved it (every framework reference is installed on every machine, so no file check decides it).
48
+
49
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
50
 
51
51
  `COMPLIANCE_ACTIVE` is `true` unless `COMPLIANCE_FRAMEWORKS` is `off`.
@@ -176,28 +176,56 @@ MAX_REVIEW_CYCLES = 10
176
176
 
177
177
  For each reviewable worktree, call:
178
178
 
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:
179
+ **Resolve `REVIEW_PUBLICATION` per worktree:** take `REVIEW_PUBLICATION` from that worktree's settings line — the line resolved above for `{root}`, the worktree's root, by the settings block when this run has not yet resolved that 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.
180
+
181
+ **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.
182
+
183
+ 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.
184
+
185
+ ### Phase 1: Analyze Changed Files
186
+
187
+ **Produces:** REVIEW_FOCUS_LIST, DIFF_CLASS, DIFF_FILES
188
+ **Requires:** DIFF_RANGE, REVIEW_DIR, COMPLIANCE_ACTIVE (from Step 0b)
189
+
190
+ Per worktree, in order. Each `git` command here writes to a file and prints nothing.
191
+
192
+ #### Step 1.1: Classify the diff
193
+
194
+ **Produces:** DIFF_CLASS, CHANGED_PATHS, REVIEW_FOCUS_LIST (reduced classes)
195
+ **Requires:** DIFF_RANGE, REVIEW_DIR
196
+
197
+ List the changed paths into `{REVIEW_DIR}/paths.txt` and print only the line count (drop `-C "{WORKTREE_PATH}"` when there is no `WORKTREE_PATH`):
180
198
 
181
199
  ```bash
182
- node "$HOME/.devflow/scripts/resolve-settings.cjs" "{root}" 2>/dev/null; echo "exit=$?"
200
+ git -C "{WORKTREE_PATH}" diff --name-only --no-renames {DIFF_RANGE} > "{REVIEW_DIR}/paths.txt"
201
+ wc -l < "{REVIEW_DIR}/paths.txt"
183
202
  ```
184
203
 
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.
204
+ Read `paths.txt` once when the count is about 40 or fewer, and in ranges of about 40 lines (Read with offset and limit) when it is more. `--no-renames` lists a moved file under its old path and its new one, so a move cannot take a file out of its own class.
186
205
 
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.
206
+ Set `DIFF_CLASS` by these rules, in order; the first that decides wins:
188
207
 
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.
208
+ 1. **Instruction and config paths are `code`.** Any changed path that is `CLAUDE.md`, `AGENTS.md`, under `.claude/` or `src/assets/`, a `*.mds` file, under a plugin's `agents/`, `skills/` or `commands/` directory, `.devflow/project.json`, `.devflow/conventions.md`, or a manifest or build file (`package.json`, `go.mod`, `Cargo.toml`, `pyproject.toml`, `requirements*.txt`, `CMakeLists.txt`). This rule runs first, so a diff made only of such files is `code` and never `docs-only`.
209
+ 2. **`docs-only`.** Every changed path matches `*.md`, `*.mdx`, `*.rst`, `*.txt`, `docs/**` or `CHANGELOG*`.
210
+ 3. **`tests-only`.** Every changed path matches `tests/**`, `**/__tests__/**`, `*.test.*`, `*.spec.*`, `*_test.go`, `test_*.py` or `*_test.py`.
211
+ 4. **`lockfile-only`.** Every changed path is `package-lock.json`, `pnpm-lock.yaml`, `yarn.lock`, `bun.lockb`, `Cargo.lock`, `go.sum`, `poetry.lock`, `uv.lock`, `Gemfile.lock` or `composer.lock`.
212
+ 5. **Mixed non-code.** Every changed path matches the docs, tests or lockfile patterns, but no single rule above holds (docs with tests, tests with a lockfile): `DIFF_CLASS` names each class involved.
213
+ 6. **Fail-safe is `code`.** A changed path that matches no class pattern makes the diff `code`, and so does an empty path list. A manifest change is `code` and never `lockfile-only`.
190
214
 
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.
215
+ Each reduced class runs only its focus set, every member reading `diff.patch`:
192
216
 
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.
217
+ - `docs-only`: documentation, consistency, security
218
+ - `tests-only`: testing, reliability, consistency, security
219
+ - `lockfile-only`: dependencies, security
194
220
 
195
- ### Phase 1: Analyze Changed Files
221
+ A mixed non-code diff runs the union of the sets of the classes it holds. Language and conditional triggers inside a reduced class are suppressed: they add no focus, and Step 1.2 applies to the `code` class only.
196
222
 
197
- **Produces:** REVIEW_FOCUS_LIST
198
- **Requires:** DIFF_RANGE, COMPLIANCE_ACTIVE (from Step 0b)
223
+ #### Step 1.2: Choose the focuses
199
224
 
200
- Per worktree, detect file types in diff using `DIFF_RANGE` to determine conditional reviews.
225
+ **Produces:** REVIEW_FOCUS_LIST (code class)
226
+ **Requires:** DIFF_CLASS, CHANGED_PATHS, COMPLIANCE_ACTIVE
227
+
228
+ When `DIFF_CLASS` is `code`, read the file types from the paths in `paths.txt` to determine conditional reviews:
201
229
 
202
230
  | Condition | Adds Review |
203
231
  |-----------|-------------|
@@ -216,20 +244,49 @@ Per worktree, detect file types in diff using `DIFF_RANGE` to determine conditio
216
244
 
217
245
  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.
218
246
 
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:
247
+ **Language focus stamp.** The eight language focuses — `typescript`, `react`, `accessibility`, `ui-design`, `go`, `java`, `python`, `rust` — ship with optional plugins, and the installer stamps the ones installed on this machine onto this line, rewriting it on every install and on `uninstall --plugin`:
248
+
249
+ Installed language focuses: (none)
250
+
251
+ A language focus is spawned only when its file-type condition above fires AND its name appears in that stamped line. A focus missing from the line is never spawned, even when its trigger fires. The eight core focuses are unconditional and are never stamp-gated.
252
+
253
+ #### Step 1.3: Write the diff files
254
+
255
+ **Produces:** DIFF_FILES
256
+ **Requires:** DIFF_RANGE, REVIEW_DIR, REVIEW_FOCUS_LIST
257
+
258
+ Write `diff.patch` once per worktree, by redirect:
220
259
 
221
260
  ```bash
222
- d="${CLAUDE_CONFIG_DIR:-}"; case "$d" in /*) ;; *) d="$HOME/.claude" ;; esac; test -f "$d/skills/devflow:{focus}/SKILL.md"; echo "exit=$?"
261
+ git -C "{WORKTREE_PATH}" diff --no-color --no-ext-diff --no-textconv {DIFF_RANGE} > "{REVIEW_DIR}/diff.patch"
223
262
  ```
224
263
 
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.
264
+ It holds the whole diff of `DIFF_RANGE`. On a `code` diff, add one patch for each language focus in REVIEW_FOCUS_LIST, by the same command with quoted pathspecs from this table:
265
+
266
+ ```bash
267
+ git -C "{WORKTREE_PATH}" diff --no-color --no-ext-diff --no-textconv {DIFF_RANGE} -- '<pathspec>' ... > "{REVIEW_DIR}/diff-{focus}.patch"
268
+ ```
269
+
270
+ | Focus | Pathspecs |
271
+ |-------|-----------|
272
+ | typescript | `'*.ts' '*.tsx'` |
273
+ | react, accessibility | `'*.tsx' '*.jsx'` |
274
+ | ui-design | `'*.tsx' '*.jsx' '*.css' '*.scss'` |
275
+ | go | `'*.go'` |
276
+ | java | `'*.java'` |
277
+ | python | `'*.py'` |
278
+ | rust | `'*.rs'` |
279
+
280
+ The core, database, dependencies, documentation and compliance focuses, and every reduced-class focus, read `diff.patch`. A language focus sees only its own extensions and reaches anything else through `DIFF_RANGE`. Set `DIFF_FILES` to the files written. They live in `REVIEW_DIR`, under the gitignored `.devflow/` tree, with `paths.txt`: never committed, posted or passed to the Git agent.
226
281
 
227
282
  ### Phase 1b: Load Decisions Index
228
283
 
229
- **Produces:** DECISIONS_CONTEXT, FEATURE_KNOWLEDGE, COMPLIANCE_FRAMEWORKS (carried from Step 0b)
284
+ **Produces:** DECISIONS_CONTEXT, FEATURE_KNOWLEDGE, FEATURE_KNOWLEDGE_RULES, COMPLIANCE_FRAMEWORKS (carried from Step 0b)
230
285
 
231
286
  ### Load DECISIONS_CONTEXT
232
287
 
288
+ When the settings line says `LEARNING=off`, set `DECISIONS_CONTEXT` to `(none)` and skip this step, locating no ledger and reading no index.
289
+
233
290
  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`):
234
291
 
235
292
  ```bash
@@ -287,56 +344,69 @@ Glob `{worktree}/.devflow/features/*/KNOWLEDGE.md`. For each file found, read on
287
344
 
288
345
  Match the current task area and description against each index line (or frontmatter `description` + `directories` on fallback). Select entries whose documented area overlaps the current task. This is a relevance judgment — prefer specificity over breadth.
289
346
 
290
- **Step 4 — Read selected KBs:**
347
+ **Step 4 — Read each selected KB's Rules:**
348
+
349
+ For each selected entry, `{kb}` is `{worktree}/.devflow/features/{slug}/KNOWLEDGE.md`:
350
+
351
+ 1. List its `##` headings with line numbers through Bash: `command grep -n '^## ' "{kb}"`. This only locates sections; the text of a KB comes from the Read view alone.
352
+ 2. Read the `## Rules` range (its line to the next heading) with the Read tool, using `offset` and `limit`, and choose the one to three bullets most relevant to the current task. The choice is yours, made per KB.
353
+ 3. If the KB has no `## Rules` section, choose one to three entries from its `## Anti-Patterns` or `## Gotchas` range the same way, and label them by that section's name instead of an ID.
291
354
 
292
- For each selected entry, read `{worktree}/.devflow/features/{slug}/KNOWLEDGE.md` in full. When the KB content contradicts the current code you observe, **trust the code** — the code is the freshness mechanism; the KB may lag behind.
355
+ When a KB contradicts the code you observe, **trust the code** — the code is the freshness mechanism; the KB may lag behind. A missing Rules section, a missing heading list and `(none)` are legitimate states, not errors.
293
356
 
294
- **Step 5 — Set FEATURE_KNOWLEDGE:**
357
+ **Step 5 — Set FEATURE_KNOWLEDGE and FEATURE_KNOWLEDGE_RULES:**
295
358
 
296
- Concatenate the selected KNOWLEDGE.md files under slug headers:
359
+ Write one block per selected KB. Paste each bullet verbatim from the Read view, never from a shell view. The path is relative to the checkout root; an agent resolves it under `WORKTREE_PATH` when one is provided.
297
360
 
298
361
  ```
299
362
  --- Feature knowledge: {slug} ---
300
- {full KNOWLEDGE.md content}
363
+ KB: .devflow/features/{slug}/KNOWLEDGE.md
364
+ Rules:
365
+ - **KB-AP-2** {bullet text, verbatim}
366
+ - **KB-INV-1** {bullet text, verbatim}
367
+ Headings: L5 Rules · L40 Overview · L62 Anti-Patterns · L118 Key Files
301
368
  ```
302
369
 
303
- If no KBs exist, no KBs are relevant, or `.devflow/features/` is absent, set `FEATURE_KNOWLEDGE` to `(none)`.
370
+ A KB with no Rules section labels its entries `Rules ({section name}):` and gives them no ID. `FEATURE_KNOWLEDGE` is these blocks; `FEATURE_KNOWLEDGE_RULES` is the same blocks without the `Headings:` line. Both come from this one selection, and each spawn names the variable its recipient takes. If no KBs exist, no KBs are relevant, or `.devflow/features/` is absent, set both to `(none)`.
304
371
 
305
- **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.
372
+ **One git call, then direct reads — no `.cjs` script.** After resolving `{worktree}`, this step is 1 index read (or N frontmatter reads on fallback), plus one heading listing and one Rules read per selected KB, bounded by KB count.
306
373
 
307
374
  Pass `FEATURE_KNOWLEDGE` to all Review agents alongside `DECISIONS_CONTEXT`.
308
375
 
309
376
  ### Phase 2: Run Reviews (Parallel)
310
377
 
311
378
  **Produces:** REVIEW_FOCUS_OUTPUTS
312
- **Requires:** DIFF_RANGE, REVIEW_DIR, TIMESTAMP, DECISIONS_CONTEXT, FEATURE_KNOWLEDGE, PR_DESCRIPTION, PRIOR_RESOLUTIONS, REVIEW_FOCUS_LIST
313
-
314
- Spawn Review agents **in a single message**. Always run 8 core reviews; conditionally add more based on changed file types (max 20 per worktree):
315
-
316
- | Focus | Always | Pattern Skill |
317
- |-------|--------|---------------|
318
- | security | ✓ | devflow:security |
319
- | architecture | ✓ | devflow:architecture |
320
- | performance | ✓ | devflow:performance |
321
- | complexity | ✓ | devflow:complexity |
322
- | consistency | ✓ | devflow:consistency |
323
- | regression | ✓ | devflow:regression |
324
- | testing | ✓ | devflow:testing |
325
- | reliability | ✓ | devflow:reliability |
326
- | typescript | presence-gated | devflow:typescript |
327
- | react | presence-gated | devflow:react |
328
- | accessibility | presence-gated | devflow:accessibility |
329
- | ui-design | presence-gated | devflow:ui-design |
330
- | go | presence-gated | devflow:go |
331
- | java | presence-gated | devflow:java |
332
- | python | presence-gated | devflow:python |
333
- | rust | presence-gated | devflow:rust |
334
- | database | conditional | devflow:database |
335
- | dependencies | conditional | devflow:dependencies |
336
- | documentation | conditional | devflow:documentation |
337
- | compliance | diff-driven | devflow:compliance |
338
-
339
- Review agent count: 8 always-active, +1-12 diff-driven conditional (max 20 total per worktree).
379
+ **Requires:** DIFF_RANGE, REVIEW_DIR, TIMESTAMP, DECISIONS_CONTEXT, FEATURE_KNOWLEDGE, PR_DESCRIPTION, PRIOR_RESOLUTIONS, REVIEW_FOCUS_LIST, DIFF_CLASS, DIFF_FILES
380
+
381
+ Spawn Review agents **in a single message**, for the focus set `DIFF_CLASS` selects (max 20 per worktree):
382
+
383
+ - `code`: the 8 core reviews on the full `diff.patch`, plus the language and conditional focuses Phase 1 added.
384
+ - `docs-only`, `tests-only`, `lockfile-only`: only the reduced set Phase 1 names, each reading `diff.patch`; a mixed non-code diff runs the union. No language or conditional focus is spawned, whatever its trigger.
385
+
386
+ | Focus | Runs | Pattern Skill | DIFF_FILE |
387
+ |-------|------|---------------|-----------|
388
+ | security | ✓ | devflow:security | diff.patch |
389
+ | architecture | ✓ | devflow:architecture | diff.patch |
390
+ | performance | ✓ | devflow:performance | diff.patch |
391
+ | complexity | ✓ | devflow:complexity | diff.patch |
392
+ | consistency | ✓ | devflow:consistency | diff.patch |
393
+ | regression | ✓ | devflow:regression | diff.patch |
394
+ | testing | ✓ | devflow:testing | diff.patch |
395
+ | reliability | ✓ | devflow:reliability | diff.patch |
396
+ | typescript | stamp-gated | devflow:typescript | diff-typescript.patch |
397
+ | react | stamp-gated | devflow:react | diff-react.patch |
398
+ | accessibility | stamp-gated | devflow:accessibility | diff-accessibility.patch |
399
+ | ui-design | stamp-gated | devflow:ui-design | diff-ui-design.patch |
400
+ | go | stamp-gated | devflow:go | diff-go.patch |
401
+ | java | stamp-gated | devflow:java | diff-java.patch |
402
+ | python | stamp-gated | devflow:python | diff-python.patch |
403
+ | rust | stamp-gated | devflow:rust | diff-rust.patch |
404
+ | database | conditional | devflow:database | diff.patch |
405
+ | dependencies | conditional | devflow:dependencies | diff.patch |
406
+ | documentation | conditional | devflow:documentation | diff.patch |
407
+ | compliance | diff-driven | devflow:compliance | diff.patch |
408
+
409
+ Review agent count: `code` runs 8 core, +1-12 added by Phase 1 (max 20 total per worktree); a reduced class or a mix runs 2-6.
340
410
 
341
411
  Each Review agent invocation (all in one message, **NOT background**):
342
412
  ```
@@ -345,7 +415,8 @@ Agent(subagent_type="Review", run_in_background=false):
345
415
  Follow 6-step process from devflow:review-methodology.
346
416
  PR: #{pr_number}, Base: {base_branch}
347
417
  WORKTREE_PATH: {worktree_path} (omit if cwd)
348
- DIFF_COMMAND: git -C {WORKTREE_PATH} diff {DIFF_RANGE} (omit -C flag if no WORKTREE_PATH)
418
+ DIFF_FILE: {diff_file} (absolute: {REVIEW_DIR}/diff.patch, or {REVIEW_DIR}/diff-{focus}.patch for a language focus, per the table)
419
+ DIFF_RANGE: {DIFF_RANGE} (information only)
349
420
  DECISIONS_CONTEXT: {decisions_context}
350
421
  FEATURE_KNOWLEDGE: {feature_knowledge}
351
422
  PR_DESCRIPTION: <pr-description>{pr_description}</pr-description>
@@ -425,13 +496,15 @@ In multi-worktree mode, report results per worktree.
425
496
  ├─ Per worktree (SEQUENTIAL — one worktree at a time):
426
497
  │ │
427
498
  │ ├─ Phase 1: Analyze changed files
428
- │ │ └─ Detect file types for conditional reviews
499
+ │ │ ├─ Classify the diff (paths.txt → DIFF_CLASS)
500
+ │ │ ├─ Choose the focuses (code class: file types + the language stamp)
501
+ │ │ └─ Write diff.patch and diff-{focus}.patch, by redirect
429
502
  │ │
430
503
  │ ├─ Phase 2: Reviews (PARALLEL within worktree)
431
- │ │ ├─ Review agent: security
432
- │ │ ├─ Review agent: architecture, performance, complexity
433
- │ │ ├─ Review agent: consistency, regression, testing
434
- │ │ └─ Review agent: [conditional]
504
+ │ │ ├─ code: Review agents security, architecture, performance, complexity,
505
+ │ │ │ consistency, regression, testing, reliability (diff.patch)
506
+ │ │ ├─ code: + language (diff-{focus}.patch) and conditional Review agents
507
+ │ │ └─ docs-only / tests-only / lockfile-only: the reduced set (diff.patch)
435
508
  │ │
436
509
  │ ├─ Phase 3: Synthesis → Review Comment (SEQUENTIAL within worktree)
437
510
  │ │ ├─ Step 3a: Synthesize agent (mode: review, writes review-summary.md)
@@ -460,6 +533,14 @@ In multi-worktree mode, report results per worktree.
460
533
  | `--full` flag | Bypass incremental detection (Step 0d), still load PRIOR_RESOLUTIONS for cross-cycle awareness |
461
534
  | Parsing failure on resolution-summary.md | fp_ratio = 0, convergence tracking degraded (see Step 0e-ii) |
462
535
  | Concurrent sessions | Advisory only, each session computes independently |
536
+ | Docs-only diff | `docs-only`: documentation, consistency, security on `diff.patch`; no language or conditional focus |
537
+ | Tests-only diff | `tests-only`: testing, reliability, consistency, security on `diff.patch`; no language or conditional focus |
538
+ | Lockfile-only diff | `lockfile-only`: dependencies, security on `diff.patch` |
539
+ | Mixed non-code diff (docs with tests, tests with a lockfile) | The union of the matching sets, on `diff.patch` |
540
+ | A path matching no class pattern, or an empty path list | `code` (fail-safe): the 8 core focuses on the full diff |
541
+ | A file moved across classes | `--no-renames` lists the old and the new path, so a code path makes the diff `code` |
542
+ | Path listing above about 40 lines | The count is printed; `paths.txt` is read in ranges of about 40 lines |
543
+ | Language files changed, plugin not installed | The focus is absent from the stamped line: not spawned |
463
544
  | Public repo (`auto` mode) | Git agent probes visibility, posts counts-only STUB comment; full report stays local |
464
545
  | `reviewPublication: off` | Git agent skips posting the review comment (OFF) — except that, only when `EVIDENCE_POLICY` is `required`, Step 0f passes `stub` and a counts-only STUB comment posts |
465
546
 
@@ -470,9 +551,9 @@ In multi-worktree mode, report results per worktree.
470
551
 
471
552
  ## Principles
472
553
 
473
- 1. **Orchestration only** - Command spawns agents, doesn't do git/review work itself
554
+ 1. **Orchestration only** - Command spawns agents, doesn't do git/review work itself. The exceptions are the read-only Phase 0 probes (`git worktree list`, `git -C ... branch --show-current`, `git -C ... cat-file -t`), the bounded Phase 1 path listing (a redirect into `paths.txt`, a `wc -l` count and ranged reads) and the redirect-only patch writes (`diff.patch`, `diff-{focus}.patch`). Redirect-only writes print nothing, so no diff content reaches this thread
474
555
  2. **Parallel, not background** - Multiple agents in one message, but `run_in_background=false` so phases complete before proceeding
475
- 3. **Git agent for git work** - All git operations go through Git agent
556
+ 3. **Git agent for git work** - All git operations go through Git agent, except the exceptions named in Principle 1; redirect-only writes print nothing
476
557
  4. **Clear ownership** - Each agent owns its output completely
477
558
  5. **Honest reporting** - Display agent outputs directly
478
559
  6. **Incremental by default** - Only review new changes unless `--full` specified
@@ -32,8 +32,20 @@ $ARGUMENTS
32
32
 
33
33
  **Produces:** DECISIONS_CONTEXT
34
34
 
35
+ **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:
36
+
37
+ ```bash
38
+ node "$HOME/.devflow/scripts/resolve-settings.cjs" "{root}" 2>/dev/null; echo "exit=$?"
39
+ ```
40
+
41
+ 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.
42
+
43
+ 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.
44
+
35
45
  ### Load DECISIONS_CONTEXT
36
46
 
47
+ When the settings line says `LEARNING=off`, set `DECISIONS_CONTEXT` to `(none)` and skip this step, locating no ledger and reading no index.
48
+
37
49
  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`):
38
50
 
39
51
  ```bash
@@ -227,17 +239,7 @@ git -C "{start}" rev-parse --show-toplevel
227
239
 
228
240
  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}`.
229
241
 
230
- **Step 1 — Check the opt-out gate, with `{root}` = `{worktree}`:**
231
-
232
- **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:
233
-
234
- ```bash
235
- node "$HOME/.devflow/scripts/resolve-settings.cjs" "{root}" 2>/dev/null; echo "exit=$?"
236
- ```
237
-
238
- 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.
239
-
240
- 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.
242
+ **Step 1 — Check the opt-out gate, with `{root}` = `{worktree}`:** take the settings line resolved above for that root, resolving it with the settings block when this run has not yet.
241
243
 
242
244
  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.
243
245
 
@@ -267,7 +269,7 @@ Write the knowledge base to:
267
269
  Then update the index cache by performing a read-modify-write on:
268
270
  {worktree}/.devflow/features/index.md
269
271
 
270
- Index line format: `- **{slug}** — {areas} — {Use-when description}`
272
+ Index line format: `- **{slug}** — {areas} — {Use-when description}` — at most 300 characters, the description at most 220; reword a longer one, never cut it.
271
273
 
272
274
  If the line for this slug already exists in index.md, replace it. If it does not exist, append it. If index.md does not exist, create it with just this line.
273
275
 
@@ -63,8 +63,34 @@ Then run a cheap syntax gate: write the authored script to a fresh, run-unique s
63
63
 
64
64
  The `budget` global governs depth. Scale Review agent roster and verification votes to `budget`. A low-budget run uses a leaner roster and fewer verification votes; a high-budget run expands both. Never hardcode a roster size — let budget guide it.
65
65
 
66
+ ### Handoff convention for sequential Code agents within a ticket
67
+
68
+ When a ticket requires multiple sequential Code agent phases, each Code agent appends its own `## Phase {N} Implementation Summary` section, at most 8,192 bytes, to `{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. It never rewrites an earlier section. The next Code agent reads, via HANDOFF_FILE input, only the section of the phase immediately before its own, not the whole file. PRIOR_PHASE_SUMMARY is the compact in-context form; the handoff file is the durable form that survives context compaction. Code is authoritative, summaries are supplementary.
69
+
70
+ ### IRON RULE (LLM-vs-plumbing)
71
+
72
+ **Author ZERO deterministic feature code.** No parsers, no schedulers, no topological-sort, no dependency-graph helpers, no confidence formulas. ALL issue reading, dependency reasoning, and scheduling decisions are LLM judgment at runtime, performed by the workflow's agents. The recipe is instructions. The workflow script Claude authors IS the runtime logic — keep it free of hand-coded feature algorithms.
73
+
74
+ ### SAFETY BANNER
75
+
76
+ **NEVER merge to main or master** — the workflow merges to an integration branch only. The user merges to main themselves after reviewing. This rule is absolute and must appear as an `engine_invariants()` note in every workflow that touches git.
77
+
78
+ ### Settings line
79
+
80
+ **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:
81
+
82
+ ```bash
83
+ node "$HOME/.devflow/scripts/resolve-settings.cjs" "{root}" 2>/dev/null; echo "exit=$?"
84
+ ```
85
+
86
+ 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.
87
+
88
+ 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.
89
+
66
90
  ### DECISIONS_CONTEXT — obtain BEFORE authoring
67
91
 
92
+ When the settings line says `LEARNING=off`, set `DECISIONS_CONTEXT` to `(none)` and skip this step, locating no ledger and reading no index.
93
+
68
94
  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`):
69
95
 
70
96
  ```bash
@@ -81,19 +107,7 @@ This is the rule the learning hooks apply (D-LEDGER-MAIN-WORKTREE, D-PROMPT-ROOT
81
107
 
82
108
  Before you author the workflow script, read `{ledger}/.devflow/learning/index.md`. If the file is absent or empty, set `DECISIONS_CONTEXT` to `(none)`; otherwise use the file content as `DECISIONS_CONTEXT`.
83
109
 
84
- The script body cannot perform this read — you (the main model) do it before authoring. Then inject the relevant DECISIONS_CONTEXT into agent prompts using the `devflow:apply-decisions` consumption algorithm (scan index → Read relevant entries → cite verbatim IDs in agent prompts). Only agents that need architectural context (Code agent, Evaluate agent, Review agent, Scrutinize agent) need DECISIONS_CONTEXT injected; lightweight agents (Validate agent, Simplify agent) do not.
85
-
86
- ### Handoff convention for sequential Code agents within a ticket
87
-
88
- 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.
89
-
90
- ### IRON RULE (LLM-vs-plumbing)
91
-
92
- **Author ZERO deterministic feature code.** No parsers, no schedulers, no topological-sort, no dependency-graph helpers, no confidence formulas. ALL issue reading, dependency reasoning, and scheduling decisions are LLM judgment at runtime, performed by the workflow's agents. The recipe is instructions. The workflow script Claude authors IS the runtime logic — keep it free of hand-coded feature algorithms.
93
-
94
- ### SAFETY BANNER
95
-
96
- **NEVER merge to main or master** — the workflow merges to an integration branch only. The user merges to main themselves after reviewing. This rule is absolute and must appear as an `engine_invariants()` note in every workflow that touches git.
110
+ The script body cannot perform this read — you (the main model) do it before authoring. Then inject the relevant DECISIONS_CONTEXT into the prompts of the Code, Design, Knowledge, Review and Scrutinize agents, using the `devflow:apply-decisions` consumption algorithm (scan index → Read relevant entries → cite verbatim IDs in agent prompts). Those are the agent types above whose contract declares it; every other agent type gets no decisions context.
97
111
 
98
112
  ---
99
113
 
@@ -168,17 +182,7 @@ Author the resolved `ISSUE_REQUIRED` and `APPLY_CONVENTIONS` into the workflow s
168
182
 
169
183
  **Produces:** COMPLIANCE_FRAMEWORKS
170
184
 
171
- **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):
172
-
173
- **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:
174
-
175
- ```bash
176
- node "$HOME/.devflow/scripts/resolve-settings.cjs" "{root}" 2>/dev/null; echo "exit=$?"
177
- ```
178
-
179
- 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.
180
-
181
- 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.
185
+ **Resolve the compliance lens** for each worktree root, from its settings line — the line resolved above for that root, by the settings block when this run has not yet resolved it (every framework reference is installed on every machine, so no file check decides it).
182
186
 
183
187
  **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.
184
188
 
@@ -198,7 +202,7 @@ and using its one-line output. If the command fails (outside a git repository),
198
202
 
199
203
  **1. Apply decisions context**
200
204
 
201
- 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.
205
+ Apply the `devflow:apply-decisions` algorithm to the DECISIONS_CONTEXT loaded by the decisions step above: scan the index, Read relevant entries, note the verbatim ADR/PF IDs you will inject into Code agent prompts.
202
206
 
203
207
  **2. Read budget**
204
208
 
@@ -368,6 +372,7 @@ Return: {"verdict": "PASS" | "FAIL", "details": "..."}`, { agentType: "Validate"
368
372
  await agent(`OPERATION: validation-fix
369
373
  Fix the validation failures on branch ${BRANCH}:
370
374
  ${failureDetails}
375
+ DECISIONS_CONTEXT: ${DECISIONS_CONTEXT}
371
376
  ISSUE_NUMBER: ${ISSUE_NUMBER}
372
377
  ISSUE_PR_LINK: ${ISSUE_PR_LINK}
373
378
  COMPLIANCE_FRAMEWORKS: ${COMPLIANCE_FRAMEWORKS}
@@ -410,6 +415,7 @@ Return: {"verdict": "PASS" | "FAIL", "rationale": "..."} — FAIL if either answ
410
415
  await agent(`OPERATION: alignment-fix
411
416
  Fix the alignment issues identified by the Evaluate agent on branch ${BRANCH}:
412
417
  ${evaluation?.rationale || "see the Evaluate agent's report"}
418
+ DECISIONS_CONTEXT: ${DECISIONS_CONTEXT}
413
419
  ISSUE_NUMBER: ${ISSUE_NUMBER}
414
420
  ISSUE_PR_LINK: ${ISSUE_PR_LINK}
415
421
  COMPLIANCE_FRAMEWORKS: ${COMPLIANCE_FRAMEWORKS}
@@ -431,6 +437,7 @@ Cover: functionality, API contracts, performance, and cover every TEST_PLAN scen
431
437
  await agent(`OPERATION: qa-fix
432
438
  Fix the failing acceptance test scenarios on branch ${BRANCH}:
433
439
  ${testResult.failures}
440
+ DECISIONS_CONTEXT: ${DECISIONS_CONTEXT}
434
441
  ISSUE_NUMBER: ${ISSUE_NUMBER}
435
442
  ISSUE_PR_LINK: ${ISSUE_PR_LINK}
436
443
  COMPLIANCE_FRAMEWORKS: ${COMPLIANCE_FRAMEWORKS}
@@ -550,6 +557,7 @@ ISSUES:
550
557
  ${chunk.map((f, n) => `${n + 1}. ${f.file ? `${f.file}${f.line ? `:${f.line}` : ""} — ` : ""}${f.description} (${f.severity})`).join("\n")}
551
558
  SCOPE: ${chunk.map((f, n) => `${n + 1}=${CAREFUL_SEVERITIES.has(String(f.severity).toLowerCase()) ? "Careful" : "Standard"}`).join(", ")}
552
559
  PUSH: false
560
+ DECISIONS_CONTEXT: ${DECISIONS_CONTEXT}
553
561
  ISSUE_NUMBER: ${ISSUE_NUMBER}
554
562
  ISSUE_PR_LINK: ${ISSUE_PR_LINK}
555
563
  COMPLIANCE_FRAMEWORKS: ${COMPLIANCE_FRAMEWORKS}
@@ -610,6 +618,7 @@ Return: {"verdict": "PASS" | "FAIL", "details": "..."}`, { agentType: "Validate"
610
618
  await agent(`OPERATION: validation-fix
611
619
  Fix the final validation failures on branch ${BRANCH}:
612
620
  ${failureDetails}
621
+ DECISIONS_CONTEXT: ${DECISIONS_CONTEXT}
613
622
  ISSUE_NUMBER: ${ISSUE_NUMBER}
614
623
  ISSUE_PR_LINK: ${ISSUE_PR_LINK}
615
624
  COMPLIANCE_FRAMEWORKS: ${COMPLIANCE_FRAMEWORKS}
@@ -698,7 +707,7 @@ Run builds, typechecks, lints and tests in the foreground, each with an explicit
698
707
  The standard implementation unit for one ticket. Run in order:
699
708
 
700
709
  ```
701
- Code(agentType:"Code", prompt: "OPERATION: implement" first line, then full task + plan + DECISIONS_CONTEXT + handoff if sequential)
710
+ Code(agentType:"Code", prompt: "OPERATION: implement" first line, then full task + plan + DECISIONS_CONTEXT + COMPLIANCE_FRAMEWORKS + handoff if sequential)
702
711
  → gate1_postcode()
703
712
  → gate2_acceptance() ← Gate 2 runs HERE — before the review pass, not after
704
713
  ```
@@ -1004,7 +1013,7 @@ Two parallel sibling tickets can produce real git conflicts. The resolution is *
1004
1013
  **Resolution procedure:**
1005
1014
 
1006
1015
  1. Git agent detects the conflict and reports the conflicting files + sections
1007
- 2. Spawn a Code agent whose prompt opens with `OPERATION: implement` and carries `COMPLIANCE_FRAMEWORKS`, with FULL intent context:
1016
+ 2. Spawn a Code agent whose prompt opens with `OPERATION: implement` and carries `COMPLIANCE_FRAMEWORKS` and `DECISIONS_CONTEXT`, with FULL intent context:
1008
1017
  - Both ticket descriptions and plans
1009
1018
  - The conflicting diff sections (both sides)
1010
1019
  - Relevant ADRs from DECISIONS_CONTEXT (loaded by main model before authoring)
@@ -1257,17 +1266,7 @@ git -C "{integration worktree root}" push origin HEAD; echo "exit=$?"
1257
1266
 
1258
1267
  **(d) Refresh.** Resolve the publication value for the integration worktree:
1259
1268
 
1260
- **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:
1261
-
1262
- ```bash
1263
- node "$HOME/.devflow/scripts/resolve-settings.cjs" "{root}" 2>/dev/null; echo "exit=$?"
1264
- ```
1265
-
1266
- 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.
1267
-
1268
- 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.
1269
-
1270
- **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.
1269
+ **Resolve `REVIEW_PUBLICATION` per worktree:** take `REVIEW_PUBLICATION` from that worktree's settings line — the line resolved above for `{root}`, the worktree's root, by the settings block when this run has not yet resolved that 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.
1271
1270
 
1272
1271
  **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.
1273
1272