devflow-kit 3.7.0 → 3.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (205) hide show
  1. package/CHANGELOG.md +479 -1
  2. package/README.md +15 -15
  3. package/dist/agents/code.md +6 -8
  4. package/dist/agents/design.md +1 -1
  5. package/dist/agents/fix.md +7 -8
  6. package/dist/agents/git.md +3 -3
  7. package/dist/agents/harden.md +1 -1
  8. package/dist/agents/refactor.md +2 -4
  9. package/dist/agents/review.md +4 -4
  10. package/dist/agents/skim.md +2 -2
  11. package/dist/agents/triage.md +9 -2
  12. package/dist/cli/commands/capture.js +1 -1
  13. package/dist/cli/commands/curation-move-io.js +102 -0
  14. package/dist/cli/commands/curation-move-step.js +374 -0
  15. package/dist/cli/commands/curation.js +808 -0
  16. package/dist/cli/commands/gate-level-prompts.js +428 -0
  17. package/dist/cli/commands/gates.js +35 -11
  18. package/dist/cli/commands/init-seed.js +11 -8
  19. package/dist/cli/commands/init.js +244 -57
  20. package/dist/cli/commands/memory.js +60 -13
  21. package/dist/cli/commands/prompt-io.js +37 -0
  22. package/dist/cli/commands/uninstall.js +157 -17
  23. package/dist/cli.js +2 -2
  24. package/dist/commands/bug-analysis.md +25 -36
  25. package/dist/commands/code-review.md +40 -44
  26. package/dist/commands/debug.md +5 -5
  27. package/dist/commands/dynamic-build.md +26 -25
  28. package/dist/commands/dynamic-plan.md +5 -5
  29. package/dist/commands/dynamic-profile.md +5 -5
  30. package/dist/commands/dynamic-tickets.md +5 -5
  31. package/dist/commands/explore.md +6 -6
  32. package/dist/commands/implement.md +53 -82
  33. package/dist/commands/plan.md +6 -6
  34. package/dist/commands/release.md +5 -5
  35. package/dist/commands/research.md +6 -6
  36. package/dist/commands/resolve.md +39 -41
  37. package/dist/commands/self-review.md +5 -13
  38. package/dist/core/area-pause-notice.js +44 -0
  39. package/dist/core/assets.js +20 -20
  40. package/dist/core/curate-tuning-config.js +5 -6
  41. package/dist/core/curation-move-notice.js +84 -0
  42. package/dist/core/curation-move-skip.js +35 -0
  43. package/dist/core/curation-move.js +35 -0
  44. package/dist/core/curation-queue-cleanup.js +135 -0
  45. package/dist/core/curation-store.js +99 -0
  46. package/dist/core/{learning-variants.js → curation-variants.js} +65 -41
  47. package/dist/core/echo-value.js +11 -5
  48. package/dist/core/evidence-policy.js +11 -9
  49. package/dist/core/feature-switch.js +95 -19
  50. package/dist/core/fs-atomic.js +1 -1
  51. package/dist/core/gate-level.js +10 -2
  52. package/dist/core/git.js +16 -14
  53. package/dist/core/ledger-root.js +82 -22
  54. package/dist/core/linked-path.js +4 -4
  55. package/dist/core/manifest-lock.js +238 -0
  56. package/dist/core/manifest.js +58 -14
  57. package/dist/core/migrations.js +1 -13
  58. package/dist/core/observations.js +2 -2
  59. package/dist/core/plugins.js +19 -19
  60. package/dist/core/pool.js +26 -0
  61. package/dist/core/project-paths.js +103 -34
  62. package/dist/core/queue-drain.js +2 -2
  63. package/dist/core/tracked-areas.js +159 -0
  64. package/dist/core/tracker.js +1 -1
  65. package/dist/{learning-off → curation-off}/agents/code.md +6 -8
  66. package/dist/{learning-off → curation-off}/agents/fix.md +7 -8
  67. package/dist/{learning-off → curation-off}/agents/refactor.md +2 -4
  68. package/dist/{learning-off → curation-off}/agents/review.md +3 -3
  69. package/dist/{learning-off → curation-off}/agents/triage.md +8 -1
  70. package/dist/{learning-off → curation-off}/commands/bug-analysis.md +20 -31
  71. package/dist/{learning-off → curation-off}/commands/code-review.md +37 -41
  72. package/dist/{learning-off → curation-off}/commands/debug.md +2 -2
  73. package/dist/{learning-off → curation-off}/commands/dynamic-build.md +23 -22
  74. package/dist/{learning-off → curation-off}/commands/explore.md +2 -2
  75. package/dist/{learning-off → curation-off}/commands/implement.md +50 -79
  76. package/dist/{learning-off → curation-off}/commands/plan.md +2 -2
  77. package/dist/{learning-off → curation-off}/commands/resolve.md +36 -38
  78. package/dist/{learning-off → curation-off}/commands/self-review.md +2 -10
  79. package/dist/hud/components/{learning-counts.js → curation-counts.js} +63 -17
  80. package/dist/hud/config.js +1 -1
  81. package/dist/hud/index.js +6 -6
  82. package/dist/hud/render.js +3 -3
  83. package/dist/skills/git/references/pr/post-resolution-summary.md +12 -11
  84. package/dist/skills/git/references/pr/post-review-summary.md +12 -11
  85. package/dist/skills/git/references/pr/update-pr-evidence.md +2 -2
  86. package/dist/skills/git/references/pr/validate-branch.md +8 -5
  87. package/dist/skills/git/references/publication-gate.md +6 -7
  88. package/dist/skills/git/references/tracker/github/ensure-pr-ready.md +13 -5
  89. package/dist/skills/git/references/tracker/github/manage-debt.md +6 -2
  90. package/dist/skills/git/references/tracker/jira/ensure-pr-ready.md +13 -5
  91. package/dist/skills/git/references/tracker/jira/manage-debt.md +6 -2
  92. package/dist/skills/git/references/tracker/linear/ensure-pr-ready.md +13 -5
  93. package/dist/skills/git/references/tracker/linear/manage-debt.md +6 -2
  94. package/dist/targets/claude-code/{learning-install.js → curation-install.js} +85 -65
  95. package/dist/targets/claude-code/installer.js +15 -15
  96. package/dist/targets/claude-code/language-stamp.js +5 -5
  97. package/dist/targets/claude-code/post-install.js +2 -2
  98. package/dist/targets/claude-code/tracker-servers.js +1 -1
  99. package/package.json +3 -2
  100. package/src/assets/agents/_partials/_code.mds +11 -11
  101. package/src/assets/agents/code.mds +6 -6
  102. package/src/assets/agents/curate.md +8 -8
  103. package/src/assets/agents/debug.mds +6 -6
  104. package/src/assets/agents/design.mds +18 -18
  105. package/src/assets/agents/evaluate.md +6 -12
  106. package/src/assets/agents/fix.mds +7 -6
  107. package/src/assets/agents/git.mds +3 -3
  108. package/src/assets/agents/harden.mds +7 -7
  109. package/src/assets/agents/knowledge.mds +23 -23
  110. package/src/assets/agents/refactor.mds +2 -2
  111. package/src/assets/agents/research.mds +15 -15
  112. package/src/assets/agents/review.mds +43 -43
  113. package/src/assets/agents/skim.mds +11 -11
  114. package/src/assets/agents/triage.mds +29 -22
  115. package/src/assets/agents/validate.md +30 -50
  116. package/src/assets/commands/_partials/_decisions.mds +22 -20
  117. package/src/assets/commands/_partials/_engine.mds +8 -8
  118. package/src/assets/commands/_partials/_knowledge.mds +29 -15
  119. package/src/assets/commands/_partials/_preamble.mds +4 -4
  120. package/src/assets/commands/_partials/_settings.mds +3 -3
  121. package/src/assets/commands/_partials/_wave.mds +7 -7
  122. package/src/assets/commands/bug-analysis.mds +37 -48
  123. package/src/assets/commands/code-review.mds +53 -57
  124. package/src/assets/commands/debug.mds +14 -14
  125. package/src/assets/commands/dynamic-build.mds +38 -37
  126. package/src/assets/commands/dynamic-plan.mds +22 -22
  127. package/src/assets/commands/dynamic-profile.mds +2 -2
  128. package/src/assets/commands/dynamic-tickets.mds +8 -8
  129. package/src/assets/commands/explore.mds +20 -20
  130. package/src/assets/commands/implement.mds +77 -98
  131. package/src/assets/commands/plan.mds +27 -27
  132. package/src/assets/commands/release.mds +12 -12
  133. package/src/assets/commands/research.mds +19 -19
  134. package/src/assets/commands/resolve.mds +66 -60
  135. package/src/assets/commands/self-review.mds +20 -20
  136. package/src/assets/mds/git/_ops.mds +9 -2
  137. package/src/assets/mds/git/_ops_pr.mds +21 -11
  138. package/src/assets/mds/git/_ops_steps.mds +20 -4
  139. package/src/assets/mds/git/_pr.mds +21 -18
  140. package/src/assets/mds/git/_references.mds +6 -7
  141. package/src/assets/mds/tracker/_github.mds +1 -4
  142. package/src/assets/mds/tracker/_jira.mds +1 -4
  143. package/src/assets/mds/tracker/_linear.mds +1 -4
  144. package/src/assets/rules/quality.md +1 -0
  145. package/src/assets/scripts/ci-wait.cjs +389 -92
  146. package/src/assets/scripts/hooks/background-memory-update +81 -3
  147. package/src/assets/scripts/hooks/capture-prompt +12 -12
  148. package/src/assets/scripts/hooks/capture-question +11 -11
  149. package/src/assets/scripts/hooks/capture-turn +12 -12
  150. package/src/assets/scripts/hooks/{learning-lock → curation-lock} +2 -2
  151. package/src/assets/scripts/hooks/curation-move +293 -0
  152. package/src/assets/scripts/hooks/ensure-devflow-init +45 -13
  153. package/src/assets/scripts/hooks/ensure-proxy +4 -4
  154. package/src/assets/scripts/hooks/ensure-root-gitignore +4 -4
  155. package/src/assets/scripts/hooks/git-marker +81 -0
  156. package/src/assets/scripts/hooks/json-helper.cjs +176 -51
  157. package/src/assets/scripts/hooks/json-parse +1 -1
  158. package/src/assets/scripts/hooks/lib/curation-move.cjs +1582 -0
  159. package/src/assets/scripts/hooks/lib/{learning-store.cjs → curation-store.cjs} +308 -122
  160. package/src/assets/scripts/hooks/lib/decisions-format.cjs +3 -3
  161. package/src/assets/scripts/hooks/lib/mkdir-lock.cjs +24 -7
  162. package/src/assets/scripts/hooks/lib/project-paths.cjs +132 -39
  163. package/src/assets/scripts/hooks/lib/render-decisions.cjs +42 -22
  164. package/src/assets/scripts/hooks/lib/tracked-areas.cjs +452 -0
  165. package/src/assets/scripts/hooks/memory-permission +10 -2
  166. package/src/assets/scripts/hooks/memory-worker +12 -1
  167. package/src/assets/scripts/hooks/pre-compact-memory +17 -16
  168. package/src/assets/scripts/hooks/queue-append +444 -102
  169. package/src/assets/scripts/hooks/resolve-project-root +2 -2
  170. package/src/assets/scripts/hooks/session-start-context +198 -72
  171. package/src/assets/scripts/hooks/session-start-memory +42 -43
  172. package/src/assets/scripts/lib/project-config.cjs +12 -5
  173. package/src/assets/scripts/pr-evidence.cjs +5 -2
  174. package/src/assets/scripts/resolve-base.cjs +1043 -0
  175. package/src/assets/scripts/resolve-settings.cjs +283 -45
  176. package/src/assets/scripts/verify-evidence.cjs +307 -75
  177. package/src/assets/skills/agent-references/SKILL.md +11 -2
  178. package/src/assets/skills/agent-references/references/commands/implement-levels.md +29 -0
  179. package/src/assets/skills/agent-references/references/commands/implement-revalidate.md +6 -4
  180. package/src/assets/skills/agent-references/references/commands/resolve-levels.md +25 -0
  181. package/src/assets/skills/agent-references/references/synthesize/review.md +4 -4
  182. package/src/assets/skills/agent-references/references/triage/severity-tiers.md +43 -0
  183. package/src/assets/skills/agent-references/references/validate/passed-alone.md +14 -0
  184. package/src/assets/skills/apply-decisions/SKILL.md +1 -1
  185. package/src/assets/skills/docs-framework/SKILL.md +7 -7
  186. package/src/assets/skills/docs-framework/references/patterns.md +3 -4
  187. package/src/assets/skills/quality-gates/SKILL.md +1 -1
  188. package/src/assets/skills/worktree-support/references/roots.md +2 -2
  189. package/templates/lint-pack/.lint-pack.conf +86 -0
  190. package/templates/lint-pack/README.md +190 -0
  191. package/templates/lint-pack/lint-pack.sh +905 -0
  192. package/dist/cli/commands/learning.js +0 -554
  193. package/dist/core/learning-queue-cleanup.js +0 -27
  194. package/dist/core/learning-store.js +0 -61
  195. /package/dist/{learning-off → curation-off}/agents/debug.md +0 -0
  196. /package/dist/{learning-off → curation-off}/agents/design.md +0 -0
  197. /package/dist/{learning-off → curation-off}/agents/harden.md +0 -0
  198. /package/dist/{learning-off → curation-off}/agents/knowledge.md +0 -0
  199. /package/dist/{learning-off → curation-off}/agents/research.md +0 -0
  200. /package/dist/{learning-off → curation-off}/agents/skim.md +0 -0
  201. /package/dist/{learning-off → curation-off}/commands/dynamic-plan.md +0 -0
  202. /package/dist/{learning-off → curation-off}/commands/dynamic-profile.md +0 -0
  203. /package/dist/{learning-off → curation-off}/commands/dynamic-tickets.md +0 -0
  204. /package/dist/{learning-off → curation-off}/commands/release.md +0 -0
  205. /package/dist/{learning-off → curation-off}/commands/research.md +0 -0
