@outerlayer/cli 0.18.0 → 0.19.1

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.
Files changed (102) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +21 -2
  3. package/dist/{agent-setup-RBTEACYU.js → agent-setup-AM42SA2D.js} +15 -16
  4. package/dist/{artifact-link-cmd-AVM2EKTV.js → artifact-link-cmd-OWRI5AJX.js} +2 -2
  5. package/dist/build-info.json +1 -1
  6. package/dist/{builder-DUI2ZH2H.js → builder-C4QNTYMS.js} +3 -3
  7. package/dist/{check-5C4YDZYV.js → check-W2JGXN3B.js} +44 -43
  8. package/dist/{chunk-S26M3YBJ.js → chunk-3UZTIRLF.js} +1 -1
  9. package/dist/{chunk-Y5MXET4M.js → chunk-3ZR7Y23Y.js} +11 -10
  10. package/dist/{chunk-47TTLEDX.js → chunk-5VML45HH.js} +35 -13
  11. package/dist/{chunk-F4XSVQJ4.js → chunk-6X4SQ5MY.js} +2 -2
  12. package/dist/{chunk-T4Y6SCG3.js → chunk-7UWVLZXD.js} +2 -2
  13. package/dist/{chunk-N3CUDFCW.js → chunk-7VUK5RFS.js} +15 -2
  14. package/dist/{chunk-SWCTGCSC.js → chunk-7YP7T6GV.js} +1 -1
  15. package/dist/{chunk-3OFZM4X6.js → chunk-B6SCN5NY.js} +151 -20
  16. package/dist/{chunk-KDVIU23F.js → chunk-BWSUPRDK.js} +1 -1
  17. package/dist/{chunk-S76AYB4M.js → chunk-CG36IONK.js} +5 -5
  18. package/dist/{chunk-RAZTWYZN.js → chunk-CGGPS7SI.js} +7 -8
  19. package/dist/chunk-CJJDJ7AT.js +56 -0
  20. package/dist/{chunk-W5VPCONO.js → chunk-EAEELQVQ.js} +33 -227
  21. package/dist/{chunk-QQM2UJ6T.js → chunk-F2KXHIFI.js} +182 -28
  22. package/dist/{chunk-KK4VBOH6.js → chunk-FBTGMSQF.js} +10 -11
  23. package/dist/{chunk-MQJSXHV7.js → chunk-G3IJ3N6F.js} +5 -3
  24. package/dist/{chunk-FUB7LRUE.js → chunk-GEMQLBMW.js} +5 -5
  25. package/dist/{chunk-Y5GE76XC.js → chunk-HOKXGFDR.js} +33 -81
  26. package/dist/{chunk-IP7BIBXJ.js → chunk-IF2OSI5T.js} +35 -1
  27. package/dist/{chunk-UYOYTKE2.js → chunk-JHGEBPLE.js} +3 -3
  28. package/dist/chunk-KYS3TQAG.js +296 -0
  29. package/dist/chunk-LLM3I5YU.js +89 -0
  30. package/dist/{chunk-B3UKB46N.js → chunk-LRG3ZMZD.js} +4 -5
  31. package/dist/{chunk-NL4XPC7W.js → chunk-LW7G5TJB.js} +1 -1
  32. package/dist/{chunk-MNTSH4CL.js → chunk-NNLA7LLQ.js} +1 -1
  33. package/dist/{chunk-GOBOJMOJ.js → chunk-PIZRPNKR.js} +4 -4
  34. package/dist/{chunk-ULSIJGLS.js → chunk-PSN33ERW.js} +56 -14
  35. package/dist/{chunk-WGAUY5LE.js → chunk-QEFKA2QD.js} +1 -1
  36. package/dist/{chunk-BMYGAGBJ.js → chunk-QNLX477Q.js} +155 -23
  37. package/dist/{chunk-JF42URPU.js → chunk-R22NZSGA.js} +33 -9
  38. package/dist/chunk-TUSYOL2O.js +113 -0
  39. package/dist/{chunk-ESC6UR76.js → chunk-TWF3RICI.js} +6 -6
  40. package/dist/{chunk-L2USZT6T.js → chunk-VMJPFQNE.js} +1 -1
  41. package/dist/{chunk-X5N6KC6V.js → chunk-WFSUUUAN.js} +2 -3
  42. package/dist/{chunk-6CHIYEZZ.js → chunk-XZ4H4X5F.js} +9 -83
  43. package/dist/{chunk-LXAY4A2G.js → chunk-YQR6E6OV.js} +34 -49
  44. package/dist/chunk-Z7K3L4FC.js +174 -0
  45. package/dist/{claude-launcher-YVXI76NX.js → claude-launcher-J5M44PFS.js} +20 -7
  46. package/dist/{cli-C77H54BV.js → cli-EXX2R73G.js} +206 -230
  47. package/dist/{command-H5CILO4S.js → command-ZQNEPDS6.js} +29 -30
  48. package/dist/{config-FXDG4NPJ.js → config-CLSGABD5.js} +2 -2
  49. package/dist/{connect-cmd-ZW5FV3ZW.js → connect-cmd-UNYKGDAL.js} +7 -7
  50. package/dist/context-cleanup-CHEWNYU6.js +11 -0
  51. package/dist/control-plane-launch-34LNRJWR.js +216 -0
  52. package/dist/{dist-QTX4RSCL.js → dist-WO7NOJNG.js} +2 -2
  53. package/dist/{docker-RC3PRX3Q.js → docker-BFU3AQGY.js} +4 -4
  54. package/dist/{doctor-2NQQML6P.js → doctor-DHUM5DBB.js} +32 -33
  55. package/dist/{emit-artifact-cmd-7MP63KXU.js → emit-artifact-cmd-XBHM647X.js} +17 -17
  56. package/dist/{emit-cmd-PPN4QQF2.js → emit-cmd-W55AEBCA.js} +6 -6
  57. package/dist/{emit-criteria-cmd-3RXPDLNK.js → emit-criteria-cmd-CRTYEF7D.js} +11 -12
  58. package/dist/{emit-finding-cmd-OL7JB6H3.js → emit-finding-cmd-7JHVRYOP.js} +12 -13
  59. package/dist/{emit-result-cmd-UZVMOCF4.js → emit-result-cmd-5NZMLCJK.js} +17 -17
  60. package/dist/emit-step-cmd-347XNGPQ.js +26 -0
  61. package/dist/{governing-source-BUU4IABS.js → governing-source-HAA4OW57.js} +21 -22
  62. package/dist/{hook-fast-W5MKHMJT.js → hook-fast-RL5E5OXE.js} +3 -3
  63. package/dist/{import-capture-cmd-ZO6KGHI2.js → import-capture-cmd-TK4XY7RD.js} +4 -4
  64. package/dist/{import-ruler-cmd-KJMWL5V6.js → import-ruler-cmd-T6LLO6Q7.js} +2 -2
  65. package/dist/index.js +4 -4
  66. package/dist/{init-WNXXYMO7.js → init-V6FOMD2V.js} +30 -31
  67. package/dist/{init-VWXIZEAN.js → init-XG47KCI4.js} +30 -31
  68. package/dist/{init-cmd-WS6TIRYT.js → init-cmd-Z4O4PPLZ.js} +70 -27
  69. package/dist/{init-update-E3J6TVIN.js → init-update-7DVAKWW3.js} +21 -22
  70. package/dist/{install-CBWIEF3R.js → install-4SEFIIW2.js} +3 -3
  71. package/dist/{login-browser-O63QZN7D.js → login-browser-DX35MARZ.js} +2 -2
  72. package/dist/{loop-UGI2BJOT.js → loop-TPUYUMSY.js} +44 -43
  73. package/dist/{machine-JOW4RNZ7.js → machine-TRHBT5NE.js} +26 -27
  74. package/dist/{mcp-serve-cmd-DOTY5FKY.js → mcp-serve-cmd-N3UTY6EE.js} +5 -5
  75. package/dist/{runner-env-4NB2GA7O.js → runner-env-FRZFFHDF.js} +4 -4
  76. package/dist/{runner-key-TC3NFWFV.js → runner-key-5FOWCW7J.js} +30 -31
  77. package/dist/{session-sender-NNVPSPY7.js → session-sender-U2BBUWNO.js} +19 -15
  78. package/dist/shell-function-NRD4KVUK.js +6 -0
  79. package/dist/{spec-cmd-OWVTBB4J.js → spec-cmd-FVLJOFGC.js} +12 -13
  80. package/dist/{starter-pack-OPWUDOWX.js → starter-pack-6LQVLBIA.js} +5 -5
  81. package/dist/{status-TKCLLKFG.js → status-BINH7MBG.js} +33 -32
  82. package/dist/{sync-cmd-Q6VYNPWG.js → sync-cmd-VXOUFS4I.js} +18 -14
  83. package/dist/{watch-ARAGADTF.js → watch-OH645CV2.js} +18 -14
  84. package/dist/{work-claim-cmd-34FERLYX.js → work-claim-cmd-ZRPSHMPT.js} +16 -17
  85. package/dist/{work-cmd-7S5B2H2P.js → work-cmd-5I3J2XQQ.js} +12 -13
  86. package/dist/{work-comment-cmd-SZJSPM5S.js → work-comment-cmd-UCCPWUSR.js} +12 -13
  87. package/dist/work-logs-cmd-7352CJPG.js +60 -0
  88. package/dist/{work-open-pr-cmd-RPXKCBWS.js → work-open-pr-cmd-LSH4VHJM.js} +13 -14
  89. package/dist/{work-pr-cmd-5LGANL32.js → work-pr-cmd-H4OQR26N.js} +12 -13
  90. package/package.json +2 -2
  91. package/skill-pack/maintained/outerlayer-cli/SKILL.md +9 -2
  92. package/skill-pack/maintained/outerlayer-cli/references/find-out-why-a-build-ended.md +76 -0
  93. package/skill-pack/shipped.json +1 -0
  94. package/skill-pack/template/build/references/release.md +3 -1
  95. package/dist/chunk-WBT5X3NH.js +0 -40
  96. package/dist/chunk-XCCLFVXM.js +0 -401
  97. package/dist/context-adopt-O5OFXMKI.js +0 -109
  98. package/dist/context-materialize-Y5IJ4MQT.js +0 -23
  99. package/dist/{chunk-NACDBXUG.js → chunk-BM63HB2M.js} +1 -1
  100. package/dist/{chunk-ZRL6HKBY.js → chunk-FVMYKL6L.js} +1 -1
  101. package/dist/{chunk-52NC2FIU.js → chunk-NTRCK4NH.js} +1 -1
  102. package/dist/{chunk-XGP3VYOG.js → chunk-P53VEAOF.js} +1 -1
