@hegemonart/get-design-done 1.28.5 → 1.28.7
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.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +102 -0
- package/README.md +2 -0
- package/package.json +1 -1
- package/reference/registry.json +0 -140
- package/reference/skill-authoring-contract.md +40 -9
- package/scripts/install.cjs +7 -0
- package/scripts/lib/install/converters/antigravity.cjs +48 -0
- package/scripts/lib/install/converters/augment.cjs +68 -0
- package/scripts/lib/install/converters/cline.cjs +206 -0
- package/scripts/lib/install/converters/codebuddy.cjs +55 -0
- package/scripts/lib/install/converters/codex.cjs +61 -0
- package/scripts/lib/install/converters/copilot.cjs +47 -0
- package/scripts/lib/install/converters/cursor.cjs +49 -0
- package/scripts/lib/install/converters/gemini.cjs +116 -0
- package/scripts/lib/install/converters/kilo.cjs +62 -0
- package/scripts/lib/install/converters/opencode.cjs +64 -0
- package/scripts/lib/install/converters/qwen.cjs +51 -0
- package/scripts/lib/install/converters/shared.cjs +377 -0
- package/scripts/lib/install/converters/trae.cjs +47 -0
- package/scripts/lib/install/converters/windsurf.cjs +47 -0
- package/scripts/lib/install/installer.cjs +529 -47
- package/scripts/lib/install/merge.cjs +31 -1
- package/scripts/lib/install/runtime-artifact-layout.cjs +431 -0
- package/scripts/lib/install/runtime-homes.cjs +225 -0
- package/scripts/lib/install/runtime-slash.cjs +172 -0
- package/scripts/lib/install/runtimes.cjs +25 -32
- package/skills/apply-reflections/SKILL.md +1 -1
- package/skills/cache-manager/SKILL.md +2 -2
- package/skills/compare/SKILL.md +8 -8
- package/skills/connections/SKILL.md +9 -9
- package/skills/darkmode/SKILL.md +8 -8
- package/skills/debug/SKILL.md +3 -3
- package/skills/design/SKILL.md +6 -6
- package/skills/discover/SKILL.md +7 -7
- package/skills/explore/SKILL.md +6 -6
- package/skills/health/SKILL.md +2 -2
- package/skills/new-cycle/SKILL.md +1 -1
- package/skills/peer-cli-add/SKILL.md +6 -6
- package/skills/peer-cli-customize/SKILL.md +5 -5
- package/skills/peers/SKILL.md +2 -2
- package/skills/plan/SKILL.md +10 -10
- package/skills/quality-gate/SKILL.md +1 -1
- package/skills/router/SKILL.md +3 -3
- package/skills/scan/SKILL.md +17 -17
- package/skills/start/SKILL.md +1 -1
- package/skills/style/SKILL.md +5 -5
- package/skills/turn-closeout/SKILL.md +1 -1
- package/skills/verify/SKILL.md +10 -10
- package/skills/warm-cache/SKILL.md +2 -2
- /package/{reference → skills/apply-reflections}/apply-reflections-procedure.md +0 -0
- /package/{reference → skills/cache-manager}/cache-policy.md +0 -0
- /package/{reference → skills/compare}/compare-rubric.md +0 -0
- /package/{reference → skills/connections}/connections-onboarding.md +0 -0
- /package/{reference → skills/darkmode}/darkmode-audit-procedure.md +0 -0
- /package/{reference → skills/debug}/debug-feedback-loops.md +0 -0
- /package/{reference → skills/design}/design-procedure.md +0 -0
- /package/{reference → skills/discover}/discover-procedure.md +0 -0
- /package/{reference → skills/explore}/explore-procedure.md +0 -0
- /package/{reference → skills/health}/health-mcp-detection.md +0 -0
- /package/{reference → skills/health}/health-skill-length-report.md +0 -0
- /package/{reference → skills/new-cycle}/milestone-completeness-rubric.md +0 -0
- /package/{reference → skills/peer-cli-add}/peer-cli-protocol.md +0 -0
- /package/{reference → skills/plan}/plan-procedure.md +0 -0
- /package/{reference → skills/quality-gate}/threat-modeling.md +0 -0
- /package/{reference → skills/router}/router-rules.md +0 -0
- /package/{reference → skills/scan}/scan-procedure.md +0 -0
- /package/{reference → skills/start}/start-procedure.md +0 -0
- /package/{reference → skills/style}/style-doc-procedure.md +0 -0
- /package/{reference → skills/verify}/verify-procedure.md +0 -0
|
@@ -88,9 +88,35 @@ function buildAgentsFileContent(runtime, payloadHeader) {
|
|
|
88
88
|
return lines.join('\n');
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
+
// Phase 28.7 (Plan 28.7-08) — Extended fingerprint detection.
|
|
92
|
+
//
|
|
93
|
+
// In Phase 24, plugin-owned AGENTS.md / GEMINI.md files were marked with the
|
|
94
|
+
// `<!-- get-design-done plugin instructions -->` HTML comment (PLUGIN_FINGERPRINT
|
|
95
|
+
// above). Phase 28.7 introduces TWO more fingerprint shapes for the new
|
|
96
|
+
// multi-artifact installer:
|
|
97
|
+
//
|
|
98
|
+
// - `gdd: auto-generated from Claude SKILL.md` — emitted by every per-runtime
|
|
99
|
+
// SKILL converter (cursor.cjs, codex.cjs, etc.) via shared.ensureAdapterHeader.
|
|
100
|
+
// This applies to every SKILL.md / command file written into a runtime's
|
|
101
|
+
// skills/ or command/ directory.
|
|
102
|
+
//
|
|
103
|
+
// - `# get-design-done rules` — emitted as the heading of the .clinerules
|
|
104
|
+
// file by converters/cline.cjs#buildClinerulesFile. Cline is rules-based
|
|
105
|
+
// and does not have a per-skill directory layout (Phase 28.7 D-09).
|
|
106
|
+
//
|
|
107
|
+
// All three shapes count as "plugin-owned" for the foreign-file protection
|
|
108
|
+
// + idempotent-re-install discipline that the installer enforces (Phase 24
|
|
109
|
+
// D-04 carry-forward). Anything else is treated as user-authored and left
|
|
110
|
+
// alone (skipped-foreign action).
|
|
111
|
+
const GDD_ADAPTER_FINGERPRINT = 'gdd: auto-generated from Claude SKILL.md';
|
|
112
|
+
const CLINERULES_HEADER_FINGERPRINT = '# get-design-done rules';
|
|
113
|
+
|
|
91
114
|
function isPluginOwned(content) {
|
|
92
115
|
if (!content || typeof content !== 'string') return false;
|
|
93
|
-
|
|
116
|
+
if (content.includes(PLUGIN_FINGERPRINT)) return true;
|
|
117
|
+
if (content.includes(GDD_ADAPTER_FINGERPRINT)) return true;
|
|
118
|
+
if (content.includes(CLINERULES_HEADER_FINGERPRINT)) return true;
|
|
119
|
+
return false;
|
|
94
120
|
}
|
|
95
121
|
|
|
96
122
|
module.exports = {
|
|
@@ -100,4 +126,8 @@ module.exports = {
|
|
|
100
126
|
buildAgentsFileContent,
|
|
101
127
|
isPluginOwned,
|
|
102
128
|
PLUGIN_FINGERPRINT,
|
|
129
|
+
// Phase 28.7 (Plan 28.7-08) — additional fingerprint shapes for the
|
|
130
|
+
// multi-artifact installer (per-runtime converters + cline rules file).
|
|
131
|
+
GDD_ADAPTER_FINGERPRINT,
|
|
132
|
+
CLINERULES_HEADER_FINGERPRINT,
|
|
103
133
|
};
|
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* scripts/lib/install/runtime-artifact-layout.cjs — Phase 28.7 (Plan 28.7-02).
|
|
5
|
+
*
|
|
6
|
+
* Per-runtime artifact layout resolver. Maps `(runtime, configDir, scope)`
|
|
7
|
+
* to a layout descriptor describing where the runtime expects its install
|
|
8
|
+
* artifacts (commands / agents / skills) and how to stage them.
|
|
9
|
+
*
|
|
10
|
+
* Architecture ported from gsd-build/get-shit-done (MIT) — per Phase 28.7
|
|
11
|
+
* D-02 (port architecture, not source). See NOTICE for upstream attribution.
|
|
12
|
+
*
|
|
13
|
+
* Scope: the 14 GDD runtimes locked by Phase 24 D-02. Phase 28.7 D-03 + D-10
|
|
14
|
+
* keep `hermes` (and gsd-build's upstream `grok` slot) OUT of scope; their
|
|
15
|
+
* branches are deliberately NOT ported.
|
|
16
|
+
*
|
|
17
|
+
* Layout table (D-03 + D-05 + D-09 + D-10):
|
|
18
|
+
* claude global → [{skills, 'skills', 'gdd-', passthrough}]
|
|
19
|
+
* claude local → [{commands, 'commands/gdd', 'gdd-', passthrough},
|
|
20
|
+
* {agents, 'agents', 'gdd-', passthrough}]
|
|
21
|
+
* cursor / codex / copilot / antigravity / windsurf / augment / trae /
|
|
22
|
+
* qwen / codebuddy → [{skills, 'skills', 'gdd-', <runtime>-converter}]
|
|
23
|
+
* gemini → [{commands, 'commands/gdd', 'gdd-', gemini-converter}]
|
|
24
|
+
* opencode → [{commands, 'command', 'gdd-', opencode-converter}]
|
|
25
|
+
* kilo → [{commands, 'command', 'gdd-', kilo-converter}]
|
|
26
|
+
* cline → [] (D-09: rules-based, embeds in `.clinerules` — wiring
|
|
27
|
+
* handled by installer.cjs + converters/cline.cjs)
|
|
28
|
+
*
|
|
29
|
+
* Modular requires (D-08): converter modules are lazy-required from
|
|
30
|
+
* `./converters/<runtime>.cjs` at `stage()` call time. This avoids:
|
|
31
|
+
* - cyclic dependencies at module load (converters may import shared
|
|
32
|
+
* utilities from this file's siblings),
|
|
33
|
+
* - loading 13 converters when only one runtime is being installed,
|
|
34
|
+
* - upstream's bundled-monolith `bin/install.js` pattern (D-08).
|
|
35
|
+
*
|
|
36
|
+
* Converter contract:
|
|
37
|
+
* convert(content: string, skillName: string, opts: { runtime: string })
|
|
38
|
+
* → string // converted single-string content; multi-file output
|
|
39
|
+
* // is expressed by emitting joined content the installer
|
|
40
|
+
* // splits, or by the converter writing extra files itself
|
|
41
|
+
* // (only `cline` does the latter — D-09).
|
|
42
|
+
*
|
|
43
|
+
* Pure / side-effect-free at module load: only `require('path')` and
|
|
44
|
+
* `require('fs')` are taken at top level. `findInstallSourceRoot` is the
|
|
45
|
+
* sole `fs.*` caller, and it is only invoked when `stage(ctx)` runs.
|
|
46
|
+
*/
|
|
47
|
+
|
|
48
|
+
const path = require('path');
|
|
49
|
+
const fs = require('fs');
|
|
50
|
+
|
|
51
|
+
// ---------------------------------------------------------------------------
|
|
52
|
+
// Allowlisted runtimes (D-03 + D-10)
|
|
53
|
+
// ---------------------------------------------------------------------------
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* The 14 runtimes GDD claims first-class install support for (Phase 24 D-02).
|
|
57
|
+
*
|
|
58
|
+
* NOTE: `hermes` and `grok` from gsd-build/get-shit-done's upstream list are
|
|
59
|
+
* intentionally absent. Phase 28.7 D-03 + D-10 lock the 14-runtime scope;
|
|
60
|
+
* adding a runtime to this set without a matching `switch` branch below will
|
|
61
|
+
* throw `TypeError: Unknown runtime` (loud-fail signal).
|
|
62
|
+
*/
|
|
63
|
+
const ALLOWED_RUNTIMES = new Set([
|
|
64
|
+
'claude',
|
|
65
|
+
'cursor',
|
|
66
|
+
'gemini',
|
|
67
|
+
'codex',
|
|
68
|
+
'copilot',
|
|
69
|
+
'antigravity',
|
|
70
|
+
'windsurf',
|
|
71
|
+
'augment',
|
|
72
|
+
'trae',
|
|
73
|
+
'qwen',
|
|
74
|
+
'codebuddy',
|
|
75
|
+
'cline',
|
|
76
|
+
'opencode',
|
|
77
|
+
'kilo',
|
|
78
|
+
]);
|
|
79
|
+
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
// Source-root resolver
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Locate the GDD repo's `skills/` source root.
|
|
86
|
+
*
|
|
87
|
+
* Resolution order:
|
|
88
|
+
* 1. If `runtimeConfigDir` is provided AND `<runtimeConfigDir>/.gdd-source`
|
|
89
|
+
* exists, read its first line as an absolute path override (test-mode
|
|
90
|
+
* hook — Plan 28.7-09 can point the resolver at a fixture skills dir).
|
|
91
|
+
* 2. Walk up from `__dirname` up to 6 levels looking for `<dir>/skills/`.
|
|
92
|
+
* 3. Throw `Error` with a descriptive message.
|
|
93
|
+
*
|
|
94
|
+
* Pure read-only fs use; safe to call repeatedly. The returned path is the
|
|
95
|
+
* directory containing `skills/`, NOT the `skills/` directory itself — that
|
|
96
|
+
* matches gsd-build's `findInstallSourceRoot()` return contract so the
|
|
97
|
+
* installer can locate `skills/`, `agents/`, and `commands/` as siblings.
|
|
98
|
+
*
|
|
99
|
+
* @param {string} [runtimeConfigDir] optional runtime config directory
|
|
100
|
+
* @returns {string} absolute path to the directory containing `skills/`
|
|
101
|
+
*/
|
|
102
|
+
function findInstallSourceRoot(runtimeConfigDir) {
|
|
103
|
+
// Step 1 — marker override
|
|
104
|
+
if (runtimeConfigDir) {
|
|
105
|
+
const markerPath = path.join(runtimeConfigDir, '.gdd-source');
|
|
106
|
+
if (fs.existsSync(markerPath)) {
|
|
107
|
+
try {
|
|
108
|
+
const src = fs.readFileSync(markerPath, 'utf8').trim();
|
|
109
|
+
if (src && fs.existsSync(src)) return src;
|
|
110
|
+
} catch {
|
|
111
|
+
/* fall through */
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Step 2 — walk up from __dirname looking for skills/
|
|
117
|
+
let dir = __dirname;
|
|
118
|
+
for (let i = 0; i < 6; i++) {
|
|
119
|
+
const candidate = path.join(dir, 'skills');
|
|
120
|
+
if (fs.existsSync(candidate)) return dir;
|
|
121
|
+
const parent = path.dirname(dir);
|
|
122
|
+
if (parent === dir) break;
|
|
123
|
+
dir = parent;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
throw new Error(
|
|
127
|
+
`findInstallSourceRoot: could not locate skills/ from ${__dirname}`
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// ---------------------------------------------------------------------------
|
|
132
|
+
// Kind factories
|
|
133
|
+
// ---------------------------------------------------------------------------
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* @typedef {'commands'|'agents'|'skills'} ArtifactKindName
|
|
137
|
+
*
|
|
138
|
+
* @typedef {Object} StageCtx
|
|
139
|
+
* @property {string} skillsRoot Absolute path to the GDD `skills/` dir.
|
|
140
|
+
* @property {string[]} skillNames Names of skill directories to stage.
|
|
141
|
+
* @property {'local'|'global'} scope
|
|
142
|
+
* @property {string} runtime
|
|
143
|
+
* @property {string} configDir
|
|
144
|
+
*
|
|
145
|
+
* @typedef {Object} StagedArtifact
|
|
146
|
+
* @property {string} srcPath Absolute path to the source file on disk.
|
|
147
|
+
* @property {string} content Converted content to be written.
|
|
148
|
+
* @property {string} name Final artifact name (prefix already applied).
|
|
149
|
+
*
|
|
150
|
+
* @typedef {Object} ArtifactKind
|
|
151
|
+
* @property {ArtifactKindName} kind
|
|
152
|
+
* @property {string} destSubpath
|
|
153
|
+
* @property {string} prefix
|
|
154
|
+
* @property {(ctx: StageCtx) => StagedArtifact[]} stage
|
|
155
|
+
*
|
|
156
|
+
* @typedef {Object} Layout
|
|
157
|
+
* @property {string} runtime
|
|
158
|
+
* @property {string} configDir
|
|
159
|
+
* @property {ArtifactKind[]} kinds
|
|
160
|
+
*/
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Build a `skills` artifact-kind descriptor.
|
|
164
|
+
*
|
|
165
|
+
* @param {string} destSubpath e.g. `'skills'`.
|
|
166
|
+
* @param {string} prefix e.g. `'gdd-'`.
|
|
167
|
+
* @param {string|null} converterPath relative require path to the converter
|
|
168
|
+
* module (e.g. `'./converters/cursor.cjs'`), or `null` for passthrough
|
|
169
|
+
* copy (claude global skills).
|
|
170
|
+
* @param {string} runtime canonical runtime ID, passed to converter as
|
|
171
|
+
* `{runtime}` so a multi-runtime converter can branch on it.
|
|
172
|
+
* @returns {ArtifactKind}
|
|
173
|
+
*/
|
|
174
|
+
function skillsKind(destSubpath, prefix, converterPath, runtime) {
|
|
175
|
+
return {
|
|
176
|
+
kind: 'skills',
|
|
177
|
+
destSubpath,
|
|
178
|
+
prefix,
|
|
179
|
+
stage: (ctx) => {
|
|
180
|
+
// Lazy require — converter is only loaded if/when an installer
|
|
181
|
+
// actually stages this runtime (D-08). For claude global, the
|
|
182
|
+
// converter is null and we passthrough-copy the source content.
|
|
183
|
+
const convert = converterPath ? require(converterPath).convert : null;
|
|
184
|
+
return ctx.skillNames.map((name) => {
|
|
185
|
+
const srcPath = path.join(ctx.skillsRoot, name, 'SKILL.md');
|
|
186
|
+
const raw = fs.readFileSync(srcPath, 'utf8');
|
|
187
|
+
const content = convert ? convert(raw, name, { runtime }) : raw;
|
|
188
|
+
return { srcPath, content, name: prefix + name };
|
|
189
|
+
});
|
|
190
|
+
},
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Build a `commands` artifact-kind descriptor.
|
|
196
|
+
*
|
|
197
|
+
* Used by:
|
|
198
|
+
* - claude local → `commands/gdd/`, no converter (passthrough copy)
|
|
199
|
+
* - gemini → `commands/gdd/`, gemini converter
|
|
200
|
+
* - opencode → `command/` (singular), opencode converter
|
|
201
|
+
* - kilo → `command/` (singular), kilo converter
|
|
202
|
+
*
|
|
203
|
+
* @param {string} destSubpath
|
|
204
|
+
* @param {string} prefix
|
|
205
|
+
* @param {string|null} converterPath
|
|
206
|
+
* @param {string} runtime
|
|
207
|
+
* @returns {ArtifactKind}
|
|
208
|
+
*/
|
|
209
|
+
function commandsKind(destSubpath, prefix, converterPath, runtime) {
|
|
210
|
+
return {
|
|
211
|
+
kind: 'commands',
|
|
212
|
+
destSubpath,
|
|
213
|
+
prefix,
|
|
214
|
+
stage: (ctx) => {
|
|
215
|
+
const convert = converterPath ? require(converterPath).convert : null;
|
|
216
|
+
return ctx.skillNames.map((name) => {
|
|
217
|
+
const srcPath = path.join(ctx.skillsRoot, name, 'SKILL.md');
|
|
218
|
+
const raw = fs.readFileSync(srcPath, 'utf8');
|
|
219
|
+
const content = convert ? convert(raw, name, { runtime }) : raw;
|
|
220
|
+
return { srcPath, content, name: prefix + name };
|
|
221
|
+
});
|
|
222
|
+
},
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Build an `agents` artifact-kind descriptor.
|
|
228
|
+
*
|
|
229
|
+
* claude local only — passthrough copy from `<repo>/agents/*` into
|
|
230
|
+
* `<configDir>/agents/`. No converter.
|
|
231
|
+
*
|
|
232
|
+
* @param {string} destSubpath
|
|
233
|
+
* @param {string} prefix
|
|
234
|
+
* @returns {ArtifactKind}
|
|
235
|
+
*/
|
|
236
|
+
function agentsKind(destSubpath, prefix) {
|
|
237
|
+
return {
|
|
238
|
+
kind: 'agents',
|
|
239
|
+
destSubpath,
|
|
240
|
+
prefix,
|
|
241
|
+
stage: (ctx) => {
|
|
242
|
+
const agentsRoot = path.join(
|
|
243
|
+
path.dirname(ctx.skillsRoot),
|
|
244
|
+
'agents'
|
|
245
|
+
);
|
|
246
|
+
return ctx.skillNames.map((name) => {
|
|
247
|
+
const srcPath = path.join(agentsRoot, name + '.md');
|
|
248
|
+
const raw = fs.existsSync(srcPath)
|
|
249
|
+
? fs.readFileSync(srcPath, 'utf8')
|
|
250
|
+
: '';
|
|
251
|
+
return { srcPath, content: raw, name: prefix + name };
|
|
252
|
+
});
|
|
253
|
+
},
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// ---------------------------------------------------------------------------
|
|
258
|
+
// Public API
|
|
259
|
+
// ---------------------------------------------------------------------------
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Resolve the artifact layout for `(runtime, configDir, scope)`.
|
|
263
|
+
*
|
|
264
|
+
* @param {string} runtime one of the 14 GDD runtimes (D-03).
|
|
265
|
+
* @param {string} configDir absolute path to the runtime's config directory
|
|
266
|
+
* (typically obtained from `runtime-homes.getGlobalConfigDir(runtime)`).
|
|
267
|
+
* @param {'local'|'global'} [scope] defaults to `'global'`.
|
|
268
|
+
* @returns {Layout}
|
|
269
|
+
* @throws {TypeError} on empty configDir, invalid scope, or unknown runtime.
|
|
270
|
+
*/
|
|
271
|
+
function resolveRuntimeArtifactLayout(runtime, configDir, scope = 'global') {
|
|
272
|
+
if (typeof configDir !== 'string' || configDir === '') {
|
|
273
|
+
throw new TypeError('configDir must be a non-empty string');
|
|
274
|
+
}
|
|
275
|
+
if (scope !== 'local' && scope !== 'global') {
|
|
276
|
+
throw new TypeError('scope must be "local" or "global"');
|
|
277
|
+
}
|
|
278
|
+
if (!ALLOWED_RUNTIMES.has(runtime)) {
|
|
279
|
+
throw new TypeError(
|
|
280
|
+
`Unknown runtime: '${runtime}' — add to runtime-artifact-layout.cjs ` +
|
|
281
|
+
`ALLOWED_RUNTIMES and switch table`
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
let kinds;
|
|
286
|
+
switch (runtime) {
|
|
287
|
+
case 'claude':
|
|
288
|
+
if (scope === 'local') {
|
|
289
|
+
kinds = [
|
|
290
|
+
commandsKind('commands/gdd', 'gdd-', null, 'claude'),
|
|
291
|
+
agentsKind('agents', 'gdd-'),
|
|
292
|
+
];
|
|
293
|
+
} else {
|
|
294
|
+
// Global claude install — passthrough skills/ tree (no conversion).
|
|
295
|
+
kinds = [skillsKind('skills', 'gdd-', null, 'claude')];
|
|
296
|
+
}
|
|
297
|
+
break;
|
|
298
|
+
|
|
299
|
+
case 'cursor':
|
|
300
|
+
kinds = [
|
|
301
|
+
skillsKind('skills', 'gdd-', './converters/cursor.cjs', 'cursor'),
|
|
302
|
+
];
|
|
303
|
+
break;
|
|
304
|
+
|
|
305
|
+
case 'gemini':
|
|
306
|
+
kinds = [
|
|
307
|
+
commandsKind(
|
|
308
|
+
'commands/gdd',
|
|
309
|
+
'gdd-',
|
|
310
|
+
'./converters/gemini.cjs',
|
|
311
|
+
'gemini'
|
|
312
|
+
),
|
|
313
|
+
];
|
|
314
|
+
break;
|
|
315
|
+
|
|
316
|
+
case 'codex':
|
|
317
|
+
kinds = [
|
|
318
|
+
skillsKind('skills', 'gdd-', './converters/codex.cjs', 'codex'),
|
|
319
|
+
];
|
|
320
|
+
break;
|
|
321
|
+
|
|
322
|
+
case 'copilot':
|
|
323
|
+
kinds = [
|
|
324
|
+
skillsKind('skills', 'gdd-', './converters/copilot.cjs', 'copilot'),
|
|
325
|
+
];
|
|
326
|
+
break;
|
|
327
|
+
|
|
328
|
+
case 'antigravity':
|
|
329
|
+
kinds = [
|
|
330
|
+
skillsKind(
|
|
331
|
+
'skills',
|
|
332
|
+
'gdd-',
|
|
333
|
+
'./converters/antigravity.cjs',
|
|
334
|
+
'antigravity'
|
|
335
|
+
),
|
|
336
|
+
];
|
|
337
|
+
break;
|
|
338
|
+
|
|
339
|
+
case 'windsurf':
|
|
340
|
+
kinds = [
|
|
341
|
+
skillsKind(
|
|
342
|
+
'skills',
|
|
343
|
+
'gdd-',
|
|
344
|
+
'./converters/windsurf.cjs',
|
|
345
|
+
'windsurf'
|
|
346
|
+
),
|
|
347
|
+
];
|
|
348
|
+
break;
|
|
349
|
+
|
|
350
|
+
case 'augment':
|
|
351
|
+
kinds = [
|
|
352
|
+
skillsKind('skills', 'gdd-', './converters/augment.cjs', 'augment'),
|
|
353
|
+
];
|
|
354
|
+
break;
|
|
355
|
+
|
|
356
|
+
case 'trae':
|
|
357
|
+
kinds = [
|
|
358
|
+
skillsKind('skills', 'gdd-', './converters/trae.cjs', 'trae'),
|
|
359
|
+
];
|
|
360
|
+
break;
|
|
361
|
+
|
|
362
|
+
case 'qwen':
|
|
363
|
+
// Qwen Code uses claude-shape per gsd-build precedent (their converter
|
|
364
|
+
// re-uses convertClaudeCommandToClaudeSkill with runtime='qwen'). Our
|
|
365
|
+
// modular equivalent is `./converters/qwen.cjs` (Plan 28.7-05 ships).
|
|
366
|
+
kinds = [
|
|
367
|
+
skillsKind('skills', 'gdd-', './converters/qwen.cjs', 'qwen'),
|
|
368
|
+
];
|
|
369
|
+
break;
|
|
370
|
+
|
|
371
|
+
case 'codebuddy':
|
|
372
|
+
kinds = [
|
|
373
|
+
skillsKind(
|
|
374
|
+
'skills',
|
|
375
|
+
'gdd-',
|
|
376
|
+
'./converters/codebuddy.cjs',
|
|
377
|
+
'codebuddy'
|
|
378
|
+
),
|
|
379
|
+
];
|
|
380
|
+
break;
|
|
381
|
+
|
|
382
|
+
case 'cline':
|
|
383
|
+
// D-09: Cline is rules-based, not skills-based. No skills/ directory
|
|
384
|
+
// is created. Plan 28.7-06's `./converters/cline.cjs` emits a
|
|
385
|
+
// `.clinerules` rule-block at install time; Plan 28.7-08's
|
|
386
|
+
// `installer.cjs` special-cases the empty-kinds + cline-converter
|
|
387
|
+
// combination. We surface the routing hint via `specialCase` so
|
|
388
|
+
// installer code can branch without re-encoding the rule.
|
|
389
|
+
kinds = [];
|
|
390
|
+
break;
|
|
391
|
+
|
|
392
|
+
case 'opencode':
|
|
393
|
+
kinds = [
|
|
394
|
+
commandsKind(
|
|
395
|
+
'command',
|
|
396
|
+
'gdd-',
|
|
397
|
+
'./converters/opencode.cjs',
|
|
398
|
+
'opencode'
|
|
399
|
+
),
|
|
400
|
+
];
|
|
401
|
+
break;
|
|
402
|
+
|
|
403
|
+
case 'kilo':
|
|
404
|
+
kinds = [
|
|
405
|
+
commandsKind('command', 'gdd-', './converters/kilo.cjs', 'kilo'),
|
|
406
|
+
];
|
|
407
|
+
break;
|
|
408
|
+
|
|
409
|
+
/* istanbul ignore next — defensive (ALLOWED_RUNTIMES guard above). */
|
|
410
|
+
default:
|
|
411
|
+
throw new TypeError(
|
|
412
|
+
`Unknown runtime: '${runtime}' — switch table not synced with ` +
|
|
413
|
+
`ALLOWED_RUNTIMES`
|
|
414
|
+
);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
const layout = { runtime, configDir, kinds };
|
|
418
|
+
if (runtime === 'cline') {
|
|
419
|
+
// D-09 routing hint — kept distinct from `kinds` so callers can detect
|
|
420
|
+
// the rules-based runtime without scanning for empty arrays.
|
|
421
|
+
layout.specialCase = 'clinerules-embed';
|
|
422
|
+
layout.converterName = 'cline';
|
|
423
|
+
}
|
|
424
|
+
return layout;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
module.exports = {
|
|
428
|
+
resolveRuntimeArtifactLayout,
|
|
429
|
+
findInstallSourceRoot,
|
|
430
|
+
ALLOWED_RUNTIMES,
|
|
431
|
+
};
|