@@ -72,7 +72,7 @@ For each worktree:
72
72
  2. **If `--review {timestamp}` provided:** use that specific directory (not supported in multi-worktree mode)
73
73
  3. **Otherwise:** sort directories by name descending (timestamps are naturally sortable), scan the 10 most recent directories only. Select the first that contains `review-summary.md` (complete review)
74
74
  4. **If latest directory already has `resolution-summary.md`:** the review is resolved — check bug-analysis fallback (step 5b).
75
- 5. **Legacy fallback:** if no timestamped subdirectories exist but flat `*.md` files do in `{worktree}/.devflow/docs/reviews/{branch-slug}/`, read them directly (backwards compatible).
75
+ 5. **Legacy fallback:** if no timestamped subdirectories exist but flat `*.md` files do in `{worktree}/.devflow/docs/reviews/{branch-slug}/`, read them directly.
76
76
 
77
77
  **5b. Bug analysis fallback** — if no qualifying review directory found (no reviews exist, or all resolved):
78
78
  - List directories in `{worktree}/.devflow/docs/bug-analysis/{branch-slug}/`
@@ -86,21 +86,21 @@ Set `TARGET_DIR` to the selected review or bug-analysis directory path, and `TAR
86
86
 
87
87
  #### Step 0d: Load Project Decisions
88
88
 
89
- **Produces:** DECISIONS_CONTEXT, FEATURE_KNOWLEDGE, FEATURE_KNOWLEDGE_RULES, EVIDENCE_POLICY, ISSUE_REQUIRED, APPLY_CONVENTIONS, REQUIRE_NON_AUTHOR_APPROVAL, REVIEW_PUBLICATION, RESOLUTION_TS
89
+ **Produces:** DECISIONS_CONTEXT, FEATURE_KNOWLEDGE, FEATURE_KNOWLEDGE_RULES, EVIDENCE_POLICY, ISSUE_REQUIRED, APPLY_CONVENTIONS, REQUIRE_NON_AUTHOR_APPROVAL, REVIEW_PUBLICATION, RESOLUTION_TS, GATE_LEVEL
90
90
 
91
- **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:
91
+ **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 in a one-worktree run:
92
92
 
93
93
  ```bash
