devflow-kit 3.0.1 → 3.2.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 (166) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/README.md +1 -1
  3. package/dist/agents/git.md +2 -2
  4. package/dist/cli/agents-view/index.js +1 -1
  5. package/dist/cli/agents-view/render.js +71 -17
  6. package/dist/cli/agents-view/state.js +42 -16
  7. package/dist/cli/agents-view/terminal.js +5 -5
  8. package/dist/cli/commands/agents.js +142 -51
  9. package/dist/cli/commands/ambient.js +1 -1
  10. package/dist/cli/commands/attribution-prompts.js +8 -8
  11. package/dist/cli/commands/capture.js +1 -1
  12. package/dist/cli/commands/compliance-prompts.js +8 -8
  13. package/dist/cli/commands/compliance.js +8 -7
  14. package/dist/cli/commands/flags.js +33 -31
  15. package/dist/cli/commands/hud.js +1 -1
  16. package/dist/cli/commands/init-seed.js +9 -9
  17. package/dist/cli/commands/init.js +162 -85
  18. package/dist/cli/commands/install-report.js +10 -10
  19. package/dist/cli/commands/learning.js +302 -136
  20. package/dist/cli/commands/memory.js +36 -15
  21. package/dist/cli/commands/proxy.js +23 -23
  22. package/dist/cli/commands/rules.js +6 -5
  23. package/dist/cli/commands/tracker-prompts.js +6 -6
  24. package/dist/cli/commands/tracker.js +9 -9
  25. package/dist/cli/commands/uninstall.js +183 -59
  26. package/dist/cli/flags-view/render.js +5 -5
  27. package/dist/cli/flags-view/state.js +9 -9
  28. package/dist/cli/flags-view/terminal.js +4 -4
  29. package/dist/cli/tui/cells.js +1 -1
  30. package/dist/cli/tui/terminal.js +6 -6
  31. package/dist/commands/code-review.md +0 -2
  32. package/dist/commands/debug.md +14 -11
  33. package/dist/commands/dynamic-build.md +51 -47
  34. package/dist/commands/dynamic-plan.md +27 -7
  35. package/dist/commands/dynamic-profile.md +17 -3
  36. package/dist/commands/dynamic-tickets.md +18 -4
  37. package/dist/commands/explore.md +9 -3
  38. package/dist/commands/implement.md +20 -16
  39. package/dist/commands/plan.md +13 -9
  40. package/dist/commands/release.md +23 -3
  41. package/dist/commands/research.md +9 -3
  42. package/dist/commands/resolve.md +9 -12
  43. package/dist/commands/self-review.md +0 -2
  44. package/dist/core/agent-frontmatter.js +28 -3
  45. package/dist/core/agent-models.js +204 -42
  46. package/dist/core/agent-state.js +28 -6
  47. package/dist/core/ansi.js +2 -2
  48. package/dist/core/assets.js +1 -1
  49. package/dist/core/cache.js +7 -8
  50. package/dist/core/codex-auth-inspect.js +4 -4
  51. package/dist/core/compliance-compose.js +3 -3
  52. package/dist/core/compliance.js +3 -4
  53. package/dist/core/evidence-policy.js +14 -13
  54. package/dist/core/external-models.js +1 -1
  55. package/dist/core/feature-config.js +71 -13
  56. package/dist/core/feature-switch.js +3 -3
  57. package/dist/core/flags.js +49 -25
  58. package/dist/core/fs-atomic.js +6 -7
  59. package/dist/core/learning-queue-cleanup.js +16 -81
  60. package/dist/core/learning-store.js +61 -0
  61. package/dist/core/linked-path.js +46 -0
  62. package/dist/core/manifest.js +5 -5
  63. package/dist/core/mds-variants.js +13 -13
  64. package/dist/core/model-discovery.js +8 -8
  65. package/dist/core/observations.js +17 -101
  66. package/dist/core/orphan-sweep.js +4 -4
  67. package/dist/core/plugins.js +13 -8
  68. package/dist/core/project-paths.js +9 -13
  69. package/dist/core/proxy-log.js +8 -8
  70. package/dist/core/proxy-state.js +3 -3
  71. package/dist/core/queue-drain.js +31 -0
  72. package/dist/core/reference-sweep.js +6 -6
  73. package/dist/core/teammate-mode-cleanup.js +1 -1
  74. package/dist/core/tracker.js +14 -14
  75. package/dist/hud/colors.js +2 -2
  76. package/dist/hud/components/learning-counts.js +54 -22
  77. package/dist/hud/components/version-badge.js +1 -1
  78. package/dist/skills/git/references/pr/resolve-review-threads.md +2 -2
  79. package/dist/skills/git/references/tracker/github/create-release.md +2 -2
  80. package/dist/skills/git/references/tracker/jira/create-release.md +2 -2
  81. package/dist/skills/git/references/tracker/linear/create-release.md +2 -2
  82. package/dist/targets/claude-code/compliance-install.js +17 -15
  83. package/dist/targets/claude-code/hooks.js +2 -2
  84. package/dist/targets/claude-code/installer.js +59 -32
  85. package/dist/targets/claude-code/legacy.js +1 -1
  86. package/dist/targets/claude-code/post-install.js +135 -45
  87. package/dist/targets/claude-code/tracker-install.js +2 -2
  88. package/package.json +1 -1
  89. package/src/assets/agents/code.md +15 -21
  90. package/src/assets/agents/design.md +4 -2
  91. package/src/assets/agents/diagnose.md +3 -1
  92. package/src/assets/agents/evaluate.md +4 -0
  93. package/src/assets/agents/git.mds +2 -2
  94. package/src/assets/agents/knowledge.md +5 -3
  95. package/src/assets/agents/learning.md +281 -196
  96. package/src/assets/agents/research.md +3 -1
  97. package/src/assets/agents/review.md +5 -3
  98. package/src/assets/agents/scrutinize.md +5 -1
  99. package/src/assets/agents/simplify.md +4 -0
  100. package/src/assets/agents/skim.md +4 -2
  101. package/src/assets/agents/synthesize.md +6 -0
  102. package/src/assets/agents/test.md +18 -10
  103. package/src/assets/agents/triage.md +11 -9
  104. package/src/assets/agents/validate.md +14 -10
  105. package/src/assets/commands/_partials/_decisions.mds +8 -3
  106. package/src/assets/commands/_partials/_docs_root.mds +3 -3
  107. package/src/assets/commands/_partials/_engine.mds +16 -32
  108. package/src/assets/commands/_partials/_knowledge.mds +0 -2
  109. package/src/assets/commands/_partials/_preamble.mds +6 -2
  110. package/src/assets/commands/_partials/_settings.mds +2 -2
  111. package/src/assets/commands/_partials/_tracker.mds +1 -1
  112. package/src/assets/commands/code-review.mds +0 -2
  113. package/src/assets/commands/debug.mds +13 -8
  114. package/src/assets/commands/dynamic-build.mds +18 -12
  115. package/src/assets/commands/dynamic-plan.mds +10 -4
  116. package/src/assets/commands/dynamic-profile.mds +1 -1
  117. package/src/assets/commands/dynamic-tickets.mds +2 -2
  118. package/src/assets/commands/explore.mds +9 -1
  119. package/src/assets/commands/implement.mds +19 -13
  120. package/src/assets/commands/plan.mds +12 -8
  121. package/src/assets/commands/release.md +23 -3
  122. package/src/assets/commands/research.mds +9 -3
  123. package/src/assets/commands/resolve.mds +9 -10
  124. package/src/assets/mds/git/_pr.mds +3 -3
  125. package/src/assets/mds/tracker/_common.mds +1 -1
  126. package/src/assets/mds/tracker/_github.mds +3 -3
  127. package/src/assets/mds/tracker/_jira.mds +3 -3
  128. package/src/assets/mds/tracker/_linear.mds +3 -3
  129. package/src/assets/mds/tracker/_mcp.mds +6 -5
  130. package/src/assets/scripts/hooks/assets/orchestrator-charter.md +4 -2
  131. package/src/assets/scripts/hooks/background-memory-update +97 -33
  132. package/src/assets/scripts/hooks/capture-prompt +4 -3
  133. package/src/assets/scripts/hooks/capture-question +4 -3
  134. package/src/assets/scripts/hooks/capture-turn +5 -20
  135. package/src/assets/scripts/hooks/ensure-devflow-init +14 -2
  136. package/src/assets/scripts/hooks/ensure-proxy +5 -6
  137. package/src/assets/scripts/hooks/ensure-root-gitignore +123 -11
  138. package/src/assets/scripts/hooks/git-marker +71 -0
  139. package/src/assets/scripts/hooks/is-hex-sha +1 -1
  140. package/src/assets/scripts/hooks/json-helper.cjs +345 -944
  141. package/src/assets/scripts/hooks/json-parse +25 -129
  142. package/src/assets/scripts/hooks/lib/decisions-format.cjs +205 -156
  143. package/src/assets/scripts/hooks/lib/learning-store.cjs +3207 -0
  144. package/src/assets/scripts/hooks/lib/mkdir-lock.cjs +7 -5
  145. package/src/assets/scripts/hooks/lib/project-paths.cjs +13 -19
  146. package/src/assets/scripts/hooks/lib/render-decisions.cjs +253 -226
  147. package/src/assets/scripts/hooks/memory-worker +10 -0
  148. package/src/assets/scripts/hooks/pre-compact-memory +66 -14
  149. package/src/assets/scripts/hooks/preamble +9 -1
  150. package/src/assets/scripts/hooks/queue-append +55 -23
  151. package/src/assets/scripts/hooks/resolve-project-root +3 -4
  152. package/src/assets/scripts/hooks/session-start-context +146 -45
  153. package/src/assets/scripts/hooks/session-start-memory +33 -11
  154. package/src/assets/scripts/lib/project-config.cjs +2 -2
  155. package/src/assets/scripts/pr-evidence.cjs +3 -3
  156. package/src/assets/scripts/redact-secrets.cjs +20 -20
  157. package/src/assets/scripts/release-trace.cjs +1 -1
  158. package/src/assets/scripts/resolve-evidence-policy.cjs +3 -3
  159. package/src/assets/scripts/resolve-settings.cjs +3 -3
  160. package/src/assets/scripts/verify-evidence.cjs +2 -2
  161. package/src/assets/skills/apply-decisions/SKILL.md +37 -17
  162. package/src/assets/skills/docs-framework/SKILL.md +2 -2
  163. package/src/assets/skills/feature-knowledge/SKILL.md +6 -5
  164. package/src/assets/skills/test-driven-development/SKILL.md +6 -4
  165. package/dist/core/observation-io.js +0 -50
  166. package/src/assets/scripts/hooks/decisions-usage-scan.cjs +0 -131
