devflow-kit 3.5.0 → 3.6.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 (107) hide show
  1. package/CHANGELOG.md +98 -0
  2. package/README.md +4 -4
  3. package/dist/agents/{diagnose.md → debug.md} +4 -4
  4. package/dist/agents/{code-fix.md → fix.md} +2 -2
  5. package/dist/agents/{scrutinize.md → harden.md} +6 -6
  6. package/dist/agents/{code-edit.md → refactor.md} +3 -3
  7. package/dist/cli/agents-view/render.js +1 -1
  8. package/dist/cli/commands/init.js +3 -3
  9. package/dist/cli/commands/learning.js +12 -12
  10. package/dist/cli/commands/legacy-hooks.js +1 -1
  11. package/dist/cli/commands/uninstall.js +111 -5
  12. package/dist/commands/bug-analysis.md +19 -15
  13. package/dist/commands/code-review.md +13 -22
  14. package/dist/commands/debug.md +15 -15
  15. package/dist/commands/dynamic-build.md +51 -55
  16. package/dist/commands/dynamic-plan.md +11 -9
  17. package/dist/commands/dynamic-profile.md +7 -5
  18. package/dist/commands/dynamic-tickets.md +11 -9
  19. package/dist/commands/explore.md +13 -13
  20. package/dist/commands/implement.md +58 -127
  21. package/dist/commands/plan.md +19 -41
  22. package/dist/commands/release.md +9 -5
  23. package/dist/commands/research.md +12 -8
  24. package/dist/commands/resolve.md +42 -86
  25. package/dist/commands/self-review.md +42 -42
  26. package/dist/core/agent-models.js +47 -11
  27. package/dist/core/{learning-tuning-config.js → curate-tuning-config.js} +14 -14
  28. package/dist/core/learning-queue-cleanup.js +1 -1
  29. package/dist/core/migrations.js +63 -44
  30. package/dist/core/plugins.js +14 -12
  31. package/dist/core/project-paths.js +3 -3
  32. package/dist/hud/codex-usage.js +247 -0
  33. package/dist/hud/components/codex-quota.js +37 -0
  34. package/dist/hud/components/usage-quota.js +1 -1
  35. package/dist/hud/config.js +1 -0
  36. package/dist/hud/index.js +16 -3
  37. package/dist/hud/render.js +3 -1
  38. package/dist/learning-off/agents/{diagnose.md → debug.md} +4 -4
  39. package/dist/learning-off/agents/{code-fix.md → fix.md} +2 -2
  40. package/dist/learning-off/agents/{scrutinize.md → harden.md} +6 -6
  41. package/dist/learning-off/agents/{code-edit.md → refactor.md} +3 -3
  42. package/dist/learning-off/commands/bug-analysis.md +9 -9
  43. package/dist/learning-off/commands/code-review.md +2 -15
  44. package/dist/learning-off/commands/debug.md +4 -8
  45. package/dist/learning-off/commands/dynamic-build.md +45 -51
  46. package/dist/learning-off/commands/dynamic-plan.md +5 -5
  47. package/dist/learning-off/commands/dynamic-profile.md +1 -1
  48. package/dist/learning-off/commands/dynamic-tickets.md +5 -5
  49. package/dist/learning-off/commands/explore.md +2 -6
  50. package/dist/learning-off/commands/implement.md +46 -119
  51. package/dist/learning-off/commands/plan.md +8 -33
  52. package/dist/learning-off/commands/release.md +4 -2
  53. package/dist/learning-off/commands/research.md +2 -2
  54. package/dist/learning-off/commands/resolve.md +31 -79
  55. package/dist/learning-off/commands/self-review.md +30 -34
  56. package/dist/skills/git/references/pr/check-merge-readiness.md +2 -0
  57. package/dist/skills/git/references/pr/update-pr-evidence.md +4 -6
  58. package/dist/targets/claude-code/installer.js +117 -84
  59. package/dist/targets/claude-code/tracker-servers.js +1 -1
  60. package/package.json +1 -1
  61. package/src/assets/agents/_partials/_code.mds +2 -2
  62. package/src/assets/agents/code.mds +2 -2
  63. package/src/assets/agents/{learning.md → curate.md} +4 -4
  64. package/src/assets/agents/{diagnose.mds → debug.mds} +4 -4
  65. package/src/assets/agents/evaluate.md +4 -4
  66. package/src/assets/agents/{code-fix.mds → fix.mds} +5 -5
  67. package/src/assets/agents/{scrutinize.mds → harden.mds} +6 -6
  68. package/src/assets/agents/{simplify.md → polish.md} +4 -4
  69. package/src/assets/agents/{code-edit.mds → refactor.mds} +6 -6
  70. package/src/assets/agents/test.md +2 -2
  71. package/src/assets/commands/_partials/_compliance.mds +1 -1
  72. package/src/assets/commands/_partials/_decisions.mds +26 -6
  73. package/src/assets/commands/_partials/_engine.mds +15 -15
  74. package/src/assets/commands/_partials/_evidence_policy.mds +0 -17
  75. package/src/assets/commands/_partials/_knowledge.mds +14 -9
  76. package/src/assets/commands/_partials/_preamble.mds +4 -2
  77. package/src/assets/commands/_partials/_roster.mds +4 -4
  78. package/src/assets/commands/bug-analysis.mds +7 -7
  79. package/src/assets/commands/code-review.mds +1 -14
  80. package/src/assets/commands/debug.mds +2 -2
  81. package/src/assets/commands/dynamic-build.mds +26 -32
  82. package/src/assets/commands/implement.mds +45 -102
  83. package/src/assets/commands/plan.mds +7 -37
  84. package/src/assets/commands/release.mds +5 -1
  85. package/src/assets/commands/resolve.mds +28 -76
  86. package/src/assets/commands/self-review.mds +27 -27
  87. package/src/assets/mds/git/_pr.mds +6 -6
  88. package/src/assets/scripts/hooks/assets/orchestrator-charter.md +4 -3
  89. package/src/assets/scripts/hooks/capture-prompt +1 -1
  90. package/src/assets/scripts/hooks/capture-question +1 -1
  91. package/src/assets/scripts/hooks/capture-turn +1 -1
  92. package/src/assets/scripts/hooks/json-helper.cjs +2 -2
  93. package/src/assets/scripts/hooks/lib/learning-store.cjs +1 -1
  94. package/src/assets/scripts/hooks/lib/project-paths.cjs +4 -4
  95. package/src/assets/scripts/hooks/preamble +1 -1
  96. package/src/assets/scripts/hooks/session-start-context +58 -45
  97. package/src/assets/scripts/verify-evidence.cjs +726 -9
  98. package/src/assets/skills/agent-references/SKILL.md +9 -5
  99. package/src/assets/skills/agent-references/references/commands/implement-evidence-asks.md +35 -0
  100. package/src/assets/skills/agent-references/references/commands/implement-revalidate.md +15 -0
  101. package/src/assets/skills/agent-references/references/synthesize/bug-analysis.md +1 -1
  102. package/src/assets/skills/apply-decisions/SKILL.md +6 -4
  103. package/src/assets/skills/docs-framework/SKILL.md +3 -3
  104. package/src/assets/skills/qa/SKILL.md +1 -1
  105. package/src/assets/skills/quality-gates/SKILL.md +7 -7
  106. package/src/assets/skills/quality-gates/references/report-template.md +7 -7
  107. /package/src/assets/skills/agent-references/references/{learning → curate}/maintain.md +0 -0
