@outerlayer/cli 0.17.0 → 0.18.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 (144) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/README.md +15 -0
  3. package/dist/agent-setup-RBTEACYU.js +28 -0
  4. package/dist/{artifact-link-cmd-2F47LT7F.js → artifact-link-cmd-AVM2EKTV.js} +4 -3
  5. package/dist/{build-BG2YENGK.js → build-TQ6X5PYN.js} +5 -4
  6. package/dist/build-info.json +1 -1
  7. package/dist/{builder-2D3WSOOY.js → builder-DUI2ZH2H.js} +5 -6
  8. package/dist/{check-5XE7XMC4.js → check-5C4YDZYV.js} +53 -50
  9. package/dist/{chunk-R7PF5OOU.js → chunk-3CWUOFV6.js} +21 -14
  10. package/dist/{chunk-G5NPRL2K.js → chunk-3OFZM4X6.js} +548 -68
  11. package/dist/{chunk-2MNPHL23.js → chunk-47TTLEDX.js} +6 -5
  12. package/dist/{chunk-PLMTLGYH.js → chunk-52NC2FIU.js} +4 -3
  13. package/dist/chunk-6CHIYEZZ.js +564 -0
  14. package/dist/{chunk-TI7B7UEO.js → chunk-AMFWYESY.js} +1 -1
  15. package/dist/{chunk-YRYMNBGQ.js → chunk-ANPNT6PM.js} +2 -1
  16. package/dist/{chunk-YU3VKZ5F.js → chunk-B3UKB46N.js} +6 -6
  17. package/dist/{chunk-JXYVA45C.js → chunk-BMYGAGBJ.js} +1050 -304
  18. package/dist/{chunk-4Q7OMKAT.js → chunk-BQXFBI7T.js} +81 -5
  19. package/dist/chunk-CRB3POP4.js +34 -0
  20. package/dist/{chunk-F47JBIAW.js → chunk-DSF2FWAZ.js} +2 -1
  21. package/dist/{chunk-N5FOE5PS.js → chunk-ECODQ7II.js} +4 -33
  22. package/dist/{chunk-NBGDBTO2.js → chunk-ESC6UR76.js} +6 -5
  23. package/dist/{chunk-HHJDN6AU.js → chunk-ESVW4MJY.js} +1 -1
  24. package/dist/{chunk-42ZI52JW.js → chunk-F4XSVQJ4.js} +4 -3
  25. package/dist/{chunk-LWSJQJC6.js → chunk-FUB7LRUE.js} +7 -7
  26. package/dist/chunk-G2YNJIGF.js +44 -0
  27. package/dist/{chunk-QKFB4K7X.js → chunk-GGOMT6KF.js} +1 -1
  28. package/dist/{chunk-VQYBXPI7.js → chunk-GOBOJMOJ.js} +5 -5
  29. package/dist/{chunk-N6LURUEF.js → chunk-GOSFARMS.js} +1 -1
  30. package/dist/chunk-JBJTC3UU.js +35 -0
  31. package/dist/{chunk-NWQTTSBB.js → chunk-JF42URPU.js} +16 -15
  32. package/dist/{chunk-ADJRGVZC.js → chunk-KDVIU23F.js} +1 -1
  33. package/dist/{chunk-S3NYLI2P.js → chunk-KK4VBOH6.js} +93 -37
  34. package/dist/{chunk-KMDLFI4P.js → chunk-L2USZT6T.js} +1 -1
  35. package/dist/{chunk-WTE3MQML.js → chunk-LXAY4A2G.js} +3 -12
  36. package/dist/{chunk-V7NIVOFD.js → chunk-M2ZWWTWZ.js} +1 -1
  37. package/dist/{chunk-ERI5GBNI.js → chunk-MLAAT4S6.js} +3 -3
  38. package/dist/{chunk-POJMEEJJ.js → chunk-MNTSH4CL.js} +1 -1
  39. package/dist/{chunk-WUYTWNMA.js → chunk-MQJSXHV7.js} +1 -1
  40. package/dist/{chunk-O765JR4W.js → chunk-MTP2QEVO.js} +1 -1
  41. package/dist/{chunk-ZM2IMMYN.js → chunk-N2PXGQRL.js} +9 -1
  42. package/dist/{chunk-J5M7BSJQ.js → chunk-N3CUDFCW.js} +9 -3
  43. package/dist/{chunk-4KSQKQXE.js → chunk-NACDBXUG.js} +19 -15
  44. package/dist/{chunk-ONKJUM6R.js → chunk-NL4XPC7W.js} +1 -1
  45. package/dist/{chunk-WVUIRTWA.js → chunk-QQM2UJ6T.js} +31 -26
  46. package/dist/{chunk-KG5ECZGJ.js → chunk-RAZTWYZN.js} +10 -9
  47. package/dist/{chunk-4NPZVMJU.js → chunk-S26M3YBJ.js} +60 -4
  48. package/dist/{chunk-UGP76IZ5.js → chunk-S5PCA3SN.js} +1 -1
  49. package/dist/{chunk-3NSNIIBE.js → chunk-S76AYB4M.js} +17 -16
  50. package/dist/{chunk-RMWLBUCJ.js → chunk-SADUQSO4.js} +1 -1
  51. package/dist/{chunk-OZGHL5Y5.js → chunk-SWCTGCSC.js} +2 -2
  52. package/dist/{chunk-GQD22KKN.js → chunk-T2Q7ISPE.js} +2 -1
  53. package/dist/{chunk-C5Y5ZJJZ.js → chunk-T4Y6SCG3.js} +5 -4
  54. package/dist/{chunk-BWQ66M6N.js → chunk-ULSIJGLS.js} +45 -13
  55. package/dist/{chunk-NNRTPG7X.js → chunk-UYOYTKE2.js} +4 -4
  56. package/dist/{chunk-PTW6W5NR.js → chunk-VYAL7PUE.js} +1 -1
  57. package/dist/{chunk-YZ5F4PIS.js → chunk-W5VPCONO.js} +146 -247
  58. package/dist/{chunk-6Y5RUTHO.js → chunk-WBT5X3NH.js} +5 -4
  59. package/dist/{chunk-RLYZLUQ7.js → chunk-WGAUY5LE.js} +2 -2
  60. package/dist/{chunk-RSNSZ2LJ.js → chunk-X5H2WYMB.js} +1 -1
  61. package/dist/{chunk-OHVJA253.js → chunk-X5N6KC6V.js} +47 -29
  62. package/dist/{chunk-22RMZBGW.js → chunk-XGP3VYOG.js} +1 -1
  63. package/dist/{chunk-HYZRY4KZ.js → chunk-XNGMQ27R.js} +16 -6
  64. package/dist/{chunk-HGECYFEI.js → chunk-Y5GE76XC.js} +131 -54
  65. package/dist/{chunk-MAK5LYRF.js → chunk-Y5MXET4M.js} +277 -535
  66. package/dist/{chunk-XCK2YAY5.js → chunk-YVZJ6GKF.js} +3 -2
  67. package/dist/{chunk-YO4PSLVB.js → chunk-ZRL6HKBY.js} +1 -1
  68. package/dist/claude-launcher-YVXI76NX.js +102 -0
  69. package/dist/{cli-A76AXELQ.js → cli-C77H54BV.js} +468 -161
  70. package/dist/{command-R2QCVX55.js → command-H5CILO4S.js} +40 -37
  71. package/dist/{config-N3C6DFQA.js → config-FXDG4NPJ.js} +2 -3
  72. package/dist/{connect-cmd-JBKAQNSF.js → connect-cmd-ZW5FV3ZW.js} +9 -8
  73. package/dist/{context-adopt-NFHCLVUB.js → context-adopt-O5OFXMKI.js} +13 -12
  74. package/dist/context-materialize-Y5IJ4MQT.js +23 -0
  75. package/dist/{dist-LKDWQWZ7.js → dist-QTX4RSCL.js} +2 -2
  76. package/dist/{docker-4J77Q2BF.js → docker-RC3PRX3Q.js} +7 -8
  77. package/dist/{doctor-4TAIARIG.js → doctor-2NQQML6P.js} +46 -39
  78. package/dist/{emit-artifact-cmd-MPZVR56N.js → emit-artifact-cmd-7MP63KXU.js} +25 -22
  79. package/dist/emit-cmd-PPN4QQF2.js +14 -0
  80. package/dist/{emit-criteria-cmd-EFGYI23V.js → emit-criteria-cmd-3RXPDLNK.js} +16 -14
  81. package/dist/{emit-finding-cmd-5GF3V4LR.js → emit-finding-cmd-OL7JB6H3.js} +18 -16
  82. package/dist/{emit-result-cmd-I4OADKMD.js → emit-result-cmd-UZVMOCF4.js} +20 -17
  83. package/dist/{exec-client-CQV746UF.js → exec-client-7UMESIE2.js} +3 -4
  84. package/dist/governing-source-BUU4IABS.js +35 -0
  85. package/dist/guest-init-KPBQOFE5.js +9 -0
  86. package/dist/{hook-fast-R4FVSZ2H.js → hook-fast-W5MKHMJT.js} +4 -1
  87. package/dist/host-key-U4B5QETR.js +8 -0
  88. package/dist/{import-capture-cmd-EQ35EARA.js → import-capture-cmd-ZO6KGHI2.js} +7 -5
  89. package/dist/{import-ruler-cmd-BGAZXCQM.js → import-ruler-cmd-KJMWL5V6.js} +5 -3
  90. package/dist/index.js +8 -4
  91. package/dist/init-VWXIZEAN.js +54 -0
  92. package/dist/{init-PWU5YVL7.js → init-WNXXYMO7.js} +38 -35
  93. package/dist/{init-cmd-XAVO7HYZ.js → init-cmd-WS6TIRYT.js} +28 -24
  94. package/dist/{init-update-CVCWD6VS.js → init-update-E3J6TVIN.js} +27 -26
  95. package/dist/{install-HDBIPHTX.js → install-CBWIEF3R.js} +4 -5
  96. package/dist/{install-cmd-5HYMXLEW.js → install-cmd-QDOTR4OM.js} +5 -4
  97. package/dist/{login-browser-QZCS3WW6.js → login-browser-O63QZN7D.js} +4 -3
  98. package/dist/{logout-cmd-QAUFDJ6J.js → logout-cmd-5V5MMBSY.js} +3 -2
  99. package/dist/{logs-H55NWW4H.js → logs-AMLKC3VP.js} +3 -1
  100. package/dist/loop-UGI2BJOT.js +76 -0
  101. package/dist/machine-JOW4RNZ7.js +49 -0
  102. package/dist/{mcp-install-cmd-FDTPQQS6.js → mcp-install-cmd-GGWB3JJ2.js} +3 -2
  103. package/dist/{mcp-serve-cmd-3KVYEUXG.js → mcp-serve-cmd-DOTY5FKY.js} +10 -8
  104. package/dist/paths-7XP63OAX.js +7 -0
  105. package/dist/pending-532ABZYC.js +8 -0
  106. package/dist/{pidfile-UZRH774M.js → pidfile-3DM4OBKO.js} +4 -2
  107. package/dist/{record-C43U4PKS.js → record-3WP6V2K5.js} +3 -2
  108. package/dist/{runner-env-EN7YE7QX.js → runner-env-4NB2GA7O.js} +5 -6
  109. package/dist/{runner-key-6SLBI7PP.js → runner-key-TC3NFWFV.js} +38 -35
  110. package/dist/{session-sender-FO3LCREV.js → session-sender-NNVPSPY7.js} +17 -14
  111. package/dist/spec-cmd-OWVTBB4J.js +116 -0
  112. package/dist/{starter-pack-KF66HGZR.js → starter-pack-OPWUDOWX.js} +7 -5
  113. package/dist/{status-7VNQN5PW.js → status-TKCLLKFG.js} +42 -39
  114. package/dist/{statusline-fast-SVTMBMD7.js → statusline-fast-KN3BX67H.js} +2 -1
  115. package/dist/{sync-cmd-GVPPFZ3G.js → sync-cmd-Q6VYNPWG.js} +16 -13
  116. package/dist/{watch-23HSAEI6.js → watch-ARAGADTF.js} +16 -13
  117. package/dist/{work-claim-cmd-LKL3GHFQ.js → work-claim-cmd-34FERLYX.js} +25 -27
  118. package/dist/work-cmd-7S5B2H2P.js +25 -0
  119. package/dist/{work-comment-cmd-AWHP56M2.js → work-comment-cmd-SZJSPM5S.js} +15 -13
  120. package/dist/{work-launch-R5HTAP6X.js → work-launch-LEQ2MPM3.js} +3 -1
  121. package/dist/{work-open-pr-cmd-IOM4AVQQ.js → work-open-pr-cmd-RPXKCBWS.js} +17 -15
  122. package/dist/work-pr-cmd-5LGANL32.js +26 -0
  123. package/package.json +3 -2
  124. package/skill-pack/maintained/outerlayer-amend/SKILL.md +4 -2
  125. package/skill-pack/shipped.json +17 -2
  126. package/skill-pack/template/build/SKILL.md +23 -10
  127. package/skill-pack/template/build/references/agent-briefs.md +3 -1
  128. package/skill-pack/template/build/references/criteria-judge.md +27 -0
  129. package/skill-pack/template/build/references/release.md +19 -28
  130. package/skill-pack/template/spec/SKILL.md +35 -10
  131. package/skill-pack/validators/acceptance-criteria.yaml +25 -26
  132. package/dist/agent-setup-T624CWPD.js +0 -27
  133. package/dist/chunk-BYT5O5RV.js +0 -61
  134. package/dist/context-materialize-IV2TUUFO.js +0 -22
  135. package/dist/emit-cmd-IJ3GVRFD.js +0 -12
  136. package/dist/guest-init-LJP5GPZF.js +0 -9
  137. package/dist/host-key-YMLXY6QB.js +0 -7
  138. package/dist/init-6XPDRDTC.js +0 -51
  139. package/dist/loop-FK3LPMMZ.js +0 -73
  140. package/dist/machine-SQXEBAM2.js +0 -46
  141. package/dist/paths-OYKMVYJP.js +0 -6
  142. package/dist/pending-MXLSRYMO.js +0 -7
  143. package/dist/work-cmd-Z2WXLZPH.js +0 -23
  144. package/dist/work-pr-cmd-HNEUIEN7.js +0 -24
