devlyn-cli 3.3.0 → 4.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.
- package/AGENTS.md +8 -8
- package/CLAUDE.md +17 -17
- package/README.md +47 -34
- package/bin/devlyn.js +104 -67
- package/bin/instruction-templates.json +26 -0
- package/config/skills/_shared/adapters/README.md +1 -1
- package/config/skills/_shared/adapters/omp.md +2 -2
- package/config/skills/_shared/archive_run.py +2 -2
- package/config/skills/_shared/codex-config.md +3 -3
- package/config/skills/_shared/engine-doctor.sh +1 -1
- package/config/skills/_shared/engine-preflight.md +5 -5
- package/config/skills/_shared/finish-gate.py +1 -1
- package/config/skills/_shared/resolve-bootstrap.py +2 -2
- package/config/skills/_shared/runtime-principles.md +6 -6
- package/config/skills/_shared/spec-verify-check.py +3 -3
- package/config/skills/_shared/task-complete.py +32 -14
- package/config/skills/{devlyn:design-ui → devlyn-design-ui}/SKILL.md +1 -1
- package/config/skills/{devlyn:engines → devlyn-engines}/SKILL.md +2 -2
- package/config/skills/{devlyn:ideate → devlyn-ideate}/SKILL.md +10 -10
- package/config/skills/{devlyn:ideate → devlyn-ideate}/references/elicitation.md +2 -2
- package/config/skills/{devlyn:ideate → devlyn-ideate}/references/from-spec-mode.md +2 -2
- package/config/skills/{devlyn:ideate → devlyn-ideate}/references/project-mode.md +5 -5
- package/config/skills/{devlyn:ideate → devlyn-ideate}/references/spec-template.md +1 -1
- package/config/skills/{devlyn:queue → devlyn-queue}/SKILL.md +6 -6
- package/config/skills/{devlyn:resolve → devlyn-resolve}/SKILL.md +4 -4
- package/config/skills/{devlyn:resolve → devlyn-resolve}/references/free-form-mode.md +3 -3
- package/config/skills/{devlyn:resolve → devlyn-resolve}/references/outer-loop.md +1 -1
- package/config/skills/{devlyn:resolve → devlyn-resolve}/references/state-schema.md +1 -1
- package/config/skills/{devlyn:resolve → devlyn-resolve}/references/task-completion.md +5 -5
- package/config/templates/prompt-templates.md +2 -2
- package/optional-skills/{devlyn:pencil-pull → devlyn-pencil-pull}/SKILL.md +1 -1
- package/optional-skills/{devlyn:pencil-push → devlyn-pencil-push}/SKILL.md +1 -1
- package/optional-skills/{devlyn:reap → devlyn-reap}/SKILL.md +5 -5
- package/optional-skills/{devlyn:reap → devlyn-reap}/scripts/reap.sh +1 -1
- package/optional-skills/{devlyn:reap → devlyn-reap}/scripts/scan.sh +1 -1
- package/package.json +3 -1
- /package/config/skills/{devlyn:ideate → devlyn-ideate}/references/templates/decision.md +0 -0
- /package/config/skills/{devlyn:ideate → devlyn-ideate}/references/templates/roadmap.md +0 -0
- /package/config/skills/{devlyn:ideate → devlyn-ideate}/references/templates/vision.md +0 -0
- /package/config/skills/{devlyn:resolve → devlyn-resolve}/references/phases/build-gate.md +0 -0
- /package/config/skills/{devlyn:resolve → devlyn-resolve}/references/phases/cleanup.md +0 -0
- /package/config/skills/{devlyn:resolve → devlyn-resolve}/references/phases/implement.md +0 -0
- /package/config/skills/{devlyn:resolve → devlyn-resolve}/references/phases/plan.md +0 -0
- /package/config/skills/{devlyn:resolve → devlyn-resolve}/references/phases/probe-derive.md +0 -0
- /package/config/skills/{devlyn:resolve → devlyn-resolve}/references/phases/surface-close.md +0 -0
- /package/config/skills/{devlyn:resolve → devlyn-resolve}/references/phases/verify.md +0 -0
package/bin/devlyn.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
const crypto = require('crypto');
|
|
3
4
|
const fs = require('fs');
|
|
4
5
|
const path = require('path');
|
|
5
6
|
const os = require('os');
|
|
@@ -14,35 +15,44 @@ const { updateInstructions, InstructionError } = require('./instructions');
|
|
|
14
15
|
// The devlyn skill bundle installed into every skill-capable agent's loader
|
|
15
16
|
// directory. Single source of truth so codex/omp/pi stay in lockstep — adding a
|
|
16
17
|
// skill here installs it everywhere.
|
|
17
|
-
const DEVLYN_CORE_SKILLS = ['devlyn
|
|
18
|
+
const DEVLYN_CORE_SKILLS = ['devlyn-resolve', 'devlyn-ideate', 'devlyn-design-ui', 'devlyn-engines', 'devlyn-queue', '_shared'];
|
|
19
|
+
// 4.0.0 renamed the colon-named skills to the Agent Skills standard (`[a-z0-9-]`, name ==
|
|
20
|
+
// folder): Git for Windows cannot check out a folder with ':' in its name. Installs from 3.x
|
|
21
|
+
// and earlier keep the old folder under either spelling (':' or npm's U+F03A extraction
|
|
22
|
+
// alias). Both are removed, and an optional skill that was installed is installed again
|
|
23
|
+
// under its new name in the same place.
|
|
24
|
+
const RENAMED_SKILLS = {
|
|
25
|
+
'devlyn:resolve': 'devlyn-resolve',
|
|
26
|
+
'devlyn:ideate': 'devlyn-ideate',
|
|
27
|
+
'devlyn:design-ui': 'devlyn-design-ui',
|
|
28
|
+
'devlyn:engines': 'devlyn-engines',
|
|
29
|
+
'devlyn:queue': 'devlyn-queue',
|
|
30
|
+
'devlyn:pencil-pull': 'devlyn-pencil-pull',
|
|
31
|
+
'devlyn:pencil-push': 'devlyn-pencil-push',
|
|
32
|
+
'devlyn:reap': 'devlyn-reap',
|
|
33
|
+
};
|
|
18
34
|
const DEVLYN_SKILL_DIR_STAMP = '__DEVLYN_SKILL_DIR__';
|
|
19
35
|
const DEVLYN_INSTALL_MARKER = '.devlyn-install.json';
|
|
20
36
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
function physicalSkillName(name) {
|
|
26
|
-
return process.platform === 'win32' ? name.replace(/:/g, '\uF03A') : name;
|
|
37
|
+
// Every spelling a colon name can have on disk: its own and npm's U+F03A extraction alias.
|
|
38
|
+
function legacySkillPaths(root, name) {
|
|
39
|
+
return [...new Set([name, name.replace(/:/g, '\uF03A')])].map((spelling) => path.join(root, spelling));
|
|
27
40
|
}
|
|
28
41
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
42
|
+
// SKILL.md of the pencil skills 0.6.0-0.7.1 installed under today's names, without the
|
|
43
|
+
// frontmatter the standard requires, hashed with LF line endings (a Windows checkout may hold
|
|
44
|
+
// CRLF). 3.x deleted these copies; 4.0 replaces them.
|
|
45
|
+
const PRE_STANDARD_SKILL_MD_SHA256 = new Set([
|
|
46
|
+
'dfdd3d19ca676558bfa2bb3ce398181b0a081ab88d1feaf69c54c706a9671631', // devlyn-pencil-pull
|
|
47
|
+
'5f2e8b29609cbb2af72941579823bec598265ebf29cd3a375d6aa47d95b74354', // devlyn-pencil-push
|
|
48
|
+
]);
|
|
37
49
|
|
|
38
|
-
function
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
skillPath(target, path.basename(relative));
|
|
45
|
-
}
|
|
50
|
+
function isPreStandardCopy(dir) {
|
|
51
|
+
const skill = path.join(dir, 'SKILL.md');
|
|
52
|
+
return fs.lstatSync(dir, { throwIfNoEntry: false })?.isDirectory() === true
|
|
53
|
+
&& fs.lstatSync(skill, { throwIfNoEntry: false })?.isFile() === true
|
|
54
|
+
&& PRE_STANDARD_SKILL_MD_SHA256.has(crypto.createHash('sha256')
|
|
55
|
+
.update(fs.readFileSync(skill, 'utf8').replace(/\r\n/g, '\n')).digest('hex'));
|
|
46
56
|
}
|
|
47
57
|
|
|
48
58
|
// Cross-agent shared skills directory read by BOTH oh-my-pi and Pi. Verified
|
|
@@ -134,21 +144,17 @@ const DEPRECATED_DIRS = [
|
|
|
134
144
|
// v0.7.x rename: devlyn-* → devlyn:*
|
|
135
145
|
'skills/devlyn-clean',
|
|
136
146
|
'skills/devlyn-design-system',
|
|
137
|
-
'skills/devlyn-design-ui',
|
|
138
147
|
'skills/devlyn-discover-product',
|
|
139
148
|
'skills/devlyn-evaluate',
|
|
140
149
|
'skills/devlyn-feature-spec',
|
|
141
150
|
'skills/devlyn-implement-ui',
|
|
142
151
|
'skills/devlyn-product-spec',
|
|
143
152
|
'skills/devlyn-recommend-features',
|
|
144
|
-
'skills/devlyn-resolve',
|
|
145
153
|
'skills/devlyn-review',
|
|
146
154
|
'skills/devlyn-team-design-ui',
|
|
147
155
|
'skills/devlyn-team-resolve',
|
|
148
156
|
'skills/devlyn-team-review',
|
|
149
157
|
'skills/devlyn-update-docs',
|
|
150
|
-
'skills/devlyn-pencil-pull',
|
|
151
|
-
'skills/devlyn-pencil-push',
|
|
152
158
|
// iter-0034 Phase 4 cutover: deleted user skills
|
|
153
159
|
'skills/devlyn:auto-resolve',
|
|
154
160
|
'skills/devlyn:browser-validate',
|
|
@@ -164,10 +170,6 @@ const DEPRECATED_DIRS = [
|
|
|
164
170
|
'skills/devlyn:team-resolve',
|
|
165
171
|
'skills/devlyn:team-review',
|
|
166
172
|
'skills/devlyn:update-docs',
|
|
167
|
-
// iter-0034 Phase 4 cutover: moved to optional-skills/. Force-removed on
|
|
168
|
-
// upgrade so users only have them if they opt in via the interactive
|
|
169
|
-
// installer (matches the pencil-pull / pencil-push pattern).
|
|
170
|
-
'skills/devlyn:reap',
|
|
171
173
|
// 0221 Session 1: standards skills moved to optional-skills/ (opt-in).
|
|
172
174
|
'skills/code-health-standards',
|
|
173
175
|
'skills/code-review-standards',
|
|
@@ -238,9 +240,9 @@ const OPTIONAL_ADDONS = [
|
|
|
238
240
|
{ name: 'polar-billing-setup', desc: 'Polar usage-based / metered billing — correct setup + diagnose silent $0-billing failures', type: 'local' },
|
|
239
241
|
{ name: 'pyx-scan', desc: 'Check whether an AI agent skill is safe before installing', type: 'local' },
|
|
240
242
|
{ name: 'dokkit', desc: 'Document template filling for DOCX/HWPX — ingest, fill, review, export', type: 'local' },
|
|
241
|
-
{ name: 'devlyn
|
|
242
|
-
{ name: 'devlyn
|
|
243
|
-
{ name: 'devlyn
|
|
243
|
+
{ name: 'devlyn-pencil-pull', desc: 'Pull Pencil designs into code with exact visual fidelity', type: 'local' },
|
|
244
|
+
{ name: 'devlyn-pencil-push', desc: 'Push codebase UI to Pencil canvas for design sync', type: 'local' },
|
|
245
|
+
{ name: 'devlyn-reap', desc: 'Safely reap orphaned MCP / codex / Superset child processes left behind by long Claude sessions', type: 'local' },
|
|
244
246
|
{ name: 'code-health-standards', desc: 'Maintainability standards — dead code, dependencies, complexity, naming, hygiene', type: 'local' },
|
|
245
247
|
{ name: 'code-review-standards', desc: 'Severity framework and approval criteria for reviewing a change', type: 'local' },
|
|
246
248
|
{ name: 'root-cause-analysis', desc: 'Evidence-first why-chain debugging to the actionable root cause', type: 'local' },
|
|
@@ -255,7 +257,7 @@ const OPTIONAL_ADDONS = [
|
|
|
255
257
|
// Note: the Codex integration uses the local `codex` CLI binary (not MCP).
|
|
256
258
|
// Install the CLI separately per https://platform.openai.com/docs/codex — the
|
|
257
259
|
// pair/risk-probe routes fail closed when Codex is required but unavailable.
|
|
258
|
-
{ name: 'playwright', desc: 'Playwright MCP for browser testing — powers /devlyn
|
|
260
|
+
{ name: 'playwright', desc: 'Playwright MCP for browser testing — powers /devlyn-resolve BUILD_GATE browser tier', type: 'mcp', command: 'npx -y @playwright/mcp@latest' },
|
|
259
261
|
];
|
|
260
262
|
|
|
261
263
|
function log(msg, color = 'reset') {
|
|
@@ -349,8 +351,8 @@ function listContents() {
|
|
|
349
351
|
|
|
350
352
|
function cleanupDeprecated(targetDir) {
|
|
351
353
|
let removed = 0;
|
|
352
|
-
const deprecated = DEPRECATED_DIRS.
|
|
353
|
-
|
|
354
|
+
const deprecated = DEPRECATED_DIRS.flatMap((relPath) =>
|
|
355
|
+
legacySkillPaths(path.join(targetDir, 'skills'), path.basename(relPath)).map((fullPath) => [relPath, fullPath]));
|
|
354
356
|
for (const relPath of DEPRECATED_FILES) {
|
|
355
357
|
const fullPath = path.join(targetDir, relPath);
|
|
356
358
|
if (fs.existsSync(fullPath)) {
|
|
@@ -369,19 +371,35 @@ function cleanupDeprecated(targetDir) {
|
|
|
369
371
|
return removed;
|
|
370
372
|
}
|
|
371
373
|
|
|
374
|
+
// Remove every old spelling of the renamed skills in `skillsDir`, after the new core skills
|
|
375
|
+
// are in place. An optional skill found under an old spelling is installed under its new name
|
|
376
|
+
// before the old copy goes, so an interrupted migration never loses it. An unedited 0.6.0-0.7.1
|
|
377
|
+
// copy is refreshed in place. Any other folder under a 4.0 name is the user's own; `-y` leaves it.
|
|
378
|
+
function retireRenamedSkills(skillsDir) {
|
|
379
|
+
const optional = new Set(OPTIONAL_ADDONS.filter((addon) => addon.type === 'local').map((addon) => addon.name));
|
|
380
|
+
for (const [oldName, newName] of Object.entries(RENAMED_SKILLS)) {
|
|
381
|
+
const found = legacySkillPaths(skillsDir, oldName).filter((fullPath) => fs.existsSync(fullPath));
|
|
382
|
+
if (found.length > 0 && optional.has(newName)) installOptionalSkillInto(skillsDir, newName);
|
|
383
|
+
else if (isPreStandardCopy(path.join(skillsDir, newName))) refreshPreStandardCopy(skillsDir, newName);
|
|
384
|
+
for (const fullPath of found) {
|
|
385
|
+
fs.rmSync(fullPath, { recursive: true, force: true });
|
|
386
|
+
log(` ✕ ${path.basename(fullPath)}/ (renamed to ${newName})`, 'dim');
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
372
391
|
function copyRecursive(src, dest, baseDir) {
|
|
373
392
|
const stats = fs.statSync(src);
|
|
374
393
|
|
|
375
394
|
if (stats.isDirectory()) {
|
|
376
395
|
// Never install dev workspaces, even when running from source repo.
|
|
377
|
-
if (UNSHIPPED_SKILL_DIRS.has(
|
|
396
|
+
if (UNSHIPPED_SKILL_DIRS.has(path.basename(src))) return;
|
|
378
397
|
if (!fs.existsSync(dest)) {
|
|
379
398
|
fs.mkdirSync(dest, { recursive: true });
|
|
380
399
|
}
|
|
381
400
|
|
|
382
401
|
for (const item of fs.readdirSync(src)) {
|
|
383
|
-
|
|
384
|
-
copyRecursive(path.join(src, item), path.join(dest, name), baseDir);
|
|
402
|
+
copyRecursive(path.join(src, item), path.join(dest, item), baseDir);
|
|
385
403
|
}
|
|
386
404
|
} else {
|
|
387
405
|
const destDir = path.dirname(dest);
|
|
@@ -407,8 +425,8 @@ function assertCompleteSkillInstall(sourceSkillsDir, skillsDir, skillNames) {
|
|
|
407
425
|
return fs.statSync(dest).isFile();
|
|
408
426
|
}
|
|
409
427
|
const missing = skillNames.filter((name) => {
|
|
410
|
-
const src =
|
|
411
|
-
const dest =
|
|
428
|
+
const src = path.join(sourceSkillsDir, name);
|
|
429
|
+
const dest = path.join(skillsDir, name);
|
|
412
430
|
return !complete(src, dest) || (name !== '_shared' && !fs.existsSync(path.join(src, 'SKILL.md')));
|
|
413
431
|
});
|
|
414
432
|
if (missing.length > 0) {
|
|
@@ -475,6 +493,7 @@ function stampInstalledSkillDir(rootDir, skillDir) {
|
|
|
475
493
|
const UNSHIPPED_SKILL_DIRS = new Set([
|
|
476
494
|
'devlyn:auto-resolve-workspace',
|
|
477
495
|
'devlyn:ideate-workspace',
|
|
496
|
+
'devlyn-ideate-workspace',
|
|
478
497
|
'preflight-workspace',
|
|
479
498
|
'roadmap-archival-workspace',
|
|
480
499
|
]);
|
|
@@ -488,12 +507,11 @@ const UNSHIPPED_SKILL_DIRS = new Set([
|
|
|
488
507
|
// no counterpart in source. Dev workspaces are skipped entirely.
|
|
489
508
|
function cleanManagedSkillDirs(sourceSkillsDir, targetSkillsDir) {
|
|
490
509
|
if (!fs.existsSync(sourceSkillsDir) || !fs.existsSync(targetSkillsDir)) return 0;
|
|
491
|
-
preflightSkillDirs(sourceSkillsDir, targetSkillsDir, fs.readdirSync(sourceSkillsDir));
|
|
492
510
|
let cleaned = 0;
|
|
493
511
|
for (const entry of fs.readdirSync(sourceSkillsDir, { withFileTypes: true })) {
|
|
494
512
|
if (!entry.isDirectory()) continue;
|
|
495
|
-
if (UNSHIPPED_SKILL_DIRS.has(
|
|
496
|
-
const targetPath =
|
|
513
|
+
if (UNSHIPPED_SKILL_DIRS.has(entry.name)) continue;
|
|
514
|
+
const targetPath = path.join(targetSkillsDir, entry.name);
|
|
497
515
|
if (fs.existsSync(targetPath)) {
|
|
498
516
|
fs.rmSync(targetPath, { recursive: true, force: true });
|
|
499
517
|
cleaned++;
|
|
@@ -596,11 +614,10 @@ function multiSelect(items, preselectedIndices = []) {
|
|
|
596
614
|
}
|
|
597
615
|
|
|
598
616
|
function installLocalSkill(skillName) {
|
|
599
|
-
const src =
|
|
617
|
+
const src = path.join(OPTIONAL_SKILLS_SOURCE, skillName);
|
|
600
618
|
const targetDir = getTargetDir();
|
|
601
619
|
const targets = new Set([path.join(targetDir, 'skills'), ...Object.values(CLI_TARGETS)
|
|
602
620
|
.map((cli) => cli.skillsDir).filter((dir) => dir && fs.existsSync(dir))]);
|
|
603
|
-
for (const target of targets) skillPath(target, skillName);
|
|
604
621
|
|
|
605
622
|
if (!fs.existsSync(src)) {
|
|
606
623
|
log(` ⚠️ Skill "${skillName}" not found`, 'yellow');
|
|
@@ -615,16 +632,38 @@ function installLocalSkill(skillName) {
|
|
|
615
632
|
// create an agent install just because someone opted into a Claude-side skill.
|
|
616
633
|
// De-dup by directory: omp and Pi share ~/.agents/skills, so the mirror runs
|
|
617
634
|
// once per unique destination.
|
|
618
|
-
for (const target of targets)
|
|
619
|
-
fs.rmSync(skillPath(target, skillName), { recursive: true, force: true });
|
|
620
|
-
const dest = path.join(target, physicalSkillName(skillName));
|
|
621
|
-
copyRecursive(src, dest, target);
|
|
622
|
-
stampInstalledSkillDir(dest, dest);
|
|
623
|
-
assertCompleteSkillInstall(OPTIONAL_SKILLS_SOURCE, target, [skillName]);
|
|
624
|
-
}
|
|
635
|
+
for (const target of targets) installOptionalSkillInto(target, skillName);
|
|
625
636
|
return true;
|
|
626
637
|
}
|
|
627
638
|
|
|
639
|
+
// One optional skill into one skill-loader directory, replacing any older copy of it. A
|
|
640
|
+
// copy under its name before the 4.0.0 rename goes only once the new one is complete.
|
|
641
|
+
function installOptionalSkillInto(target, skillName) {
|
|
642
|
+
const dest = path.join(target, skillName);
|
|
643
|
+
fs.rmSync(dest, { recursive: true, force: true });
|
|
644
|
+
copyRecursive(path.join(OPTIONAL_SKILLS_SOURCE, skillName), dest, target);
|
|
645
|
+
stampInstalledSkillDir(dest, dest);
|
|
646
|
+
assertCompleteSkillInstall(OPTIONAL_SKILLS_SOURCE, target, [skillName]);
|
|
647
|
+
const oldName = Object.keys(RENAMED_SKILLS).find((name) => RENAMED_SKILLS[name] === skillName);
|
|
648
|
+
for (const fullPath of oldName ? legacySkillPaths(target, oldName) : []) {
|
|
649
|
+
fs.rmSync(fullPath, { recursive: true, force: true });
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
// A 0.6.0-0.7.1 copy is one SKILL.md, the file that identifies it. Renaming the new one over it is
|
|
654
|
+
// atomic, so an interrupted run leaves the old copy, which the retry finds again, or the new.
|
|
655
|
+
function refreshPreStandardCopy(target, skillName) {
|
|
656
|
+
const skill = path.join(target, skillName, 'SKILL.md');
|
|
657
|
+
const staged = `${skill}.${process.pid}.tmp`;
|
|
658
|
+
try {
|
|
659
|
+
fs.copyFileSync(path.join(OPTIONAL_SKILLS_SOURCE, skillName, 'SKILL.md'), staged);
|
|
660
|
+
fs.renameSync(staged, skill);
|
|
661
|
+
} finally {
|
|
662
|
+
fs.rmSync(staged, { force: true });
|
|
663
|
+
}
|
|
664
|
+
assertCompleteSkillInstall(OPTIONAL_SKILLS_SOURCE, target, [skillName]);
|
|
665
|
+
}
|
|
666
|
+
|
|
628
667
|
function installMcpServer(name, command) {
|
|
629
668
|
try {
|
|
630
669
|
log(`\n🔌 Installing MCP server: ${name}...`, 'cyan');
|
|
@@ -681,7 +720,6 @@ function installSkillsForCLI(cliKey) {
|
|
|
681
720
|
fs.mkdirSync(cli.skillsDir, { recursive: true });
|
|
682
721
|
}
|
|
683
722
|
clearInstallMarker(cli.skillsDir);
|
|
684
|
-
preflightSkillDirs(sourceSkillsDir, cli.skillsDir, cli.skillsToInstall);
|
|
685
723
|
|
|
686
724
|
const removed = cleanupDeprecated(path.dirname(cli.skillsDir));
|
|
687
725
|
if (removed > 0) {
|
|
@@ -690,14 +728,13 @@ function installSkillsForCLI(cliKey) {
|
|
|
690
728
|
|
|
691
729
|
let copied = 0;
|
|
692
730
|
for (const skillName of cli.skillsToInstall) {
|
|
693
|
-
const src =
|
|
694
|
-
const
|
|
695
|
-
const dest = path.join(cli.skillsDir, physicalSkillName(skillName));
|
|
731
|
+
const src = path.join(sourceSkillsDir, skillName);
|
|
732
|
+
const dest = path.join(cli.skillsDir, skillName);
|
|
696
733
|
if (!fs.existsSync(src)) continue;
|
|
697
734
|
// Full replace per cleanManagedSkillDirs semantics: stale files in the
|
|
698
735
|
// installed mirror would otherwise persist forever.
|
|
699
|
-
if (fs.existsSync(
|
|
700
|
-
fs.rmSync(
|
|
736
|
+
if (fs.existsSync(dest)) {
|
|
737
|
+
fs.rmSync(dest, { recursive: true, force: true });
|
|
701
738
|
}
|
|
702
739
|
copyRecursive(src, dest, cli.skillsDir);
|
|
703
740
|
stampInstalledSkillDir(dest, dest);
|
|
@@ -705,6 +742,7 @@ function installSkillsForCLI(cliKey) {
|
|
|
705
742
|
log(` → ${cli.skillsDir.replace(os.homedir(), '~')}/${skillName}`, 'dim');
|
|
706
743
|
}
|
|
707
744
|
assertCompleteSkillInstall(sourceSkillsDir, cli.skillsDir, cli.skillsToInstall);
|
|
745
|
+
retireRenamedSkills(cli.skillsDir);
|
|
708
746
|
writeInstallMarker(cli.skillsDir);
|
|
709
747
|
return copied;
|
|
710
748
|
}
|
|
@@ -803,6 +841,10 @@ function installClaudeCore() {
|
|
|
803
841
|
log('\n📁 Installing Claude Code config to .claude/', 'green');
|
|
804
842
|
if (!fs.existsSync(skillsDir)) fs.mkdirSync(skillsDir, { recursive: true });
|
|
805
843
|
clearInstallMarker(skillsDir);
|
|
844
|
+
const removed = cleanupDeprecated(targetDir);
|
|
845
|
+
if (removed > 0) {
|
|
846
|
+
log(`\n🧹 Cleaned up ${removed} deprecated file${removed > 1 ? 's' : ''}`, 'yellow');
|
|
847
|
+
}
|
|
806
848
|
const refreshed = cleanManagedSkillDirs(
|
|
807
849
|
path.join(CONFIG_SOURCE, 'skills'),
|
|
808
850
|
skillsDir,
|
|
@@ -813,17 +855,12 @@ function installClaudeCore() {
|
|
|
813
855
|
copyRecursive(CONFIG_SOURCE, targetDir, targetDir);
|
|
814
856
|
assertCompleteSkillInstall(path.join(CONFIG_SOURCE, 'skills'), skillsDir, DEVLYN_CORE_SKILLS);
|
|
815
857
|
for (const name of DEVLYN_CORE_SKILLS) {
|
|
816
|
-
const dest =
|
|
858
|
+
const dest = path.join(skillsDir, name);
|
|
817
859
|
stampInstalledSkillDir(dest, dest);
|
|
818
860
|
}
|
|
861
|
+
retireRenamedSkills(skillsDir);
|
|
819
862
|
writeInstallMarker(skillsDir);
|
|
820
863
|
|
|
821
|
-
// Remove deprecated files from previous versions
|
|
822
|
-
const removed = cleanupDeprecated(targetDir);
|
|
823
|
-
if (removed > 0) {
|
|
824
|
-
log(`\n🧹 Cleaned up ${removed} deprecated file${removed > 1 ? 's' : ''}`, 'yellow');
|
|
825
|
-
}
|
|
826
|
-
|
|
827
864
|
// Keep installer-managed pipeline state and install metadata out of git.
|
|
828
865
|
const gitignorePath = path.join(process.cwd(), '.gitignore');
|
|
829
866
|
const gitignoreEntries = ['.devlyn/', '.claude/skills/.devlyn-install.json'];
|
|
@@ -149,10 +149,13 @@
|
|
|
149
149
|
"4bbcb7fefd5366ed4151ce588e8482b747bdd85a7ecf795862a1c243218a162f",
|
|
150
150
|
"4c3c4295f7cb794d0466f93886bf89b316382feafec68606385eb6b4c36eebbc",
|
|
151
151
|
"4c4ee4b0948bc84b130c39b9846a5317ec76a6e3a8d95281a78e740192081662",
|
|
152
|
+
"4cae665b0a714cd7b20b59ef356b53e21dec1cf4679458de2a23b5077bceafff",
|
|
153
|
+
"4d42f91b8ff88de40921f825ec3a9aeeba30e85c7442ea2f8876b7c68555c39c",
|
|
152
154
|
"4d756bc5c6a7c7ca1589efc6c340c75fb389699fe14d114aa211a29921e7effe",
|
|
153
155
|
"4dcba526b49c91411d98925a7f638d990acea0f904ba8f143f195f7f99f85e33",
|
|
154
156
|
"4e114313a6fbf27b89bebe7847f9aebb4ca2c61d23d167997efd459fa091e602",
|
|
155
157
|
"4f6bf3fa8b8b706d234a7d5a3dda34e52ce1fcba68770aadf606c1717543bd5a",
|
|
158
|
+
"50fe2edc6da214c0ae4bfce43d8d210f98ff15da2d2f9bca88269dab9a4ed179",
|
|
156
159
|
"53a8f3196d2320ba46bf1299bfabb38dff495218bb47b35a43ac5072308f9deb",
|
|
157
160
|
"54cdf7a05afb97642d06a0d8284f17d51fed5ce0fdcdac949655c47734802893",
|
|
158
161
|
"55ff3f39ef7341cfb1e8b50271821d574eeddc455461d6df317caa9c5b55827f",
|
|
@@ -200,6 +203,7 @@
|
|
|
200
203
|
"8574b17a21f98a1cf558a7b88780eda07e8c39943168d0be49cbf4575edc23f1",
|
|
201
204
|
"8694f41265b0f74734ce6801434fe255a4c2261501bcf13d37fe2e5b85a859e9",
|
|
202
205
|
"870810ca9060fa45ef2eafd41c21282a21b9493cbec9632e2893556d07f3301f",
|
|
206
|
+
"890e3bdec4212b404e6c3675021922215d96705bb8def099a0d04ee65286585c",
|
|
203
207
|
"892c26f1d54958622f5615734666f3b1aedb07e7a3ac225c416a5d3f1508312c",
|
|
204
208
|
"8954f0209ecdac5a48f68c9ba5da95840ba745aabfb3751c6c216a06d809d1c9",
|
|
205
209
|
"897d0d57a5ab67b082a3fbaf078ac3e9c724acb033b6df35b8959ae28c26bc93",
|
|
@@ -221,12 +225,15 @@
|
|
|
221
225
|
"9e65019acb60433529160c929b840398fe6e5d72dcfd219cb79e69ba2d3cd5e9",
|
|
222
226
|
"9f62c5b2a94e8b5e81528ccbdb6f78d147d14882108568b2cb3b7f85212694c0",
|
|
223
227
|
"a02eb2d8d77553327fb77377dbfedeab059b2e68e0a33c469b9be54a5d55182b",
|
|
228
|
+
"a27ec7f5f0f0a2798e53695f20dc43fe28378d551fc060e2c772d0b522a336e5",
|
|
224
229
|
"a3a15249968f64085b0cec8c0826688a4c3a1e4cf09b4879054baa086d5cbca1",
|
|
230
|
+
"a4da26a46ab83815d8ca5d747c68a907ad67dad485adbc6c863b982ee23b307e",
|
|
225
231
|
"a5d6ff585d696254d6727cd1e6d7f8825881f90210eff744265e211ced715ea3",
|
|
226
232
|
"a7ff913df40945a8a16b6632214020a368119ff665953d4a07ec58330b39f101",
|
|
227
233
|
"aafc680a7ac73e100f4a17d2c4070190e68563f78614c39f4c2f58f1e291d9a9",
|
|
228
234
|
"ab7f6d08d95cf1c22b7ec6e2e113158b7f767b73d8dde04fd1c3b33788922c93",
|
|
229
235
|
"ac432d9179f245fec0beaf4010355613dcd6d476d8c9268c9cd430c98e73ff35",
|
|
236
|
+
"af3a498714fecb29ebdc1e43e5cc0425efaf1c290130e6913cabd75fe4c9cc67",
|
|
230
237
|
"af77f01317665c50815eb3cfefe481519efcc9c8b81bac06fc110abf723c7868",
|
|
231
238
|
"b3921b2317558010f99625aff30f3ed7a7a0dd4f37c586a6c4f9e1001e100134",
|
|
232
239
|
"b3ac898e73c5b7923c1050bdbc36144dc6f4ad8bd9b83c8515394c418ef447ed",
|
|
@@ -265,12 +272,14 @@
|
|
|
265
272
|
"d189a2002b4ef0e858acb734c4ed14f6af6f0b7bb250b178f65d439369a9149a",
|
|
266
273
|
"d41692aa7577bbd85144fe73d111947f98e1304f4aceb891d712daa5907d550d",
|
|
267
274
|
"d486a0b267c9425bde2cba737d802d2412a9b4b4b339e925500c1643327d2a3d",
|
|
275
|
+
"d5d8d02a1fb53cd28ed1c33e7184067b76defbfcc6cab9498b365dee35579013",
|
|
268
276
|
"d75bdfc9cf08cfcb46214f69dac4f20b1a0a30b86d91127007fe587de9eaaeb0",
|
|
269
277
|
"d768a149b5842e0d50eda941872188c8b29bcfb4b1aa0f4190fd4299f237fce0",
|
|
270
278
|
"d8c50cb04441e6b568236bc6cd494b4de296dfc7e8b33cf96e7aeb94612df3b8",
|
|
271
279
|
"da019f3edfb762b9216016a3ea9cf7211b2ba698a55ddda5cec2e478218b0288",
|
|
272
280
|
"ddb200267b43942de3c061b449d08cc3f73441258b74816cfe13da091377b428",
|
|
273
281
|
"dff43f9976c68267baf13f6a460f24af8e76be233c8440ac4684dc664106deae",
|
|
282
|
+
"e05f671dbf45aef8e7e4211195d46be8554c188d8df8899093359c414ffef2fe",
|
|
274
283
|
"e237f12ed08800ccc4c6eb4ae57cdd59d61198711f6a3b02dcb668aa08fddb93",
|
|
275
284
|
"e289dbab99dadb30d8315b32b8243154148c82955f238936bce4c1fe1c3ae525",
|
|
276
285
|
"e2bac40f3ff0b39726f95caaa9b19aa3b21596f165ac7a9dc68ebf42681d58cb",
|
|
@@ -327,6 +336,7 @@
|
|
|
327
336
|
"07d5c3147813efd7b5cf262709d4ee1643f962e5442f1f6e0f374d12d8d8c346",
|
|
328
337
|
"07ec9e6c76821368b71110413acf43edd6e3c91b93e380eebed8f363a1915c7a",
|
|
329
338
|
"080051ed34915b572971d9fc734b95ba7a7984f6e799a7286055d41a7aeaa3b6",
|
|
339
|
+
"0845abb4d59bce13c33c80b3292ba829bace0abe26d67a100a3bbc07e5db2b7d",
|
|
330
340
|
"086b65c51d3342970968f4c3c6554a605b8740ed82809d26587cbd08f87d19f8",
|
|
331
341
|
"0ab05e7ec571a8c899901514ab0655622817e8a77254ec2ec763fd78dad7f5bd",
|
|
332
342
|
"0b45db686d97f33be4dc2b091ed259de534c2e3f97f8787574e722d2e86a0c1d",
|
|
@@ -366,6 +376,7 @@
|
|
|
366
376
|
"18b3b8a84421d45d2f1cfd2d3bc936bb1635eb9fb426587ffb8b10ab224f5562",
|
|
367
377
|
"18d96415b31677a8efe1d8e5d3246c62456fdee9f6371e8bc7817de6c062eb50",
|
|
368
378
|
"1a7c6046a588a2608c146e5cb4403d943ef1d70f3779be1920a245442b48d7af",
|
|
379
|
+
"1af26e8d5dc8268e6372c1f2429aa2531a5780ae1956530a5b2978451121b4eb",
|
|
369
380
|
"1b0c98cba21a4d616442124ed1e29259006398777a40fac41ba6b1894727c31f",
|
|
370
381
|
"1c12577abd7db4345386fc7f24148dcbf6dabfe2ac89de3089fd27cca797aa0c",
|
|
371
382
|
"1c14e388ba39b4953aa51b2b73a92d287027f6849e25ee8725d9e3ea51f78fa1",
|
|
@@ -400,6 +411,7 @@
|
|
|
400
411
|
"2712e0f66046a30d80b9127688c67c73e809521dddedef1c10fad373d9a22114",
|
|
401
412
|
"278bed8b8219c30412f09523678c050173875c14aa8545062e718669a4e76ee8",
|
|
402
413
|
"27fe72a818b59177a7e692df7b02048eb7b8dd3b34e6e5a7717f2898df66ea00",
|
|
414
|
+
"284c050b55f96ae3c30d7f006aedd815f6b9601ceab010d569bc8622ee389fc3",
|
|
403
415
|
"287fa116a8235756a8b0e28caa951a9ad981667443434e13dbfde3c23f1590e6",
|
|
404
416
|
"28c5b42a58dca1a093576c8c35369c346caaf3963e14a4702ab3330d0d93e4d4",
|
|
405
417
|
"2939f7a22fd12f3ca3fdd0a08fc52535cf25dae38b9b445aceed09dc331fc1de",
|
|
@@ -451,6 +463,7 @@
|
|
|
451
463
|
"3ed5bcfca2cccfb1da4c181b27f9f44b6e53bd9c47c3b12990dd2e0c0ea51c32",
|
|
452
464
|
"3ee9206330fd3a17b04c5a5d136b92c2abf4792831c3c706bca463db3668fbcc",
|
|
453
465
|
"3ef2dde760ee9b50380364f83f368268a7c7a91cbdda6e0f629ebb09258cffaf",
|
|
466
|
+
"40464d8ac0f0395c447e7e502f262d5b05398716259b109e9ee7929fa1fa0105",
|
|
454
467
|
"40cc672b94e87300a3b317348d99f4c939e38316b5b9aa7f81e95f2ccf848f10",
|
|
455
468
|
"40fc22e1faeaa5a3be482334a312717b259f384e991c70e962ebef12d16120e7",
|
|
456
469
|
"41323b1c12be256f604edf8c49ff505acbaa75b6a1b938b76286d5eebec1ce95",
|
|
@@ -474,6 +487,7 @@
|
|
|
474
487
|
"477c7b699d1d2f66b63f04b30c3f78ddb4208b6346af58ed3dfa48d0568191cf",
|
|
475
488
|
"47bac4155f4e8f3d8e9eedce9dc7fc8039d74bc18c23213979fbe55e786d71a1",
|
|
476
489
|
"480420a6bcf31ae06cf1d4fcf34c24d949be485d2e13c2827b54331bec129053",
|
|
490
|
+
"4846658fe0742e27b3e2fccbbf222dbb4b23f47b5a31792249fc818e4ab4a659",
|
|
477
491
|
"484dc70c61110ccc7f4ba15e1a3e010b6653920e1bd852b9de61625942f7b056",
|
|
478
492
|
"485f3e37ba8a27b5027fd887f7baeea98a9099c6c7421d0e67e848d99905dc54",
|
|
479
493
|
"4923c02dff4a34a20d2f104ec3b17311cf269330932b7cf29addb2f4369dd23c",
|
|
@@ -493,6 +507,7 @@
|
|
|
493
507
|
"4dda6aecfc27e1a2889a30e12310abdc986d59cb8a7034ee9da3ee43c274dbf6",
|
|
494
508
|
"4e9eb8208ccd7fc7ec25010de2d9fa3df043452f3fa808ec520e283b7ebfa156",
|
|
495
509
|
"500e680bebe35b368080d6a1f6d39183323f519612fc9a776509ed0a2effcaf7",
|
|
510
|
+
"50bdeff1ac1044668a9692a076ff3bb504a42fdcb5abc6b41ccc4f05d57e9acd",
|
|
496
511
|
"5111747b387a61c55834df35d588156d2ef1e72b5530f4c33453754e4d35fcf1",
|
|
497
512
|
"5111bcf0edbbdb07d24a854086303f0f76a489fae171e7e441c1ec5dd62dd109",
|
|
498
513
|
"51ac33809c5f2a830a22d1f67f0f38f3b1e26acb47673fb3f691deb93d7e42b4",
|
|
@@ -521,6 +536,7 @@
|
|
|
521
536
|
"5b29b4f80abac3c4f6748a16f38b3bb72c61a639f65c845d0569a87f8f8a0cf0",
|
|
522
537
|
"5b79e4d8b7b75485b9be3341ec0d49ef4754c31d527bfb170d5cec1af92539e8",
|
|
523
538
|
"5b82f9020d952e89ccf8803bce90dd5b9c38b39fa59a629349c9d15cc14c9597",
|
|
539
|
+
"5d1183e08f92cb76c9fb41131742771101daebd65199b32050818a554e1ca185",
|
|
524
540
|
"5d56b35a8b69aabc401bb42cf93f38d0eebcb1219f3a8a032e124c45d4e4b5d8",
|
|
525
541
|
"5dec4f3f015629b0c29c802b30a9e373c570fca85bb3e260c0dac9662d2685cd",
|
|
526
542
|
"5dfd01e48b8b3eb9d6eec85d68624b2af0dd0eeb483307865ef88b0fc916bc97",
|
|
@@ -571,11 +587,13 @@
|
|
|
571
587
|
"76fdf7a80d7948c3007f8c54d3d710e8855a4227cefc915b8b07c0cdb299ceb0",
|
|
572
588
|
"77071010460d4aa8c89841d31a6f18600b804496de948710953dbd6f6fffc816",
|
|
573
589
|
"7766a3152ac33c155748ef3a7c9f500a7927870409100f55e1070f32f3667c54",
|
|
590
|
+
"793c5984744c21dfd4e8720e6319d61ff51ed30117c633b410024aaffa5ba048",
|
|
574
591
|
"7aaf7227bd67650944c709f4143b6b9161834d391e5cfd4aaeea105f5e840594",
|
|
575
592
|
"7af6e9be693d906ba1f942430f46b288176e418d35eefb869d3cc35570e3daff",
|
|
576
593
|
"7b47b07e3062f3dc839f11397bc3265120e01a35b0fda094d738e28a6729e6c3",
|
|
577
594
|
"7c0dacd603b4381539d6d3cf21f5fe625cf54b05eb4aa750fce658529b11d81d",
|
|
578
595
|
"7c79750557c7d7156df6f135fb582ec09cc5f4987ac8e2af0f5113e42c117224",
|
|
596
|
+
"7d083db061c678113c12453eb73299caa9e207dd6418ad63406154fd330f3309",
|
|
579
597
|
"7d2239e2cd4893c57ac0bf1373a2ef46419f614d0ce18a12df51222bc7795327",
|
|
580
598
|
"7e529bc76ca67f2023890da254ef0b09596f7d924d1a4eb93c72262783dc6c18",
|
|
581
599
|
"7eab506921c339be748106aa49468dba61ebd5a93aabc111621ccc8a9df52cc9",
|
|
@@ -608,6 +626,7 @@
|
|
|
608
626
|
"8b417f12b79e7328ab8998bde222da856470a9fe2a5eff838c710d5fc66c850e",
|
|
609
627
|
"8c89d0106c4051f7400670c2e83e6e3cfd95533b6d4d5f715124f28dbf41c37e",
|
|
610
628
|
"8cff7c530e70102f9506012e91f305c306c56a6e68073f44aba74a827c87f679",
|
|
629
|
+
"8d0079bdee4cf4dc86c1cca826f81584fe2c97db04514fdd666167df8b509979",
|
|
611
630
|
"8d3788c5b6eb17b9c58873208bbd36df9e4d3f969563165095a9dbb17d6c73fe",
|
|
612
631
|
"8db63678d5615054312a1b20b4383358fb0ec689e6ba6cb0d650bb133a2e3452",
|
|
613
632
|
"9101242a1f901484fc6110064e8e3ff4d4935c0ed69ee76003b57f8faf020765",
|
|
@@ -646,9 +665,11 @@
|
|
|
646
665
|
"a292850ee0ceb0549d2e0cd50e48c8596594a509597f7210f59acbad7b45b475",
|
|
647
666
|
"a2b7ab33386255547ecd6fce85b574d0354ef8e93d2bafb58e0cb77d7fee46b7",
|
|
648
667
|
"a2cb37971755afd2b67d7f91f0857ce9e0dee7464e8e16d79c72070bc0e5a5ef",
|
|
668
|
+
"a309b4f27f5733300e22b7b04a044b6c30df42b7ad51c9d03369e8d8d3da2f79",
|
|
649
669
|
"a35c41356dc27962435aafef3aaad9060a987aa83ea01992da6f7c26612468c9",
|
|
650
670
|
"a53c30ff3a184f3192f7c528b6cfe50dd917e8185edf31d66c5c1454abcbea9d",
|
|
651
671
|
"a5700a94e3e29b246bd9e2e29b2292287687cedbb69902f0b87ffbdcf382915c",
|
|
672
|
+
"a5de90a81e905134db282ef1cd50e17a684c8ea3217630147a47e2d5058edc3f",
|
|
652
673
|
"a624d3a28050dba8ceaf70f1e940c8a2d090c22a63118eee78fc1df154a88e2b",
|
|
653
674
|
"a6bc0c56d741f39aea2dbceb9bdd671326f12cebf7468c9c0f1c2d8ae733acc4",
|
|
654
675
|
"a880b449c712d425187e6119469d719a96f01f7a603de858022b385f47f84602",
|
|
@@ -700,6 +721,7 @@
|
|
|
700
721
|
"bf636ba39e22c5f06aa4e4850e7e4c16e87eab4439b1c18d7bc5313d6c402cc6",
|
|
701
722
|
"bfd30b5a63ea49031fefd4a7c7804c72731ea35ea47884d0aa154e9aeb83e805",
|
|
702
723
|
"bfe131637d915e23907418c2ea412a31e4a0e3e90da24c96b3d23380d7f3ceaa",
|
|
724
|
+
"c115b2ba9ec7abe2fa5261a5894e3c4899794b527f01ec682ae7fd2479199c08",
|
|
703
725
|
"c150c40a04099d7b726eb8aecc8eec8e92f9f9248a6a5c15556c08000c4bd231",
|
|
704
726
|
"c16ff4fe013ee2cef905d767a09305d9c1b2f778a06b439f0bc4645ac05bc82b",
|
|
705
727
|
"c1c7e45fedafb97770b6726539694eb0668c70677c2031fe2db2bc8b5339423a",
|
|
@@ -750,6 +772,7 @@
|
|
|
750
772
|
"d606733e95736b3e28e4dce4847b9775effc0944c4cd54c733400074991934ef",
|
|
751
773
|
"d660cb0c81a7032782da6910fa05eafa83d36520ca5fdb95e7077da96216a3ca",
|
|
752
774
|
"d6df42e35e82f71f257f5e79d038bf60a96e4965dbdb6bf08bc95c250754e5fe",
|
|
775
|
+
"d905ca576280d8a3d774bcadebfa57a9e22bdf7c1678ca9a548a1c25d643bf17",
|
|
753
776
|
"d94088aedb09a1feb3ad388a69e242043b4a921ca8d76b4660d94e18e2836546",
|
|
754
777
|
"d9547a0d7d9a97bffa84178d8ab73f3556f22c34120759d50eaa165c3ef0c318",
|
|
755
778
|
"d9683236273b7f1759c34a892267b1c57d59dec57415bb762201a50b5925c408",
|
|
@@ -771,10 +794,12 @@
|
|
|
771
794
|
"e031aef2a9adb0d0900e8269cf84c892f77b9938984e26df54826d1771861629",
|
|
772
795
|
"e0cecf4838b7ba38afa78577855d5bf7fab251d3f1b1ba01c51c0f76b97aea90",
|
|
773
796
|
"e160cfba0b71557be31005767ee845cab16d8c3a9bafde3d12ec31e8af0a1339",
|
|
797
|
+
"e16ebeb4c7803de28999a926918b42bec8d548691719827a636d84bc47941d80",
|
|
774
798
|
"e2070548ec9a6244c569ef0b9a43c2e5dd99cf9c0fa4540a21fd0595b291e444",
|
|
775
799
|
"e29fec7d54a144ea4867a3764fccdee6849d58d0f32eacdd56b2c317863fa1c6",
|
|
776
800
|
"e2e0fc585321ee2013cccaed95d47c49fbca71b54c67abad9080d19d70e3c1a5",
|
|
777
801
|
"e3b2f7be15a793f07cbe8e51aa2feeac51d4c67077b94e5e20bad2e14be07fc5",
|
|
802
|
+
"e468c242cc38c390f9679fca61f355848f58d51570249dfbb65b4f2e26a9dfb1",
|
|
778
803
|
"e4bafa0f553e899b65f05feabf4cbe86d8246c57cbba745eb79e6aa858f40a6b",
|
|
779
804
|
"e5160f4da789914e7f93694a55b9f80b8d06c3b0a126ff60f7627b0b418ae292",
|
|
780
805
|
"e55a62fa1a993f5df1b44d1c55ef27915938d58a1c357604f3dc150f795672df",
|
|
@@ -789,6 +814,7 @@
|
|
|
789
814
|
"e97387270720794226b6f1c657a0d5a961dbe06f8b873d6150b2f6246e54891f",
|
|
790
815
|
"eabe96ee6140792fb6d7c188c3ce031cba5e2c6663aecdeb019d9d51d5a90a43",
|
|
791
816
|
"eaf6d28a8d55fb98dcd4ddb84ab4645b4bf6d328a26811ddfcc1423b0b8ea604",
|
|
817
|
+
"ed4a68efc0af88b2192a06ae6b208992b617aae54b768d125b95442b987d517b",
|
|
792
818
|
"edb34ab257304ae32df0fd5b8d4b41e982ff5e956231e56b05c7bbc1e8ae44ca",
|
|
793
819
|
"edd212c7b0941068f6fd2d2051ad28651acd16ee12d9400f060553af6274ed2e",
|
|
794
820
|
"eddcbf50ba05f1f633fea0ad0a384300670be2ec6b45f8cc4f622aaa7a431b88",
|
|
@@ -46,7 +46,7 @@ Keep each section to ≤ 8 lines. Adapters are deltas, not full prompts. If an a
|
|
|
46
46
|
|
|
47
47
|
Adapters may add two more sections beyond the base format:
|
|
48
48
|
|
|
49
|
-
- **`## Role eligibility`** — fixed ASCII fields, one per line: `executor: yes|no`, `pair_judge: yes|no`. Absent section = eligible for both roles (every adapter shipped before iter-0051). Present only when a backend is structurally unable or not certified for a role — e.g. a completion-only local model has no tool/file-edit access, so it declares `executor: no`. `_shared/engine-preflight.md` and `/devlyn
|
|
49
|
+
- **`## Role eligibility`** — fixed ASCII fields, one per line: `executor: yes|no`, `pair_judge: yes|no`. Absent section = eligible for both roles (every adapter shipped before iter-0051). Present only when a backend is structurally unable or not certified for a role — e.g. a completion-only local model has no tool/file-edit access, so it declares `executor: no`. `_shared/engine-preflight.md` and `/devlyn-engines` read this section as a structured marker, not prose, so it validates mechanically.
|
|
50
50
|
- **`## Invocation`** — for backends called over an API or CLI backends with non-default invocation contracts: the concrete request shape (endpoint, JSON body, timeout) and the adapter-declared availability probe (`_shared/engine-preflight.md#role-resolution`'s "an adapter may declare a different probe" hook).
|
|
51
51
|
|
|
52
52
|
## When to add a new adapter
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Identity
|
|
4
4
|
|
|
5
|
-
You are the model running behind the `omp` CLI. Follow the canonical phase prompt exactly; this adapter exists so oh-my-pi can be selected as a first-class native task worker by `/devlyn
|
|
5
|
+
You are the model running behind the `omp` CLI. Follow the canonical phase prompt exactly; this adapter exists so oh-my-pi can be selected as a first-class native task worker by `/devlyn-resolve`.
|
|
6
6
|
|
|
7
7
|
## Output Discipline
|
|
8
8
|
|
|
@@ -10,4 +10,4 @@ Keep phase output machine-consumable and concise. Write the artifacts the canoni
|
|
|
10
10
|
|
|
11
11
|
## Fresh Context
|
|
12
12
|
|
|
13
|
-
Each native `task` tool invocation with a fresh `context` is a fresh phase worker. Do not call `/devlyn
|
|
13
|
+
Each native `task` tool invocation with a fresh `context` is a fresh phase worker. Do not call `/devlyn-resolve` recursively from inside a phase prompt; execute only the phase body you received.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
"""Archive devlyn
|
|
2
|
+
"""Archive devlyn-resolve run artifacts per references/pipeline-state.md#archive-contract.
|
|
3
3
|
|
|
4
4
|
Usage:
|
|
5
5
|
python3 scripts/archive_run.py [--devlyn-dir .devlyn]
|
|
@@ -67,7 +67,7 @@ PER_RUN_PATTERNS = (
|
|
|
67
67
|
"verify.primary.timeout.json",
|
|
68
68
|
"verify.pair.timeout.json",
|
|
69
69
|
"finish-gate.summary.json",
|
|
70
|
-
# iter-0033a/2026-04-30 archive-fix iter: NEW /devlyn
|
|
70
|
+
# iter-0033a/2026-04-30 archive-fix iter: NEW /devlyn-resolve emits
|
|
71
71
|
# plan.md (PLAN output) + final-report.md (PHASE 6 render) +
|
|
72
72
|
# cumulative.patch (cumulative diff). Smoke 2's archive listing
|
|
73
73
|
# captured all three; archive_run.py was missing them because the
|
|
@@ -22,7 +22,7 @@ if [ ! -f "$CODEX_MONITORED_PATH" ]; then
|
|
|
22
22
|
fi
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
-
**Read-only critique / adversarial review / debate** (`/devlyn
|
|
25
|
+
**Read-only critique / adversarial review / debate** (`/devlyn-resolve` VERIFY pair-mode, plus any future ideate read-only critique). Codex returns findings on stdout; the orchestrator writes files.
|
|
26
26
|
|
|
27
27
|
```bash
|
|
28
28
|
DEVLYN_CODEX_PROMPT_FILE="<prompt-file>" CODEX_MONITORED_ISOLATED=1 CODEX_MONITORED_TIMEOUT_SEC=600 bash "$CODEX_MONITORED_PATH" \
|
|
@@ -32,7 +32,7 @@ DEVLYN_CODEX_PROMPT_FILE="<prompt-file>" CODEX_MONITORED_ISOLATED=1 CODEX_MONITO
|
|
|
32
32
|
-
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
-
**Workspace-write implementation** (`/devlyn
|
|
35
|
+
**Workspace-write implementation** (`/devlyn-resolve` IMPLEMENT phase when `--engine codex` or `--engine auto` routes to Codex, plus codex-routed `/devlyn-ideate` phases):
|
|
36
36
|
|
|
37
37
|
```bash
|
|
38
38
|
DEVLYN_CODEX_PROMPT_FILE="<prompt-file>" bash "$CODEX_MONITORED_PATH" \
|
|
@@ -76,6 +76,6 @@ The local Codex CLI, fronted by `codex-monitored.sh`, is the integration boundar
|
|
|
76
76
|
|
|
77
77
|
## Invocation from inside a skill prompt
|
|
78
78
|
|
|
79
|
-
Skills write the invocation as a Bash command the runtime executes. Example shape from `/devlyn
|
|
79
|
+
Skills write the invocation as a Bash command the runtime executes. Example shape from `/devlyn-resolve` PHASE 2 IMPLEMENT when routed to Codex:
|
|
80
80
|
|
|
81
81
|
> Run `DEVLYN_CODEX_PROMPT_FILE="<IMPLEMENT-prompt-file>" bash "$CODEX_MONITORED_PATH" --json -C <state.base_ref.repo_root> -s workspace-write -m <model_requested> -c sandbox_workspace_write.network_access=false -c model_reasoning_effort=xhigh -`. Capture stdout as the IMPLEMENT reply; non-zero exit → treat as subagent failure. The wrapper emits `[codex-monitored]` heartbeat and lifecycle lines on **stderr** — stdout stays clean for Codex output, so the orchestrator can parse the reply without filtering. Heartbeat-on-stderr keeps the orchestrator's combined-output stream non-silent (defeats the iter-0008 byte-watchdog kill) without polluting the codex-reply view of stdout. Do not pipe the wrapper; direct capture or file redirection preserves streaming and avoids the pipe-refusal exit.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
# engine-doctor.sh — read-only detection for /devlyn
|
|
2
|
+
# engine-doctor.sh — read-only detection for /devlyn-engines' no-arg output.
|
|
3
3
|
#
|
|
4
4
|
# WHY (iter-0050): users need to see what's actually on the machine, not
|
|
5
5
|
# just what's pinned. This script never writes .devlyn/engines.json, never
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# Shared — Engine Pre-flight
|
|
2
2
|
|
|
3
|
-
Used by `/devlyn
|
|
3
|
+
Used by `/devlyn-resolve` and `/devlyn-ideate`. One shared availability rule so every skill routes identically.
|
|
4
4
|
|
|
5
5
|
## Rule
|
|
6
6
|
|
|
7
|
-
Each skill resolves the effective engine from its own SKILL.md default plus any explicit `--engine` flag passed by the user. `/devlyn
|
|
7
|
+
Each skill resolves the effective engine from its own SKILL.md default plus any explicit `--engine` flag passed by the user. `/devlyn-resolve` also computes the default VERIFY-pair route and conditional risk-probe requirements before the phase that needs the OTHER engine.
|
|
8
8
|
|
|
9
9
|
Engine requirements have two classes:
|
|
10
10
|
|
|
@@ -15,11 +15,11 @@ Engine requirements have two classes:
|
|
|
15
15
|
|
|
16
16
|
The orchestrator is the CLI the user opened. PLAN remains orchestrator-fixed. Resolve the legacy executor as explicit `--engine` > `cwd/.devlyn/engines.json` `executor` > the invoking skill's supported default. BUILD_GATE runs commands in the orchestrator without a separate model; risk-probe derivation keeps its existing route.
|
|
17
17
|
|
|
18
|
-
The role profiles and `--role-config` below apply only to `/devlyn
|
|
18
|
+
The role profiles and `--role-config` below apply only to `/devlyn-resolve`; `/devlyn-ideate` keeps its existing `--engine` / legacy executor selection and never inherits worker/judge profiles. `role-config.py` is resolve’s deterministic resolver. Optional project `roles.worker`, `roles.primary_judge`, and `roles.pair_judge` each require `engine` and accept exact `model`/`effort`; `/devlyn-resolve --role-config <path>` supplies the same `{"roles": {...}}` object for one run. Each entry replaces the entire lower entry. Worker/primary precedence is run role > `--engine` engine-only > project role > legacy executor. Pair precedence is run role > project role > existing `pair_judge_priority`/binary complement. An absent primary profile follows the legacy executor, not the worker profile. No parent/global devlyn config lookup.
|
|
19
19
|
|
|
20
20
|
Worker controls IMPLEMENT, its included code/doc cleanup, and their repair rounds only; owner CLEANUP performs artifact/invariant checks without a worker dispatch; primary/pair control VERIFY only. OTHER must differ from the resolved primary engine. Explicit same-engine pair is invalid; a legacy priority list skips the primary. `--no-pair` does not dispatch or check availability of an unused pair. Configured pins remain explicit promises, while an unconfigured unavailable automatic OTHER records its solo reason.
|
|
21
21
|
|
|
22
|
-
Before the first phase, `/devlyn
|
|
22
|
+
Before the first phase, `/devlyn-resolve` freezes resolution with `state-phase-write.py --freeze-roles`; subsequent status/dispatch reads that state instead of mutable config. `state.engine` stays the legacy executor. The resolver rejects statically unsupported selected channel fields before PLAN, and validates adapter names and the existing ASCII `executor: yes|no` / `pair_judge: yes|no` eligibility markers; absent eligibility section means both. Malformed configuration fails with `BLOCKED:invalid-engine-config`.
|
|
23
23
|
|
|
24
24
|
Before each affected worker/judge, read `role-config.py --state .devlyn/pipeline.state.json --role <role> [--resolved-model <inherited-exact-model>]`. It returns source/channel, requested values and argv additions. Explicit Codex options require current version-matching native model metadata; refresh the native CLI's cache when missing/stale. Explicit Claude judge effort requires the adapter's version/exact-model capability declaration; model-only selection passes the exact ID without that effort declaration and validates the native result. No model/effort fields means unchanged phase defaults. Unknown support fails with `BLOCKED:unsupported-role-option`; no clamp, fallback or invented model identity. Native Agent workers reject unsupported explicit Claude fields without switching to a CLI worker. Show inherited/unknown values honestly; availability is not role fitness.
|
|
25
25
|
|
|
@@ -33,7 +33,7 @@ When a run or phase requires engine `<name>` (claude, codex, omp, or any adapter
|
|
|
33
33
|
|
|
34
34
|
Never prompt the user mid-pipeline. Missing engines for explicit routes are BLOCKED states, not silent fallbacks. Missing OTHER engines for automatic escalations are reported solo-skips, not fallbacks — the auto route was never selected.
|
|
35
35
|
|
|
36
|
-
Per-skill defaults: `/devlyn
|
|
36
|
+
Per-skill defaults: `/devlyn-resolve` uses Claude for IMPLEMENT when the orchestrator has Claude Code's native Agent primitive; Codex CLI and oh-my-pi orchestrators use their own fresh worker as the default route (Codex child process, omp native `task`) so implementation and independent verification retain structural isolation. PLAN uses the owner context; BUILD_GATE/CLEANUP use owner commands. VERIFY invokes the OTHER engine by default when available unless `--no-pair` was passed. `/devlyn-ideate` defaults to Claude; `--engine` selects the elicitation/normalization adapter, not an automatic cross-model challenge phase. Any future ideate read-only critique must follow `_shared/codex-config.md` isolation rules. Each SKILL.md flag block is source of truth for that skill's default.
|
|
37
37
|
|
|
38
38
|
## What a skill must report after a BLOCKED engine check
|
|
39
39
|
|