devflow-kit 2.4.0 → 3.0.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 (213) hide show
  1. package/CHANGELOG.md +229 -0
  2. package/README.md +111 -18
  3. package/dist/agents/git.md +822 -0
  4. package/dist/cli/commands/agents.js +6 -1
  5. package/dist/cli/commands/ambient.js +160 -145
  6. package/dist/cli/commands/attribution-prompts.js +1 -1
  7. package/dist/cli/commands/capture.js +29 -55
  8. package/dist/cli/commands/compliance-prompts.js +1 -1
  9. package/dist/cli/commands/compliance.js +48 -55
  10. package/dist/cli/commands/context.js +17 -32
  11. package/dist/cli/commands/debug.js +65 -26
  12. package/dist/cli/commands/flags.js +3 -3
  13. package/dist/cli/commands/hud.js +34 -10
  14. package/dist/cli/commands/init-seed.js +61 -27
  15. package/dist/cli/commands/init.js +649 -240
  16. package/dist/cli/commands/install-report.js +200 -0
  17. package/dist/cli/commands/knowledge/index.js +2 -2
  18. package/dist/cli/commands/knowledge/toggle.js +35 -37
  19. package/dist/cli/commands/learning.js +79 -57
  20. package/dist/cli/commands/legacy-hooks.js +11 -14
  21. package/dist/cli/commands/memory.js +134 -135
  22. package/dist/cli/commands/prompt-io.js +4 -4
  23. package/dist/cli/commands/proxy.js +23 -41
  24. package/dist/cli/commands/security.js +81 -29
  25. package/dist/cli/commands/skills.js +71 -7
  26. package/dist/cli/commands/tracker-prompts.js +145 -0
  27. package/dist/cli/commands/tracker.js +277 -0
  28. package/dist/cli/commands/uninstall.js +520 -169
  29. package/dist/cli.js +2 -0
  30. package/dist/commands/bug-analysis.md +58 -14
  31. package/dist/commands/code-review.md +110 -32
  32. package/dist/commands/debug.md +55 -11
  33. package/dist/commands/dynamic-build.md +344 -73
  34. package/dist/commands/dynamic-plan.md +77 -27
  35. package/dist/commands/dynamic-profile.md +25 -11
  36. package/dist/commands/dynamic-tickets.md +76 -15
  37. package/dist/commands/explore.md +37 -7
  38. package/dist/commands/implement.md +314 -62
  39. package/dist/commands/plan.md +146 -32
  40. package/dist/commands/release.md +64 -17
  41. package/dist/commands/research.md +34 -8
  42. package/dist/commands/resolve.md +196 -68
  43. package/dist/commands/self-review.md +45 -9
  44. package/dist/core/agent-models.js +55 -12
  45. package/dist/core/assets.js +58 -2
  46. package/dist/core/compliance-compose.js +27 -27
  47. package/dist/core/evidence-policy.js +363 -0
  48. package/dist/core/feature-config.js +200 -65
  49. package/dist/core/feature-switch.js +112 -0
  50. package/dist/core/flags.js +34 -6
  51. package/dist/core/fs-atomic.js +27 -0
  52. package/dist/core/hook-log-dirs.js +104 -0
  53. package/dist/core/learning-tuning-config.js +5 -3
  54. package/dist/core/ledger-root.js +102 -0
  55. package/dist/core/manifest.js +38 -10
  56. package/dist/core/mds-variants.js +798 -0
  57. package/dist/core/migrations.js +49 -23
  58. package/dist/core/model-discovery.js +12 -1
  59. package/dist/core/plugins.js +361 -12
  60. package/dist/core/project-paths.js +1 -18
  61. package/dist/core/proxy-log.js +8 -6
  62. package/dist/core/proxy-state.js +11 -8
  63. package/dist/core/reference-sweep.js +136 -0
  64. package/dist/core/same-location.js +25 -0
  65. package/dist/core/tracker.js +494 -0
  66. package/dist/hud/components/config-counts.js +15 -4
  67. package/dist/hud/components/learning-counts.js +14 -0
  68. package/dist/hud/config.js +2 -1
  69. package/dist/hud/cost-history.js +2 -4
  70. package/dist/hud/git.js +52 -7
  71. package/dist/hud/index.js +7 -9
  72. package/dist/skills/git/references/decision-markers.md +19 -0
  73. package/dist/skills/git/references/learn-conventions.md +56 -0
  74. package/dist/skills/git/references/pr/check-ci-status.md +14 -0
  75. package/dist/skills/git/references/pr/check-merge-readiness.md +28 -0
  76. package/dist/skills/git/references/pr/ensure-pr-ready.md +24 -0
  77. package/dist/skills/git/references/pr/fetch-review-threads.md +22 -0
  78. package/dist/skills/git/references/pr/post-resolution-summary.md +40 -0
  79. package/dist/skills/git/references/pr/post-review-summary.md +42 -0
  80. package/dist/skills/git/references/pr/resolve-review-threads.md +35 -0
  81. package/dist/skills/git/references/pr/update-pr-evidence.md +14 -0
  82. package/dist/skills/git/references/pr/validate-branch.md +18 -0
  83. package/dist/skills/git/references/publication-gate.md +13 -0
  84. package/dist/skills/git/references/tracker/_mcp.md +153 -0
  85. package/dist/skills/git/references/tracker/github/associate-release.md +18 -0
  86. package/dist/skills/git/references/tracker/github/backlink-shipped-issues.md +40 -0
  87. package/dist/skills/git/references/tracker/github/create-release.md +11 -0
  88. package/dist/skills/git/references/tracker/github/ensure-pr-ready.md +16 -0
  89. package/dist/skills/git/references/tracker/github/ensure-traceable-issue.md +69 -0
  90. package/dist/skills/git/references/tracker/github/fetch-issue.md +32 -0
  91. package/dist/skills/git/references/tracker/github/fetch-issues-batch.md +17 -0
  92. package/dist/skills/git/references/tracker/github/gather-release-evidence.md +19 -0
  93. package/dist/skills/git/references/tracker/github/manage-debt.md +101 -0
  94. package/dist/skills/git/references/tracker/github/post-wave-report.md +28 -0
  95. package/dist/skills/git/references/tracker/github/setup-task.md +26 -0
  96. package/dist/skills/git/references/tracker/jira/associate-release.md +18 -0
  97. package/dist/skills/git/references/tracker/jira/backlink-shipped-issues.md +49 -0
  98. package/dist/skills/git/references/tracker/jira/create-release.md +17 -0
  99. package/dist/skills/git/references/tracker/jira/ensure-pr-ready.md +22 -0
  100. package/dist/skills/git/references/tracker/jira/ensure-traceable-issue.md +53 -0
  101. package/dist/skills/git/references/tracker/jira/fetch-issue.md +14 -0
  102. package/dist/skills/git/references/tracker/jira/fetch-issues-batch.md +15 -0
  103. package/dist/skills/git/references/tracker/jira/gather-release-evidence.md +18 -0
  104. package/dist/skills/git/references/tracker/jira/manage-debt.md +37 -0
  105. package/dist/skills/git/references/tracker/jira/post-wave-report.md +33 -0
  106. package/dist/skills/git/references/tracker/jira/setup-task.md +31 -0
  107. package/dist/skills/git/references/tracker/linear/associate-release.md +18 -0
  108. package/dist/skills/git/references/tracker/linear/backlink-shipped-issues.md +53 -0
  109. package/dist/skills/git/references/tracker/linear/create-release.md +17 -0
  110. package/dist/skills/git/references/tracker/linear/ensure-pr-ready.md +22 -0
  111. package/dist/skills/git/references/tracker/linear/ensure-traceable-issue.md +53 -0
  112. package/dist/skills/git/references/tracker/linear/fetch-issue.md +14 -0
  113. package/dist/skills/git/references/tracker/linear/fetch-issues-batch.md +15 -0
  114. package/dist/skills/git/references/tracker/linear/gather-release-evidence.md +18 -0
  115. package/dist/skills/git/references/tracker/linear/manage-debt.md +37 -0
  116. package/dist/skills/git/references/tracker/linear/post-wave-report.md +33 -0
  117. package/dist/skills/git/references/tracker/linear/setup-task.md +32 -0
  118. package/dist/skills/git/references/trust-rule.md +7 -0
  119. package/dist/targets/claude-code/claude-paths.js +59 -57
  120. package/dist/targets/claude-code/compliance-install.js +49 -65
  121. package/dist/targets/claude-code/hooks.js +108 -3
  122. package/dist/targets/claude-code/installer.js +1187 -32
  123. package/dist/targets/claude-code/legacy.js +5 -0
  124. package/dist/targets/claude-code/post-install.js +366 -151
  125. package/dist/targets/claude-code/tracker-install.js +134 -0
  126. package/package.json +8 -6
  127. package/src/assets/agents/code.md +45 -6
  128. package/src/assets/agents/design.md +2 -1
  129. package/src/assets/agents/git.mds +825 -0
  130. package/src/assets/agents/knowledge.md +3 -3
  131. package/src/assets/agents/learning.md +11 -0
  132. package/src/assets/agents/review.md +3 -1
  133. package/src/assets/agents/synthesize.md +1 -1
  134. package/src/assets/agents/test.md +16 -5
  135. package/src/assets/agents/tracker.md +474 -0
  136. package/src/assets/agents/validate.md +7 -5
  137. package/src/assets/commands/_partials/_compliance.mds +19 -1
  138. package/src/assets/commands/_partials/_decisions.mds +15 -3
  139. package/src/assets/commands/_partials/_docs_root.mds +35 -0
  140. package/src/assets/commands/_partials/_engine.mds +13 -11
  141. package/src/assets/commands/_partials/_evidence_policy.mds +30 -0
  142. package/src/assets/commands/_partials/_factory.mds +1 -1
  143. package/src/assets/commands/_partials/_knowledge.mds +27 -9
  144. package/src/assets/commands/_partials/_plan_contract.mds +22 -7
  145. package/src/assets/commands/_partials/_preamble.mds +2 -2
  146. package/src/assets/commands/_partials/_publication.mds +8 -2
  147. package/src/assets/commands/_partials/_settings.mds +28 -0
  148. package/src/assets/commands/_partials/_ticket_template.mds +3 -2
  149. package/src/assets/commands/_partials/_tracker.mds +18 -0
  150. package/src/assets/commands/_partials/_wave.mds +16 -10
  151. package/src/assets/commands/bug-analysis.mds +31 -19
  152. package/src/assets/commands/code-review.mds +67 -41
  153. package/src/assets/commands/debug.mds +13 -7
  154. package/src/assets/commands/dynamic-build.mds +274 -66
  155. package/src/assets/commands/dynamic-plan.mds +50 -23
  156. package/src/assets/commands/dynamic-profile.mds +24 -11
  157. package/src/assets/commands/dynamic-tickets.mds +63 -16
  158. package/src/assets/commands/explore.mds +4 -5
  159. package/src/assets/commands/implement.mds +234 -67
  160. package/src/assets/commands/plan.mds +91 -33
  161. package/src/assets/commands/release.md +64 -17
  162. package/src/assets/commands/research.mds +11 -9
  163. package/src/assets/commands/resolve.mds +150 -78
  164. package/src/assets/commands/self-review.mds +24 -25
  165. package/src/assets/mds/git/_pr.mds +331 -0
  166. package/src/assets/mds/git/_references.mds +135 -0
  167. package/src/assets/mds/tracker/_common.mds +156 -0
  168. package/src/assets/mds/tracker/_github.mds +472 -0
  169. package/src/assets/mds/tracker/_jira.mds +407 -0
  170. package/src/assets/mds/tracker/_linear.mds +449 -0
  171. package/src/assets/mds/tracker/_mcp.mds +305 -0
  172. package/src/assets/scripts/hooks/assets/orchestrator-charter.md +5 -8
  173. package/src/assets/scripts/hooks/background-memory-update +40 -19
  174. package/src/assets/scripts/hooks/capture-prompt +18 -8
  175. package/src/assets/scripts/hooks/capture-question +18 -8
  176. package/src/assets/scripts/hooks/capture-turn +27 -13
  177. package/src/assets/scripts/hooks/debug-trace +11 -6
  178. package/src/assets/scripts/hooks/ensure-devflow-init +33 -6
  179. package/src/assets/scripts/hooks/ensure-proxy +9 -8
  180. package/src/assets/scripts/hooks/ensure-root-gitignore +236 -60
  181. package/src/assets/scripts/hooks/git-marker +48 -0
  182. package/src/assets/scripts/hooks/hook-log-init +3 -1
  183. package/src/assets/scripts/hooks/json-helper.cjs +228 -5
  184. package/src/assets/scripts/hooks/lib/project-paths.cjs +1 -20
  185. package/src/assets/scripts/hooks/log-paths +80 -0
  186. package/src/assets/scripts/hooks/memory-worker +22 -13
  187. package/src/assets/scripts/hooks/pre-compact-memory +44 -15
  188. package/src/assets/scripts/hooks/preamble +1 -4
  189. package/src/assets/scripts/hooks/queue-append +146 -28
  190. package/src/assets/scripts/hooks/resolve-project-root +101 -7
  191. package/src/assets/scripts/hooks/session-start-context +534 -20
  192. package/src/assets/scripts/hooks/session-start-memory +38 -15
  193. package/src/assets/scripts/lib/project-config.cjs +633 -0
  194. package/src/assets/scripts/pr-evidence.cjs +1961 -0
  195. package/src/assets/scripts/redact-secrets.cjs +490 -62
  196. package/src/assets/scripts/release-trace.cjs +1143 -0
  197. package/src/assets/scripts/resolve-evidence-policy.cjs +1145 -0
  198. package/src/assets/scripts/resolve-settings.cjs +1054 -0
  199. package/src/assets/scripts/verify-evidence.cjs +1822 -0
  200. package/src/assets/skills/compliance/SKILL.md +4 -2
  201. package/src/assets/skills/docs-framework/SKILL.md +11 -10
  202. package/src/assets/skills/docs-framework/references/patterns.md +10 -17
  203. package/src/assets/skills/gap-analysis/SKILL.md +2 -2
  204. package/src/assets/skills/git/SKILL.md +8 -78
  205. package/src/assets/skills/git/references/github-api.md +179 -141
  206. package/src/assets/skills/git/references/patterns.md +11 -6
  207. package/src/assets/skills/review-methodology/SKILL.md +1 -1
  208. package/src/assets/skills/review-methodology/references/patterns.md +6 -61
  209. package/src/assets/skills/review-methodology/references/violations.md +14 -22
  210. package/src/assets/skills/worktree-support/SKILL.md +1 -1
  211. package/src/assets/skills/worktree-support/references/roots.md +29 -0
  212. package/src/targets/claude-code/templates/managed-settings.json +25 -9
  213. package/src/assets/agents/git.md +0 -938
