@outerlayer/cli 0.19.1 → 0.22.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.
Files changed (146) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +26 -7
  3. package/dist/{agent-setup-AM42SA2D.js → agent-setup-XAJH6MPW.js} +13 -12
  4. package/dist/build-GTMEADQD.js +12 -0
  5. package/dist/build-command-ND2ENDBS.js +50 -0
  6. package/dist/build-info.json +1 -1
  7. package/dist/{builder-C4QNTYMS.js → builder-OAUSTZHL.js} +7 -5
  8. package/dist/{check-W2JGXN3B.js → check-3YHMJQ3P.js} +48 -50
  9. package/dist/{chunk-F2KXHIFI.js → chunk-22DYXLU7.js} +360 -66
  10. package/dist/{chunk-P53VEAOF.js → chunk-2CMJLYV6.js} +1 -1
  11. package/dist/{chunk-FBTGMSQF.js → chunk-2HT2XGJX.js} +16 -9
  12. package/dist/{chunk-S5PCA3SN.js → chunk-2J5JGLW5.js} +1 -1
  13. package/dist/{chunk-R22NZSGA.js → chunk-34XORKFD.js} +9 -9
  14. package/dist/{chunk-QOZKPLVJ.js → chunk-3W333NFO.js} +40 -1
  15. package/dist/{chunk-HOKXGFDR.js → chunk-4JHVPFH6.js} +22 -16
  16. package/dist/{chunk-AMFWYESY.js → chunk-4NM3I3VV.js} +1 -1
  17. package/dist/{chunk-PIZRPNKR.js → chunk-4QKLMNI3.js} +5 -5
  18. package/dist/{chunk-NNLA7LLQ.js → chunk-5OCIHFGE.js} +29 -5
  19. package/dist/{chunk-PSN33ERW.js → chunk-6IO62VJS.js} +3 -3
  20. package/dist/{chunk-7YP7T6GV.js → chunk-7V7KG3YM.js} +2 -2
  21. package/dist/{chunk-QNLX477Q.js → chunk-AEKSX4EY.js} +165 -72
  22. package/dist/{chunk-JHGEBPLE.js → chunk-ATRIVTRE.js} +3 -3
  23. package/dist/{chunk-X5H2WYMB.js → chunk-BLW6GPBZ.js} +1 -1
  24. package/dist/{chunk-MLAAT4S6.js → chunk-C3HKR67W.js} +3 -3
  25. package/dist/{chunk-XZ4H4X5F.js → chunk-C3OVGKVJ.js} +15 -8
  26. package/dist/{chunk-BM63HB2M.js → chunk-EAQSOE62.js} +2 -2
  27. package/dist/{chunk-LW7G5TJB.js → chunk-EXV37PKS.js} +2 -2
  28. package/dist/{chunk-B6SCN5NY.js → chunk-FGW2774C.js} +175 -44
  29. package/dist/{chunk-KYS3TQAG.js → chunk-G2WME4RG.js} +4 -4
  30. package/dist/{chunk-LRG3ZMZD.js → chunk-G6DZCKA6.js} +4 -4
  31. package/dist/chunk-GISNHSYL.js +41 -0
  32. package/dist/{chunk-G2YNJIGF.js → chunk-HCVLP7XA.js} +10 -1
  33. package/dist/{chunk-QEFKA2QD.js → chunk-I66MQDXH.js} +2 -2
  34. package/dist/{chunk-3CWUOFV6.js → chunk-IRBNIRQJ.js} +12 -7
  35. package/dist/{chunk-CG36IONK.js → chunk-JRCSET55.js} +2 -2
  36. package/dist/{chunk-CGGPS7SI.js → chunk-JVB63NIB.js} +5 -5
  37. package/dist/{chunk-M2ZWWTWZ.js → chunk-KDHYLBRR.js} +1 -1
  38. package/dist/{chunk-N2PXGQRL.js → chunk-KIGSGZBB.js} +1 -1
  39. package/dist/{chunk-EAEELQVQ.js → chunk-KOQELWQ6.js} +5 -5
  40. package/dist/{chunk-MTP2QEVO.js → chunk-KPBQYEND.js} +1 -1
  41. package/dist/{chunk-VYAL7PUE.js → chunk-LOB2SUM3.js} +1 -1
  42. package/dist/{chunk-GGOMT6KF.js → chunk-PHHBYAL6.js} +1 -1
  43. package/dist/{chunk-IF2OSI5T.js → chunk-QOALB6ZD.js} +2 -2
  44. package/dist/{chunk-BWSUPRDK.js → chunk-TPKYTORP.js} +1 -1
  45. package/dist/{chunk-XNGMQ27R.js → chunk-UD3EXMKB.js} +2 -2
  46. package/dist/{chunk-7UWVLZXD.js → chunk-USWVXQIH.js} +1 -1
  47. package/dist/{chunk-BQXFBI7T.js → chunk-V7MQKOZY.js} +32 -7
  48. package/dist/{chunk-6X4SQ5MY.js → chunk-V7SAQ645.js} +1 -1
  49. package/dist/{chunk-TWF3RICI.js → chunk-VSUXCMMH.js} +110 -11
  50. package/dist/{chunk-FVMYKL6L.js → chunk-VWLOQ6FI.js} +1 -1
  51. package/dist/{chunk-3ZR7Y23Y.js → chunk-VX74ND77.js} +650 -70
  52. package/dist/{chunk-Z7K3L4FC.js → chunk-W3SWJ2TD.js} +2 -2
  53. package/dist/chunk-WERZMIKA.js +718 -0
  54. package/dist/{chunk-GEMQLBMW.js → chunk-WMHYIBJW.js} +6 -6
  55. package/dist/{chunk-5VML45HH.js → chunk-XCRZTXRL.js} +2 -2
  56. package/dist/{chunk-ECODQ7II.js → chunk-ZFLOGMUC.js} +1 -1
  57. package/dist/chunk-ZNPE7FW5.js +137 -0
  58. package/dist/claude-launcher-4BQNXYAF.js +267 -0
  59. package/dist/{cli-EXX2R73G.js → cli-NMGVZQPB.js} +189 -119
  60. package/dist/{command-ZQNEPDS6.js → command-GE62AJZY.js} +32 -34
  61. package/dist/{config-CLSGABD5.js → config-7Q52COZ3.js} +3 -2
  62. package/dist/{connect-cmd-UNYKGDAL.js → connect-cmd-ZFOK6HEL.js} +5 -5
  63. package/dist/{context-cleanup-CHEWNYU6.js → context-cleanup-DSA3HGQU.js} +1 -1
  64. package/dist/{control-plane-launch-34LNRJWR.js → control-plane-launch-SZTE4TUS.js} +62 -28
  65. package/dist/{dist-WO7NOJNG.js → dist-7IH56ELA.js} +1 -1
  66. package/dist/{docker-BFU3AQGY.js → docker-2OVBKVRK.js} +7 -7
  67. package/dist/{doctor-DHUM5DBB.js → doctor-3SQGZVYP.js} +35 -36
  68. package/dist/{emit-artifact-cmd-XBHM647X.js → emit-artifact-cmd-R42BE6ID.js} +19 -18
  69. package/dist/{emit-cmd-W55AEBCA.js → emit-cmd-3W5IO5ET.js} +3 -3
  70. package/dist/{emit-criteria-cmd-CRTYEF7D.js → emit-criteria-cmd-MQZE7W4Y.js} +52 -16
  71. package/dist/{emit-finding-cmd-7JHVRYOP.js → emit-finding-cmd-ZS5JEGGM.js} +13 -12
  72. package/dist/{emit-result-cmd-5NZMLCJK.js → emit-result-cmd-FUE3DXBW.js} +19 -18
  73. package/dist/{emit-step-cmd-347XNGPQ.js → emit-step-cmd-T7PRA44X.js} +14 -13
  74. package/dist/{exec-client-7UMESIE2.js → exec-client-YIDTWXMZ.js} +4 -3
  75. package/dist/{governing-source-HAA4OW57.js → governing-source-TORXL4I4.js} +19 -18
  76. package/dist/{guest-init-KPBQOFE5.js → guest-init-TO6HAWIT.js} +4 -3
  77. package/dist/{hook-fast-RL5E5OXE.js → hook-fast-WFB2ZMRB.js} +2 -2
  78. package/dist/host-key-2LXQDSBO.js +9 -0
  79. package/dist/{import-capture-cmd-TK4XY7RD.js → import-capture-cmd-Q56DDZVO.js} +1 -1
  80. package/dist/index.js +5 -5
  81. package/dist/init-2CRAVIUU.js +52 -0
  82. package/dist/{init-V6FOMD2V.js → init-AHDZCMDC.js} +32 -33
  83. package/dist/{init-cmd-Z4O4PPLZ.js → init-cmd-IXDL2ZSL.js} +25 -23
  84. package/dist/{init-update-7DVAKWW3.js → init-update-YB3PODDH.js} +69 -24
  85. package/dist/{install-4SEFIIW2.js → install-CZUIW2AF.js} +5 -4
  86. package/dist/{install-cmd-QDOTR4OM.js → install-cmd-Q7RJGFUO.js} +6 -5
  87. package/dist/{login-browser-DX35MARZ.js → login-browser-BN5UKPHS.js} +3 -3
  88. package/dist/{logout-cmd-5V5MMBSY.js → logout-cmd-RZFWTNYD.js} +2 -2
  89. package/dist/{logs-AMLKC3VP.js → logs-RJPYTVQE.js} +3 -2
  90. package/dist/loop-ZDW6TRAA.js +75 -0
  91. package/dist/machine-JCOHLASP.js +47 -0
  92. package/dist/{mcp-install-cmd-GGWB3JJ2.js → mcp-install-cmd-GD4QUP7Z.js} +2 -2
  93. package/dist/{mcp-serve-cmd-N3UTY6EE.js → mcp-serve-cmd-IULQPVHL.js} +6 -5
  94. package/dist/{paths-7XP63OAX.js → paths-N3LU4O2Z.js} +3 -2
  95. package/dist/pending-GRCV3ZR4.js +9 -0
  96. package/dist/{pidfile-3DM4OBKO.js → pidfile-IF3TCL5A.js} +4 -3
  97. package/dist/receive-files-T2BIUBQL.js +254 -0
  98. package/dist/{record-3WP6V2K5.js → record-73PQE77B.js} +4 -3
  99. package/dist/relay-PSZ4LGMW.js +210 -0
  100. package/dist/relay-protocol-K7KP2SPI.js +6 -0
  101. package/dist/{runner-env-FRZFFHDF.js → runner-env-LDOBJESN.js} +6 -5
  102. package/dist/runner-identity-RWCBTY2A.js +14 -0
  103. package/dist/{runner-key-5FOWCW7J.js → runner-key-HMYLP6WN.js} +32 -33
  104. package/dist/{session-sender-U2BBUWNO.js → session-sender-2G25JYHI.js} +20 -19
  105. package/dist/{spec-cmd-FVLJOFGC.js → spec-cmd-LBVXM6XS.js} +13 -12
  106. package/dist/{starter-pack-6LQVLBIA.js → starter-pack-5EQYGSJF.js} +2 -2
  107. package/dist/{status-BINH7MBG.js → status-QZB2GWXJ.js} +36 -38
  108. package/dist/{statusline-fast-KN3BX67H.js → statusline-fast-2OK3DVAA.js} +2 -2
  109. package/dist/{sync-cmd-VXOUFS4I.js → sync-cmd-TQQIR4PN.js} +19 -18
  110. package/dist/{watch-OH645CV2.js → watch-4JES4PCS.js} +19 -18
  111. package/dist/{work-claim-cmd-ZRPSHMPT.js → work-claim-cmd-XG6O7B63.js} +17 -16
  112. package/dist/{work-cmd-5I3J2XQQ.js → work-cmd-L6WMPAA2.js} +13 -12
  113. package/dist/{work-comment-cmd-UCCPWUSR.js → work-comment-cmd-SNTDCPGH.js} +13 -12
  114. package/dist/{work-logs-cmd-7352CJPG.js → work-logs-cmd-3S7IAVII.js} +13 -12
  115. package/dist/{work-open-pr-cmd-LSH4VHJM.js → work-open-pr-cmd-E3WMO5XT.js} +15 -14
  116. package/dist/{work-pr-cmd-H4OQR26N.js → work-pr-cmd-22T6FG4T.js} +14 -13
  117. package/dist/work-stop-cmd-WR7ESS4Z.js +53 -0
  118. package/package.json +2 -2
  119. package/skill-pack/maintained/outerlayer-build/SKILL.md +347 -0
  120. package/skill-pack/{template/build → maintained/outerlayer-build}/references/evidence.md +2 -2
  121. package/skill-pack/{template/build → maintained/outerlayer-build}/references/release.md +4 -4
  122. package/skill-pack/{template/build → maintained/outerlayer-build}/references/review-loop.md +3 -1
  123. package/skill-pack/shipped.json +2 -0
  124. package/skill-pack/template/build/SKILL.md +4 -253
  125. package/skill-pack/validators/acceptance-criteria.yaml +1 -1
  126. package/dist/build-TQ6X5PYN.js +0 -12
  127. package/dist/chunk-3UZTIRLF.js +0 -320
  128. package/dist/chunk-CX22S5BA.js +0 -45
  129. package/dist/chunk-LLM3I5YU.js +0 -89
  130. package/dist/chunk-SADUQSO4.js +0 -50
  131. package/dist/chunk-VMJPFQNE.js +0 -261
  132. package/dist/claude-launcher-J5M44PFS.js +0 -115
  133. package/dist/host-key-U4B5QETR.js +0 -8
  134. package/dist/init-XG47KCI4.js +0 -53
  135. package/dist/loop-TPUYUMSY.js +0 -77
  136. package/dist/machine-TRHBT5NE.js +0 -48
  137. package/dist/pending-532ABZYC.js +0 -8
  138. package/dist/relay-L76HDX72.js +0 -46
  139. package/dist/{chunk-YVZJ6GKF.js → chunk-DIB2WLBL.js} +1 -1
  140. package/dist/{chunk-GOSFARMS.js → chunk-F35VMF5M.js} +1 -1
  141. package/dist/{chunk-DSF2FWAZ.js → chunk-IZSVXRDR.js} +1 -1
  142. /package/skill-pack/{template/build → maintained/outerlayer-build}/references/agent-briefs.md +0 -0
  143. /package/skill-pack/{template/build → maintained/outerlayer-build}/references/criteria-judge.md +0 -0
  144. /package/skill-pack/{template/build → maintained/outerlayer-build}/references/review-briefs.md +0 -0
  145. /package/skill-pack/{template/build → maintained/outerlayer-build}/scripts/criterion-citations.mjs +0 -0
  146. /package/skill-pack/{template/build → maintained/outerlayer-build}/scripts/record-criteria.mjs +0 -0
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { EXEC_PORT } from './chunk-X5H2WYMB.js';
3
+ import { EXEC_PORT } from './chunk-BLW6GPBZ.js';
4
4
  import { createConnection } from 'net';