@@ -16,13 +16,19 @@ Orchestrate a single task through implementation by spawning specialized agents.
16
16
 
17
17
  ## Input
18
18
 
19
- `$ARGUMENTS` contains whatever follows `/implement`:
19
+ What follows `/implement` is bound once, here. Every later step names it `COMMAND_INPUT` and never restates it:
20
+
21
+ <command-input>
22
+ $ARGUMENTS
23
+ </command-input>
24
+
25
+ `COMMAND_INPUT` is one of:
20
26
  - Plan document path: `.devflow/docs/design/42-jwt-auth.2026-04-07_1430.md` (path to an existing `.md` file)
21
27
  - Issue reference: `#42`
22
28
  - Task description: "implement JWT auth"
23
29
  - Empty: use conversation context
24
30
 
25
- **Issue-reference grammar (L1 — command layer, permissive and provider-blind):** scan `$ARGUMENTS` for candidate issue references — a `#`-prefixed token and a bare digit run are both candidates — and collect them in source order as the raw token list `ISSUE_REFS`. Forward that list to the Git agent **verbatim**: the command never renders, normalises, pads, strips or coerces a token, and never rules a candidate out. Under `github` a token matching `^#?[1-9][0-9]{0,8}$` **is** a reference and the Git agent renders it as `#{n}`.
31
+ **Issue-reference grammar (L1 — command layer, permissive and provider-blind):** scan `COMMAND_INPUT` for candidate issue references — a `#`-prefixed token and a bare digit run are both candidates — and collect them in source order as the raw token list `ISSUE_REFS`. Forward that list to the Git agent **verbatim**: the command never renders, normalises, pads, strips or coerces a token, and never rules a candidate out. Under `github` a token matching `^#?[1-9][0-9]{0,8}$` **is** a reference and the Git agent renders it as `#{n}`.
26
32
 