@@ -29,8 +29,41 @@ export const DEVFLOW_PLUGINS = [
29
29
  name: 'devflow-core-skills',
30
30
  description: 'Auto-activating quality enforcement skills - foundation layer for all Devflow plugins',
31
31
  commands: [],
32
- agents: ['learning'],
32
+ /**
33
+ * Hook-spawned agents live here, and `commands: []` above is why that works.
34
+ *
35
+ * Guard 5 reverse (registry-integrity.test.ts, "declared agents are spawned")
36
+ * skips a plugin whose commands spawn nothing — `if (spawned.size === 0)
37
+ * continue` — and this plugin ships no commands at all. So `learning` and
38
+ * `tracker`, which are spawned by a SessionStart directive rather than by any
39
+ * command, satisfy the reverse check STRUCTURALLY.
40
+ *
41
+ * Recorded because the alternative looks equivalent and is not: adding either
42
+ * name to an exemption list would make the guard pass by being told to ignore
43
+ * them, which is the vacuous-guard trap this repo polices everywhere else. If
44
+ * this plugin ever gains a command, the right fix is a new commands-less
45
+ * plugin for the hook-spawned agents — never an exemption.
46
+ *
47
+ * Neither agent may gain a `_roster.mds` row: that file is asserted
48
+ * set-equal, both directions, against the `agentType` values present in
49
+ * dist/commands/, and a hook-spawned agent appears in none of them.
50
+ */
51
+ agents: ['learning', 'tracker'],
33
52
  skills: ['apply-decisions', 'apply-feature-knowledge', 'software-design', 'docs-framework', 'git', 'boundary-validation', 'test-driven-development', 'testing', 'dependency-research'],
53
+ requires: [
54
+ 'architecture',
55
+ 'complexity',
56
+ 'consistency',
57
+ 'database',
58
+ 'dependencies',
59
+ 'documentation',
60
+ 'performance',
61
+ 'regression',
62
+ 'reliability',
63
+ 'review-methodology',
64
+ 'security',
65
+ 'worktree-support',
66
+ ],
34
67
  rules: ['security', 'engineering', 'quality', 'reliability'],
35
68
  },
