devflow-kit 3.3.0 → 3.5.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 (220) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/README.md +8 -4
  3. package/dist/agents/code-edit.md +133 -0
  4. package/dist/agents/code-fix.md +165 -0
  5. package/dist/agents/code.md +187 -0
  6. package/{src/assets → dist}/agents/design.md +1 -2
  7. package/{src/assets → dist}/agents/diagnose.md +1 -2
  8. package/dist/agents/git.md +33 -722
  9. package/{src/assets → dist}/agents/knowledge.md +12 -5
  10. package/{src/assets → dist}/agents/research.md +8 -2
  11. package/{src/assets → dist}/agents/review.md +8 -11
  12. package/{src/assets → dist}/agents/scrutinize.md +4 -1
  13. package/dist/agents/skim.md +152 -0
  14. package/{src/assets → dist}/agents/triage.md +9 -2
  15. package/dist/cli/commands/behavior-prompts.js +77 -0
  16. package/dist/cli/commands/behavior.js +123 -0
  17. package/dist/cli/commands/flags.js +8 -2
  18. package/dist/cli/commands/init-seed.js +7 -3
  19. package/dist/cli/commands/init.js +134 -5
  20. package/dist/cli/commands/learning.js +38 -3
  21. package/dist/cli/commands/rules.js +16 -0
  22. package/dist/cli/commands/tracker.js +112 -15
  23. package/dist/cli/commands/uninstall.js +42 -1
  24. package/dist/cli.js +2 -0
  25. package/dist/commands/bug-analysis.md +35 -13
  26. package/dist/commands/code-review.md +155 -69
  27. package/dist/commands/debug.md +39 -16
  28. package/dist/commands/dynamic-build.md +61 -72
  29. package/dist/commands/dynamic-plan.md +39 -25
  30. package/dist/commands/dynamic-profile.md +28 -14
  31. package/dist/commands/dynamic-tickets.md +38 -22
  32. package/dist/commands/explore.md +18 -16
  33. package/dist/commands/implement.md +121 -150
  34. package/dist/commands/plan.md +51 -31
  35. package/dist/commands/release.md +72 -6
  36. package/dist/commands/research.md +49 -20
  37. package/dist/commands/resolve.md +54 -46
  38. package/dist/commands/self-review.md +38 -25
  39. package/dist/core/agent-frontmatter.js +101 -0
  40. package/dist/core/agent-models.js +43 -0
  41. package/dist/core/assets.js +55 -10
  42. package/dist/core/claude-md-audit.js +190 -0
  43. package/dist/core/compliance-compose.js +6 -4
  44. package/dist/core/feature-switch.js +41 -1
  45. package/dist/core/flags.js +139 -0
  46. package/dist/core/fs-atomic.js +8 -3
  47. package/dist/core/learning-variants.js +213 -0
  48. package/dist/core/manifest.js +73 -3
  49. package/dist/core/mds-variants.js +98 -19
  50. package/dist/core/plugins.js +111 -72
  51. package/dist/core/project-paths.js +0 -4
  52. package/dist/core/proxy-log.js +1 -1
  53. package/dist/core/proxy-state.js +1 -1
  54. package/dist/core/tracker.js +120 -2
  55. package/dist/learning-off/agents/code-edit.md +129 -0
  56. package/dist/learning-off/agents/code-fix.md +161 -0
  57. package/dist/learning-off/agents/code.md +183 -0
  58. package/dist/learning-off/agents/design.md +118 -0
  59. package/dist/learning-off/agents/diagnose.md +210 -0
  60. package/dist/learning-off/agents/knowledge.md +96 -0
  61. package/dist/learning-off/agents/research.md +155 -0
  62. package/dist/learning-off/agents/review.md +224 -0
  63. package/dist/learning-off/agents/scrutinize.md +120 -0
  64. package/{src/assets → dist/learning-off}/agents/skim.md +5 -8
  65. package/dist/learning-off/agents/triage.md +170 -0
  66. package/dist/learning-off/commands/bug-analysis.md +420 -0
  67. package/dist/learning-off/commands/code-review.md +530 -0
  68. package/dist/learning-off/commands/debug.md +314 -0
  69. package/dist/learning-off/commands/dynamic-build.md +1245 -0
  70. package/dist/learning-off/commands/dynamic-plan.md +426 -0
  71. package/dist/learning-off/commands/dynamic-profile.md +214 -0
  72. package/dist/learning-off/commands/dynamic-tickets.md +634 -0
  73. package/dist/learning-off/commands/explore.md +210 -0
  74. package/dist/learning-off/commands/implement.md +774 -0
  75. package/dist/learning-off/commands/plan.md +671 -0
  76. package/dist/learning-off/commands/release.md +311 -0
  77. package/dist/learning-off/commands/research.md +229 -0
  78. package/dist/learning-off/commands/resolve.md +842 -0
  79. package/dist/learning-off/commands/self-review.md +266 -0
  80. package/dist/skills/git/references/learn-conventions.md +27 -3
  81. package/dist/skills/git/references/pr/check-ci-status.md +19 -0
  82. package/dist/skills/git/references/pr/check-merge-readiness.md +19 -0
  83. package/dist/skills/git/references/pr/fetch-review-threads.md +30 -0
  84. package/dist/skills/git/references/pr/post-resolution-summary.md +18 -0
  85. package/dist/skills/git/references/pr/post-review-summary.md +20 -0
  86. package/dist/skills/git/references/pr/resolve-review-threads.md +28 -4
  87. package/dist/skills/git/references/pr/update-pr-evidence.md +13 -0
  88. package/dist/skills/git/references/pr/validate-branch.md +26 -0
  89. package/dist/skills/git/references/tracker/_contract.md +33 -0
  90. package/dist/skills/git/references/tracker/github/associate-release.md +24 -0
  91. package/dist/skills/git/references/tracker/github/backlink-shipped-issues.md +31 -1
  92. package/dist/skills/git/references/tracker/github/create-release.md +30 -1
  93. package/dist/skills/git/references/tracker/github/ensure-pr-ready.md +89 -2
  94. package/dist/skills/git/references/tracker/github/ensure-traceable-issue.md +16 -1
  95. package/dist/skills/git/references/tracker/github/fetch-issue.md +38 -1
  96. package/dist/skills/git/references/tracker/github/fetch-issues-batch.md +49 -1
  97. package/dist/skills/git/references/tracker/github/gather-release-evidence.md +29 -0
  98. package/dist/skills/git/references/tracker/github/manage-debt.md +21 -1
  99. package/dist/skills/git/references/tracker/github/post-wave-report.md +17 -1
  100. package/dist/skills/git/references/tracker/github/setup-task.md +53 -1
  101. package/dist/skills/git/references/tracker/jira/associate-release.md +25 -1
  102. package/dist/skills/git/references/tracker/jira/backlink-shipped-issues.md +31 -1
  103. package/dist/skills/git/references/tracker/jira/create-release.md +30 -1
  104. package/dist/skills/git/references/tracker/jira/ensure-pr-ready.md +89 -2
  105. package/dist/skills/git/references/tracker/jira/ensure-traceable-issue.md +16 -1
  106. package/dist/skills/git/references/tracker/jira/fetch-issue.md +38 -1
  107. package/dist/skills/git/references/tracker/jira/fetch-issues-batch.md +49 -1
  108. package/dist/skills/git/references/tracker/jira/gather-release-evidence.md +29 -0
  109. package/dist/skills/git/references/tracker/jira/manage-debt.md +21 -1
  110. package/dist/skills/git/references/tracker/jira/post-wave-report.md +17 -1
  111. package/dist/skills/git/references/tracker/jira/setup-task.md +55 -3
  112. package/dist/skills/git/references/tracker/linear/associate-release.md +25 -1
  113. package/dist/skills/git/references/tracker/linear/backlink-shipped-issues.md +31 -1
  114. package/dist/skills/git/references/tracker/linear/create-release.md +30 -1
  115. package/dist/skills/git/references/tracker/linear/ensure-pr-ready.md +89 -2
  116. package/dist/skills/git/references/tracker/linear/ensure-traceable-issue.md +16 -1
  117. package/dist/skills/git/references/tracker/linear/fetch-issue.md +38 -1
  118. package/dist/skills/git/references/tracker/linear/fetch-issues-batch.md +49 -1
  119. package/dist/skills/git/references/tracker/linear/gather-release-evidence.md +29 -0
  120. package/dist/skills/git/references/tracker/linear/manage-debt.md +21 -1
  121. package/dist/skills/git/references/tracker/linear/post-wave-report.md +17 -1
  122. package/dist/skills/git/references/tracker/linear/setup-task.md +55 -3
  123. package/dist/targets/claude-code/agent-type-owner.js +164 -0
  124. package/dist/targets/claude-code/behavior-install.js +111 -0
  125. package/dist/targets/claude-code/installer.js +140 -37
  126. package/dist/targets/claude-code/language-stamp.js +185 -0
  127. package/dist/targets/claude-code/learning-install.js +497 -0
  128. package/dist/targets/claude-code/tracker-install.js +33 -16
  129. package/dist/targets/claude-code/tracker-servers.js +107 -0
  130. package/package.json +4 -3
  131. package/src/assets/agents/_partials/_code.mds +109 -0
  132. package/src/assets/agents/code-edit.mds +81 -0
  133. package/src/assets/agents/code-fix.mds +113 -0
  134. package/src/assets/agents/code.mds +135 -0
  135. package/src/assets/agents/design.mds +148 -0
  136. package/src/assets/agents/diagnose.mds +225 -0
  137. package/src/assets/agents/evaluate.md +8 -4
  138. package/src/assets/agents/explore.md +58 -0
  139. package/src/assets/agents/git.mds +33 -722
  140. package/src/assets/agents/knowledge.mds +131 -0
  141. package/src/assets/agents/learning.md +19 -69
  142. package/src/assets/agents/research.mds +182 -0
  143. package/src/assets/agents/review.mds +282 -0
  144. package/src/assets/agents/scrutinize.mds +135 -0
  145. package/src/assets/agents/simplify.md +3 -0
  146. package/src/assets/agents/skim.mds +165 -0
  147. package/src/assets/agents/synthesize.md +26 -352
  148. package/src/assets/agents/test.md +8 -0
  149. package/src/assets/agents/tracker.md +20 -7
  150. package/src/assets/agents/triage.mds +201 -0
  151. package/src/assets/agents/validate.md +13 -6
  152. package/src/assets/commands/_partials/_compliance.mds +41 -4
  153. package/src/assets/commands/_partials/_decisions.mds +33 -2
  154. package/src/assets/commands/_partials/_engine.mds +14 -6
  155. package/src/assets/commands/_partials/_knowledge.mds +25 -12
  156. package/src/assets/commands/_partials/_preamble.mds +34 -10
  157. package/src/assets/commands/_partials/_publication.mds +5 -4
  158. package/src/assets/commands/_partials/_roster.mds +4 -3
  159. package/src/assets/commands/_partials/_settings.mds +13 -5
  160. package/src/assets/commands/_partials/_wave.mds +9 -1
  161. package/src/assets/commands/bug-analysis.mds +27 -5
  162. package/src/assets/commands/code-review.mds +158 -52
  163. package/src/assets/commands/debug.mds +41 -3
  164. package/src/assets/commands/dynamic-build.mds +47 -27
  165. package/src/assets/commands/dynamic-plan.mds +40 -9
  166. package/src/assets/commands/dynamic-profile.mds +9 -1
  167. package/src/assets/commands/dynamic-tickets.mds +21 -6
  168. package/src/assets/commands/explore.mds +28 -2
  169. package/src/assets/commands/implement.mds +126 -129
  170. package/src/assets/commands/plan.mds +58 -14
  171. package/src/assets/commands/{release.md → release.mds} +30 -26
  172. package/src/assets/commands/research.mds +42 -11
  173. package/src/assets/commands/resolve.mds +59 -15
  174. package/src/assets/commands/self-review.mds +30 -5
  175. package/src/assets/mds/.mdsroot +4 -0
  176. package/src/assets/mds/git/_ops.mds +383 -0
  177. package/src/assets/mds/git/_ops_pr.mds +201 -0
  178. package/src/assets/mds/git/_ops_steps.mds +147 -0
  179. package/src/assets/mds/git/_pr.mds +39 -44
  180. package/src/assets/mds/git/_references.mds +6 -3
  181. package/src/assets/mds/tracker/_common.mds +5 -5
  182. package/src/assets/mds/tracker/_contract.mds +73 -0
  183. package/src/assets/mds/tracker/_github.mds +73 -16
  184. package/src/assets/mds/tracker/_jira.mds +77 -19
  185. package/src/assets/mds/tracker/_linear.mds +77 -19
  186. package/src/assets/mds/tracker/_mcp.mds +2 -2
  187. package/src/assets/mds/tracker/_steps.mds +98 -0
  188. package/src/assets/rules/behavior.md +6 -0
  189. package/src/assets/rules/context-economy.md +10 -0
  190. package/src/assets/rules/go.md +1 -0
  191. package/src/assets/rules/java.md +1 -0
  192. package/src/assets/rules/python.md +1 -0
  193. package/src/assets/rules/rust.md +1 -0
  194. package/src/assets/rules/typescript.md +1 -0
  195. package/src/assets/scripts/claude-md-audit.cjs +611 -0
  196. package/src/assets/scripts/hooks/assets/orchestrator-charter.md +3 -3
  197. package/src/assets/scripts/hooks/json-helper.cjs +13 -5
  198. package/src/assets/scripts/hooks/json-parse +34 -10
  199. package/src/assets/scripts/hooks/lib/project-paths.cjs +0 -6
  200. package/src/assets/scripts/hooks/session-start-context +315 -7
  201. package/src/assets/skills/agent-references/SKILL.md +33 -0
  202. package/src/assets/skills/agent-references/references/learning/maintain.md +71 -0
  203. package/src/assets/skills/agent-references/references/synthesize/bug-analysis.md +71 -0
  204. package/src/assets/skills/agent-references/references/synthesize/design.md +36 -0
  205. package/src/assets/skills/agent-references/references/synthesize/exploration.md +38 -0
  206. package/src/assets/skills/agent-references/references/synthesize/planning.md +60 -0
  207. package/src/assets/skills/agent-references/references/synthesize/research.md +61 -0
  208. package/src/assets/skills/agent-references/references/synthesize/review.md +76 -0
  209. package/src/assets/skills/apply-decisions/SKILL.md +1 -1
  210. package/src/assets/skills/apply-feature-knowledge/SKILL.md +5 -5
  211. package/src/assets/skills/compliance/SKILL.md +1 -1
  212. package/src/assets/skills/docs-framework/SKILL.md +80 -83
  213. package/src/assets/skills/docs-framework/references/patterns.md +14 -25
  214. package/src/assets/skills/docs-framework/references/violations.md +7 -7
  215. package/src/assets/skills/feature-knowledge/SKILL.md +43 -12
  216. package/src/assets/skills/gap-analysis/SKILL.md +0 -16
  217. package/src/assets/skills/gap-analysis/references/compliance.md +19 -0
  218. package/src/assets/skills/quality-gates/SKILL.md +1 -1
  219. package/dist/skills/git/references/pr/ensure-pr-ready.md +0 -24
  220. package/src/assets/agents/code.md +0 -330