27
33
  **A token of any other shape is neither coerced nor dropped silently — and no producer-side grammar check rejects it before the fetch.** Adjudication belongs to the operation that runs, and each one answers in its own Output block: `fetch-issue` strips a leading `#` and takes the text branch, so a non-numeric token is used as a **search term** and the operation returns the first open match or nothing; `fetch-issues-batch` resolves each token to an issue number, drops the ones it cannot resolve, and names them in `NOT_FOUND ({refs})` beside the issues it did fetch. Read the outcome from the operation that ran — a token's shape is a verdict nowhere, and there is nothing upstream holding it back.
28
34
 
@@ -48,8 +54,6 @@ If the user prompt does NOT match re-validation, proceed with the full pipeline
48
54
 
49
55
  **Produces:** TASK_ID, BASE_BRANCH, EXECUTION_PLAN, DECISIONS_CONTEXT, FEATURE_KNOWLEDGE, PR_DESCRIPTION_GUIDANCE, ISSUE_NUMBER, EVIDENCE_POLICY, ISSUE_REQUIRED, APPLY_CONVENTIONS, REQUIRE_NON_AUTHOR_APPROVAL, PR_EXCEPTIONS, TEST_PLAN, EVIDENCE_FILE, PR_TEST_PLAN_BLOCK, REVIEW_PUBLICATION
50
56
 
51
- **Load Companion Skills** — Load via Skill tool: `devflow:test-driven-development`, `devflow:patterns`, `devflow:dependency-research`. If a skill fails to load, continue without it.
52
-
53
57
  Record the current branch name as `BASE_BRANCH` - this will be the PR target.
54
58
 
55
59
  **Docs root (D-DOCS-ROOT).** Every `.devflow/docs/` path this command reads or writes lives at the checkout's toplevel, never under the directory the session started in. Resolve `{worktree}` from the start directory — `WORKTREE_PATH` if provided, otherwise cwd (`devflow:worktree-support`) — by running
@@ -70,7 +74,7 @@ Accept the output only when it is exactly two lines: `exit=0` last and, before i
70
74
 
71
75
  Set `EVIDENCE_POLICY`, `ISSUE_REQUIRED`, `APPLY_CONVENTIONS` and `REQUIRE_NON_AUTHOR_APPROVAL` from the accepted line. Pass agents only the three mechanism inputs, never `EVIDENCE_POLICY`. Report `Evidence policy: {EVIDENCE_POLICY} (source: {SOURCE})`, plus any `WARN` tokens as advisory, once in the final report.
72
76
 
73
- **Plan Document Handling** (when $ARGUMENTS is a path ending in `.md`):
77
+ **Plan Document Handling** (when `COMMAND_INPUT` is a path ending in `.md`):
74
78
  1. Read the plan document from the path provided
75
79
  2. Extract from YAML frontmatter: `execution-strategy`, `context-risk`, `issue` number
76
80
  3. Extract from body: Subtask Breakdown, Implementation Plan, Patterns to Follow, Acceptance Criteria
@@ -81,23 +85,25 @@ Set `EVIDENCE_POLICY`, `ISSUE_REQUIRED`, `APPLY_CONVENTIONS` and `REQUIRE_NON_AU
81
85
 
82
86
  If `PR_DESCRIPTION_GUIDANCE` was not set above (non-plan paths: issue input or task description), set it to `(none)`.
83
87
 
88
+ **Empty input.** When `COMMAND_INPUT` is empty — a plan handoff arrives this way, with the plan already in the conversation — there is no argument to name the branch from, and the Git agent sees none of this conversation. Write the description yourself: one line, taken from the plan's title or, with no plan, from the conversation. Send it as the setup-task `TASK_DESCRIPTION` below.
89
+
84
90
  Spawn Git agent to set up task environment. The Git agent derives the branch name automatically from the issue or task description:
85
91
 
86
92
  ```
87
93
  Agent(subagent_type="Git"):
88
94
  "OPERATION: setup-task
89
95
  BASE_BRANCH: {current branch name}
