@outerlayer/cli 0.22.1 → 0.23.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/CHANGELOG.md +20 -0
- package/README.md +4 -1
- package/dist/{agent-setup-LTSLXPS3.js → agent-setup-SNDCEHG2.js} +14 -12
- package/dist/{artifact-link-cmd-OWRI5AJX.js → artifact-link-cmd-LEI6EOZE.js} +2 -2
- package/dist/bridge-QFN3KJP6.js +8 -0
- package/dist/{build-6WRNZPVR.js → build-WHHFA7KM.js} +2 -2
- package/dist/build-info.json +1 -1
- package/dist/{builder-G3MLDMTI.js → builder-7FBQAWQZ.js} +3 -3
- package/dist/{check-UYKEMQNR.js → check-3CGLWMHM.js} +37 -37
- package/dist/{chunk-ZPSLJFGL.js → chunk-2TT7DEMZ.js} +2 -2
- package/dist/{chunk-3V5C64Y5.js → chunk-6AOZD3LY.js} +3 -4
- package/dist/{chunk-5NJIWKD4.js → chunk-BOG4ENP7.js} +9 -9
- package/dist/{chunk-G3IJ3N6F.js → chunk-BUP5N3X6.js} +1 -1
- package/dist/{chunk-FRNYCJ4W.js → chunk-C2XZBNHY.js} +1 -1
- package/dist/{chunk-BET347JZ.js → chunk-C64D7HR3.js} +6 -7
- package/dist/{chunk-AEKSX4EY.js → chunk-CBCKD6DO.js} +1 -1
- package/dist/{chunk-56X5TOJY.js → chunk-D64E222W.js} +5 -6
- package/dist/{chunk-URAKVDSI.js → chunk-DJYOCD65.js} +9 -10
- package/dist/{chunk-IZSVXRDR.js → chunk-DXDF43YG.js} +1 -1
- package/dist/{chunk-F7CU5ABH.js → chunk-DYEFPYME.js} +1 -1
- package/dist/{chunk-ORNJJ7XN.js → chunk-FX6IHR5C.js} +11 -12
- package/dist/{chunk-ENTHEUKT.js → chunk-G3LHWUBK.js} +4 -4
- package/dist/{chunk-5QRP3MVS.js → chunk-GNPTU4BM.js} +9 -4
- package/dist/{chunk-JRCSET55.js → chunk-GXV73IIS.js} +6 -6
- package/dist/{chunk-5OCIHFGE.js → chunk-HBISTTG3.js} +32 -23
- package/dist/chunk-JKNYTNYD.js +151 -0
- package/dist/{chunk-CUFFDEF3.js → chunk-KGKFEONR.js} +4 -4
- package/dist/{chunk-USWVXQIH.js → chunk-MQ743JX3.js} +3 -3
- package/dist/{chunk-XR56WEA5.js → chunk-OGMZJWWD.js} +1 -1
- package/dist/chunk-QS43O4DR.js +113 -0
- package/dist/{chunk-FOCML5FI.js → chunk-QSEPKZXR.js} +15 -14
- package/dist/{chunk-7VUK5RFS.js → chunk-QZBXLLTV.js} +36 -1
- package/dist/{chunk-WFSUUUAN.js → chunk-RKOTJQVG.js} +1 -1
- package/dist/{chunk-7FEY33MY.js → chunk-TFGXOHF6.js} +13 -13
- package/dist/{chunk-V7SAQ645.js → chunk-VJBFQP3H.js} +21 -12
- package/dist/{chunk-ZNPE7FW5.js → chunk-VPEGE3QZ.js} +1 -1
- package/dist/{chunk-W3SWJ2TD.js → chunk-VWFOKRYS.js} +5 -2
- package/dist/{chunk-XCRZTXRL.js → chunk-WX2WEERU.js} +63 -43
- package/dist/chunk-WXJXHZVB.js +73 -0
- package/dist/{chunk-BOMRFYTZ.js → chunk-WY7HFY62.js} +3 -3
- package/dist/{chunk-VSUXCMMH.js → chunk-XFGL53GU.js} +51 -33
- package/dist/{chunk-6YBLN4TR.js → chunk-XGPC3IOR.js} +4 -5
- package/dist/{chunk-QC72I5GQ.js → chunk-XOEV4FVK.js} +3 -3
- package/dist/{chunk-EAQSOE62.js → chunk-XSPA5ODY.js} +21 -19
- package/dist/{chunk-JZGFDTNC.js → chunk-Z42JY3LQ.js} +20 -3
- package/dist/{chunk-O6RJ3QMU.js → chunk-ZKWKQIJU.js} +86 -6
- package/dist/{chunk-QOALB6ZD.js → chunk-ZLZ3XVPI.js} +3 -3
- package/dist/{claude-launcher-TBWV3YL3.js → claude-launcher-KEESTJHO.js} +5 -5
- package/dist/{cli-U253V422.js → cli-44WGGICQ.js} +126 -112
- package/dist/{command-IQTPFSXY.js → command-4FAP2D3P.js} +22 -23
- package/dist/connect-cmd-6DUTUK63.js +22 -0
- package/dist/{context-cleanup-DSA3HGQU.js → context-cleanup-LTH77FC3.js} +3 -3
- package/dist/{control-plane-launch-OWSNH6YA.js → control-plane-launch-SEYCOZFH.js} +8 -9
- package/dist/{dist-7IH56ELA.js → dist-SOH3O24Y.js} +2 -2
- package/dist/{docker-JU422JL7.js → docker-KMK4LOET.js} +3 -3
- package/dist/{doctor-FZTS57ZO.js → doctor-4H77CEB7.js} +24 -25
- package/dist/{emit-artifact-cmd-YLZ5WLSF.js → emit-artifact-cmd-XCZ3ALLV.js} +15 -15
- package/dist/emit-cmd-WQH2NK7H.js +15 -0
- package/dist/{emit-criteria-cmd-MF6TVE7C.js → emit-criteria-cmd-JE72JHKJ.js} +10 -10
- package/dist/{emit-finding-cmd-S3YMFTZT.js → emit-finding-cmd-ILIDRMYN.js} +10 -10
- package/dist/{emit-result-cmd-JHEUFTPX.js → emit-result-cmd-WPKG5YAS.js} +15 -15
- package/dist/{emit-step-cmd-TUI2T3DS.js → emit-step-cmd-OVMLQSL6.js} +11 -11
- package/dist/{governing-source-XSEIRSBE.js → governing-source-EQBKPME7.js} +16 -17
- package/dist/{guest-init-DF7V5D2R.js → guest-init-HWSE7W6L.js} +3 -2
- package/dist/{hook-fast-O3UUN6SO.js → hook-fast-27SHD72I.js} +1 -1
- package/dist/{hook-wrap-fast-NPLHJXFK.js → hook-wrap-fast-NOOGDNSW.js} +2 -2
- package/dist/{import-capture-cmd-Q56DDZVO.js → import-capture-cmd-TCOKNVBM.js} +12 -7
- package/dist/{import-ruler-cmd-T6LLO6Q7.js → import-ruler-cmd-VJOHOJQ7.js} +2 -2
- package/dist/index.js +6 -6
- package/dist/{init-ZZZPYGUH.js → init-HAAHIQFN.js} +23 -24
- package/dist/{init-VZE72CR4.js → init-WQ62BXDN.js} +23 -24
- package/dist/{init-cmd-W5VV62ZN.js → init-cmd-VPFIDY64.js} +24 -24
- package/dist/init-update-UZIJ2FMU.js +529 -0
- package/dist/layout-UOJQGEPW.js +10 -0
- package/dist/{login-browser-BN5UKPHS.js → login-browser-4OMZFP3U.js} +4 -3
- package/dist/{logout-cmd-RZFWTNYD.js → logout-cmd-5V5MMBSY.js} +2 -2
- package/dist/{loop-6WENRS5S.js → loop-JPW2QJ64.js} +37 -37
- package/dist/{machine-M4MQBV5A.js → machine-PGDRWPI2.js} +22 -23
- package/dist/{mcp-install-cmd-GD4QUP7Z.js → mcp-install-cmd-GGWB3JJ2.js} +2 -2
- package/dist/{mcp-serve-cmd-SBW7HYKD.js → mcp-serve-cmd-CNRC5AL5.js} +3 -3
- package/dist/{runner-identity-FTHZFMGY.js → runner-identity-IIZ3RK7M.js} +3 -3
- package/dist/{runner-key-QT7GKGEE.js → runner-key-BPP5XRYR.js} +23 -24
- package/dist/{session-sender-BK6TGNVO.js → session-sender-EKKZ5DEU.js} +16 -16
- package/dist/{settings-J2652U5N.js → settings-AKYEOCC2.js} +1 -1
- package/dist/{spec-cmd-ZNJ3GXWC.js → spec-cmd-JDHGNFVJ.js} +11 -11
- package/dist/{starter-pack-5EQYGSJF.js → starter-pack-55EFILC5.js} +7 -4
- package/dist/{status-JOO7MGIC.js → status-UCQDEMFX.js} +30 -30
- package/dist/{statusline-fast-2OK3DVAA.js → statusline-fast-GVRSBHAF.js} +2 -2
- package/dist/{sync-cmd-W2FPY3T5.js → sync-cmd-NSVXOYFJ.js} +15 -15
- package/dist/{watch-WLH5ZUZU.js → watch-NQVZWPBJ.js} +15 -15
- package/dist/{work-claim-cmd-4PLDTEZR.js → work-claim-cmd-FPJXQAXP.js} +13 -13
- package/dist/{work-cmd-KWHAYUYB.js → work-cmd-FMPDXPU6.js} +11 -11
- package/dist/{work-comment-cmd-4CUI7ZDE.js → work-comment-cmd-ZVUE2IUN.js} +11 -11
- package/dist/{work-logs-cmd-AF253WLM.js → work-logs-cmd-CQH2SYT4.js} +11 -11
- package/dist/{work-open-pr-cmd-JETE6HRL.js → work-open-pr-cmd-YY2OGJOI.js} +12 -12
- package/dist/{work-pr-cmd-V5G4CPMG.js → work-pr-cmd-EHFTEVJO.js} +11 -11
- package/dist/{work-stop-cmd-FIEKUDGE.js → work-stop-cmd-LGWSBSBT.js} +11 -11
- package/package.json +1 -1
- package/skill-pack/maintained/outerlayer-amend/SKILL.md +83 -82
- package/skill-pack/maintained/outerlayer-build/SKILL.md +4 -2
- package/skill-pack/maintained/outerlayer-build/references/agent-briefs.md +17 -4
- package/skill-pack/maintained/outerlayer-build/references/criteria-judge.md +10 -0
- package/skill-pack/maintained/outerlayer-build/references/release.md +7 -4
- package/skill-pack/maintained/outerlayer-build/references/review-briefs.md +10 -3
- package/skill-pack/maintained/outerlayer-cli/SKILL.md +13 -4
- package/skill-pack/maintained/outerlayer-cli/references/merge-base-branch.md +54 -0
- package/dist/chunk-NTRCK4NH.js +0 -38
- package/dist/chunk-QF7WZUU6.js +0 -56
- package/dist/connect-cmd-ZFOK6HEL.js +0 -17
- package/dist/emit-cmd-3W5IO5ET.js +0 -14
- package/dist/init-update-YFPIQS5G.js +0 -211
- package/dist/{chunk-F35VMF5M.js → chunk-GOSFARMS.js} +1 -1
- package/dist/{chunk-3AZYLAJC.js → chunk-QILR6TZP.js} +1 -1
- package/dist/{chunk-DIB2WLBL.js → chunk-YVZJ6GKF.js} +1 -1
|
@@ -0,0 +1,529 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { contextIsGoverned, inspectStarterFiles, readShippedManifest, skillsFolders, contentHash, canonical } from './chunk-XFGL53GU.js';
|
|
4
|
+
import { keepHandWritten } from './chunk-ZKWKQIJU.js';
|
|
5
|
+
import { runEmit, inspectReplacedOutputs } from './chunk-WX2WEERU.js';
|
|
6
|
+
import './chunk-VJBFQP3H.js';
|
|
7
|
+
import { COMMIT_LINE } from './chunk-GXV73IIS.js';
|
|
8
|
+
import './chunk-BUP5N3X6.js';
|
|
9
|
+
import './chunk-XSPA5ODY.js';
|
|
10
|
+
import './chunk-GOSFARMS.js';
|
|
11
|
+
import './chunk-XGPC3IOR.js';
|
|
12
|
+
import { retiredSkillPaths, removeRetiredSkills } from './chunk-MQ743JX3.js';
|
|
13
|
+
import './chunk-QS43O4DR.js';
|
|
14
|
+
import './chunk-ZJSNLVCE.js';
|
|
15
|
+
import { findGitDirs } from './chunk-BJ3KTMDH.js';
|
|
16
|
+
import './chunk-CBCKD6DO.js';
|
|
17
|
+
import { setMcpEntry } from './chunk-YVZJ6GKF.js';
|
|
18
|
+
import { C } from './chunk-ANPNT6PM.js';
|
|
19
|
+
import './chunk-EABW6AJQ.js';
|
|
20
|
+
import { skillsBaseFor, isAgentsMdLayout, holdsTodaysLayoutSources, discoverOuterlayerPaths, declareAgentsMdLayout, linkClaudeSkills, SKILLS_LINK_PATH, readConfigObject, filesBelow, describeSkillsLink, FIRST_VERSION_READING_AGENTS_SKILLS } from './chunk-JKNYTNYD.js';
|
|
21
|
+
import { writeMaintainedFiles, maintainedFilesForExistingSkills, loadMaintainedFiles, AGENTS_SKILLS_BASE, OUTERLAYER_SKILLS_BASE } from './chunk-HBISTTG3.js';
|
|
22
|
+
import { cliInvocation } from './chunk-CRB3POP4.js';
|
|
23
|
+
import { linkedAgentsPath, hasSymlinkComponent } from './chunk-VWFOKRYS.js';
|
|
24
|
+
import './chunk-YQR6E6OV.js';
|
|
25
|
+
import './chunk-TUSYOL2O.js';
|
|
26
|
+
import { parseOuterlayerConfig } from './chunk-RKOTJQVG.js';
|
|
27
|
+
import './chunk-QZBXLLTV.js';
|
|
28
|
+
import './chunk-VNVZDWO3.js';
|
|
29
|
+
import './chunk-RA3O54FC.js';
|
|
30
|
+
import './chunk-OW52QLK3.js';
|
|
31
|
+
import './chunk-IHNQWF6F.js';
|
|
32
|
+
import './chunk-URWYRAIC.js';
|
|
33
|
+
import './chunk-GISNHSYL.js';
|
|
34
|
+
import './chunk-Z5GEFMRW.js';
|
|
35
|
+
import { existsSync, readFileSync, mkdirSync, writeFileSync, unlinkSync, readdirSync, rmdirSync, renameSync, lstatSync } from 'fs';
|
|
36
|
+
import { join, dirname } from 'path';
|
|
37
|
+
|
|
38
|
+
createRequire(import.meta.url);
|
|
39
|
+
function removeFile(root, path) {
|
|
40
|
+
if (hasSymlinkComponent(root, path)) return false;
|
|
41
|
+
unlinkSync(join(root, path));
|
|
42
|
+
for (let dir = dirname(path); dir !== "."; dir = dirname(dir)) {
|
|
43
|
+
try {
|
|
44
|
+
if (readdirSync(join(root, dir)).length > 0) break;
|
|
45
|
+
rmdirSync(join(root, dir));
|
|
46
|
+
} catch {
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
var exists = (root, rel) => {
|
|
53
|
+
try {
|
|
54
|
+
lstatSync(join(root, rel));
|
|
55
|
+
return true;
|
|
56
|
+
} catch {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
function scopesOf(paths) {
|
|
61
|
+
const scopes = /* @__PURE__ */ new Set();
|
|
62
|
+
for (const path of paths) {
|
|
63
|
+
const at = path.split("/").indexOf(".outerlayer");
|
|
64
|
+
if (at !== -1) scopes.add(path.split("/").slice(0, at).join("/"));
|
|
65
|
+
}
|
|
66
|
+
return [...scopes].sort();
|
|
67
|
+
}
|
|
68
|
+
function configuredTargets(root) {
|
|
69
|
+
try {
|
|
70
|
+
const parsed = parseOuterlayerConfig(readFileSync(join(root, ".outerlayer", "config.json"), "utf8"));
|
|
71
|
+
return parsed.config?.targets ?? [];
|
|
72
|
+
} catch {
|
|
73
|
+
return [];
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function readJson(root, rel) {
|
|
77
|
+
try {
|
|
78
|
+
const doc = JSON.parse(readFileSync(join(root, rel), "utf8"));
|
|
79
|
+
return doc !== null && typeof doc === "object" && !Array.isArray(doc) ? doc : void 0;
|
|
80
|
+
} catch {
|
|
81
|
+
return void 0;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
var serversOf = (doc) => {
|
|
85
|
+
const value = doc.mcpServers;
|
|
86
|
+
if (value === void 0) return {};
|
|
87
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
88
|
+
};
|
|
89
|
+
function controlPlaneNote() {
|
|
90
|
+
return `A CLI or runner older than ${FIRST_VERSION_READING_AGENTS_SKILLS}, the first that reads .agents/skills/, delivers none of these skills. Keeping .claude/skills/ as an identical copy of .agents/skills/ until they upgrade keeps them working. Until then, make every edit in both folders. To make the copy now, run \`cp -R .agents/skills/. .claude/skills/\`, and commit it.`;
|
|
91
|
+
}
|
|
92
|
+
function migrateToAgentsMdLayout(root, opts) {
|
|
93
|
+
const outerlayerPaths = discoverOuterlayerPaths(root);
|
|
94
|
+
const retired = retiredSkillPaths(root);
|
|
95
|
+
const inspected = inspectReplacedOutputs(root);
|
|
96
|
+
const edited = inspected.edited;
|
|
97
|
+
const generated = inspected.generated.filter(
|
|
98
|
+
(path) => !hasSymlinkComponent(root, path) && !(opts.controlPlane && (path === SKILLS_LINK_PATH || path.startsWith(`${SKILLS_LINK_PATH}/`) || path.includes(`/${SKILLS_LINK_PATH}/`)))
|
|
99
|
+
);
|
|
100
|
+
const removedSet = /* @__PURE__ */ new Set([...retired, ...generated]);
|
|
101
|
+
const survives = (rel) => {
|
|
102
|
+
if (!exists(root, rel)) return false;
|
|
103
|
+
if (!lstatSync(join(root, rel)).isDirectory()) return !removedSet.has(rel);
|
|
104
|
+
return filesBelow(root, rel).some((file) => !removedSet.has(file));
|
|
105
|
+
};
|
|
106
|
+
if (exists(root, ".outerlayer/config.json") && readConfigObject(root) === void 0) {
|
|
107
|
+
return {
|
|
108
|
+
dryRun: opts.dryRun,
|
|
109
|
+
removed: [],
|
|
110
|
+
editedKept: edited,
|
|
111
|
+
removedDiffering: [],
|
|
112
|
+
moved: [],
|
|
113
|
+
notMoved: [{ path: ".outerlayer/config.json", because: "it is not a JSON object, so the layout cannot be declared; fix it first and nothing has moved" }],
|
|
114
|
+
mcp: { moved: [], merged: [], conflicts: [], keptForCursor: false },
|
|
115
|
+
link: { status: "skipped", reason: "nothing moved" },
|
|
116
|
+
layoutDeclared: false,
|
|
117
|
+
commandsKept: false
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
const linkedSkills = linkedAgentsPath(root);
|
|
121
|
+
if (linkedSkills !== void 0) {
|
|
122
|
+
return {
|
|
123
|
+
dryRun: opts.dryRun,
|
|
124
|
+
removed: [],
|
|
125
|
+
editedKept: edited,
|
|
126
|
+
removedDiffering: [],
|
|
127
|
+
moved: [],
|
|
128
|
+
notMoved: [{ path: linkedSkills, because: "it is a link, and a write there would land outside the repository; nothing has moved" }],
|
|
129
|
+
mcp: { moved: [], merged: [], conflicts: [], keptForCursor: false },
|
|
130
|
+
link: { status: "skipped", reason: "nothing moved" },
|
|
131
|
+
layoutDeclared: false,
|
|
132
|
+
commandsKept: false
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
const moves = [];
|
|
136
|
+
const notMoved = [];
|
|
137
|
+
for (const scope of scopesOf(outerlayerPaths)) {
|
|
138
|
+
const at = (rel) => scope === "" ? rel : `${scope}/${rel}`;
|
|
139
|
+
const instructions = at(".outerlayer/AGENTS.md");
|
|
140
|
+
if (exists(root, instructions)) {
|
|
141
|
+
if (hasSymlinkComponent(root, instructions) || hasSymlinkComponent(root, at("AGENTS.md"))) {
|
|
142
|
+
notMoved.push({ path: instructions, because: "it or its destination is a link, and a move would follow it" });
|
|
143
|
+
} else if (survives(at("AGENTS.md"))) notMoved.push({ path: instructions, because: `${at("AGENTS.md")} exists and is not a file \`context emit\` generated` });
|
|
144
|
+
else moves.push({ from: instructions, to: at("AGENTS.md") });
|
|
145
|
+
}
|
|
146
|
+
const skills = at(".outerlayer/skills");
|
|
147
|
+
if (exists(root, skills) && hasSymlinkComponent(root, skills)) {
|
|
148
|
+
notMoved.push({ path: skills, because: "it is a link, and a move would take files out of the folder it points to" });
|
|
149
|
+
} else if (exists(root, skills)) {
|
|
150
|
+
for (const name of readdirSync(join(root, skills)).sort()) {
|
|
151
|
+
const from = `${skills}/${name}`;
|
|
152
|
+
if (!survives(from)) continue;
|
|
153
|
+
const to = at(`.agents/skills/${name}`);
|
|
154
|
+
if (hasSymlinkComponent(root, from) || hasSymlinkComponent(root, to)) {
|
|
155
|
+
notMoved.push({ path: from, because: `it or ${to} is a link, and a move would follow it` });
|
|
156
|
+
} else if (survives(to)) notMoved.push({ path: from, because: `${to} exists and is not a file \`context emit\` generated` });
|
|
157
|
+
else moves.push({ from, to });
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
const keptForCursor = configuredTargets(root).includes("cursor");
|
|
162
|
+
const mcpPlan = keptForCursor ? [] : scopesOf(outerlayerPaths).map((scope) => ({ src: scope === "" ? ".outerlayer/mcp.json" : `${scope}/.outerlayer/mcp.json`, dst: scope === "" ? ".mcp.json" : `${scope}/.mcp.json` })).filter((m) => exists(root, m.src));
|
|
163
|
+
const linkedMcp = mcpPlan.filter((m) => hasSymlinkComponent(root, m.src) || hasSymlinkComponent(root, m.dst));
|
|
164
|
+
for (const m of linkedMcp) notMoved.push({ path: m.src, because: `it or ${m.dst} is a link, and a move would follow it` });
|
|
165
|
+
mcpPlan.splice(0, mcpPlan.length, ...mcpPlan.filter((m) => !linkedMcp.includes(m)));
|
|
166
|
+
const result = {
|
|
167
|
+
dryRun: opts.dryRun,
|
|
168
|
+
removed: [.../* @__PURE__ */ new Set([...retired, ...generated])].sort(),
|
|
169
|
+
editedKept: edited,
|
|
170
|
+
removedDiffering: inspected.replacedDiffering.filter((path) => removedSet.has(path)),
|
|
171
|
+
moved: moves,
|
|
172
|
+
notMoved,
|
|
173
|
+
mcp: { moved: [], merged: [], conflicts: [], keptForCursor },
|
|
174
|
+
link: { status: "skipped", reason: "not planned" },
|
|
175
|
+
layoutDeclared: false,
|
|
176
|
+
commandsKept: outerlayerPaths.some((p) => /(^|\/)\.outerlayer\/commands\//.test(p))
|
|
177
|
+
};
|
|
178
|
+
const mcpMoves = [];
|
|
179
|
+
for (const { src, dst } of mcpPlan) {
|
|
180
|
+
const source = readJson(root, src);
|
|
181
|
+
if (source === void 0 || serversOf(source) === void 0) {
|
|
182
|
+
result.notMoved.push({ path: src, because: "it is not a JSON object with an mcpServers object" });
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
if (!exists(root, dst)) {
|
|
186
|
+
result.mcp.moved.push({ from: src, to: dst });
|
|
187
|
+
mcpMoves.push({ src, dst });
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
const target = readJson(root, dst);
|
|
191
|
+
const targetServers = target === void 0 ? void 0 : serversOf(target);
|
|
192
|
+
if (target === void 0 || targetServers === void 0) {
|
|
193
|
+
result.notMoved.push({ path: src, because: `${dst} is not a JSON object with an mcpServers object` });
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
const sourceServers = serversOf(source);
|
|
197
|
+
const conflicts = Object.keys(sourceServers).filter((name) => name in targetServers && canonical(targetServers[name]) !== canonical(sourceServers[name]));
|
|
198
|
+
if (conflicts.length > 0) {
|
|
199
|
+
result.mcp.conflicts.push(...conflicts.map((name) => `${dst} "${name}"`));
|
|
200
|
+
result.notMoved.push({ path: src, because: `${dst} defines ${conflicts.map((n) => `"${n}"`).join(", ")} differently` });
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
const missing = Object.keys(sourceServers).filter((name) => !(name in targetServers));
|
|
204
|
+
if (missing.length > 0) {
|
|
205
|
+
result.mcp.merged.push(dst);
|
|
206
|
+
mcpMoves.push({ src, dst, merge: { doc: { ...source, ...target, mcpServers: { ...sourceServers, ...targetServers } } } });
|
|
207
|
+
} else {
|
|
208
|
+
result.mcp.moved.push({ from: src, to: dst });
|
|
209
|
+
mcpMoves.push({ src, dst });
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
const skillsStay = moves.some((m) => m.to === ".agents/skills" || m.to.startsWith(".agents/skills/")) || survives(".agents/skills");
|
|
213
|
+
if (opts.controlPlane) {
|
|
214
|
+
result.link = { status: "skipped", reason: "this control plane keeps .claude/skills/ as a copy for older CLIs" };
|
|
215
|
+
} else if (!opts.skillsLink) {
|
|
216
|
+
result.link = { status: "skipped", reason: "--no-skills-link" };
|
|
217
|
+
} else if (!skillsStay) {
|
|
218
|
+
result.link = { status: "skipped", reason: "there are no skills in .agents/skills/" };
|
|
219
|
+
} else {
|
|
220
|
+
const blocking = opts.dryRun ? filesBelow(root, SKILLS_LINK_PATH).filter((file) => !removedSet.has(file)) : [];
|
|
221
|
+
result.link = blocking.length > 0 ? { status: "blocked", blocking } : { status: "linked" };
|
|
222
|
+
}
|
|
223
|
+
if (result.moved.some((m) => m.to.startsWith(".agents/skills/")) && opts.controlPlane) result.controlPlaneNote = controlPlaneNote();
|
|
224
|
+
result.layoutDeclared = result.notMoved.length === 0;
|
|
225
|
+
if (opts.dryRun) return result;
|
|
226
|
+
removeRetiredSkills(root, (path) => hasSymlinkComponent(root, path));
|
|
227
|
+
for (const path of generated) removeFile(root, path);
|
|
228
|
+
result.removed = result.removed.filter((path) => !exists(root, path));
|
|
229
|
+
for (const { from, to } of moves) {
|
|
230
|
+
mkdirSync(join(root, dirname(to)), { recursive: true });
|
|
231
|
+
renameSync(join(root, from), join(root, to));
|
|
232
|
+
}
|
|
233
|
+
for (const scope of scopesOf(outerlayerPaths)) {
|
|
234
|
+
const outerlayer = scope === "" ? ".outerlayer" : `${scope}/.outerlayer`;
|
|
235
|
+
for (const dir of [`${outerlayer}/skills`, outerlayer]) {
|
|
236
|
+
try {
|
|
237
|
+
rmdirSync(join(root, dir));
|
|
238
|
+
} catch {
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
for (const m of mcpMoves) {
|
|
243
|
+
if (m.merge !== void 0) writeFileSync(join(root, m.dst), `${JSON.stringify(m.merge.doc, null, 2)}
|
|
244
|
+
`);
|
|
245
|
+
else if (!exists(root, m.dst)) renameSync(join(root, m.src), join(root, m.dst));
|
|
246
|
+
if (exists(root, m.src)) unlinkSync(join(root, m.src));
|
|
247
|
+
}
|
|
248
|
+
if (result.link.status === "linked" || result.link.status === "blocked") result.link = linkClaudeSkills(root);
|
|
249
|
+
result.layoutDeclared = result.notMoved.length === 0 && declareAgentsMdLayout(root);
|
|
250
|
+
return result;
|
|
251
|
+
}
|
|
252
|
+
function describeMigration(m, color) {
|
|
253
|
+
const { green, yellow, dim, reset } = color;
|
|
254
|
+
const lines = [];
|
|
255
|
+
const verb = (done, planned) => m.dryRun ? planned : `${green}${done}${reset}`;
|
|
256
|
+
lines.push(m.dryRun ? "Move to the AGENTS.md layout (nothing written):" : "Moved to the AGENTS.md layout:");
|
|
257
|
+
for (const path of m.removed) lines.push(` ${verb("removed", "would remove")} ${path} ${dim}(generated by emit)${reset}`);
|
|
258
|
+
for (const path of m.removedDiffering) {
|
|
259
|
+
lines.push(` ${dim}${path} differed from this CLI's copy of the skill; its header says an edit is overwritten, so it ${m.dryRun ? "would be removed" : "was removed"} with the others${reset}`);
|
|
260
|
+
}
|
|
261
|
+
for (const { from, to } of m.moved) lines.push(` ${verb("moved", "would move")} ${from} to ${to}`);
|
|
262
|
+
for (const { from, to } of m.mcp.moved) lines.push(` ${verb("moved", "would move")} ${from} to ${to}`);
|
|
263
|
+
for (const path of m.mcp.merged) lines.push(` ${verb("added", "would add")} the servers of an .outerlayer/mcp.json to ${path}`);
|
|
264
|
+
if (m.mcp.keptForCursor) lines.push(` ${dim}kept .outerlayer/mcp.json: the cursor target compiles it into .cursor/mcp.json${reset}`);
|
|
265
|
+
for (const path of m.editedKept) {
|
|
266
|
+
lines.push(` ${yellow}kept${reset} ${path} ${dim}(differs from what emit generates, so it is yours; delete it by hand if you do not need it)${reset}`);
|
|
267
|
+
}
|
|
268
|
+
for (const { path, because } of m.notMoved) lines.push(` ${yellow}left${reset} ${path} ${dim}(${because})${reset}`);
|
|
269
|
+
if (m.commandsKept) {
|
|
270
|
+
lines.push(` ${dim}kept .outerlayer/commands/ and the commands compiled from it: run \`${cliInvocation()} context emit\` after you change a command${reset}`);
|
|
271
|
+
}
|
|
272
|
+
if (m.link.status === "skipped") lines.push(` ${dim}no .claude/skills link (${m.link.reason})${reset}`);
|
|
273
|
+
else if (m.dryRun) {
|
|
274
|
+
lines.push(
|
|
275
|
+
m.link.status === "linked" ? ` would link ${SKILLS_LINK_PATH} to ../.agents/skills` : ` ${yellow}would leave${reset} ${SKILLS_LINK_PATH}/ as it is: it still holds ${m.link.blocking.join(", ")}`
|
|
276
|
+
);
|
|
277
|
+
} else {
|
|
278
|
+
const text = describeSkillsLink(m.link);
|
|
279
|
+
if (text !== "") lines.push(` ${m.link.status === "linked" ? `${green}\u2713${reset}` : `${yellow}!${reset}`} ${text}`);
|
|
280
|
+
}
|
|
281
|
+
if (m.notMoved.length > 0 || !m.layoutDeclared) {
|
|
282
|
+
lines.push(` ${yellow}!${reset} The layout is not declared yet. Resolve the files listed as left, then run \`${cliInvocation()} init --update\` again.`);
|
|
283
|
+
} else {
|
|
284
|
+
lines.push(` ${verb("declared", "would declare")} "layout": 2 in .outerlayer/config.json`);
|
|
285
|
+
}
|
|
286
|
+
if (m.controlPlaneNote !== void 0) lines.push("", m.controlPlaneNote);
|
|
287
|
+
return lines;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// src/init-update.ts
|
|
291
|
+
var NOT_COMPILED = `There is no .outerlayer/config.json, so \`${cliInvocation()} context emit\` did not run.`;
|
|
292
|
+
var errorMessage = (err) => err instanceof Error ? err.message : String(err);
|
|
293
|
+
function actionFor(item) {
|
|
294
|
+
if (item.state === "outdated") return "update";
|
|
295
|
+
if (item.state === "missing") return "write";
|
|
296
|
+
if (item.state === "current") return "none";
|
|
297
|
+
return "keep";
|
|
298
|
+
}
|
|
299
|
+
function removals(root, report, packRoot) {
|
|
300
|
+
const manifest = readShippedManifest(packRoot);
|
|
301
|
+
const planned = [];
|
|
302
|
+
const add = (path) => planned.push({ path, state: "retired", action: "remove" });
|
|
303
|
+
const skillsDir = `${report.base}/`;
|
|
304
|
+
for (const file of report.retired.filter((f) => f.state === "unedited")) {
|
|
305
|
+
add(file.path);
|
|
306
|
+
const rel = file.path.slice(skillsDir.length);
|
|
307
|
+
if (report.base !== OUTERLAYER_SKILLS_BASE || !manifest.ok || !/^[^/]+\/scripts\//.test(rel)) continue;
|
|
308
|
+
for (const folder of skillsFolders().filter((f) => `${f}/` !== skillsDir)) {
|
|
309
|
+
const native = `${folder}/${rel}`;
|
|
310
|
+
if (hasSymlinkComponent(root, native)) continue;
|
|
311
|
+
try {
|
|
312
|
+
if (manifest.files.get(file.path)?.has(contentHash(readFileSync(join(root, native), "utf8"))) === true) add(native);
|
|
313
|
+
} catch {
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
return planned;
|
|
318
|
+
}
|
|
319
|
+
function plan(report) {
|
|
320
|
+
return report.items.map((item) => {
|
|
321
|
+
const planned = { path: item.path, state: item.state, action: actionFor(item) };
|
|
322
|
+
if (item.kind === "mcp") planned.server = item.server;
|
|
323
|
+
if (item.kind === "file" && item.state === "edited" && item.file.source !== void 0) {
|
|
324
|
+
planned.compare = `git diff --no-index ${item.file.source} ${item.path}`;
|
|
325
|
+
}
|
|
326
|
+
return planned;
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
function apply(root, item) {
|
|
330
|
+
if (item.kind === "file") {
|
|
331
|
+
const abs = join(root, item.path);
|
|
332
|
+
mkdirSync(dirname(abs), { recursive: true });
|
|
333
|
+
writeFileSync(abs, item.file.content);
|
|
334
|
+
} else {
|
|
335
|
+
setMcpEntry(root, item.server, { ...item.entry });
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
var CLASHING_FLAGS = ["remove", "org", "local", "template", "factory"];
|
|
339
|
+
function updateFlagProblem(flags) {
|
|
340
|
+
if (flags.update !== true) return flags.dryRun === true ? "--dry-run only applies to --update." : void 0;
|
|
341
|
+
const clash = CLASHING_FLAGS.find((name) => flags[name] !== void 0 && flags[name] !== false);
|
|
342
|
+
return clash === void 0 ? void 0 : `--update changes only the files init wrote, so it cannot be combined with --${clash}.`;
|
|
343
|
+
}
|
|
344
|
+
var MCP_SOURCE = ".outerlayer/mcp.json";
|
|
345
|
+
function sameJson(a, b) {
|
|
346
|
+
try {
|
|
347
|
+
return b !== void 0 && canonical(JSON.parse(a)) === canonical(JSON.parse(b));
|
|
348
|
+
} catch {
|
|
349
|
+
return false;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
function keepUnlessCompiled(keep, mcpSourceBefore) {
|
|
353
|
+
return (output) => {
|
|
354
|
+
if (output.kind === "file" && sameJson(output.existing, mcpSourceBefore)) return false;
|
|
355
|
+
return keep(output);
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
function maintainedDrift(root, packRoot, base) {
|
|
359
|
+
return maintainedFilesForExistingSkills(root, loadMaintainedFiles(packRoot, void 0, base), base).filter((file) => !existsSync(join(root, file.path)) || readFileSync(join(root, file.path), "utf8") !== file.content).map((file) => {
|
|
360
|
+
const present = existsSync(join(root, file.path));
|
|
361
|
+
return { item: { path: file.path, state: present ? "outdated" : "missing", action: present ? "update" : "write" }, file };
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
function runStarterUpdate(opts) {
|
|
365
|
+
const dryRun = opts.dryRun === true;
|
|
366
|
+
const empty = { dryRun, items: [], emitted: [], kept: [], manifest: "ok" };
|
|
367
|
+
const dirs = findGitDirs(opts.cwd);
|
|
368
|
+
if (dirs === void 0) return { ...empty, status: "skipped", reason: "not a git repository" };
|
|
369
|
+
const root = dirs.repoRoot;
|
|
370
|
+
if (contextIsGoverned(dirs.gitCommonDir)) {
|
|
371
|
+
return { ...empty, status: "skipped", reason: "this repository's context comes from a control plane and arrives at session start" };
|
|
372
|
+
}
|
|
373
|
+
const skillsBase = opts.base ?? skillsBaseFor(root);
|
|
374
|
+
const agentsMd = skillsBase === AGENTS_SKILLS_BASE;
|
|
375
|
+
const linked = agentsMd ? linkedAgentsPath(root) : void 0;
|
|
376
|
+
if (linked !== void 0) return { ...empty, status: "failed", reason: `${linked} is a link, and a write there would land outside the repository; replace it with a folder and run this again` };
|
|
377
|
+
const report = inspectStarterFiles(root, { packRoot: opts.packRoot, base: skillsBase });
|
|
378
|
+
const dropped = removals(root, report, opts.packRoot);
|
|
379
|
+
const refreshed = agentsMd ? maintainedDrift(root, opts.packRoot, skillsBase) : [];
|
|
380
|
+
const items = [...plan(report), ...refreshed.map((r) => r.item), ...dropped];
|
|
381
|
+
const base = { dryRun, items, emitted: [], kept: [], manifest: report.manifest };
|
|
382
|
+
const changes = report.items.filter((i) => i.state === "outdated" || i.state === "missing");
|
|
383
|
+
const nothing = changes.length === 0 && dropped.length === 0 && refreshed.length === 0;
|
|
384
|
+
if (dryRun || nothing) return { ...base, status: "done", reason: nothing ? "nothing to update" : "dry run" };
|
|
385
|
+
const created = new Set(changes.filter((i) => i.kind === "file" && i.state === "missing").map((i) => i.path));
|
|
386
|
+
const mcpSource = join(root, MCP_SOURCE);
|
|
387
|
+
const mcpSourceBefore = existsSync(mcpSource) ? readFileSync(mcpSource, "utf8") : void 0;
|
|
388
|
+
try {
|
|
389
|
+
for (const item of changes) apply(root, item);
|
|
390
|
+
for (const item of dropped) if (!removeFile(root, item.path)) item.action = "keep";
|
|
391
|
+
if (agentsMd) writeMaintainedFiles(root, refreshed.map((r) => ({ ...r.file, skill: "", skillClass: "maintained" })));
|
|
392
|
+
} catch (err) {
|
|
393
|
+
return { ...base, status: "failed", reason: `could not write the files: ${errorMessage(err)}` };
|
|
394
|
+
}
|
|
395
|
+
if (agentsMd) return { ...base, status: "done", reason: "updated" };
|
|
396
|
+
if (!existsSync(join(root, ".outerlayer", "config.json"))) {
|
|
397
|
+
try {
|
|
398
|
+
writeMaintainedFiles(root, maintainedFilesForExistingSkills(root, loadMaintainedFiles(opts.packRoot)));
|
|
399
|
+
} catch (err) {
|
|
400
|
+
return { ...base, status: "failed", reason: `could not write the files: ${errorMessage(err)}` };
|
|
401
|
+
}
|
|
402
|
+
return { ...base, status: "done", reason: NOT_COMPILED };
|
|
403
|
+
}
|
|
404
|
+
try {
|
|
405
|
+
const keep = keepUnlessCompiled(keepHandWritten(created), mcpSourceBefore);
|
|
406
|
+
const pending = runEmit({ cwd: root, check: true, quiet: true, keep }).drift ?? [];
|
|
407
|
+
const emitted = runEmit({ cwd: root, quiet: true, keep });
|
|
408
|
+
if (emitted.exitCode !== 0) throw new Error(emitted.errors.map((e) => `${e.path}: ${e.message}`).join("; "));
|
|
409
|
+
return {
|
|
410
|
+
...base,
|
|
411
|
+
status: "done",
|
|
412
|
+
reason: "updated",
|
|
413
|
+
emitted: pending.filter((d) => d.kind !== "orphaned").map((d) => d.path),
|
|
414
|
+
kept: emitted.kept
|
|
415
|
+
};
|
|
416
|
+
} catch (err) {
|
|
417
|
+
return { ...base, status: "failed", reason: `context emit failed: ${errorMessage(err)}` };
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
var TEXT_FILE = /\.(md|ya?ml|json|mjs|cjs|js|ts|sh|py|txt)$/;
|
|
421
|
+
var OLD_SKILLS_PATH = ".outerlayer/skills/";
|
|
422
|
+
function staleSkillReferences(root) {
|
|
423
|
+
const candidates = ["AGENTS.md", ".outerlayer/policy.yaml"];
|
|
424
|
+
for (const dir of [".outerlayer/validators", ".agents/skills"]) {
|
|
425
|
+
const walk = (rel) => {
|
|
426
|
+
let entries;
|
|
427
|
+
try {
|
|
428
|
+
entries = readdirSync(join(root, rel), { withFileTypes: true });
|
|
429
|
+
} catch {
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
for (const entry of entries) {
|
|
433
|
+
if (entry.isDirectory()) walk(`${rel}/${entry.name}`);
|
|
434
|
+
else if (entry.isFile() && TEXT_FILE.test(entry.name)) candidates.push(`${rel}/${entry.name}`);
|
|
435
|
+
}
|
|
436
|
+
};
|
|
437
|
+
walk(dir);
|
|
438
|
+
}
|
|
439
|
+
return candidates.filter((rel) => {
|
|
440
|
+
try {
|
|
441
|
+
return readFileSync(join(root, rel), "utf8").includes(OLD_SKILLS_PATH);
|
|
442
|
+
} catch {
|
|
443
|
+
return false;
|
|
444
|
+
}
|
|
445
|
+
}).sort();
|
|
446
|
+
}
|
|
447
|
+
function runInitUpdate(opts) {
|
|
448
|
+
const dryRun = opts.dryRun === true;
|
|
449
|
+
const dirs = findGitDirs(opts.cwd);
|
|
450
|
+
if (dirs === void 0 || contextIsGoverned(dirs.gitCommonDir)) return runStarterUpdate(opts);
|
|
451
|
+
const root = dirs.repoRoot;
|
|
452
|
+
const todays = !isAgentsMdLayout(root) && (existsSync(join(root, ".outerlayer", "config.json")) || holdsTodaysLayoutSources(discoverOuterlayerPaths(root)));
|
|
453
|
+
if (!todays) {
|
|
454
|
+
if (!isAgentsMdLayout(root) && !dryRun && linkedAgentsPath(root) === void 0) declareAgentsMdLayout(root);
|
|
455
|
+
return runStarterUpdate({ ...opts, base: AGENTS_SKILLS_BASE });
|
|
456
|
+
}
|
|
457
|
+
let migration;
|
|
458
|
+
try {
|
|
459
|
+
migration = migrateToAgentsMdLayout(root, { dryRun, skillsLink: opts.skillsLink !== false, controlPlane: opts.controlPlane === true });
|
|
460
|
+
} catch (err) {
|
|
461
|
+
return { status: "failed", reason: `could not move the files: ${errorMessage(err)}`, dryRun, items: [], emitted: [], kept: [], manifest: "ok" };
|
|
462
|
+
}
|
|
463
|
+
if (dryRun) return { status: "done", reason: "dry run", dryRun, items: [], emitted: [], kept: [], manifest: "ok", migration };
|
|
464
|
+
if (migration.notMoved.length > 0 || !migration.layoutDeclared) {
|
|
465
|
+
return { status: "done", reason: "the move is not finished, so the starter files are left as they are", dryRun, items: [], emitted: [], kept: [], manifest: "ok", migration };
|
|
466
|
+
}
|
|
467
|
+
const starter = runStarterUpdate({ cwd: opts.cwd, packRoot: opts.packRoot });
|
|
468
|
+
if (migration.link.status === "skipped" && migration.link.reason.startsWith("there are no skills") && existsSync(join(root, ".agents", "skills"))) {
|
|
469
|
+
migration.link = linkClaudeSkills(root);
|
|
470
|
+
}
|
|
471
|
+
const staleReferences = isAgentsMdLayout(root) ? staleSkillReferences(root) : [];
|
|
472
|
+
return { ...starter, migration, ...staleReferences.length > 0 ? { staleReferences } : {} };
|
|
473
|
+
}
|
|
474
|
+
var VERB = {
|
|
475
|
+
update: { done: "updated", planned: "would update" },
|
|
476
|
+
write: { done: "wrote", planned: "would write" },
|
|
477
|
+
remove: { done: "removed", planned: "would remove" }
|
|
478
|
+
};
|
|
479
|
+
function formatInitUpdate(result) {
|
|
480
|
+
if (result.status === "skipped") return `${C.dim}- Nothing to update: ${result.reason}${C.reset}
|
|
481
|
+
`;
|
|
482
|
+
const lines = [];
|
|
483
|
+
const label = (p) => p.server === void 0 ? p.path : `${p.path} "${p.server}" server`;
|
|
484
|
+
const changed = result.items.filter((p) => p.action === "update" || p.action === "write" || p.action === "remove");
|
|
485
|
+
const kept = result.items.filter((p) => p.action === "keep" && p.state !== "retired");
|
|
486
|
+
const current = result.items.filter((p) => p.action === "none");
|
|
487
|
+
if (result.migration !== void 0) lines.push(...describeMigration(result.migration, C), "");
|
|
488
|
+
if (result.migration?.dryRun === true) {
|
|
489
|
+
lines.push(`${C.dim}The starter files are checked after the move.${C.reset}`);
|
|
490
|
+
return `${lines.join("\n")}
|
|
491
|
+
`;
|
|
492
|
+
}
|
|
493
|
+
lines.push(result.dryRun ? `Plan for \`${cliInvocation()} init --update\` (nothing written):` : "Starter files:");
|
|
494
|
+
for (const p of changed) {
|
|
495
|
+
const verb = VERB[p.action];
|
|
496
|
+
const why = p.action === "update" ? "outdated, unedited" : p.action === "remove" ? "no longer shipped, unedited" : "missing";
|
|
497
|
+
lines.push(` ${result.dryRun ? verb.planned : `${C.green}${verb.done}${C.reset}`} ${label(p)} ${C.dim}(${why})${C.reset}`);
|
|
498
|
+
}
|
|
499
|
+
for (const p of kept) {
|
|
500
|
+
const why = p.state === "unreadable" ? "not valid JSON" : "edited by you";
|
|
501
|
+
lines.push(` ${C.yellow}kept${C.reset} ${label(p)} ${C.dim}(${why}, left as it is)${C.reset}`);
|
|
502
|
+
if (p.compare !== void 0) lines.push(` ${C.dim}compare: ${p.compare}${C.reset}`);
|
|
503
|
+
}
|
|
504
|
+
if (current.length > 0) lines.push(` ${C.dim}${current.length} already current${C.reset}`);
|
|
505
|
+
if (result.manifest !== "ok") {
|
|
506
|
+
lines.push(
|
|
507
|
+
` ${C.yellow}!${C.reset} This CLI's record of earlier versions is ${result.manifest}, so every changed file counts as edited and is left as it is.`
|
|
508
|
+
);
|
|
509
|
+
}
|
|
510
|
+
if (result.emitted.length > 0) {
|
|
511
|
+
lines.push("", `Recompiled by \`${cliInvocation()} context emit\`:`, ...result.emitted.map((p) => ` ${p}`));
|
|
512
|
+
}
|
|
513
|
+
for (const p of result.kept) lines.push(` ${C.dim}kept ${p} (written by hand, not replaced)${C.reset}`);
|
|
514
|
+
if (result.staleReferences !== void 0) {
|
|
515
|
+
lines.push("", `These files still name .outerlayer/skills/, which no longer holds the skills. Change each path to .agents/skills/:`);
|
|
516
|
+
lines.push(...result.staleReferences.map((p) => ` ${p}`));
|
|
517
|
+
}
|
|
518
|
+
const migrated = result.migration !== void 0 && !result.dryRun;
|
|
519
|
+
if (result.status === "failed") lines.push("", `${C.red}\u2717${C.reset} ${result.reason}`);
|
|
520
|
+
else if (!result.dryRun && (changed.length > 0 || migrated)) {
|
|
521
|
+
if (result.reason === NOT_COMPILED) lines.push("", `${C.dim}${NOT_COMPILED}${C.reset}`);
|
|
522
|
+
lines.push("", "The changes are left uncommitted.", COMMIT_LINE);
|
|
523
|
+
if (migrated) lines.push("Commit the removed and moved files too: AGENTS.md, .agents/, .mcp.json and .claude/skills.");
|
|
524
|
+
} else if (changed.length === 0) lines.push("", `${C.green}\u2713${C.reset} Nothing to update.`);
|
|
525
|
+
return `${lines.join("\n")}
|
|
526
|
+
`;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
export { formatInitUpdate, runInitUpdate, runStarterUpdate, updateFlagProblem };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
export { AGENTS_MD_LAYOUT, FIRST_VERSION_READING_AGENTS_SKILLS, SKILLS_LINK_PATH, declareAgentsMdLayout, describeSkillsLink, filesBelow, holdsTodaysLayoutSources, isAgentsMdLayout, linkClaudeSkills, readConfigObject, skillsBaseFor } from './chunk-JKNYTNYD.js';
|
|
4
|
+
import './chunk-HBISTTG3.js';
|
|
5
|
+
import './chunk-RKOTJQVG.js';
|
|
6
|
+
import './chunk-QZBXLLTV.js';
|
|
7
|
+
import './chunk-RA3O54FC.js';
|
|
8
|
+
import './chunk-Z5GEFMRW.js';
|
|
9
|
+
|
|
10
|
+
createRequire(import.meta.url);
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
export { DEFAULT_DASHBOARD, readPipedKey, realLoginDeps, runLoginCommand, sanitizeMachineName, stdinKind } from './chunk-
|
|
4
|
-
import './chunk-
|
|
3
|
+
export { DEFAULT_DASHBOARD, readPipedKey, realLoginDeps, runLoginCommand, sanitizeMachineName, stdinKind } from './chunk-XSPA5ODY.js';
|
|
4
|
+
import './chunk-GOSFARMS.js';
|
|
5
5
|
import './chunk-BJ3KTMDH.js';
|
|
6
|
-
import './chunk-EABW6AJQ.js';
|
|
7
6
|
import './chunk-ANPNT6PM.js';
|
|
7
|
+
import './chunk-EABW6AJQ.js';
|
|
8
8
|
import './chunk-CRB3POP4.js';
|
|
9
|
+
import './chunk-QZBXLLTV.js';
|
|
9
10
|
import './chunk-VNVZDWO3.js';
|
|
10
11
|
import './chunk-Z5GEFMRW.js';
|
|
11
12
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
export { realLogoutDeps, revokeTokenOnDashboard, runLogoutCommand } from './chunk-
|
|
4
|
-
import './chunk-EABW6AJQ.js';
|
|
3
|
+
export { realLogoutDeps, revokeTokenOnDashboard, runLogoutCommand } from './chunk-GOSFARMS.js';
|
|
5
4
|
import './chunk-ANPNT6PM.js';
|
|
5
|
+
import './chunk-EABW6AJQ.js';
|
|
6
6
|
import './chunk-CRB3POP4.js';
|
|
7
7
|
import './chunk-VNVZDWO3.js';
|
|
8
8
|
import './chunk-Z5GEFMRW.js';
|