thachvd-kit 1.0.36 → 1.0.38

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 (32) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +240 -0
  3. package/THIRD_PARTY_NOTICES.md +49 -0
  4. package/bin/cli.js +80 -24
  5. package/bin/config.js +164 -0
  6. package/bin/entry.js +11 -1
  7. package/bin/native-skills.js +183 -0
  8. package/bin/spec-doctor.js +251 -0
  9. package/bin/spec-link.js +97 -0
  10. package/bin/spec-recipe.js +74 -0
  11. package/bin/spec-state.js +415 -0
  12. package/bin/spec.js +859 -0
  13. package/bin/upgrade.js +303 -298
  14. package/package.json +5 -3
  15. package/skills/finishing-a-development-branch/SKILL.md +240 -0
  16. package/skills/requesting-code-review/code-reviewer.md +198 -0
  17. package/skills/subagent-driven-development/SKILL.md +574 -0
  18. package/skills/subagent-driven-development/implementer-prompt.md +154 -0
  19. package/skills/subagent-driven-development/re-review-prompt.md +115 -0
  20. package/skills/subagent-driven-development/scripts/review-package +53 -0
  21. package/skills/subagent-driven-development/scripts/review-package.js +52 -0
  22. package/skills/subagent-driven-development/scripts/sdd-workspace +82 -0
  23. package/skills/subagent-driven-development/scripts/sdd-workspace-lib.js +62 -0
  24. package/skills/subagent-driven-development/scripts/sdd-workspace.js +15 -0
  25. package/skills/subagent-driven-development/scripts/task-brief +43 -0
  26. package/skills/subagent-driven-development/scripts/task-brief.js +46 -0
  27. package/skills/subagent-driven-development/task-reviewer-prompt.md +207 -0
  28. package/skills/system-discovery/SKILL.md +140 -0
  29. package/skills/system-reverse-engineer/SKILL.md +208 -0
  30. package/skills/system-spec-review/SKILL.md +177 -0
  31. package/skills/upstream.json +30 -0
  32. package/skills/using-git-worktrees/SKILL.md +175 -0
