@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
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { resolvePackRoot, loadTemplateFiles, loadMaintainedFiles, TEMPLATE_SKILLS, skillDir, writeMaintainedFiles, MAINTAINED_SKILLS } from './chunk-5OCIHFGE.js';
|
|
4
3
|
import { C } from './chunk-ANPNT6PM.js';
|
|
4
|
+
import { resolvePackRoot, OUTERLAYER_SKILLS_BASE, loadTemplateFiles, loadMaintainedFiles, rewriteSkillPaths, TEMPLATE_SKILLS, skillDir, writeMaintainedFiles, MAINTAINED_SKILLS } from './chunk-HBISTTG3.js';
|
|
5
5
|
import { cliInvocation } from './chunk-CRB3POP4.js';
|
|
6
|
+
import { linkedAgentsPath } from './chunk-VWFOKRYS.js';
|
|
6
7
|
import { resolvePackageVersion } from './chunk-RA3O54FC.js';
|
|
7
8
|
import { readFileSync, existsSync, mkdirSync, writeFileSync } from 'fs';
|
|
8
9
|
import { join, dirname } from 'path';
|
|
@@ -26,16 +27,19 @@ function assertKnownTemplate(name) {
|
|
|
26
27
|
function installStarterPack(opts) {
|
|
27
28
|
const packRoot = opts.packRoot ?? resolvePackRoot();
|
|
28
29
|
const version = opts.version ?? resolvePackageVersion();
|
|
29
|
-
const
|
|
30
|
-
const
|
|
30
|
+
const base = opts.base ?? OUTERLAYER_SKILLS_BASE;
|
|
31
|
+
const linked = base.startsWith(".agents/") ? linkedAgentsPath(opts.repoRoot) : void 0;
|
|
32
|
+
if (linked !== void 0) throw new StarterPackError(`${linked} is a link, and a write there would land outside the repository; replace it with a folder and run this again`);
|
|
33
|
+
const templateFiles = loadTemplateFiles(packRoot, version, base);
|
|
34
|
+
const maintainedFiles = loadMaintainedFiles(packRoot, version, base);
|
|
31
35
|
const validatorFiles = VALIDATOR_FILES.map(({ name }) => ({
|
|
32
36
|
path: `${VALIDATORS_DIR}/${name}`,
|
|
33
|
-
content: readFileSync(join(packRoot, "validators", name), "utf8")
|
|
37
|
+
content: rewriteSkillPaths(readFileSync(join(packRoot, "validators", name), "utf8"), base)
|
|
34
38
|
}));
|
|
35
39
|
const copied = [];
|
|
36
40
|
const kept = [];
|
|
37
41
|
for (const skill of TEMPLATE_SKILLS) {
|
|
38
|
-
if (existsSync(join(opts.repoRoot, skillDir(skill)))) {
|
|
42
|
+
if (existsSync(join(opts.repoRoot, skillDir(skill, base)))) {
|
|
39
43
|
kept.push(skill);
|
|
40
44
|
continue;
|
|
41
45
|
}
|
|
@@ -67,6 +71,7 @@ function installStarterPack(opts) {
|
|
|
67
71
|
validatorsWritten.push(file.path);
|
|
68
72
|
}
|
|
69
73
|
return {
|
|
74
|
+
base,
|
|
70
75
|
copied,
|
|
71
76
|
kept,
|
|
72
77
|
maintained: [...written.created, ...written.rewritten],
|
|
@@ -75,21 +80,23 @@ function installStarterPack(opts) {
|
|
|
75
80
|
validatorsKept
|
|
76
81
|
};
|
|
77
82
|
}
|
|
78
|
-
var skillFile = (skill) => `${skillDir(skill)}/SKILL.md`;
|
|
83
|
+
var skillFile = (skill, base) => `${skillDir(skill, base)}/SKILL.md`;
|
|
79
84
|
function validatorLabel(path) {
|
|
80
85
|
return VALIDATOR_FILES.find(({ name }) => path === `${VALIDATORS_DIR}/${name}`)?.label ?? "a check";
|
|
81
86
|
}
|
|
82
87
|
function formatStarterPackOutput(result) {
|
|
83
88
|
const lines = [];
|
|
84
|
-
|
|
89
|
+
const { base } = result;
|
|
90
|
+
lines.push(`${C.green}\u2713${C.reset} Installed the starter skills in ${base}/`, "");
|
|
85
91
|
lines.push("Yours to edit \u2014 copied once, never overwritten:");
|
|
86
92
|
for (const skill of TEMPLATE_SKILLS) {
|
|
87
93
|
lines.push(
|
|
88
|
-
result.kept.includes(skill) ? ` ${C.dim}kept${C.reset} ${skillDir(skill)}/ ${C.dim}(already exists, left exactly as it is)${C.reset}` : ` ${skillFile(skill)}`
|
|
94
|
+
result.kept.includes(skill) ? ` ${C.dim}kept${C.reset} ${skillDir(skill, base)}/ ${C.dim}(already exists, left exactly as it is)${C.reset}` : ` ${skillFile(skill, base)}`
|
|
89
95
|
);
|
|
90
96
|
}
|
|
91
|
-
|
|
92
|
-
|
|
97
|
+
const rewriter = base === OUTERLAYER_SKILLS_BASE ? "emit" : "`init --update`";
|
|
98
|
+
lines.push("", `Rewritten on every ${rewriter} \u2014 edits are overwritten by the installed CLI:`);
|
|
99
|
+
for (const skill of MAINTAINED_SKILLS) lines.push(` ${skillFile(skill, base)}`);
|
|
93
100
|
lines.push(
|
|
94
101
|
"",
|
|
95
102
|
result.policy === "written" ? `${C.green}\u2713${C.reset} Wrote ${POLICY_PATH} (review required)` : `${C.dim}${POLICY_PATH} already exists \u2014 left as it is${C.reset}`,
|
|
@@ -98,8 +105,10 @@ function formatStarterPackOutput(result) {
|
|
|
98
105
|
),
|
|
99
106
|
...result.validatorsKept.map((path) => `${C.dim}${path} already exists \u2014 left as it is${C.reset}`),
|
|
100
107
|
"",
|
|
101
|
-
|
|
102
|
-
|
|
108
|
+
...base === OUTERLAYER_SKILLS_BASE ? [
|
|
109
|
+
`Next: create .outerlayer/config.json naming your agent tools, for example {"targets": ["claude-code"]},`,
|
|
110
|
+
`then run ${C.yellow}${cliInvocation()} context emit${C.reset} to compile the skills into their native files.`
|
|
111
|
+
] : [`Agents read these skills from ${base}/ as they are. Nothing needs compiling.`]
|
|
103
112
|
);
|
|
104
113
|
return lines.join("\n") + "\n";
|
|
105
114
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
3
|
import { rewriteControlPlanePaths, rewriteAgentsFilePaths, SUPPORTED_CONTROL_PLANE_LAYOUT, rewriteHookCommand } from './chunk-HCVLP7XA.js';
|
|
4
|
-
import { MAINTAINED_SKILLS } from './chunk-
|
|
4
|
+
import { MAINTAINED_SKILLS } from './chunk-HBISTTG3.js';
|
|
5
5
|
import { existsSync, mkdirSync, copyFileSync, lstatSync, readdirSync, writeFileSync, readFileSync } from 'fs';
|
|
6
6
|
import { join, dirname } from 'path';
|
|
7
7
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
3
|
import { readContextManifest, removeContextManifest } from './chunk-YQR6E6OV.js';
|
|
4
4
|
import { removePreCommitGuardHook } from './chunk-TUSYOL2O.js';
|
|
5
|
-
import { CONTEXT_PIN_FILENAME } from './chunk-
|
|
5
|
+
import { CONTEXT_PIN_FILENAME } from './chunk-RKOTJQVG.js';
|
|
6
6
|
import { execFileSync } from 'child_process';
|
|
7
7
|
import { lstatSync, existsSync, unlinkSync, readdirSync, rmdirSync, readFileSync, mkdirSync, writeFileSync } from 'fs';
|
|
8
8
|
import { join, dirname, isAbsolute } from 'path';
|
|
@@ -80,6 +80,9 @@ function hasSymlinkComponent(root, rel) {
|
|
|
80
80
|
}
|
|
81
81
|
return false;
|
|
82
82
|
}
|
|
83
|
+
function linkedAgentsPath(root) {
|
|
84
|
+
return [".agents", ".agents/skills"].find((rel) => hasSymlinkComponent(root, rel));
|
|
85
|
+
}
|
|
83
86
|
function trackedPaths(repoRoot) {
|
|
84
87
|
try {
|
|
85
88
|
const out = execFileSync("git", ["ls-files", "-z", "--", "AGENTS.md", ".claude", ".outerlayer"], {
|
|
@@ -171,4 +174,4 @@ function cleanupEarlierCopies(input) {
|
|
|
171
174
|
return result;
|
|
172
175
|
}
|
|
173
176
|
|
|
174
|
-
export { cleanupEarlierCopies, hasSymlinkComponent };
|
|
177
|
+
export { cleanupEarlierCopies, hasSymlinkComponent, linkedAgentsPath };
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { retiredSkillPaths, removeRetiredSkills } from './chunk-
|
|
4
|
-
import { maintainedFilesForExistingSkills, loadMaintainedFiles, writeMaintainedFiles } from './chunk-5OCIHFGE.js';
|
|
3
|
+
import { retiredSkillPaths, removeRetiredSkills } from './chunk-MQ743JX3.js';
|
|
5
4
|
import { C } from './chunk-ANPNT6PM.js';
|
|
5
|
+
import { isAgentsMdLayout, discoverOuterlayerPaths, isForeignTree, toRepoRelative } from './chunk-JKNYTNYD.js';
|
|
6
|
+
import { maintainedFilesForExistingSkills, loadMaintainedFiles, writeMaintainedFiles } from './chunk-HBISTTG3.js';
|
|
6
7
|
import { cliInvocation } from './chunk-CRB3POP4.js';
|
|
7
|
-
import { emitTree,
|
|
8
|
+
import { emitTree, generatedHeaderSource, parseOuterlayerConfig, classifyTree } from './chunk-RKOTJQVG.js';
|
|
8
9
|
import { existsSync, readFileSync, mkdirSync, writeFileSync, copyFileSync, unlinkSync, rmdirSync, readdirSync } from 'fs';
|
|
9
|
-
import { join, dirname
|
|
10
|
+
import { join, dirname } from 'path';
|
|
10
11
|
|
|
11
12
|
createRequire(import.meta.url);
|
|
12
13
|
var CONTENT_KINDS = /* @__PURE__ */ new Set(["instructions", "skill", "skill-reference", "command", "mcp"]);
|
|
@@ -14,6 +15,13 @@ var SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", ".git"]);
|
|
|
14
15
|
var NO_CONFIG_MESSAGE = 'no .outerlayer/config.json with a non-empty targets array \u2014 create one, e.g. {"targets": ["claude-code"]}';
|
|
15
16
|
var EmitError = class extends Error {
|
|
16
17
|
};
|
|
18
|
+
var EMIT_NOT_NEEDED_NOTICE = `Claude Code and Codex read AGENTS.md and .agents/skills/ without a generated copy. Run \`${cliInvocation()} init --update\` to move this repository there and stop committing generated files.`;
|
|
19
|
+
var NATIVE_TARGETS = /* @__PURE__ */ new Set(["claude-code", "codex"]);
|
|
20
|
+
function noticeFor(repoRoot, targets) {
|
|
21
|
+
if (targets.length === 0 || !targets.every((t) => NATIVE_TARGETS.has(t))) return void 0;
|
|
22
|
+
return isAgentsMdLayout(repoRoot) ? void 0 : EMIT_NOT_NEEDED_NOTICE;
|
|
23
|
+
}
|
|
24
|
+
var HAND_OWNED_OUTPUT = /(^|\/)(CLAUDE\.md|AGENTS\.md|\.claude\/skills\/|\.agents\/skills\/)/;
|
|
17
25
|
function resolveTargetsFromConfig(repoRoot) {
|
|
18
26
|
const configPath = join(repoRoot, ".outerlayer", "config.json");
|
|
19
27
|
if (!existsSync(configPath)) throw new EmitError(NO_CONFIG_MESSAGE);
|
|
@@ -24,36 +32,6 @@ function resolveTargetsFromConfig(repoRoot) {
|
|
|
24
32
|
const detail = result.errors.map((e) => `${e.path}: ${e.message}`).join("; ");
|
|
25
33
|
throw new EmitError(`invalid .outerlayer/config.json \u2014 ${detail}`);
|
|
26
34
|
}
|
|
27
|
-
function toRepoRelative(repoRoot, absPath) {
|
|
28
|
-
return normalizePath(relative(repoRoot, absPath).split(sep).join("/"));
|
|
29
|
-
}
|
|
30
|
-
function discoverOuterlayerPaths(repoRoot) {
|
|
31
|
-
const out = [];
|
|
32
|
-
walk(repoRoot, repoRoot, false, out);
|
|
33
|
-
return out.sort();
|
|
34
|
-
}
|
|
35
|
-
function isForeignTree(dir) {
|
|
36
|
-
return existsSync(join(dir, ".git")) || existsSync(join(dir, CONTEXT_PIN_FILENAME));
|
|
37
|
-
}
|
|
38
|
-
function walk(dir, repoRoot, insideOuterlayer, out) {
|
|
39
|
-
let entries;
|
|
40
|
-
try {
|
|
41
|
-
entries = readdirSync(dir, { withFileTypes: true });
|
|
42
|
-
} catch {
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
for (const entry of entries) {
|
|
46
|
-
if (entry.isSymbolicLink()) continue;
|
|
47
|
-
const full = join(dir, entry.name);
|
|
48
|
-
if (entry.isDirectory()) {
|
|
49
|
-
if (!insideOuterlayer && SKIP_DIRS.has(entry.name)) continue;
|
|
50
|
-
if (!insideOuterlayer && isForeignTree(full)) continue;
|
|
51
|
-
walk(full, repoRoot, insideOuterlayer || entry.name === ".outerlayer", out);
|
|
52
|
-
} else if (entry.isFile() && insideOuterlayer) {
|
|
53
|
-
out.push(toRepoRelative(repoRoot, full));
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
35
|
function buildEmitInput(repoRoot, targets, maintained, excluded = /* @__PURE__ */ new Set()) {
|
|
58
36
|
const bundled = new Map(maintained.map((f) => [f.path, f.content]));
|
|
59
37
|
const discovered = [.../* @__PURE__ */ new Set([...discoverOuterlayerPaths(repoRoot).filter((p) => !excluded.has(p)), ...bundled.keys()])].sort();
|
|
@@ -143,10 +121,10 @@ function walkAll(dir, repoRoot, out) {
|
|
|
143
121
|
}
|
|
144
122
|
}
|
|
145
123
|
}
|
|
146
|
-
function findOrphans(repoRoot, computedFiles, sourcePaths) {
|
|
124
|
+
function findOrphans(repoRoot, computedFiles, sourcePaths, ignore) {
|
|
147
125
|
const orphans = [];
|
|
148
126
|
for (const path of discoverAllFiles(repoRoot)) {
|
|
149
|
-
if (computedFiles.has(path)) continue;
|
|
127
|
+
if (computedFiles.has(path) || ignore?.(path) === true) continue;
|
|
150
128
|
let content;
|
|
151
129
|
try {
|
|
152
130
|
content = readFileSync(join(repoRoot, path), "utf8");
|
|
@@ -200,17 +178,20 @@ function runEmit(opts = {}) {
|
|
|
200
178
|
const cwd = opts.cwd ?? process.cwd();
|
|
201
179
|
if (!existsSync(cwd)) throw new EmitError(`no such directory: ${cwd}`);
|
|
202
180
|
const targets = resolveTargetsFromConfig(cwd);
|
|
203
|
-
const
|
|
181
|
+
const agentsMd = isAgentsMdLayout(cwd);
|
|
182
|
+
const ignoreOrphan = agentsMd ? (path) => HAND_OWNED_OUTPUT.test(path) : void 0;
|
|
183
|
+
const maintained = agentsMd ? [] : maintainedFilesForExistingSkills(cwd, loadMaintainedFiles());
|
|
184
|
+
const notice = noticeFor(cwd, targets);
|
|
204
185
|
const retired = retiredSkillPaths(cwd);
|
|
205
186
|
const built = buildEmitInput(cwd, targets, maintained, new Set(retired));
|
|
206
187
|
const emitted = emitTree(built.input);
|
|
207
188
|
const { result, kept } = withholdKept(cwd, emitted, opts.keep);
|
|
208
189
|
const hasErrors = result.errors.length > 0;
|
|
209
190
|
const outputs = new Set(emitted.files.map((f) => f.path));
|
|
210
|
-
if (opts.check) return runCheck(cwd, opts, targets, result, hasErrors, outputs, built.sourcePaths, maintained, kept, retired);
|
|
191
|
+
if (opts.check) return runCheck(cwd, opts, targets, result, hasErrors, outputs, built.sourcePaths, maintained, kept, retired, notice, ignoreOrphan);
|
|
211
192
|
const written = hasErrors ? { files: [], copies: [], maintained: [] } : writeOutputs(cwd, result, maintained);
|
|
212
193
|
const removed = hasErrors ? [] : removeRetiredSkills(cwd);
|
|
213
|
-
const orphaned = hasErrors ? [] : removeOrphans(cwd, findOrphans(cwd, outputs, built.sourcePaths));
|
|
194
|
+
const orphaned = hasErrors ? [] : removeOrphans(cwd, findOrphans(cwd, outputs, built.sourcePaths, ignoreOrphan));
|
|
214
195
|
const exitCode = hasErrors ? 1 : 0;
|
|
215
196
|
const output = opts.json ? JSON.stringify({
|
|
216
197
|
targets,
|
|
@@ -232,8 +213,11 @@ function runEmit(opts = {}) {
|
|
|
232
213
|
for (const w of result.warnings) process.stderr.write(` ${C.yellow}!${C.reset} ${w.path}: ${w.message}
|
|
233
214
|
`);
|
|
234
215
|
}
|
|
216
|
+
if (notice !== void 0 && !opts.json) process.stderr.write(`${C.dim}${notice}${C.reset}
|
|
217
|
+
`);
|
|
235
218
|
}
|
|
236
219
|
return {
|
|
220
|
+
...notice === void 0 ? {} : { notice },
|
|
237
221
|
targets,
|
|
238
222
|
files: written.files,
|
|
239
223
|
copies: written.copies,
|
|
@@ -247,7 +231,7 @@ function runEmit(opts = {}) {
|
|
|
247
231
|
exitCode
|
|
248
232
|
};
|
|
249
233
|
}
|
|
250
|
-
function runCheck(cwd, opts, targets, result, hasErrors, outputs, sourcePaths, maintained, kept, retired) {
|
|
234
|
+
function runCheck(cwd, opts, targets, result, hasErrors, outputs, sourcePaths, maintained, kept, retired, notice, ignoreOrphan) {
|
|
251
235
|
const drift = [];
|
|
252
236
|
if (!hasErrors) {
|
|
253
237
|
for (const path of retired) drift.push({ kind: "retired", path });
|
|
@@ -264,7 +248,7 @@ function runCheck(cwd, opts, targets, result, hasErrors, outputs, sourcePaths, m
|
|
|
264
248
|
if (d) drift.push(d);
|
|
265
249
|
}
|
|
266
250
|
const retiredPaths = new Set(retired);
|
|
267
|
-
drift.push(...findOrphans(cwd, outputs, sourcePaths).filter((d) => !retiredPaths.has(d.path)));
|
|
251
|
+
drift.push(...findOrphans(cwd, outputs, sourcePaths, ignoreOrphan).filter((d) => !retiredPaths.has(d.path)));
|
|
268
252
|
drift.sort((a, b) => a.path.localeCompare(b.path) || a.kind.localeCompare(b.kind));
|
|
269
253
|
}
|
|
270
254
|
const exitCode = hasErrors || drift.length > 0 ? 1 : 0;
|
|
@@ -279,8 +263,44 @@ function runCheck(cwd, opts, targets, result, hasErrors, outputs, sourcePaths, m
|
|
|
279
263
|
for (const w of result.warnings) process.stderr.write(` ${C.yellow}!${C.reset} ${w.path}: ${w.message}
|
|
280
264
|
`);
|
|
281
265
|
}
|
|
266
|
+
if (notice !== void 0 && !opts.json) process.stderr.write(`${C.dim}${notice}${C.reset}
|
|
267
|
+
`);
|
|
268
|
+
}
|
|
269
|
+
return { ...notice === void 0 ? {} : { notice }, targets, files: [], copies: [], maintained: [], kept, retired: [], orphaned: [], warnings: result.warnings, errors: result.errors, drift, output, exitCode };
|
|
270
|
+
}
|
|
271
|
+
var REPLACED_OUTPUT = /^(?:(?:.*\/)?(?:CLAUDE|AGENTS)\.md|(?:.*\/)?\.(?:claude|agents)\/skills\/.+)$/;
|
|
272
|
+
function inspectReplacedOutputs(repoRoot) {
|
|
273
|
+
let configured = [];
|
|
274
|
+
try {
|
|
275
|
+
configured = resolveTargetsFromConfig(repoRoot);
|
|
276
|
+
} catch {
|
|
277
|
+
}
|
|
278
|
+
const targets = [.../* @__PURE__ */ new Set([...configured, "claude-code", "codex"])];
|
|
279
|
+
const maintained = maintainedFilesForExistingSkills(repoRoot, loadMaintainedFiles());
|
|
280
|
+
const maintainedPaths = new Set(maintained.map((f) => f.path));
|
|
281
|
+
const built = buildEmitInput(repoRoot, targets, maintained, new Set(retiredSkillPaths(repoRoot)));
|
|
282
|
+
const emitted = emitTree(built.input);
|
|
283
|
+
const generated = [];
|
|
284
|
+
const edited = [];
|
|
285
|
+
const replacedDiffering = [];
|
|
286
|
+
const classify = (path, same) => {
|
|
287
|
+
(same ? generated : edited).push(path);
|
|
288
|
+
};
|
|
289
|
+
for (const file of emitted.files) {
|
|
290
|
+
if (!REPLACED_OUTPUT.test(file.path) || !existsSync(join(repoRoot, file.path))) continue;
|
|
291
|
+
const disk = readFileSync(join(repoRoot, file.path), "utf8");
|
|
292
|
+
const source = generatedHeaderSource(disk);
|
|
293
|
+
const stale = source !== null && maintainedPaths.has(source);
|
|
294
|
+
const same = stale ? true : disk === file.content;
|
|
295
|
+
if (stale && disk !== file.content) replacedDiffering.push(file.path);
|
|
296
|
+
classify(file.path, same);
|
|
297
|
+
}
|
|
298
|
+
for (const copy of emitted.copies) {
|
|
299
|
+
if (!REPLACED_OUTPUT.test(copy.toPath) || !existsSync(join(repoRoot, copy.toPath))) continue;
|
|
300
|
+
const source = join(repoRoot, copy.fromSourcePath);
|
|
301
|
+
classify(copy.toPath, existsSync(source) && readFileSync(join(repoRoot, copy.toPath)).equals(readFileSync(source)));
|
|
282
302
|
}
|
|
283
|
-
return {
|
|
303
|
+
return { generated: generated.sort(), edited: edited.sort(), replacedDiffering: replacedDiffering.sort() };
|
|
284
304
|
}
|
|
285
305
|
|
|
286
|
-
export { EmitError, runEmit };
|
|
306
|
+
export { EMIT_NOT_NEEDED_NOTICE, EmitError, inspectReplacedOutputs, runEmit };
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { RELAY_PORT, BUILD_HOME } from './chunk-URWYRAIC.js';
|
|
4
|
+
import { createServer, connect } from 'net';
|
|
5
|
+
|
|
6
|
+
createRequire(import.meta.url);
|
|
7
|
+
var BRIDGE_ADDRESS = "172.17.0.1";
|
|
8
|
+
var BRIDGE_CIDR = "172.17.0.1/16";
|
|
9
|
+
var TUNNEL_PORT = RELAY_PORT;
|
|
10
|
+
var CONTAINER_PROXY = `http://${BRIDGE_ADDRESS}:${TUNNEL_PORT}`;
|
|
11
|
+
var CONTAINER_NO_PROXY = ["localhost", "127.0.0.1", "::1", "10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"];
|
|
12
|
+
function dockerClientConfig() {
|
|
13
|
+
const proxies = { default: { httpProxy: CONTAINER_PROXY, httpsProxy: CONTAINER_PROXY, noProxy: CONTAINER_NO_PROXY.join(",") } };
|
|
14
|
+
return `${JSON.stringify({ proxies }, null, 2)}
|
|
15
|
+
`;
|
|
16
|
+
}
|
|
17
|
+
async function writeDockerClientConfig(run, agentUser) {
|
|
18
|
+
const dir = `${BUILD_HOME}/.docker`;
|
|
19
|
+
const script = [
|
|
20
|
+
"set -e",
|
|
21
|
+
"umask 077",
|
|
22
|
+
`mkdir -p ${dir}`,
|
|
23
|
+
`cat > ${dir}/config.json.partial`,
|
|
24
|
+
`mv ${dir}/config.json.partial ${dir}/config.json`,
|
|
25
|
+
`chown "$(id -u "$1"):$(id -g "$1")" ${dir} ${dir}/config.json`,
|
|
26
|
+
`chmod 700 ${dir}`,
|
|
27
|
+
`chmod 600 ${dir}/config.json`
|
|
28
|
+
].join("\n");
|
|
29
|
+
const result = await run(["/bin/sh", "-c", script, "sh", agentUser], dockerClientConfig());
|
|
30
|
+
if (result.status === 0) return void 0;
|
|
31
|
+
return `the Docker client configuration could not be written in the microVM (exit ${result.status}): ${result.stderr.trim().split("\n")[0]}`;
|
|
32
|
+
}
|
|
33
|
+
function parseAddress(text) {
|
|
34
|
+
const match = /^(.+):(\d+)$/.exec(text);
|
|
35
|
+
const port = Number(match?.[2]);
|
|
36
|
+
if (match === null || port > 65535) throw new Error(`${JSON.stringify(text)} is not host:port`);
|
|
37
|
+
return { host: match[1], port };
|
|
38
|
+
}
|
|
39
|
+
async function startBridgeForward(opts) {
|
|
40
|
+
const listen = parseAddress(opts.listen);
|
|
41
|
+
const to = parseAddress(opts.to);
|
|
42
|
+
const open = /* @__PURE__ */ new Set();
|
|
43
|
+
const server = createServer({ allowHalfOpen: true }, (client) => {
|
|
44
|
+
const upstream = connect({ host: to.host, port: to.port, allowHalfOpen: true });
|
|
45
|
+
open.add(client);
|
|
46
|
+
client.on("error", () => void 0);
|
|
47
|
+
upstream.on("error", () => void 0);
|
|
48
|
+
client.on("close", () => {
|
|
49
|
+
open.delete(client);
|
|
50
|
+
upstream.destroy();
|
|
51
|
+
});
|
|
52
|
+
upstream.on("close", () => client.destroy());
|
|
53
|
+
client.pipe(upstream);
|
|
54
|
+
upstream.pipe(client);
|
|
55
|
+
});
|
|
56
|
+
await new Promise((resolve, reject) => {
|
|
57
|
+
server.once("error", reject);
|
|
58
|
+
server.listen(listen.port, listen.host, () => {
|
|
59
|
+
resolve();
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
server.on("error", (error) => process.stderr.write(`outerlayer: the bridge forwarder hit an error: ${error.message}
|
|
63
|
+
`));
|
|
64
|
+
return {
|
|
65
|
+
port: server.address().port,
|
|
66
|
+
close: () => new Promise((resolve) => {
|
|
67
|
+
for (const socket of open) socket.destroy();
|
|
68
|
+
server.close(() => resolve());
|
|
69
|
+
})
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export { BRIDGE_ADDRESS, BRIDGE_CIDR, CONTAINER_NO_PROXY, CONTAINER_PROXY, TUNNEL_PORT, dockerClientConfig, startBridgeForward, writeDockerClientConfig };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { LiveUploader } from './chunk-
|
|
4
|
-
import { spoolDir } from './chunk-
|
|
5
|
-
import { CaptureDaemon } from './chunk-
|
|
3
|
+
import { LiveUploader } from './chunk-DJYOCD65.js';
|
|
4
|
+
import { spoolDir } from './chunk-XOEV4FVK.js';
|
|
5
|
+
import { CaptureDaemon } from './chunk-CBCKD6DO.js';
|
|
6
6
|
import { parseWorkItemEnv } from './chunk-T2Q7ISPE.js';
|
|
7
7
|
import { homeFromEnv } from './chunk-VNVZDWO3.js';
|
|
8
8
|
import { mkdirSync, writeFileSync, rmSync } from 'fs';
|
|
@@ -1,29 +1,30 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
+
import { POLICY_CONTENT, VALIDATOR_FILES, VALIDATORS_DIR, POLICY_PATH } from './chunk-VJBFQP3H.js';
|
|
3
4
|
import { findGitDirs } from './chunk-BJ3KTMDH.js';
|
|
4
|
-
import { mcpTargetPath, INIT_STDIO_ENTRY, INIT_DOCS_ENTRY, DOCS_MCP_SERVER_NAME } from './chunk-
|
|
5
|
-
import {
|
|
6
|
-
import { resolvePackRoot, skillDir, namesCore, loadTemplateFiles, TEMPLATE_SKILLS } from './chunk-
|
|
5
|
+
import { mcpTargetPath, INIT_STDIO_ENTRY, INIT_DOCS_ENTRY, DOCS_MCP_SERVER_NAME } from './chunk-YVZJ6GKF.js';
|
|
6
|
+
import { skillsBaseFor, isAgentsMdLayout } from './chunk-JKNYTNYD.js';
|
|
7
|
+
import { resolvePackRoot, OUTERLAYER_SKILLS_BASE, skillDir, namesCore, loadTemplateFiles, rewriteSkillPaths, restoreSkillPaths, TEMPLATE_SKILLS } from './chunk-HBISTTG3.js';
|
|
7
8
|
import { cliInvocation } from './chunk-CRB3POP4.js';
|
|
8
|
-
import { hasSymlinkComponent } from './chunk-
|
|
9
|
+
import { hasSymlinkComponent } from './chunk-VWFOKRYS.js';
|
|
9
10
|
import { cloneIsGoverned } from './chunk-YQR6E6OV.js';
|
|
10
|
-
import { emitTree, ALL_TARGET_IDS, classifyTree, splitRawFile } from './chunk-
|
|
11
|
+
import { emitTree, ALL_TARGET_IDS, classifyTree, splitRawFile } from './chunk-RKOTJQVG.js';
|
|
11
12
|
import { createHash } from 'crypto';
|
|
12
|
-
import { existsSync, readFileSync } from 'fs';
|
|
13
|
+
import { existsSync, readFileSync, realpathSync } from 'fs';
|
|
13
14
|
import { join, dirname } from 'path';
|
|
14
15
|
|
|
15
16
|
createRequire(import.meta.url);
|
|
16
17
|
var SHIPPED_MANIFEST = "shipped.json";
|
|
17
|
-
function currentStarterFiles(packRoot = resolvePackRoot(), policy = POLICY_CONTENT) {
|
|
18
|
-
const templates = loadTemplateFiles(packRoot).map((f) => ({
|
|
18
|
+
function currentStarterFiles(packRoot = resolvePackRoot(), policy = POLICY_CONTENT, base = OUTERLAYER_SKILLS_BASE) {
|
|
19
|
+
const templates = loadTemplateFiles(packRoot, void 0, base).map((f) => ({
|
|
19
20
|
path: f.path,
|
|
20
21
|
content: f.content,
|
|
21
22
|
skill: f.skill,
|
|
22
|
-
source: join(packRoot, "template", f.skill, f.path.slice(skillDir(f.skill).length + 1))
|
|
23
|
+
source: join(packRoot, "template", f.skill, f.path.slice(skillDir(f.skill, base).length + 1))
|
|
23
24
|
}));
|
|
24
25
|
const validators = VALIDATOR_FILES.map(({ name }) => {
|
|
25
26
|
const source = join(packRoot, "validators", name);
|
|
26
|
-
return { path: `${VALIDATORS_DIR}/${name}`, content: readFileSync(source, "utf8"), source };
|
|
27
|
+
return { path: `${VALIDATORS_DIR}/${name}`, content: rewriteSkillPaths(readFileSync(source, "utf8"), base), source };
|
|
27
28
|
});
|
|
28
29
|
return [...templates, ...validators, { path: POLICY_PATH, content: policy }];
|
|
29
30
|
}
|
|
@@ -66,12 +67,17 @@ function canonical(value) {
|
|
|
66
67
|
}
|
|
67
68
|
return JSON.stringify(value);
|
|
68
69
|
}
|
|
69
|
-
function
|
|
70
|
+
function shippedPath(path, base) {
|
|
71
|
+
return path.startsWith(`${base}/`) ? `${OUTERLAYER_SKILLS_BASE}/${path.slice(base.length + 1)}` : path;
|
|
72
|
+
}
|
|
73
|
+
function fileState(root, file, manifest, base) {
|
|
70
74
|
const abs = join(root, file.path);
|
|
71
75
|
if (!existsSync(abs)) return "missing";
|
|
72
|
-
const
|
|
73
|
-
if (
|
|
74
|
-
|
|
76
|
+
const disk = readFileSync(abs, "utf8");
|
|
77
|
+
if (contentHash(disk) === contentHash(file.content)) return "current";
|
|
78
|
+
const hash = contentHash(restoreSkillPaths(disk, base));
|
|
79
|
+
if (hash === contentHash(restoreSkillPaths(file.content, base))) return "outdated";
|
|
80
|
+
if (manifest.ok && manifest.files.get(shippedPath(file.path, base))?.has(hash) === true) return "outdated";
|
|
75
81
|
return "edited";
|
|
76
82
|
}
|
|
77
83
|
function mcpItems(root) {
|
|
@@ -98,17 +104,18 @@ function mcpItems(root) {
|
|
|
98
104
|
return { ...base, state: "edited" };
|
|
99
105
|
});
|
|
100
106
|
}
|
|
101
|
-
function retiredFiles(root, shipped, manifest) {
|
|
107
|
+
function retiredFiles(root, shipped, manifest, base) {
|
|
102
108
|
if (!manifest.ok) return [];
|
|
103
|
-
const current = new Set(shipped.map((f) => f.path));
|
|
109
|
+
const current = new Set(shipped.map((f) => shippedPath(f.path, base)));
|
|
104
110
|
const prefixes = TEMPLATE_SKILLS.map((skill) => `${skillDir(skill)}/`);
|
|
105
111
|
const retired = [];
|
|
106
|
-
for (const [
|
|
107
|
-
if (current.has(
|
|
112
|
+
for (const [known, hashes] of manifest.files) {
|
|
113
|
+
if (current.has(known) || !prefixes.some((prefix) => known.startsWith(prefix))) continue;
|
|
114
|
+
const path = base === OUTERLAYER_SKILLS_BASE ? known : `${base}/${known.slice(OUTERLAYER_SKILLS_BASE.length + 1)}`;
|
|
108
115
|
const abs = join(root, path);
|
|
109
116
|
if (!existsSync(abs) || hasSymlinkComponent(root, path)) continue;
|
|
110
117
|
try {
|
|
111
|
-
retired.push({ path, state: hashes.has(contentHash(readFileSync(abs, "utf8"))) ? "unedited" : "edited" });
|
|
118
|
+
retired.push({ path, state: hashes.has(contentHash(restoreSkillPaths(readFileSync(abs, "utf8"), base))) ? "unedited" : "edited" });
|
|
112
119
|
} catch {
|
|
113
120
|
}
|
|
114
121
|
}
|
|
@@ -116,13 +123,14 @@ function retiredFiles(root, shipped, manifest) {
|
|
|
116
123
|
}
|
|
117
124
|
function inspectStarterFiles(root, opts = {}) {
|
|
118
125
|
const packRoot = opts.packRoot ?? resolvePackRoot();
|
|
126
|
+
const base = opts.base ?? skillsBaseFor(root);
|
|
119
127
|
const manifest = readShippedManifest(packRoot);
|
|
120
|
-
const shipped = currentStarterFiles(packRoot);
|
|
121
|
-
const files = shipped.map((file) => ({ kind: "file", path: file.path, state: fileState(root, file, manifest), file }));
|
|
122
|
-
const buildEdited = files.some((f) => f.path === `${skillDir("build")}/SKILL.md` && f.state === "edited");
|
|
123
|
-
const buildPrefix = `${skillDir("build")}/`;
|
|
124
|
-
const retired = retiredFiles(root, shipped, manifest).filter((f) => !(buildEdited && f.path.startsWith(buildPrefix)));
|
|
125
|
-
return { items: [...files, ...mcpItems(root)], retired, manifest: manifest.ok ? "ok" : manifest.problem };
|
|
128
|
+
const shipped = currentStarterFiles(packRoot, void 0, base);
|
|
129
|
+
const files = shipped.map((file) => ({ kind: "file", path: file.path, state: fileState(root, file, manifest, base), file }));
|
|
130
|
+
const buildEdited = files.some((f) => f.path === `${skillDir("build", base)}/SKILL.md` && f.state === "edited");
|
|
131
|
+
const buildPrefix = `${skillDir("build", base)}/`;
|
|
132
|
+
const retired = retiredFiles(root, shipped, manifest, base).filter((f) => !(buildEdited && f.path.startsWith(buildPrefix)));
|
|
133
|
+
return { base, items: [...files, ...mcpItems(root)], retired, manifest: manifest.ok ? "ok" : manifest.problem };
|
|
126
134
|
}
|
|
127
135
|
function itemLabel(item) {
|
|
128
136
|
return item.kind === "file" ? item.path : `${item.path} "${item.server}" server`;
|
|
@@ -132,7 +140,7 @@ function contextIsGoverned(gitCommonDir) {
|
|
|
132
140
|
}
|
|
133
141
|
var NAME = "Starter files";
|
|
134
142
|
var UPDATE = `${cliInvocation()} init --update`;
|
|
135
|
-
function shownPaths(items, all) {
|
|
143
|
+
function shownPaths(items, all, base) {
|
|
136
144
|
const shown = [];
|
|
137
145
|
const whole = /* @__PURE__ */ new Set();
|
|
138
146
|
for (const item of items) {
|
|
@@ -140,7 +148,7 @@ function shownPaths(items, all) {
|
|
|
140
148
|
if (skill !== void 0) {
|
|
141
149
|
const ofSkill = all.filter((i) => i.kind === "file" && i.file.skill === skill);
|
|
142
150
|
if (ofSkill.every((i) => items.includes(i))) {
|
|
143
|
-
if (!whole.has(skill)) shown.push(`${skillDir(skill)}/`);
|
|
151
|
+
if (!whole.has(skill)) shown.push(`${skillDir(skill, base)}/`);
|
|
144
152
|
whole.add(skill);
|
|
145
153
|
continue;
|
|
146
154
|
}
|
|
@@ -164,8 +172,8 @@ function checkStarterFiles(cwd, opts = {}) {
|
|
|
164
172
|
const retired = report.retired.filter((f) => f.state === "unedited");
|
|
165
173
|
const parts = [];
|
|
166
174
|
if (current.length > 0) parts.push(`${current.length} current`);
|
|
167
|
-
if (outdated.length > 0) parts.push(`outdated and unedited: ${shownPaths(outdated, report.items).join(", ")}`);
|
|
168
|
-
if (missing.length > 0) parts.push(`missing: ${shownPaths(missing, report.items).join(", ")}`);
|
|
175
|
+
if (outdated.length > 0) parts.push(`outdated and unedited: ${shownPaths(outdated, report.items, report.base).join(", ")}`);
|
|
176
|
+
if (missing.length > 0) parts.push(`missing: ${shownPaths(missing, report.items, report.base).join(", ")}`);
|
|
169
177
|
if (retired.length > 0) parts.push(`no longer shipped, unedited: ${retired.map((f) => f.path).join(", ")}`);
|
|
170
178
|
if (edited.length > 0) parts.push(`edited by you, left as they are: ${edited.map(itemLabel).join(", ")}`);
|
|
171
179
|
if (unreadable.length > 0) parts.push(`${unreadable[0].path} is not valid JSON, so its servers were not read`);
|
|
@@ -244,15 +252,25 @@ ${shortBuild()}`
|
|
|
244
252
|
fix: `Rename each heading to a phase: ${BUILD_PHASES.join(", ")}.`
|
|
245
253
|
});
|
|
246
254
|
}
|
|
247
|
-
const
|
|
248
|
-
|
|
249
|
-
)
|
|
255
|
+
const agentsMd = isAgentsMdLayout(repoRoot);
|
|
256
|
+
const seen = /* @__PURE__ */ new Set();
|
|
257
|
+
const lacking = folders.filter((folder) => {
|
|
258
|
+
if (!namesCore(read(join(repoRoot, folder, "build", "SKILL.md")) ?? "") || existsSync(join(repoRoot, folder, "outerlayer-build", "SKILL.md"))) return false;
|
|
259
|
+
let key = folder;
|
|
260
|
+
try {
|
|
261
|
+
key = realpathSync(join(repoRoot, folder));
|
|
262
|
+
} catch {
|
|
263
|
+
}
|
|
264
|
+
if (seen.has(key)) return false;
|
|
265
|
+
seen.add(key);
|
|
266
|
+
return true;
|
|
267
|
+
});
|
|
250
268
|
if (lacking.length > 0) {
|
|
251
269
|
checks.push({
|
|
252
270
|
name: NAME2,
|
|
253
271
|
status: "warn",
|
|
254
272
|
detail: `${lacking.join(", ")} holds build with no outerlayer-build beside it`,
|
|
255
|
-
fix: `Run \`${cliInvocation()} context emit\` to write outerlayer-build, then commit.`
|
|
273
|
+
fix: `Run \`${cliInvocation()} ${agentsMd ? "init --update" : "context emit"}\` to write outerlayer-build, then commit.`
|
|
256
274
|
});
|
|
257
275
|
}
|
|
258
276
|
return checks;
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { removeRetiredSkills } from './chunk-
|
|
4
|
-
import { defaultFetch } from './chunk-
|
|
5
|
-
import { resolveGatewayCredentials } from './chunk-NTRCK4NH.js';
|
|
3
|
+
import { removeRetiredSkills } from './chunk-MQ743JX3.js';
|
|
4
|
+
import { defaultFetch, resolveGatewayCredentials } from './chunk-QS43O4DR.js';
|
|
6
5
|
import { appendContextProvenance } from './chunk-ZJSNLVCE.js';
|
|
7
|
-
import { loadMaintainedFiles, writeMaintainedFiles } from './chunk-
|
|
6
|
+
import { loadMaintainedFiles, writeMaintainedFiles } from './chunk-HBISTTG3.js';
|
|
8
7
|
import { cliInvocation } from './chunk-CRB3POP4.js';
|
|
9
8
|
import { writeDegraded, writeSourceCache, SOURCE_CACHE_TTL_RETRY_MS, writeContextManifest, SOURCE_CACHE_TTL_SUCCESS_MS, readSourceCache, isSourceCacheFresh, clearDegraded } from './chunk-YQR6E6OV.js';
|
|
10
|
-
import { normalizeRepoName, parseOuterlayerConfig, classifyTree, emitTree } from './chunk-
|
|
9
|
+
import { normalizeRepoName, parseOuterlayerConfig, classifyTree, emitTree } from './chunk-RKOTJQVG.js';
|
|
11
10
|
import { homeFromEnv } from './chunk-VNVZDWO3.js';
|
|
12
11
|
import { withTokenHeader } from './chunk-URWYRAIC.js';
|
|
13
12
|
import { execFileSync } from 'child_process';
|
|
@@ -429,7 +429,7 @@ async function handleWorkLaunch(sessionId, home, env, spawnImpl = spawnDetached,
|
|
|
429
429
|
}
|
|
430
430
|
async function missingRenewalHookContext(home, cwd) {
|
|
431
431
|
try {
|
|
432
|
-
const { settingsPath, readSettings, isOurHookCommand } = await import('./settings-
|
|
432
|
+
const { settingsPath, readSettings, isOurHookCommand } = await import('./settings-AKYEOCC2.js');
|
|
433
433
|
const userSettings = readSettings(settingsPath("user", { home }));
|
|
434
434
|
const projectSettings = readSettings(settingsPath("project", { cwd }));
|
|
435
435
|
if (userSettings === null && projectSettings === null) return void 0;
|
|
@@ -624,11 +624,11 @@ async function missingControlPlane(cwd, sessionId, home, env) {
|
|
|
624
624
|
const dirs = findGitDirs(cwd);
|
|
625
625
|
if (dirs === void 0) return void 0;
|
|
626
626
|
if (existsSync(join(dirs.gitCommonDir, "outerlayer", "materialized.json")) || hasExcludeBlock(dirs.gitCommonDir)) {
|
|
627
|
-
const { cleanupEarlierCopies } = await import('./context-cleanup-
|
|
627
|
+
const { cleanupEarlierCopies } = await import('./context-cleanup-LTH77FC3.js');
|
|
628
628
|
cleanupEarlierCopies(dirs);
|
|
629
629
|
}
|
|
630
630
|
if (!contextPossiblyGoverned(cwd, home)) return void 0;
|
|
631
|
-
const { governanceOf } = await import('./control-plane-launch-
|
|
631
|
+
const { governanceOf } = await import('./control-plane-launch-SEYCOZFH.js');
|
|
632
632
|
if (await governanceOf({ cwd, env, home }) !== "governed") return void 0;
|
|
633
633
|
recordMissingContext(dirs, sessionId, home);
|
|
634
634
|
const launcher = `${cliInvocation()} claude`;
|