@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.
Files changed (71) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +102 -0
  4. package/README.md +2 -0
  5. package/package.json +1 -1
  6. package/reference/registry.json +0 -140
  7. package/reference/skill-authoring-contract.md +40 -9
  8. package/scripts/install.cjs +7 -0
  9. package/scripts/lib/install/converters/antigravity.cjs +48 -0
  10. package/scripts/lib/install/converters/augment.cjs +68 -0
  11. package/scripts/lib/install/converters/cline.cjs +206 -0
  12. package/scripts/lib/install/converters/codebuddy.cjs +55 -0
  13. package/scripts/lib/install/converters/codex.cjs +61 -0
  14. package/scripts/lib/install/converters/copilot.cjs +47 -0
  15. package/scripts/lib/install/converters/cursor.cjs +49 -0
  16. package/scripts/lib/install/converters/gemini.cjs +116 -0
  17. package/scripts/lib/install/converters/kilo.cjs +62 -0
  18. package/scripts/lib/install/converters/opencode.cjs +64 -0
  19. package/scripts/lib/install/converters/qwen.cjs +51 -0
  20. package/scripts/lib/install/converters/shared.cjs +377 -0
  21. package/scripts/lib/install/converters/trae.cjs +47 -0
  22. package/scripts/lib/install/converters/windsurf.cjs +47 -0
  23. package/scripts/lib/install/installer.cjs +529 -47
  24. package/scripts/lib/install/merge.cjs +31 -1
  25. package/scripts/lib/install/runtime-artifact-layout.cjs +431 -0
  26. package/scripts/lib/install/runtime-homes.cjs +225 -0
  27. package/scripts/lib/install/runtime-slash.cjs +172 -0
  28. package/scripts/lib/install/runtimes.cjs +25 -32
  29. package/skills/apply-reflections/SKILL.md +1 -1
  30. package/skills/cache-manager/SKILL.md +2 -2
  31. package/skills/compare/SKILL.md +8 -8
  32. package/skills/connections/SKILL.md +9 -9
  33. package/skills/darkmode/SKILL.md +8 -8
  34. package/skills/debug/SKILL.md +3 -3
  35. package/skills/design/SKILL.md +6 -6
  36. package/skills/discover/SKILL.md +7 -7
  37. package/skills/explore/SKILL.md +6 -6
  38. package/skills/health/SKILL.md +2 -2
  39. package/skills/new-cycle/SKILL.md +1 -1
  40. package/skills/peer-cli-add/SKILL.md +6 -6
  41. package/skills/peer-cli-customize/SKILL.md +5 -5
  42. package/skills/peers/SKILL.md +2 -2
  43. package/skills/plan/SKILL.md +10 -10
  44. package/skills/quality-gate/SKILL.md +1 -1
  45. package/skills/router/SKILL.md +3 -3
  46. package/skills/scan/SKILL.md +17 -17
  47. package/skills/start/SKILL.md +1 -1
  48. package/skills/style/SKILL.md +5 -5
  49. package/skills/turn-closeout/SKILL.md +1 -1
  50. package/skills/verify/SKILL.md +10 -10
  51. package/skills/warm-cache/SKILL.md +2 -2
  52. /package/{reference → skills/apply-reflections}/apply-reflections-procedure.md +0 -0
  53. /package/{reference → skills/cache-manager}/cache-policy.md +0 -0
  54. /package/{reference → skills/compare}/compare-rubric.md +0 -0
  55. /package/{reference → skills/connections}/connections-onboarding.md +0 -0
  56. /package/{reference → skills/darkmode}/darkmode-audit-procedure.md +0 -0
  57. /package/{reference → skills/debug}/debug-feedback-loops.md +0 -0
  58. /package/{reference → skills/design}/design-procedure.md +0 -0
  59. /package/{reference → skills/discover}/discover-procedure.md +0 -0
  60. /package/{reference → skills/explore}/explore-procedure.md +0 -0
  61. /package/{reference → skills/health}/health-mcp-detection.md +0 -0
  62. /package/{reference → skills/health}/health-skill-length-report.md +0 -0
  63. /package/{reference → skills/new-cycle}/milestone-completeness-rubric.md +0 -0
  64. /package/{reference → skills/peer-cli-add}/peer-cli-protocol.md +0 -0
  65. /package/{reference → skills/plan}/plan-procedure.md +0 -0
  66. /package/{reference → skills/quality-gate}/threat-modeling.md +0 -0
  67. /package/{reference → skills/router}/router-rules.md +0 -0
  68. /package/{reference → skills/scan}/scan-procedure.md +0 -0
  69. /package/{reference → skills/start}/start-procedure.md +0 -0
  70. /package/{reference → skills/style}/style-doc-procedure.md +0 -0
  71. /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
- return content.includes(PLUGIN_FINGERPRINT);
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
+ };