5
5
 
6
6
  createRequire(import.meta.url);
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { fetchFactories, selectFactory, saveFactoryConnection, autoConnectedLine } from './chunk-CG36IONK.js';
4
- import { resolveRepoIdentity } from './chunk-QNLX477Q.js';
3
+ import { fetchFactories, selectFactory, saveFactoryConnection, autoConnectedLine } from './chunk-JRCSET55.js';
5
4
  import { resolveGatewayCredentials } from './chunk-NTRCK4NH.js';
6
5
  import { findGitDirs, readRepoConnection } from './chunk-BJ3KTMDH.js';
6
+ import { resolveRepoIdentity } from './chunk-AEKSX4EY.js';
7
7
  import { cliInvocation } from './chunk-CRB3POP4.js';
8
8
  import { homeFromEnv } from './chunk-VNVZDWO3.js';
9
9
  import { openSync, fstatSync, readSync, closeSync } from 'fs';
@@ -4,6 +4,6 @@ import { createRequire } from 'node:module';
4
4
  createRequire(import.meta.url);
5
5
 
6
6
  // src/runner/protocol.ts
7
- var RUNNER_PROTOCOL = 20;
7
+ var RUNNER_PROTOCOL = 22;
8
8
 
9
9
  export { RUNNER_PROTOCOL };
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { EXEC_PORT } from './chunk-X5H2WYMB.js';
3
+ import { EXEC_PORT } from './chunk-BLW6GPBZ.js';
4
4
  import { startTimeOf } from './chunk-JBJTC3UU.js';