@@ -1,13 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { runEmit } from './chunk-2MNPHL23.js';
4
- import { addStdioMcpEntryIfAbsent, addDocsMcpEntryIfAbsent, DOCS_MCP_SERVER_NAME } from './chunk-XCK2YAY5.js';
5
- import { installStarterPack } from './chunk-42ZI52JW.js';
6
- import { C } from './chunk-YRYMNBGQ.js';
7
- import { resolveGitCommonDir, defaultGitRunner } from './chunk-YZ5F4PIS.js';
8
- import { pinExists, readContextManifest } from './chunk-WTE3MQML.js';
9
- import { loadTemplateFiles, loadMaintainedFiles, skillDir } from './chunk-POJMEEJJ.js';
10
- import { generatedHeaderSource } from './chunk-OHVJA253.js';
3
+ import { runEmit } from './chunk-47TTLEDX.js';
4
+ import { addStdioMcpEntryIfAbsent, addDocsMcpEntryIfAbsent, DOCS_MCP_SERVER_NAME } from './chunk-YVZJ6GKF.js';
5
+ import { installStarterPack } from './chunk-F4XSVQJ4.js';
6
+ import { C } from './chunk-ANPNT6PM.js';
7
+ import { resolveGitCommonDir, defaultGitRunner } from './chunk-W5VPCONO.js';
8
+ import { pinExists, readContextManifest } from './chunk-LXAY4A2G.js';
9
+ import { loadTemplateFiles, loadMaintainedFiles, skillDir } from './chunk-MNTSH4CL.js';
10
+ import { generatedHeaderSource } from './chunk-X5N6KC6V.js';
11
+ import { cliInvocation } from './chunk-CRB3POP4.js';
11
12
  import { execFileSync } from 'child_process';