36
69
  {
@@ -39,6 +72,25 @@ export const DEVFLOW_PLUGINS = [
39
72
  commands: ['/plan'],
40
73
  agents: ['git', 'skim', 'synthesize', 'design'],
41
74
  skills: ['gap-analysis', 'design-review', 'patterns', 'worktree-support', 'feature-knowledge', 'apply-feature-knowledge'],
75
+ requires: [
76
+ 'apply-decisions',
77
+ 'architecture',
78
+ 'complexity',
79
+ 'consistency',
80
+ 'database',
81
+ 'dependencies',
82
+ 'docs-framework',
83
+ 'documentation',
84
+ 'git',
85
+ 'performance',
86
+ 'regression',
87
+ 'reliability',
88
+ 'review-methodology',
89
+ 'security',
90
+ 'software-design',
91
+ 'test-driven-development',
92
+ 'testing',
93
+ ],
42
94
  rules: [],
43
95
  },
44
96
  {
@@ -47,6 +99,26 @@ export const DEVFLOW_PLUGINS = [
47
99
  commands: ['/implement'],
48
100
  agents: ['git', 'code', 'simplify', 'scrutinize', 'evaluate', 'test', 'validate', 'knowledge'],
49
101
  skills: ['patterns', 'qa', 'quality-gates', 'worktree-support', 'feature-knowledge', 'apply-feature-knowledge'],
102
+ requires: [
103
+ 'apply-decisions',
104
+ 'architecture',
105
+ 'boundary-validation',
106
+ 'complexity',
107
+ 'consistency',
108
+ 'database',
109
+ 'dependencies',
110
+ 'dependency-research',
111
+ 'documentation',
112
+ 'git',
113
+ 'performance',
114
+ 'regression',
115
+ 'reliability',
116
+ 'review-methodology',
117
+ 'security',
118
+ 'software-design',
119
+ 'test-driven-development',
120
+ 'testing',
121
+ ],
50
122
  rules: [],
51
123
  },
52
124
  {
@@ -55,14 +127,34 @@ export const DEVFLOW_PLUGINS = [
55
127
  commands: ['/code-review'],
56
128
  agents: ['git', 'review', 'synthesize'],
57
129
  skills: ['architecture', 'complexity', 'consistency', 'database', 'dependencies', 'documentation', 'performance', 'regression', 'reliability', 'review-methodology', 'security', 'testing', 'worktree-support', 'apply-feature-knowledge'],
130
+ requires: ['apply-decisions', 'docs-framework', 'git', 'quality-gates', 'software-design'],
58
131
  rules: [],
59
132
  },
60
133
  {
61
134
  name: 'devflow-resolve',
62
135
  description: 'Process and fix code review issues with blast-radius triage, Code agent fixes, and Validate agent verification',
63
136
  commands: ['/resolve'],
64
- agents: ['git', 'triage', 'code', 'simplify', 'validate', 'knowledge'],
137
+ agents: ['git', 'triage', 'code', 'simplify', 'validate', 'test', 'knowledge'],
65
138
  skills: ['patterns', 'security', 'worktree-support', 'feature-knowledge', 'apply-feature-knowledge', 'apply-decisions'],
139
+ requires: [
140
+ 'architecture',
141
+ 'boundary-validation',
142
+ 'complexity',
143
+ 'consistency',
144
+ 'database',
145
+ 'dependencies',
146
+ 'dependency-research',
147
+ 'documentation',
148
+ 'git',
149
+ 'performance',
150
+ 'qa',
151
+ 'regression',
152
+ 'reliability',
153
+ 'review-methodology',
154
+ 'software-design',
155
+ 'test-driven-development',
156
+ 'testing',
157
+ ],
66
158
  rules: [],
67
159
  },
68
160
  {
@@ -71,6 +163,25 @@ export const DEVFLOW_PLUGINS = [
71
163
  commands: ['/debug'],
72
164
  agents: ['git', 'synthesize', 'simplify', 'knowledge'],
73
165
  skills: ['git', 'worktree-support', 'feature-knowledge', 'apply-feature-knowledge'],
166
+ requires: [
167
+ 'apply-decisions',
168
+ 'architecture',
169
+ 'complexity',
170
+ 'consistency',
171
+ 'database',
172
+ 'dependencies',
173
+ 'docs-framework',
174
+ 'documentation',
175
+ 'patterns',
176
+ 'performance',
177
+ 'regression',
178
+ 'reliability',
179
+ 'review-methodology',
180
+ 'security',
181
+ 'software-design',
182
+ 'test-driven-development',
183
+ 'testing',
184
+ ],
74
185
  rules: [],
75
186
  },
76
187
  {
@@ -79,6 +190,22 @@ export const DEVFLOW_PLUGINS = [
79
190
  commands: ['/explore'],
80
191
  agents: ['skim', 'synthesize', 'knowledge'],
81
192
  skills: ['worktree-support', 'apply-feature-knowledge', 'feature-knowledge'],
193
+ requires: [
194
+ 'apply-decisions',
195
+ 'architecture',
196
+ 'complexity',
197
+ 'consistency',
198
+ 'database',
199
+ 'dependencies',
200
+ 'docs-framework',
201
+ 'documentation',
202
+ 'performance',
203
+ 'regression',
204
+ 'reliability',
205
+ 'review-methodology',
206
+ 'security',
207
+ 'testing',
208
+ ],
82
209
  rules: [],
83
210
  },
84
211
  {
@@ -87,6 +214,22 @@ export const DEVFLOW_PLUGINS = [
87
214
  commands: ['/research'],
88
215
  agents: ['research', 'skim', 'synthesize', 'knowledge'],
89
216
  skills: ['worktree-support', 'apply-feature-knowledge', 'feature-knowledge', 'research-codebase', 'research-external', 'research-market', 'research-competitor', 'research-technology'],
217
+ requires: [
218
+ 'apply-decisions',
219
+ 'architecture',
220
+ 'complexity',
221
+ 'consistency',
222
+ 'database',
223
+ 'dependencies',
224
+ 'docs-framework',
225
+ 'documentation',
226
+ 'performance',
227
+ 'regression',
228
+ 'reliability',
229
+ 'review-methodology',
230
+ 'security',
231
+ 'testing',
232
+ ],
90
233
  rules: [],
91
234
  },
92
235
  {
@@ -95,6 +238,7 @@ export const DEVFLOW_PLUGINS = [
95
238
  commands: ['/release'],
96
239
  agents: ['git', 'validate'],
97
240
  skills: ['git', 'worktree-support'],
241
+ requires: ['testing'],
98
242
  rules: [],
99
243
  },
100
244
  {
@@ -103,6 +247,7 @@ export const DEVFLOW_PLUGINS = [
103
247
  commands: ['/self-review'],
104
248
  agents: ['simplify', 'scrutinize', 'validate', 'knowledge'],
105
249
  skills: ['quality-gates', 'software-design', 'worktree-support', 'feature-knowledge', 'apply-feature-knowledge'],
250
+ requires: ['apply-decisions', 'testing'],
106
251
  rules: [],
107
252
  },
108
253
  {
@@ -120,6 +265,17 @@ export const DEVFLOW_PLUGINS = [
120
265
  'security',
121
266
  'worktree-support',
122
267
  ],
268
+ requires: [
269
+ 'architecture',
270
+ 'database',
271
+ 'dependencies',
272
+ 'docs-framework',
273
+ 'documentation',
274
+ 'git',
275
+ 'performance',
276
+ 'review-methodology',
277
+ 'testing',
278
+ ],
123
279
  rules: [],
124
280
  },
125
281
  {
@@ -148,6 +304,21 @@ export const DEVFLOW_PLUGINS = [
148
304
  'feature-knowledge',
149
305
  'apply-feature-knowledge',
150
306
  ],
307
+ requires: [
308
+ 'apply-decisions',
309
+ 'boundary-validation',
310
+ 'dependency-research',
311
+ 'docs-framework',
312
+ 'git',
313
+ 'quality-gates',
314
+ 'research-codebase',
315
+ 'research-competitor',
316
+ 'research-external',
317
+ 'research-market',
318
+ 'research-technology',
319
+ 'software-design',
320
+ 'test-driven-development',
321
+ ],
151
322
  rules: [],
152
323
  },
153
324
  {
@@ -157,6 +328,31 @@ export const DEVFLOW_PLUGINS = [
157
328
  commands: ['/dynamic-tickets', '/dynamic-plan', '/dynamic-build', '/dynamic-profile'],
158
329
  agents: ['code', 'validate', 'simplify', 'scrutinize', 'evaluate', 'test', 'review', 'git', 'synthesize', 'knowledge', 'design'],
159
330
  skills: ['apply-decisions', 'apply-feature-knowledge', 'worktree-support', 'docs-framework'],
331
+ requires: [
332
+ 'architecture',
333
+ 'boundary-validation',
334
+ 'complexity',
335
+ 'consistency',
336
+ 'database',
337
+ 'dependencies',
338
+ 'dependency-research',
339
+ 'design-review',
340
+ 'documentation',
341
+ 'feature-knowledge',
342
+ 'gap-analysis',
343
+ 'git',
344
+ 'patterns',
345
+ 'performance',
346
+ 'qa',
347
+ 'quality-gates',
348
+ 'regression',
349
+ 'reliability',
350
+ 'review-methodology',
351
+ 'security',
352
+ 'software-design',
353
+ 'test-driven-development',
354
+ 'testing',
355
+ ],
160
356
  optional: true,
161
357
  rules: [],
162
358
  },
@@ -166,6 +362,7 @@ export const DEVFLOW_PLUGINS = [
166
362
  commands: [],
167
363
  agents: [],
168
364
  skills: ['typescript'],
365
+ requires: [],
169
366
  optional: true,
170
367
  rules: ['typescript'],
171
368
  },
@@ -175,6 +372,7 @@ export const DEVFLOW_PLUGINS = [
175
372
  commands: [],
176
373
  agents: [],
177
374
  skills: ['react'],
375
+ requires: [],
178
376
  optional: true,
179
377
  rules: ['react'],
180
378
  },
@@ -184,6 +382,7 @@ export const DEVFLOW_PLUGINS = [
184
382
  commands: [],
185
383
  agents: [],
186
384
  skills: ['accessibility'],
385
+ requires: [],
187
386
  optional: true,
188
387
  rules: ['accessibility'],
189
388
  },
@@ -193,6 +392,7 @@ export const DEVFLOW_PLUGINS = [
193
392
  commands: [],
194
393
  agents: [],
195
394
  skills: ['ui-design'],
395
+ requires: [],
196
396
  optional: true,
197
397
  rules: ['ui-design'],
198
398
  },
@@ -202,6 +402,7 @@ export const DEVFLOW_PLUGINS = [
202
402
  commands: [],
203
403
  agents: [],
204
404
  skills: ['go'],
405
+ requires: [],
205
406
  optional: true,
206
407
  rules: ['go'],
207
408
  },
@@ -211,6 +412,7 @@ export const DEVFLOW_PLUGINS = [
211
412
  commands: [],
212
413
  agents: [],
213
414
  skills: ['java'],
415
+ requires: [],
214
416
  optional: true,
215
417
  rules: ['java'],
216
418
  },
@@ -220,6 +422,7 @@ export const DEVFLOW_PLUGINS = [
220
422
  commands: [],
221
423
  agents: [],
222
424
  skills: ['python'],
425
+ requires: [],
223
426
  optional: true,
224
427
  rules: ['python'],
225
428
  },
@@ -229,6 +432,7 @@ export const DEVFLOW_PLUGINS = [
229
432
  commands: [],
230
433
  agents: [],
231
434
  skills: ['rust'],
435
+ requires: [],
232
436
  optional: true,
233
437
  rules: ['rust'],
234
438
  },
@@ -280,6 +484,60 @@ export const FEATURE_OWNED_SKILLS = ['compliance'];
280
484
  * (guarded by plugins.test.ts FEATURE_OWNED constants describe block).
281
485
  */
282
486
  export const FEATURE_OWNED_RULES = ['compliance'];
487
+ // ── Skill-closure boundaries ──────────────────────────────────────────────────
488
+ /**
489
+ * Skills that are REFERENCED but never REQUIRED — the presence-gated set.
490
+ *
491
+ * D-PRESENCE-GATED: every language/ecosystem skill ships with an optional,
492
+ * command-less plugin, so a reference to one is a reference to something the
493
+ * user may deliberately not have. The referencing prompts are written to probe
494
+ * first and proceed without it — `/code-review` checks
495
+ * `skills/devflow:{focus}/SKILL.md` under Claude Code's directory (`CLAUDE_CONFIG_DIR`
496
+ * when absolute, else `~/.claude` — D-CLAUDE-DIR-PROMPTS) before spawning that focus, the
497
+ * Review and Code agents continue when the Skill invocation fails. Putting them
498
+ * in a `requires` would reinstate the universal install for exactly the eight
499
+ * skills the selection prompt exists to let a user decline (AC-25).
500
+ *
501
+ * DERIVED from the registry rather than hand-listed: a ninth language plugin is
502
+ * presence-gated by being declared, with no second roster to remember. Guarded
503
+ * against its own definition in tests/guards/requires-closure.test.ts.
504
+ */
505
+ export const PRESENCE_GATED_SKILLS = [
506
+ ...new Set(DEVFLOW_PLUGINS
507
+ .filter(plugin => plugin.optional === true && plugin.commands.length === 0)
508
+ .flatMap(plugin => plugin.skills)),
509
+ ];
510
+ /**
511
+ * The classified exception to the closure guard — declared HERE, at the
512
+ * declaration site of the field it exempts, and imported by the guard.
513
+ *
514
+ * D-TEMPLATE-EXCEPTION (applies PF-067: one authority for a prohibition and its
515
+ * exemptions). Every other templated reference in the corpus carries a literal
516
+ * prefix and resolves through it — `devflow:research-{RESEARCH_TYPE}` resolves
517
+ * because five in-scope skills start with `research-`. The Review focus skill is
518
+ * the one reference with NO literal prefix: the whole skill name is substituted
519
+ * at spawn time, and the substitution set spans the presence-gated language
520
+ * skills, so there is nothing a scan or a `requires` entry could resolve it to.
521
+ *
522
+ * Two spellings, one exception: the command writes the placeholder it passes and
523
+ * the agent writes the placeholder it receives.
524
+ *
525
+ * An entry here is NOT permission to stop thinking about the reference — the
526
+ * guard asserts each literal still occurs in the corpus, so an exemption that
527
+ * outlives its site fails rather than rotting.
528
+ */
529
+ export const TEMPLATE_SKILL_REFS = [
530
+ {
531
+ literal: 'devflow:{focus}',
532
+ site: 'dist/commands/code-review.md (Review agent spawn prompt)',
533
+ why: 'the whole skill name is substituted per focus; the substitution set includes presence-gated language skills',
534
+ },
535
+ {
536
+ literal: 'devflow:{FOCUS}',
537
+ site: 'src/assets/agents/review.md (the Review agent loading its own focus skill)',
538
+ why: 'receiving half of the same substitution — the agent is told which focus it is, not which skill exists',
539
+ },
540
+ ];
283
541
  // ── Feature redirect ──────────────────────────────────────────────────────────
284
542
  /**
285
543
  * Plugin names (and aliases) that have been converted to built-in features.
@@ -405,21 +663,112 @@ export function buildAssetMaps(plugins) {
405
663
  return { skillsMap, agentsMap };
406
664
  }
407
665
  /**
408
- * Build a skills map from ALL plugins (regardless of selection).
409
- * Skills are tiny markdown files — always install all of them so commands
410
- * (review, resolve) can spawn agents that depend on skills from other plugins.
666
+ * The install closure of a plugin selection: everything those plugins own plus
667
+ * everything they use.
668
+ *
669
+ * ONE spelling of `skills ∪ requires`, because every consumer that spells it
670
+ * inline is a place the two halves can be forgotten apart: the installer's
671
+ * install set, its removal set, the skills-list scope and the closure guard all
672
+ * read this. Pure, order-independent, no I/O.
411
673
  */
412
- export function buildFullSkillsMap() {
674
+ export function skillsOf(plugins) {
675
+ const skills = new Set();
676
+ for (const plugin of plugins) {
677
+ for (const skill of plugin.skills)
678
+ skills.add(skill);
679
+ for (const skill of plugin.requires)
680
+ skills.add(skill);
681
+ }
682
+ return skills;
683
+ }
684
+ /**
685
+ * Every plugin that OWNS a skill, in registry order.
686
+ *
687
+ * D-ALL-OWNERS: returns all declarers, not the first — `devflow skills list`'s
688
+ * owner column becomes a lie the moment install is scoped, because the answer a
689
+ * user needs from it is "which plugin do I select to keep this?", and a
690
+ * first-wins answer names one plugin out of several that would each do. Empty
691
+ * for a skill no plugin owns, which for a registry-valid name cannot happen:
692
+ * a `requires` entry is guarded to be a known skill, and a known skill is one
693
+ * some plugin declares.
694
+ */
695
+ export function skillOwners(name) {
696
+ return DEVFLOW_PLUGINS.filter(plugin => plugin.skills.includes(name)).map(plugin => plugin.name);
697
+ }
698
+ /**
699
+ * Build the skill → source-plugin map for a SELECTION.
700
+ *
701
+ * The key set is the selection's closure ({@link skillsOf}); the value is the
702
+ * plugin the skill is copied on behalf of. A skill the selection only REQUIRES
703
+ * has no owner among the selected plugins, so its owner is resolved from the
704
+ * full registry ({@link skillOwners}) — the map's value is a provenance label,
705
+ * and labelling a required skill with the plugin that happens to need it would
706
+ * misattribute ownership.
707
+ */
708
+ export function buildScopedSkillsMap(plugins) {
413
709
  const skillsMap = new Map();
414
- for (const plugin of DEVFLOW_PLUGINS) {
710
+ for (const plugin of plugins) {
415
711
  for (const skill of plugin.skills) {
416
- if (!skillsMap.has(skill)) {
712
+ if (!skillsMap.has(skill))
417
713
  skillsMap.set(skill, plugin.name);
418
- }
419
714
  }
420
715
  }
716
+ for (const skill of skillsOf(plugins)) {
717
+ if (skillsMap.has(skill))
718
+ continue;
719
+ const owner = skillOwners(skill)[0];
720
+ if (owner !== undefined)
721
+ skillsMap.set(skill, owner);
722
+ }
421
723
  return skillsMap;
422
724
  }
725
+ /**
726
+ * Build a skills map over the WHOLE registry.
727
+ *
728
+ * The scoped map applied to every plugin: `skills ∪ requires` across the full
729
+ * registry is `skills` across the full registry, since a `requires` entry is
730
+ * always some plugin's owned skill. Retained for the consumers that legitimately
731
+ * want every skill regardless of selection — uninstall's removal manifest and
732
+ * `devflow skills list`'s catalogue.
733
+ */
734
+ export function buildFullSkillsMap() {
735
+ return buildScopedSkillsMap(DEVFLOW_PLUGINS);
736
+ }
737
+ /**
738
+ * Decide the skill install/remove/dormant sets for one run — pure, no fs.
739
+ *
740
+ * H4: extracted so the decision is unit-testable without a temp tree, and so
741
+ * `installViaFileCopy` consumes a decision rather than growing a fourth set of
742
+ * inline set-arithmetic.
743
+ *
744
+ * The removal set is GATED on a full install. A `--plugin=X` run is a request to
745
+ * add X, not a statement that X is the whole selection, so it may never remove
746
+ * what another plugin contributed (AC-22). {@link FEATURE_OWNED_SKILLS} is
747
+ * subtracted unconditionally: those install and uninstall with their feature,
748
+ * and sweeping them here would delete an artifact this code does not own
749
+ * (applies ADR-024).
750
+ *
751
+ * A shadow is NEVER removed, whatever the selection — `~/.devflow/skills/` is
752
+ * user content. One that falls outside the install set simply applies to
753
+ * nothing, and is reported so the user can tell "inert" from "ignored".
754
+ */
755
+ export function resolveSkillInstallPlan(input) {
756
+ const install = skillsOf(input.effectivePlugins);
757
+ const remove = new Set();
758
+ if (!input.isPartialInstall) {
759
+ for (const skill of skillsOf(DEVFLOW_PLUGINS)) {
760
+ if (install.has(skill))
761
+ continue;
762
+ if (FEATURE_OWNED_SKILLS.includes(skill))
763
+ continue;
764
+ remove.add(skill);
765
+ }
766
+ }
767
+ const dormantShadows = [...new Set(input.shadowedSkills)]
768
+ .filter(skill => !install.has(skill))
769
+ .sort();
770
+ return { install, remove, dormantShadows };
771
+ }
423
772
  /**
424
773
  * Derive unique rule names from all plugins.
425
774
  */
@@ -484,9 +833,9 @@ export const WORKFLOW_ORDER = [
484
833
  ];
485
834
  /**
486
835
  * Plugin names excluded from the init multiselect buckets.
487
- * These are always installed regardless of user selection:
836
+ * init adds them itself rather than offering them:
488
837
  * - devflow-core-skills (always installed, non-optional)
489
- * - devflow-ambient (always installed, non-optional)
838
+ * - devflow-ambient (installed iff ambient mode is on — D-AMBIENT-FOLLOWS-SWITCH)
490
839
  *
491
840
  * Invariant: EXCLUDED ∩ optional === ∅ — no optional plugin may be excluded from
492
841
  * the init UI without a re-init carry mechanism to preserve it across full reinstalls.
@@ -499,7 +848,7 @@ export const EXCLUDED = new Set(['devflow-core-skills', 'devflow-ambient']);
499
848
  *
500
849
  * Excluded from both buckets (not selectable at init):
501
850
  * - devflow-core-skills (always installed)
502
- * - devflow-ambient (always installed)
851
+ * - devflow-ambient (installed iff ambient mode is on)
503
852
  *
504
853
  * Pure function — does not mutate the input array; preserves DEVFLOW_PLUGINS
505
854
  * ordering within each bucket; deterministic; no I/O.
@@ -35,7 +35,7 @@ export function getDocsDir(projectRoot) {
35
35
  // ---------------------------------------------------------------------------
36
36
  // Feature config (neutral .devflow root — not inside learning/)
37
37
  // ---------------------------------------------------------------------------
38
- /** .devflow/config.json — feature toggles {memory, learning, knowledge} */
38
+ /** .devflow/config.json — per-repo facts {reviewPublication, tracker override} */
39
39
  export function getFeatureConfigPath(projectRoot) {
40
40
  return path.join(projectRoot, '.devflow', 'config.json');
41
41
  }
@@ -139,21 +139,4 @@ export function getResearchDir(projectRoot) {
139
139
  export function getHandoffPath(projectRoot, branchSlug) {
140
140
  return path.join(projectRoot, '.devflow', 'docs', `handoff-${branchSlug}.md`);
141
141
  }
142
- // ---------------------------------------------------------------------------
143
- // Gitignore entries (returned as string arrays for updateGitignore callers)
144
- // ---------------------------------------------------------------------------
145
- /**
146
- * The canonical list of generic gitignore entries Devflow adds to a project's
147
- * root .gitignore for LOCAL-scope installs. Currently just `.claude/`.
148
- *
149
- * `.devflow/` is intentionally NOT here: it is managed by ensureDevflowGitignore
150
- * (TS) / ensure-root-gitignore (hook), which write the feature-knowledge carve-out
151
- * for ALL scopes. Adding a bare `.devflow/` here would append a wholesale-ignore
152
- * line after the carve-out and re-bury it (last match wins in .gitignore).
153
- *
154
- * CJS mirror: src/assets/scripts/hooks/lib/project-paths.cjs getGitignoreEntries().
155
- */
156
- export function getGitignoreEntries() {
157
- return ['.claude/'];
158
- }
159
142
  //# sourceMappingURL=project-paths.js.map
@@ -28,12 +28,14 @@ export const PROXY_LOG_TAIL_BYTES = 1_048_576;
28
28
  * Call sites compose on top of this result to add process-specific vars
29
29
  * (e.g. SUBSWITCH_CONFIG for the relay spawn and doctor spawn).
30
30
  *
31
- * applies ADR-003: the prior denylist rationale is gone — the routing runtime
32
- * reads exactly four env vars (ANTHROPIC_API_KEY, FORCE_COLOR, NO_COLOR,
33
- * SUBSWITCH_CONFIG — NO_COLOR read in dist/tty.js with presence semantics; CI is
34
- * read only by the `init` subcommand which devflow never invokes).
35
- * Verified by whole-dist grep of the 0.4.0 package. An allowlist is the correct
36
- * shape: 61 inherited vars → 6.
31
+ * applies ADR-003: the prior denylist rationale is gone — on the paths devflow
32
+ * invokes (serve, doctor, models) the routing runtime reads ANTHROPIC_API_KEY,
33
+ * FORCE_COLOR, NO_COLOR (dist/tty.js, presence semantics), SUBSWITCH_CONFIG and
34
+ * XDG_CONFIG_HOME (user-config lookup, reached only on an implicit config load —
35
+ * see D-EFR-6 in model-discovery.ts). CI is read only by `init`; CODEX_HOME and
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
38
+ * package. An allowlist is the correct shape: 61 inherited vars → 6.
37
39
  *
38
40
  * HOME is retained: the runtime's loadConfig resolves ~ paths via homedir().
39
41
  *
@@ -88,14 +88,17 @@ export async function writeProxyState(devflowDir, state) {
88
88
  // Pure helpers
89
89
  // ---------------------------------------------------------------------------
90
90
  /**
91
- * Accepted top-level keys for the subswitch 0.4.0 FileConfigSchema (z.strictObject).
92
- * Unknown top-level keys cause a hard relay startup error — never emit them.
91
+ * Top-level keys devflow carries into the routing config. Unknown top-level keys
92
+ * cause a hard relay startup error — never emit them.
93
93
  *
94
- * @D-EFR-4 Subswitch 0.4.0 routing config contract:
95
- * FileConfigSchema is a z.strictObject with exactly 5 accepted top-level keys:
96
- * port, logLevel, anthropic, providers, limits. Unknown keys cause a hard startup
97
- * error — the relay refuses to start. anthropic and limits are themselves
98
- * strictObject + prefault({}), so they may be partially specified.
94
+ * @D-EFR-4 Subswitch 0.5.0 routing config contract:
95
+ * FileConfigSchema is a z.strictObject with exactly 6 accepted top-level keys:
96
+ * port, logLevel, anthropic, providers, limits, codexIngress. Unknown keys cause a
97
+ * hard startup error — the relay refuses to start. anthropic and limits are
98
+ * themselves strictObject + prefault({}), so they may be partially specified.
99
+ * codexIngress is accepted by the relay but deliberately NOT carried: devflow's
100
+ * relay serves Claude Code only, and the ingress block would make it accept native
101
+ * Codex traffic and hold Claude credentials on devflow's behalf.
99
102
  */
100
103
  const ROUTING_CONFIG_ALLOWED_TOP_KEYS = new Set([
101
104
  'port', 'logLevel', 'anthropic', 'providers', 'limits',
@@ -163,7 +166,7 @@ export function buildRoutingConfigJson(port, existingContent) {
163
166
  const parsed = JSON.parse(existingContent);
164
167
  if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {
165
168
  for (const [k, v] of Object.entries(parsed)) {
166
- // Only preserve the 5 accepted top-level keys; port is always ours.
169
+ // Only preserve the carried top-level keys; port is always ours.
167
170
  if (ROUTING_CONFIG_ALLOWED_TOP_KEYS.has(k) && k !== 'port') {
168
171
  preserved[k] = v;
169
172
  }