5
- import { RELAY_PORT } from './chunk-BQXFBI7T.js';
5
+ import { RELAY_PORT } from './chunk-V7MQKOZY.js';
6
6
  import { spawn, spawnSync } from 'child_process';
7
7
  import { writeFileSync, chmodSync, mkdirSync } from 'fs';
8
8
 
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { skillDir, FORMER_MAINTAINED_NAMES, isMaintainedCopy } from './chunk-NNLA7LLQ.js';
3
+ import { skillDir, FORMER_MAINTAINED_NAMES, isMaintainedCopy } from './chunk-5OCIHFGE.js';
4
4
  import { cliInvocation } from './chunk-CRB3POP4.js';
5
5
  import { emitTree, ALL_TARGET_IDS, classifyTree } from './chunk-WFSUUUAN.js';
6
6
  import { readFileSync, existsSync, unlinkSync, rmdirSync, readdirSync } from 'fs';
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
+ import { TARGET_TUNNEL, TARGET_LEASE, destinationTarget } from './chunk-GISNHSYL.js';
3
4
  import { existsSync, unlinkSync, chmodSync } from 'fs';
4
5
  import { request as request$1, createServer } from 'http';
5
6
  import { request } from 'https';
@@ -293,15 +294,20 @@ async function startDestination(input) {
293
294
  for (const socket of sockets) socket.destroy();
294
295
  await Promise.all(listeners.map((listener) => new Promise((resolve) => listener.close(() => resolve()))));
295
296
  };