@@ -49,7 +49,14 @@ export const DEVFLOW_PLUGINS = [
49
49
  * dist/commands/, and a hook-spawned agent appears in none of them.
50
50
  */
51
51
  agents: ['learning', 'tracker'],
52
- skills: ['apply-decisions', 'apply-feature-knowledge', 'software-design', 'docs-framework', 'git', 'boundary-validation', 'test-driven-development', 'testing', 'dependency-research'],
52
+ /**
53
+ * D-AGENT-REFS: `agent-references` is a reference-only skill. It holds the Synthesize mode
54
+ * templates and the Learning maintain step, which those two agents read by explicit path, so
55
+ * it sits here (core-skills is always installed) and no other plugin lists or requires it.
56
+ * It is never preloaded: tests/guards/agent-references.test.ts holds that, and the one
57
+ * exception to the repo-wide ban on `disable-model-invocation` names this skill alone.
58
+ */
59
+ skills: ['apply-decisions', 'apply-feature-knowledge', 'software-design', 'docs-framework', 'git', 'boundary-validation', 'test-driven-development', 'testing', 'dependency-research', 'agent-references'],
53
60
  requires: [
54
61
  'architecture',
55
62
  'complexity',
@@ -64,34 +71,30 @@ export const DEVFLOW_PLUGINS = [
64
71
  'security',
65
72
  'worktree-support',
66
73
  ],
67
- rules: ['security', 'engineering', 'quality', 'reliability'],
74
+ // D-CONTEXT-ECONOMY-RULE: reading discipline is a core rule, not a skill, because it
75
+ // must reach every session and every spawned agent without an activation step. It
76
+ // tells the model to list a large file's headings and read ranges, and to count
77
+ // search matches before printing them. Its body stays near 400 characters (ceiling
78
+ // 450) and names no search binary, since the rule is loaded into every session;
79
+ // tests/rules.test.ts enforces the length, the directives and this registration.
80
+ rules: ['security', 'engineering', 'quality', 'reliability', 'context-economy'],
68
81
  },
69
82
  {
70
83
  name: 'devflow-plan',
71
84
  description: 'Unified design planning with gap analysis and design review',
72
85
  commands: ['/plan'],
73
- agents: ['git', 'skim', 'synthesize', 'design'],
86
+ agents: ['git', 'skim', 'synthesize', 'design', 'explore'],
74
87
  skills: ['gap-analysis', 'design-review', 'patterns', 'worktree-support', 'feature-knowledge', 'apply-feature-knowledge'],
75
88
  // D-CHARTER-BOUNDED-INLINE: /plan's main thread orchestrates and loads no
76
89
  // companion skills, so `requires:` lists only skills this plugin's command,
77
90
  // agents and skills reference. `software-design` and `test-driven-development`
78
91
  // have no reader here; the closure guard's reverse arm rejects an unread entry.
92
+ // `docs-framework` is read: Phase 14 loads it at the step that names the
93
+ // design document (D-DOCS-NAMES-AUTHORITY).
79
94
  requires: [
80
95
  'apply-decisions',
81
- 'architecture',
82
- 'complexity',
83
- 'consistency',
84
- 'database',
85
- 'dependencies',
86
96
  'docs-framework',
87
- 'documentation',
88
97
  'git',
89
- 'performance',
90
- 'regression',
91
- 'reliability',
92
- 'review-methodology',
93
- 'security',
94
- 'testing',
95
98
  ],
96
99
  rules: [],
97
100
  },
@@ -99,17 +102,15 @@ export const DEVFLOW_PLUGINS = [
99
102
  name: 'devflow-implement',
100
103
  description: 'Complete task implementation workflow - accepts plan documents, issues, or task descriptions',
101
104
  commands: ['/implement'],
102
- agents: ['git', 'code', 'simplify', 'scrutinize', 'evaluate', 'test', 'validate', 'knowledge'],
105
+ agents: ['git', 'code', 'code-fix', 'simplify', 'scrutinize', 'evaluate', 'test', 'validate', 'knowledge'],
103
106
  skills: ['patterns', 'qa', 'quality-gates', 'worktree-support', 'feature-knowledge', 'apply-feature-knowledge'],
104
107
  requires: [
105
108
  'apply-decisions',
106
109
  'architecture',
107
- 'boundary-validation',
108
110
  'complexity',
109
111
  'consistency',
110
112
  'database',
111
113
  'dependencies',
112
- 'dependency-research',
113
114
  'documentation',
114
115
  'git',
115
116
  'performance',
@@ -133,23 +134,21 @@ export const DEVFLOW_PLUGINS = [
133
134
  // no companion skills, so `requires:` lists only skills this plugin's command,
134
135
  // agents and skills reference. `quality-gates` and `software-design` have no
135
136
  // reader here; the closure guard's reverse arm rejects an unread entry.
136
- requires: ['apply-decisions', 'docs-framework', 'git'],
137
+ requires: ['apply-decisions', 'git'],
137
138
  rules: [],
138
139
  },
139
140
  {
140
141
  name: 'devflow-resolve',
141
142
  description: 'Process and fix code review issues with blast-radius triage, Code agent fixes, and Validate agent verification',
142
143
  commands: ['/resolve'],
143
- agents: ['git', 'triage', 'code', 'simplify', 'validate', 'test', 'knowledge'],
144
- skills: ['patterns', 'security', 'worktree-support', 'feature-knowledge', 'apply-feature-knowledge', 'apply-decisions'],
144
+ agents: ['git', 'triage', 'code', 'code-fix', 'simplify', 'validate', 'test', 'knowledge'],
145
+ skills: ['patterns', 'worktree-support', 'feature-knowledge', 'apply-feature-knowledge', 'apply-decisions'],
145
146
  requires: [
146
147
  'architecture',
147
- 'boundary-validation',
148
148
  'complexity',
149
149
  'consistency',
150
150
  'database',
151
151
  'dependencies',
152
- 'dependency-research',
153
152
  'documentation',
154
153
  'git',
155
154
  'performance',
@@ -157,6 +156,7 @@ export const DEVFLOW_PLUGINS = [
157
156
  'regression',
158
157
  'reliability',
159
158
  'review-methodology',
159
+ 'security',
160
160
  'software-design',
161
161
  'test-driven-development',
162
162
  'testing',
@@ -167,8 +167,11 @@ export const DEVFLOW_PLUGINS = [
167
167
  name: 'devflow-debug',
168
168
  description: 'Debugging workflows with competing hypothesis investigation via parallel subagents',
169
169
  commands: ['/debug'],
170
- agents: ['git', 'synthesize', 'simplify', 'knowledge'],
170
+ agents: ['git', 'synthesize', 'simplify', 'knowledge', 'explore', 'code'],
171
171
  skills: ['git', 'worktree-support', 'feature-knowledge', 'apply-feature-knowledge'],
172
+ // D-DEBUG-FIX-VIA-CODE: the fix is a Code spawn. Code loads no skill by language or mode
173
+ // (D-NO-RUNTIME-SKILLS), so `requires:` lists only the skills this command, its agents and the
174
+ // skills they preload reference; the closure guard rejects an entry nothing reads.
172
175
  requires: [
173
176
  'apply-decisions',
174
177
  'architecture',
@@ -176,9 +179,7 @@ export const DEVFLOW_PLUGINS = [
176
179
  'consistency',
177
180
  'database',
178
181
  'dependencies',
179
- 'docs-framework',
180
182
  'documentation',
181
- 'patterns',
182
183
  'performance',
183
184
  'regression',
184
185
  'reliability',
@@ -194,23 +195,12 @@ export const DEVFLOW_PLUGINS = [
194
195
  name: 'devflow-explore',
195
196
  description: 'Codebase exploration with structured analysis and optional knowledge base creation',
196
197
  commands: ['/explore'],
197
- agents: ['skim', 'synthesize', 'knowledge'],
198
+ // 'explore' is devflow's override of Claude Code's built-in Explore agent, spawned by
199
+ // type name (D-EXPLORE-OVERRIDE and D-EXPLORE-NO-CLOBBER, targets/claude-code/agent-type-owner.ts).
200
+ agents: ['skim', 'synthesize', 'knowledge', 'explore'],
198
201
  skills: ['worktree-support', 'apply-feature-knowledge', 'feature-knowledge'],
199
202
  requires: [
200
203
  'apply-decisions',
201
- 'architecture',
202
- 'complexity',
203
- 'consistency',
204
- 'database',
205
- 'dependencies',
206
- 'docs-framework',
207
- 'documentation',
208
- 'performance',
209
- 'regression',
210
- 'reliability',
211
- 'review-methodology',
212
- 'security',
213
- 'testing',
214
204
  ],
215
205
  rules: [],
216
206
  },
@@ -220,21 +210,11 @@ export const DEVFLOW_PLUGINS = [
220
210
  commands: ['/research'],
221
211
  agents: ['research', 'skim', 'synthesize', 'knowledge'],
222
212
  skills: ['worktree-support', 'apply-feature-knowledge', 'feature-knowledge', 'research-codebase', 'research-external', 'research-market', 'research-competitor', 'research-technology'],
213
+ // `docs-framework` is read: Phase 2 loads it at the step that names the
214
+ // research directory (D-DOCS-NAMES-AUTHORITY).
223
215
  requires: [
224
216
  'apply-decisions',
225
- 'architecture',
226
- 'complexity',
227
- 'consistency',
228
- 'database',
229
- 'dependencies',
230
217
  'docs-framework',
231
- 'documentation',
232
- 'performance',
233
- 'regression',
234
- 'reliability',
235
- 'review-methodology',
236
- 'security',
237
- 'testing',
238
218
  ],
239
219
  rules: [],
240
220
  },
@@ -280,7 +260,6 @@ export const DEVFLOW_PLUGINS = [
280
260
  'architecture',
281
261
  'database',
282
262
  'dependencies',
283
- 'docs-framework',
284
263
  'documentation',
285
264
  'git',
286
265
  'performance',
@@ -293,7 +272,7 @@ export const DEVFLOW_PLUGINS = [
293
272
  name: 'devflow-ambient',
294
273
  description: 'Orchestrator ambient mode — session charter, per-prompt reminder, plan handoff',
295
274
  commands: [],
296
- agents: ['code', 'validate', 'simplify', 'scrutinize', 'evaluate', 'test', 'skim', 'review', 'git', 'synthesize', 'triage', 'design', 'knowledge', 'research', 'learning'],
275
+ agents: ['code', 'code-edit', 'validate', 'simplify', 'scrutinize', 'evaluate', 'test', 'skim', 'review', 'git', 'synthesize', 'triage', 'design', 'knowledge', 'research', 'learning', 'explore'],
297
276
  skills: [
298
277
  'review-methodology',
299
278
  'security',
@@ -317,9 +296,6 @@ export const DEVFLOW_PLUGINS = [
317
296
  ],
318
297
  requires: [
319
298
  'apply-decisions',
320
- 'boundary-validation',
321
- 'dependency-research',
322
- 'docs-framework',
323
299
  'git',
324
300
  'quality-gates',
325
301
  'research-codebase',
@@ -337,22 +313,19 @@ export const DEVFLOW_PLUGINS = [
337
313
  description: 'Dynamic workflow recipes - dependency-aware tickets→plan→build delivery pipeline',
338
314
  // Commands compiled from commands/*.mds at build time (build:mds).
339
315
  commands: ['/dynamic-tickets', '/dynamic-plan', '/dynamic-build', '/dynamic-profile'],
340
- agents: ['code', 'validate', 'simplify', 'scrutinize', 'evaluate', 'test', 'review', 'git', 'synthesize', 'knowledge', 'design'],
316
+ agents: ['code', 'code-fix', 'validate', 'simplify', 'scrutinize', 'evaluate', 'test', 'review', 'git', 'synthesize', 'knowledge', 'design'],
341
317
  skills: ['apply-decisions', 'apply-feature-knowledge', 'worktree-support', 'docs-framework'],
342
318
  requires: [
343
319
  'architecture',
344
- 'boundary-validation',
345
320
  'complexity',
346
321
  'consistency',
347
322
  'database',
348
323
  'dependencies',
349
- 'dependency-research',
350
324
  'design-review',
351
325
  'documentation',
352
326
  'feature-knowledge',
353
327
  'gap-analysis',
354
328
  'git',
355
- 'patterns',
356
329
  'performance',
357
330
  'qa',
358
331
  'quality-gates',
@@ -485,29 +458,72 @@ export const FEATURE_OWNED_SKILLS = ['compliance'];
485
458
  /**
486
459
  * Rules owned by the feature system — not any plugin in DEVFLOW_PLUGINS.
487
460
  * The compliance rule (src/assets/rules/compliance.md) is stamped and installed
488
- * by convergeComplianceArtifacts, not by the plugin installer.
461
+ * by convergeComplianceArtifacts, not by the plugin installer. The behavior rule
462
+ * (src/assets/rules/behavior.md) is installed and removed by convergeBehaviorRule.
463
+ *
464
+ * D-BEHAVIOR-OPT-IN: the behavior rule is OPT-IN and default off. How agents reply and
465
+ * act is a taste, so no install carries it until the user asks: `features.behavior` in
466
+ * the machine manifest (`devflow init --behavior`, `devflow behavior --enable`). That is
467
+ * why it sits here and in no plugin's `rules` array: a plugin's rules install for every
468
+ * install that selects the plugin, with no switch, and the core plugin is always
469
+ * selected. The rule is one bullet per behavior and stays small, because every session
470
+ * and every subagent that loads the rules pays for it; tests/rules.test.ts pins the
471
+ * shape, the length and this registration.
489
472
  *
490
473
  * Used by:
491
474
  * - rules.ts: union into allRules for shadow/unshadow/list
492
- * - tests: independent literal ['compliance'] (avoids EXCLUDED-as-oracle trap)
475
+ * - tests: independent literal ['compliance', 'behavior'] (avoids EXCLUDED-as-oracle trap)
493
476
  *
494
477
  * D-FO-2: FEATURE_OWNED_RULES must be disjoint from getAllRuleNames()
495
478
  * (guarded by plugins.test.ts FEATURE_OWNED constants describe block).
496
479
  */
497
- export const FEATURE_OWNED_RULES = ['compliance'];
480
+ export const FEATURE_OWNED_RULES = ['compliance', 'behavior'];
481
+ /**
482
+ * Skills a learning-off machine does not install.
483
+ *
484
+ * D-LEARNING-VARIANT-INSTALL: the learning-off variants of the commands and
485
+ * agents (D-LEARNING-VARIANTS) carry no decisions text and preload no
486
+ * apply-decisions, so the skill has no reader on a machine with learning off. It
487
+ * stays OWNED and REQUIRED by its plugins in the registry — the closure guard
488
+ * reasons over the learning-on variant, the superset — and the install drops it
489
+ * on top of the selection: `installViaFileCopy` skips it when `learning` is false
490
+ * and `convergeLearningVariants` installs or removes it when the switch flips.
491
+ *
492
+ * This is a machine-switch condition, not a deselection: the plan
493
+ * ({@link resolveSkillInstallPlan}) is untouched, so a learning-off machine never
494
+ * reports the skill as "removed because no selected plugin requires it" nor its
495
+ * shadow as inactive for a plugin that is not selected.
496
+ *
497
+ * Used by:
498
+ * - installer.ts installViaFileCopy: omits these from the install loop when learning is off
499
+ * - learning-install.ts convergeLearningVariants: installs or removes the directory
500
+ * - tests: independent literal ['apply-decisions'] (avoids the EXCLUDED-as-oracle trap)
501
+ */
502
+ export const LEARNING_GATED_SKILLS = ['apply-decisions'];
503
+ /**
504
+ * A skills map with the learning-gated skills left out when learning is off.
505
+ *
506
+ * Pure: the same map instance comes back when learning is on, a copy otherwise.
507
+ */
508
+ export function omitLearningGatedSkills(skillsMap, learning) {
509
+ if (learning)
510
+ return skillsMap;
511
+ const gated = LEARNING_GATED_SKILLS;
512
+ return new Map([...skillsMap].filter(([skill]) => !gated.includes(skill)));
513
+ }
498
514
  // ── Skill-closure boundaries ──────────────────────────────────────────────────
499
515
  /**
500
516
  * Skills that are REFERENCED but never REQUIRED — the presence-gated set.
501
517
  *
502
518
  * D-PRESENCE-GATED: every language/ecosystem skill ships with an optional,
503
519
  * command-less plugin, so a reference to one is a reference to something the
504
- * user may deliberately not have. The referencing prompts are written to probe
505
- * first and proceed without it — `/code-review` checks
506
- * `skills/devflow:{focus}/SKILL.md` under Claude Code's directory (`CLAUDE_CONFIG_DIR`
507
- * when absolute, else `~/.claude` — D-CLAUDE-DIR-PROMPTS) before spawning that focus, the
508
- * Review and Code agents continue when the Skill invocation fails. Putting them
509
- * in a `requires` would reinstate the universal install for exactly the eight
510
- * skills the selection prompt exists to let a user decline (AC-25).
520
+ * user may deliberately not have. The referencing prompts are written to
521
+ * proceed without it: `/code-review` spawns a language focus only when the
522
+ * installer stamped it into the command (D-LANGUAGE-FOCUS-STAMP,
523
+ * {@link installedLanguageFocuses}), and the Review agent continues when the
524
+ * Skill invocation fails. Putting them in a `requires` would reinstate
525
+ * the universal install for exactly the eight skills the selection prompt
526
+ * exists to let a user decline (AC-25).
511
527
  *
512
528
  * DERIVED from the registry rather than hand-listed: a ninth language plugin is
513
529
  * presence-gated by being declared, with no second roster to remember. Guarded
@@ -545,7 +561,7 @@ export const TEMPLATE_SKILL_REFS = [
545
561
  },
546
562
  {
547
563
  literal: 'devflow:{FOCUS}',
548
- site: 'src/assets/agents/review.md (the Review agent loading its own focus skill)',
564
+ site: 'src/assets/agents/review.mds (the Review agent loading its own focus skill)',
549
565
  why: 'receiving half of the same substitution — the agent is told which focus it is, not which skill exists',
550
566
  },
551
567
  ];
@@ -733,6 +749,29 @@ export function buildScopedSkillsMap(plugins) {
733
749
  }
734
750
  return skillsMap;
735
751
  }
752
+ /**
753
+ * The language focuses an install selection makes available — the list the
754
+ * installer stamps into the installed /code-review command.
755
+ *
756
+ * D-LANGUAGE-FOCUS-STAMP: the language gate moved from a run-time `test -f`
757
+ * probe of Claude Code's directory to this list, computed once at install time.
758
+ * Pure plumbing and nothing more: the registry's {@link PRESENCE_GATED_SKILLS}
759
+ * filtered to the skills the selection's closure installs
760
+ * ({@link buildScopedSkillsMap}), in registry order. Which focuses a diff gets
761
+ * stays a prompt rule that the orchestrator executes; no code here, or anywhere
762
+ * in the installer, classifies a diff or chooses a focus.
763
+ *
764
+ * The selection is the EFFECTIVE one (`FileCopyOptions.effectivePlugins`), never
765
+ * the plugins one run copies: `--plugin=X` installs X alone while the machine's
766
+ * selection is the manifest's plugins plus X, and the stamp has to describe what
767
+ * is on disk. Selective uninstall passes the plugins that remain.
768
+ *
769
+ * @param effectivePlugins - The plugins whose skill closure is, or stays, installed.
770
+ */
771
+ export function installedLanguageFocuses(effectivePlugins) {
772
+ const installed = buildScopedSkillsMap(effectivePlugins);
773
+ return PRESENCE_GATED_SKILLS.filter(skill => installed.has(skill));
774
+ }
736
775
  /**
737
776
  * Build a skills map over the WHOLE registry.
738
777
  *
@@ -131,8 +131,4 @@ export function getDesignDir(projectRoot) {
131
131
  export function getResearchDir(projectRoot) {
132
132
  return path.join(projectRoot, '.devflow', 'docs', 'research');
133
133
  }
134
- /** .devflow/docs/handoff-{branchSlug}.md — Code agent phase handoff artifact */
135
- export function getHandoffPath(projectRoot, branchSlug) {
136
- return path.join(projectRoot, '.devflow', 'docs', `handoff-${branchSlug}.md`);
137
- }
138
134
  //# sourceMappingURL=project-paths.js.map
@@ -34,7 +34,7 @@ export const PROXY_LOG_TAIL_BYTES = 1_048_576;
34
34
  * XDG_CONFIG_HOME (user-config lookup, reached only on an implicit config load —
35
35
  * see D-EFR-6 in model-discovery.ts). CI is read only by `init`; CODEX_HOME and
36
36
  * CLAUDE_CONFIG_DIR only by the Codex ingress, `init` and the Codex doctor, none of
37
- * which devflow enables or invokes. Verified by whole-dist grep of the 0.5.0
37
+ * which devflow enables or invokes. Verified by whole-dist grep of the 0.6.0
38
38
  * package. An allowlist is the correct shape: 61 inherited vars → 6.
39
39
  *
40
40
  * HOME is retained: the runtime's loadConfig resolves ~ paths via homedir().
@@ -91,7 +91,7 @@ export async function writeProxyState(devflowDir, state) {
91
91
  * Top-level keys devflow carries into the routing config. Unknown top-level keys
92
92
  * cause a hard relay startup error — never emit them.
93
93
  *
94
- * @D-EFR-4 Subswitch 0.5.0 routing config contract:
94
+ * @D-EFR-4 Subswitch 0.6.0 routing config contract:
95
95
  * FileConfigSchema is a z.strictObject with exactly 6 accepted top-level keys:
96
96
  * port, logLevel, anthropic, providers, limits, codexIngress. Unknown keys cause a
97
97
  * hard startup error — the relay refuses to start. anthropic and limits are
@@ -60,6 +60,44 @@ export const TRACKER_PROVIDER_IDS = TRACKER_PROVIDERS.map(p => p.id);
60
60
  */
61
61
  export const DEFAULT_TRACKER_PROVIDER = 'github';
62
62
  // ---------------------------------------------------------------------------
63
+ // Tracker tool servers — the allowlist half of the Git and Tracker agents
64
+ // ---------------------------------------------------------------------------
65
+ /**
66
+ * D-TRACKER-SERVER-ALLOWLIST: the Git and Tracker agents hold a tool ALLOWLIST, and the
67
+ * tracker tool servers a user has connected differ per machine, so the shipped allowlist
68
+ * names no server (the agent sources stay vendor-neutral). The installer stamps one
69
+ * whole-server entry per name below onto the INSTALLED `tools:` line of those two agents
70
+ * (`stampAgentTools`, src/core/agent-frontmatter.ts), after the file is copied. Claude Code
71
+ * has no pattern form for an allowlist entry, so a server is granted by its name; a name
72
+ * that matches no connected server is inert (it grants nothing and blocks nothing).
73
+ *
74
+ * The default is one FLAT list, stamped whatever the provider: every install carries every
75
+ * provider, and a repository may select a provider other than the machine's, so a list
76
+ * keyed on the machine's provider would strand that repository. A server the user runs
77
+ * under another name is added with `devflow tracker --servers`. A wrong or missing name
78
+ * does not fail silently: the agent finds no tool for the capability it needs and reports
79
+ * `TRACEABILITY: DEGRADED (no tracker tool for {capability})`.
80
+ *
81
+ * The default leaves `github` out. Under the github provider the Git agent uses `gh` and
82
+ * never reads `_mcp.md`, so a stamped `github` server is never used by a tracker operation;
83
+ * under jira or linear, a connected GitHub server that also advertises issue creation would
84
+ * make the `_mcp.md` capability selection ambiguous, which is a degraded run. A user who
85
+ * wants it adds it with `devflow tracker --servers`.
86
+ */
87
+ export const TRACKER_MCP_SERVERS_DEFAULT = Object.freeze([
88
+ 'atlassian',
89
+ 'jira',
90
+ 'claude_ai_Atlassian',
91
+ 'linear',
92
+ 'claude_ai_Linear',
93
+ ]);
94
+ /** A server name as a user may configure it. Byte-exact, like a provider token. */
95
+ export const TRACKER_SERVER_NAME_RE = /^[A-Za-z0-9_-]{1,64}$/;
96
+ /** The most servers one list may hold; every entry lands in a prompt-adjacent frontmatter line. */
97
+ export const TRACKER_SERVERS_MAX = 32;
98
+ /** The reserved word that returns the setting to {@link TRACKER_MCP_SERVERS_DEFAULT}. */
99
+ export const TRACKER_SERVERS_DEFAULT_WORD = 'default';
100
+ // ---------------------------------------------------------------------------
63
101
  // Artifact basenames — one spelling for every TypeScript reader
64
102
  //
65
103
  // NOT the only spelling in the repository, and a rename that assumes it is will
@@ -238,6 +276,72 @@ export function parseTrackerId(input) {
238
276
  }
239
277
  return { ok: true, value: input };
240
278
  }
279
+ /**
280
+ * Validate a list of tracker server names. The one rule set behind both the CLI argument
281
+ * and the manifest field.
282
+ *
283
+ * REJECT, NEVER REPAIR (as {@link parseTrackerId}): a name is accepted byte-exact against
284
+ * {@link TRACKER_SERVER_NAME_RE} and must not hold `__`, which is what separates a server
285
+ * from its tool in an entry such as `mcp__server__tool`. No trim, no case folding, no
286
+ * alias. Exact duplicates collapse to the first occurrence and the order is kept. The list
287
+ * is non-empty and holds at most {@link TRACKER_SERVERS_MAX} distinct names.
288
+ */
289
+ export function validateTrackerServers(raw) {
290
+ if (raw.length === 0) {
291
+ return { ok: false, error: 'No tracker servers given. Pass one or more server names, or "default".' };
292
+ }
293
+ const seen = new Set();
294
+ for (const entry of raw) {
295
+ if (typeof entry !== 'string' || !TRACKER_SERVER_NAME_RE.test(entry)) {
296
+ return {
297
+ ok: false,
298
+ error: `Invalid tracker server name: "${describeTrackerValue(entry)}". ` +
299
+ 'Names are 1-64 characters from A-Z, a-z, 0-9, "_" and "-".',
300
+ };
301
+ }
302
+ if (entry.includes('__')) {
303
+ return {
304
+ ok: false,
305
+ error: `Invalid tracker server name: "${describeTrackerValue(entry)}". ` +
306
+ 'A name must not contain "__" (it separates a server from its tool).',
307
+ };
308
+ }
309
+ seen.add(entry);
310
+ }
311
+ if (seen.size > TRACKER_SERVERS_MAX) {
312
+ return { ok: false, error: `Too many tracker servers: ${seen.size} (at most ${TRACKER_SERVERS_MAX}).` };
313
+ }
314
+ return { ok: true, value: [...seen] };
315
+ }
316
+ /**
317
+ * Strict boundary parser for `devflow tracker --servers <list>`.
318
+ *
319
+ * `default` alone selects {@link TRACKER_MCP_SERVERS_DEFAULT}; anything else is a
320
+ * comma-separated list of names handed to {@link validateTrackerServers} unchanged. An
321
+ * empty argument, an empty item (`a,,b`, a trailing comma) and the reserved word inside a
322
+ * list are errors, never silently dropped.
323
+ */
324
+ export function parseTrackerServers(input) {
325
+ if (input === '') {
326
+ return { ok: false, error: 'Missing tracker servers. Pass a comma-separated list of names, or "default".' };
327
+ }
328
+ if (input === TRACKER_SERVERS_DEFAULT_WORD)
329
+ return { ok: true, value: { kind: 'default' } };
330
+ const items = input.split(',');
331
+ if (items.includes(TRACKER_SERVERS_DEFAULT_WORD)) {
332
+ return { ok: false, error: `"${TRACKER_SERVERS_DEFAULT_WORD}" is reserved: pass it alone, not inside a list.` };
333
+ }
334
+ const validated = validateTrackerServers(items);
335
+ return validated.ok ? { ok: true, value: { kind: 'list', servers: validated.value } } : validated;
336
+ }
337
+ /** The servers in force for `state`: its own list, else the default. */
338
+ export function effectiveTrackerServers(state) {
339
+ return state.servers ?? TRACKER_MCP_SERVERS_DEFAULT;
340
+ }
341
+ /** The whole-server allowlist entries for `servers`, in order: `github` becomes `mcp__github`. */
342
+ export function trackerServerTools(servers) {
343
+ return servers.map(name => `mcp__${name}`);
344
+ }
241
345
  /**
242
346
  * Tolerant sink normaliser for a raw `manifest.features.tracker` value.
243
347
  *
@@ -249,9 +353,11 @@ export function parseTrackerId(input) {
249
353
  * D-TRACKER-SELF-HEAL [DR-26]: self-healing here is SILENT and emits no
250
354
  * DEGRADED — that is the correct self-heal behaviour, and it is a different
251
355
  * condition from a per-repo config value outside the domain (which does emit
252
- * `unknown tracker provider`). The two must not be conflated.
356
+ * `unknown tracker provider`). The two must not be conflated. The one exception is
357
+ * `servers` (see the body): a present but invalid list heals to the default AND reaches
358
+ * `onWarning` when a caller supplies one, because the user wrote that list on purpose.
253
359
  */
254
- export function normalizeTrackerFeature(raw) {
360
+ export function normalizeTrackerFeature(raw, onWarning) {
255
361
  const DEFAULT = { provider: DEFAULT_TRACKER_PROVIDER };
256
362
  if (raw === null || raw === undefined || typeof raw !== 'object' || Array.isArray(raw)) {
257
363
  return DEFAULT;
@@ -259,6 +365,18 @@ export function normalizeTrackerFeature(raw) {
259
365
  const obj = raw;
260
366
  if (!isTrackerProvider(obj.provider))
261
367
  return DEFAULT;
368
+ // `servers`: absent is the default, silently. A present value that is not a valid list is
369
+ // dropped WHOLE (never trimmed to its valid names) and reported through `onWarning`, which a
370
+ // caller with a terminal passes; the reader itself has no output channel. The state then
371
+ // reads as the default list, and the next `devflow tracker --servers` or `devflow init`
372
+ // writes the manifest without the bad value.
373
+ if (obj.servers === undefined)
374
+ return { provider: obj.provider };
375
+ const servers = Array.isArray(obj.servers) ? validateTrackerServers(obj.servers) : undefined;
376
+ if (servers?.ok === true)
377
+ return { provider: obj.provider, servers: servers.value };
378
+ onWarning?.(`The manifest's tracker servers setting is not a valid list (${servers?.ok === false ? servers.error : 'not a list'}); ` +
379
+ 'using the default. Run `devflow tracker --servers <names>` to set it, or `devflow tracker --servers default`.');
262
380
  return { provider: obj.provider };
263
381
  }
264
382
  // ---------------------------------------------------------------------------