90
- ISSUE_INPUT: {$ARGUMENTS verbatim, when it is a single whitespace-delimited token that does not end in .md; when it ends in .md, the plan frontmatter's issue value verbatim unless absent or pending — otherwise omit}
91
- TASK_DESCRIPTION: {$ARGUMENTS verbatim, when it is two or more whitespace-delimited tokens — otherwise omit}
96
+ ISSUE_INPUT: {COMMAND_INPUT verbatim, when it is a single whitespace-delimited token that does not end in .md; when it ends in .md, the plan frontmatter's issue value verbatim unless absent or pending — otherwise omit}
97
+ TASK_DESCRIPTION: {COMMAND_INPUT verbatim, when it is two or more whitespace-delimited tokens; when COMMAND_INPUT is empty, the one-line description you wrote above — otherwise omit}
92
98
  ISSUE_REQUIRED: {ISSUE_REQUIRED}
93
99
  APPLY_CONVENTIONS: {APPLY_CONVENTIONS}
94
- PLAN_ARTIFACT_PATH: {path to plan document if $ARGUMENTS ends in .md, otherwise (none)}
100
+ PLAN_ARTIFACT_PATH: {path to plan document if COMMAND_INPUT ends in .md, otherwise (none)}
95
101
  Derive branch name from issue or description, create feature branch, and fetch issue if specified.
96
102
  Return the branch setup summary."
97
103
  ```
98
104
 
99
105
  The issue token is forwarded **unclassified**, and the routing is decided by
100
- SHAPE alone — how many tokens `$ARGUMENTS` has, and whether it ends in `.md`.
106
+ SHAPE alone — how many tokens `COMMAND_INPUT` has, and whether it ends in `.md`.
101
107
 
102
108
  `setup-task` is the one step that has resolved a provider, and therefore the only
103
109
  one that knows what an issue reference looks like on this machine: `#123`,
@@ -158,7 +164,7 @@ Note: the section reaches a public PR body. The Code agent re-checks every line
158
164
 
159
165
  **Test plan.** Before any Code spawn, give the task a test plan in the evidence file `{worktree}/.devflow/docs/evidence-{branch_slug}.md` (`EVIDENCE_FILE`) — unlike the handoff file, it stays after the PR exists. It holds up to three sections, in this order and nothing else: `## Test Plan`; `## Evidence Exceptions`, a byte copy of `PR_EXCEPTIONS` present only while that is not `(none)`; and `## Claims`, always last, so every claim is appended at the end of the file. Create the file if absent; if it exists, replace its `## Test Plan` and `## Evidence Exceptions` sections and keep `## Claims` byte-identical.
160
166
 
161
- Write the `## Test Plan` section: when `$ARGUMENTS` is a plan document with a `## Test Plan` section, copy that section's lines verbatim; otherwise write one TP line per acceptance criterion the plan, the issue or the task text states, numbered from `TP-1`. Never invent a criterion, and word every scenario yourself in plain words: the lines reach the PR body, so a scenario holds no `#`, `@` or `/` — no issue reference, mention, closing keyword target or URL — and the files a TP covers go in its `files:` field. Each line follows the TP-line contract:
167
+ Write the `## Test Plan` section: when `COMMAND_INPUT` is a plan document with a `## Test Plan` section, copy that section's lines verbatim; otherwise write one TP line per acceptance criterion the plan, the issue or the task text states, numbered from `TP-1`. Never invent a criterion, and word every scenario yourself in plain words: the lines reach the PR body, so a scenario holds no `#`, `@` or `/` — no issue reference, mention, closing keyword target or URL — and the files a TP covers go in its `files:` field. Each line follows the TP-line contract:
162
168
 
163
169
  **Test-plan line (TP).** Write every test-plan entry as one line in exactly this shape. `TP_LINE_RE` in `pr-evidence.cjs` parses it and refuses any other line.
164
170
 
@@ -428,7 +434,7 @@ ISSUE_PR_LINK: {ISSUE_PR_LINK captured in Phase 1, or (none)}"
428
434
  After Code agent completes, spawn Validate agent to verify correctness:
429
435
 
430
436
  ```
431
- Agent(subagent_type="Validate", model="haiku"):
437
+ Agent(subagent_type="Validate"):
432
438
  "FILES_CHANGED: {list of files from Code agent output}
433
439
  VALIDATION_SCOPE: full
434
440
  Run build, typecheck, lint, test. Report pass/fail with failure details."
@@ -508,7 +514,7 @@ If Scrutinize agent returns BLOCKED, report to user and halt.
508
514
  If Scrutinize agent made code changes (status: FIXED), spawn Validate agent to verify:
509
515
 
510
516
  ```
511
- Agent(subagent_type="Validate", model="haiku"):
517
+ Agent(subagent_type="Validate"):
512
518
  "FILES_CHANGED: {files modified by Scrutinize agent}
513
519
  VALIDATION_SCOPE: changed-only
514
520
  Verify Scrutinize agent's fixes didn't break anything."
@@ -556,7 +562,7 @@ Validate alignment with request and plan. Report ALIGNED or MISALIGNED with deta
556
562
  ```
557
563
  - Spawn Validate agent to verify fix didn't break tests:
558
564
  ```
559
- Agent(subagent_type="Validate", model="haiku"):
565
+ Agent(subagent_type="Validate"):
560
566
  "FILES_CHANGED: {files modified by fix Code agent}
561
567
  VALIDATION_SCOPE: changed-only"
562
568
  ```
@@ -604,7 +610,7 @@ After every Test agent run — PASS or FAIL, first run or retry — append its T
604
610
  ```
605
611
  - Spawn Validate agent to verify fix didn't break tests:
606
612
  ```
607
- Agent(subagent_type="Validate", model="haiku"):
613
+ Agent(subagent_type="Validate"):
608
614
  "FILES_CHANGED: {files modified by fix Code agent}
609
615
  VALIDATION_SCOPE: changed-only"
610
616
  ```
@@ -740,8 +746,6 @@ DIRECTORIES: {list of primary directories touched by this workflow}
740
746
  FILES_CHANGED: {list of files changed}
741
747
  DECISIONS_CONTEXT: {DECISIONS_CONTEXT if available, else (none)}
742
748
 
743
- Load the devflow:feature-knowledge skill and follow its authoring process.
744
-
745
749
  Write the knowledge base to:
746
750
  {worktree}/.devflow/features/{slug}/KNOWLEDGE.md
747
751
 
@@ -18,13 +18,19 @@ The orchestrator only spawns agents and gates — all analytical work is done by
18
18
 
19
19
  ## Input
20
20
 
21
- `$ARGUMENTS` contains whatever follows `/plan`:
21
+ What follows `/plan` is bound once, here. Every later step names it `COMMAND_INPUT` and never restates it:
22
+
23
+ <command-input>
24
+ $ARGUMENTS
25
+ </command-input>
26
+
27
+ `COMMAND_INPUT` is one of:
22
28
  - Opens with a candidate issue reference → issue mode (one candidate = single-ref, more than one = multi-issue)
23
29
  - Path to existing `.md` file → **error**: "Use /implement with plan documents"
24
30
  - Other text → feature description
25
31
  - Empty → use conversation context
26
32
 
27
- **Issue-reference grammar (L1 — command layer, permissive and provider-blind):** scan `$ARGUMENTS` for candidate issue references — a `#`-prefixed token and a bare digit run are both candidates — and collect them in source order as the raw token list `ISSUE_REFS`. Forward that list to the Git agent **verbatim**: the command never renders, normalises, pads, strips or coerces a token, and never rules a candidate out. Under `github` a token matching `^#?[1-9][0-9]{0,8}$` **is** a reference and the Git agent renders it as `#{n}`.
33
+ **Issue-reference grammar (L1 — command layer, permissive and provider-blind):** scan `COMMAND_INPUT` for candidate issue references — a `#`-prefixed token and a bare digit run are both candidates — and collect them in source order as the raw token list `ISSUE_REFS`. Forward that list to the Git agent **verbatim**: the command never renders, normalises, pads, strips or coerces a token, and never rules a candidate out. Under `github` a token matching `^#?[1-9][0-9]{0,8}$` **is** a reference and the Git agent renders it as `#{n}`.
28
34
 
29
35
  **A token of any other shape is neither coerced nor dropped silently — and no producer-side grammar check rejects it before the fetch.** Adjudication belongs to the operation that runs, and each one answers in its own Output block: `fetch-issue` strips a leading `#` and takes the text branch, so a non-numeric token is used as a **search term** and the operation returns the first open match or nothing; `fetch-issues-batch` resolves each token to an issue number, drops the ones it cannot resolve, and names them in `NOT_FOUND ({refs})` beside the issues it did fetch. Read the outcome from the operation that ran — a token's shape is a verdict nowhere, and there is nothing upstream holding it back.
30
36
 
@@ -62,7 +68,7 @@ Explore the user's intent through focused Socratic questioning before spawning a
62
68
 
63
69
  **Step 0 — Fetch issue(s)** (issue mode only; skip for feature-description and empty modes):
64
70
 
65
- - **Single-ref** (one candidate ref in `$ARGUMENTS`):
71
+ - **Single-ref** (one candidate ref in `COMMAND_INPUT`):
66
72
 
67
73
  ```
68
74
  Agent(subagent_type="Git"):
@@ -106,8 +112,6 @@ If the user says "skip" or "just proceed" — skip remaining questions, present
106
112
  **Produces:** SKIM_CONTEXT, DECISIONS_CONTEXT, FEATURE_KNOWLEDGE
107
113
  **Requires:** CONFIRMED_SCOPE
108
114
 
109
- **Load Companion Skills** — Load via Skill tool: `devflow:test-driven-development`, `devflow:patterns`, `devflow:software-design`, `devflow:security`, `devflow:design-review`. If a skill fails to load, continue without it.
110
-
111
115
  Spawn Skim agent for codebase context:
112
116
 
113
117
  ```
@@ -212,7 +216,7 @@ Pass `FEATURE_KNOWLEDGE` alongside `DECISIONS_CONTEXT` to Explore and Design age
212
216
  **Produces:** EXPLORE_OUTPUTS
213
217
  **Requires:** SKIM_CONTEXT, DECISIONS_CONTEXT
214
218
 
215
- Spawn 4 Explore agents **in a single message**, each with Skim agent context, `DECISIONS_CONTEXT` (from Phase 2), and `FEATURE_KNOWLEDGE` (from Phase 2). Include instructions: "follow `devflow:apply-decisions` for DECISIONS_CONTEXT" and "The FEATURE_KNOWLEDGE is a baseline — VALIDATE, EXTEND, and CORRECT it, don't repeat it. Focus on areas the feature knowledge doesn't cover and changes since it was last updated."
219
+ Spawn 4 Explore agents **in a single message**, each with Skim agent context, `DECISIONS_CONTEXT` (from Phase 2), and `FEATURE_KNOWLEDGE` (from Phase 2). Include instructions: "follow `devflow:apply-decisions` for DECISIONS_CONTEXT" and "The FEATURE_KNOWLEDGE is a baseline — VALIDATE, EXTEND, and CORRECT it, don't repeat it. Focus on areas the feature knowledge doesn't cover and changes since it was last updated." Ask each agent for a final report of at most about 1,500 tokens: findings with file:line references, not file dumps.
216
220
 
217
221
  | Focus | Thoroughness | Find |
218
222
  |-------|-------------|------|
@@ -355,7 +359,7 @@ User can:
355
359
  **Produces:** IMPL_EXPLORE_OUTPUTS
356
360
  **Requires:** SKIM_CONTEXT, ACCEPTED_SCOPE
357
361
 
358
- Spawn 4 Explore agents **in a single message**, each with Skim agent context + accepted scope:
362
+ Spawn 4 Explore agents **in a single message**, each with Skim agent context + accepted scope. Ask each agent for a final report of at most about 1,500 tokens: findings with file:line references, not file dumps.
359
363
 
360
364
  | Focus | Thoroughness | Find |
361
365
  |-------|-------------|------|
@@ -384,7 +388,7 @@ Combine into: patterns to follow, integration points, reusable code, edge cases"
384
388
  **Produces:** PLAN_OUTPUTS
385
389
  **Requires:** IMPL_EXPLORATION_SYNTHESIS, GAP_SYNTHESIS, DECISIONS_CONTEXT
386
390
 
387
- Spawn 3 Plan agents **in a single message**, each with implementation exploration synthesis:
391
+ Spawn 3 Plan agents **in a single message**, each with implementation exploration synthesis. Ask each agent for a final report of at most about 1,500 tokens: the plan itself, not a restatement of the exploration.
388
392
 
389
393
  | Focus | Output |
390
394
  |-------|--------|
@@ -573,7 +577,7 @@ Spawn a Git agent with `OPERATION: ensure-traceable-issue`:
573
577
  ```
574
578
  Agent(subagent_type="Git"):
575
579
  "OPERATION: ensure-traceable-issue
576
- ISSUE_INPUT: {the raw candidate token from $ARGUMENTS if /plan was invoked with an issue reference, else omit}
580
+ ISSUE_INPUT: {the raw candidate token from COMMAND_INPUT if /plan was invoked with an issue reference, else omit}
577
581
  TASK_DESCRIPTION: {Gate 0 confirmed scope — one-line title}
578
582
  INITIAL_REQUEST: {the Gate 0 confirmed scope statement}
579
583
  REQUIREMENTS: {discovered requirements summary from Phase 6 gap synthesis}
@@ -17,13 +17,19 @@ Release the project using adaptive learned configuration. On first run, scans th
17
17
 
18
18
  ## Input
19
19
 
20
- `$ARGUMENTS` contains whatever follows `/release`:
20
+ What follows `/release` is bound once, here. Every later step names it `COMMAND_INPUT` and never restates it:
21
+
22
+ <command-input>
23
+ $ARGUMENTS
24
+ </command-input>
25
+
26
+ `COMMAND_INPUT` is one of:
21
27
  - Explicit version: `v1.2.3` or `1.2.3`
22
28
  - Bump type: `patch`, `minor`, `major`
23
29
  - Flag: `--dry-run`
24
30
  - Empty: interactive mode (will ask for version)
25
31
 
26
- Parse from $ARGUMENTS:
32
+ Parse from `COMMAND_INPUT`:
27
33
  - `VERSION`: explicit version string if present (strip leading `v`)
28
34
  - `BUMP_TYPE`: `patch | minor | major` if bump type provided
29
35
  - `DRY_RUN`: true if `--dry-run` present, false otherwise
@@ -48,7 +54,21 @@ Read `.release/RELEASE-FLOW.md`:
48
54
 
49
55
  **Produces:** DECISIONS_CONTEXT, FEATURE_KNOWLEDGE
50
56
 
51
- Read `.devflow/learning/index.md`. If the file is absent or empty, set `DECISIONS_CONTEXT` to `(none)`; otherwise use the file content as `DECISIONS_CONTEXT`.
57
+ 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`):
58
+
59
+ ```bash
60
+ git -C "{start}" rev-parse --path-format=absolute --show-toplevel --git-common-dir
61
+ ```
62
+
63
+ Line 1 is the checkout's toplevel, line 2 the repository's common git directory. A git older than 2.31 echoes `--path-format=absolute` back as a line of its own first. `{ledger}` is the first of these that applies:
64
+
65
+ 1. **The main worktree** — line 2 without its trailing `/.git`, when the output is exactly two lines each beginning with `/`, line 2 ends in `/.git`, and the directory left once it is removed is not your home directory and contains a `.devflow/` directory.
66
+ 2. **The toplevel** — line 1, or on an older git the line after the echoed flag.
67
+ 3. **The start directory itself** — when the command failed or printed no absolute toplevel (outside a git repository).
68
+
69
+ This is the rule the learning hooks apply (D-LEDGER-MAIN-WORKTREE, D-PROMPT-ROOT), so you read the index the Learning agent writes.
70
+
71
+ 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`.
52
72
 
53
73
  Load feature knowledge: Attempt to read `.devflow/features/index.md` (the regenerable cache). If absent or empty, glob `.devflow/features/*/KNOWLEDGE.md` and read each file's YAML frontmatter (`name`, `description`, `directories`) as the relevance surface. Pick release-relevant KBs by matching their documented area against the release context. For each selected KB, read the full `KNOWLEDGE.md` — trust current code over KB content on any mismatch. Concatenate under slug headers and set `FEATURE_KNOWLEDGE` (or `(none)` if no KBs exist or none are relevant). No `index.json`, no subprocess, no `.cjs` script.
54
74
 
@@ -16,7 +16,13 @@ Research a topic by spawning parallel Research agents across multiple research t
16
16
 
17
17
  ## Input
18
18
 
19
- `$ARGUMENTS` contains whatever follows `/research`:
19
+ What follows `/research` is bound once, here. Every later step names it `COMMAND_INPUT` and never restates it:
20
+
21
+ <command-input>
22
+ $ARGUMENTS
23
+ </command-input>
24
+
25
+ `COMMAND_INPUT` is one of:
20
26
  - Research question: "best caching strategies"
21
27
  - Comparison question: "compare React vs Svelte for our use case"
22
28
  - Empty: use conversation context
@@ -64,7 +70,7 @@ The index is one direct file read, written at render time by `render-decisions.c
64
70
 
65
71
  When `DECISIONS_CONTEXT` is not `(none)`, follow `devflow:apply-decisions` to scan the index, identify plausibly-relevant entries, Read full entry bodies on demand, and cite verbatim IDs in downstream agent prompts and reasoning.
66
72
 
67
- Use `DECISIONS_CONTEXT` locally when framing research — prior decisions and pitfalls suggest areas to investigate. Follow `devflow:apply-decisions` to Read full entry bodies on demand. Pass `DECISIONS_CONTEXT` to each Research agent in Phase 4 so they can cite relevant decisions in findings.
73
+ Use `DECISIONS_CONTEXT` locally when framing research — prior decisions and pitfalls suggest areas to investigate. Follow `devflow:apply-decisions` to Read full entry bodies on demand. Pass `DECISIONS_CONTEXT` to each Research agent in Phase 4 so their findings can account for relevant decisions.
68
74
 
69
75
  ### Load Feature Knowledge
70
76
 
@@ -183,7 +189,7 @@ If external research was skipped due to tool unavailability: inform user.
183
189
  1. If `codebase` type was not in RESEARCH_PLAN → skip
184
190
  2. Check if matching feature knowledge already exists by reading `{worktree}/.devflow/features/index.md` (or globbing frontmatter if absent). If covered → skip
185
191
  3. Use AskUserQuestion: "No feature knowledge exists for {researched area}. Create one?"
186
- 4. If user accepts: spawn `Agent(subagent_type="Knowledge")` with researched area context + worktree root, instructing it to load `devflow:feature-knowledge`, write `KNOWLEDGE.md`, and update `index.md` directly
192
+ 4. If user accepts: spawn `Agent(subagent_type="Knowledge")` with researched area context + worktree root, instructing it to write `KNOWLEDGE.md` and update `index.md` directly
187
193
  5. Set FEATURE_KNOWLEDGE_STATUS = created or skipped
188
194
 
189
195
  **Failure handling**: Non-blocking. If Knowledge agent fails, log and continue.
@@ -266,14 +266,14 @@ Wait for Triage agent to complete before proceeding. Parse verdict ledger from T
266
266
  - **ESCALATED**: Security issues requiring human escalation
267
267
  - **FIX_NOW**: Valid issues assigned to Code agents (with risk tier: Standard | Careful)
268
268
  - **FALSE_POSITIVE**: Issues the Review agent got wrong (with cited evidence)
269
- - **BY_DESIGN**: Intentional code (with ADR or code doc citation)
269
+ - **BY_DESIGN**: Intentional code (with a recorded decision, stated in words, or a code doc citation)
270
270
  - **FIX_SEPARATE**: Valid but out of blast-radius scope (must become manage-debt ticket)
271
271
  - **TECH_DEBT**: Architectural overhaul only — LAST RESORT
272
272
  - **DUPLICATE**: Collapsed duplicate issue — carries `duplicate_of: <primary-id>` referencing the non-DUPLICATE primary; inherits the primary's outcome
273
273
 
274
- Collect all decisions citations (ADR-NNN / PF-NNN) from Triage agent Reasoning columns.
274
+ 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.
275
275
 
276
- **Triage agent completeness assertion (avoids PF-002):** Verify the parsed ledger against ISSUES before proceeding:
276
+ **Triage agent completeness assertion:** Verify the parsed ledger against ISSUES before proceeding:
277
277
  1. Every issue `id` from ISSUES must appear in exactly one verdict bucket — none may vanish, none may appear in multiple buckets. DUPLICATE is a valid bucket; a valid DUPLICATE entry must name its `duplicate_of` primary (the `Duplicate Of` column of the ledger's DUPLICATE table) and that primary must be a non-DUPLICATE issue id. A missing `duplicate_of` or one that chains to another DUPLICATE is a **Triage agent failure** (retry-then-abort as below).
278
278
  2. If the Triage agent output is empty, contains a skill re-entrancy guard string (e.g., contains `already running`), or is missing any issue IDs from ISSUES: treat as a **Triage agent failure**:
279
279
  - Retry the Triage agent once with the same inputs.
@@ -361,7 +361,7 @@ If no fixes were made (CODE_AGENT_RESULTS contains 0 commits) → set VERIFICATI
361
361
  Otherwise, spawn Validate agent:
362
362
 
363
363
  ```
364
- Agent(subagent_type="Validate", model="haiku"):
364
+ Agent(subagent_type="Validate"):
365
365
  "FILES_CHANGED: {list of files from Code agent output}
366
366
  VALIDATION_SCOPE: full
367
367
  Run build, typecheck, lint, test. Report pass/fail with failure details."
@@ -487,7 +487,7 @@ Run this step only when `EVIDENCE_POLICY` is `required` and THREAD_MAP is non-em
487
487
 
488
488
  Prepare THREAD_MAP with verdicts from triage/code agent results:
489
489
  - For each `ext-{N}`: match to an issue verdict (FIXED, FALSE_POSITIVE, BY_DESIGN, ESCALATED) by `file:line` correlation
490
- - If the matched issue has verdict DUPLICATE, use the **primary's** verdict and verification status for the reply — do not expose DUPLICATE to the thread author (avoids PF-024; caller-side mapping — git.md contracts unchanged)
490
+ - If the matched issue has verdict DUPLICATE, use the **primary's** verdict and verification status for the reply — do not expose DUPLICATE to the thread author (caller-side mapping: the Git agent's verdict set has no DUPLICATE, so its contract stays unchanged)
491
491
  - Include `commit_sha` from Code agent results for FIXED verdicts
492
492
  - If `fork_no_push` is set: drop FIXED entries from THREAD_MAP — their commits never reached the PR — and record each as `DEGRADED` in `## Third-Party Threads`
493
493
  - Unmatched threads: ESCALATED (human review)
@@ -665,8 +665,6 @@ DIRECTORIES: {list of primary directories touched by this workflow}
665
665
  FILES_CHANGED: {list of files changed}
666
666
  DECISIONS_CONTEXT: {DECISIONS_CONTEXT if available, else (none)}
667
667
 
668
- Load the devflow:feature-knowledge skill and follow its authoring process.
669
-
670
668
  Write the knowledge base to:
671
669
  {worktree}/.devflow/features/{slug}/KNOWLEDGE.md
672
670
 
@@ -793,8 +791,7 @@ Written in Phase 5 (Collect Results) to `{TARGET_DIR}/resolution-summary.md`:
793
791
 
794
792
  ## Decisions Citations
795
793
 
796
- - applies ADR-{NNN} — {batch-id}, {issue-id}
797
- - avoids PF-{NNN} — {batch-id}, {issue-id}
794
+ - {decision applied or pitfall avoided, stated in words — never its ID} — {batch-id}, {issue-id}
798
795
 
799
796
  (Omit section if no citations were made)
800
797
 
@@ -832,9 +829,9 @@ Final gate: PASS | FAILED after {n} attempts
832
829
  | {description} | {file}:{line} | {why} |
833
830
 
834
831
  ## By Design
835
- | Issue | File:Line | Rationale (ADR/doc) |
836
- |-------|-----------|---------------------|
837
- | {description} | {file}:{line} | {applies ADR-NNN or code comment} |
832
+ | Issue | File:Line | Rationale (decision/doc) |
833
+ |-------|-----------|--------------------------|
834
+ | {description} | {file}:{line} | {the decision, in words, or code comment} |
838
835
 
839
836
  ## Fix Separately
840
837
  | Issue | File:Line | Reason | Tracked |
@@ -225,8 +225,6 @@ DIRECTORIES: {list of primary directories touched by this workflow}
225
225
  FILES_CHANGED: {list of files changed}
226
226
  DECISIONS_CONTEXT: {DECISIONS_CONTEXT if available, else (none)}
227
227
 
228
- Load the devflow:feature-knowledge skill and follow its authoring process.
229
-
230
228
  Write the knowledge base to:
231
229
  {worktree}/.devflow/features/{slug}/KNOWLEDGE.md
232
230
 
@@ -4,8 +4,8 @@
4
4
  * Pure module — zero I/O. All functions take content strings and return
5
5
  * new content strings; callers own file reads and writes.
6
6
  *
7
- * applies ADR-013: pure core-layer module, no Claude Code adapter concerns.
8
- * avoids PF-014: no process.exit(); all fallible paths return Result.
7
+ * Pure core-layer module, no Claude Code adapter concerns.
8
+ * No process.exit(); all fallible paths return Result.
9
9
  *
10
10
  * Regex scoping guarantee: ALL operations are confined to the FIRST `---…---`
11
11
  * block. Model/effort lines in the document body are never touched.
@@ -96,6 +96,31 @@ export function readFrontmatterModel(content) {
96
96
  const m = MODEL_RE.exec(parts.value.fmBody);
97
97
  return Ok(m ? m[1] : '');
98
98
  }
99
+ // ---------------------------------------------------------------------------
100
+ // readFrontmatterEffort
101
+ // ---------------------------------------------------------------------------
102
+ /**
103
+ * Read the `effort:` value from the first frontmatter block.
104
+ *
105
+ * D-SHIPPED-EFFORT: an agent's shipped effort is part of its shipped default,
106
+ * the same as its model, so the reader that answers "what did devflow ship?"
107
+ * must see both. This is the effort twin of readFrontmatterModel and has the
108
+ * same contract: it reads only the leading frontmatter block (an `effort:`
109
+ * line in the body is ignored), returns Ok('') when no `effort:` line exists,
110
+ * and returns an error for missing or unterminated frontmatter.
111
+ *
112
+ * The value is returned as written. Whether it is a valid effort level is the
113
+ * caller's decision (loadShippedAgentDefaults owns that check against
114
+ * EFFORT_LEVELS), so a typo in a shipped file is reported rather than hidden here.
115
+ */
116
+ export function readFrontmatterEffort(content) {
117
+ const parts = parseFrontmatter(content);
118
+ if (!parts.ok)
119
+ return Err(parts.error);
120
+ const EFFORT_RE = /^effort:[ \t]*(.*?)[ \t]*$/m;
121
+ const m = EFFORT_RE.exec(parts.value.fmBody);
122
+ return Ok(m ? m[1] : '');
123
+ }
99
124
  /**
100
125
  * Rewrite the `model:` and optionally `effort:` lines in the first
101
126
  * frontmatter block of `content`.
@@ -156,7 +181,7 @@ export function rewriteAgentFrontmatter(content, opts) {
156
181
  if (currentEffort !== opts.effort) {
157
182
  // Use a replacement function — NOT a string — so that $&, $`, $',
158
183
  // and $1 in opts.effort are written verbatim rather than expanded as
159
- // replacement patterns (avoids PF-018).
184
+ // replacement patterns.
160
185
  newBody = newBody.replace(EFFORT_RE, () => `effort: ${opts.effort}`);
161
186
  }
162
187
  }