296
- return { ...served, close };
297
+ return { ...served, acceptStream: (stream) => void server.emit("connection", stream), close };
297
298
  }
298
299
  async function startBuildServices(input) {
300
+ const streamed = input.serve === "stream";
299
301
  const tunnel = await input.startTunnel(join(input.buildDir, "tunnel.sock"), {
300
302
  ...input.tunnelOptions,
303
+ ...streamed ? { socket: false } : {},
301
304
  ...input.allowHosts === void 0 ? {} : { allowHosts: input.allowHosts },
302
305
  recordPath: join(input.jobDir, "tunnel.json")
303
306
  });
304
307
  const servers = [];
308
+ const targets = /* @__PURE__ */ new Map();
309
+ if (streamed) targets.set(TARGET_TUNNEL, (stream) => tunnel.acceptStream(stream));
310
+ if (streamed && input.lease !== void 0) targets.set(TARGET_LEASE, (stream) => input.lease.accept(stream));
305
311
  const closeAll = async () => {
306
312
  await Promise.all(servers.map((s) => s.close()));
307
313
  await tunnel.close();
@@ -314,30 +320,39 @@ async function startBuildServices(input) {
314
320
  for (const [index, destination] of input.destinations.entries()) {
315
321
  const server = await startDestination({
316
322
  destination,
317
- ...input.serve === "tcp" ? {} : { socketPath: destinationSocketPath(input.buildDir, index) },
318
- ...input.serve === "socket" ? {} : { port: input.ports?.destinations?.[index] ?? 0 },
323
+ ...input.serve === "tcp" || streamed ? {} : { socketPath: destinationSocketPath(input.buildDir, index) },
324
+ ...input.serve === "socket" || streamed ? {} : { port: input.ports?.destinations?.[index] ?? 0 },
319
325
  hostEnv: input.hostEnv,
320
326
  onUsed: (name) => tunnel.destinationUsed(name),
321
327
  ...input.destinationOptions
322
328
  });
323
329
  servers.push(server);
330
+ targets.set(destinationTarget(index), (stream) => server.acceptStream(stream));
324
331
  if (server.port !== void 0) destinationPorts.push(server.port);
325
332
  }
326
333
  const builtIns = input.builtIns === void 0 ? [] : builtInDestinations({ gatewayUrl: input.builtIns.gatewayUrl, itemKey: input.builtIns.itemKey, hostEnv: input.hostEnv, claudeUpstream: input.builtIns.claudeUpstream });
327
334
  for (const builtIn of builtIns) {
328
335
  const server = await startDestination({
329
336
  destination: builtIn.destination,
330
- ...input.serve === "tcp" ? {} : { socketPath: join(input.buildDir, builtIn.socket) },
331
- ...input.serve === "socket" ? {} : { port: input.ports?.builtIns?.[builtIn.destination.name] ?? 0 },
337
+ ...input.serve === "tcp" || streamed ? {} : { socketPath: join(input.buildDir, builtIn.socket) },
338
+ ...input.serve === "socket" || streamed ? {} : { port: input.ports?.builtIns?.[builtIn.destination.name] ?? 0 },
332
339
  hostEnv: builtIn.hostEnv,
333
340
  drop: builtIn.drop,
334
341
  onUsed: (name) => tunnel.destinationUsed(name),
335
342
  ...input.destinationOptions
336
343
  });
337
344
  servers.push(server);
345
+ targets.set(builtIn.destination.name, (stream) => server.acceptStream(stream));
338
346
  if (server.port !== void 0) builtInPorts[builtIn.destination.name] = server.port;
339
347
  }
340
- return { ...tunnel, proxyPort, destinationPorts, builtInPorts, close: closeAll };
348
+ return { ...tunnel, streams: {
349
+ accept: (target, stream) => {
350
+ const serve = targets.get(target);
351
+ if (serve === void 0) return false;
352
+ serve(stream);
353
+ return true;
354
+ }
355
+ }, proxyPort, destinationPorts, builtInPorts, close: closeAll };
341
356
  } catch (err) {
342
357
  await closeAll();
343
358
  throw err;
@@ -413,6 +428,16 @@ function parseClaimedRepositories(value) {
413
428
  const at = primaryAt === -1 ? 0 : primaryAt;
414
429
  return [{ ...parsed[at], primary: true }, ...parsed.filter((_, index) => index !== at).map((entry) => ({ ...entry, primary: false }))];
415
430
  }
431
+ function parseUnreachable(value) {
432
+ if (!Array.isArray(value)) return [];
433
+ const entries = [];
434
+ for (const entry of value) {
435
+ if (typeof entry !== "object" || entry === null) continue;
436
+ const { repository, reason } = entry;
437
+ if (typeof repository === "string" && repository !== "" && typeof reason === "string") entries.push({ repository, reason });
438
+ }
439
+ return entries;
440
+ }
416
441
  function repositoriesOf(input) {
417
442
  if (input.repositories !== void 0 && input.repositories.length > 0) return input.repositories;
418
443
  if (input.repository === void 0 || input.repository === null || input.repository === "" || input.branch === void 0) return [];
@@ -620,4 +645,4 @@ function withTunnelRecord(environment, record, onlyWhenUsed = false) {
620
645
  };
621
646
  }
622
647
 
623
- export { AGENT_CREDENTIAL_MISSING, BUILD_HOME, BUILT_IN_NAMES, CHECKOUT_DIR, CLAUDE_CREDENTIAL_VARIABLES, CLAUDE_PORT, CLAUDE_SOCKET, DESTINATION_BASE_PORT, EVAL_INPUT_DIR, GATEWAY_PORT, GATEWAY_SOCKET, JOB_MOUNT, RELAY_PORT, authorEnvironment, buildEnvironment, builtInEnvironment, checkEnvironment, checkoutPath, claudeCredential, commitIdentityRecord, containerLocalAddress, destinationEnvironment, headerVariables, isRefusedInConfig, isReservedVariable, lifecycleWorkdir, parseClaimIdentity, parseClaimedRepositories, parseIsolation, primaryOf, proxyEnvironment, repositoriesOf, repositoryPath, resolveDestinations, sharedUserEnvironment, startBuildServices, tokenHeader, withGitConfig, withHooksPath, withProxyWarningHidden, withTokenHeader, withTunnelRecord };
648
+ export { AGENT_CREDENTIAL_MISSING, BUILD_HOME, BUILT_IN_NAMES, CHECKOUT_DIR, CLAUDE_CREDENTIAL_VARIABLES, CLAUDE_PORT, CLAUDE_SOCKET, DESTINATION_BASE_PORT, EVAL_INPUT_DIR, GATEWAY_PORT, GATEWAY_SOCKET, JOB_MOUNT, RELAY_PORT, authorEnvironment, buildEnvironment, builtInEnvironment, checkEnvironment, checkoutPath, claudeCredential, commitIdentityRecord, containerLocalAddress, destinationEnvironment, headerVariables, isRefusedInConfig, isReservedVariable, lifecycleWorkdir, parseClaimIdentity, parseClaimedRepositories, parseIsolation, parseUnreachable, primaryOf, proxyEnvironment, repositoriesOf, repositoryPath, resolveDestinations, sharedUserEnvironment, startBuildServices, tokenHeader, withGitConfig, withHooksPath, withProxyWarningHidden, withTokenHeader, withTunnelRecord };
@@ -1,7 +1,7 @@
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';
3
4
  import { C } from './chunk-ANPNT6PM.js';
4
- import { resolvePackRoot, loadTemplateFiles, loadMaintainedFiles, TEMPLATE_SKILLS, skillDir, writeMaintainedFiles, MAINTAINED_SKILLS } from './chunk-NNLA7LLQ.js';
5
5
  import { cliInvocation } from './chunk-CRB3POP4.js';
6
6
  import { resolvePackageVersion } from './chunk-RA3O54FC.js';
7
7
  import { readFileSync, existsSync, mkdirSync, writeFileSync } from 'fs';
@@ -1,14 +1,16 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { mcpTargetPath, INIT_STDIO_ENTRY, INIT_DOCS_ENTRY, DOCS_MCP_SERVER_NAME } from './chunk-YVZJ6GKF.js';
4
- import { POLICY_CONTENT, VALIDATOR_FILES, VALIDATORS_DIR, POLICY_PATH } from './chunk-6X4SQ5MY.js';
5
3
  import { findGitDirs } from './chunk-BJ3KTMDH.js';
6
- import { resolvePackRoot, loadTemplateFiles, skillDir } from './chunk-NNLA7LLQ.js';
4
+ import { mcpTargetPath, INIT_STDIO_ENTRY, INIT_DOCS_ENTRY, DOCS_MCP_SERVER_NAME } from './chunk-DIB2WLBL.js';
5
+ import { POLICY_CONTENT, VALIDATOR_FILES, VALIDATORS_DIR, POLICY_PATH } from './chunk-V7SAQ645.js';
6
+ import { resolvePackRoot, skillDir, namesCore, loadTemplateFiles, TEMPLATE_SKILLS } from './chunk-5OCIHFGE.js';
7
7
  import { cliInvocation } from './chunk-CRB3POP4.js';
8
+ import { hasSymlinkComponent } from './chunk-W3SWJ2TD.js';
8
9
  import { cloneIsGoverned } from './chunk-YQR6E6OV.js';
10
+ import { emitTree, ALL_TARGET_IDS, classifyTree, splitRawFile } from './chunk-WFSUUUAN.js';
9
11
  import { createHash } from 'crypto';
10
12
  import { existsSync, readFileSync } from 'fs';
11
- import { join } from 'path';
13
+ import { join, dirname } from 'path';
12
14
 
13
15
  createRequire(import.meta.url);
14
16
  var SHIPPED_MANIFEST = "shipped.json";
@@ -25,8 +27,9 @@ function currentStarterFiles(packRoot = resolvePackRoot(), policy = POLICY_CONTE
25
27
  });
26
28
  return [...templates, ...validators, { path: POLICY_PATH, content: policy }];
27
29
  }
30
+ var TEMPLATE_VERSION = /(Copied once from the default template by outerlayer init) [^\s;]+(; never overwritten\.)/;
28
31
  function contentHash(content) {
29
- return createHash("sha256").update(content.replace(/\r\n/g, "\n")).digest("hex");
32
+ return createHash("sha256").update(content.replace(/\r\n/g, "\n").replace(TEMPLATE_VERSION, "$1$2")).digest("hex");
30
33
  }
31
34
  function readShippedManifest(packRoot = resolvePackRoot()) {
32
35
  const path = join(packRoot, SHIPPED_MANIFEST);
@@ -95,13 +98,31 @@ function mcpItems(root) {
95
98
  return { ...base, state: "edited" };
96
99
  });
97
100
  }