94
94
  node "$HOME/.devflow/scripts/resolve-settings.cjs" "{root}" 2>/dev/null; echo "exit=$?"
95
95
  ```
96
96
 
97
- 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> GATE_LEVEL=<full|standard|lean>` — 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 GATE_LEVEL=full` instead.
97
+ 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> CURATION=<on|off> KNOWLEDGE=<on|off> GATE_LEVEL=<full|standard|lean>` — 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=off CURATION=off KNOWLEDGE=off GATE_LEVEL=full` instead.
98
98
 
99
99
  The accepted line is the only source of these values.
100
100
 
101
101
  ### Load DECISIONS_CONTEXT
102
102
 
103
- When the settings line says `LEARNING=off`, set `DECISIONS_CONTEXT` to `(none)` and skip this step, locating no ledger and reading no index.
103
+ When the settings line says `CURATION=off`, set `DECISIONS_CONTEXT` to `(none)` and skip this step, locating no ledger and reading no index.
104
104
 
105
105
  The decisions ledger belongs to the repository, not to one checkout: a linked worktree reads the main worktree's copy, a subdirectory session the repository root's. Locate it with ONE git call, run from the start directory — `WORKTREE_PATH` if provided, otherwise cwd (`devflow:worktree-support`):
106
106
 
@@ -114,11 +114,11 @@ Line 1 is the checkout's toplevel, line 2 the common git directory. A git older
114
114
  2. **The toplevel** — line 1, or on an older git the line after the echoed flag.
115
115
  3. **The start directory itself** — when the command failed or printed no absolute toplevel (outside a git repository).
116
116
 
117
- This is the rule the learning hooks apply, so you read the index the Curate agent writes.
117
+ This is the rule the curation hooks apply, so you read the index the Curate agent writes.
118
118
 
119
119
  **Step 1 — Read the pre-rendered index:**
120
120
 
121
- Attempt to read `{ledger}/.devflow/learning/index.md`.
121
+ Attempt to read `{ledger}/.devflow/curation/index.md`.
122
122
 
123
123
  - If the file exists and contains non-empty content: use that content as `DECISIONS_CONTEXT`.
124
124
  - If the file is absent or empty: set `DECISIONS_CONTEXT` to `(none)`.
@@ -216,6 +216,12 @@ Resolve this per worktree — unlike the evidence policy above, the settings lin
216
216
 
217
217
  Set it per worktree, from that worktree's lens, and pass that worktree's `COMPLIANCE_DIRECTIVE` to each of its Code and Fix spawns, on a line of its own.
218
218
 
219
+ **Gate level.** Each worktree keeps its own `GATE_LEVEL`. When any is `standard` or `lean`, once per run, run `d="${CLAUDE_CONFIG_DIR:-}"; case "$d" in /*) ;; *) d="$HOME/.claude" ;; esac; printf '%s\n' "$d"` in Bash and Read `<that directory>/skills/devflow:agent-references/references/commands/resolve-levels.md` with the Read tool, and apply each row to the phase it names, as the reference says.
220
+
221
+ - No row or rule overrides the next two lines.
222
+ - If the Read fails, or the file has no `## Phases` heading with the `| Phase | standard | lean |` header, or a row breaks its grammar, apply no row in any worktree, keep every `GATE_LEVEL` and say `level reference unreadable: no level rows applied`.
223
+ - No level changes the Triage security gate or the ESCALATED route. The Verification Gate, the CI gate and the compliance directive run at every level.
224
+
219
225
  **Mint `RESOLUTION_TS` once per run:** `date -u +%Y-%m-%dT%H:%M:%SZ`. Every worktree reuses it — the resolution comment's dedup marker is searched per PR, so one run key keeps a retry of this run deduplicated while the next /resolve on the same PR posts. Phase 5 writes it as the summary's `**Date**:` and Phase 9b-2 passes it, so the local file and the posted marker agree.
220
226
 
221
227
  ### Phase 1: Parse Issues
@@ -287,13 +293,15 @@ Follow devflow:apply-feature-knowledge for FEATURE_KNOWLEDGE."
287
293
 
288
294
  Wait for Triage agent to complete before proceeding. Parse verdict ledger from Triage agent output:
289
295
  - **ESCALATED**: Security issues requiring human escalation
290
- - **FIX_NOW**: Valid issues assigned to Code agents (with risk tier: Standard | Careful)
296
+ - **FIX_NOW**: Valid issues assigned to Code agents (with risk tier: Standard | Careful | `Standard, prose only: edit text alone; agent instructions count as logic; if this issue needs a logic change, leave it unedited and name it`; any other value counts as Careful). SCOPE gives one `{id}: {tier}` line per issue.
291
297
  - **FALSE_POSITIVE**: Issues the Review agent got wrong (with cited evidence)
292
298
  - **BY_DESIGN**: Intentional code (with a recorded decision, stated in words, or a code doc citation)
293
299
  - **FIX_SEPARATE**: Valid but out of blast-radius scope (must become manage-debt ticket)
294
300
  - **TECH_DEBT**: Architectural overhaul only — LAST RESORT
295
301
  - **DUPLICATE**: Collapsed duplicate issue — carries `duplicate_of: <primary-id>` referencing the non-DUPLICATE primary; inherits the primary's outcome
296
302
 
303
+ A ledger `### Summary` line `- Tiers: not applied (…)` is the level note.
304
+
297
305
  Collect every decision and pitfall the Triage agent's Reasoning columns state, in its words — the resolution summary is posted, so it never carries an ADR/PF ID.
298
306
 
299
307
  **Triage agent completeness assertion:** Verify the parsed ledger against ISSUES before proceeding:
@@ -309,10 +317,10 @@ Collect every decision and pitfall the Triage agent's Reasoning columns state, i
309
317
  **Produces:** BATCHES
310
318
  **Requires:** TRIAGE_RESULTS
311
319
 
312
- If FIX_NOW list is empty: skip to Phase 5 — write full summary (Phase 5), run manage-debt (Phase 9) if FIX_SEPARATE/TECH_DEBT exist, run thread resolution + resolution comment (Phase 9b), run merge readiness (Phase 9c), display results (Phase 10).
320
+ If FIX_NOW list is empty: skip to Phase 5, then run Phases 9, 9b, 9c and 10.
313
321
 
314
322
  Otherwise, batch FIX_NOW issues for Code agent execution. **DUPLICATE issues are never dispatched** — they inherit the primary's outcome:
315
- - **Same-file issues** → one batch (one Code agent per file, sequential for same-file pairs)
323
+ - **Same-file issues** → one batch (one Code agent per file)
316
324
  - **Distinct-file issues** → parallel Code agents
317
325
  - **Max 5 issues per batch** — chunk large sets
318
326
 
@@ -344,24 +352,27 @@ Spawn distinct-file batch Code agents **in a single message** (parallel). Sequen
344
352
  Collect from each Code agent:
345
353
  - `{status, commitShas, unresolved}` per batch
346
354
  - `## Verification` block (commands run + results)
355
+ - An unresolved prose-only issue that Code names as needing a logic change, and whose type is not `security` → FIX_SEPARATE in TRIAGE_RESULTS, Reason `needs a logic change`; every other unresolved issue stays Blocked
347
356
 
348
357
  ### Phase 5: Write resolution-summary.md
349
358
 
350
359
  **Produces:** RESOLUTION_FILE (early write for compaction safety)
351
- **Requires:** TRIAGE_RESULTS, CODE_AGENT_RESULTS, TARGET_DIR, TARGET_DIR_REL, BRANCH_INFO, RESOLUTION_TS
360
+ **Requires:** TRIAGE_RESULTS, CODE_AGENT_RESULTS, TARGET_DIR, TARGET_DIR_REL, BRANCH_INFO, RESOLUTION_TS, GATE_LEVEL
352
361
 
353
- **Immediately write `resolution-summary.md`** to `{TARGET_DIR}` using the Write tool. Do this now — not in Phase 9 — while results are fresh in context. This ensures the record is persisted even if later phases (Polish, Verification Gate, CI gate, Tech Debt) trigger context compaction.
362
+ **Immediately write `resolution-summary.md`** to `{TARGET_DIR}` using the Write tool.
354
363
 
355
364
  Set `Tracked` for FIX_SEPARATE and TECH_DEBT items to `(pending)` — to be backfilled after Phase 9 manage-debt (or `TRACEABILITY: DEGRADED ({reason})` if manage-debt degrades).
356
365
 
357
366
  DUPLICATE issues are listed **only** in `## Duplicates` — never in `## Fixed Issues`, `## False Positives`, `## By Design`, `## Fix Separately`, `## Deferred to Tech Debt`, `## Escalations`, or `## Blocked`. A duplicate of a FALSE_POSITIVE primary therefore leaves only the primary in the `False Positive` row and the `## False Positives` section; the same holds for every other outcome the duplicate inherits.
358
367
 
359
- Use the template from the Output Artifact section below.
368
+ Open each Issue cell with its severity in brackets when it has one, as `[HIGH]`.
369
+
370
+ Use the template from the Output Artifact section below. Put text not for public posting in a final `## Private notes` section.
360
371
 
361
372
  ### Phase 6: Polish
362
373
 
363
374
  **Produces:** POLISH_RESULT
364
- **Requires:** CODE_AGENT_RESULTS
375
+ **Requires:** CODE_AGENT_RESULTS, GATE_LEVEL
365
376
 
366
377
  If any fixes were made, spawn Polish agent to refine the changed code:
367
378
 
@@ -423,7 +434,7 @@ git -C {worktree} push
423
434
 
424
435
  **If `fork_no_push` is set:** do not push. Record `Push: skipped — cannot push to fork` under `## Verification`, and skip Phase 8 — no pushed commit exists for CI to check.
425
436
 
426
- **Route after push:** VERIFICATION_STATUS = PASS → continue to Phase 8 (CI gate). VERIFICATION_STATUS = FAILED → skip Phase 8; proceed directly to Phase 9 (manage-debt), then Phase 9b (thread resolution + resolution comment), then Phase 9c (merge readiness), then Phase 10 (report). VERIFICATION_STATUS = SKIPPED → skip Phase 8 (no fixes applied); proceed to Phase 9 (manage-debt), then Phase 9b (thread resolution + resolution comment), then Phase 9c (merge readiness, when non-author approval is required), then Phase 10 (report).
437
+ **Route after push:** VERIFICATION_STATUS = PASS → continue to Phase 8 (CI gate). FAILED or SKIPPED → skip Phase 8 and continue with Phase 9 and the later phases in order.
427
438
 
428
439
  ### Phase 8: CI Status Gate (Conditional)
429
440
 
@@ -593,7 +604,7 @@ If the script prints a `TRACEABILITY: DEGRADED` line: warn, proceed to Phase 10.
593
604
 
594
605
  ### Phase 10: Report
595
606
 
596
- **Requires:** BRANCH_INFO, TARGET_DIR, PR_COMMENT, THREAD_RESOLUTION_RESULT
607
+ **Requires:** BRANCH_INFO, TARGET_DIR, PR_COMMENT, THREAD_RESOLUTION_RESULT, GATE_LEVEL
597
608
 
598
609
  The resolution summary was already written to `{TARGET_DIR}/resolution-summary.md` in Phase 5 (updated by Phase 7, Phase 9 and Phase 9b-1). Display results to the user:
599
610
 
@@ -603,6 +614,7 @@ The resolution summary was already written to `{TARGET_DIR}/resolution-summary.m
603
614
  **Branch**: {branch}
604
615
  **Reviews Processed**: {n} reports from {TARGET_DIR}
605
616
  **Total Issues**: {n}
617
+ **Gate level**: {GATE_LEVEL, with any level note}
606
618
 
607
619
  ### Results
608
620
  | Outcome | Count |
@@ -648,14 +660,6 @@ In multi-worktree mode, report results per worktree with aggregate summary.
648
660
 
649
661
  ### Feature Knowledge Write-Back (Conditional)
650
662
 
651
- 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
652
-
653
- ```bash
654
- git -C "{start}" rev-parse --show-toplevel
655
- ```
656
-
657
- 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}`.
658
-
659
663
  **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.
660
664
 
661
665
  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.
@@ -703,21 +707,18 @@ When the Knowledge agent reports `KB_COMMIT: skipped (detached HEAD)`, the files
703
707
  /resolve (orchestrator - spawns agents only)
704
708
  │
705
709
  ├─ Phase 0: Worktree Discovery & Pre-flight
706
- ├─ Phase 1: Parse issues from TARGET_DIR + extract confidence %
710
+ ├─ Phase 1: Parse issues from TARGET_DIR
707
711
  ├─ Phase 1b: Fetch external threads (evidence policy required)
708
712
  ├─ Phase 2: Global Triage [Triage agent, opus, single agent]
709
- ├─ Phase 3: Batch FIX_NOW issues (skip if empty; DUPLICATE issues never dispatched)
710
- ├─ Phase 4: Fix [Code agent × N, OPERATION: issue-fix, PUSH: false]
713
+ ├─ Phase 3: Batch FIX_NOW issues
714
+ ├─ Phase 4: Fix [Code agent × N]
711
715
  ├─ Phase 5: Write resolution-summary.md (compaction safety; Tracked = "(pending)" or "(pending — TRACEABILITY: DEGRADED)" if manage-debt degrades)
712
- ├─ Phase 6: Polish [Polish agent]
716
+ ├─ Phase 6: Polish
713
717
  ├─ Phase 7: Verification Gate [Validate agent, haiku] + push + Fix agent validation-fix loop ≤2
714
- ├─ Phase 8: CI Status Gate (conditional — skipped if no fixes or verification FAILED)
718
+ ├─ Phase 8: CI Status Gate (conditional)
715
719
  ├─ Phase 9: Git agent (manage-debt) — FIX_SEPARATE + TECH_DEBT → backfill Tracked={ISSUE_REF} (or TRACEABILITY: DEGRADED on failure)
716
720
  │
717
- ├─ Phase 9b: Thread resolution + resolution comment
718
- │ ├─ Step 9b-0: verify-evidence.cjs --stale-out → ≤1 Test agent on the stale TPs (wrapped) — only after this run's push
719
- │ ├─ Step 9b-1: Git agent (resolve-review-threads) — evidence policy required
720
- │ ├─ Step 9b-2: Git agent (post-resolution-summary, REVIEW_PUBLICATION) — always-on
721
+ ├─ Phase 9b: 9b-0 Test agent (stale TPs), 9b-1/9b-2 Git agent (threads, resolution comment)
721
722
  │ └─ Step 9b-3: verify-evidence.cjs publish (inline, no Git spawn) — only when the head moved
722
723
  │
723
724
  ├─ Phase 9c: verify-evidence.cjs readiness (inline, no Git spawn) — non-author approval required, report-only
@@ -730,27 +731,23 @@ When the Knowledge agent reports `KB_COMMIT: skipped (detached HEAD)`, the files
730
731
  | Case | Handling |
731
732
  |------|----------|
732
733
  | No reviews exist | Check bug-analysis fallback (Step 0c-5b); if also absent, error and suggest `/code-review` or `/bug-analysis` |
733
- | All false positives | Normal completion, report shows 0 fixes |
734
734
  | Fix attempt fails | Revert changes, mark BLOCKED, continue others |
735
735
  | Issue dependencies | Sequential chain, skip dependents if predecessor blocked |
736
- | No actionable issues | Report "No issues to resolve" |
737
- | Latest review already resolved | Check bug-analysis fallback (Step 0c-5b); if also absent, skip worktree and suggest `/code-review` or `/bug-analysis` |
736
+ | No issues parsed | Report "No issues to resolve" |
738
737
  | `--review {timestamp}` in multi-worktree mode | Not supported — use `--path` + `--review` to target specific worktree + review |
739
738
  | gh/GitHub absent | manage-debt degrades (`TRACEABILITY: DEGRADED ({reason})`); Tracked stays `(pending — TRACEABILITY: DEGRADED ({reason}))` — recorded, not dropped |
740
739
  | `EVIDENCE_POLICY` is `standard` | Phases 1b and 9b-step-1 are skipped; post-resolution-summary (Phase 9b step 2) still runs if a PR is known |
741
740
  | `REQUIRE_NON_AUTHOR_APPROVAL` is `false` | Phase 9c is skipped and reported as SKIPPED |
742
- | Public repo (`auto` mode) | Git agent probes visibility, posts counts-only STUB comment; full resolution report stays local |
743
741
  | `reviewPublication: off` | Git agent skips posting the resolution comment (OFF) — except that, only when `EVIDENCE_POLICY` is `required`, Step 0d passes `stub` and a counts-only STUB comment posts |
744
- | Fork PR this run cannot push to (no maintainer edits, no push access of its own) | validate-branch emits `TRACEABILITY: DEGRADED (cannot push to fork)` → `fork_no_push`: Phase 7 skips the push, Phase 8 is skipped, 9b-1 records FIXED threads as DEGRADED instead of citing unpushed commits; 9b-2 still posts the resolution comment; the head did not move, so 9b-0 and 9b-3 are skipped |
742
+ | Fork PR this run cannot push to | `TRACEABILITY: DEGRADED (cannot push to fork)` → `fork_no_push`: no push in Phase 7, Phase 8 skipped, 9b-1 records FIXED threads as DEGRADED, 9b-2 still posts; the head did not move, so 9b-0 and 9b-3 are skipped |
745
743
  | The PR has no trusted evidence record | 9b-0 finds no vouched-for stale line, so no Test agent runs; 9b-3 still refreshes the block and comment, every TP without a claim reading `UNVERIFIED` |
746
744
  | A CI run behind a claim has expired (~90 days) | The TP reads `INDETERMINATE` — never verified, never failed — until a claim at a newer SHA settles it |
747
745
 
748
746
  ## Principles
749
747
 
750
748
  1. **Orchestration only** - Command spawns agents, doesn't do git/resolve work itself
751
- 2. **No agent grades its own homework** - Triage agent validates, Code agents fix, Validate agent verifies
752
- 3. **Git agent for git work** - All git operations go through Git agent; the CI wait, the evidence refresh and the merge-readiness check are inline scripts (plumbing, no model work)
753
- 4. **Traceability-aware** - Policy-gated ops (thread fetch/resolve, merge readiness) are skipped cleanly when the evidence policy does not ask for them; resolution comment (Phase 9b-2) is always-on; test-plan evidence is re-verified (≤1 Test agent) and refreshed only when this run moved the head (Steps 9b-0, 9b-3)
749
+ 2. **Git agent for git work** - All git operations go through Git agent; inline scripts are plumbing
750
+ 3. **Traceability-aware** - Policy-gated ops are skipped cleanly when the evidence policy does not ask for them; resolution comment (Phase 9b-2) is always-on; test-plan evidence is re-verified (≤1 Test agent) and refreshed only when this run moved the head (Steps 9b-0, 9b-3)
754
751
 
755
752
  ## Output Artifact
756
753
 
@@ -763,6 +760,7 @@ Written in Phase 5 (Collect Results) to `{TARGET_DIR}/resolution-summary.md`:
763
760
  **Date**: {RESOLUTION_TS}
764
761
  **Review**: {TARGET_DIR_REL}
765
762
  **Command**: /resolve
763
+ **Gate level**: {GATE_LEVEL, with any level note}
766
764
 
767
765
  ## Decisions Citations
768
766
 
@@ -24,19 +24,19 @@ Detect changed files and build context:
24
24
  4. Build TASK_DESCRIPTION from recent commit messages or branch name
25
25
  5. Record `HEAD_BEFORE` (`git rev-parse HEAD`) now, before Polish runs — Phase 3 compares against it
26
26
 
27
- **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:
27
+ **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 in a one-worktree run:
28
28
 
29
29
  ```bash
30
30
  node "$HOME/.devflow/scripts/resolve-settings.cjs" "{root}" 2>/dev/null; echo "exit=$?"
31
31
  ```
32
32
 
33
- 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> GATE_LEVEL=<full|standard|lean>` — 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 GATE_LEVEL=full` instead.
33
+ 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> CURATION=<on|off> KNOWLEDGE=<on|off> GATE_LEVEL=<full|standard|lean>` — 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=off CURATION=off KNOWLEDGE=off GATE_LEVEL=full` instead.
34
34
 
35
35
  The accepted line is the only source of these values.
36
36
 
37
37
  ### Load DECISIONS_CONTEXT
38
38
 
39
- When the settings line says `LEARNING=off`, set `DECISIONS_CONTEXT` to `(none)` and skip this step, locating no ledger and reading no index.
39
+ When the settings line says `CURATION=off`, set `DECISIONS_CONTEXT` to `(none)` and skip this step, locating no ledger and reading no index.
40
40
 
41
41
  The decisions ledger belongs to the repository, not to one checkout: a linked worktree reads the main worktree's copy, a subdirectory session the repository root's. Locate it with ONE git call, run from the start directory — `WORKTREE_PATH` if provided, otherwise cwd (`devflow:worktree-support`):
42
42
 
@@ -50,11 +50,11 @@ Line 1 is the checkout's toplevel, line 2 the common git directory. A git older
50
50
  2. **The toplevel** — line 1, or on an older git the line after the echoed flag.
51
51
  3. **The start directory itself** — when the command failed or printed no absolute toplevel (outside a git repository).
52
52
 
53
- This is the rule the learning hooks apply, so you read the index the Curate agent writes.
53
+ This is the rule the curation hooks apply, so you read the index the Curate agent writes.
54
54
 
55
55
  **Step 1 — Read the pre-rendered index:**
56
56
 
57
- Attempt to read `{ledger}/.devflow/learning/index.md`.
57
+ Attempt to read `{ledger}/.devflow/curation/index.md`.
58
58
 
59
59
  - If the file exists and contains non-empty content: use that content as `DECISIONS_CONTEXT`.
60
60
  - If the file is absent or empty: set `DECISIONS_CONTEXT` to `(none)`.
@@ -214,14 +214,6 @@ Display summary:
214
214
 
215
215
  ### Feature Knowledge Write-Back (Conditional)
216
216
 
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
217
  **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.
226
218
 
227
219
  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.
@@ -0,0 +1,44 @@
1
+ /**
2
+ * @file area-pause-notice.ts
3
+ *
4
+ * The fixed notice of a paused area. When git tracks files in the folders of an area, or
5
+ * a `.git` entry stands and git did not answer, the area's feature reads and writes
6
+ * nothing there, and says so once at session start. The curation area covers the curation
7
+ * folder, the old ledger folder and the backup folders with one notice; the memory
8
+ * area covers the memory folder. Pure: no fs, no os, no process state.
9
+ *
10
+ * The words hold nothing from the repository: the area is a fixed enum, and no path,
11
+ * count or git output goes into them. The session start hook
12
+ * (src/assets/scripts/hooks/session-start-context) holds the curation words, and the
13
+ * memory session start hook (src/assets/scripts/hooks/session-start-memory) holds the
14
+ * memory words; tests/shell-hooks.test.ts requires each copy to agree with this module.
15
+ * The two commands a notice tells the user to run are listed in NOTICE_COMMAND_PHRASES in
16
+ * tests/guards/no-fsmonitor-index-read.test.ts, which holds every copy to them.
17
+ */
18
+ const UNTRACK_STEPS = 'To find the files, run `git ls-files .devflow`. '
19
+ + 'Untrack them with `git rm --cached <file>`, then delete them if you did not make them. ';
20
+ const RETRY_STEPS = 'The check runs again at the next session start. ';
21
+ /** The notice of each paused area and reason, as one paragraph of short sentences. */
22
+ export const AREA_PAUSE_NOTICE = {
23
+ curation: {
24
+ tracked: 'Devflow curation is paused for this project, because git tracks files in a curation data folder. '
25
+ + 'Devflow reads and writes nothing in these folders while git tracks files there. '
26
+ + UNTRACK_STEPS
27
+ + 'Run these commands in the main checkout.',
28
+ unknown: 'Devflow curation is paused for this project, because git did not answer whether it tracks files in a curation data folder. '
29
+ + 'Devflow reads and writes nothing in these folders until git answers. '
30
+ + RETRY_STEPS
31
+ + 'If this notice stays, check that git runs in this project.',
32
+ },
33
+ memory: {
34
+ tracked: 'Devflow memory is paused for this checkout, because git tracks files in the memory folder. '
35
+ + 'Devflow reads and writes nothing there while git tracks files there. '
36
+ + UNTRACK_STEPS
37
+ + 'Run these commands in this checkout.',
38
+ unknown: 'Devflow memory is paused for this checkout, because git did not answer whether it tracks files in the memory folder. '
39
+ + 'Devflow reads and writes nothing there until git answers. '
40
+ + RETRY_STEPS
41
+ + 'If this notice stays, check that git runs in this checkout.',
42
+ },
43
+ };
44
+ //# sourceMappingURL=area-pause-notice.js.map
@@ -1,13 +1,13 @@
1
1
  import { join } from 'path';