12
13
  import { existsSync, mkdirSync, writeFileSync } from 'fs';
13
14
  import { join, dirname } from 'path';
@@ -176,7 +177,7 @@ function renderPaths(paths, kept) {
176
177
  `;
177
178
  }
178
179
  function renderDone(paths, kept, mcpKept) {
179
- const mcpNote = mcpKept ? ` ${C.yellow}!${C.reset} The outerlayer and ${DOCS_MCP_SERVER_NAME} entries were not added to .mcp.json, so their MCP servers are not set up. Add them to .mcp.json by hand, or move the servers you wrote into .outerlayer/mcp.json and run \`outerlayer context emit\`.
180
+ const mcpNote = mcpKept ? ` ${C.yellow}!${C.reset} The outerlayer and ${DOCS_MCP_SERVER_NAME} entries were not added to .mcp.json, so their MCP servers are not set up. Add them to .mcp.json by hand, or move the servers you wrote into .outerlayer/mcp.json and run \`${cliInvocation()} context emit\`.
180
181
  ` : "";
181
182
  const what = mcpKept ? "the OuterLayer skills" : "the OuterLayer skills and MCP servers";
182
183
  if (paths.length === 0) {
@@ -1,15 +1,70 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
3
  import { parseSize } from './chunk-7RQ73DLO.js';
4
- import { JOB_MOUNT, GATEWAY_PORT, GATEWAY_SOCKET, CLAUDE_PORT, CLAUDE_SOCKET, RELAY_PORT, DESTINATION_BASE_PORT } from './chunk-4Q7OMKAT.js';
5
4
  import { BUILDKIT_IMAGE } from './chunk-CX22S5BA.js';
6
- import { compareVersions } from './chunk-JXYVA45C.js';
7
- import { runnerDir } from './chunk-ZM2IMMYN.js';
5
+ import { compareVersions } from './chunk-BMYGAGBJ.js';
6
+ import { runnerDir } from './chunk-N2PXGQRL.js';
7
+ import { CLAUDE_PORT, JOB_MOUNT, GATEWAY_PORT, GATEWAY_SOCKET, CLAUDE_SOCKET, RELAY_PORT, DESTINATION_BASE_PORT } from './chunk-BQXFBI7T.js';
8
8
  import { createHash } from 'crypto';
9
9
  import { realpathSync } from 'fs';
10
10
  import { join, dirname, resolve } from 'path';
11
11
 
12
12
  createRequire(import.meta.url);
13
+
14
+ // src/runner/judge-command.ts
15
+ var JUDGE_DIR = "/outerlayer/judge";
16
+ var JUDGE_HOME = `${JUDGE_DIR}/home`;
17
+ var JUDGE_TREE = `${JUDGE_DIR}/tree`;
18
+ var JUDGE_REPORT = `${JUDGE_DIR}/report.html`;
19
+ var JUDGE_PROGRAM = "/opt/outerlayer/claude/bin/claude";
20
+ var MAX_REPORT_BYTES = 5 * 1024 * 1024;
21
+ var JUDGE_MAX_TURNS = 60;
22
+ var JUDGE_PATH = "/opt/outerlayer/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
23
+ var JUDGE_TOOLS = "Read,Grep,Glob,Write";
24
+ function judgeCommand(input) {
25
+ const env = {
26
+ HOME: JUDGE_HOME,
27
+ TMPDIR: `${JUDGE_HOME}/tmp`,
28
+ PATH: JUDGE_PATH,
29
+ ANTHROPIC_BASE_URL: `http://127.0.0.1:${CLAUDE_PORT}`,
30
+ CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: "1",
31
+ DISABLE_AUTOUPDATER: "1",
32
+ ...input.credential === void 0 ? {} : { [input.credential.variable]: input.credential.placeholder }
33
+ };
34
+ const argv = [
35
+ JUDGE_PROGRAM,
36
+ "-p",
37
+ "--output-format",
38
+ "json",
39
+ "--setting-sources",
40
+ "user",
41
+ "--strict-mcp-config",
42
+ "--disable-slash-commands",
43
+ "--no-session-persistence",
44
+ "--tools",
45
+ JUDGE_TOOLS,
46
+ "--allowedTools",
47
+ // A path that starts with two slashes is absolute in a permission rule.
48
+ `Read(/${JUDGE_DIR}/**),Edit(/${JUDGE_REPORT})`,
49
+ "--add-dir",
50
+ JUDGE_TREE,
51
+ "--permission-mode",
52
+ "dontAsk",
53
+ "--max-turns",
54
+ String(JUDGE_MAX_TURNS),
55
+ // After the separator, so a brief that starts with a dash is not read as an option.
56
+ "--",
57
+ input.brief
58
+ ];
59
+ return { argv, env, cwd: JUDGE_DIR };
60
+ }
61
+ var HASH_SCRIPT = 'const fs=require("fs"),c=require("crypto");const p=fs.realpathSync(process.argv[1]);process.stdout.write(c.createHash("sha256").update(fs.readFileSync(p)).digest("hex")+" "+p+"\\n")';
62
+ var HASH_ARGV = ["/opt/outerlayer/bin/node", "-e", HASH_SCRIPT, JUDGE_PROGRAM];
63
+ function parseProgramHash(stdout) {
64
+ return /^([0-9a-f]{64}) /.exec(stdout.trim())?.[1];
65
+ }
66
+
67
+ // src/runner/container/run-args.ts
13
68
  var BUILD_LABEL = "ai.outerlayer.build";
14
69
  var RUNNER_LABEL = "ai.outerlayer.runner";
15
70
  function resolvedRunnerDir(configPath) {
@@ -71,6 +126,7 @@ function containerRunArgs(input) {
71
126
  `type=volume,src=${input.volume},dst=/tmp,volume-subpath=tmp`,
72
127
  "--mount",
73
128
  `type=bind,src=${mountPath(input.buildDir)},dst=${JOB_MOUNT},readonly`,
129
+ ...input.judgeDir === void 0 ? [] : ["--mount", `type=bind,src=${mountPath(input.judgeDir)},dst=${JUDGE_DIR}`],
74
130
  "--entrypoint",
75
131
  "/opt/outerlayer/bin/tini",
76
132
  input.image,
@@ -261,4 +317,4 @@ function ensureBuilder(rawRun, spec, options = {}) {
261
317
  );
262
318
  }
263
319
 
264
- export { BUILD_LABEL, MIN_BUILDX_VERSION, RUNNER_LABEL, builderName, builderSpec, buildxState, containerExecArgs, containerRunArgs, ensureBuilder, ensureFailureCount, isOutOfMemory, prepareRunArgs, proxyEnvironment, runnerLabelValue, trackImageBuild };
320
+ export { BUILD_LABEL, HASH_ARGV, JUDGE_DIR, JUDGE_MAX_TURNS, JUDGE_PROGRAM, MAX_REPORT_BYTES, MIN_BUILDX_VERSION, RUNNER_LABEL, builderName, builderSpec, buildxState, containerExecArgs, containerRunArgs, ensureBuilder, ensureFailureCount, isOutOfMemory, judgeCommand, parseProgramHash, prepareRunArgs, proxyEnvironment, runnerLabelValue, trackImageBuild };
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { RUNNER_DIR_MODE, RUNNER_FILE_MODE } from './chunk-ZM2IMMYN.js';
3
+ import { RUNNER_DIR_MODE, RUNNER_FILE_MODE } from './chunk-N2PXGQRL.js';
4
4
  import { readFileSync, mkdirSync, writeFileSync, renameSync } from 'fs';
5
5
  import { join } from 'path';
6
6
 
@@ -1,11 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { sanitizeTerminal } from './chunk-WUYTWNMA.js';
4
- import { remoteLookupFailed } from './chunk-JXYVA45C.js';
5
- import { DEFAULT_DASHBOARD } from './chunk-4KSQKQXE.js';
6
- import { resolveGatewayCredentials } from './chunk-PLMTLGYH.js';
3
+ import { sanitizeTerminal } from './chunk-MQJSXHV7.js';
4
+ import { remoteLookupFailed } from './chunk-BMYGAGBJ.js';
5
+ import { DEFAULT_DASHBOARD } from './chunk-NACDBXUG.js';
6
+ import { resolveGatewayCredentials } from './chunk-52NC2FIU.js';
7
7
  import { readCloudConfig } from './chunk-EABW6AJQ.js';
8
8
  import { writeRepoConnection, findGitDirs, readRepoConnection } from './chunk-BJ3KTMDH.js';
9
+ import { cliInvocation } from './chunk-CRB3POP4.js';
9
10
  import { execFileSync } from 'child_process';
10
11
  import { createInterface } from 'readline/promises';
11
12
 
@@ -53,7 +54,7 @@ function notLinkedText(factoryName, repository, url) {
53
54
  Link it on the factory's Work page: ${url}
54
55
  1. Connect GitHub repository, and grant the App access to ${name}.
55
56
  2. Link repository, and pick ${name} and its default branch.
56
- Then run \`outerlayer connect\` again.
57
+ Then run \`${cliInvocation()} connect\` again.
57
58
  `;
58
59
  }
59
60
 
@@ -151,7 +152,7 @@ async function fetchFactories(fetchImpl, url, token, repository) {
151
152
  return { ok: false, result: result(1, "failed", message, message) };
152
153
  }
153
154
  if (res.status === 401) {
154
- const message = "the gateway refused the login. Run `outerlayer login` to sign in again.";
155
+ const message = `the gateway refused the login. Run \`${cliInvocation()} login\` to sign in again.`;
155
156
  return { ok: false, result: result(1, "failed", message, message) };
156
157
  }
157
158
  if (!res.ok) {
@@ -160,7 +161,7 @@ async function fetchFactories(fetchImpl, url, token, repository) {
160
161
  }
161
162
  const factories = parseFactories(await res.json().catch(() => null));
162
163
  if (factories === void 0) {
163
- const message = `${url} answered, but the reply is not a list of factories. Check the gateway address with \`outerlayer doctor\`, then run \`outerlayer connect\` again.`;
164
+ const message = `${url} answered, but the reply is not a list of factories. Check the gateway address with \`${cliInvocation()} doctor\`, then run \`${cliInvocation()} connect\` again.`;
164
165
  return { ok: false, result: result(1, "failed", `${url} did not answer with a factory list`, message) };
165
166
  }
166
167
  return { ok: true, factories };
@@ -205,7 +206,7 @@ ${listText(factories, repository)}`;
205
206
  if (!deps.isTerminal) {
206
207
  const why = linked.length > 1 ? `${repository} is linked to more than one factory you can use` : `you can use more than one factory, and none is the only one ${repository} is linked to`;
207
208
  const message = `${why}, and there is no terminal to ask on.
208
- Run \`outerlayer connect --factory <org>/<factory>\` with one of:
209
+ Run \`${cliInvocation()} connect --factory <org>/<factory>\` with one of:
209
210
  ${listText(factories, repository)}`;
210
211
  return result(1, "failed", "more than one factory fits; pass --factory", message);
211
212
  }
@@ -226,18 +227,18 @@ ${listText(factories, repository)}`;
226
227
  }))
227
228
  });
228
229
  const factory = pool.find((f) => f.id === picked);
229
- if (!factory) return result(1, "failed", "no factory was chosen", "no factory was chosen. Run `outerlayer connect` again, or pass --factory <org>/<factory>.");
230
+ if (!factory) return result(1, "failed", "no factory was chosen", `no factory was chosen. Run \`${cliInvocation()} connect\` again, or pass --factory <org>/<factory>.`);
230
231
  return { factory, reason: "prompt" };
231
232
  }
232
233
  async function runConnect(flags, deps) {
233
234
  const creds = resolveGatewayCredentials({ home: deps.home, env: deps.env, cwd: deps.cwd });
234
235
  if (creds.credential === void 0) {
235
- const message = "no saved credential. Run `outerlayer login` to sign in, then run `outerlayer connect` again.";
236
- return { ...result(1, "skipped", "no credential; run `outerlayer login` first", message), next: "Run `outerlayer login`, then `outerlayer init` again." };
236
+ const message = `no saved credential. Run \`${cliInvocation()} login\` to sign in, then run \`${cliInvocation()} connect\` again.`;
237
+ return { ...result(1, "skipped", `no credential; run \`${cliInvocation()} login\` first`, message), next: `Run \`${cliInvocation()} login\`, then \`${cliInvocation()} init\` again.` };
237
238
  }
238
239
  if (creds.kind === "key") {
239
240
  if (flags.factory !== void 0 && flags.factory !== creds.appId) {
240
- const message2 = `a factory key decides the factory${creds.appId ? ` (${creds.appId})` : ""}, so --factory ${flags.factory} cannot apply. Remove --factory, or sign in with \`outerlayer login\` and unset the key.`;
241
+ const message2 = `a factory key decides the factory${creds.appId ? ` (${creds.appId})` : ""}, so --factory ${flags.factory} cannot apply. Remove --factory, or sign in with \`${cliInvocation()} login\` and unset the key.`;
241
242
  return result(1, "failed", "--factory names a factory other than the key's", message2);
242
243
  }
243
244
  const message = `Your factory key decides the factory${creds.appId ? ` (${creds.appId})` : ""}, so there is nothing to connect. No file was changed.`;
@@ -248,14 +249,14 @@ async function runConnect(flags, deps) {
248
249
  }
249
250
  const repository = deps.resolveRepository(deps.cwd);
250
251
  if (repository === void 0 && remoteLookupFailed(deps.cwd)) {
251
- const message = "git did not answer when asked for this repository's remote, so connect cannot tell which repository it is. Run `git remote -v` here, then run `outerlayer connect` again.";
252
+ const message = `git did not answer when asked for this repository's remote, so connect cannot tell which repository it is. Run \`git remote -v\` here, then run \`${cliInvocation()} connect\` again.`;
252
253
  return result(1, "failed", "git could not read this repository's remote", message);
253
254
  }
254
255
  if (repository === void 0) {
255
- return result(1, "skipped", "this repository has no git remote", "this repository has no git remote, so connect cannot tell which repository it is. Add one (`git remote add origin <url>`), then run `outerlayer connect` again.");
256
+ return result(1, "skipped", "this repository has no git remote", `this repository has no git remote, so connect cannot tell which repository it is. Add one (\`git remote add origin <url>\`), then run \`${cliInvocation()} connect\` again.`);
256
257
  }
257
258
  if (creds.url === void 0) {
258
- const message = "no gateway address is saved. Run `outerlayer login` to sign in.";
259
+ const message = `no gateway address is saved. Run \`${cliInvocation()} login\` to sign in.`;
259
260
  return result(1, "failed", message, message);
260
261
  }
261
262
  const listed = await fetchFactories(deps.fetchImpl, creds.url, creds.credential, repository);
@@ -285,7 +286,7 @@ async function runConnect(flags, deps) {
285
286
  const linkUrl = workPageUrl(deps.home, factory.organization.name, factory.name);
286
287
  return { ...result(EXIT_NOT_LINKED, "done", why, connected + notLinkedText(factory.displayName, repository, linkUrl)), ...chosen, linked, linkUrl };
287
288
  }
288
- const changeIt = "Run `outerlayer connect --factory <org>/<factory>` to change it.";
289
+ const changeIt = `Run \`${cliInvocation()} connect --factory <org>/<factory>\` to change it.`;
289
290
  const text = linked === null ? `${connected}Could not check whether ${sanitizeTerminal(repository)} is linked to ${factory.displayName}.
290
291
  ${changeIt}` : connected + changeIt;
291
292
  return { ...result(0, "done", why, text), ...chosen, linked };
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { RUNNER_DIR_MODE, RUNNER_FILE_MODE } from './chunk-ZM2IMMYN.js';
3
+ import { RUNNER_DIR_MODE, RUNNER_FILE_MODE } from './chunk-N2PXGQRL.js';
4
4
  import { existsSync, readFileSync, mkdirSync, chmodSync, writeFileSync } from 'fs';
5
5
  import { dirname, join } from 'path';
6
6
 
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { DEFAULT_UNIT_NAME } from './chunk-RLYZLUQ7.js';
3
+ import { DEFAULT_UNIT_NAME } from './chunk-WGAUY5LE.js';
4
4
  import { parseRunnerEnv } from './chunk-6MZSX4M7.js';
5
- import { RUNNER_FILE_MODE } from './chunk-ZM2IMMYN.js';
5
+ import { RUNNER_FILE_MODE } from './chunk-N2PXGQRL.js';
6
6
  import { existsSync, readFileSync, writeFileSync, renameSync, rmSync } from 'fs';
7
7
  import { join, dirname } from 'path';
8
8
 
@@ -1,11 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
3
  import { parseTrackerNumber } from './chunk-WZBHBH3J.js';
4
+ import { cliInvocation } from './chunk-CRB3POP4.js';
4
5
  import { mkdirSync, appendFileSync, readFileSync } from 'fs';
5
6
  import { join } from 'path';
6
7
 
7
8
  createRequire(import.meta.url);
8
- var HOW_TO_CREATE_AN_ITEM = "outerlayer work build --local";
9
+ var HOW_TO_CREATE_AN_ITEM = `${cliInvocation()} work build --local`;
9
10
  function parseWorkItemEnv(raw) {
10
11
  if (raw === void 0) return { reason: "OUTERLAYER_WORK is not set" };
11
12
  const value = raw.trim();
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { skillDir, FORMER_MAINTAINED_NAMES, isMaintainedCopy } from './chunk-POJMEEJJ.js';
4
- import { emitTree, ALL_TARGET_IDS, classifyTree } from './chunk-OHVJA253.js';
3
+ import { skillDir, FORMER_MAINTAINED_NAMES, isMaintainedCopy } from './chunk-MNTSH4CL.js';
4
+ import { emitTree, ALL_TARGET_IDS, classifyTree } from './chunk-X5N6KC6V.js';
5
+ import { cliInvocation } from './chunk-CRB3POP4.js';
5
6
  import { readFileSync, existsSync, unlinkSync, rmdirSync, readdirSync } from 'fs';
6
7
  import { join, dirname, relative, sep } from 'path';
7
8
 
@@ -70,7 +71,7 @@ function checkFormerSkillNames(repoRoot) {
70
71
  name: "Renamed skills",
71
72
  status: "warn",
72
73
  detail: `copies under earlier names: ${retired.map(skillDir).join(", ")}`,
73
- fix: "Run `outerlayer context emit` to replace them with the current names, then commit."
74
+ fix: `Run \`${cliInvocation()} context emit\` to replace them with the current names, then commit.`
74
75
  });
75
76
  }
76
77
  const hits = filesNamingFormerSkills(repoRoot);
@@ -79,7 +80,7 @@ function checkFormerSkillNames(repoRoot) {
79
80
  name: "Skill names",
80
81
  status: "warn",
81
82
  detail: `${hits.map((h) => `${h.path} (${h.formers.join(", ")})`).join("; ")} still ${hits.length === 1 ? "names" : "name"} a skill by an earlier name`,
82
- fix: `Replace each earlier name with the current one: ${Object.entries(FORMER_MAINTAINED_NAMES).map(([former, current]) => `${former} \u2192 ${current}`).join(", ")}. \`outerlayer init --update\` does this for a file you have not edited.`
83
+ fix: `Replace each earlier name with the current one: ${Object.entries(FORMER_MAINTAINED_NAMES).map(([former, current]) => `${former} \u2192 ${current}`).join(", ")}. \`${cliInvocation()} init --update\` does this for a file you have not edited.`
83
84
  });
84
85
  }