package/bin/upgrade.js CHANGED
@@ -1,298 +1,303 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
- const { normalizeNewlines, replaceSection, FAST_PATH_SECTION, GETTING_STARTED_FAST_PATH_SECTION } = require('./policy');
4
-
5
- const START = '<!-- thachvd-kit:project-policy:start -->';
6
- const END = '<!-- thachvd-kit:project-policy:end -->';
7
-
8
- const PROJECT_POLICY = `${START}
9
- ## Engineering Policy
10
-
11
- Prefer the smallest sufficient change, not the fewest lines of code.
12
-
13
- - Preserve required behavior, product and architectural contracts, UX/accessibility, security/data integrity, compatibility/performance, and maintainability before optimizing for simplicity.
14
- - Reuse an existing project abstraction when it satisfies the required contract. Do not bypass it merely because a lower-level primitive is shorter.
15
- - Avoid speculative abstractions and unrelated refactors.
16
- - Do not split or reorganize code solely to satisfy a line-count target. Prefer cohesive modules and split only for a concrete cohesion, ownership, testability, or maintainability benefit.
17
- - Fast-path eligibility is based on risk and contract surface, not file count. A code change plus its focused test can still be trivial; a one-file auth, payment, schema, concurrency, or public-contract change is not.
18
- - Use the cheapest reliable context source. Read/search directly for known local code and exact text; use one structural index such as codebase-memory-mcp or CodeGraph for unknown ownership, call paths, architecture, or impact; avoid duplicate retrieval once sufficient evidence is available.
19
- - Prefer RTK for verbose shell output when it preserves the information needed. Use raw output when required for diagnosis.
20
- - Tests or equivalent verification are mandatory before claiming completion.
21
- ${END}`;
22
-
23
- // Files managed by the "## Engineering Policy" block above (unchanged from
24
- // before the Matt Pocock migration).
25
- const TARGETS = [
26
- 'AGENTS.md',
27
- path.join('.agent', 'docs', 'conventions.md'),
28
- path.join('.agent', 'docs', 'workflow.md'),
29
- path.join('.agent', 'docs', 'tooling.md')
30
- ];
31
-
32
- function normalize(text) {
33
- return normalizeNewlines(text);
34
- }
35
-
36
- function removeKnownObsoleteDefaults(text) {
37
- return normalize(text)
38
- .replace(/^\s*- Maximum file length: 300 lines unless the existing project standard is stricter\.\s*\n?/gm, '')
39
- .replace(/^\s*- Keep files under 300 lines unless the project already has a different standard[^\n]*\n?/gm, '')
40
- .replace(/^\s*- \*\*MCP First\*\*:[^\n]*\n?/gm, '')
41
- .replace(/^\s*- Use MCP first for code discovery and technical documentation;[^\n]*\n?/gm, '')
42
- .replace(/Use it only for one-file, unambiguous changes with no behavior, API, schema, security, dependency, CI, workflow, or release contract change\.[^\n]*/g,
43
- 'Fast-path eligibility is based on risk and contract surface, not file count. Use it only for localized, mechanically obvious, low-risk changes with focused verification.')
44
- .replace(/Use a fast path only for one-file, unambiguous changes with no behavior or contract change\.[^\n]*/g,
45
- 'Use a fast path only for localized, mechanically obvious, low-risk changes with focused verification; file count alone is not a gate.')
46
- .replace(/\n{3,}/g, '\n\n');
47
- }
48
-
49
- function upsertManagedBlock(content) {
50
- let text = removeKnownObsoleteDefaults(content);
51
- const start = text.indexOf(START);
52
- const end = text.indexOf(END);
53
-
54
- if (start >= 0 && end >= start) {
55
- const after = end + END.length;
56
- return `${text.slice(0, start)}${PROJECT_POLICY}${text.slice(after)}`.replace(/\n{3,}/g, '\n\n').trimEnd() + '\n';
57
- }
58
-
59
- const trimmed = text.trimEnd();
60
- return `${trimmed}${trimmed ? '\n\n' : ''}${PROJECT_POLICY}\n`;
61
- }
62
-
63
- // --- Superpowers -> Matt Pocock skills migration -------------------------
64
- //
65
- // thachvd-kit used to generate Superpowers-branded workflow content into
66
- // AGENTS.md, .cursorrules, and .agent/docs/{workflow,tooling,getting-started,
67
- // index-project-prompt}.md. `upgrade` must move an existing project's
68
- // *generated* sections over to the current Matt Pocock skill workflow while
69
- // leaving hand-written/custom content alone.
70
- //
71
- // This never does a blind "contains Superpowers" strip. Each replacement is
72
- // gated on the exact signature thachvd-kit itself used to emit for that
73
- // section (checked with `LEGACY.test(...)` against the section body before
74
- // touching it); a section whose content doesn't match is left untouched,
75
- // including if the user rewrote it themselves. The "## Fast Path" sections
76
- // are the one exception: they are already synced unconditionally by
77
- // bin/policy.js for `init`, and this mirrors that exact behavior instead of
78
- // duplicating a second definition of "current" fast-path wording.
79
-
80
- const SUPERPOWERS_MIGRATION_TARGETS = [
81
- 'AGENTS.md',
82
- '.cursorrules',
83
- path.join('.agent', 'docs', 'workflow.md'),
84
- path.join('.agent', 'docs', 'tooling.md'),
85
- path.join('.agent', 'docs', 'getting-started.md'),
86
- path.join('.agent', 'docs', 'index-project-prompt.md')
87
- ];
88
-
89
- function extractSection(text, heading) {
90
- const marker = `${heading}\n`;
91
- const start = text.indexOf(marker);
92
- if (start < 0) return null;
93
- const searchFrom = start + marker.length;
94
- const nextHeading = text.indexOf('\n## ', searchFrom);
95
- const end = nextHeading >= 0 ? nextHeading + 1 : text.length;
96
- return { start, end, body: text.slice(start, end) };
97
- }
98
-
99
- // Replaces a heading-delimited section only when its current body matches a
100
- // known legacy signature. Leaves the text unchanged if the heading is
101
- // missing or its content doesn't look like thachvd-kit's own old output.
102
- function replaceLegacySection(text, heading, legacySignature, replacement) {
103
- const section = extractSection(text, heading);
104
- if (!section || !legacySignature.test(section.body)) return text;
105
- const prefix = text.slice(0, section.start);
106
- const suffix = text.slice(section.end).replace(/^\n+/, '');
107
- return `${prefix}${replacement.trimEnd()}\n\n${suffix}`.replace(/\n{3,}/g, '\n\n');
108
- }
109
-
110
- // Replaces one exact known-legacy line/sentence with its current
111
- // equivalent. Safe because the match is the full, specific sentence
112
- // thachvd-kit generated, not a loose keyword.
113
- function replaceLegacyLine(text, legacyLine, replacementLine) {
114
- return text.includes(legacyLine) ? text.split(legacyLine).join(replacementLine) : text;
115
- }
116
-
117
- const AGENTS_WORKFLOW_SECTION = `## Workflow
118
-
119
- Matt Pocock's promoted skills (installed under \`.agents/skills/\` by \`thachvd-kit setup\`) are the workflow layer. Use the matching skill when a specialized workflow is useful:
120
-
121
- - Clear, localized change: inspect -> edit -> focused verification. Do not force a heavyweight skill.
122
- - Ambiguous feature or design: \`/grill-with-docs\`, then optionally \`/to-spec\` for a durable contract.
123
- - Normal feature: \`/grill-with-docs\` -> \`/to-spec\` -> \`/implement\`.
124
- - Large feature needing decomposition: add \`/to-tickets\` before \`/implement\`.
125
- - Huge, multi-session uncertainty: \`/wayfinder\`.
126
- - Bug or failing behavior: \`/diagnosing-bugs\`.
127
- - Test-driven implementation: \`/tdd\` (skip the ceremony for trivial config/text changes).
128
- - Architecture survey: \`/improve-codebase-architecture\`; use \`/codebase-design\` as the design vocabulary.
129
- - Pre-completion review: \`/code-review\` once when code risk warrants it.
130
-
131
- If unsure which skill fits, use \`/ask-matt\`.
132
-
133
- Questions and research do not edit product code. A fast path is allowed only when the change is localized, mechanically obvious, low-risk, and has focused verification; file count alone is not a gate. State the scope and verification before editing. If the task becomes ambiguous or its behavior, contract, or risk surface grows, use the matching planning skill above instead.
134
-
135
- See \`.agent/docs/workflow.md\` for the full route matrix. This kit does not implement a second workflow engine; it only installs and checks the promoted skill set (\`thachvd-kit skills install|check|update\`).`;
136
-
137
- function migrateAgentsStyleMarkdown(content) {
138
- let text = normalize(content);
139
- text = replaceLegacySection(text, '## Workflow', /Superpowers is the primary workflow backend/, AGENTS_WORKFLOW_SECTION);
140
- text = replaceLegacyLine(
141
- text,
142
- "- Superpowers: installed through the AI client's official plugin surface",
143
- '- Matt Pocock skills: promoted set installed under `.agents/skills/` via `thachvd-kit skills install`'
144
- );
145
- // Older, short-form .cursorrules that never embedded the full AGENTS.md body.
146
- text = replaceLegacyLine(
147
- text,
148
- 'Use Superpowers as the workflow backend. Use direct local evidence when it is sufficient and structural tooling such as codebase-memory MCP only when ownership, call paths, architecture, or impact need discovery.',
149
- "Use Matt Pocock's promoted skills (`.agents/skills/`) as the workflow backend; run `/ask-matt` if unsure which one fits. Use direct local evidence when it is sufficient and structural tooling such as codebase-memory MCP only when ownership, call paths, architecture, or impact need discovery."
150
- );
151
- return text;
152
- }
153
-
154
- const WORKFLOW_ROUTE_MATRIX_SECTION = `## Route Matrix
155
-
156
- | Situation | Skill | Gate |
157
- |---|---|---|
158
- | Question or research only | direct answer or research | no product-code edits |
159
- | Clear, localized change | fast path (no skill) | inspect -> edit -> focused verify |
160
- | Ambiguous feature or design | /grill-with-docs, then optionally /to-spec | durable contract before implementation when useful |
161
- | Normal feature | /grill-with-docs -> /to-spec -> /implement | spec agreed before implementation |
162
- | Large feature needing decomposition | /grill-with-docs -> /to-spec -> /to-tickets -> /implement | tickets agreed before implementation |
163
- | Huge, multi-session uncertainty | /wayfinder | shared decision map before implementation |
164
- | Bug or failing behavior | /diagnosing-bugs | reproduce -> root cause -> regression protection -> fix -> verify |
165
- | Test-driven implementation | /tdd | red -> green -> refactor per slice |
166
- | Architecture survey | /improve-codebase-architecture (+ /codebase-design vocabulary) | findings reviewed before large refactors |
167
- | Pre-merge | /code-review | blocking findings resolved |
168
-
169
- Not sure which row applies? Run /ask-matt instead of guessing.`;
170
-
171
- const WORKFLOW_STANDARD_FLOW_SECTION = `## Standard Feature Flow
172
-
173
- /grill-with-docs -> /to-spec -> (/to-tickets for large work) -> /implement (with /tdd where it helps) -> /code-review.`;
174
-
175
- function migrateWorkflowMarkdown(content) {
176
- let text = normalize(content);
177
- text = replaceLegacyLine(
178
- text,
179
- 'This project uses Superpowers as the workflow backend. thachvd-kit only provides project context and integration setup.',
180
- "This project uses Matt Pocock's promoted skills (installed under .agents/skills/ by `thachvd-kit setup`) as the workflow layer. thachvd-kit only provides project context, the skill manifest, and integration setup; it is not a second workflow engine."
181
- );
182
- text = replaceLegacyLine(
183
- text,
184
- '2. Use the native Superpowers skill that matches the request.',
185
- '2. Use the promoted skill that matches the request, or run /ask-matt if unsure which one fits.'
186
- );
187
- text = replaceLegacySection(text, '## Route Matrix', /Superpowers path/, WORKFLOW_ROUTE_MATRIX_SECTION);
188
- text = replaceLegacySection(text, '## Standard Feature Flow', /\bbrainstorming\s*->/, WORKFLOW_STANDARD_FLOW_SECTION);
189
- // Always kept in sync with the current risk-based wording, same as
190
- // bin/policy.js does for a freshly generated project.
191
- text = replaceSection(text, '## Fast Path', FAST_PATH_SECTION);
192
- return text;
193
- }
194
-
195
- const TOOLING_MATT_SKILLS_SECTION = `## Matt Pocock Skills
196
-
197
- Matt Pocock's promoted engineering and productivity skills are the workflow layer for this project, installed project-locally under \`.agents/skills/\` (never globally):
198
-
199
- - Install the promoted set: \`thachvd-kit skills install\` (\`--dry-run\` to preview the command without running it)
200
- - Check what is installed: \`thachvd-kit skills check\` (read-only)
201
- - Update the promoted set: \`thachvd-kit skills update\` (re-adds each skill individually for safety, so it is slower than install — one network clone per skill)
202
- - The full manifest lives in \`bin/matt-skills.js\` (\`PROMOTED_SKILLS\`); it mirrors upstream's \`skills/engineering/\` + \`skills/productivity/\` catalog and never includes \`in-progress\`, \`misc\`, or \`deprecated\` skills.
203
- - After the first install, run \`/setup-matt-pocock-skills\` once inside the AI client to configure the issue tracker, triage labels, and generated docs location. thachvd-kit does not simulate that skill.
204
- - Unsure which skill fits a task? Run \`/ask-matt\`.`;
205
-
206
- function migrateToolingMarkdown(content) {
207
- const text = normalize(content);
208
- return replaceLegacySection(text, '## Superpowers', /Install Superpowers separately/, TOOLING_MATT_SKILLS_SECTION);
209
- }
210
-
211
- const GETTING_STARTED_SETUP_SECTION = `## Setup
212
-
213
- 1. Run \`thachvd-kit init\` in the repository.
214
- 2. Open or print \`.agent/docs/index-project-prompt.md\` with \`thachvd-kit prompt\`.
215
- 3. Run \`thachvd-kit setup\` (installs the promoted skill set by default; add \`--no-install-skills\` to skip) and RTK.
216
- 4. Inside the AI client, run \`/setup-matt-pocock-skills\` once to configure the issue tracker, triage labels, and doc layout.
217
- 5. Run \`thachvd-kit doctor\` and restart the AI client.`;
218
-
219
- const GETTING_STARTED_STANDARD_FLOW_SECTION = `## Standard Flow
220
-
221
- 1. \`/grill-with-docs\` for unclear requirements or design.
222
- 2. \`/to-spec\` when a durable implementation contract is useful.
223
- 3. \`/to-tickets\` for large work that benefits from decomposition.
224
- 4. \`/implement\`, with \`/tdd\` where red-green-refactor helps.
225
- 5. \`/code-review\` once before completion.
226
-
227
- Not sure which skill fits? Run \`/ask-matt\`.`;
228
-
229
- const GETTING_STARTED_BUG_FLOW_SECTION = `## Bug Flow
230
-
231
- Use \`/diagnosing-bugs\`: reproduce the symptom, inspect the path with codebase-memory MCP, test hypotheses, add regression protection, fix the root cause, and verify.`;
232
-
233
- function migrateGettingStartedMarkdown(content) {
234
- let text = normalize(content);
235
- text = replaceLegacyLine(
236
- text,
237
- 'thachvd-kit creates project context. Superpowers owns the development workflow.',
238
- "thachvd-kit creates project context. Matt Pocock's promoted skills own the development workflow."
239
- );
240
- text = replaceLegacySection(text, '## Setup', /Install Superpowers and RTK/, GETTING_STARTED_SETUP_SECTION);
241
- text = replaceLegacySection(text, '## Standard Flow', /Use Superpowers native skills/, GETTING_STARTED_STANDARD_FLOW_SECTION);
242
- text = replaceLegacySection(text, '## Bug Flow', /`systematic-debugging`/, GETTING_STARTED_BUG_FLOW_SECTION);
243
- // Always kept in sync, same reasoning as the workflow.md Fast Path above.
244
- text = replaceSection(text, '## Fast Path', GETTING_STARTED_FAST_PATH_SECTION);
245
- return text;
246
- }
247
-
248
- function migrateIndexProjectPrompt(content) {
249
- return replaceLegacyLine(
250
- normalize(content),
251
- 'Use Superpowers for the workflow and use codebase-memory MCP for structural code discovery when available.',
252
- 'Use the project\'s Matt Pocock skills for workflow (see AGENTS.md; run /ask-matt if unsure which fits) and use codebase-memory MCP for structural code discovery when available.'
253
- );
254
- }
255
-
256
- function migrateSuperpowersWorkflow(relativePath, content) {
257
- const normalized = relativePath.split(path.sep).join('/');
258
- if (normalized === 'AGENTS.md' || normalized === '.cursorrules') return migrateAgentsStyleMarkdown(content);
259
- if (normalized.endsWith('/workflow.md')) return migrateWorkflowMarkdown(content);
260
- if (normalized.endsWith('/tooling.md')) return migrateToolingMarkdown(content);
261
- if (normalized.endsWith('/getting-started.md')) return migrateGettingStartedMarkdown(content);
262
- if (normalized.endsWith('/index-project-prompt.md')) return migrateIndexProjectPrompt(content);
263
- return normalize(content);
264
- }
265
-
266
- const ALL_UPGRADE_TARGETS = Array.from(new Set([...TARGETS, ...SUPERPOWERS_MIGRATION_TARGETS]));
267
-
268
- function upgradeProject(rootDir, options = {}) {
269
- const dryRun = options.dryRun === true;
270
- const results = [];
271
-
272
- for (const relativePath of ALL_UPGRADE_TARGETS) {
273
- const fullPath = path.join(rootDir, relativePath);
274
- if (!fs.existsSync(fullPath)) continue;
275
-
276
- const existing = fs.readFileSync(fullPath, 'utf8');
277
- let updated = migrateSuperpowersWorkflow(relativePath, existing);
278
- if (TARGETS.includes(relativePath)) updated = upsertManagedBlock(updated);
279
-
280
- const changed = normalize(existing) !== updated;
281
- if (changed && !dryRun) fs.writeFileSync(fullPath, updated, 'utf8');
282
- results.push({ path: relativePath, changed, dryRun: changed && dryRun });
283
- }
284
-
285
- return results;
286
- }
287
-
288
- module.exports = {
289
- START,
290
- END,
291
- PROJECT_POLICY,
292
- TARGETS,
293
- SUPERPOWERS_MIGRATION_TARGETS,
294
- removeKnownObsoleteDefaults,
295
- upsertManagedBlock,
296
- migrateSuperpowersWorkflow,
297
- upgradeProject
298
- };
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const { normalizeNewlines, replaceSection, FAST_PATH_SECTION, GETTING_STARTED_FAST_PATH_SECTION } = require('./policy');
4
+
5
+ const START = '<!-- thachvd-kit:project-policy:start -->';
6
+ const END = '<!-- thachvd-kit:project-policy:end -->';
7
+
8
+ const PROJECT_POLICY = `${START}
9
+ ## Engineering Policy
10
+
11
+ Prefer the smallest sufficient change, not the fewest lines of code.
12
+
13
+ - Preserve required behavior, product and architectural contracts, UX/accessibility, security/data integrity, compatibility/performance, and maintainability before optimizing for simplicity.
14
+ - Reuse an existing project abstraction when it satisfies the required contract. Do not bypass it merely because a lower-level primitive is shorter.
15
+ - Avoid speculative abstractions and unrelated refactors.
16
+ - Do not split or reorganize code solely to satisfy a line-count target. Prefer cohesive modules and split only for a concrete cohesion, ownership, testability, or maintainability benefit.
17
+ - Fast-path eligibility is based on risk and contract surface, not file count. A code change plus its focused test can still be trivial; a one-file auth, payment, schema, concurrency, or public-contract change is not.
18
+ - Use the cheapest reliable context source. Read/search directly for known local code and exact text; use one structural index such as codebase-memory-mcp or CodeGraph for unknown ownership, call paths, architecture, or impact; avoid duplicate retrieval once sufficient evidence is available.
19
+ - Prefer RTK for verbose shell output when it preserves the information needed. Use raw output when required for diagnosis.
20
+ - Tests or equivalent verification are mandatory before claiming completion.
21
+ ${END}`;
22
+
23
+ // Files managed by the "## Engineering Policy" block above (unchanged from
24
+ // before the Matt Pocock migration).
25
+ const TARGETS = [
26
+ 'AGENTS.md',
27
+ path.join('.agent', 'docs', 'conventions.md'),
28
+ path.join('.agent', 'docs', 'workflow.md'),
29
+ path.join('.agent', 'docs', 'tooling.md')
30
+ ];
31
+
32
+ function normalize(text) {
33
+ return normalizeNewlines(text);
34
+ }
35
+
36
+ function removeKnownObsoleteDefaults(text) {
37
+ return normalize(text)
38
+ .replace(/^\s*- Maximum file length: 300 lines unless the existing project standard is stricter\.\s*\n?/gm, '')
39
+ .replace(/^\s*- Keep files under 300 lines unless the project already has a different standard[^\n]*\n?/gm, '')
40
+ .replace(/^\s*- \*\*MCP First\*\*:[^\n]*\n?/gm, '')
41
+ .replace(/^\s*- Use MCP first for code discovery and technical documentation;[^\n]*\n?/gm, '')
42
+ .replace(/Use it only for one-file, unambiguous changes with no behavior, API, schema, security, dependency, CI, workflow, or release contract change\.[^\n]*/g,
43
+ 'Fast-path eligibility is based on risk and contract surface, not file count. Use it only for localized, mechanically obvious, low-risk changes with focused verification.')
44
+ .replace(/Use a fast path only for one-file, unambiguous changes with no behavior or contract change\.[^\n]*/g,
45
+ 'Use a fast path only for localized, mechanically obvious, low-risk changes with focused verification; file count alone is not a gate.')
46
+ .replace(/\n{3,}/g, '\n\n');
47
+ }
48
+
49
+ function upsertManagedBlock(content) {
50
+ let text = removeKnownObsoleteDefaults(content);
51
+ const start = text.indexOf(START);
52
+ const end = text.indexOf(END);
53
+
54
+ if (start >= 0 && end >= start) {
55
+ const after = end + END.length;
56
+ return `${text.slice(0, start)}${PROJECT_POLICY}${text.slice(after)}`.replace(/\n{3,}/g, '\n\n').trimEnd() + '\n';
57
+ }
58
+
59
+ const trimmed = text.trimEnd();
60
+ return `${trimmed}${trimmed ? '\n\n' : ''}${PROJECT_POLICY}\n`;
61
+ }
62
+
63
+ // --- Superpowers -> Matt Pocock skills migration -------------------------
64
+ //
65
+ // thachvd-kit used to generate Superpowers-branded workflow content into
66
+ // AGENTS.md, .cursorrules, and .agent/docs/{workflow,tooling,getting-started,
67
+ // index-project-prompt}.md. `upgrade` must move an existing project's
68
+ // *generated* sections over to the current Matt Pocock skill workflow while
69
+ // leaving hand-written/custom content alone.
70
+ //
71
+ // This never does a blind "contains Superpowers" strip. Each replacement is
72
+ // gated on the exact signature thachvd-kit itself used to emit for that
73
+ // section (checked with `LEGACY.test(...)` against the section body before
74
+ // touching it); a section whose content doesn't match is left untouched,
75
+ // including if the user rewrote it themselves. The "## Fast Path" sections
76
+ // are the one exception: they are already synced unconditionally by
77
+ // bin/policy.js for `init`, and this mirrors that exact behavior instead of
78
+ // duplicating a second definition of "current" fast-path wording.
79
+
80
+ const SUPERPOWERS_MIGRATION_TARGETS = [
81
+ 'AGENTS.md',
82
+ '.cursorrules',
83
+ path.join('.agent', 'docs', 'workflow.md'),
84
+ path.join('.agent', 'docs', 'tooling.md'),
85
+ path.join('.agent', 'docs', 'getting-started.md'),
86
+ path.join('.agent', 'docs', 'index-project-prompt.md')
87
+ ];
88
+
89
+ function extractSection(text, heading) {
90
+ const marker = `${heading}\n`;
91
+ const start = text.indexOf(marker);
92
+ if (start < 0) return null;
93
+ const searchFrom = start + marker.length;
94
+ const nextHeading = text.indexOf('\n## ', searchFrom);
95
+ const end = nextHeading >= 0 ? nextHeading + 1 : text.length;
96
+ return { start, end, body: text.slice(start, end) };
97
+ }
98
+
99
+ // Replaces a heading-delimited section only when its current body matches a
100
+ // known legacy signature. Leaves the text unchanged if the heading is
101
+ // missing or its content doesn't look like thachvd-kit's own old output.
102
+ function replaceLegacySection(text, heading, legacySignature, replacement) {
103
+ const section = extractSection(text, heading);
104
+ if (!section || !legacySignature.test(section.body)) return text;
105
+ const prefix = text.slice(0, section.start);
106
+ const suffix = text.slice(section.end).replace(/^\n+/, '');
107
+ return `${prefix}${replacement.trimEnd()}\n\n${suffix}`.replace(/\n{3,}/g, '\n\n');
108
+ }
109
+
110
+ // Replaces one exact known-legacy line/sentence with its current
111
+ // equivalent. Safe because the match is the full, specific sentence
112
+ // thachvd-kit generated, not a loose keyword.
113
+ function replaceLegacyLine(text, legacyLine, replacementLine) {
114
+ return text.includes(legacyLine) ? text.split(legacyLine).join(replacementLine) : text;
115
+ }
116
+
117
+ const AGENTS_WORKFLOW_SECTION = `## Workflow
118
+
119
+ Matt Pocock's promoted skills plus thachvd-kit's native workflow skills (installed under \`.agents/skills/\` and \`.claude/skills/\` by \`thachvd-kit setup\`) are the workflow layer. Use the matching skill when a specialized workflow is useful:
120
+
121
+ - Clear, localized change: inspect -> edit -> focused verification. Do not force a heavyweight skill.
122
+ - Ambiguous feature or design: \`/grill-with-docs\`, then optionally \`/to-spec\` for a durable contract.
123
+ - Normal feature: \`/grill-with-docs\` -> \`/to-spec\` -> choose workspace -> \`/implement\`.
124
+ - Large feature needing decomposition: add \`/to-tickets\`, choose workspace, then choose \`/implement\` or \`/subagent-driven-development\`.
125
+ - Huge, multi-session uncertainty: \`/wayfinder\`.
126
+ - Bug or failing behavior: \`/diagnosing-bugs\`.
127
+ - Test-driven implementation: \`/tdd\` (skip the ceremony for trivial config/text changes).
128
+ - Architecture survey: \`/improve-codebase-architecture\`; use \`/codebase-design\` as the design vocabulary.
129
+ - Pre-completion review: \`/code-review\` once when code risk warrants it.
130
+ - Workspace choice: stay on the current branch when explicitly requested; use \`/using-git-worktrees\` only when isolation is wanted.
131
+ - Branch handoff: \`/finishing-a-development-branch\` after verification and review.
132
+
133
+ If unsure which skill fits, use \`/ask-matt\`.
134
+
135
+ Questions and research do not edit product code. A fast path is allowed only when the change is localized, mechanically obvious, low-risk, and has focused verification; file count alone is not a gate. State the scope and verification before editing. If the task becomes ambiguous or its behavior, contract, or risk surface grows, use the matching planning skill above instead.
136
+
137
+ See \`.agent/docs/workflow.md\` for the full route matrix. This kit does not implement a second Matt workflow engine; it installs Matt's promoted skills plus thachvd-kit native skills (\`thachvd-kit skills install|check|update\`).`;
138
+
139
+ function migrateAgentsStyleMarkdown(content) {
140
+ let text = normalize(content);
141
+ text = replaceLegacySection(text, '## Workflow', /Superpowers is the primary workflow backend/, AGENTS_WORKFLOW_SECTION);
142
+ text = replaceLegacyLine(
143
+ text,
144
+ "- Superpowers: installed through the AI client's official plugin surface",
145
+ '- Matt Pocock skills: promoted set installed under `.agents/skills/` via `thachvd-kit skills install`'
146
+ );
147
+ // Older, short-form .cursorrules that never embedded the full AGENTS.md body.
148
+ text = replaceLegacyLine(
149
+ text,
150
+ 'Use Superpowers as the workflow backend. Use direct local evidence when it is sufficient and structural tooling such as codebase-memory MCP only when ownership, call paths, architecture, or impact need discovery.',
151
+ "Use Matt Pocock's promoted and thachvd-kit native skills (`.agents/skills/` and `.claude/skills/`) as the workflow layer; run `/ask-matt` if unsure which one fits. Use direct local evidence when it is sufficient and structural tooling such as codebase-memory MCP only when ownership, call paths, architecture, or impact need discovery."
152
+ );
153
+ return text;
154
+ }
155
+
156
+ const WORKFLOW_ROUTE_MATRIX_SECTION = `## Route Matrix
157
+
158
+ | Situation | Skill | Gate |
159
+ |---|---|---|
160
+ | Question or research only | direct answer or research | no product-code edits |
161
+ | Clear, localized change | fast path (no skill) | inspect -> edit -> focused verify |
162
+ | Ambiguous feature or design | /grill-with-docs, then optionally /to-spec | durable contract before implementation when useful |
163
+ | Normal feature | /grill-with-docs -> /to-spec -> choose workspace -> /implement | spec agreed before implementation |
164
+ | Large feature needing decomposition | /grill-with-docs -> /to-spec -> /to-tickets -> choose workspace -> executor | tickets agreed before implementation |
165
+ | Huge, multi-session uncertainty | /wayfinder | shared decision map before implementation |
166
+ | Bug or failing behavior | /diagnosing-bugs | reproduce -> root cause -> regression protection -> fix -> verify |
167
+ | Test-driven implementation | /tdd | red -> green -> refactor per slice |
168
+ | Architecture survey | /improve-codebase-architecture (+ /codebase-design vocabulary) | findings reviewed before large refactors |
169
+ | Pre-merge | /code-review | blocking findings resolved |
170
+
171
+ Not sure which row applies? Run /ask-matt instead of guessing.`;
172
+
173
+ const WORKFLOW_STANDARD_FLOW_SECTION = `## Standard Feature Flow
174
+
175
+ /grill-with-docs -> /to-spec -> (/to-tickets for large work) -> choose workspace -> choose executor (/implement or /subagent-driven-development) -> /code-review -> /finishing-a-development-branch.`;
176
+
177
+ function migrateWorkflowMarkdown(content) {
178
+ let text = normalize(content);
179
+ text = replaceLegacyLine(
180
+ text,
181
+ 'This project uses Superpowers as the workflow backend. thachvd-kit only provides project context and integration setup.',
182
+ "This project uses Matt Pocock's promoted skills plus thachvd-kit's native workflow skills (installed under .agents/skills/ and .claude/skills/ by `thachvd-kit setup`) as the workflow layer. Native skills add opt-in workspace isolation, subagent-driven execution, and branch finishing; they do not replace Matt's planning, implementation, testing, or review skills."
183
+ );
184
+ text = replaceLegacyLine(
185
+ text,
186
+ '2. Use the native Superpowers skill that matches the request.',
187
+ '2. Use the promoted skill that matches the request, or run /ask-matt if unsure which one fits.'
188
+ );
189
+ text = replaceLegacySection(text, '## Route Matrix', /Superpowers path/, WORKFLOW_ROUTE_MATRIX_SECTION);
190
+ text = replaceLegacySection(text, '## Standard Feature Flow', /\bbrainstorming\s*->/, WORKFLOW_STANDARD_FLOW_SECTION);
191
+ // Always kept in sync with the current risk-based wording, same as
192
+ // bin/policy.js does for a freshly generated project.
193
+ text = replaceSection(text, '## Fast Path', FAST_PATH_SECTION);
194
+ return text;
195
+ }
196
+
197
+ const TOOLING_MATT_SKILLS_SECTION = `## Matt Pocock Skills + Native Workflow Skills
198
+
199
+ Matt Pocock's promoted engineering and productivity skills are installed project-locally under \`.agents/skills/\` (never globally); thachvd-kit native workflow skills are installed under \`.agents/skills/\` and \`.claude/skills/\`:
200
+
201
+ - Install the promoted set: \`thachvd-kit skills install\` (\`--dry-run\` to preview the command without running it)
202
+ - Check what is installed: \`thachvd-kit skills check\` (read-only)
203
+ - Update the promoted set: \`thachvd-kit skills update\` (re-adds each skill individually for safety, so it is slower than install — one network clone per skill)
204
+ - The full manifest lives in \`bin/matt-skills.js\` (\`PROMOTED_SKILLS\`); it mirrors upstream's \`skills/engineering/\` + \`skills/productivity/\` catalog and never includes \`in-progress\`, \`misc\`, or \`deprecated\` skills.
205
+ - After the first install, run \`/setup-matt-pocock-skills\` once inside the AI client to configure the issue tracker, triage labels, and generated docs location. thachvd-kit does not simulate that skill.
206
+ - Unsure which skill fits a task? Run \`/ask-matt\`.
207
+ - Native skills: \`/using-git-worktrees\` (opt-in isolation), \`/subagent-driven-development\` (alternative executor for multi-task plans), and \`/finishing-a-development-branch\`.
208
+ - Native skills are refreshed from bundled copies; runtime updates never fetch upstream repositories.`;
209
+
210
+ function migrateToolingMarkdown(content) {
211
+ const text = normalize(content);
212
+ return replaceLegacySection(text, '## Superpowers', /Install Superpowers separately/, TOOLING_MATT_SKILLS_SECTION);
213
+ }
214
+
215
+ const GETTING_STARTED_SETUP_SECTION = `## Setup
216
+
217
+ 1. Run \`thachvd-kit init\` in the repository.
218
+ 2. Open or print \`.agent/docs/index-project-prompt.md\` with \`thachvd-kit prompt\`.
219
+ 3. Run \`thachvd-kit setup\` (installs promoted and native skill sets by default; add \`--no-install-skills\` to skip) and RTK.
220
+ 4. Inside the AI client, run \`/setup-matt-pocock-skills\` once to configure the issue tracker, triage labels, and doc layout.
221
+ 5. Run \`thachvd-kit doctor\` and restart the AI client.`;
222
+
223
+ const GETTING_STARTED_STANDARD_FLOW_SECTION = `## Standard Flow
224
+
225
+ 1. \`/grill-with-docs\` for unclear requirements or design.
226
+ 2. \`/to-spec\` when a durable implementation contract is useful.
227
+ 3. \`/to-tickets\` for large work that benefits from decomposition.
228
+ 4. Choose the current branch/workspace or \`/using-git-worktrees\` when isolation is wanted.
229
+ 5. Choose \`/implement\` (with \`/tdd\` where useful) or \`/subagent-driven-development\` for multiple relatively independent tasks.
230
+ 6. \`/code-review\`, then \`/finishing-a-development-branch\` once verification is complete.
231
+
232
+ Not sure which skill fits? Run \`/ask-matt\`.`;
233
+
234
+ const GETTING_STARTED_BUG_FLOW_SECTION = `## Bug Flow
235
+
236
+ Use \`/diagnosing-bugs\`: reproduce the symptom, inspect the path with codebase-memory MCP, test hypotheses, add regression protection, fix the root cause, and verify.`;
237
+
238
+ function migrateGettingStartedMarkdown(content) {
239
+ let text = normalize(content);
240
+ text = replaceLegacyLine(
241
+ text,
242
+ 'thachvd-kit creates project context. Superpowers owns the development workflow.',
243
+ "thachvd-kit creates project context. Matt Pocock's promoted and thachvd-kit native skills own the development workflow."
244
+ );
245
+ text = replaceLegacySection(text, '## Setup', /Install Superpowers and RTK/, GETTING_STARTED_SETUP_SECTION);
246
+ text = replaceLegacySection(text, '## Standard Flow', /Use Superpowers native skills/, GETTING_STARTED_STANDARD_FLOW_SECTION);
247
+ text = replaceLegacySection(text, '## Bug Flow', /`systematic-debugging`/, GETTING_STARTED_BUG_FLOW_SECTION);
248
+ // Always kept in sync, same reasoning as the workflow.md Fast Path above.
249
+ text = replaceSection(text, '## Fast Path', GETTING_STARTED_FAST_PATH_SECTION);
250
+ return text;
251
+ }
252
+
253
+ function migrateIndexProjectPrompt(content) {
254
+ return replaceLegacyLine(
255
+ normalize(content),
256
+ 'Use Superpowers for the workflow and use codebase-memory MCP for structural code discovery when available.',
257
+ 'Use the project\'s Matt Pocock skills plus thachvd-kit native skills for workflow (see AGENTS.md; run /ask-matt if unsure which fits) and use codebase-memory MCP for structural code discovery when available.'
258
+ );
259
+ }
260
+
261
+ function migrateSuperpowersWorkflow(relativePath, content) {
262
+ const normalized = relativePath.split(path.sep).join('/');
263
+ if (normalized === 'AGENTS.md' || normalized === '.cursorrules') return migrateAgentsStyleMarkdown(content);
264
+ if (normalized.endsWith('/workflow.md')) return migrateWorkflowMarkdown(content);
265
+ if (normalized.endsWith('/tooling.md')) return migrateToolingMarkdown(content);
266
+ if (normalized.endsWith('/getting-started.md')) return migrateGettingStartedMarkdown(content);
267
+ if (normalized.endsWith('/index-project-prompt.md')) return migrateIndexProjectPrompt(content);
268
+ return normalize(content);
269
+ }
270
+
271
+ const ALL_UPGRADE_TARGETS = Array.from(new Set([...TARGETS, ...SUPERPOWERS_MIGRATION_TARGETS]));
272
+
273
+ function upgradeProject(rootDir, options = {}) {
274
+ const dryRun = options.dryRun === true;
275
+ const results = [];
276
+
277
+ for (const relativePath of ALL_UPGRADE_TARGETS) {
278
+ const fullPath = path.join(rootDir, relativePath);
279
+ if (!fs.existsSync(fullPath)) continue;
280
+
281
+ const existing = fs.readFileSync(fullPath, 'utf8');
282
+ let updated = migrateSuperpowersWorkflow(relativePath, existing);
283
+ if (TARGETS.includes(relativePath)) updated = upsertManagedBlock(updated);
284
+
285
+ const changed = normalize(existing) !== updated;
286
+ if (changed && !dryRun) fs.writeFileSync(fullPath, updated, 'utf8');
287
+ results.push({ path: relativePath, changed, dryRun: changed && dryRun });
288
+ }
289
+
290
+ return results;
291
+ }
292
+
293
+ module.exports = {
294
+ START,
295
+ END,
296
+ PROJECT_POLICY,
297
+ TARGETS,
298
+ SUPERPOWERS_MIGRATION_TARGETS,
299
+ removeKnownObsoleteDefaults,
300
+ upsertManagedBlock,
301
+ migrateSuperpowersWorkflow,
302
+ upgradeProject
303
+ };