2
2
  import { getPackageRoot } from './paths.js';
3
3
  import { SKILL_REFS_OUTPUT_DIR } from './mds-variants.js';
4
- import { LEARNING_OFF_OUTPUT_DIR } from './learning-variants.js';
4
+ import { CURATION_OFF_OUTPUT_DIR } from './curation-variants.js';
5
5
  /**
6
6
  * Flat skills source directory: src/assets/skills/{name}/
7
7
  * All plugins' skills live here directly (no per-plugin subdirectory).
8
8
  *
9
9
  * @param root - Package root to resolve against. Injectable so a caller working
10
- * on a temp tree (the learning converge) reads the skill source from the same
10
+ * on a temp tree (the curation converge) reads the skill source from the same
11
11
  * root as the rest of its sources.
12
12
  */
13
13
  export function skillsDir(root = getPackageRoot()) {
@@ -41,42 +41,42 @@ export function scriptsDir() {
41
41
  /**
42
42
  * Compiled commands directory: dist/commands/
43
43
  * Single lookup directory for installed commands: one compiled file per `.mds`
44
- * command host in src/assets/commands/. A host that carries a learning arm also
45
- * has a learning-off variant (see learningOffDir).
44
+ * command host in src/assets/commands/. A host that carries a curation arm also
45
+ * has a curation-off variant (see curationOffDir).
46
46
  */
47
47
  export function commandsDir() {
48
48
  return join(getPackageRoot(), 'dist', 'commands');
49
49
  }
50
50
  /**
51
- * Learning-off variant directory: dist/learning-off/{commands,agents}/
51
+ * Curation-off variant directory: dist/curation-off/{commands,agents}/
52
52
  *
53
- * Holds the learning-off variant of each prompt that carries a learning arm
53
+ * Holds the curation-off variant of each prompt that carries a curation arm
54
54
  * (D-LEARNING-VARIANTS), and only those. Absent until the build has run, so every
55
55
  * reader tolerates its absence.
56
56
  *
57
- * The spelling comes from LEARNING_OFF_OUTPUT_DIR in learning-variants.ts, the
57
+ * The spelling comes from CURATION_OFF_OUTPUT_DIR in curation-variants.ts, the
58
58
  * build's own destination, rather than being retyped here.
59
59
  *
60
60
  * @param kind - Which prompt kind's variants.
61
61
  * @param root - Package root to resolve against (see agentsDir).
62
62
  */
63
- export function learningOffDir(kind, root = getPackageRoot()) {
64
- return join(root, ...LEARNING_OFF_OUTPUT_DIR.split('/'), kind);
63
+ export function curationOffDir(kind, root = getPackageRoot()) {
64
+ return join(root, ...CURATION_OFF_OUTPUT_DIR.split('/'), kind);
65
65
  }
66
66
  /**
67
67
  * Command source directories, MOST-PREFERRED FIRST.
68
68
  *
69
- * D-LEARNING-VARIANT-INSTALL: with learning off the learning-off variant comes
69
+ * D-LEARNING-VARIANT-INSTALL: with curation off the curation-off variant comes
70
70
  * first, so a host with an arm installs its off variant and a host with none falls
71
- * through to the one compiled file; with learning on the order is the normal
71
+ * through to the one compiled file; with curation on the order is the normal
72
72
  * single-directory lookup.
73
73
  *
74
- * @param learning - The machine's settled learning switch.
74
+ * @param curation - The machine's settled curation switch.
75
75
  * @param root - Package root to resolve against (see agentsDir).
76
76
  */
77
- export function commandSourceDirs(learning, root = getPackageRoot()) {
77
+ export function commandSourceDirs(curation, root = getPackageRoot()) {
78
78
  const normal = join(root, 'dist', 'commands');
79
- return learning ? [normal] : [learningOffDir('commands', root), normal];
79
+ return curation ? [normal] : [curationOffDir('commands', root), normal];
80
80
  }
81
81
  /**
82
82
  * Compiled agents directory: dist/agents/{name}.md
@@ -124,17 +124,17 @@ export function compiledSkillRefsDir(root = getPackageRoot()) {
124
124
  * The non-empty tuple makes an empty list a compile error at every call site:
125
125
  * an empty list would survive a `??` default and resolve to nothing.
126
126
  *
127
- * D-LEARNING-VARIANT-INSTALL: `learning: false` puts dist/learning-off/agents first,
128
- * for the installer and the converge only. The default (learning on) is the order
127
+ * D-LEARNING-VARIANT-INSTALL: `curation: false` puts dist/curation-off/agents first,
128
+ * for the installer and the converge only. The default (curation on) is the order
129
129
  * every other reader wants: the shipped defaults (model, effort) are the same in
130
130
  * both variants, so loadShippedAgentDefaults and the test harness keep reading the
131
- * learning-on tree.
131
+ * curation-on tree.
132
132
  *
133
133
  * @param root - Package root to resolve against (see agentsDir).
134
- * @param learning - The machine's settled learning switch; on by default.
134
+ * @param curation - The machine's settled curation switch; on by default.
135
135
  */
136
- export function agentSourceDirs(root = getPackageRoot(), learning = true) {
136
+ export function agentSourceDirs(root = getPackageRoot(), curation = true) {
137
137
  const normal = [compiledAgentsDir(root), agentsDir(root)];
138
- return learning ? normal : [learningOffDir('agents', root), ...normal];
138
+ return curation ? normal : [curationOffDir('agents', root), ...normal];
139
139
  }
140
140
  //# sourceMappingURL=assets.js.map
@@ -1,7 +1,6 @@
1
1
  import * as fs from 'fs';
2
- import * as path from 'path';
3
2
  import { getDevFlowDirectory } from '../targets/claude-code/claude-paths.js';
4
- import { getCurateTuningConfigPath } from './project-paths.js';
3
+ import { getCurateTuningConfigPath, getGlobalCurateTuningConfigPath } from './project-paths.js';
5
4
  const VALID_MODELS = new Set(['opus', 'sonnet', 'haiku']);
6
5
  function isValidModel(value) {
7
6
  return typeof value === 'string' && VALID_MODELS.has(value);
@@ -64,15 +63,15 @@ function readConfigFile(filePath) {
64
63
  *
65
64
  * Priority (highest wins): project config → global config → defaults.
66
65
  *
67
- * - Global: `~/.devflow/learning.json`
68
- * - Project: `<ledgerRoot>/.devflow/learning/learning.json` — pass the ledger root
69
- * (getLedgerRoot), where session-start-context reads it and `devflow learning
66
+ * - Global: `~/.devflow/curation.json`
67
+ * - Project: `<ledgerRoot>/.devflow/curation/curation.json` — pass the ledger root
68
+ * (getLedgerRoot), where session-start-context reads it and `devflow curation
70
69
  * --configure` writes it (D-LEDGER-MAIN-WORKTREE).
71
70
  *
72
71
  * Invalid JSON in either file is silently ignored and treated as absent.
73
72
  */
74
73
  export function loadCurateTuningConfig(ledgerRoot) {
75
- const globalConfigPath = path.join(getDevFlowDirectory(), 'learning.json');
74
+ const globalConfigPath = getGlobalCurateTuningConfigPath(getDevFlowDirectory());
76
75
  const projectConfigPath = getCurateTuningConfigPath(ledgerRoot);
77
76
  let config = { ...DEFAULTS };
78
77
  const globalJson = readConfigFile(globalConfigPath);
@@ -0,0 +1,84 @@
1
+ /**
2
+ * @file curation-move-notice.ts
3
+ *
4
+ * The notice for a project whose ledger still sits in the old folder: which line to
5
+ * show, the words of each, the fixed notice of a skipped move, and where the shell
6
+ * shim's markers for the project stand. The statusline (src/hud/components/curation-counts.ts)
7
+ * and `devflow curation` (src/cli/commands/curation.ts) both import it from here, so they
8
+ * say the same words and read the same markers, and neither imports the other.
9
+ *
10
+ * Reads the disk with one lstat per path, never follows a link and never opens the old
11
+ * ledger. The HUD runs it on every prompt, so it forks nothing and holds no state.
12
+ */
13
+ import * as fs from 'node:fs';
14
+ import * as path from 'node:path';
15
+ import { LEGACY_NAMES, curationMoveMarkerKey } from './project-paths.js';
16
+ import { MOVE_SKIP_NOTICE, isMoveSkipReason } from './curation-move-skip.js';
17
+ /** The file suffix of each marker kind, as the shim writes it. */
18
+ const MARKER_SUFFIX = {
19
+ refused: 'skip',
20
+ tracked: 'tracked',
21
+ unknown: 'unknown',
22
+ };
23
+ /**
24
+ * The marker the `curation-move` shim writes for the ledger root `root`:
25
+ * `<home>/.devflow/logs/curation-move.<key>.<suffix>`, the key being the root's
26
+ * {@link curationMoveMarkerKey}. Without `kind` it is the refusal marker (`refused`, the
27
+ * suffix `skip`). The shim builds the same paths in `_df_cm_markers`
28
+ * (src/assets/scripts/hooks/curation-move); tests/shell-hooks.test.ts runs that function
29
+ * and requires the two to agree for short, long and non-ASCII roots. Every marker stands
30
+ * outside the project, so a skipped move writes nothing into it.
31
+ */
32
+ export function getCurationMoveMarkerPath(home, root, kind = 'refused') {
33
+ return path.join(home, '.devflow', 'logs', `curation-move.${curationMoveMarkerKey(root)}.${MARKER_SUFFIX[kind]}`);
34
+ }
35
+ /** Whether anything, a link included, sits at `target`. One lstat, never followed. */
36
+ function exists(target) {
37
+ try {
38
+ fs.lstatSync(target);
39
+ return true;
40
+ }
41
+ catch {
42
+ return false;
43
+ }
44
+ }
45
+ /** The markers {@link gatherMoveNotice} looks for, in the order it prefers them, and the notice each one means. */
46
+ const MARKER_NOTICES = [
47
+ ['tracked', 'tracked'],
48
+ ['unknown', 'unknown'],
49
+ ['refused', 'refused'],
50
+ ];
51
+ /**
52
+ * The one extra question of a project with no counts to show: does it still have the old
53
+ * ledger folder? One existence test. If it does, one more for each of the shim's markers
54
+ * under the key of this same root ({@link getCurationMoveMarkerPath}) says which notice
55
+ * applies. Null when the old folder is gone. The old ledger itself is never opened or counted.
56
+ */
57
+ export function gatherMoveNotice(ledgerRoot, home) {
58
+ if (!exists(path.join(ledgerRoot, '.devflow', LEGACY_NAMES.folder)))
59
+ return null;
60
+ const found = MARKER_NOTICES.find(([kind]) => exists(getCurationMoveMarkerPath(home, ledgerRoot, kind)));
61
+ return found === undefined ? 'pointer' : found[1];
62
+ }
63
+ const MOVE_NOTICE_TEXT = {
64
+ pointer: 'run devflow init, or open Claude Code in this project after it',
65
+ refused: 'move refused, see the hook log',
66
+ tracked: 'move skipped, git tracks files in the .devflow data folders',
67
+ unknown: 'move skipped, git did not answer',
68
+ };
69
+ /**
70
+ * The one line the HUD prints for a notice. With `counts` (the entry counts, such as
71
+ * `2 decisions, 1 pitfall`) the notice follows them on the same line.
72
+ */
73
+ export function formatMoveNotice(notice, counts) {
74
+ return counts === undefined ? `Curation: ${MOVE_NOTICE_TEXT[notice]}` : `Curation: ${counts}; ${MOVE_NOTICE_TEXT[notice]}`;
75
+ }
76
+ /**
77
+ * The text `devflow curation --status`, `--list` and `--show` print for a notice: the HUD's
78
+ * line, except that a skipped move gets its whole fixed notice (MOVE_SKIP_NOTICE),
79
+ * because these commands have room to say what to do.
80
+ */
81
+ export function describeMoveNotice(notice) {
82
+ return isMoveSkipReason(notice) ? `Curation: ${MOVE_SKIP_NOTICE[notice]}` : formatMoveNotice(notice);
83
+ }
84
+ //# sourceMappingURL=curation-move-notice.js.map
@@ -0,0 +1,35 @@
1
+ /**
2
+ * @file curation-move-skip.ts
3
+ *
4
+ * The fixed notice of a skipped move. The move leaves a project alone, and changes
5
+ * nothing, when git tracks files in a curation data folder (`tracked`) or when a
6
+ * `.git` entry stands and git did not answer (`unknown`). Pure: no fs, no os, no
7
+ * process state, so the init step (src/cli/commands/curation-move-step.ts) and the
8
+ * notice module (src/core/curation-move-notice.ts) can both import it.
9
+ *
10
+ * The words hold nothing from the repository. The two commands the notice tells the
11
+ * user to run are listed in NOTICE_COMMAND_PHRASES in
12
+ * tests/guards/no-fsmonitor-index-read.test.ts, which holds this file to them. The
13
+ * notice of a paused area is in src/core/area-pause-notice.ts.
14
+ */
15
+ import { CURATION_DIR_NAME, LEGACY_NAMES } from './project-paths.js';
16
+ const MOVE_DESCRIPTION = `devflow did not move the curation data of this project from .devflow/${LEGACY_NAMES.folder}/ to .devflow/${CURATION_DIR_NAME}/, `;
17
+ /** The notice of each skip reason, as one paragraph of short sentences. */
18
+ export const MOVE_SKIP_NOTICE = {
19
+ tracked: `${MOVE_DESCRIPTION}because git tracks files in a curation data folder. `
20
+ + 'To find them, run `git ls-files .devflow`. '
21
+ + 'Untrack them with `git rm --cached <file>`, and delete them if you did not make them. '
22
+ + 'Run these commands in the checkout that holds these folders.',
23
+ unknown: `${MOVE_DESCRIPTION}because git did not answer. `
24
+ + 'The move runs again at the next session start or the next init. '
25
+ + 'If this notice stays, check that git runs in this project.',
26
+ };
27
+ /**
28
+ * Whether `value` is a {@link MoveSkipReason}: a reason that has a notice. The members
29
+ * come from the keys of {@link MOVE_SKIP_NOTICE}, which the compiler requires to list
30
+ * every reason, so this module needs no runtime import of the move seam.
31
+ */
32
+ export function isMoveSkipReason(value) {
33
+ return typeof value === 'string' && Object.hasOwn(MOVE_SKIP_NOTICE, value);
34
+ }
35
+ //# sourceMappingURL=curation-move-skip.js.map
@@ -0,0 +1,35 @@
1
+ /**
2
+ * The CLI's view of the curation move — a typed seam onto the package's own
3
+ * `hooks/lib/curation-move.cjs`, never a second implementation of it.
4
+ *
5
+ * The one-time move of the old ledger folder to its new name lives in its own module,
6
+ * beside the store it builds on. `devflow init` and `devflow curation` reach it only
7
+ * through this seam: the module is loaded with the evidence-policy seam's `loadScript`
8
+ * from the package's own scripts directory and shape-checked against
9
+ * CURATION_MOVE_SURFACE; the interfaces below are TRANSCRIBED from the module's JSDoc
10
+ * and are this side's only shape authority (as for the store, see curation-store.ts).
11
+ */
12
+ import { join } from 'path';
13
+ import { scriptsDir } from './assets.js';
14
+ import { loadScript } from './evidence-policy.js';
15
+ /** The move module, relative to src/assets/scripts/ (and ~/.devflow/scripts/). */
16
+ export const CURATION_MOVE_SCRIPT_NAME = join('hooks', 'lib', 'curation-move.cjs');
17
+ /**
18
+ * Every key of CurationMoveModule and the runtime kind the loader requires of it.
19
+ * `satisfies` makes the compiler reject an interface key missing here.
20
+ */
21
+ export const CURATION_MOVE_SURFACE = Object.freeze({
22
+ moveLedger: 'function',
23
+ sweepLedgerBackups: 'function',
24
+ backupPendingRows: 'function',
25
+ backupQueueFiles: 'function',
26
+ });
27
+ /**
28
+ * Load the curation move module from `dir` (default: the package's own scripts
29
+ * directory) and shape-check its surface. Never throws: a missing file is
30
+ * `not-found`; a module that throws on load or lacks a surface key is `unusable`.
31
+ */
32
+ export function loadCurationMove(dir = scriptsDir()) {
33
+ return loadScript(join(dir, CURATION_MOVE_SCRIPT_NAME), CURATION_MOVE_SURFACE);
34
+ }
35
+ //# sourceMappingURL=curation-move.js.map