101
+ function retiredFiles(root, shipped, manifest) {
102
+ if (!manifest.ok) return [];
103
+ const current = new Set(shipped.map((f) => f.path));
104
+ const prefixes = TEMPLATE_SKILLS.map((skill) => `${skillDir(skill)}/`);
105
+ const retired = [];
106
+ for (const [path, hashes] of manifest.files) {
107
+ if (current.has(path) || !prefixes.some((prefix) => path.startsWith(prefix))) continue;
108
+ const abs = join(root, path);
109
+ if (!existsSync(abs) || hasSymlinkComponent(root, path)) continue;
110
+ try {
111
+ retired.push({ path, state: hashes.has(contentHash(readFileSync(abs, "utf8"))) ? "unedited" : "edited" });
112
+ } catch {
113
+ }
114
+ }
115
+ return retired.sort((a, b) => a.path.localeCompare(b.path));
116
+ }
98
117
  function inspectStarterFiles(root, opts = {}) {
99
118
  const packRoot = opts.packRoot ?? resolvePackRoot();
100
119
  const manifest = readShippedManifest(packRoot);
101
- const files = currentStarterFiles(packRoot).map(
102
- (file) => ({ kind: "file", path: file.path, state: fileState(root, file, manifest), file })
103
- );
104
- return { items: [...files, ...mcpItems(root)], manifest: manifest.ok ? "ok" : manifest.problem };
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 };
105
126
  }