85
86
  return checks;
@@ -1,7 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
+ import { CONTROL_PLANE_DIR_VARIABLE } from './chunk-G2YNJIGF.js';
3
4
  import { deadHooksState, huskyPrepareScript, preparePackageManagerCommand } from './chunk-XCCLFVXM.js';
5
+ import { appendContextProvenance } from './chunk-ZJSNLVCE.js';
4
6
  import { readRepoConnection, findGitDirs } from './chunk-BJ3KTMDH.js';
7
+ import { cliInvocation } from './chunk-CRB3POP4.js';
5
8
  import { homeFromEnv } from './chunk-VNVZDWO3.js';
6
9
  import { readFileSync, mkdirSync, writeFileSync, renameSync, existsSync, statSync, appendFileSync, opendirSync, unlinkSync } from 'fs';
7
10
  import { spawn, execFileSync } from 'child_process';
@@ -56,7 +59,7 @@ function assessSyncHealth(status, now = Date.now(), staleAfterMs = SYNC_STALE_AF
56
59
  return {
57
60
  level: "unknown",
58
61
  headline: "no sync has run on this machine yet",
59
- details: ["run `outerlayer sync` once to verify the connection"]
62
+ details: [`run \`${cliInvocation()} sync\` once to verify the connection`]
60
63
  };
61
64
  }