package/CHANGELOG.md CHANGED
@@ -5,6 +5,103 @@ All notable changes to Devflow will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [3.6.0] - 2026-10-14
9
+
10
+ ### Upgrade notes — Agent rename (6 agents)
11
+
12
+ This change releases as a minor version (3.6.0). It renames six agents, and a prompt that names
13
+ an old agent does not work. Read the steps below that you must do by hand.
14
+
15
+ Six agents have new names that state their job ([#466](https://github.com/dean0x/devflow/issues/466)).
16
+ The agent `code` keeps its name. The learning feature keeps its names too: `devflow learning`,
17
+ `features.learning`, `.devflow/learning/` and the learning ops do not change.
18
+
19
+ | Old slug | New slug | Old `name:` | New `name:` |
20
+ |--------------|------------|--------------|-------------|
21
+ | `code-fix` | `fix` | `Code-fix` | `Fix` |
22
+ | `code-edit` | `refactor` | `Code-edit` | `Refactor` |
23
+ | `scrutinize` | `harden` | `Scrutinize` | `Harden` |
24
+ | `simplify` | `polish` | `Simplify` | `Polish` |
25
+ | `diagnose` | `debug` | `Diagnose` | `Debug` |
26
+ | `learning` | `curate` | `Learning` | `Curate` |
27
+
28
+ The `/debug` command does not change. `Debug` is the agent that `/bug-analysis` spawns.
29
+ Use `Refactor` for a given mechanical change, such as "rename X to Y everywhere".
30
+ Use `Polish` for a judgment pass that makes code cleaner and keeps its behaviour.
31
+
32
+ **What devflow migrates automatically:**
33
+ - Keys in `~/.devflow/agent-models.json`. The one-time migration `canonicalise-agent-keys-v2`
34
+ runs on the first `devflow init` after this upgrade. Each read of the file also maps an old key
35
+ to its new slug. If the old key and the new key both exist, the new key wins.
36
+ `devflow agents --set <old slug>` writes the new slug and tells you.
37
+ - The session-start hook reads `agents.curate.model`, then an older `agents.learning.model`, and
38
+ spawns `Curate`. `devflow init` updates the hook.
39
+ - `token-audit` counts old transcripts under the new names, so a past `Code-fix` spawn counts as
40
+ `Fix`. Its JSON report key `codeFixByOperation` is now `fixByOperation`.
41
+
42
+ **What `devflow init` and `devflow uninstall` do to agent files:**
43
+ - A full `devflow init` removes the six old files from `~/.claude/agents/devflow/` and installs
44
+ the new ones. It removes every other file in that folder that devflow does not own.
45
+ - A partial `devflow init --plugin=<name>` and a selective `devflow uninstall --plugin=<name>`
46
+ run the orphan sweep. The sweep deletes every `.md` file in `~/.claude/agents/devflow/` whose
47
+ name is not a devflow agent. This includes the six old files.
48
+ - Do not keep your own agent files in `~/.claude/agents/devflow/`, because devflow deletes them.
49
+ A file of your own directly in `~/.claude/agents/` is never touched. This is also true when it
50
+ has the name of an old devflow agent, for example `~/.claude/agents/simplify.md`.
51
+
52
+ **Partial install and partial uninstall on a 3.5.0 install:**
53
+ - The commands of the plugins that stay installed name the old agents until something rewrites
54
+ them. The sweep removes the old agent files, and the new agent files are not on disk until
55
+ something writes them. For this reason both commands now repair the plugins that stay installed.
56
+ - `devflow init --plugin=<name>`: the sweep can delete an old agent file. If it does, the install
57
+ writes the commands and the agents of every plugin in `~/.devflow/manifest.json`. It does not
58
+ write only the plugin you name. If the sweep deletes nothing, the install writes only the plugin
59
+ you name, as before.
60
+ - `devflow uninstall --plugin=<name>`: the sweep can delete an old agent file. If it does, the
61
+ uninstall writes the current commands and agents of the plugins that stay installed. It also
62
+ prints a note. It does not update the hooks, the scripts or `settings.json`. Run a full
63
+ `devflow init` to update them. Until you do, the hook from 3.5.0 can name an agent that no
64
+ longer exists.
65
+ - If there is no readable `~/.devflow/manifest.json`, or the manifest lists no plugin that Devflow
66
+ knows, the uninstall writes nothing. It prints a warning that tells you to run `devflow init`.
67
+ - If the install is a legacy project-local install (`<repo>/.claude`), the uninstall writes
68
+ nothing. It prints a warning. The warning tells you to remove that install in full with
69
+ `devflow uninstall --scope local`.
70
+ - If the write fails, the rewrite stops at the first file that fails. The files that it wrote
71
+ before the failure stay written. The uninstall still finishes and prints a warning that tells
72
+ you to run `devflow init`.
73
+
74
+ **What you must migrate by hand:**
75
+ - Your own prompts, commands, agents or `CLAUDE.md` that name an old agent, for example
76
+ `subagent_type: "Simplify"` or `subagent_type: "Code-edit"`. Devflow cannot edit files it does
77
+ not own. Change them to the new name, for example `subagent_type: "Polish"`.
78
+ - Open Claude Code sessions. Restart each one after `devflow init`. An open session loaded its
79
+ agent types when it started, so it does not know `Fix`, `Refactor`, `Harden`, `Polish`, `Debug`
80
+ or `Curate`. `devflow init` also removes the files of the old agents. The orchestrator charter
81
+ of an open session still names `Code-edit`.
82
+
83
+ **Downgrade warning:** if you downgrade to 3.5.0, it does not know the new keys. Your per-agent
84
+ model overrides that you saved as `fix`, `refactor`, `harden`, `polish`, `debug` or `curate` do
85
+ not apply, and 3.5.0 gives no message. Check them with `devflow agents --list`.
86
+
87
+ ### Added
88
+
89
+ - **The HUD shows your Codex usage limits.** A new `codexQuota` segment sits on line 2 next to the Claude quota, for example `Codex 5h ███░░░░░ 40% (1h 2m) · 7d █░░░░░░░ 12% (3d 4h)`. It reads the newest rate-limit record that Codex writes to `~/.codex/sessions`, so it opens no credential file and makes no network call. A window is identified by its length, so a weekly-only plan and a 5h + 7d plan both label correctly. A window past its reset time shows 0%, and a red `limited` marker shows while Codex reports a reached limit. The segment is hidden when there is no recent Codex session, so users without Codex see no change.
90
+
91
+ ### Changed
92
+
93
+ - **`/plan` bounds Revise at 2 rounds** ([#455](https://github.com/dean0x/devflow/issues/455)). Each revision spawns five agents (Plan ×3, Synthesize, Design). After the second revision, Gate 2 offers Accept, Cancel or "Restart /plan with these constraints". The first-pass fan-out does not change.
94
+ - **The PR evidence refresh and the merge-readiness check run as a script, not as a Git agent spawn** ([#455](https://github.com/dean0x/devflow/issues/455)). `/implement`, `/resolve` and `/dynamic-build` run `verify-evidence.cjs publish` from the main session, and `/resolve` runs `verify-evidence.cjs readiness`. The `update-pr-evidence` and `check-merge-readiness` operations stay defined and run the same script. The refresh never blocks, and the readiness check only reports.
95
+ - **Agents get a scoped slice of the decisions index** ([#454](https://github.com/dean0x/devflow/issues/454)). On a direct delegation the main session passes only the index lines that match the agent's task, a `(slice: N of M entries — full index: <path>)` marker and the index footer. Sibling agents over one diff share one slice. When the main session is not sure, it includes the entry.
96
+ - **Command bodies are smaller and have size ceilings** ([#456](https://github.com/dean0x/devflow/issues/456)). Rare `/implement` branches (the ticket-link ask, the missing-test-plan ask, the evidence exception and the re-validation path) move to reference files that the command reads by explicit path. `/implement`, `/resolve`, `/plan` and `/code-review` are shorter. A test holds a size ceiling for each of the 14 compiled commands, learning-on and learning-off.
97
+
98
+ ### Fixed
99
+
100
+ - **`/release` no longer folds the `Exempt (not attested)` line into the last traceability bullet.** The `## Traceability exceptions` block put that line directly under the last `-` bullet, so Markdown rendered it inside that bullet (seen in the v3.5.0 release notes). The template now holds a blank line between them, and the command states the rule so a composed block always carries it.
101
+ - **The HUD status line exits promptly.** The 2-second overall timeout timer is now cleared when a render finishes, so each status-line render takes about 0.3 s instead of about 2.1 s. A render that times out still prints nothing.
102
+
103
+ ---
104
+
8
105
  ## [3.5.0] - 2026-10-12
9
106
 
10
107
  ### Added
@@ -1577,6 +1674,7 @@ devflow init
1577
1674
  ---
1578
1675
 
1579
1676
  [Unreleased]: https://github.com/dean0x/devflow/compare/v2.0.0...HEAD
1677
+ [3.6.0]: https://github.com/dean0x/devflow/compare/v3.5.0...v3.6.0
1580
1678
  [3.5.0]: https://github.com/dean0x/devflow/compare/v3.4.0...v3.5.0
1581
1679
  [3.4.0]: https://github.com/dean0x/devflow/compare/v3.3.0...v3.4.0
1582
1680
  [3.3.0]: https://github.com/dean0x/devflow/compare/v3.2.0...v3.3.0
package/README.md CHANGED
@@ -30,7 +30,7 @@ you: /implement (hand it the plan)
30
30
 
31
31
  Git branch feat/42-rate-limit-upload
32
32
  Code implements the plan — your learned decisions, pitfalls, and feature knowledge preloaded
33
- Simplify · Scrutinize cleanup pass, then 9-pillar quality gate
33
+ Polish · Harden cleanup pass, then 9-pillar quality gate
34
34
  Evaluate implementation matches the original request ✓
35
35
  Validate build ✓ typecheck ✓ lint ✓ tests ✓
36
36
  Test 5/5 QA scenarios pass
@@ -76,11 +76,11 @@ This is the **orchestrated flow** — you stay in the loop between every step. W
76
76
 
77
77
  **Your issue tracker, not just GitHub.** Pick the tracker your team actually uses — GitHub, Jira, or Linear — at `devflow init`, with `devflow init --tracker <id>`, or later with `devflow tracker --set <id>`; that sets your machine's default. A repository can select its own in `.devflow/project.json`, and devflow follows it there automatically — one machine can work on a Jira repository and a GitHub one side by side. Every install carries every provider's mechanics (48 generated reference files, the tool-call contract among them) and the background agent, because pull requests stay on GitHub whatever your tracker and any repository may pick any provider. On a non-GitHub tracker that agent learns your conventions once per provider (project key, issue types, required fields, workflow transitions, how a reference renders) and writes them to `~/.devflow/tracker/{provider}.md`, so traceability speaks your tracker's vocabulary instead of assuming `#123`. Each provider's conventions are learned from the first repository that uses it. Those files are yours: hand-editable, kept across an uninstall, and refused rather than silently trusted if one no longer names its own provider. The Git and Tracker agents reach a tracker only through the servers you allow (Atlassian, Jira and Linear by default); `devflow tracker --servers` names others. **GitHub is the default** and needs no configuration: no background run and no conventions file.
78
78
 
79
- **Full lifecycle.** Beyond the core flow: `/explore` maps a codebase into knowledge bases, `/research` runs multi-type research with trust-aware synthesis, `/debug` investigates with competing hypotheses in parallel, `/bug-analysis` hunts bugs before review, `/self-review` runs Simplify + Scrutinize quality passes, and `/release` ships with learned configuration.
79
+ **Full lifecycle.** Beyond the core flow: `/explore` maps a codebase into knowledge bases, `/research` runs multi-type research with trust-aware synthesis, `/debug` investigates with competing hypotheses in parallel, `/bug-analysis` hunts bugs before review, `/self-review` runs Polish + Harden quality passes, and `/release` ships with learned configuration.
80
80
 
81
81
  **Everything is composable.** 21 plugins (12 core + 9 optional). Install only what you need.
82
82
 
83
- **HUD.** A persistent status line updates on every prompt — project, branch, diff stats, context usage, model, cost with weekly/monthly totals, quota reset timers, and configuration counts at a glance.
83
+ **HUD.** A persistent status line updates on every prompt — project, branch, diff stats, context usage, model, cost with weekly/monthly totals, quota reset timers (Claude and Codex), and configuration counts at a glance.
84
84
 
85
85
  ```
86
86
  ~/devflow · main · +2 -1 · v2.0.0+3
@@ -166,7 +166,7 @@ To keep the knowledge bases or conventions local, add `.devflow/features/` or `.
166
166
  | `/research` | Multi-type research with trust-aware synthesis |
167
167
  | `/plan` | Full design pipeline: explore → gap analysis → design → PR-ready plan document |
168
168
  | `/implement` | Execute plan: accepts plan documents from `/plan`, issues, or task descriptions → PR |
169
- | `/self-review` | Simplify + Scrutinize quality pass |
169
+ | `/self-review` | Polish + Harden quality pass |
170
170
  | `/code-review` | Multi-perspective parallel code review |
171
171
  | `/resolve` | Validate and fix all review issues |
172
172
  | `/debug` | Competing hypothesis investigation |
@@ -1,6 +1,6 @@
1
1
  ---
2
- name: Diagnose
3
- description: Proactive bug finding agent with static+semantic analysis. Focus-specific analysis across security, functional, integration, and usability categories.
2
+ name: Debug
3
+ description: Proactive bug finding agent with static+semantic analysis. Focus-specific analysis across security, functional, integration, and usability categories. The /bug-analysis command spawns it. It is not the /debug command.
4
4
  model: opus
5
5
  effort: medium
6
6
  skills:
@@ -16,7 +16,7 @@ tools:
16
16
  - Skill
17
17
  ---
18
18
 
19
- # Diagnose Agent
19
+ # Debug Agent
20
20
 
21
21
  You are a proactive bug finding agent. Your focus area is specified in the prompt. You hunt for real bugs — not style issues — using a 5-step methodology that combines static analysis findings with semantic code understanding.
22
22
 
@@ -117,7 +117,7 @@ Assign to each verified finding:
117
117
 
118
118
  **Category mapping** (for `/resolve` compatibility — severity-based approximation):
119
119
 
120
- > **Trade-off**: The Review agent uses location-based categories (lines you added / lines you touched / unchanged lines). The Diagnose agent focuses on diff-changed code and lacks per-line location context, so it approximates using severity as a proxy. This means a LOW-severity bug in newly-added code is placed in Pre-existing — not because it predates the change, but to signal lower urgency. The resolve pipeline should treat Pre-existing findings from the Diagnose agent as low-urgency, not as assertions about code origin.
120
+ > **Trade-off**: The Review agent uses location-based categories (lines you added / lines you touched / unchanged lines). The Debug agent focuses on diff-changed code and lacks per-line location context, so it approximates using severity as a proxy. This means a LOW-severity bug in newly-added code is placed in Pre-existing — not because it predates the change, but to signal lower urgency. The resolve pipeline should treat Pre-existing findings from the Debug agent as low-urgency, not as assertions about code origin.
121
121
 
122
122
  - CRITICAL / HIGH severity → `## Issues in Your Changes (BLOCKING)` — must fix before merge
123
123
  - MEDIUM severity → `## Issues in Code You Touched (Should Fix)` — fix while here
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: Code-fix
2
+ name: Fix
3
3
  description: Autonomous gate-failure repair on feature branch. Fixes the listed validation, alignment, QA or CI failures, verifies, and commits.
4
4
  model: sonnet
5
5
  effort: high
@@ -28,7 +28,7 @@ disallowedTools:
28
28
  - DesignSync
29
29
  ---
30
30
 
31
- # Code-fix Agent
31
+ # Fix Agent
32
32
 
33
33
  You are an autonomous repair specialist working on a feature branch. A quality gate (validation, alignment, QA or CI) reported failures. You fix exactly the failures you are given, verify the fix and commit it. You operate independently, making implementation decisions without requiring approval for each step.
34
34
 
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: Scrutinize
2
+ name: Harden
3
3
  description: Self-review agent that evaluates and fixes implementation issues using 9-pillar framework. Runs in fresh context after Code agent completes.
4
4
  model: opus
5
5
  effort: medium
@@ -31,9 +31,9 @@ disallowedTools:
31
31
  - mcp__*
32
32
  ---
33
33
 
34
- # Scrutinize Agent
34
+ # Harden Agent
35
35
 
36
- You are a meticulous self-review specialist. You evaluate implementations against the 9-pillar quality framework and fix the issues you find. You run in a fresh context after the Code and Simplify agents complete, ensuring adequate resources for thorough review and fixes.
36
+ You are a meticulous self-review specialist. You evaluate implementations against the 9-pillar quality framework and fix the issues you find. You run in a fresh context after the Code and Polish agents complete, ensuring adequate resources for thorough review and fixes.
37
37
 
38
38
  ## Input Context
39
39
 
@@ -59,7 +59,7 @@ Follow the `devflow:apply-decisions` skill to scan the index, Read full bodies o
59
59
 
60
60
  4. **Evaluate P1 pillars** (Complexity, Error Handling, Tests): These SHOULD pass. Fix all issues found.
61
61
 
62
- 5. **Evaluate P2** (Documentation): Fix if straightforward. Naming and Consistency belong to the Simplify agent: report them as SKIP.
62
+ 5. **Evaluate P2** (Documentation): Fix if straightforward. Naming and Consistency belong to the Polish agent: report them as SKIP.
63
63
 
64
64
  6. **Commit fixes**: If any changes were made, create a commit with message "fix: address self-review issues".
65
65
 
@@ -97,8 +97,8 @@ Return structured completion status:
97
97
  - Tests: PASS | FIXED (description)
98
98
 
99
99
  ### P2 Pillars
100
- - Naming: SKIP (Simplify agent)
101
- - Consistency: SKIP (Simplify agent)
100
+ - Naming: SKIP (Polish agent)
101
+ - Consistency: SKIP (Polish agent)
102
102
  - Documentation: PASS | FIXED (description)
103
103
 
104
104
  ### Files Modified
@@ -1,6 +1,6 @@
1
1
  ---
2
- name: Code-edit
3
- description: Autonomous mechanical edit on feature branch. Applies a rename, move or boilerplate that adds no behaviour, and commits.
2
+ name: Refactor
3
+ description: Autonomous mechanical edit on feature branch. Makes a given rename, move or boilerplate change and commits. For judgment-based cleanup use Polish.
4
4
  model: sonnet
5
5
  effort: high
6
6
  skills:
@@ -27,7 +27,7 @@ disallowedTools:
27
27
  - DesignSync
28
28
  ---
29
29
 
30
- # Code-edit Agent
30
+ # Refactor Agent
31
31
 
32
32
  You are an autonomous editing specialist working on a feature branch. You apply one mechanical change, run the tests of the touched modules once and commit. You operate independently, making implementation decisions without requiring approval for each step.
33
33
 
@@ -26,7 +26,7 @@
26
26
  * fits whole inside the cursor's "‹ … ›" wrapper with the dirty marker
27
27
  * ("‹ default (medium) ● ›", 22) — the shipped effort (D-SHIPPED-EFFORT) and the
28
28
  * unsaved mark are never clipped on the cursor row. The agent names the registry
29
- * holds are at most 10 characters ("Scrutinize"); longer orphan keys are
29
+ * holds are at most 10 characters ("Synthesize"); longer orphan keys are
30
30
  * truncated by truncateVisible.
31
31
  *
32
32
  * MODEL has no such slack for a worker row, whose shipped default is a full
@@ -784,7 +784,7 @@ export const initCommand = new Command('init')
784
784
  'devflow-explore': 'codebase exploration + knowledge bases',
785
785
  'devflow-research': 'multi-type research with synthesis',
786
786
  'devflow-release': 'adaptive release with learned config',
787
- 'devflow-self-review': 'Simplify agent + Scrutinize agent',
787
+ 'devflow-self-review': 'Polish agent + Harden agent',
788
788
  'devflow-bug-analysis': 'proactive bug finding, post-pipeline',
789
789
  'devflow-typescript': 'TypeScript patterns',
790
790
  'devflow-react': 'React patterns',
@@ -1967,7 +1967,7 @@ export const initCommand = new Command('init')
1967
1967
  content = addCaptureHooks(cleanedForCapture, devflowDir);
1968
1968
  // Memory hooks — Stop (memory-worker), SessionStart (session-start-memory),
1969
1969
  // PreCompact — through the same transform `devflow memory --enable/--disable`
1970
- // uses (D-FEATURES-NARROW-ONLY). Learning agent (spawned via
1970
+ // uses (D-FEATURES-NARROW-ONLY). Curate agent (spawned via
1971
1971
  // session-start-context directive) handles decision/pitfall detection.
1972
1972
  // Knowledge is handled in-command via write-through (knowledge_writeback MDS partial).
1973
1973
  content = convergeMemoryHooks(content, memoryEnabled, devflowDir);
@@ -1980,7 +1980,7 @@ export const initCommand = new Command('init')
1980
1980
  content = addContextHook(cleanedForContext, devflowDir);
1981
1981
  // Legacy dream-worker hook cleanup — strip any stale spawn-dream-worker entry
1982
1982
  // left in settings.json by a prior install (session-start-context now spawns
1983
- // the Learning agent via directive).
1983
+ // the Curate agent via directive).
1984
1984
  content = removeDreamHook(content);
1985
1985
  // Strip Devflow-managed teammateMode ("auto"). User-set values (e.g. "tmux") are preserved.
1986
1986
  content = stripDevflowTeammateModeFromJson(content);
@@ -3,7 +3,7 @@ import { promises as fs } from 'fs';
3
3
  import * as path from 'path';
4
4
  import * as p from '@clack/prompts';
5
5
  import color from 'picocolors';
6
- import { getLearningDir, getLearningTuningConfigPath, } from '../../core/project-paths.js';
6
+ import { getLearningDir, getCurateTuningConfigPath, } from '../../core/project-paths.js';
7
7
  import { loadShippedAgentDefaults } from '../../core/agent-models.js';
8
8
  import { readMachineFeature, writeMachineFeature } from '../../core/feature-switch.js';
9
9
  import { loadSettingsModule, narrowedSwitchLabel, personalConfigTrackedWarning } from '../../core/evidence-policy.js';
@@ -263,7 +263,7 @@ async function handleRestore(anchor) {
263
263
  * The scope choices of `devflow learning --configure`.
264
264
  *
265
265
  * D-LEARNING-MODEL-PRECEDENCE: the session-start hook takes the first layer that
266
- * supplies a model — the project file, then a `devflow agents` Learning mapping,
266
+ * supplies a model — the project file, then a `devflow agents` Curate mapping,
267
267
  * then the global file. A global file therefore has no effect for a user who has
268
268
  * such a mapping, and its hint says so.
269
269
  */
@@ -272,24 +272,24 @@ export const CONFIGURE_SCOPE_OPTIONS = [
272
272
  {
273
273
  value: 'global',
274
274
  label: 'Global',
275
- hint: 'All projects (~/.devflow/learning.json); a devflow agents Learning mapping takes precedence over it',
275
+ hint: 'All projects (~/.devflow/learning.json); a devflow agents Curate mapping takes precedence over it',
276
276
  },
277
277
  ];
278
278
  /** The models `devflow learning --configure` offers, each with what it is good for. */
279
- const LEARNING_MODEL_CHOICES = [
279
+ const CURATE_MODEL_CHOICES = [
280
280
  { value: 'opus', label: 'Opus', note: 'highest quality for detection + curation judgment' },
281
281
  { value: 'sonnet', label: 'Sonnet', note: 'good balance of quality and speed' },
282
282
  { value: 'haiku', label: 'Haiku', note: 'fastest, lowest cost' },
283
283
  ];
284
284
  /**
285
- * D-LEARNING-SHIPPED-ROW: the model offered as "Recommended" is the one the Learning
285
+ * D-LEARNING-SHIPPED-ROW: the model offered as "Recommended" is the one the Curate
286
286
  * agent ships with, the `model:` line of its frontmatter. It is read from there and
287
287
  * written nowhere else, so a change of the shipped tier moves the recommendation with
288
288
  * it and this list never has to be edited. A shipped model outside the three offered
289
289
  * (or none) recommends nothing.
290
290
  */
291
- export function learningModelOptions(shippedModel) {
292
- return LEARNING_MODEL_CHOICES.map(choice => ({
291
+ export function curateModelOptions(shippedModel) {
292
+ return CURATE_MODEL_CHOICES.map(choice => ({
293
293
  value: choice.value,
294
294
  label: choice.label,
295
295
  hint: choice.value === shippedModel
@@ -299,10 +299,10 @@ export function learningModelOptions(shippedModel) {
299
299
  }
300
300
  async function handleConfigure() {
301
301
  p.intro(color.bgCyan(color.black(' Learning Configuration ')));
302
- const shippedModel = (await loadShippedAgentDefaults()).learning?.model;
302
+ const shippedModel = (await loadShippedAgentDefaults()).curate?.model;
303
303
  const model = await p.select({
304
304
  message: 'Model for decision detection',
305
- options: learningModelOptions(shippedModel),
305
+ options: curateModelOptions(shippedModel),
306
306
  });
307
307
  if (p.isCancel(model)) {
308
308
  p.cancel('Configuration cancelled.');
@@ -341,7 +341,7 @@ async function handleConfigure() {
341
341
  // main checkout in a linked worktree; the current directory outside git.
342
342
  const projectRoot = (await getLedgerRoot()) ?? process.cwd();
343
343
  const learningDir = getLearningDir(projectRoot);
344
- const projectConfigPath = getLearningTuningConfigPath(projectRoot);
344
+ const projectConfigPath = getCurateTuningConfigPath(projectRoot);
345
345
  // D-CLI-NO-SYMLINK (core/linked-path.ts): nothing is written through a .devflow,
346
346
  // a learning folder or a learning.json that is a symbolic link.
347
347
  const linked = await firstSymbolicLink([path.dirname(learningDir), learningDir, projectConfigPath]);
@@ -419,7 +419,7 @@ async function handleClear() {
419
419
  process.exitCode = 1;
420
420
  return;
421
421
  }
422
- // A mid-run Learning agent whose claimed batch vanishes stops without further
422
+ // A mid-run Curate agent whose claimed batch vanishes stops without further
423
423
  // writes — the desired outcome of clearing.
424
424
  const drain = await drainLearningQueue(ledgerRoot);
425
425
  p.log.success(`Cleared ${counted(cleared.value.cleared, 'observation')} no entry uses and kept ${cleared.value.kept} ` +
@@ -480,7 +480,7 @@ async function handleToggle(enabled) {
480
480
  return;
481
481
  }
482
482
  // Drain the current project's learning (decisions-detection) queue so stale
483
- // turns don't process on re-enable. A mid-run Learning agent whose claimed
483
+ // turns don't process on re-enable. A mid-run Curate agent whose claimed
484
484
  // batch vanishes aborts without changes — the desired outcome of disabling.
485
485
  const ledgerRoot = await getLedgerRoot();
486
486
  if (ledgerRoot) {
@@ -2,7 +2,7 @@ import { devflowHookOwner, hasHook, removeHooks, } from '../../targets/claude-co
2
2
  // ─── Dream worker hook cleanup ──────────────────────────────────────────────
3
3
  //
4
4
  // The spawn-dream-worker SessionStart hook belonged to the retired detached
5
- // dream worker. Decisions processing runs as the directive-spawned Learning agent
5
+ // dream worker. Decisions processing runs as the directive-spawned Curate agent
6
6
  // (session-start-context Section 2), which needs no hook registration of its
7
7
  // own. remove/has exist for upgrade cleanup: init and uninstall strip any
8
8
  // stale entry left in settings.json by a prior install.
@@ -7,7 +7,7 @@ import color from 'picocolors';
7
7
  import { getInstallationPaths, getClaudeDirectory, getHomeDirectory, getManagedSettingsPath } from '../../targets/claude-code/claude-paths.js';
8
8
  import { getGitRoot } from '../../core/git.js';
9
9
  import { isSameLocation } from '../../core/same-location.js';
10
- import { DEVFLOW_PLUGINS, SKILL_NAMESPACE, getAllSkillNames, getAllAgentNames, getAllCommandNames, parsePluginSelection, resolveFeatureRedirect, prefixSkillName, unprefixSkillName, skillsOf, FEATURE_OWNED_SKILLS } from '../../core/plugins.js';
10
+ import { DEVFLOW_PLUGINS, SKILL_NAMESPACE, buildAssetMaps, getAllSkillNames, getAllAgentNames, getAllCommandNames, parsePluginSelection, resolveFeatureRedirect, prefixSkillName, unprefixSkillName, skillsOf, FEATURE_OWNED_SKILLS } from '../../core/plugins.js';
11
11
  import { readManifest, removeManifestPlugins } from '../../core/manifest.js';
12
12
  import { sweepOrphanedAssets, mdFileName, mdEntryName } from '../../core/orphan-sweep.js';
13
13
  import { LEGACY_SKILL_NAMES } from '../../targets/claude-code/legacy.js';
@@ -20,7 +20,7 @@ import { removeContextHook } from './context.js';
20
20
  import { applyProxyTeardownToSettings } from './proxy.js';
21
21
  import { readProxyState, proxyJsonExists } from '../../core/proxy-state.js';
22
22
  import { hudCacheDir } from '../../core/cache.js';
23
- import { TRACKER_ATTEMPTS_NAMES, TRACKER_CLAIM_FILE, TRACKER_CONVENTIONS_DIR, TRACKER_ENABLED_FILE, TRACKER_LEGACY_ATTEMPTS_FILE, TRACKER_LEGACY_CONVENTIONS_FILE, TRACKER_PROVIDER_IDS, TRACKER_STAGED_PREFIX, } from '../../core/tracker.js';
23
+ import { effectiveTrackerServers, TRACKER_ATTEMPTS_NAMES, TRACKER_CLAIM_FILE, TRACKER_CONVENTIONS_DIR, TRACKER_ENABLED_FILE, TRACKER_LEGACY_ATTEMPTS_FILE, TRACKER_LEGACY_CONVENTIONS_FILE, TRACKER_PROVIDER_IDS, TRACKER_STAGED_PREFIX, } from '../../core/tracker.js';
24
24
  import { CLAUDE_MD_AUDIT_STAMP_FILE, CLAUDE_MD_AUDIT_STAMP_TMP_PREFIX } from '../../core/claude-md-audit.js';
25
25
  import { revertExternalAgents } from '../../core/agent-models.js';
26
26
  import { detectShell, getProfilePath } from '../../core/safe-delete.js';
@@ -32,6 +32,7 @@ import { stripDevflowTeammateModeFromJson } from '../../core/teammate-mode-clean
32
32
  import { getPackageRoot, isContainedIn } from '../../core/paths.js';
33
33
  import { firstSymbolicLink } from '../../core/linked-path.js';
34
34
  import { restampInstalledCommands } from '../../targets/claude-code/language-stamp.js';
35
+ import { installCommandsAndAgents } from '../../targets/claude-code/installer.js';
35
36
  /**
36
37
  * Where a retired repo-local install lives: `<gitRoot>/.claude` and `<gitRoot>/.devflow`.
37
38
  *
@@ -488,7 +489,7 @@ export function userContentPaths(devflowDir) {
488
489
  const name = `${TRACKER_LEGACY_CONVENTIONS_FILE}.${id}.bak`;
489
490
  return { relPath: name, label: `${name} (previous issue tracker conventions)` };
490
491
  }),
491
- // learning.json — global learning agent tuning config
492
+ // learning.json — global curate agent tuning config
492
493
  { relPath: 'learning.json', label: 'learning.json' },
493
494
  // hud.json — user HUD enable/disable preference and display config
494
495
  { relPath: 'hud.json', label: 'hud.json (HUD configuration)' },
@@ -885,6 +886,89 @@ export async function runDryRunPhase(opts) {
885
886
  }
886
887
  }
887
888
  }
889
+ /**
890
+ * After a selective uninstall removed a retired agent file, write the current commands
891
+ * and agents of the plugins that stay installed.
892
+ *
893
+ * A retired agent file only exists on a machine that ran an older release. That
894
+ * release's commands, for the plugins that stay, still spawn the retired name, and the
895
+ * agents that replaced it are not installed. Removing the file without this step would
896
+ * leave those plugins unable to spawn their agents until the next full `devflow init`.
897
+ *
898
+ * Writes only commands and agents, through the same copy path `devflow init` uses
899
+ * ({@link installCommandsAndAgents}). It does not touch the hooks, the scripts or
900
+ * settings.json, so the notice tells the user to run `devflow init` for those.
901
+ *
902
+ * Never runs in a legacy local scope (D-CLI-NO-SYMLINK): a repository can commit a command
903
+ * file as a symbolic link, and the copy writes through it. The folder guard below does not
904
+ * check files. `devflow init` can not update a legacy local install either, so the warning
905
+ * tells the user to remove it in full.
906
+ *
907
+ * Skipped, with a warning, when there is no readable manifest or it lists no known plugin (the
908
+ * retained set would be a guess), or when a folder is behind a link the caller's guard
909
+ * refuses. Those warnings name `devflow init` as the remedy. When the copy fails, it stops
910
+ * at the first failure: files it wrote before then stay, and the warning names the same
911
+ * remedy. Never throws: an uninstall must finish.
912
+ * Agent model lines are reverted again after the copy, as the selective phase does before
913
+ * its removal, so a freshly written agent carries no external-model line. Like the
914
+ * selective phase, it prints the warnings of that revert only with `verbose`.
915
+ */
916
+ export async function refreshRetainedCommandsAndAgents(opts) {
917
+ const { claudeDir, devflowDir, retained, retiredAgents } = opts;
918
+ const scope = opts.scope ?? 'user';
919
+ const verbose = opts.verbose ?? false;
920
+ const mayChange = opts.mayChange ?? changeAnything;
921
+ const agentsDir = path.join(claudeDir, 'agents', 'devflow');
922
+ const commandsDir = path.join(claudeDir, 'commands', 'devflow');
923
+ const retired = `Removed the agent file(s) of an older Devflow release: ${retiredAgents.join(', ')}.`;
924
+ const remedy = 'Run `devflow init` to update the commands, agents, hooks and scripts of the plugins that stay installed.';
925
+ if (retained.length === 0)
926
+ return;
927
+ if (scope === 'local') {
928
+ p.log.warn(`${retired} Devflow does not rewrite files in a legacy local install, so the remaining commands can still name the removed agents. Remove the legacy local install in full with \`devflow uninstall --scope local\`.`);
929
+ return;
930
+ }
931
+ // readManifest returns null for a missing file and for one it can not parse or validate.
932
+ const manifest = await readManifest(devflowDir).catch(() => null);
933
+ if (manifest === null) {
934
+ p.log.warn(`${retired} There is no readable manifest, so Devflow did not rewrite the remaining files. ${remedy}`);
935
+ return;
936
+ }
937
+ if (manifest.plugins.length === 0) {
938
+ p.log.warn(`${retired} The manifest lists no plugins, so Devflow did not rewrite the remaining files. ${remedy}`);
939
+ return;
940
+ }
941
+ // resolveInstalledPlugins falls back to the whole registry when no manifest name resolves, so
942
+ // the retained set would hold plugins that were never installed.
943
+ if (!manifest.plugins.some(name => DEVFLOW_PLUGINS.some(plugin => plugin.name === name))) {
944
+ p.log.warn(`${retired} The manifest lists no known plugin, so Devflow did not rewrite the remaining files. ${remedy}`);
945
+ return;
946
+ }
947
+ if (!(await mayChange(agentsDir)) || !(await mayChange(commandsDir))) {
948
+ p.log.warn(`${retired} A linked folder blocks the rewrite. ${remedy}`);
949
+ return;
950
+ }
951
+ try {
952
+ await installCommandsAndAgents({
953
+ plugins: retained,
954
+ agentsMap: buildAssetMaps(retained).agentsMap,
955
+ claudeDir,
956
+ learning: manifest.features.learning,
957
+ trackerServers: effectiveTrackerServers(manifest.features.tracker),
958
+ warn: (msg) => p.log.warn(msg),
959
+ });
960
+ }
961
+ catch (err) {
962
+ p.log.warn(`${retired} Devflow could not write the current commands and agents (${err instanceof Error ? err.message : String(err)}). ${remedy}`);
963
+ return;
964
+ }
965
+ try {
966
+ await revertExternalAgents({ installDir: agentsDir, devflowDir, onWarning: (msg) => { if (verbose)
967
+ p.log.warn(msg); } });
968
+ }
969
+ catch { /* the revert is best effort, as in the selective phase */ }
970
+ p.log.info(`${retired} Devflow wrote the current commands and agents of the plugins that stay installed. Run \`devflow init\` to update the hooks and scripts.`);
971
+ }
888
972
  /**
889
973
  * SELECTIVE PHASE (per scope): revert agent model overrides, remove the
890
974
  * selected plugins' assets, and clean up the ambient hook if the ambient
@@ -919,7 +1003,23 @@ export async function runSelectivePhaseForScope(opts) {
919
1003
  }
920
1004
  catch { /* agents dir absent or revert failed — non-fatal */ }
921
1005
  }
922
- await removeSelectedPlugins(claudeDir, selectedPlugins, verbose, installedPlugins, mayChange);
1006
+ const sweeps = await removeSelectedPlugins(claudeDir, selectedPlugins, verbose, installedPlugins, mayChange);
1007
+ // A retired agent file means the install is from an older release, and the commands of the
1008
+ // plugins that stay installed still spawn the name that was just removed. Write their
1009
+ // current commands and agents so the install stays whole. Runs before the language stamp
1010
+ // below, which then restamps the command this wrote.
1011
+ if (sweeps.agents.removed.length > 0) {
1012
+ const removed = new Set(selectedPlugins.map(sp => sp.name));
1013
+ await refreshRetainedCommandsAndAgents({
1014
+ claudeDir,
1015
+ devflowDir,
1016
+ retained: installedPlugins.filter(plugin => !removed.has(plugin.name)),
1017
+ retiredAgents: sweeps.agents.removed,
1018
+ scope,
1019
+ verbose,
1020
+ mayChange,
1021
+ });
1022
+ }
923
1023
  // D-LANGUAGE-FOCUS-STAMP: re-stamp the installed /code-review from the selection that REMAINS.
924
1024
  // A language plugin owns a skill and no command, so removing it deletes the skill while its
925
1025
  // name would stay on the stamped line, and /code-review would spawn a focus whose skill is gone.
@@ -1627,6 +1727,9 @@ export async function removeAllDevFlow(claudeDir, devflowScriptsDir, verbose, ma
1627
1727
  * A folder `mayChange` refuses is not swept at all (D-CLI-NO-SYMLINK,
1628
1728
  * legacyLocalChangeGuard). An entry in a swept folder that is itself a link is
1629
1729
  * only unlinked: `fs.rm` never follows the link it is given.
1730
+ *
1731
+ * Returns what each sweep removed and failed to remove, so a caller can tell that
1732
+ * a retired agent was removed (see {@link refreshRetainedCommandsAndAgents}).
1630
1733
  */
1631
1734
  export async function sweepDevflowNamespaces(claudeDir, verbose, mayChange = changeAnything) {
1632
1735
  const agentsDir = path.join(claudeDir, 'agents', 'devflow');
@@ -1656,6 +1759,7 @@ export async function sweepDevflowNamespaces(claudeDir, verbose, mayChange = cha
1656
1759
  p.log.warn(`Could not remove orphaned ${kind} "${failure.name}" (${reason}) — remove it manually`);
1657
1760
  }
1658
1761
  }
1762
+ return { agents: agentsSweep, commands: commandsSweep, skills: skillsSweep };
1659
1763
  }
1660
1764
  /**
1661
1765
  * Remove only specific plugin assets (selective uninstall).
@@ -1665,6 +1769,8 @@ export async function sweepDevflowNamespaces(claudeDir, verbose, mayChange = cha
1665
1769
  * For skills: only remove skills that are NOT used by any remaining plugin.
1666
1770
  * Each removal passes `mayChange` first, which skips one a symbolic link would
1667
1771
  * redirect in a legacy local install (D-CLI-NO-SYMLINK, legacyLocalChangeGuard).
1772
+ *
1773
+ * Returns what the closing registry-diff sweep removed.
1668
1774
  */
1669
1775
  export async function removeSelectedPlugins(claudeDir, plugins, verbose, installedPlugins = DEVFLOW_PLUGINS, mayChange = changeAnything) {
1670
1776
  const { skills, agents, commands, rules } = computeAssetsToRemove(plugins, installedPlugins);
@@ -1734,6 +1840,6 @@ export async function removeSelectedPlugins(claudeDir, plugins, verbose, install
1734
1840
  // Removes any orphaned files whose names left the registry (retired, renamed,
1735
1841
  // or deleted from all plugins). Spans ALL plugins so assets belonging to
1736
1842
  // non-selected plugins are never swept.
1737
- await sweepDevflowNamespaces(claudeDir, verbose, mayChange);
1843
+ return sweepDevflowNamespaces(claudeDir, verbose, mayChange);
1738
1844
  }
1739
1845
  //# sourceMappingURL=uninstall.js.map