@outerlayer/cli 0.17.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 +72 -0
- package/README.md +36 -2
- package/dist/agent-setup-TPR4BBFV.js +27 -0
- package/dist/{artifact-link-cmd-2F47LT7F.js → artifact-link-cmd-W7XF5BFB.js} +4 -3
- package/dist/{build-BG2YENGK.js → build-TQ6X5PYN.js} +5 -4
- package/dist/build-info.json +1 -1
- package/dist/{builder-2D3WSOOY.js → builder-C4QNTYMS.js} +5 -6
- package/dist/{check-5XE7XMC4.js → check-UWQAL2MN.js} +56 -52
- package/dist/{chunk-R7PF5OOU.js → chunk-3CWUOFV6.js} +21 -14
- package/dist/{chunk-4NPZVMJU.js → chunk-3UZTIRLF.js} +60 -4
- package/dist/chunk-452TM7J4.js +502 -0
- package/dist/{chunk-NNRTPG7X.js → chunk-5GHGAF6P.js} +4 -4
- package/dist/{chunk-WVUIRTWA.js → chunk-5MYFOW5V.js} +196 -37
- package/dist/{chunk-HGECYFEI.js → chunk-5TN7GLYX.js} +138 -109
- package/dist/{chunk-VQYBXPI7.js → chunk-6D7GT22T.js} +5 -5
- package/dist/{chunk-G5NPRL2K.js → chunk-6U3MV7TZ.js} +687 -76
- package/dist/{chunk-42ZI52JW.js → chunk-6X4SQ5MY.js} +4 -3
- package/dist/{chunk-MAK5LYRF.js → chunk-7KSSBQTS.js} +278 -535
- package/dist/{chunk-NWQTTSBB.js → chunk-7SJPQWBM.js} +41 -16
- package/dist/{chunk-J5M7BSJQ.js → chunk-7VUK5RFS.js} +23 -4
- package/dist/{chunk-OZGHL5Y5.js → chunk-7YP7T6GV.js} +2 -2
- package/dist/{chunk-TI7B7UEO.js → chunk-AMFWYESY.js} +1 -1
- package/dist/{chunk-YRYMNBGQ.js → chunk-ANPNT6PM.js} +2 -1
- package/dist/{chunk-4KSQKQXE.js → chunk-BM63HB2M.js} +20 -16
- package/dist/{chunk-4Q7OMKAT.js → chunk-BQXFBI7T.js} +81 -5
- package/dist/{chunk-ADJRGVZC.js → chunk-BWSUPRDK.js} +1 -1
- package/dist/{chunk-3NSNIIBE.js → chunk-CG36IONK.js} +18 -17
- package/dist/chunk-CJJDJ7AT.js +56 -0
- package/dist/chunk-CRB3POP4.js +34 -0
- package/dist/{chunk-LWSJQJC6.js → chunk-DADWEUH3.js} +7 -7
- package/dist/{chunk-KG5ECZGJ.js → chunk-DJ3ZUSC3.js} +11 -11
- package/dist/{chunk-F47JBIAW.js → chunk-DSF2FWAZ.js} +2 -1
- package/dist/{chunk-N5FOE5PS.js → chunk-ECODQ7II.js} +4 -33
- package/dist/{chunk-HHJDN6AU.js → chunk-ESVW4MJY.js} +1 -1
- package/dist/{chunk-YO4PSLVB.js → chunk-FVMYKL6L.js} +1 -1
- package/dist/chunk-G2YNJIGF.js +44 -0
- package/dist/{chunk-WUYTWNMA.js → chunk-G3IJ3N6F.js} +5 -3
- package/dist/{chunk-QKFB4K7X.js → chunk-GGOMT6KF.js} +1 -1
- package/dist/{chunk-N6LURUEF.js → chunk-GOSFARMS.js} +1 -1
- package/dist/{chunk-S3NYLI2P.js → chunk-HPJNLETG.js} +93 -38
- package/dist/{chunk-IP7BIBXJ.js → chunk-IF2OSI5T.js} +35 -1
- package/dist/{chunk-C5Y5ZJJZ.js → chunk-IXYZUUYQ.js} +5 -4
- package/dist/chunk-JBJTC3UU.js +35 -0
- package/dist/chunk-KYS3TQAG.js +296 -0
- package/dist/chunk-LLM3I5YU.js +89 -0
- package/dist/{chunk-YU3VKZ5F.js → chunk-LRG3ZMZD.js} +6 -7
- package/dist/{chunk-V7NIVOFD.js → chunk-M2ZWWTWZ.js} +1 -1
- package/dist/{chunk-ERI5GBNI.js → chunk-MLAAT4S6.js} +3 -3
- package/dist/{chunk-O765JR4W.js → chunk-MTP2QEVO.js} +1 -1
- package/dist/{chunk-ZM2IMMYN.js → chunk-N2PXGQRL.js} +9 -1
- package/dist/{chunk-BWQ66M6N.js → chunk-NFIR3GEE.js} +98 -24
- package/dist/{chunk-POJMEEJJ.js → chunk-NNLA7LLQ.js} +1 -1
- package/dist/{chunk-PLMTLGYH.js → chunk-NTRCK4NH.js} +5 -4
- package/dist/{chunk-22RMZBGW.js → chunk-P53VEAOF.js} +1 -1
- package/dist/{chunk-RLYZLUQ7.js → chunk-QEFKA2QD.js} +2 -2
- package/dist/{chunk-JXYVA45C.js → chunk-QNLX477Q.js} +1200 -322
- package/dist/{chunk-UGP76IZ5.js → chunk-S5PCA3SN.js} +1 -1
- package/dist/{chunk-RMWLBUCJ.js → chunk-SADUQSO4.js} +1 -1
- package/dist/{chunk-GQD22KKN.js → chunk-T2Q7ISPE.js} +2 -1
- package/dist/chunk-TUSYOL2O.js +113 -0
- package/dist/{chunk-NBGDBTO2.js → chunk-TWF3RICI.js} +9 -8
- package/dist/{chunk-ONKJUM6R.js → chunk-UVG35MWF.js} +1 -1
- package/dist/{chunk-KMDLFI4P.js → chunk-VMJPFQNE.js} +1 -1
- package/dist/chunk-VRRGENS4.js +144 -0
- package/dist/{chunk-PTW6W5NR.js → chunk-VYAL7PUE.js} +1 -1
- package/dist/{chunk-OHVJA253.js → chunk-WFSUUUAN.js} +47 -30
- package/dist/{chunk-RSNSZ2LJ.js → chunk-X5H2WYMB.js} +1 -1
- package/dist/{chunk-HYZRY4KZ.js → chunk-XNGMQ27R.js} +16 -6
- package/dist/chunk-XSZD4AZ6.js +490 -0
- package/dist/chunk-YQR6E6OV.js +109 -0
- package/dist/{chunk-XCK2YAY5.js → chunk-YVZJ6GKF.js} +3 -2
- package/dist/{chunk-2MNPHL23.js → chunk-ZHAUSEEN.js} +38 -15
- package/dist/claude-launcher-FPPHZPMR.js +115 -0
- package/dist/{cli-A76AXELQ.js → cli-HROW5T7X.js} +567 -285
- package/dist/{command-R2QCVX55.js → command-OEAV7BVX.js} +42 -40
- package/dist/{config-N3C6DFQA.js → config-CLSGABD5.js} +2 -3
- package/dist/{connect-cmd-JBKAQNSF.js → connect-cmd-UNYKGDAL.js} +10 -9
- package/dist/context-cleanup-HSVYDGMI.js +9 -0
- package/dist/control-plane-launch-NYVDJESK.js +216 -0
- package/dist/{dist-LKDWQWZ7.js → dist-WO7NOJNG.js} +2 -2
- package/dist/{docker-4J77Q2BF.js → docker-BFU3AQGY.js} +7 -8
- package/dist/{doctor-4TAIARIG.js → doctor-23BBJWBX.js} +48 -42
- package/dist/{emit-artifact-cmd-MPZVR56N.js → emit-artifact-cmd-O6SCM7TV.js} +27 -24
- package/dist/emit-cmd-7SP3I6UZ.js +14 -0
- package/dist/{emit-criteria-cmd-EFGYI23V.js → emit-criteria-cmd-LQNERZRV.js} +17 -16
- package/dist/{emit-finding-cmd-5GF3V4LR.js → emit-finding-cmd-AJPKHIOV.js} +18 -17
- package/dist/{emit-result-cmd-I4OADKMD.js → emit-result-cmd-RUICOKWQ.js} +22 -19
- package/dist/emit-step-cmd-347XNGPQ.js +26 -0
- package/dist/{exec-client-CQV746UF.js → exec-client-7UMESIE2.js} +3 -4
- package/dist/governing-source-V5EEGPTA.js +34 -0
- package/dist/guest-init-KPBQOFE5.js +9 -0
- package/dist/{hook-fast-R4FVSZ2H.js → hook-fast-YAZG5MDX.js} +5 -2
- package/dist/host-key-U4B5QETR.js +8 -0
- package/dist/{import-capture-cmd-EQ35EARA.js → import-capture-cmd-KKFFOGWP.js} +7 -5
- package/dist/{import-ruler-cmd-BGAZXCQM.js → import-ruler-cmd-5P6JOXQN.js} +5 -3
- package/dist/index.js +8 -4
- package/dist/{init-PWU5YVL7.js → init-LWHDMZQG.js} +40 -38
- package/dist/init-MOINY2DD.js +53 -0
- package/dist/{init-cmd-XAVO7HYZ.js → init-cmd-HSMRID6A.js} +75 -30
- package/dist/{init-update-CVCWD6VS.js → init-update-LWX5MPPR.js} +29 -29
- package/dist/{install-HDBIPHTX.js → install-4SEFIIW2.js} +4 -5
- package/dist/{install-cmd-5HYMXLEW.js → install-cmd-QDOTR4OM.js} +5 -4
- package/dist/{login-browser-QZCS3WW6.js → login-browser-DX35MARZ.js} +5 -4
- package/dist/{logout-cmd-QAUFDJ6J.js → logout-cmd-5V5MMBSY.js} +3 -2
- package/dist/{logs-H55NWW4H.js → logs-AMLKC3VP.js} +3 -1
- package/dist/loop-SYYPVFYW.js +77 -0
- package/dist/machine-6X63G2KH.js +48 -0
- package/dist/{mcp-install-cmd-FDTPQQS6.js → mcp-install-cmd-GGWB3JJ2.js} +3 -2
- package/dist/{mcp-serve-cmd-3KVYEUXG.js → mcp-serve-cmd-N3UTY6EE.js} +11 -9
- package/dist/paths-7XP63OAX.js +7 -0
- package/dist/pending-532ABZYC.js +8 -0
- package/dist/{pidfile-UZRH774M.js → pidfile-3DM4OBKO.js} +4 -2
- package/dist/{record-C43U4PKS.js → record-3WP6V2K5.js} +3 -2
- package/dist/{runner-env-EN7YE7QX.js → runner-env-FRZFFHDF.js} +5 -6
- package/dist/{runner-key-6SLBI7PP.js → runner-key-276SJU5R.js} +40 -38
- package/dist/session-sender-GGIY5OAX.js +36 -0
- package/dist/{pending-MXLSRYMO.js → shell-function-NRD4KVUK.js} +1 -2
- package/dist/spec-cmd-SIZBRN7D.js +115 -0
- package/dist/{starter-pack-KF66HGZR.js → starter-pack-6LQVLBIA.js} +7 -5
- package/dist/{status-7VNQN5PW.js → status-NAK6DYSF.js} +46 -42
- package/dist/{statusline-fast-SVTMBMD7.js → statusline-fast-KN3BX67H.js} +2 -1
- package/dist/sync-cmd-G7GF4UTW.js +35 -0
- package/dist/{watch-23HSAEI6.js → watch-EVM5GSMP.js} +22 -15
- package/dist/{work-claim-cmd-LKL3GHFQ.js → work-claim-cmd-3J3QW56U.js} +26 -29
- package/dist/work-cmd-5EPPD33Y.js +24 -0
- package/dist/{work-comment-cmd-AWHP56M2.js → work-comment-cmd-2ACOZQAE.js} +16 -15
- package/dist/{work-launch-R5HTAP6X.js → work-launch-LEQ2MPM3.js} +3 -1
- package/dist/work-logs-cmd-QDD2NMJL.js +60 -0
- package/dist/{work-open-pr-cmd-IOM4AVQQ.js → work-open-pr-cmd-XNCEI4ZM.js} +18 -17
- package/dist/work-pr-cmd-H4OQR26N.js +25 -0
- package/package.json +3 -2
- package/skill-pack/maintained/outerlayer-amend/SKILL.md +4 -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 +18 -2
- package/skill-pack/template/build/SKILL.md +23 -10
- package/skill-pack/template/build/references/agent-briefs.md +3 -1
- package/skill-pack/template/build/references/criteria-judge.md +27 -0
- package/skill-pack/template/build/references/release.md +22 -29
- package/skill-pack/template/spec/SKILL.md +35 -10
- package/skill-pack/validators/acceptance-criteria.yaml +25 -26
- package/dist/agent-setup-T624CWPD.js +0 -27
- package/dist/chunk-6Y5RUTHO.js +0 -39
- package/dist/chunk-BYT5O5RV.js +0 -61
- package/dist/chunk-WTE3MQML.js +0 -133
- package/dist/chunk-XCCLFVXM.js +0 -401
- package/dist/chunk-YZ5F4PIS.js +0 -797
- package/dist/context-adopt-NFHCLVUB.js +0 -108
- package/dist/context-materialize-IV2TUUFO.js +0 -22
- package/dist/emit-cmd-IJ3GVRFD.js +0 -12
- package/dist/guest-init-LJP5GPZF.js +0 -9
- package/dist/host-key-YMLXY6QB.js +0 -7
- package/dist/init-6XPDRDTC.js +0 -51
- package/dist/loop-FK3LPMMZ.js +0 -73
- package/dist/machine-SQXEBAM2.js +0 -46
- package/dist/paths-OYKMVYJP.js +0 -6
- package/dist/session-sender-FO3LCREV.js +0 -29
- package/dist/sync-cmd-GVPPFZ3G.js +0 -28
- package/dist/work-cmd-Z2WXLZPH.js +0 -23
- package/dist/work-pr-cmd-HNEUIEN7.js +0 -24
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { C } from './chunk-
|
|
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-
|
|
7
|
-
import {
|
|
3
|
+
import { C } from './chunk-ANPNT6PM.js';
|
|
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
|
+
import { cliInvocation } from './chunk-CRB3POP4.js';
|
|
8
|
+
import { existsSync, readFileSync, mkdirSync, writeFileSync, copyFileSync, unlinkSync, rmdirSync, readdirSync } from 'fs';
|
|
8
9
|
import { join, dirname, relative, sep } from 'path';
|
|
9
10
|
|
|
10
11
|
createRequire(import.meta.url);
|
|
@@ -31,6 +32,9 @@ function discoverOuterlayerPaths(repoRoot) {
|
|
|
31
32
|
walk(repoRoot, repoRoot, false, out);
|
|
32
33
|
return out.sort();
|
|
33
34
|
}
|
|
35
|
+
function isForeignTree(dir) {
|
|
36
|
+
return existsSync(join(dir, ".git")) || existsSync(join(dir, CONTEXT_PIN_FILENAME));
|
|
37
|
+
}
|
|
34
38
|
function walk(dir, repoRoot, insideOuterlayer, out) {
|
|
35
39
|
let entries;
|
|
36
40
|
try {
|
|
@@ -43,7 +47,7 @@ function walk(dir, repoRoot, insideOuterlayer, out) {
|
|
|
43
47
|
const full = join(dir, entry.name);
|
|
44
48
|
if (entry.isDirectory()) {
|
|
45
49
|
if (!insideOuterlayer && SKIP_DIRS.has(entry.name)) continue;
|
|
46
|
-
if (!insideOuterlayer &&
|
|
50
|
+
if (!insideOuterlayer && isForeignTree(full)) continue;
|
|
47
51
|
walk(full, repoRoot, insideOuterlayer || entry.name === ".outerlayer", out);
|
|
48
52
|
} else if (entry.isFile() && insideOuterlayer) {
|
|
49
53
|
out.push(toRepoRelative(repoRoot, full));
|
|
@@ -81,13 +85,14 @@ function writeOutputs(repoRoot, result, maintained) {
|
|
|
81
85
|
}
|
|
82
86
|
return { files, copies, maintained: [...changedMaintained.created, ...changedMaintained.rewritten] };
|
|
83
87
|
}
|
|
84
|
-
function renderSuccess(targets, files, copies, maintained, retired) {
|
|
88
|
+
function renderSuccess(targets, files, copies, maintained, retired, orphaned) {
|
|
85
89
|
const copySuffix = copies.length > 0 ? `, ${copies.length} ${copies.length === 1 ? "copy" : "copies"}` : "";
|
|
86
90
|
const lines = [
|
|
87
91
|
`${C.green}\u2713${C.reset} emitted ${files.length} file${files.length === 1 ? "" : "s"}${copySuffix} for ${C.dim}${targets.join(", ")}${C.reset}`
|
|
88
92
|
];
|
|
89
93
|
for (const path of maintained) lines.push(` ${C.dim}updated ${path} to this CLI's version${C.reset}`);
|
|
90
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}`);
|
|
91
96
|
return lines.join("\n");
|
|
92
97
|
}
|
|
93
98
|
function renderFailure(errors) {
|
|
@@ -97,7 +102,7 @@ function renderFailure(errors) {
|
|
|
97
102
|
}
|
|
98
103
|
function renderCheck(targets, drift) {
|
|
99
104
|
if (drift.length === 0) return `${C.green}\u2713${C.reset} up to date for ${C.dim}${targets.join(", ")}${C.reset}`;
|
|
100
|
-
const lines = [`${C.red}\u2717${C.reset} drift detected (${drift.length}) \u2014 run
|
|
105
|
+
const lines = [`${C.red}\u2717${C.reset} drift detected (${drift.length}) \u2014 run \`${cliInvocation()} emit\` to update`];
|
|
101
106
|
for (const d of drift) lines.push(` ${C.red}\u2717${C.reset} ${d.kind.padEnd(8)} ${d.path}`);
|
|
102
107
|
return lines.join("\n");
|
|
103
108
|
}
|
|
@@ -131,7 +136,7 @@ function walkAll(dir, repoRoot, out) {
|
|
|
131
136
|
if (entry.isSymbolicLink()) continue;
|
|
132
137
|
const full = join(dir, entry.name);
|
|
133
138
|
if (entry.isDirectory()) {
|
|
134
|
-
if (SKIP_DIRS.has(entry.name) || entry.name === ".outerlayer") continue;
|
|
139
|
+
if (SKIP_DIRS.has(entry.name) || entry.name === ".outerlayer" || isForeignTree(full)) continue;
|
|
135
140
|
walkAll(full, repoRoot, out);
|
|
136
141
|
} else if (entry.isFile()) {
|
|
137
142
|
out.push(toRepoRelative(repoRoot, full));
|
|
@@ -154,6 +159,21 @@ function findOrphans(repoRoot, computedFiles, sourcePaths) {
|
|
|
154
159
|
}
|
|
155
160
|
return orphans;
|
|
156
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
|
+
}
|
|
157
177
|
function withholdKept(repoRoot, result, keep) {
|
|
158
178
|
if (keep === void 0) return { result, kept: [] };
|
|
159
179
|
const kept = [];
|
|
@@ -186,9 +206,11 @@ function runEmit(opts = {}) {
|
|
|
186
206
|
const emitted = emitTree(built.input);
|
|
187
207
|
const { result, kept } = withholdKept(cwd, emitted, opts.keep);
|
|
188
208
|
const hasErrors = result.errors.length > 0;
|
|
189
|
-
|
|
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);
|
|
190
211
|
const written = hasErrors ? { files: [], copies: [], maintained: [] } : writeOutputs(cwd, result, maintained);
|
|
191
212
|
const removed = hasErrors ? [] : removeRetiredSkills(cwd);
|
|
213
|
+
const orphaned = hasErrors ? [] : removeOrphans(cwd, findOrphans(cwd, outputs, built.sourcePaths));
|
|
192
214
|
const exitCode = hasErrors ? 1 : 0;
|
|
193
215
|
const output = opts.json ? JSON.stringify({
|
|
194
216
|
targets,
|
|
@@ -196,9 +218,10 @@ function runEmit(opts = {}) {
|
|
|
196
218
|
copies: written.copies,
|
|
197
219
|
maintained: written.maintained,
|
|
198
220
|
retired: removed,
|
|
221
|
+
orphaned,
|
|
199
222
|
warnings: result.warnings,
|
|
200
223
|
errors: result.errors
|
|
201
|
-
}) : 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);
|
|
202
225
|
if (!opts.quiet) {
|
|
203
226
|
if (opts.json) {
|
|
204
227
|
process.stdout.write(output + "\n");
|
|
@@ -217,13 +240,14 @@ function runEmit(opts = {}) {
|
|
|
217
240
|
maintained: written.maintained,
|
|
218
241
|
kept,
|
|
219
242
|
retired: removed,
|
|
243
|
+
orphaned,
|
|
220
244
|
warnings: result.warnings,
|
|
221
245
|
errors: result.errors,
|
|
222
246
|
output,
|
|
223
247
|
exitCode
|
|
224
248
|
};
|
|
225
249
|
}
|
|
226
|
-
function runCheck(cwd, opts, targets, result, hasErrors, sourcePaths, maintained, kept, retired) {
|
|
250
|
+
function runCheck(cwd, opts, targets, result, hasErrors, outputs, sourcePaths, maintained, kept, retired) {
|
|
227
251
|
const drift = [];
|
|
228
252
|
if (!hasErrors) {
|
|
229
253
|
for (const path of retired) drift.push({ kind: "retired", path });
|
|
@@ -231,7 +255,6 @@ function runCheck(cwd, opts, targets, result, hasErrors, sourcePaths, maintained
|
|
|
231
255
|
const d = compareFile(cwd, file.path, file.content);
|
|
232
256
|
if (d) drift.push(d);
|
|
233
257
|
}
|
|
234
|
-
const computedFiles = new Set(result.files.map((f) => f.path));
|
|
235
258
|
for (const file of result.files) {
|
|
236
259
|
const d = compareFile(cwd, file.path, file.content);
|
|
237
260
|
if (d) drift.push(d);
|
|
@@ -241,7 +264,7 @@ function runCheck(cwd, opts, targets, result, hasErrors, sourcePaths, maintained
|
|
|
241
264
|
if (d) drift.push(d);
|
|
242
265
|
}
|
|
243
266
|
const retiredPaths = new Set(retired);
|
|
244
|
-
drift.push(...findOrphans(cwd,
|
|
267
|
+
drift.push(...findOrphans(cwd, outputs, sourcePaths).filter((d) => !retiredPaths.has(d.path)));
|
|
245
268
|
drift.sort((a, b) => a.path.localeCompare(b.path) || a.kind.localeCompare(b.kind));
|
|
246
269
|
}
|
|
247
270
|
const exitCode = hasErrors || drift.length > 0 ? 1 : 0;
|
|
@@ -257,7 +280,7 @@ function runCheck(cwd, opts, targets, result, hasErrors, sourcePaths, maintained
|
|
|
257
280
|
`);
|
|
258
281
|
}
|
|
259
282
|
}
|
|
260
|
-
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 };
|
|
261
284
|
}
|
|
262
285
|
|
|
263
286
|
export { EmitError, runEmit };
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { versionAtLeast, MINIMUM_CLAUDE_VERSION, SHIM_SCRIPT, CONTROL_PLANE_DIR_VARIABLE } from './chunk-G2YNJIGF.js';
|
|
4
|
+
export { MINIMUM_CLAUDE_VERSION } from './chunk-G2YNJIGF.js';
|
|
5
|
+
import { homeFromEnv } from './chunk-VNVZDWO3.js';
|
|
6
|
+
import './chunk-Z5GEFMRW.js';
|
|
7
|
+
import { spawnSync, execFileSync, spawn } from 'child_process';
|
|
8
|
+
import { existsSync, accessSync, constants, statSync, readFileSync } from 'fs';
|
|
9
|
+
import { join, delimiter, isAbsolute, resolve } from 'path';
|
|
10
|
+
|
|
11
|
+
createRequire(import.meta.url);
|
|
12
|
+
function readDeliveryRecord(cwd) {
|
|
13
|
+
let common;
|
|
14
|
+
try {
|
|
15
|
+
common = execFileSync("git", ["rev-parse", "--git-common-dir"], { cwd, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], timeout: 5e3 }).trim();
|
|
16
|
+
} catch {
|
|
17
|
+
return { kind: "none" };
|
|
18
|
+
}
|
|
19
|
+
const path = join(isAbsolute(common) ? common : resolve(cwd, common), "outerlayer", "delivery.json");
|
|
20
|
+
if (!existsSync(path)) return { kind: "none" };
|
|
21
|
+
try {
|
|
22
|
+
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
23
|
+
if (typeof parsed.dir === "string" && isAbsolute(parsed.dir) && typeof parsed.repository === "string" && typeof parsed.sha === "string") {
|
|
24
|
+
return { kind: "found", record: { repository: parsed.repository, sha: parsed.sha, dir: parsed.dir, launcher: parsed.launcher === true } };
|
|
25
|
+
}
|
|
26
|
+
} catch {
|
|
27
|
+
}
|
|
28
|
+
return { kind: "invalid", path };
|
|
29
|
+
}
|
|
30
|
+
function findClaude(path) {
|
|
31
|
+
for (const entry of (path ?? "").split(delimiter)) {
|
|
32
|
+
if (entry === "") continue;
|
|
33
|
+
const candidate = join(entry, "claude");
|
|
34
|
+
try {
|
|
35
|
+
accessSync(candidate, constants.X_OK);
|
|
36
|
+
if (statSync(candidate).size === Buffer.byteLength(SHIM_SCRIPT) && readFileSync(candidate, "utf8") === SHIM_SCRIPT) continue;
|
|
37
|
+
} catch {
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
return candidate;
|
|
41
|
+
}
|
|
42
|
+
return void 0;
|
|
43
|
+
}
|
|
44
|
+
var SIGNALS = ["SIGINT", "SIGTERM", "SIGHUP"];
|
|
45
|
+
var SIGNAL_NUMBERS = { SIGHUP: 1, SIGINT: 2, SIGTERM: 15 };
|
|
46
|
+
function run(program, argv, env, cwd, stderr) {
|
|
47
|
+
return new Promise((done) => {
|
|
48
|
+
const child = spawn(program, argv, { cwd, env, stdio: "inherit" });
|
|
49
|
+
const forward = (signal) => () => {
|
|
50
|
+
child.kill(signal);
|
|
51
|
+
};
|
|
52
|
+
const handlers = SIGNALS.map((signal) => [signal, forward(signal)]);
|
|
53
|
+
for (const [signal, handler] of handlers) process.on(signal, handler);
|
|
54
|
+
const finish = (code) => {
|
|
55
|
+
for (const [signal, handler] of handlers) process.off(signal, handler);
|
|
56
|
+
done(code);
|
|
57
|
+
};
|
|
58
|
+
child.on("error", (err) => {
|
|
59
|
+
stderr(`outerlayer claude: could not start ${program}: ${err.message}
|
|
60
|
+
`);
|
|
61
|
+
finish(127);
|
|
62
|
+
});
|
|
63
|
+
child.on("exit", (code, signal) => finish(code ?? 128 + (signal === null ? 0 : SIGNAL_NUMBERS[signal] ?? 0)));
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
async function runClaudeLauncher(args, deps = {}) {
|
|
67
|
+
const cwd = deps.cwd ?? process.cwd();
|
|
68
|
+
const env = deps.env ?? process.env;
|
|
69
|
+
const stderr = deps.stderr ?? ((text) => void process.stderr.write(text));
|
|
70
|
+
const claude = findClaude(env.PATH);
|
|
71
|
+
if (claude === void 0) {
|
|
72
|
+
stderr("outerlayer claude: no claude program found on PATH\n");
|
|
73
|
+
return 127;
|
|
74
|
+
}
|
|
75
|
+
const found = readDeliveryRecord(cwd);
|
|
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) {
|
|
78
|
+
stderr(`outerlayer claude: ${found.path} is not a readable delivery record, so the control plane cannot be attached
|
|
79
|
+
`);
|
|
80
|
+
return 1;
|
|
81
|
+
}
|
|
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
|
|
87
|
+
`);
|
|
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;
|
|
99
|
+
}
|
|
100
|
+
const reported = spawnSync(claude, ["--version"], { env, encoding: "utf8", timeout: 15e3, stdio: ["ignore", "pipe", "ignore"] }).stdout ?? "";
|
|
101
|
+
if (/\d+\.\d+\.\d+/.test(reported) && !versionAtLeast(reported)) {
|
|
102
|
+
stderr(`outerlayer claude: Claude Code ${reported.trim().split(/\s+/)[0]} is older than ${MINIMUM_CLAUDE_VERSION}, the oldest version known to load a control plane's instructions for subagents; the minimum version is ${MINIMUM_CLAUDE_VERSION}
|
|
103
|
+
`);
|
|
104
|
+
return 1;
|
|
105
|
+
}
|
|
106
|
+
return run(
|
|
107
|
+
claude,
|
|
108
|
+
["--add-dir", dir, "--settings", join(dir, "settings.json"), ...args],
|
|
109
|
+
{ ...env, CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD: "1", [CONTROL_PLANE_DIR_VARIABLE]: dir },
|
|
110
|
+
cwd,
|
|
111
|
+
stderr
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export { runClaudeLauncher };
|