62
65
  const host = status.url ? safeHost(status.url) : "the configured endpoint";
@@ -71,7 +74,7 @@ function assessSyncHealth(status, now = Date.now(), staleAfterMs = SYNC_STALE_AF
71
74
  );
72
75
  if (status.pending) details.push(`${status.pending} session(s) waiting to ship`);
73
76
  if (status.held) details.push(`${status.held} transcript(s) held \u2014 their launch could not be determined`);
74
- details.push("run `outerlayer doctor` for the full picture");
77
+ details.push(`run \`${cliInvocation()} doctor\` for the full picture`);
75
78
  return {
76
79
  level: "error",
77
80
  headline: `sync is FAILING \u2014 last attempt ${formatAgo(now - Date.parse(status.at))}`,
@@ -104,7 +107,7 @@ function assessSyncHealth(status, now = Date.now(), staleAfterMs = SYNC_STALE_AF
104
107
  headline: `sync ran ${formatAgo(age)} but ${host} has never been reached`,
105
108
  details: [
106
109
  "every run so far had an empty queue, so the connection is unproven",
107
- "run `outerlayer sync --all` to verify it"
110
+ `run \`${cliInvocation()} sync --all\` to verify it`
108
111
  ]
109
112
  };
110
113
  }
@@ -388,7 +391,7 @@ function hookErrorsContext(home, writtenBytes, seenBytes) {
388
391
  }