@@ -1,34 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { CONTEXT_PIN_SCHEMA_VERSION, CONTEXT_PIN_FILENAME } from './chunk-X5N6KC6V.js';
4
- import { readFileSync, existsSync, writeFileSync, mkdirSync, utimesSync, unlinkSync } from 'fs';
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 manifestFilesPresent(workpieceRoot, manifest) {
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
- utimesSync(path, seconds, seconds);
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 buildHoldPath(gitCommonDir) {
111
- return join(stateDir(gitCommonDir), "build-hold.json");
112
- }
113
- function readBuildHold(gitCommonDir) {
114
- const parsed = readJson(buildHoldPath(gitCommonDir));
115
- if (parsed && typeof parsed.sha === "string" && typeof parsed.repository === "string" && typeof parsed.ref === "string" && typeof parsed.at === "string") {
116
- return parsed;
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 writeBuildHold(gitCommonDir, hold) {
121
- writeJson(buildHoldPath(gitCommonDir), hold);
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, isSourceCacheFresh, manifestFilesPresent, pinExists, readBuildHold, readContextManifest, readDegraded, readPin, readSourceCache, touchLastCheck, writeBuildHold, writeContextManifest, writeDegraded, writePinIfChanged, writeSourceCache };
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 };
@@ -0,0 +1,174 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire } from 'node:module';
3
+ import { readContextManifest, removeContextManifest } from './chunk-YQR6E6OV.js';
4
+ import { removePreCommitGuardHook } from './chunk-TUSYOL2O.js';
5
+ import { CONTEXT_PIN_FILENAME } from './chunk-WFSUUUAN.js';
6
+ import { execFileSync } from 'child_process';
7
+ import { existsSync, unlinkSync, lstatSync, readdirSync, rmdirSync, readFileSync, mkdirSync, writeFileSync } from 'fs';
8
+ import { join, dirname, isAbsolute } from 'path';
9
+
10
+ createRequire(import.meta.url);
11
+ var CONTEXT_EXCLUDE_MARKER = "outerlayer context materialization";
12
+ var BEGIN_PREFIX = `# BEGIN ${CONTEXT_EXCLUDE_MARKER}`;
13
+ var END = `# END ${CONTEXT_EXCLUDE_MARKER}`;
14
+ function excludeFilePath(gitCommonDir) {
15
+ return join(gitCommonDir, "info", "exclude");
16
+ }
17
+ function readLines(path) {
18
+ if (!existsSync(path)) return [];
19
+ const content = readFileSync(path, "utf8");
20
+ if (content === "") return [];
21
+ const lines = content.split("\n");
22
+ if (lines[lines.length - 1] === "") lines.pop();
23
+ return lines;
24
+ }
25
+ function writeLines(path, lines) {
26
+ mkdirSync(dirname(path), { recursive: true });
27
+ writeFileSync(path, lines.length ? lines.join("\n") + "\n" : "");
28
+ }
29
+ function findWellFormedBlock(lines) {
30
+ let i = 0;
31
+ while (i < lines.length) {
32
+ if (!lines[i].startsWith(BEGIN_PREFIX)) {
33
+ i++;
34
+ continue;
35
+ }
36
+ const beginIdx = i;
37
+ let endIdx = -1;
38
+ let j = beginIdx + 1;
39
+ for (; j < lines.length; j++) {
40
+ if (lines[j] === END) {
41
+ endIdx = j;
42
+ break;
43
+ }
44
+ if (lines[j].startsWith(BEGIN_PREFIX)) break;
45
+ }
46
+ if (endIdx !== -1) return { beginIdx, endIdx };
47
+ i = j;
48
+ }
49
+ return void 0;
50
+ }
51
+ function removeContextExcludes(gitCommonDir) {
52
+ const path = excludeFilePath(gitCommonDir);
53
+ const lines = readLines(path);
54
+ const block = findWellFormedBlock(lines);
55
+ if (block === void 0) return { changed: false };
56
+ writeLines(path, [...lines.slice(0, block.beginIdx), ...lines.slice(block.endIdx + 1)]);
57
+ return { changed: true };
58
+ }
59
+ function contextExcludesPresent(gitCommonDir) {
60
+ return findWellFormedBlock(readLines(excludeFilePath(gitCommonDir))) !== void 0;
61
+ }
62
+
63
+ // src/context-cleanup.ts
64
+ function hasEarlierCopies(gitCommonDir) {
65
+ return readContextManifest(gitCommonDir) !== void 0 || contextExcludesPresent(gitCommonDir);
66
+ }
67
+ function isCopiedPath(rel) {
68
+ if (isAbsolute(rel) || rel.split("/").includes("..")) return false;
69
+ return rel === "AGENTS.md" || rel.startsWith(".claude/") || rel.startsWith(".outerlayer/");
70
+ }
71
+ function hasSymlinkComponent(root, rel) {
72
+ let current = root;
73
+ for (const segment of rel.split("/")) {
74
+ current = join(current, segment);
75
+ try {
76
+ if (lstatSync(current).isSymbolicLink()) return true;
77
+ } catch {
78
+ return false;
79
+ }
80
+ }
81
+ return false;
82
+ }
83
+ function trackedPaths(repoRoot) {
84
+ try {
85
+ const out = execFileSync("git", ["ls-files", "-z", "--", "AGENTS.md", ".claude", ".outerlayer"], {
86
+ cwd: repoRoot,
87
+ encoding: "utf8",
88
+ stdio: ["ignore", "pipe", "ignore"],
89
+ timeout: 5e3
90
+ });
91
+ return new Set(out.split("\0").filter((path) => path !== ""));
92
+ } catch {
93
+ return void 0;
94
+ }
95
+ }
96
+ function isPin(text) {
97
+ try {
98
+ const value = JSON.parse(text);
99
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
100
+ const { schemaVersion, sha, ...rest } = value;
101
+ return Object.keys(rest).length === 0 && typeof schemaVersion === "number" && typeof sha === "string" && /^[0-9a-f]{40}$/.test(sha);
102
+ } catch {
103
+ return false;
104
+ }
105
+ }
106
+ function pinMayDiffer(repoRoot, args) {
107
+ try {
108
+ execFileSync("git", ["diff", "--quiet", ...args, "--", CONTEXT_PIN_FILENAME], { cwd: repoRoot, stdio: "ignore", timeout: 5e3 });
109
+ return false;
110
+ } catch {
111
+ return true;
112
+ }
113
+ }
114
+ function restorePin(repoRoot) {
115
+ try {
116
+ if (!isPin(readFileSync(join(repoRoot, CONTEXT_PIN_FILENAME), "utf8"))) return false;
117
+ if (pinMayDiffer(repoRoot, ["--cached"]) || !pinMayDiffer(repoRoot, [])) return false;
118
+ execFileSync("git", ["checkout", "--", CONTEXT_PIN_FILENAME], { cwd: repoRoot, stdio: "ignore", timeout: 5e3 });
119
+ return true;
120
+ } catch {
121
+ return false;
122
+ }
123
+ }
124
+ function pruneEmptyDirs(start, root) {
125
+ let current = start;
126
+ while (current !== root && current.startsWith(root)) {
127
+ try {
128
+ if (readdirSync(current).length > 0) return;
129
+ rmdirSync(current);
130
+ } catch {
131
+ return;
132
+ }
133
+ current = dirname(current);
134
+ }
135
+ }
136
+ function cleanupEarlierCopies(input) {
137
+ const { repoRoot, gitCommonDir } = input;
138
+ const result = { removedFiles: [], excludeRemoved: false, guardRemoved: false, pinRestored: false };
139
+ if (!hasEarlierCopies(gitCommonDir)) return result;
140
+ let complete = true;
141
+ try {
142
+ const manifest = readContextManifest(gitCommonDir);
143
+ if (manifest !== void 0) {
144
+ const tracked = trackedPaths(repoRoot);
145
+ if (tracked === void 0) return result;
146
+ const isTracked = (rel) => [...tracked].some((path) => path === rel || rel.startsWith(`${path}/`));
147
+ for (const rel of manifest.files) {
148
+ if (!isCopiedPath(rel) || isTracked(rel) || hasSymlinkComponent(repoRoot, rel)) continue;
149
+ const abs = join(repoRoot, rel);
150
+ if (!existsSync(abs)) continue;
151
+ try {
152
+ unlinkSync(abs);
153
+ result.removedFiles.push(rel);
154
+ pruneEmptyDirs(dirname(abs), repoRoot);
155
+ } catch {
156
+ complete = false;
157
+ }
158
+ }
159
+ }
160
+ } catch {
161
+ return result;
162
+ }
163
+ if (!complete) return result;
164
+ result.pinRestored = restorePin(repoRoot);
165
+ try {
166
+ result.guardRemoved = removePreCommitGuardHook(repoRoot).removed;
167
+ result.excludeRemoved = removeContextExcludes(gitCommonDir).changed;
168
+ removeContextManifest(gitCommonDir);
169
+ } catch {
170
+ }
171
+ return result;
172
+ }
173
+
174
+ export { cleanupEarlierCopies };
@@ -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
- if (found.kind === "none") return run(claude, args, env, cwd, stderr);
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
- const { dir } = found.record;
82
- if (!existsSync(dir)) {
83
- stderr(`outerlayer claude: the control plane of ${found.record.repository} is not at ${dir}, so it cannot be attached
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
- return 1;
88
+ return 1;
89
+ }
90
+ } else {
91
+ const { resolveLaunchPlane } = await import('./control-plane-launch-34LNRJWR.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)) {