@outerlayer/cli 0.16.1 → 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 (153) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/README.md +26 -11
  3. package/dist/agent-setup-RBTEACYU.js +28 -0
  4. package/dist/artifact-link-cmd-AVM2EKTV.js +25 -0
  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-CNTMSGOG.js → check-5C4YDZYV.js} +53 -50
  9. package/dist/{chunk-R7PF5OOU.js → chunk-3CWUOFV6.js} +21 -14
  10. package/dist/{chunk-R4ZQQ7U2.js → chunk-3OFZM4X6.js} +551 -72
  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-JJEGKEFV.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-FWX735W7.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-CA3XMYFN.js → chunk-GOBOJMOJ.js} +6 -6
  29. package/dist/{chunk-N6LURUEF.js → chunk-GOSFARMS.js} +1 -1
  30. package/dist/chunk-JBJTC3UU.js +35 -0
  31. package/dist/{chunk-U3HXXRTY.js → chunk-JF42URPU.js} +16 -15
  32. package/dist/{chunk-ADJRGVZC.js → chunk-KDVIU23F.js} +1 -1
  33. package/dist/{chunk-6QRMLNH3.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-RSPXEVDX.js → chunk-NL4XPC7W.js} +1 -1
  45. package/dist/{chunk-EHAAPRWY.js → chunk-QQM2UJ6T.js} +31 -26
  46. package/dist/{chunk-5FEK6PNE.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-YDSMROTB.js → chunk-S76AYB4M.js} +25 -20
  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-6JNURGOA.js → chunk-ULSIJGLS.js} +45 -13
  55. package/dist/{chunk-ONRCEE6D.js → chunk-UYOYTKE2.js} +4 -4
  56. package/dist/{chunk-PTW6W5NR.js → chunk-VYAL7PUE.js} +1 -1
  57. package/dist/{chunk-JEHRUE3F.js → chunk-W5VPCONO.js} +166 -196
  58. package/dist/{chunk-NPQWKGUA.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-W3EKCZSQ.js → chunk-Y5GE76XC.js} +180 -53
  65. package/dist/{chunk-EWORLJMO.js → chunk-Y5MXET4M.js} +277 -526
  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-AEWH62UE.js → cli-C77H54BV.js} +489 -174
  70. package/dist/{command-HHPBR6CS.js → command-H5CILO4S.js} +40 -37
  71. package/dist/{config-N3C6DFQA.js → config-FXDG4NPJ.js} +2 -3
  72. package/dist/connect-cmd-ZW5FV3ZW.js +17 -0
  73. package/dist/{context-adopt-VMMGFRUZ.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-N6Y7HKK3.js → doctor-2NQQML6P.js} +47 -39
  78. package/dist/{emit-artifact-cmd-H5MH3AOP.js → emit-artifact-cmd-7MP63KXU.js} +25 -22
  79. package/dist/emit-cmd-PPN4QQF2.js +14 -0
  80. package/dist/{emit-criteria-cmd-HBP6XS5C.js → emit-criteria-cmd-3RXPDLNK.js} +16 -14
  81. package/dist/{emit-finding-cmd-ZXDRL6PG.js → emit-finding-cmd-OL7JB6H3.js} +18 -16
  82. package/dist/{emit-result-cmd-RFKALS5Z.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/hidden-prompt-UXBFMQC5.js +68 -0
  87. package/dist/{hook-fast-D7HV4IXG.js → hook-fast-W5MKHMJT.js} +4 -1
  88. package/dist/host-key-U4B5QETR.js +8 -0
  89. package/dist/{import-capture-cmd-EQ35EARA.js → import-capture-cmd-ZO6KGHI2.js} +7 -5
  90. package/dist/{import-ruler-cmd-BGAZXCQM.js → import-ruler-cmd-KJMWL5V6.js} +5 -3
  91. package/dist/index.js +8 -4
  92. package/dist/init-VWXIZEAN.js +54 -0
  93. package/dist/{init-FBCA4DRA.js → init-WNXXYMO7.js} +80 -53
  94. package/dist/{init-cmd-CAG572UE.js → init-cmd-WS6TIRYT.js} +28 -24
  95. package/dist/{init-update-VDFF4K3B.js → init-update-E3J6TVIN.js} +27 -26
  96. package/dist/{install-HDBIPHTX.js → install-CBWIEF3R.js} +4 -5
  97. package/dist/{install-cmd-5HYMXLEW.js → install-cmd-QDOTR4OM.js} +5 -4
  98. package/dist/{login-browser-QZCS3WW6.js → login-browser-O63QZN7D.js} +4 -3
  99. package/dist/{logout-cmd-QAUFDJ6J.js → logout-cmd-5V5MMBSY.js} +3 -2
  100. package/dist/{logs-H55NWW4H.js → logs-AMLKC3VP.js} +3 -1
  101. package/dist/loop-UGI2BJOT.js +76 -0
  102. package/dist/machine-JOW4RNZ7.js +49 -0
  103. package/dist/{mcp-install-cmd-FDTPQQS6.js → mcp-install-cmd-GGWB3JJ2.js} +3 -2
  104. package/dist/{mcp-serve-cmd-3KVYEUXG.js → mcp-serve-cmd-DOTY5FKY.js} +10 -8
  105. package/dist/paths-7XP63OAX.js +7 -0
  106. package/dist/pending-532ABZYC.js +8 -0
  107. package/dist/{pidfile-UZRH774M.js → pidfile-3DM4OBKO.js} +4 -2
  108. package/dist/{record-C43U4PKS.js → record-3WP6V2K5.js} +3 -2
  109. package/dist/{runner-env-EN7YE7QX.js → runner-env-4NB2GA7O.js} +5 -6
  110. package/dist/runner-key-TC3NFWFV.js +177 -0
  111. package/dist/{session-sender-24L5EW25.js → session-sender-NNVPSPY7.js} +17 -14
  112. package/dist/spec-cmd-OWVTBB4J.js +116 -0
  113. package/dist/{starter-pack-KF66HGZR.js → starter-pack-OPWUDOWX.js} +7 -5
  114. package/dist/{status-XHSGEYO5.js → status-TKCLLKFG.js} +42 -39
  115. package/dist/{statusline-fast-SVTMBMD7.js → statusline-fast-KN3BX67H.js} +2 -1
  116. package/dist/{sync-cmd-5G5EIEHD.js → sync-cmd-Q6VYNPWG.js} +16 -13
  117. package/dist/{watch-UTOXO4SE.js → watch-ARAGADTF.js} +16 -13
  118. package/dist/{work-claim-cmd-RKHYFE5Y.js → work-claim-cmd-34FERLYX.js} +25 -27
  119. package/dist/work-cmd-7S5B2H2P.js +25 -0
  120. package/dist/{work-comment-cmd-A55CUSYE.js → work-comment-cmd-SZJSPM5S.js} +15 -13
  121. package/dist/{work-launch-R5HTAP6X.js → work-launch-LEQ2MPM3.js} +3 -1
  122. package/dist/{work-open-pr-cmd-E6O53IJD.js → work-open-pr-cmd-RPXKCBWS.js} +17 -15
  123. package/dist/work-pr-cmd-5LGANL32.js +26 -0
  124. package/package.json +3 -2
  125. package/skill-pack/maintained/outerlayer-amend/SKILL.md +6 -2
  126. package/skill-pack/maintained/outerlayer-cli/SKILL.md +2 -0
  127. package/skill-pack/maintained/outerlayer-evidence/SKILL.md +4 -2
  128. package/skill-pack/maintained/outerlayer-findings/SKILL.md +2 -0
  129. package/skill-pack/shipped.json +27 -5
  130. package/skill-pack/template/build/SKILL.md +25 -10
  131. package/skill-pack/template/build/references/agent-briefs.md +3 -1
  132. package/skill-pack/template/build/references/criteria-judge.md +27 -0
  133. package/skill-pack/template/build/references/release.md +27 -34
  134. package/skill-pack/template/build/scripts/criterion-citations.mjs +8 -3
  135. package/skill-pack/template/build/scripts/record-criteria.mjs +8 -2
  136. package/skill-pack/template/spec/SKILL.md +37 -10
  137. package/skill-pack/validators/acceptance-criteria.yaml +25 -25
  138. package/skill-pack/validators/code-review.yaml +6 -5
  139. package/dist/agent-setup-K3ABU5NL.js +0 -27
  140. package/dist/chunk-BYT5O5RV.js +0 -61
  141. package/dist/connect-cmd-JUAW6MU4.js +0 -16
  142. package/dist/context-materialize-2WXTS4CW.js +0 -22
  143. package/dist/emit-cmd-IJ3GVRFD.js +0 -12
  144. package/dist/guest-init-LJP5GPZF.js +0 -9
  145. package/dist/host-key-YMLXY6QB.js +0 -7
  146. package/dist/init-MYX7YMIH.js +0 -51
  147. package/dist/loop-75J4YXLZ.js +0 -73
  148. package/dist/machine-A6ZCTUGS.js +0 -46
  149. package/dist/paths-OYKMVYJP.js +0 -6
  150. package/dist/pending-MXLSRYMO.js +0 -7
  151. package/dist/runner-key-W25ISHI3.js +0 -155
  152. package/dist/work-cmd-DJQJEZVB.js +0 -23
  153. package/dist/work-pr-cmd-L77K32WK.js +0 -24
@@ -1,20 +1,70 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { autoConnect } from './chunk-NPQWKGUA.js';
3
+ import { autoConnect } from './chunk-WBT5X3NH.js';
4
4
  import { detectActiveSession } from './chunk-IP7BIBXJ.js';
5
- import { workPageUrl } from './chunk-YDSMROTB.js';
6
- import { sanitizeTerminal } from './chunk-WUYTWNMA.js';
7
- import { resolveRepoIdentity } from './chunk-JXYVA45C.js';
8
- import { C } from './chunk-YRYMNBGQ.js';
5
+ import { workPageUrl } from './chunk-S76AYB4M.js';
6
+ import { sanitizeTerminal } from './chunk-MQJSXHV7.js';
7
+ import { resolveRepoIdentity } from './chunk-BMYGAGBJ.js';
8
+ import { C } from './chunk-ANPNT6PM.js';
9
9
  import { parseTrackerNumber, trackerNumberError } from './chunk-WZBHBH3J.js';
10
- import { defaultFetch } from './chunk-YO4PSLVB.js';
11
- import { resolveGatewayCredentials, unauthorizedMessage } from './chunk-PLMTLGYH.js';
12
- import { signRunnerRequest } from './chunk-V7NIVOFD.js';
10
+ import { defaultFetch } from './chunk-ZRL6HKBY.js';
11
+ import { resolveGatewayCredentials, unauthorizedMessage } from './chunk-52NC2FIU.js';
12
+ import { signRunnerRequest } from './chunk-M2ZWWTWZ.js';
13
13
  import { readRepoConnection } from './chunk-BJ3KTMDH.js';
14
14
  import { homeFromEnv } from './chunk-VNVZDWO3.js';
15
15
 
16
16
  createRequire(import.meta.url);
17
17
 
18
+ // ../trackers/src/descriptor.ts
19
+ var TRACKERS = {
20
+ github: {
21
+ label: "GitHub",
22
+ hasStoredConnection: false,
23
+ verifiedKeys: false,
24
+ issueRef: "number",
25
+ scopeNoun: "repository",
26
+ connect: { kind: "builtin" }
27
+ },
28
+ linear: {
29
+ label: "Linear",
30
+ hasStoredConnection: true,
31
+ verifiedKeys: true,
32
+ issueRef: "key",
33
+ scopeNoun: "team",
34
+ connect: {
35
+ kind: "oauth",
36
+ summary: "Read the teams you pick in a workspace, and file specs as issues. One authorization; Linear registers its own webhook."
37
+ }
38
+ },
39
+ jira: {
40
+ label: "Jira",
41
+ hasStoredConnection: true,
42
+ verifiedKeys: true,
43
+ issueRef: "key",
44
+ scopeNoun: "project",
45
+ connect: {
46
+ kind: "form",
47
+ summary: "Read the projects you pick on a site, with a service account. One webhook is created in Jira by an admin.",
48
+ intro: "Uses a service account's OAuth client credential. Create one under Atlassian administration, then paste it here. Read scope only.",
49
+ notice: "After connecting, you get a webhook URL and secret to put on one webhook in Jira. That is the only manual step, and the only time the secret is shown.",
50
+ fields: [
51
+ { name: "siteUrl", label: "Site URL", placeholder: "https://your-team.atlassian.net" },
52
+ { name: "clientId", label: "Client ID" },
53
+ { name: "clientSecret", label: "Client secret", secret: true },
54
+ {
55
+ name: "projectKeys",
56
+ label: "Projects to read",
57
+ placeholder: "ENG, OPS",
58
+ helperText: "Project keys, comma separated. Only issues in these projects are listed."
59
+ }
60
+ ]
61
+ }
62
+ }
63
+ };
64
+ function verifiedTrackerNames(descriptors) {
65
+ return Object.keys(descriptors).filter((name) => descriptors[name].verifiedKeys);
66
+ }
67
+
18
68
  // src/runner/signature-refusals.ts
19
69
  var MESSAGES = /* @__PURE__ */ new Map([
20
70
  [
@@ -101,14 +151,8 @@ function parseRetries(raw) {
101
151
  const n = parseTrackerNumber(raw);
102
152
  return n === void 0 ? 0 : Math.min(n, WORK_LINK_RETRY_DELAYS_MS.length);
103
153
  }
104
- function resolveSubject(opts) {
105
- const issue = parsePositiveInt(opts.issue, "--issue");
106
- if (issue === void 0) {
107
- throw new WorkCommandError("pass --issue");
108
- }
109
- return { issue };
110
- }
111
- var TRACKER_FLAG_HELP = 'expected "linear" or "jira" \u2014 GitHub issues are named by number, with no --tracker';
154
+ var VERIFIED_TRACKERS = verifiedTrackerNames(TRACKERS);
155
+ var TRACKER_FLAG_HELP = `expected ${VERIFIED_TRACKERS.map((name) => `"${name}"`).join(" or ")} \u2014 GitHub issues are named by number, with no --tracker`;
112
156
  function resolveWorkSubject(opts) {
113
157
  if (opts.issue === void 0) {
114
158
  throw new WorkCommandError("pass --issue");
@@ -120,32 +164,36 @@ function resolveWorkSubject(opts) {
120
164
  }
121
165
  return { repository: resolveRepository(opts.repo, opts.cwd), issue: asNumber };
122
166
  }
123
- if (opts.tracker !== void 0 && opts.tracker !== "linear" && opts.tracker !== "jira") {
167
+ const tracker = opts.tracker === void 0 ? void 0 : VERIFIED_TRACKERS.find((name) => name === opts.tracker);
168
+ if (opts.tracker !== void 0 && tracker === void 0) {
124
169
  throw new WorkCommandError(`invalid --tracker "${opts.tracker}": ${TRACKER_FLAG_HELP}`);
125
170
  }
126
- return { key: String(opts.issue), tracker: opts.tracker, repository: opts.repo };
171
+ return { key: String(opts.issue), tracker, repository: opts.repo };
127
172
  }
128
173
  async function postJson(url, path, apiKey, appId, body, fetchImpl, timeoutMs, signer) {
129
174
  const deadline = timeoutMs === void 0 ? void 0 : startDeadline(timeoutMs);
130
175
  try {
131
- return await postJsonBefore(url, path, apiKey, appId, body, fetchImpl, deadline, signer);
176
+ return await sendJsonBefore("POST", url, path, apiKey, appId, body, fetchImpl, deadline, signer);
132
177
  } finally {
133
178
  deadline?.clear();
134
179
  }
135
180
  }
181
+ function patchJson(url, path, apiKey, appId, body, fetchImpl) {
182
+ return sendJsonBefore("PATCH", url, path, apiKey, appId, body, fetchImpl, void 0, void 0);
183
+ }
136
184
  function startDeadline(ms) {
137
185
  const controller = new AbortController();
138
186
  const timer = setTimeout(() => controller.abort(), ms);
139
187
  return { signal: controller.signal, ms, clear: () => clearTimeout(timer) };
140
188
  }
141
- async function postJsonBefore(url, path, apiKey, appId, body, fetchImpl, deadline, signer) {
189
+ async function sendJsonBefore(method, url, path, apiKey, appId, body, fetchImpl, deadline, signer) {
142
190
  let response;
143
191
  const endpoint = new URL(path, url).toString();
144
192
  const payload = JSON.stringify(body);
145
- const signature = await signatureHeaders("POST", endpoint, payload ?? "", signer);
193
+ const signature = await signatureHeaders(method, endpoint, payload ?? "", signer);
146
194
  try {
147
195
  response = await fetchImpl(endpoint, {
148
- method: "POST",
196
+ method,
149
197
  headers: {
150
198
  "content-type": "application/json",
151
199
  authorization: `Bearer ${apiKey}`,
@@ -264,6 +312,22 @@ async function findLiveItem(creds, repository, subject, fetchImpl) {
264
312
  const items = page.data ?? [];
265
313
  return items[0] ?? null;
266
314
  }
315
+ async function findLiveItemForIssue(creds, opts, fetchImpl) {
316
+ const subject = resolveWorkSubject(opts);
317
+ if ("issue" in subject) {
318
+ const item = await findLiveItem(creds, subject.repository, { issue: subject.issue }, fetchImpl);
319
+ return { item, label: `${subject.repository}#${subject.issue}` };
320
+ }
321
+ const query = new URLSearchParams({ key: subject.key });
322
+ if (subject.tracker !== void 0) query.set("tracker", subject.tracker);
323
+ const page = await getJson(creds.url, `/v1/work-items?${query.toString()}`, creds.apiKey, creds.appId, fetchImpl);
324
+ const items = page.data ?? [];
325
+ if (items.length > 1) {
326
+ const trackers = items.map((i) => i.tracker ?? "unknown").join(" and ");
327
+ throw new WorkCommandError(`${subject.key} names an item in ${trackers}. Pass --tracker to say which.`);
328
+ }
329
+ return { item: items[0] ?? null, label: subject.key };
330
+ }
267
331
  function environmentFacts(opts) {
268
332
  const identity = resolveRepoIdentity(opts.cwd);
269
333
  const sessionId = opts.sessionIdOverride ?? detectActiveSession({
@@ -336,9 +400,7 @@ async function runWorkBuild(opts) {
336
400
  const { data: data2 } = await postJsonWithRetry(url, "/v1/work-items", apiKey, appId, body2, fetchImpl, retries, sleep);
337
401
  const label = data2.number != null ? `#${data2.number}` : String(data2.workItemId);
338
402
  const launch = data2.number != null ? `OUTERLAYER_WORK=${data2.number} claude` : null;
339
- const branch = typeof data2.branch === "string" && data2.branch !== "" ? data2.branch : null;
340
- const output2 = opts.json ? JSON.stringify({ ...data2, ...launch !== null ? { launchCommand: launch } : {} }) : `${C.green}\u2713${C.reset} on Work for you to build ${C.dim}\xB7${C.reset} ${label} ${C.dim}\xB7${C.reset} no host will take it` + (branch !== null ? `
341
- branch: ${branch}` : "") + (launch !== null ? `
403
+ const output2 = opts.json ? JSON.stringify({ ...data2, ...launch !== null ? { launchCommand: launch } : {} }) : `${C.green}\u2713${C.reset} on Work for you to build ${C.dim}\xB7${C.reset} ${label} ${C.dim}\xB7${C.reset} no host will take it` + (launch !== null ? `
342
404
  start your session with: ${launch}` : "");
343
405
  if (!opts.quiet) process.stdout.write(output2 + "\n");
344
406
  return { data: data2, output: output2 };
@@ -360,7 +422,7 @@ async function runWorkLinkSession(opts) {
360
422
  return await linkSession(opts);
361
423
  } catch (err) {
362
424
  if (opts.logFailures) {
363
- const { logHookError } = await import('./hook-fast-D7HV4IXG.js');
425
+ const { logHookError } = await import('./hook-fast-W5MKHMJT.js');
364
426
  const reason = err instanceof Error ? err.message : String(err);
365
427
  logHookError(opts.home ?? homeFromEnv(opts.env ?? process.env), new Error(`work link-session #${opts.number} failed: ${reason}`));
366
428
  }
@@ -428,13 +490,10 @@ async function runWorkRemove(opts) {
428
490
  if (!opts.quiet) process.stdout.write(output2 + "\n");
429
491
  return { data: data2, output: output2 };
430
492
  }
431
- const subject = resolveSubject(opts);
432
- const repository = resolveRepository(opts.repo, cwd);
433
- const number = subject.issue;
434
- const item = await findLiveItem(creds, repository, subject, fetchImpl);
493
+ const { item, label } = await findLiveItemForIssue(creds, { ...opts, cwd }, fetchImpl);
435
494
  if (!item) {
436
495
  const data2 = { workItemId: null, removed: true, itemWithdrawn: false, noLiveAddition: true };
437
- const output2 = opts.json ? JSON.stringify(data2) : `${C.green}\u2713${C.reset} nothing to remove ${C.dim}\xB7${C.reset} no live addition on ${repository}#${number}`;
496
+ const output2 = opts.json ? JSON.stringify(data2) : `${C.green}\u2713${C.reset} nothing to remove ${C.dim}\xB7${C.reset} no live addition on ${label}`;
438
497
  if (!opts.quiet) process.stdout.write(output2 + "\n");
439
498
  return { data: data2, output: output2 };
440
499
  }
@@ -485,13 +544,10 @@ async function runWorkStatus(opts) {
485
544
  if (!opts.quiet) process.stdout.write(body + "\n");
486
545
  return { data: data2, output: body };
487
546
  }
488
- const subject = resolveSubject(opts);
489
- const repository = resolveRepository(opts.repo, cwd);
490
547
  const fetchImpl = opts.fetchImpl ?? defaultFetch;
491
- const number = subject.issue;
492
- const item = await findLiveItem(creds, repository, subject, fetchImpl);
548
+ const { item, label } = await findLiveItemForIssue(creds, { ...opts, cwd }, fetchImpl);
493
549
  if (!item) {
494
- throw new WorkCommandError(`no live item for ${repository}#${number}`);
550
+ throw new WorkCommandError(`no live item for ${label}`);
495
551
  }
496
552
  const { data } = await getJson(creds.url, `/v1/work-items/${item.id}`, creds.apiKey, creds.appId, fetchImpl);
497
553
  const output = statusOutput(data, opts.json === true);
@@ -536,4 +592,4 @@ async function runWorkList(opts) {
536
592
  return { data, output };
537
593
  }
538
594
 
539
- export { WorkCommandError, environmentFacts, findLiveItem, getJson, isSignatureRefusal, parsePositiveInt, postJson, resolveCredentials, resolveRepository, runWorkBuild, runWorkLinkSession, runWorkList, runWorkRemove, runWorkStatus, signatureRefusalMessage };
595
+ export { TRACKERS, WorkCommandError, environmentFacts, findLiveItemForIssue, getJson, isSignatureRefusal, parsePositiveInt, patchJson, postJson, resolveCredentials, runWorkBuild, runWorkLinkSession, runWorkList, runWorkRemove, runWorkStatus, signatureRefusalMessage, verifiedTrackerNames };
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
+ import { trackImageBuild, isOutOfMemory, ensureBuilder } from './chunk-S26M3YBJ.js';
3
4
  import { RecipeError } from './chunk-QOZKPLVJ.js';
4
- import { trackImageBuild, isOutOfMemory, ensureBuilder } from './chunk-4NPZVMJU.js';
5
5
  import { spawn } from 'child_process';
6
6
  import { existsSync, mkdirSync, createWriteStream, rmSync, readFileSync } from 'fs';
7
7
  import { join, dirname } from 'path';
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { CONTEXT_PIN_SCHEMA_VERSION, CONTEXT_PIN_FILENAME } from './chunk-OHVJA253.js';
4
- import { readFileSync, existsSync, writeFileSync, mkdirSync, utimesSync, statSync, unlinkSync } from 'fs';
3
+ import { CONTEXT_PIN_SCHEMA_VERSION, CONTEXT_PIN_FILENAME } from './chunk-X5N6KC6V.js';
4
+ import { readFileSync, existsSync, writeFileSync, mkdirSync, utimesSync, unlinkSync } from 'fs';
5
5
  import { join, dirname } from 'path';
6
6
 
7
7
  createRequire(import.meta.url);
@@ -59,7 +59,6 @@ function writeContextManifest(gitCommonDir, manifest) {
59
59
  function manifestFilesPresent(workpieceRoot, manifest) {
60
60
  return manifest.files.every((f) => existsSync(join(workpieceRoot, f)));
61
61
  }
62
- var DEBOUNCE_MS = 10 * 60 * 1e3;
63
62
  function lastCheckPath(gitCommonDir) {
64
63
  return join(stateDir(gitCommonDir), "last-check");
65
64
  }
@@ -73,14 +72,6 @@ function touchLastCheck(gitCommonDir, now) {
73
72
  } catch {
74
73
  }
75
74
  }
76
- function isLastCheckFresh(gitCommonDir, now, debounceMs = DEBOUNCE_MS) {
77
- try {
78
- const mtimeMs = statSync(lastCheckPath(gitCommonDir)).mtimeMs;
79
- return now - mtimeMs < debounceMs;
80
- } catch {
81
- return false;
82
- }
83
- }
84
75
  function degradedPath(gitCommonDir) {
85
76
  return join(stateDir(gitCommonDir), "degraded.json");
86
77
  }
@@ -130,4 +121,4 @@ function writeBuildHold(gitCommonDir, hold) {
130
121
  writeJson(buildHoldPath(gitCommonDir), hold);
131
122
  }
132
123
 
133
- export { SOURCE_CACHE_TTL_RETRY_MS, SOURCE_CACHE_TTL_SUCCESS_MS, clearDegraded, isLastCheckFresh, isSourceCacheFresh, manifestFilesPresent, pinExists, readBuildHold, readContextManifest, readDegraded, readPin, readSourceCache, touchLastCheck, writeBuildHold, writeContextManifest, writeDegraded, writePinIfChanged, writeSourceCache };
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 };
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { hostKeyPath, runnerDir, RUNNER_DIR_MODE, RUNNER_FILE_MODE } from './chunk-ZM2IMMYN.js';
3
+ import { hostKeyPath, runnerDir, RUNNER_DIR_MODE, RUNNER_FILE_MODE } from './chunk-N2PXGQRL.js';
4
4
  import { generateKeyPairSync, createPrivateKey, createPublicKey, sign } from 'crypto';
5
5
  import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'fs';
6
6
 
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
3
  import { compareVersions } from './chunk-I2UOAV7X.js';
4
- import { launcherPath, writeLauncher, LauncherWriteError, pathNotes } from './chunk-PTW6W5NR.js';
5
- import { currentVersion, currentLink, isInLayout, packageRootIn, versionDir, switchCurrent, execStartLine } from './chunk-TI7B7UEO.js';
6
- import { RUNNER_DIR_MODE } from './chunk-ZM2IMMYN.js';
4
+ import { launcherPath, writeLauncher, LauncherWriteError, pathNotes } from './chunk-VYAL7PUE.js';
5
+ import { currentVersion, currentLink, isInLayout, packageRootIn, versionDir, switchCurrent, execStartLine } from './chunk-AMFWYESY.js';
6
+ import { RUNNER_DIR_MODE } from './chunk-N2PXGQRL.js';
7
7
  import { realpathSync, readFileSync, mkdirSync, rmSync, cpSync, existsSync } from 'fs';
8
8
  import { dirname, sep, join } from 'path';
9
9
 
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { splitRawFile } from './chunk-OHVJA253.js';
3
+ import { splitRawFile } from './chunk-X5N6KC6V.js';
4
4
  import { resolvePackageVersion } from './chunk-RA3O54FC.js';
5
5
  import { existsSync, readFileSync, mkdirSync, writeFileSync, readdirSync } from 'fs';
6
6
  import { join, dirname } from 'path';
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { ArtifactTombstoneRecordSchema, ArtifactSpoolRecordSchema } from './chunk-J5M7BSJQ.js';
3
+ import { ArtifactTombstoneRecordSchema, ArtifactSpoolRecordSchema } from './chunk-N3CUDFCW.js';
4
4
  import { homeFromEnv } from './chunk-VNVZDWO3.js';
5
5
  import { mkdirSync, appendFileSync, writeFileSync, renameSync, unlinkSync, existsSync, readdirSync, readFileSync, statSync } from 'fs';
6
6
  import { join, dirname } from 'path';
@@ -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, existsSync, rmSync, mkdirSync, writeFileSync, renameSync } from 'fs';
5
5
  import { join } from 'path';
6
6
 
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
+ import { BUILD_HOME } from './chunk-BQXFBI7T.js';
3
4
  import { join, dirname } from 'path';
4
5
 
5
6
  createRequire(import.meta.url);
@@ -72,5 +73,12 @@ function diskTemplatesDir(runnerDirPath) {
72
73
  function vsockPath(buildDirPath) {
73
74
  return join(buildDirPath, "v.sock");
74
75
  }
76
+ var SHIM_DIR = `${BUILD_HOME}/.outerlayer/bin`;
77
+ function deliveryDir(repository, sha) {
78
+ if (!/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/.test(repository) || repository.split("/").some((part) => part === "." || part === "..") || !/^[0-9a-f]{7,64}$/.test(sha)) {
79
+ throw new Error(`cannot name a delivery directory for ${repository} at ${sha}`);
80
+ }
81
+ return `${BUILD_HOME}/.outerlayer/context/${repository}/${sha}`;
82
+ }
75
83
 
76
- export { RUNNER_DIR_MODE, RUNNER_FILE_MODE, attemptStamp, buildDir, contextHomeDir, diskTemplatesDir, ghConfigDir, hostKeyPath, imagesDir, jobDir, jobsDir, mirrorDir, pidFilePath, repoCacheDir, rootfsDir, rootfsPathFor, runnerDir, runnerDirOfBuild, spoolDir, stagedContextDir, vmAssetsDir, vsockPath };
84
+ export { RUNNER_DIR_MODE, RUNNER_FILE_MODE, SHIM_DIR, attemptStamp, buildDir, contextHomeDir, deliveryDir, diskTemplatesDir, ghConfigDir, hostKeyPath, imagesDir, jobDir, jobsDir, mirrorDir, pidFilePath, repoCacheDir, rootfsDir, rootfsPathFor, runnerDir, runnerDirOfBuild, spoolDir, stagedContextDir, vmAssetsDir, vsockPath };
@@ -21728,12 +21728,13 @@ var UsageSchema = external_exports.looseObject({
21728
21728
  * open string: the provider adds tiers over time. Absent means standard. */
21729
21729
  speed: external_exports.string().min(1).max(SPEED_MAX_LENGTH).optional()
21730
21730
  });
21731
- var INPUT_BAND_BOUNDARIES = [128e3, 2e5, 256e3, 272e3, 512e3];
21731
+ var INPUT_BAND_BOUNDARIES = [1e5, 128e3, 2e5, 256e3, 272e3, 512e3];
21732
21732
  function inputBandOf(totalInput) {
21733
21733
  let band = 0;
21734
21734
  for (const boundary of INPUT_BAND_BOUNDARIES) if (totalInput >= boundary) band = boundary;
21735
21735
  return band;
21736
21736
  }
21737
+ var BAND_BOUNDARIES_MAX = 64;
21737
21738
  var TOKEN_BUCKETS_MAX = 1024;
21738
21739
  var TokenBucketSchema = external_exports.looseObject({
21739
21740
  model: external_exports.string().min(1).max(BUCKET_MODEL_MAX_LENGTH),
@@ -21950,7 +21951,12 @@ var AgentSessionSchema = external_exports.looseObject({
21950
21951
  /** Token counts so far, per model, speed and input band. On a chunk part
21951
21952
  * or a streamed piece these cover the whole session so far, never just
21952
21953
  * the turns that payload carries. Absent from older writers. */
21953
- buckets: external_exports.array(TokenBucketSchema).max(TOKEN_BUCKETS_MAX).optional()
21954
+ buckets: external_exports.array(TokenBucketSchema).max(TOKEN_BUCKETS_MAX).optional(),
21955
+ /** The input band boundaries `buckets` were grouped by. A price tier whose
21956
+ * threshold falls inside one of these bands cannot be applied from the
21957
+ * buckets alone. Absent from older writers, which used
21958
+ * {@link UNRECORDED_INPUT_BAND_BOUNDARIES}. */
21959
+ bandBoundaries: external_exports.array(count).max(BAND_BOUNDARIES_MAX).optional()
21954
21960
  }),
21955
21961
  /** Filled natively (`pr-link` lines, `git commit` tool results) or by later
21956
21962
  * joins. A session can link MANY pull requests (stacked PRs, long-lived seat
@@ -22525,4 +22531,4 @@ xmlchars/xmlns/1.0/ed3.js:
22525
22531
  *)
22526
22532
  */
22527
22533
 
22528
- export { ARTIFACT_KINDS, ARTIFACT_MAX_CAPTION_LENGTH, ARTIFACT_MAX_FILENAME_LENGTH, ARTIFACT_MAX_REPLACES_TARGETS, ArtifactCriterionIdSchema, ArtifactSpoolRecordSchema, ArtifactTombstoneRecordSchema, BUCKET_MODEL_MAX_LENGTH, CAPTURE_TIERS, CriteriaListSchema, EMITTED_RESULTS, EMITTED_RESULT_MAX_BODY_LENGTH, EMITTED_RESULT_MAX_LINK_LENGTH, EVENT_TYPES, EmittedNameSchema, FindingBatchSchema, FindingsResponseSchema, RESERVED_EMIT_NAMES, SAME_PROBLEM_RULES, SCHEMA_VERSION, SPEED_MAX_LENGTH, bannedPathsForTier, bindTests, downconvertSession, inferArtifactKind, inputBandOf, isHumanUserTurn, mediaTypeForArtifactPath, parseAgentSession, parseJunit, parseTestSelector, turnCountBound };
22534
+ export { ARTIFACT_KINDS, ARTIFACT_MAX_CAPTION_LENGTH, ARTIFACT_MAX_FILENAME_LENGTH, ARTIFACT_MAX_REPLACES_TARGETS, ArtifactCriterionIdSchema, ArtifactSpoolRecordSchema, ArtifactTombstoneRecordSchema, BUCKET_MODEL_MAX_LENGTH, CAPTURE_TIERS, CriteriaListSchema, EMITTED_RESULTS, EMITTED_RESULT_MAX_BODY_LENGTH, EMITTED_RESULT_MAX_LINK_LENGTH, EVENT_TYPES, EmittedNameSchema, FindingBatchSchema, FindingsResponseSchema, INPUT_BAND_BOUNDARIES, RESERVED_EMIT_NAMES, SAME_PROBLEM_RULES, SCHEMA_VERSION, SPEED_MAX_LENGTH, bannedPathsForTier, bindTests, downconvertSession, inferArtifactKind, inputBandOf, isHumanUserTurn, mediaTypeForArtifactPath, parseAgentSession, parseJunit, parseTestSelector, turnCountBound };
@@ -1,9 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { revokeTokenOnDashboard } from './chunk-N6LURUEF.js';
4
- import { C } from './chunk-YRYMNBGQ.js';
3
+ import { revokeTokenOnDashboard } from './chunk-GOSFARMS.js';
4
+ import { C } from './chunk-ANPNT6PM.js';
5
5
  import { readCloudConfig, writeCloudConfig, cloudConfigPath } from './chunk-EABW6AJQ.js';
6
6
  import { findGitDirs } from './chunk-BJ3KTMDH.js';
7
+ import { cliInvocation } from './chunk-CRB3POP4.js';
7
8
  import { homeFromEnv } from './chunk-VNVZDWO3.js';
8
9
  import { generateKeyPairSync, privateDecrypt, constants, createPrivateKey } from 'crypto';
9
10
  import { spawn } from 'child_process';
@@ -18,7 +19,7 @@ var LoginError = class extends Error {
18
19
  };
19
20
  function runLogin(opts) {
20
21
  const apiKey = opts.apiKey.trim();
21
- if (apiKey.length === 0) throw new LoginError("no API key given \u2014 pipe it on stdin, or run outerlayer login with no key on stdin to sign in by browser");
22
+ if (apiKey.length === 0) throw new LoginError(`no API key given \u2014 pipe it on stdin, or run ${cliInvocation()} login with no key on stdin to sign in by browser`);
22
23
  if (/\s/.test(apiKey)) throw new LoginError("the API key must be a single token with no spaces or line breaks");
23
24
  const url = opts.url?.trim() || void 0;
24
25
  const appId = opts.appId?.trim() || void 0;
@@ -229,7 +230,7 @@ function decryptToken(privateKeyPem, encryptedToken) {
229
230
  Buffer.from(encryptedToken, "base64")
230
231
  ).toString("utf8");
231
232
  } catch {
232
- throw new LoginError("could not decrypt the token the dashboard sent; run outerlayer login again");
233
+ throw new LoginError(`could not decrypt the token the dashboard sent; run ${cliInvocation()} login again`);
233
234
  }
234
235
  }
235
236
  function normalizeDashboard(raw) {
@@ -246,7 +247,7 @@ function approveLink(dashboard, code) {
246
247
  return `${dashboard}/cli/login?code=${encodeURIComponent(code)}`;
247
248
  }
248
249
  function waitingDocument(link, code, id) {
249
- return JSON.stringify({ status: "waiting", url: link, code, check: `outerlayer login --check ${id}` }) + "\n";
250
+ return JSON.stringify({ status: "waiting", url: link, code, check: `${cliInvocation()} login --check ${id}` }) + "\n";
250
251
  }
251
252
  async function finishApproved(flags, deps, home, dashboard, approved, privateKeyPem) {
252
253
  const accountToken = decryptToken(privateKeyPem, approved.encryptedToken);
@@ -257,7 +258,7 @@ async function finishApproved(flags, deps, home, dashboard, approved, privateKey
257
258
  const revoked = await revokeTokenOnDashboard(deps.fetchImpl, dashboard, accountToken);
258
259
  return fail(
259
260
  deps,
260
- `could not save the login: ${err instanceof Error ? err.message : String(err)}. ` + (revoked === "revoked" ? "The token was revoked; run outerlayer login again." : "The token could not be revoked; revoke it on the CLI logins list at /profile/security.")
261
+ `could not save the login: ${err instanceof Error ? err.message : String(err)}. ` + (revoked === "revoked" ? `The token was revoked; run ${cliInvocation()} login again.` : "The token could not be revoked; revoke it on the CLI logins list at /profile/security.")
261
262
  );
262
263
  }
263
264
  if (before.accountToken && before.accountToken !== accountToken) {
@@ -279,9 +280,12 @@ async function finishApproved(flags, deps, home, dashboard, approved, privateKey
279
280
  }
280
281
  function nextAfterLogin(cwd) {
281
282
  const dirs = findGitDirs(cwd);
282
- if (dirs === void 0) return "Next: in your repository, run `outerlayer init --factory <org>/<factory>`.\n";
283
- if (existsSync(join(dirs.repoRoot, ".outerlayer"))) return "Next: run `outerlayer connect` to choose a factory.\n";
284
- return "Next: run `outerlayer init --factory <org>/<factory>` to set up this repository.\n";
283
+ if (dirs === void 0) return `Next: in your repository, run \`${cliInvocation()} init --factory <org>/<factory>\`.
284
+ `;
285
+ if (existsSync(join(dirs.repoRoot, ".outerlayer"))) return `Next: run \`${cliInvocation()} connect\` to choose a factory.
286
+ `;
287
+ return `Next: run \`${cliInvocation()} init --factory <org>/<factory>\` to set up this repository.
288
+ `;
285
289
  }
286
290
  function fail(deps, message) {
287
291
  deps.stderr.write(`${C.red}\u2717${C.reset} ${message}
@@ -301,10 +305,10 @@ async function runPastedKey(flags, deps, key, home) {
301
305
  }
302
306
  async function runCheck(flags, deps, home, id) {
303
307
  const pending = readPending(home, id);
304
- if (!pending) return fail(deps, `no pending login ${id}; run outerlayer login to start one`);
308
+ if (!pending) return fail(deps, `no pending login ${id}; run ${cliInvocation()} login to start one`);
305
309
  if (Date.parse(pending.expires_at) <= deps.now().getTime()) {
306
310
  deletePending(home, id);
307
- return fail(deps, "the login link expired; run outerlayer login again");
311
+ return fail(deps, `the login link expired; run ${cliInvocation()} login again`);
308
312
  }
309
313
  const result = await pollLogin(deps, pending.dashboard, pending.id);
310
314
  switch (result.kind) {
@@ -317,7 +321,7 @@ async function runCheck(flags, deps, home, id) {
317
321
  return fail(deps, "the login was denied");
318
322
  case "expired":
319
323
  deletePending(home, id);
320
- return fail(deps, "the login link expired; run outerlayer login again");
324
+ return fail(deps, `the login link expired; run ${cliInvocation()} login again`);
321
325
  case "unavailable":
322
326
  deps.stderr.write(`could not check the login yet: ${result.message}
323
327
  `);
@@ -376,7 +380,7 @@ Waiting for approval...
376
380
  case "denied":
377
381
  return fail(deps, "the login was denied");
378
382
  case "expired":
379
- return fail(deps, "the login link expired; run outerlayer login again");
383
+ return fail(deps, `the login link expired; run ${cliInvocation()} login again`);
380
384
  case "unavailable":
381
385
  case "error":
382
386
  failures += 1;
@@ -392,7 +396,7 @@ Waiting for approval...
392
396
  }
393
397
  const untilExpiryMs = Math.max(0, expiresAt - deps.now().getTime());
394
398
  await deps.sleep(Math.min(waitS * 1e3, untilExpiryMs));
395
- if (deps.now().getTime() >= expiresAt) return fail(deps, "the login link expired; run outerlayer login again");
399
+ if (deps.now().getTime() >= expiresAt) return fail(deps, `the login link expired; run ${cliInvocation()} login again`);
396
400
  }
397
401
  }
398
402
  async function runLoginCommand(flags, deps) {
@@ -414,7 +418,7 @@ async function runLoginCommand(flags, deps) {
414
418
  return EXIT_USAGE;
415
419
  }
416
420
  if (flags.noInput) {
417
- return fail(deps, 'no API key on stdin and --no-input forbids prompting \u2014 pipe the key: echo "$KEY" | outerlayer login');
421
+ return fail(deps, `no API key on stdin and --no-input forbids prompting \u2014 pipe the key: echo "$KEY" | ${cliInvocation()} login`);
418
422
  }
419
423
  purgeExpiredPending(home, deps.now());
420
424
  return await runBrowserLogin(flags, deps, home);
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { MIN_ENGINE_MAJOR } from './chunk-EWORLJMO.js';
3
+ import { MIN_ENGINE_MAJOR } from './chunk-Y5MXET4M.js';
4
4
  import { firecrackerArch, MICROVM_ARCHES, guestAssetsPinned } from './chunk-CX22S5BA.js';
5
5
  import { spawnSync } from 'child_process';
6
6
  import { existsSync, accessSync, constants, statSync, readFileSync } from 'fs';
@@ -1,30 +1,31 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { LEASE_SECONDS, releaseLease, isUnfinished, setStage, jobEnv, runHook, describeHookEnd, provisionMicroVm, deliverCommitHooks, provisionProcess, provisionEnvironment, readProvisionOut, resolveHostBuild, workdirProblem, listenOnBroker, hostEnvironment, hostCommandEnvironment, execArgv, microVmCommandLine, runCommand, execCommandLine, startSender, startHostServices, finishJob, isGroupAlive, outcomeFromExitCode, isTimedOut, readCpuUsec, isIdle, stopOrphanedMicroVms, unfinishedJobs, listAdoptableJobs, retryFailedReleases, recoverLostJobs, hookLimitsFor, needsRenew, renewLease, RENEW_INTERVAL_SECONDS, ALREADY_RELEASED } from './chunk-R4ZQQ7U2.js';
4
- import { writePendingUpdate } from './chunk-O765JR4W.js';
5
- import { readHousekeepingRecord, writeHousekeepingRecord } from './chunk-UGP76IZ5.js';
6
3
  import { decideInstalledSwitch } from './chunk-3JVYMD4G.js';
7
- import { fetchVersionMeta, npmVersion, npmSupportsProvenance, fetchTarballDigest, fetchProvenance, installVersion, auditSignatures } from './chunk-YETTWTAY.js';
8
- import { writeJobFile, readJobFile, readJobFileChecked } from './chunk-RMWLBUCJ.js';
9
4
  import { compareVersions, satisfiesRange } from './chunk-I2UOAV7X.js';
10
- import { RUNNER_PROTOCOL } from './chunk-ADJRGVZC.js';
11
- import { currentSkillCommand, formerSkillProblem, placeholderQueues, placeholderProblem } from './chunk-FWX735W7.js';
5
+ import { fetchVersionMeta, npmVersion, npmSupportsProvenance, fetchTarballDigest, fetchProvenance, installVersion, auditSignatures } from './chunk-YETTWTAY.js';
6
+ import { LEASE_SECONDS, releaseLease, isUnfinished, setStage, jobEnv, runHook, describeHookEnd, provisionMicroVm, deliverCommitHooks, provisionProcess, provisionEnvironment, readProvisionOut, resolveHostBuild, workdirProblem, listenOnBroker, hostEnvironment, hostCommandEnvironment, execArgv, microVmCommandLine, runCommand, execCommandLine, startSender, startHostServices, finishJob, isGroupAlive, outcomeFromExitCode, isTimedOut, readCpuUsec, isIdle, stopOrphanedMicroVms, unfinishedJobs, listAdoptableJobs, retryFailedReleases, recoverLostJobs, hookLimitsFor, needsRenew, renewLease, RENEW_INTERVAL_SECONDS, ALREADY_RELEASED } from './chunk-3OFZM4X6.js';
7
+ import { writeJobFile, readJobFile, readJobFileChecked } from './chunk-SADUQSO4.js';
8
+ import { RUNNER_PROTOCOL } from './chunk-KDVIU23F.js';
9
+ import { writePendingUpdate } from './chunk-MTP2QEVO.js';
10
+ import { readHousekeepingRecord, writeHousekeepingRecord } from './chunk-S5PCA3SN.js';
11
+ import { currentSkillCommand, formerSkillProblem, placeholderQueues, placeholderProblem } from './chunk-FUB7LRUE.js';
12
+ import { writeMarker, readMarker, currentVersion, removeMarker, entryIn, versionDir, startedThroughCurrent, switchCurrent, cleanVersions, isInLayout, stagingDir } from './chunk-AMFWYESY.js';
12
13
  import { freeBytes, formatBytes } from './chunk-YYYRBYWG.js';
13
- import { writeMarker, readMarker, currentVersion, removeMarker, entryIn, versionDir, startedThroughCurrent, switchCurrent, cleanVersions, isInLayout, stagingDir } from './chunk-TI7B7UEO.js';
14
14
  import { RepoFilter } from './chunk-TBT347UY.js';
15
- import { describeCallFailure, retrySend, shortClaim, relativeToRunner, formatDuration, provisionContainer, lifecycleSteps, lifecycleFailureReason, prepareBranch, containerCommandLine, BuildTokens, classifyRefusal, refusalCode, measureDisk, createRunnerLog, setUpRunnerCgroup, parseCpuList, ensureTunnel, keepGhConfigCurrent, createContainerRuntime, formatClock } from './chunk-EWORLJMO.js';
16
- import { spawnRun } from './chunk-KMDLFI4P.js';
17
- import { checkFit } from './chunk-RLYZLUQ7.js';
18
- import { isSignatureRefusal, WorkCommandError, getJson, postJson } from './chunk-6QRMLNH3.js';
19
- import { isBuiltinContainer, isBuiltinVm, isBuiltinProcess, loadRunnerConfig, checkHooks, builtinKind, DEFAULT_UPDATE_MAX_WAIT_HOURS } from './chunk-22RMZBGW.js';
20
- import { startTimeOf, claimPidFile, readPidFile, isSameProcess, releasePidFile } from './chunk-N5FOE5PS.js';
21
- import { builderName, runnerLabelValue, ensureFailureCount, builderSpec, ensureBuilder, BUILD_LABEL, RUNNER_LABEL } from './chunk-4NPZVMJU.js';
15
+ import { provisionContainer, lifecycleSteps, lifecycleFailureReason, prepareBranch, containerCommandLine, measureDisk, setUpRunnerCgroup, parseCpuList, ensureTunnel, keepGhConfigCurrent, createContainerRuntime } from './chunk-Y5MXET4M.js';
16
+ import { spawnRun } from './chunk-L2USZT6T.js';
17
+ import { builderName, runnerLabelValue, ensureFailureCount, builderSpec, ensureBuilder, BUILD_LABEL, RUNNER_LABEL } from './chunk-S26M3YBJ.js';
18
+ import { describeCallFailure, retrySend, shortClaim, relativeToRunner, formatDuration, BuildTokens, classifyRefusal, refusalCode, createRunnerLog, formatClock } from './chunk-6CHIYEZZ.js';
19
+ import { checkFit } from './chunk-WGAUY5LE.js';
20
+ import { isSignatureRefusal, WorkCommandError, getJson, postJson } from './chunk-KK4VBOH6.js';
21
+ import { isBuiltinContainer, isBuiltinVm, isBuiltinProcess, loadRunnerConfig, checkHooks, builtinKind, DEFAULT_UPDATE_MAX_WAIT_HOURS } from './chunk-XGP3VYOG.js';
22
22
  import { exceedsDisk } from './chunk-7RQ73DLO.js';
23
- import { parseClaimedRepositories, repositoriesOf, primaryOf, sharedUserEnvironment, JOB_MOUNT, claudeCredential } from './chunk-4Q7OMKAT.js';
24
- import { parseClaimIdentity } from './chunk-BYT5O5RV.js';
23
+ import { claimPidFile, readPidFile, releasePidFile } from './chunk-ECODQ7II.js';
24
+ import { startTimeOf, isSameProcess } from './chunk-JBJTC3UU.js';
25
25
  import { resolveVersion } from './chunk-RA3O54FC.js';
26
- import { loadHostKey, ensureHostKey, signerFor } from './chunk-V7NIVOFD.js';
27
- import { RUNNER_DIR_MODE, runnerDir, buildDir, attemptStamp, jobDir, jobsDir, pidFilePath, spoolDir, RUNNER_FILE_MODE, rootfsDir } from './chunk-ZM2IMMYN.js';
26
+ import { loadHostKey, ensureHostKey, signerFor } from './chunk-M2ZWWTWZ.js';
27
+ import { RUNNER_DIR_MODE, runnerDir, buildDir, attemptStamp, jobDir, jobsDir, pidFilePath, spoolDir, RUNNER_FILE_MODE, rootfsDir } from './chunk-N2PXGQRL.js';
28
+ import { parseClaimIdentity, parseClaimedRepositories, repositoriesOf, primaryOf, sharedUserEnvironment, JOB_MOUNT, claudeCredential } from './chunk-BQXFBI7T.js';
28
29
  import { HOOKS_DIR_NAME, writeCommitHooks } from './chunk-XCCLFVXM.js';
29
30
  import { randomBytes } from 'crypto';
30
31
  import { mkdirSync, existsSync, chmodSync, statSync, readdirSync, readFileSync, rmSync, renameSync, writeFileSync, closeSync, openSync, constants, lstatSync } from 'fs';
@@ -839,8 +840,11 @@ function reportRepeating(state, key, message, level = "error") {
839
840
  }
840
841
  }
841
842
  function deriveRepo(item) {
842
- const host = item.tracker === void 0 ? void 0 : TRACKER_REPOSITORY_HOSTS[item.tracker];
843
- if (host === void 0) return void 0;
843
+ if (item.tracker === void 0) return void 0;
844
+ const host = TRACKER_REPOSITORY_HOSTS[item.tracker];
845
+ if (host === void 0) {
846
+ return item.specRepository ? `${TRACKER_REPOSITORY_HOSTS.github}/${item.specRepository}` : void 0;
847
+ }
844
848
  const hash = item.trackerKey.lastIndexOf("#");
845
849
  const repoPart = hash === -1 ? item.trackerKey : item.trackerKey.slice(0, hash);
846
850
  return repoPart === "" ? void 0 : `${host}/${repoPart}`;
@@ -1315,7 +1319,7 @@ var CLAIM_REFUSAL_CODES = new Set(
1315
1319
  "pull_request_from_fork pull_request_on_default_branch pull_request_ambiguous pull_request_repository_not_connected branch_claimed_elsewhere".split(" ")
1316
1320
  );
1317
1321
  async function tryClaimAndStart(state, item, queue) {
1318
- const { postJson: postJson2 } = await import('./work-cmd-DJQJEZVB.js');
1322
+ const { postJson: postJson2 } = await import('./work-cmd-7S5B2H2P.js');
1319
1323
  const log = logOf(state);
1320
1324
  const hostKey = await loadHostKey(state.config.configPath);
1321
1325
  const claim = await retrySend(
@@ -1610,6 +1614,7 @@ async function startJob(state, item, queue, claimId, itemKey, branch, identity,
1610
1614
  config: state.config,
1611
1615
  runtime: runtimeOf(state),
1612
1616
  item,
1617
+ repository: primary?.repository,
1613
1618
  itemKey,
1614
1619
  jobDir: dirPath,
1615
1620
  cliVersion,
@@ -1635,10 +1640,10 @@ async function startJob(state, item, queue, claimId, itemKey, branch, identity,
1635
1640
  installCommitHooks(active.job, log, tag);
1636
1641
  } else {
1637
1642
  const runtime = runtimeOf(state);
1638
- const build = await startHostBuild(state, active, item.specRepository ?? void 0);
1643
+ const build = await startHostBuild(state, active, primary?.repository);
1639
1644
  const provisionEnv = provisionEnvironment(jobEnv(state.config, item.number, itemKey, dirPath, process.env, branch, identity?.author), {
1640
1645
  buildDir: build.state.buildDir,
1641
- repository: item.specRepository,
1646
+ repository: primary?.repository ?? null,
1642
1647
  recipeCommit: build.recipeCommit,
1643
1648
  limits: {
1644
1649
  memory: state.config.build?.memory ?? "8g",
@@ -1978,7 +1983,7 @@ async function renewLeaseIfDue(state, active, nowMs) {
1978
1983
  }
1979
1984
  async function watchTick(state, active, nowMs, logMtimeMs) {
1980
1985
  if (active.ending) {
1981
- if (active.job.stage === "checks") await renewLeaseIfDue(state, active, nowMs);
1986
+ if (active.job.stage === "checks" || active.job.stage === "judge") await renewLeaseIfDue(state, active, nowMs);
1982
1987
  return;
1983
1988
  }
1984
1989
  const log = logOf(state);
@@ -2074,7 +2079,7 @@ async function start(configPath, deps = { fetchImpl: fetch }) {
2074
2079
  const outcome = await onStartUnderMarker({
2075
2080
  configPath,
2076
2081
  own: ownVersionOf(deps),
2077
- check: update.check ? () => update.check(configPath) : async () => (await import('./check-CNTMSGOG.js')).runRunnerCheck(configPath, { fetchImpl: deps.fetchImpl }),
2082
+ check: update.check ? () => update.check(configPath) : async () => (await import('./check-5C4YDZYV.js')).runRunnerCheck(configPath, { fetchImpl: deps.fetchImpl }),
2078
2083
  now: () => (deps.now ?? (() => /* @__PURE__ */ new Date()))().getTime(),
2079
2084
  log
2080
2085
  });