389
392
  async function handleWorkLaunch(sessionId, home, env, spawnImpl = spawnDetached, cwd = process.cwd()) {
390
393
  if (!sessionId || env.OUTERLAYER_WORK === void 0) return void 0;
391
- const { parseWorkItemEnv, appendLaunchRecord } = await import('./work-launch-R5HTAP6X.js');
394
+ const { parseWorkItemEnv, appendLaunchRecord } = await import('./work-launch-LEQ2MPM3.js');
392
395
  const parsed = parseWorkItemEnv(env.OUTERLAYER_WORK);
393
396
  if ("reason" in parsed) {
394
397
  logHookError(home, new Error(`OUTERLAYER_WORK ignored: ${parsed.reason}`));
@@ -433,7 +436,7 @@ async function missingRenewalHookContext(home, cwd) {
433
436
  const registeredIn = (settings) => (settings.hooks?.PostToolUse ?? []).some((block) => (block.hooks ?? []).some((h) => isOurHookCommand(h)));
434
437
  const registered = userSettings !== null && registeredIn(userSettings) || projectSettings !== null && registeredIn(projectSettings);
435
438
  if (registered) return void 0;
436
- return "This install has no PostToolUse hook, so this session's work-item lease will never be renewed while it works and may be lost to another worker mid-session. Run `outerlayer init` to register it.";
439
+ return `This install has no PostToolUse hook, so this session's work-item lease will never be renewed while it works and may be lost to another worker mid-session. Run \`${cliInvocation()} init\` to register it.`;
437
440
  } catch {
438
441
  return void 0;
439
442
  }
@@ -454,7 +457,7 @@ async function maybeRenewWorkLease(event, sessionId, home = homeFromEnv(), env =
454
457
  if (now - statSync(marker).mtimeMs < WORK_LEASE_RENEW_DEBOUNCE_MS) return;
455
458
  } catch {
456
459
  }
457
- const { parseWorkItemEnv } = await import('./work-launch-R5HTAP6X.js');
460
+ const { parseWorkItemEnv } = await import('./work-launch-LEQ2MPM3.js');
458
461
  const parsed = parseWorkItemEnv(env.OUTERLAYER_WORK);
459
462
  if ("reason" in parsed) return;
460
463
  writeFileSync(marker, String(now));
@@ -470,7 +473,7 @@ async function handleWorkSessionEnd(event, sessionId, _home = homeFromEnv(), env
470
473
  try {
471
474
  if (event !== "SessionEnd") return;
472
475
  if (!sessionId || env.OUTERLAYER_WORK === void 0) return;
473
- const { parseWorkItemEnv } = await import('./work-launch-R5HTAP6X.js');
476
+ const { parseWorkItemEnv } = await import('./work-launch-LEQ2MPM3.js');
474
477
  const parsed = parseWorkItemEnv(env.OUTERLAYER_WORK);
475
478
  if ("reason" in parsed) return;
476
479
  spawnImpl(
@@ -487,7 +490,7 @@ function syncHealthContext(home) {
487
490
  if (health.level !== "error") return null;
488
491
  return [`OuterLayer sync is failing on this machine: ${health.headline}`, ...health.details.map((d) => ` - ${d}`)].join("\n");
489
492
  }
490
- var UNTRUSTED_STALE_CLI_CONTEXT = "The installed OuterLayer CLI appears stale relative to a checkout near your working directory; run `outerlayer doctor` for details.";
493
+ var UNTRUSTED_STALE_CLI_CONTEXT = `The installed OuterLayer CLI appears stale relative to a checkout near your working directory; run \`${cliInvocation()} doctor\` for details.`;
491
494
  function installedCliStalenessContext(home, cwd) {
492
495
  const result = checkInstalledCliStaleness({ home, cwd });
493
496
  if (result === null || !result.stale) return null;
@@ -547,10 +550,10 @@ function deadHooksAutoHealContext(cwd, home) {
547
550
  const hooksDirLabel = sanitizeForContext(state.hooksDir);
548
551
  const script = huskyPrepareScript(state.repoRoot);
549
552
  if (script === null) {
550
- return `Git hooks are dead in this checkout (${hooksDirLabel} is missing or empty, via core.hooksPath) and package.json declares no husky prepare script to run automatically. Run \`outerlayer doctor\` for the fix.`;
553
+ return `Git hooks are dead in this checkout (${hooksDirLabel} is missing or empty, via core.hooksPath) and package.json declares no husky prepare script to run automatically. Run \`${cliInvocation()} doctor\` for the fix.`;
551
554
  }
552
555
  if (recentHealFailure(home, state.repoRoot)) {
553
- return `Git hooks are still dead in this checkout (${hooksDirLabel}) \u2014 a previous auto-heal attempt failed recently, so it will not retry yet. Run \`outerlayer doctor\` for the fix.`;
556
+ return `Git hooks are still dead in this checkout (${hooksDirLabel}) \u2014 a previous auto-heal attempt failed recently, so it will not retry yet. Run \`${cliInvocation()} doctor\` for the fix.`;
554
557
  }
555
558
  const command = preparePackageManagerCommand(state.repoRoot);
556
559
  const [bin, ...args] = command.split(" ");
@@ -563,7 +566,7 @@ function deadHooksAutoHealContext(cwd, home) {
563
566
  const after = deadHooksState(state.repoRoot);
564
567
  if (after.dead) {
565
568
  markHealFailure(home, state.repoRoot);
566
- return `OuterLayer ran \`${command}\` to regenerate dead git hooks, but ${hooksDirLabel} is still missing or empty afterward. Run \`outerlayer doctor\` for the fix.`;
569
+ return `OuterLayer ran \`${command}\` to regenerate dead git hooks, but ${hooksDirLabel} is still missing or empty afterward. Run \`${cliInvocation()} doctor\` for the fix.`;
567
570
  }
568
571
  clearHealFailureMarker(home, state.repoRoot);
569
572
  return null;
@@ -594,6 +597,29 @@ function contextPossiblyGoverned(cwd, home = homeFromEnv()) {
594
597
  return false;
595
598
  }
596
599
  }
600
+ function recordDeliveredContext(cwd, sessionId, home) {
601
+ const dirs = findGitDirs(cwd);
602
+ if (dirs === void 0) return;
603
+ let record;
604
+ try {
605
+ record = JSON.parse(readFileSync(join(dirs.gitCommonDir, "outerlayer", "delivery.json"), "utf8"));
606
+ } catch {
607
+ return;
608
+ }
609
+ if (typeof record.repository !== "string" || typeof record.sha !== "string") return;
610
+ appendContextProvenance(
611
+ {
612
+ t: (/* @__PURE__ */ new Date()).toISOString(),
613
+ sessionId,
614
+ repoRoot: dirs.repoRoot,
615
+ repository: record.repository,
616
+ ...typeof record.ref === "string" ? { ref: record.ref } : {},
617
+ sha: record.sha,
618
+ verification: "verified"
619
+ },
620
+ home
621
+ );
622
+ }
597
623
  async function runHookFast(event, home = homeFromEnv(), read = readStdin, env = process.env, spawnImpl = spawnDetached) {
598
624
  try {
599
625
  const stdin = read();
@@ -632,9 +658,15 @@ async function runHookFast(event, home = homeFromEnv(), read = readStdin, env =
632
658
  const hookErrorsBytes = fileSizeBytes(join(dir, "hook-errors.log"));
633
659
  const hookErrorsSeen = hookErrorsSeenBytes(home);
634
660
  recordHookErrorsSeen(home, hookErrorsBytes);
635
- if (contextPossiblyGoverned(sessionCwd, home)) {
661
+ if (env[CONTROL_PLANE_DIR_VARIABLE] !== void 0) {
662
+ try {
663
+ recordDeliveredContext(sessionCwd, typeof payload.session_id === "string" ? payload.session_id : "unknown", home);
664
+ } catch (err) {
665
+ logHookError(home, err);
666
+ }
667
+ } else if (contextPossiblyGoverned(sessionCwd, home)) {
636
668
  try {
637
- const { materializeContext: materialize } = await import('./context-materialize-IV2TUUFO.js');
669
+ const { materializeContext: materialize } = await import('./context-materialize-Y5IJ4MQT.js');
638
670
  const sessionId = typeof payload.session_id === "string" ? payload.session_id : "unknown";
639
671
  const result = await materialize({ cwd: sessionCwd, sessionId, home });
640
672
  materializeMessage = result.message;
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { LiveUploader } from './chunk-NWQTTSBB.js';
4
- import { CaptureDaemon } from './chunk-JXYVA45C.js';
5
- import { parseWorkItemEnv } from './chunk-GQD22KKN.js';
6
- import { spoolDir } from './chunk-BWQ66M6N.js';
3
+ import { LiveUploader } from './chunk-JF42URPU.js';
4
+ import { CaptureDaemon } from './chunk-BMYGAGBJ.js';
5
+ import { parseWorkItemEnv } from './chunk-T2Q7ISPE.js';
6
+ import { spoolDir } from './chunk-ULSIJGLS.js';
7
7
  import { homeFromEnv } from './chunk-VNVZDWO3.js';
8
8
  import { mkdirSync, writeFileSync, rmSync } from 'fs';
9
9
  import { join } from 'path';
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { currentLink } from './chunk-TI7B7UEO.js';
3
+ import { currentLink } from './chunk-AMFWYESY.js';
4
4
  import { readFileSync, statSync, chmodSync, mkdirSync, writeFileSync, renameSync, rmSync, existsSync, lstatSync, accessSync, constants, realpathSync } from 'fs';
5
5
  import { randomBytes } from 'crypto';
6
6
  import { join, dirname, delimiter, resolve } from 'path';