@outerlayer/cli 0.18.0 → 0.19.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 +25 -0
- package/README.md +21 -2
- package/dist/{agent-setup-RBTEACYU.js → agent-setup-TPR4BBFV.js} +15 -16
- package/dist/{artifact-link-cmd-AVM2EKTV.js → artifact-link-cmd-W7XF5BFB.js} +2 -2
- package/dist/build-info.json +1 -1
- package/dist/{builder-DUI2ZH2H.js → builder-C4QNTYMS.js} +3 -3
- package/dist/{check-5C4YDZYV.js → check-UWQAL2MN.js} +44 -43
- package/dist/{chunk-S26M3YBJ.js → chunk-3UZTIRLF.js} +1 -1
- package/dist/{chunk-W5VPCONO.js → chunk-452TM7J4.js} +33 -227
- package/dist/{chunk-UYOYTKE2.js → chunk-5GHGAF6P.js} +3 -3
- package/dist/{chunk-QQM2UJ6T.js → chunk-5MYFOW5V.js} +182 -28
- package/dist/{chunk-Y5GE76XC.js → chunk-5TN7GLYX.js} +33 -81
- package/dist/{chunk-GOBOJMOJ.js → chunk-6D7GT22T.js} +4 -4
- package/dist/{chunk-3OFZM4X6.js → chunk-6U3MV7TZ.js} +151 -20
- package/dist/{chunk-F4XSVQJ4.js → chunk-6X4SQ5MY.js} +2 -2
- package/dist/{chunk-Y5MXET4M.js → chunk-7KSSBQTS.js} +11 -10
- package/dist/{chunk-JF42URPU.js → chunk-7SJPQWBM.js} +33 -9
- package/dist/{chunk-N3CUDFCW.js → chunk-7VUK5RFS.js} +15 -2
- package/dist/{chunk-SWCTGCSC.js → chunk-7YP7T6GV.js} +1 -1
- package/dist/{chunk-KDVIU23F.js → chunk-BWSUPRDK.js} +1 -1
- package/dist/{chunk-S76AYB4M.js → chunk-CG36IONK.js} +5 -5
- package/dist/chunk-CJJDJ7AT.js +56 -0
- package/dist/{chunk-FUB7LRUE.js → chunk-DADWEUH3.js} +5 -5
- package/dist/{chunk-RAZTWYZN.js → chunk-DJ3ZUSC3.js} +7 -8
- package/dist/{chunk-MQJSXHV7.js → chunk-G3IJ3N6F.js} +5 -3
- package/dist/{chunk-KK4VBOH6.js → chunk-HPJNLETG.js} +10 -11
- package/dist/{chunk-IP7BIBXJ.js → chunk-IF2OSI5T.js} +35 -1
- package/dist/{chunk-T4Y6SCG3.js → chunk-IXYZUUYQ.js} +2 -2
- package/dist/chunk-KYS3TQAG.js +296 -0
- package/dist/chunk-LLM3I5YU.js +89 -0
- package/dist/{chunk-B3UKB46N.js → chunk-LRG3ZMZD.js} +4 -5
- package/dist/{chunk-ULSIJGLS.js → chunk-NFIR3GEE.js} +56 -14
- package/dist/{chunk-MNTSH4CL.js → chunk-NNLA7LLQ.js} +1 -1
- package/dist/{chunk-WGAUY5LE.js → chunk-QEFKA2QD.js} +1 -1
- package/dist/{chunk-BMYGAGBJ.js → chunk-QNLX477Q.js} +155 -23
- package/dist/chunk-TUSYOL2O.js +113 -0
- package/dist/{chunk-ESC6UR76.js → chunk-TWF3RICI.js} +6 -6
- package/dist/{chunk-NL4XPC7W.js → chunk-UVG35MWF.js} +1 -1
- package/dist/{chunk-L2USZT6T.js → chunk-VMJPFQNE.js} +1 -1
- package/dist/chunk-VRRGENS4.js +144 -0
- package/dist/{chunk-X5N6KC6V.js → chunk-WFSUUUAN.js} +2 -3
- package/dist/{chunk-6CHIYEZZ.js → chunk-XSZD4AZ6.js} +9 -83
- package/dist/{chunk-LXAY4A2G.js → chunk-YQR6E6OV.js} +34 -49
- package/dist/{chunk-47TTLEDX.js → chunk-ZHAUSEEN.js} +35 -13
- package/dist/{claude-launcher-YVXI76NX.js → claude-launcher-FPPHZPMR.js} +20 -7
- package/dist/{cli-C77H54BV.js → cli-HROW5T7X.js} +203 -228
- package/dist/{command-H5CILO4S.js → command-OEAV7BVX.js} +29 -30
- package/dist/{config-FXDG4NPJ.js → config-CLSGABD5.js} +2 -2
- package/dist/{connect-cmd-ZW5FV3ZW.js → connect-cmd-UNYKGDAL.js} +7 -7
- package/dist/context-cleanup-HSVYDGMI.js +9 -0
- package/dist/control-plane-launch-NYVDJESK.js +216 -0
- package/dist/{dist-QTX4RSCL.js → dist-WO7NOJNG.js} +2 -2
- package/dist/{docker-RC3PRX3Q.js → docker-BFU3AQGY.js} +4 -4
- package/dist/{doctor-2NQQML6P.js → doctor-23BBJWBX.js} +32 -33
- package/dist/{emit-artifact-cmd-7MP63KXU.js → emit-artifact-cmd-O6SCM7TV.js} +17 -17
- package/dist/{emit-cmd-PPN4QQF2.js → emit-cmd-7SP3I6UZ.js} +6 -6
- package/dist/{emit-criteria-cmd-3RXPDLNK.js → emit-criteria-cmd-LQNERZRV.js} +11 -12
- package/dist/{emit-finding-cmd-OL7JB6H3.js → emit-finding-cmd-AJPKHIOV.js} +12 -13
- package/dist/{emit-result-cmd-UZVMOCF4.js → emit-result-cmd-RUICOKWQ.js} +17 -17
- package/dist/emit-step-cmd-347XNGPQ.js +26 -0
- package/dist/{governing-source-BUU4IABS.js → governing-source-V5EEGPTA.js} +21 -22
- package/dist/{hook-fast-W5MKHMJT.js → hook-fast-YAZG5MDX.js} +3 -3
- package/dist/{import-capture-cmd-ZO6KGHI2.js → import-capture-cmd-KKFFOGWP.js} +4 -4
- package/dist/{import-ruler-cmd-KJMWL5V6.js → import-ruler-cmd-5P6JOXQN.js} +2 -2
- package/dist/index.js +4 -4
- package/dist/{init-WNXXYMO7.js → init-LWHDMZQG.js} +30 -31
- package/dist/{init-VWXIZEAN.js → init-MOINY2DD.js} +30 -31
- package/dist/{init-cmd-WS6TIRYT.js → init-cmd-HSMRID6A.js} +67 -26
- package/dist/{init-update-E3J6TVIN.js → init-update-LWX5MPPR.js} +21 -22
- package/dist/{install-CBWIEF3R.js → install-4SEFIIW2.js} +3 -3
- package/dist/{login-browser-O63QZN7D.js → login-browser-DX35MARZ.js} +2 -2
- package/dist/{loop-UGI2BJOT.js → loop-SYYPVFYW.js} +44 -43
- package/dist/{machine-JOW4RNZ7.js → machine-6X63G2KH.js} +26 -27
- package/dist/{mcp-serve-cmd-DOTY5FKY.js → mcp-serve-cmd-N3UTY6EE.js} +5 -5
- package/dist/{runner-env-4NB2GA7O.js → runner-env-FRZFFHDF.js} +4 -4
- package/dist/{runner-key-TC3NFWFV.js → runner-key-276SJU5R.js} +30 -31
- package/dist/{session-sender-NNVPSPY7.js → session-sender-GGIY5OAX.js} +19 -15
- package/dist/shell-function-NRD4KVUK.js +6 -0
- package/dist/{spec-cmd-OWVTBB4J.js → spec-cmd-SIZBRN7D.js} +12 -13
- package/dist/{starter-pack-OPWUDOWX.js → starter-pack-6LQVLBIA.js} +5 -5
- package/dist/{status-TKCLLKFG.js → status-NAK6DYSF.js} +33 -32
- package/dist/{sync-cmd-Q6VYNPWG.js → sync-cmd-G7GF4UTW.js} +18 -14
- package/dist/{watch-ARAGADTF.js → watch-EVM5GSMP.js} +18 -14
- package/dist/{work-claim-cmd-34FERLYX.js → work-claim-cmd-3J3QW56U.js} +16 -17
- package/dist/{work-cmd-7S5B2H2P.js → work-cmd-5EPPD33Y.js} +12 -13
- package/dist/{work-comment-cmd-SZJSPM5S.js → work-comment-cmd-2ACOZQAE.js} +12 -13
- package/dist/work-logs-cmd-QDD2NMJL.js +60 -0
- package/dist/{work-open-pr-cmd-RPXKCBWS.js → work-open-pr-cmd-XNCEI4ZM.js} +13 -14
- package/dist/{work-pr-cmd-5LGANL32.js → work-pr-cmd-H4OQR26N.js} +12 -13
- package/package.json +2 -2
- package/skill-pack/maintained/outerlayer-cli/SKILL.md +9 -2
- package/skill-pack/maintained/outerlayer-cli/references/find-out-why-a-build-ended.md +76 -0
- package/skill-pack/shipped.json +1 -0
- package/skill-pack/template/build/references/release.md +3 -1
- package/dist/chunk-WBT5X3NH.js +0 -40
- package/dist/chunk-XCCLFVXM.js +0 -401
- package/dist/context-adopt-O5OFXMKI.js +0 -109
- package/dist/context-materialize-Y5IJ4MQT.js +0 -23
- package/dist/{chunk-NACDBXUG.js → chunk-BM63HB2M.js} +1 -1
- package/dist/{chunk-ZRL6HKBY.js → chunk-FVMYKL6L.js} +1 -1
- package/dist/{chunk-52NC2FIU.js → chunk-NTRCK4NH.js} +1 -1
- package/dist/{chunk-XGP3VYOG.js → chunk-P53VEAOF.js} +1 -1
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { WorkCommandError, postJson } from './chunk-
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { signingFetchFor } from './chunk-
|
|
7
|
-
import {
|
|
3
|
+
import { WorkCommandError, postJson } from './chunk-HPJNLETG.js';
|
|
4
|
+
import { composeDelivery } from './chunk-LLM3I5YU.js';
|
|
5
|
+
import { defaultGitRunner, materializeContext, isStagingWriteFault, lookupGoverningSource } from './chunk-452TM7J4.js';
|
|
6
|
+
import { signingFetchFor } from './chunk-FVMYKL6L.js';
|
|
7
|
+
import { SHIM_SCRIPT } from './chunk-G2YNJIGF.js';
|
|
8
|
+
import { readDegraded, readContextManifest, readSourceCache } from './chunk-YQR6E6OV.js';
|
|
8
9
|
import { signerFor } from './chunk-M2ZWWTWZ.js';
|
|
9
10
|
import { SHIM_DIR, stagedContextDir, contextHomeDir, deliveryDir } from './chunk-N2PXGQRL.js';
|
|
10
|
-
import {
|
|
11
|
-
import { fstatSync, existsSync, readdirSync, mkdirSync, writeFileSync, chmodSync, rmSync, copyFileSync, lstatSync, readFileSync } from 'fs';
|
|
11
|
+
import { fstatSync, mkdirSync, writeFileSync, chmodSync, rmSync, lstatSync } from 'fs';
|
|
12
12
|
import { relative, join, dirname } from 'path';
|
|
13
13
|
|
|
14
14
|
createRequire(import.meta.url);
|
|
@@ -300,82 +300,8 @@ var BuildTokens = class {
|
|
|
300
300
|
);
|
|
301
301
|
}
|
|
302
302
|
};
|
|
303
|
-
function deliverySection(dir) {
|
|
304
|
-
return `This repository's control plane is not in the checkout. Its files are in \`${dir}\`. When an instruction or skill names a path under \`.outerlayer/\` or \`.claude/\`, read it under \`${dir}\`.`;
|
|
305
|
-
}
|
|
306
|
-
function isFile(path) {
|
|
307
|
-
try {
|
|
308
|
-
return lstatSync(path).isFile();
|
|
309
|
-
} catch {
|
|
310
|
-
return false;
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
function filesUnder(dir, base = dir) {
|
|
314
|
-
if (!existsSync(dir) || !lstatSync(dir).isDirectory()) return [];
|
|
315
|
-
const out = [];
|
|
316
|
-
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
317
|
-
const abs = join(dir, entry.name);
|
|
318
|
-
if (entry.isDirectory()) out.push(...filesUnder(abs, base));
|
|
319
|
-
else if (entry.isFile()) out.push(abs.slice(base.length + 1));
|
|
320
|
-
}
|
|
321
|
-
return out.sort();
|
|
322
|
-
}
|
|
323
|
-
function readText(path) {
|
|
324
|
-
if (!isFile(path)) return void 0;
|
|
325
|
-
const content = readFileSync(path);
|
|
326
|
-
return content.includes(0) ? void 0 : content.toString("utf8");
|
|
327
|
-
}
|
|
328
|
-
function deliveredSettings(raw, dir) {
|
|
329
|
-
if (raw === void 0) return "{}\n";
|
|
330
|
-
const rewrite = (value) => {
|
|
331
|
-
if (typeof value === "string") return rewriteHookCommand(value, dir);
|
|
332
|
-
if (Array.isArray(value)) return value.map(rewrite);
|
|
333
|
-
if (typeof value === "object" && value !== null) return Object.fromEntries(Object.entries(value).map(([key, inner]) => [key, rewrite(inner)]));
|
|
334
|
-
return value;
|
|
335
|
-
};
|
|
336
|
-
try {
|
|
337
|
-
return `${JSON.stringify(rewrite(JSON.parse(raw)), null, 2)}
|
|
338
|
-
`;
|
|
339
|
-
} catch {
|
|
340
|
-
return rewriteHookCommand(raw, dir);
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
function composeDelivery(input) {
|
|
344
|
-
const { tree, dir } = input;
|
|
345
|
-
const added = [];
|
|
346
|
-
const put = (rel, content) => {
|
|
347
|
-
mkdirSync(dirname(join(tree, rel)), { recursive: true });
|
|
348
|
-
writeFileSync(join(tree, rel), content);
|
|
349
|
-
added.push(rel);
|
|
350
|
-
};
|
|
351
|
-
for (const skill of MAINTAINED_SKILLS) {
|
|
352
|
-
for (const rel of filesUnder(join(tree, ".outerlayer/skills", skill))) {
|
|
353
|
-
const target = `.claude/skills/${skill}/${rel}`;
|
|
354
|
-
if (existsSync(join(tree, target))) continue;
|
|
355
|
-
mkdirSync(dirname(join(tree, target)), { recursive: true });
|
|
356
|
-
copyFileSync(join(tree, ".outerlayer/skills", skill, rel), join(tree, target));
|
|
357
|
-
added.push(target);
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
for (const rel of [...filesUnder(join(tree, ".claude/skills"), tree), ...filesUnder(join(tree, ".claude/agents"), tree)]) {
|
|
361
|
-
const text = readText(join(tree, rel));
|
|
362
|
-
if (text === void 0) continue;
|
|
363
|
-
const rewritten = rewriteControlPlanePaths(text, dir);
|
|
364
|
-
if (rewritten !== text) writeFileSync(join(tree, rel), rewritten);
|
|
365
|
-
}
|
|
366
|
-
const agents = readText(join(tree, "AGENTS.md"));
|
|
367
|
-
put("CLAUDE.md", agents === void 0 ? `${deliverySection(dir)}
|
|
368
|
-
` : `${deliverySection(dir)}
|
|
369
303
|
|
|
370
|
-
|
|
371
|
-
put("settings.json", deliveredSettings(readText(join(tree, ".claude/settings.json")), dir));
|
|
372
|
-
return added;
|
|
373
|
-
}
|
|
374
|
-
function sharedSkillNames(tree) {
|
|
375
|
-
const dir = join(tree, ".claude/skills");
|
|
376
|
-
if (!existsSync(dir)) return [];
|
|
377
|
-
return readdirSync(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort();
|
|
378
|
-
}
|
|
304
|
+
// src/runner/control-plane-delivery.ts
|
|
379
305
|
function shimScript() {
|
|
380
306
|
return SHIM_SCRIPT;
|
|
381
307
|
}
|
|
@@ -561,4 +487,4 @@ async function imageTargetFor(input) {
|
|
|
561
487
|
return { ok: true, repository: resolved.source.repository, pinned: { commit: resolved.source.sha, ref: resolved.source.ref } };
|
|
562
488
|
}
|
|
563
489
|
|
|
564
|
-
export { BuildTokens, classifyRefusal, commandWithShim, controlPlaneTokenFailure, createRunnerLog, describeCallFailure, formatClock, formatDuration, imageTargetFor, pinnedSourceOf, refusalCode, relativeToRunner, removeStagedContext, resolveGoverningSource, retrySend,
|
|
490
|
+
export { BuildTokens, classifyRefusal, commandWithShim, controlPlaneTokenFailure, createRunnerLog, describeCallFailure, formatClock, formatDuration, imageTargetFor, logStamp, pinnedSourceOf, refusalCode, relativeToRunner, removeStagedContext, resolveGoverningSource, retrySend, shimScript, shortClaim, stageGovernedContext };
|
|
@@ -1,34 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { join, dirname } from 'path';
|
|
3
|
+
import { unlinkSync, readFileSync, mkdirSync, writeFileSync, existsSync } from 'fs';
|
|
4
|
+
import { isAbsolute, join, dirname } from 'path';
|
|
6
5
|
|
|
7
6
|
createRequire(import.meta.url);
|
|
8
|
-
function pinPath(workpieceRoot) {
|
|
9
|
-
return join(workpieceRoot, CONTEXT_PIN_FILENAME);
|
|
10
|
-
}
|
|
11
|
-
function readPin(workpieceRoot) {
|
|
12
|
-
try {
|
|
13
|
-
const parsed = JSON.parse(readFileSync(pinPath(workpieceRoot), "utf8"));
|
|
14
|
-
if (typeof parsed === "object" && parsed !== null && typeof parsed.sha === "string" && typeof parsed.schemaVersion === "number") {
|
|
15
|
-
return parsed;
|
|
16
|
-
}
|
|
17
|
-
return void 0;
|
|
18
|
-
} catch {
|
|
19
|
-
return void 0;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
function pinExists(workpieceRoot) {
|
|
23
|
-
return existsSync(pinPath(workpieceRoot));
|
|
24
|
-
}
|
|
25
|
-
function writePinIfChanged(workpieceRoot, sha) {
|
|
26
|
-
const existing = readPin(workpieceRoot);
|
|
27
|
-
if (existing?.sha === sha && existing.schemaVersion === CONTEXT_PIN_SCHEMA_VERSION) return false;
|
|
28
|
-
const pin = { schemaVersion: CONTEXT_PIN_SCHEMA_VERSION, sha };
|
|
29
|
-
writeFileSync(pinPath(workpieceRoot), JSON.stringify(pin) + "\n");
|
|
30
|
-
return true;
|
|
31
|
-
}
|
|
32
7
|
function stateDir(gitCommonDir) {
|
|
33
8
|
return join(gitCommonDir, "outerlayer");
|
|
34
9
|
}
|
|
@@ -56,19 +31,9 @@ function readContextManifest(gitCommonDir) {
|
|
|
56
31
|
function writeContextManifest(gitCommonDir, manifest) {
|
|
57
32
|
writeJson(manifestPath(gitCommonDir), manifest);
|
|
58
33
|
}
|
|
59
|
-
function
|
|
60
|
-
return manifest.files.every((f) => existsSync(join(workpieceRoot, f)));
|
|
61
|
-
}
|
|
62
|
-
function lastCheckPath(gitCommonDir) {
|
|
63
|
-
return join(stateDir(gitCommonDir), "last-check");
|
|
64
|
-
}
|
|
65
|
-
function touchLastCheck(gitCommonDir, now) {
|
|
66
|
-
const path = lastCheckPath(gitCommonDir);
|
|
67
|
-
mkdirSync(dirname(path), { recursive: true });
|
|
68
|
-
writeFileSync(path, String(now));
|
|
69
|
-
const seconds = now / 1e3;
|
|
34
|
+
function removeContextManifest(gitCommonDir) {
|
|
70
35
|
try {
|
|
71
|
-
|
|
36
|
+
unlinkSync(manifestPath(gitCommonDir));
|
|
72
37
|
} catch {
|
|
73
38
|
}
|
|
74
39
|
}
|
|
@@ -107,18 +72,38 @@ function writeSourceCache(gitCommonDir, cache) {
|
|
|
107
72
|
function isSourceCacheFresh(cache, now) {
|
|
108
73
|
return now - Date.parse(cache.checkedAt) < cache.ttlMs;
|
|
109
74
|
}
|
|
110
|
-
function
|
|
111
|
-
return join(stateDir(gitCommonDir), "
|
|
112
|
-
}
|
|
113
|
-
function
|
|
114
|
-
const parsed = readJson(
|
|
115
|
-
if (
|
|
116
|
-
return
|
|
75
|
+
function deliveryRecordPath(gitCommonDir) {
|
|
76
|
+
return join(stateDir(gitCommonDir), "delivery.json");
|
|
77
|
+
}
|
|
78
|
+
function readDeliveryRecord(gitCommonDir) {
|
|
79
|
+
const parsed = readJson(deliveryRecordPath(gitCommonDir));
|
|
80
|
+
if (typeof parsed?.dir === "string" && isAbsolute(parsed.dir) && typeof parsed.repository === "string" && typeof parsed.sha === "string") {
|
|
81
|
+
return {
|
|
82
|
+
...typeof parsed.schemaVersion === "number" ? { schemaVersion: parsed.schemaVersion } : {},
|
|
83
|
+
repository: parsed.repository,
|
|
84
|
+
...typeof parsed.ref === "string" ? { ref: parsed.ref } : {},
|
|
85
|
+
sha: parsed.sha,
|
|
86
|
+
dir: parsed.dir,
|
|
87
|
+
...parsed.launcher === true ? { launcher: true } : {}
|
|
88
|
+
};
|
|
117
89
|
}
|
|
118
90
|
return void 0;
|
|
119
91
|
}
|
|
120
|
-
function
|
|
121
|
-
|
|
92
|
+
function removeLauncherDeliveryRecord(gitCommonDir) {
|
|
93
|
+
if (readDeliveryRecord(gitCommonDir)?.launcher !== true) return;
|
|
94
|
+
try {
|
|
95
|
+
unlinkSync(deliveryRecordPath(gitCommonDir));
|
|
96
|
+
} catch {
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function deliveryRecordExists(gitCommonDir) {
|
|
100
|
+
return existsSync(deliveryRecordPath(gitCommonDir));
|
|
101
|
+
}
|
|
102
|
+
function writeDeliveryRecord(gitCommonDir, record) {
|
|
103
|
+
writeJson(deliveryRecordPath(gitCommonDir), record);
|
|
104
|
+
}
|
|
105
|
+
function cloneIsGoverned(gitCommonDir) {
|
|
106
|
+
return readSourceCache(gitCommonDir)?.status === "governed" || deliveryRecordExists(gitCommonDir);
|
|
122
107
|
}
|
|
123
108
|
|
|
124
|
-
export { SOURCE_CACHE_TTL_RETRY_MS, SOURCE_CACHE_TTL_SUCCESS_MS, clearDegraded,
|
|
109
|
+
export { SOURCE_CACHE_TTL_RETRY_MS, SOURCE_CACHE_TTL_SUCCESS_MS, clearDegraded, cloneIsGoverned, isSourceCacheFresh, readContextManifest, readDegraded, readDeliveryRecord, readSourceCache, removeContextManifest, removeLauncherDeliveryRecord, writeContextManifest, writeDegraded, writeDeliveryRecord, writeSourceCache };
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
3
|
import { C } from './chunk-ANPNT6PM.js';
|
|
4
|
-
import { retiredSkillPaths, removeRetiredSkills } from './chunk-
|
|
5
|
-
import { maintainedFilesForExistingSkills, loadMaintainedFiles, writeMaintainedFiles } from './chunk-
|
|
6
|
-
import { emitTree, parseOuterlayerConfig, classifyTree, generatedHeaderSource, CONTEXT_PIN_FILENAME, normalizePath } from './chunk-
|
|
4
|
+
import { retiredSkillPaths, removeRetiredSkills } from './chunk-IXYZUUYQ.js';
|
|
5
|
+
import { maintainedFilesForExistingSkills, loadMaintainedFiles, writeMaintainedFiles } from './chunk-NNLA7LLQ.js';
|
|
6
|
+
import { emitTree, parseOuterlayerConfig, classifyTree, generatedHeaderSource, CONTEXT_PIN_FILENAME, normalizePath } from './chunk-WFSUUUAN.js';
|
|
7
7
|
import { cliInvocation } from './chunk-CRB3POP4.js';
|
|
8
|
-
import { existsSync, readFileSync, mkdirSync, writeFileSync, copyFileSync, readdirSync } from 'fs';
|
|
8
|
+
import { existsSync, readFileSync, mkdirSync, writeFileSync, copyFileSync, unlinkSync, rmdirSync, readdirSync } from 'fs';
|
|
9
9
|
import { join, dirname, relative, sep } from 'path';
|
|
10
10
|
|
|
11
11
|
createRequire(import.meta.url);
|
|
@@ -32,6 +32,9 @@ function discoverOuterlayerPaths(repoRoot) {
|
|
|
32
32
|
walk(repoRoot, repoRoot, false, out);
|
|
33
33
|
return out.sort();
|
|
34
34
|
}
|
|
35
|
+
function isForeignTree(dir) {
|
|
36
|
+
return existsSync(join(dir, ".git")) || existsSync(join(dir, CONTEXT_PIN_FILENAME));
|
|
37
|
+
}
|
|
35
38
|
function walk(dir, repoRoot, insideOuterlayer, out) {
|
|
36
39
|
let entries;
|
|
37
40
|
try {
|
|
@@ -44,7 +47,7 @@ function walk(dir, repoRoot, insideOuterlayer, out) {
|
|
|
44
47
|
const full = join(dir, entry.name);
|
|
45
48
|
if (entry.isDirectory()) {
|
|
46
49
|
if (!insideOuterlayer && SKIP_DIRS.has(entry.name)) continue;
|
|
47
|
-
if (!insideOuterlayer &&
|
|
50
|
+
if (!insideOuterlayer && isForeignTree(full)) continue;
|
|
48
51
|
walk(full, repoRoot, insideOuterlayer || entry.name === ".outerlayer", out);
|
|
49
52
|
} else if (entry.isFile() && insideOuterlayer) {
|
|
50
53
|
out.push(toRepoRelative(repoRoot, full));
|
|
@@ -82,13 +85,14 @@ function writeOutputs(repoRoot, result, maintained) {
|
|
|
82
85
|
}
|
|
83
86
|
return { files, copies, maintained: [...changedMaintained.created, ...changedMaintained.rewritten] };
|
|
84
87
|
}
|
|
85
|
-
function renderSuccess(targets, files, copies, maintained, retired) {
|
|
88
|
+
function renderSuccess(targets, files, copies, maintained, retired, orphaned) {
|
|
86
89
|
const copySuffix = copies.length > 0 ? `, ${copies.length} ${copies.length === 1 ? "copy" : "copies"}` : "";
|
|
87
90
|
const lines = [
|
|
88
91
|
`${C.green}\u2713${C.reset} emitted ${files.length} file${files.length === 1 ? "" : "s"}${copySuffix} for ${C.dim}${targets.join(", ")}${C.reset}`
|
|
89
92
|
];
|
|
90
93
|
for (const path of maintained) lines.push(` ${C.dim}updated ${path} to this CLI's version${C.reset}`);
|
|
91
94
|
for (const path of retired) lines.push(` ${C.dim}removed ${path}: this skill has a new name${C.reset}`);
|
|
95
|
+
for (const path of orphaned) lines.push(` ${C.dim}removed ${path}: its source is gone${C.reset}`);
|
|
92
96
|
return lines.join("\n");
|
|
93
97
|
}
|
|
94
98
|
function renderFailure(errors) {
|
|
@@ -132,7 +136,7 @@ function walkAll(dir, repoRoot, out) {
|
|
|
132
136
|
if (entry.isSymbolicLink()) continue;
|
|
133
137
|
const full = join(dir, entry.name);
|
|
134
138
|
if (entry.isDirectory()) {
|
|
135
|
-
if (SKIP_DIRS.has(entry.name) || entry.name === ".outerlayer") continue;
|
|
139
|
+
if (SKIP_DIRS.has(entry.name) || entry.name === ".outerlayer" || isForeignTree(full)) continue;
|
|
136
140
|
walkAll(full, repoRoot, out);
|
|
137
141
|
} else if (entry.isFile()) {
|
|
138
142
|
out.push(toRepoRelative(repoRoot, full));
|
|
@@ -155,6 +159,21 @@ function findOrphans(repoRoot, computedFiles, sourcePaths) {
|
|
|
155
159
|
}
|
|
156
160
|
return orphans;
|
|
157
161
|
}
|
|
162
|
+
function removeOrphans(repoRoot, orphans) {
|
|
163
|
+
const removed = [];
|
|
164
|
+
for (const { path } of orphans) {
|
|
165
|
+
unlinkSync(join(repoRoot, path));
|
|
166
|
+
removed.push(path);
|
|
167
|
+
for (let dir = dirname(path); dir !== "."; dir = dirname(dir)) {
|
|
168
|
+
try {
|
|
169
|
+
rmdirSync(join(repoRoot, dir));
|
|
170
|
+
} catch {
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return removed;
|
|
176
|
+
}
|
|
158
177
|
function withholdKept(repoRoot, result, keep) {
|
|
159
178
|
if (keep === void 0) return { result, kept: [] };
|
|
160
179
|
const kept = [];
|
|
@@ -187,9 +206,11 @@ function runEmit(opts = {}) {
|
|
|
187
206
|
const emitted = emitTree(built.input);
|
|
188
207
|
const { result, kept } = withholdKept(cwd, emitted, opts.keep);
|
|
189
208
|
const hasErrors = result.errors.length > 0;
|
|
190
|
-
|
|
209
|
+
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
211
|
const written = hasErrors ? { files: [], copies: [], maintained: [] } : writeOutputs(cwd, result, maintained);
|
|
192
212
|
const removed = hasErrors ? [] : removeRetiredSkills(cwd);
|
|
213
|
+
const orphaned = hasErrors ? [] : removeOrphans(cwd, findOrphans(cwd, outputs, built.sourcePaths));
|
|
193
214
|
const exitCode = hasErrors ? 1 : 0;
|
|
194
215
|
const output = opts.json ? JSON.stringify({
|
|
195
216
|
targets,
|
|
@@ -197,9 +218,10 @@ function runEmit(opts = {}) {
|
|
|
197
218
|
copies: written.copies,
|
|
198
219
|
maintained: written.maintained,
|
|
199
220
|
retired: removed,
|
|
221
|
+
orphaned,
|
|
200
222
|
warnings: result.warnings,
|
|
201
223
|
errors: result.errors
|
|
202
|
-
}) : hasErrors ? renderFailure(result.errors) : renderSuccess(targets, written.files, written.copies, written.maintained, removed);
|
|
224
|
+
}) : hasErrors ? renderFailure(result.errors) : renderSuccess(targets, written.files, written.copies, written.maintained, removed, orphaned);
|
|
203
225
|
if (!opts.quiet) {
|
|
204
226
|
if (opts.json) {
|
|
205
227
|
process.stdout.write(output + "\n");
|
|
@@ -218,13 +240,14 @@ function runEmit(opts = {}) {
|
|
|
218
240
|
maintained: written.maintained,
|
|
219
241
|
kept,
|
|
220
242
|
retired: removed,
|
|
243
|
+
orphaned,
|
|
221
244
|
warnings: result.warnings,
|
|
222
245
|
errors: result.errors,
|
|
223
246
|
output,
|
|
224
247
|
exitCode
|
|
225
248
|
};
|
|
226
249
|
}
|
|
227
|
-
function runCheck(cwd, opts, targets, result, hasErrors, sourcePaths, maintained, kept, retired) {
|
|
250
|
+
function runCheck(cwd, opts, targets, result, hasErrors, outputs, sourcePaths, maintained, kept, retired) {
|
|
228
251
|
const drift = [];
|
|
229
252
|
if (!hasErrors) {
|
|
230
253
|
for (const path of retired) drift.push({ kind: "retired", path });
|
|
@@ -232,7 +255,6 @@ function runCheck(cwd, opts, targets, result, hasErrors, sourcePaths, maintained
|
|
|
232
255
|
const d = compareFile(cwd, file.path, file.content);
|
|
233
256
|
if (d) drift.push(d);
|
|
234
257
|
}
|
|
235
|
-
const computedFiles = new Set(result.files.map((f) => f.path));
|
|
236
258
|
for (const file of result.files) {
|
|
237
259
|
const d = compareFile(cwd, file.path, file.content);
|
|
238
260
|
if (d) drift.push(d);
|
|
@@ -242,7 +264,7 @@ function runCheck(cwd, opts, targets, result, hasErrors, sourcePaths, maintained
|
|
|
242
264
|
if (d) drift.push(d);
|
|
243
265
|
}
|
|
244
266
|
const retiredPaths = new Set(retired);
|
|
245
|
-
drift.push(...findOrphans(cwd,
|
|
267
|
+
drift.push(...findOrphans(cwd, outputs, sourcePaths).filter((d) => !retiredPaths.has(d.path)));
|
|
246
268
|
drift.sort((a, b) => a.path.localeCompare(b.path) || a.kind.localeCompare(b.kind));
|
|
247
269
|
}
|
|
248
270
|
const exitCode = hasErrors || drift.length > 0 ? 1 : 0;
|
|
@@ -258,7 +280,7 @@ function runCheck(cwd, opts, targets, result, hasErrors, sourcePaths, maintained
|
|
|
258
280
|
`);
|
|
259
281
|
}
|
|
260
282
|
}
|
|
261
|
-
return { targets, files: [], copies: [], maintained: [], kept, retired: [], warnings: result.warnings, errors: result.errors, drift, output, exitCode };
|
|
283
|
+
return { targets, files: [], copies: [], maintained: [], kept, retired: [], orphaned: [], warnings: result.warnings, errors: result.errors, drift, output, exitCode };
|
|
262
284
|
}
|
|
263
285
|
|
|
264
286
|
export { EmitError, runEmit };
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
3
|
import { versionAtLeast, MINIMUM_CLAUDE_VERSION, SHIM_SCRIPT, CONTROL_PLANE_DIR_VARIABLE } from './chunk-G2YNJIGF.js';
|
|
4
4
|
export { MINIMUM_CLAUDE_VERSION } from './chunk-G2YNJIGF.js';
|
|
5
|
+
import { homeFromEnv } from './chunk-VNVZDWO3.js';
|
|
5
6
|
import './chunk-Z5GEFMRW.js';
|
|
6
7
|
import { spawnSync, execFileSync, spawn } from 'child_process';
|
|
7
8
|
import { existsSync, accessSync, constants, statSync, readFileSync } from 'fs';
|
|
@@ -20,7 +21,7 @@ function readDeliveryRecord(cwd) {
|
|
|
20
21
|
try {
|
|
21
22
|
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
22
23
|
if (typeof parsed.dir === "string" && isAbsolute(parsed.dir) && typeof parsed.repository === "string" && typeof parsed.sha === "string") {
|
|
23
|
-
return { kind: "found", record: { repository: parsed.repository, sha: parsed.sha, dir: parsed.dir } };
|
|
24
|
+
return { kind: "found", record: { repository: parsed.repository, sha: parsed.sha, dir: parsed.dir, launcher: parsed.launcher === true } };
|
|
24
25
|
}
|
|
25
26
|
} catch {
|
|
26
27
|
}
|
|
@@ -72,17 +73,29 @@ async function runClaudeLauncher(args, deps = {}) {
|
|
|
72
73
|
return 127;
|
|
73
74
|
}
|
|
74
75
|
const found = readDeliveryRecord(cwd);
|
|
75
|
-
|
|
76
|
-
if (found.kind === "invalid") {
|
|
76
|
+
const build = found.kind === "found" && found.record.launcher !== true ? found.record : void 0;
|
|
77
|
+
if (found.kind === "invalid" && env.OUTERLAYER_JOB_DIR !== void 0) {
|
|
77
78
|
stderr(`outerlayer claude: ${found.path} is not a readable delivery record, so the control plane cannot be attached
|
|
78
79
|
`);
|
|
79
80
|
return 1;
|
|
80
81
|
}
|
|
81
|
-
|
|
82
|
-
if (
|
|
83
|
-
|
|
82
|
+
let dir;
|
|
83
|
+
if (build !== void 0) {
|
|
84
|
+
dir = build.dir;
|
|
85
|
+
if (!existsSync(dir)) {
|
|
86
|
+
stderr(`outerlayer claude: the control plane of ${build.repository} is not at ${dir}, so it cannot be attached
|
|
84
87
|
`);
|
|
85
|
-
|
|
88
|
+
return 1;
|
|
89
|
+
}
|
|
90
|
+
} else {
|
|
91
|
+
const { resolveLaunchPlane } = await import('./control-plane-launch-NYVDJESK.js');
|
|
92
|
+
const plane = await resolveLaunchPlane({ cwd, env, home: homeFromEnv(env), fetchImpl: deps.fetchImpl, stderr });
|
|
93
|
+
if (plane.kind === "none") return run(claude, args, env, cwd, stderr);
|
|
94
|
+
if (plane.kind === "refused") {
|
|
95
|
+
stderr(plane.message);
|
|
96
|
+
return 1;
|
|
97
|
+
}
|
|
98
|
+
dir = plane.dir;
|
|
86
99
|
}
|
|
87
100
|
const reported = spawnSync(claude, ["--version"], { env, encoding: "utf8", timeout: 15e3, stdio: ["ignore", "pipe", "ignore"] }).stdout ?? "";
|
|
88
101
|
if (/\d+\.\d+\.\d+/.test(reported) && !versionAtLeast(reported)) {
|