106
127
  function itemLabel(item) {
107
128
  return item.kind === "file" ? item.path : `${item.path} "${item.server}" server`;
@@ -140,17 +161,19 @@ function checkStarterFiles(cwd, opts = {}) {
140
161
  const missing = by("missing");
141
162
  const edited = by("edited");
142
163
  const unreadable = by("unreadable");
164
+ const retired = report.retired.filter((f) => f.state === "unedited");
143
165
  const parts = [];
144
166
  if (current.length > 0) parts.push(`${current.length} current`);
145
167
  if (outdated.length > 0) parts.push(`outdated and unedited: ${shownPaths(outdated, report.items).join(", ")}`);
146
168
  if (missing.length > 0) parts.push(`missing: ${shownPaths(missing, report.items).join(", ")}`);
169
+ if (retired.length > 0) parts.push(`no longer shipped, unedited: ${retired.map((f) => f.path).join(", ")}`);
147
170
  if (edited.length > 0) parts.push(`edited by you, left as they are: ${edited.map(itemLabel).join(", ")}`);
148
171
  if (unreadable.length > 0) parts.push(`${unreadable[0].path} is not valid JSON, so its servers were not read`);
149
172
  if (report.manifest !== "ok") {
150
173
  parts.push(`this CLI's record of earlier versions is ${report.manifest}, so an outdated file cannot be told from an edited one`);
151
174
  }
152
175
  const mcpOutdated = outdated.some((i) => i.kind === "mcp" && i.server === "outerlayer");
153
- const actionable = outdated.length + missing.length > 0;
176
+ const actionable = outdated.length + missing.length + retired.length > 0;
154
177
  const compare = edited.length > 0 ? ` Compare an edited file with this CLI's version: \`${UPDATE} --dry-run\`.` : "";
155
178
  if (!actionable && report.manifest === "ok") {
156
179
  return { checks: [{ name: NAME, status: "pass", detail: parts.join("; ") + (compare === "" ? "" : `.${compare}`) }], mcpOutdated };
@@ -158,5 +181,81 @@ function checkStarterFiles(cwd, opts = {}) {
158
181
  const fix = actionable ? `Run \`${UPDATE}\` to update the outdated files and write the missing ones. It never changes a file you edited.${compare}` : "Reinstall the CLI: `npm install -g @outerlayer/cli`, or run it with `npx -y @outerlayer/cli`.";
159
182
  return { checks: [{ name: NAME, status: "warn", detail: parts.join("; "), fix }], mcpOutdated };
160
183
  }
184
+ var BUILD_PHASES = ["Intake", "Criteria", "Implement", "Review", "Pull request", "Evidence"];
185
+ var CHANGES_HEADING = "## Changes for this repository";
186
+ var NAME2 = "Build skill";
187
+ function changeHeadings(text) {
188
+ const lines = text.split(/\r?\n/);
189
+ const start = lines.findIndex((line) => line.trim() === CHANGES_HEADING);
190
+ if (start === -1) return [];
191
+ const headings = [];
192
+ for (const line of lines.slice(start + 1)) {
193
+ if (/^## /.test(line)) break;
194
+ const match = /^### (.+?)\s*$/.exec(line);
195
+ if (match) headings.push(match[1]);
196
+ }
197
+ return headings;
198
+ }
199
+ function skillsFolders() {
200
+ const probe = `${skillDir("probe")}/SKILL.md`;
201
+ const compiled = emitTree({
202
+ entries: classifyTree([probe]).entries,
203
+ contents: /* @__PURE__ */ new Map([[probe, "---\nname: probe\ndescription: probe\n---\n"]]),
204
+ assetPaths: [],
205
+ targets: [...ALL_TARGET_IDS]
206
+ });
207
+ return [...new Set(compiled.files.map((file) => dirname(dirname(file.path))))].sort();
208
+ }
209
+ function shortBuild() {
210
+ const file = loadTemplateFiles().find((f) => f.path === `${skillDir("build")}/SKILL.md`);
211
+ if (file === void 0) return "";
212
+ return splitRawFile(file.content).body.split("\n").filter((line) => !line.startsWith("<!--")).join("\n").trim();
213
+ }
214
+ var read = (abs) => {
215
+ try {
216
+ return readFileSync(abs, "utf8");
217
+ } catch {
218
+ return void 0;
219
+ }
220
+ };
221
+ function checkBuildSkill(repoRoot) {
222
+ const folders = [".outerlayer/skills", ...skillsFolders()];
223
+ const source = `${folders[0]}/build/SKILL.md`;
224
+ const builds = (existsSync(join(repoRoot, source)) ? [source] : folders.slice(1).map((f) => `${f}/build/SKILL.md`)).map((path) => ({ path, text: read(join(repoRoot, path)) })).filter((b) => b.text !== void 0);
225
+ const checks = [];
226
+ const detached = builds.filter((b) => !namesCore(b.text));
227
+ if (detached.length > 0) {
228
+ checks.push({
229
+ name: NAME2,
230
+ status: "warn",
231
+ detail: `${detached.map((b) => b.path).join(", ")} does not name outerlayer-build, so it gets no updates from the core`,
232
+ fix: `Move to the short build, and put your own changes under the name of the phase each applies to:
233
+
234
+ ${shortBuild()}`
235
+ });
236
+ }
237
+ for (const build of builds.filter((b) => namesCore(b.text))) {
238
+ const unknown = changeHeadings(build.text).filter((heading) => !BUILD_PHASES.includes(heading));
239
+ if (unknown.length === 0) continue;
240
+ checks.push({
241
+ name: NAME2,
242
+ status: "warn",
243
+ detail: `${build.path} has ${unknown.map((h) => `"${h}"`).join(", ")} under "Changes for this repository", which matches no phase`,
244
+ fix: `Rename each heading to a phase: ${BUILD_PHASES.join(", ")}.`
245
+ });
246
+ }
247
+ const lacking = folders.filter(
248
+ (folder) => namesCore(read(join(repoRoot, folder, "build", "SKILL.md")) ?? "") && !existsSync(join(repoRoot, folder, "outerlayer-build", "SKILL.md"))
249
+ );
250
+ if (lacking.length > 0) {
251
+ checks.push({
252
+ name: NAME2,
253
+ status: "warn",
254
+ detail: `${lacking.join(", ")} holds build with no outerlayer-build beside it`,
255
+ fix: `Run \`${cliInvocation()} context emit\` to write outerlayer-build, then commit.`
256
+ });
257
+ }
258
+ return checks;
259
+ }
161
260
 
162
- export { canonical, checkStarterFiles, contextIsGoverned, inspectStarterFiles };
261
+ export { canonical, checkBuildSkill, checkStarterFiles, contentHash, contextIsGoverned, inspectStarterFiles, readShippedManifest, skillsFolders };
@@ -2,7 +2,7 @@
2
2
  import { createRequire } from 'node:module';
3
3
  import { readCloudConfig, cloudConfigPath } from './chunk-EABW6AJQ.js';
4
4
  import { homeFromEnv } from './chunk-VNVZDWO3.js';
5
- import { signRunnerRequest, signerFor } from './chunk-M2ZWWTWZ.js';
5
+ import { signRunnerRequest, signerFor } from './chunk-KDHYLBRR.js';
6
6
 
7
7
  createRequire(import.meta.url);
8
8