@outerlayer/cli 0.14.1 → 0.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/{agent-setup-CN2HUBEJ.js → agent-setup-K3ABU5NL.js} +8 -7
  3. package/dist/build-info.json +1 -1
  4. package/dist/{check-SRGR36KI.js → check-CNTMSGOG.js} +20 -17
  5. package/dist/{chunk-HFKKFTXU.js → chunk-2MNPHL23.js} +19 -11
  6. package/dist/{chunk-FOJGZYFC.js → chunk-42ZI52JW.js} +1 -1
  7. package/dist/{chunk-SXWS25JC.js → chunk-5FEK6PNE.js} +6 -6
  8. package/dist/{chunk-PQUM37BK.js → chunk-6JNURGOA.js} +1 -1
  9. package/dist/{chunk-SWHQ4LUM.js → chunk-6QRMLNH3.js} +21 -3
  10. package/dist/{chunk-FI5UYJMQ.js → chunk-ADJRGVZC.js} +1 -1
  11. package/dist/chunk-C5Y5ZJJZ.js +88 -0
  12. package/dist/{chunk-Q2UK3C4P.js → chunk-CA3XMYFN.js} +3 -3
  13. package/dist/{chunk-NHDVD7DU.js → chunk-EHAAPRWY.js} +13 -11
  14. package/dist/{chunk-RBKIH5ST.js → chunk-EWORLJMO.js} +19 -5
  15. package/dist/{chunk-SMHOCDCI.js → chunk-FWX735W7.js} +18 -4
  16. package/dist/{chunk-3NLOVYJQ.js → chunk-JEHRUE3F.js} +47 -22
  17. package/dist/{chunk-MTF3PHVZ.js → chunk-NBGDBTO2.js} +3 -3
  18. package/dist/{chunk-2M63GG56.js → chunk-OHVJA253.js} +1 -1
  19. package/dist/{chunk-KFRM23WD.js → chunk-ONRCEE6D.js} +2 -2
  20. package/dist/{chunk-T5VPP6H7.js → chunk-OZGHL5Y5.js} +1 -1
  21. package/dist/{chunk-ZA5CHAFY.js → chunk-POJMEEJJ.js} +21 -4
  22. package/dist/{chunk-4OGPT6I2.js → chunk-R4ZQQ7U2.js} +28 -6
  23. package/dist/{chunk-JYIEHQIF.js → chunk-RSPXEVDX.js} +1 -1
  24. package/dist/{chunk-MSASO5O4.js → chunk-U3HXXRTY.js} +1 -1
  25. package/dist/{chunk-HFKQIZXL.js → chunk-W3EKCZSQ.js} +12 -5
  26. package/dist/{chunk-LCEXHCHD.js → chunk-WTE3MQML.js} +1 -1
  27. package/dist/{cli-UW2H3UUW.js → cli-AEWH62UE.js} +61 -58
  28. package/dist/{command-5LD7G2QQ.js → command-HHPBR6CS.js} +8 -7
  29. package/dist/{context-adopt-PJUMW2EZ.js → context-adopt-VMMGFRUZ.js} +5 -4
  30. package/dist/{context-materialize-FDHYKNDT.js → context-materialize-2WXTS4CW.js} +5 -4
  31. package/dist/{doctor-H7REBSLQ.js → doctor-N6Y7HKK3.js} +11 -10
  32. package/dist/{emit-artifact-cmd-FOGNJXVR.js → emit-artifact-cmd-H5MH3AOP.js} +2 -2
  33. package/dist/{emit-cmd-ZEYWLC2C.js → emit-cmd-IJ3GVRFD.js} +4 -3
  34. package/dist/{emit-finding-cmd-DLI4MKMN.js → emit-finding-cmd-ZXDRL6PG.js} +158 -45
  35. package/dist/{emit-result-cmd-MUSL7GQA.js → emit-result-cmd-RFKALS5Z.js} +2 -2
  36. package/dist/{hook-fast-WYQD6D7T.js → hook-fast-D7HV4IXG.js} +1 -1
  37. package/dist/{import-capture-cmd-6QVCOIHK.js → import-capture-cmd-EQ35EARA.js} +3 -3
  38. package/dist/{import-ruler-cmd-KLRGRBCP.js → import-ruler-cmd-BGAZXCQM.js} +1 -1
  39. package/dist/index.js +3 -3
  40. package/dist/{init-UBXK6MF7.js → init-FBCA4DRA.js} +10 -9
  41. package/dist/{init-NTXA3SN7.js → init-MYX7YMIH.js} +10 -9
  42. package/dist/{init-cmd-NARDUPIG.js → init-cmd-CAG572UE.js} +9 -8
  43. package/dist/{init-update-O5YYFGF4.js → init-update-VDFF4K3B.js} +9 -8
  44. package/dist/{loop-SW2M5VDD.js → loop-75J4YXLZ.js} +17 -16
  45. package/dist/{machine-U66FKVDP.js → machine-A6ZCTUGS.js} +8 -7
  46. package/dist/{runner-env-XTC53CHN.js → runner-env-EN7YE7QX.js} +1 -1
  47. package/dist/{runner-key-3JSMDRJA.js → runner-key-W25ISHI3.js} +10 -9
  48. package/dist/{session-sender-4M247XSV.js → session-sender-24L5EW25.js} +3 -3
  49. package/dist/{starter-pack-IB4UUIX3.js → starter-pack-KF66HGZR.js} +3 -3
  50. package/dist/{status-STZYPU3W.js → status-XHSGEYO5.js} +11 -10
  51. package/dist/{sync-cmd-UWD5JOFU.js → sync-cmd-5G5EIEHD.js} +2 -2
  52. package/dist/{watch-DBNB7R6X.js → watch-UTOXO4SE.js} +2 -2
  53. package/dist/{work-claim-cmd-LY4U6QHN.js → work-claim-cmd-RKHYFE5Y.js} +4 -4
  54. package/dist/{work-cmd-RVRQ32EH.js → work-cmd-DJQJEZVB.js} +1 -1
  55. package/dist/{work-comment-cmd-FFUM4TJU.js → work-comment-cmd-A55CUSYE.js} +1 -1
  56. package/dist/{work-open-pr-cmd-HLDWP4T2.js → work-open-pr-cmd-E6O53IJD.js} +1 -1
  57. package/package.json +1 -1
  58. package/skill-pack/maintained/{amend → outerlayer-amend}/SKILL.md +2 -2
  59. package/skill-pack/maintained/{outerlayer → outerlayer-cli}/SKILL.md +3 -3
  60. package/skill-pack/maintained/{emitting-evidence → outerlayer-evidence}/SKILL.md +1 -1
  61. package/skill-pack/maintained/{reporting-findings → outerlayer-findings}/SKILL.md +24 -30
  62. package/skill-pack/shipped.json +10 -1
  63. package/skill-pack/template/build/SKILL.md +5 -1
  64. package/skill-pack/template/build/references/agent-briefs.md +7 -1
  65. package/skill-pack/template/build/references/evidence.md +1 -1
  66. package/skill-pack/template/build/references/release.md +1 -1
  67. package/skill-pack/template/build/references/review-briefs.md +6 -0
  68. package/skill-pack/template/writing-specs/SKILL.md +1 -1
  69. /package/skill-pack/maintained/{outerlayer → outerlayer-cli}/references/open-pull-request.md +0 -0
  70. /package/skill-pack/maintained/{emitting-evidence → outerlayer-evidence}/references/agents-snippet.md +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,33 @@
1
1
  # @outerlayer/cli
2
2
 
3
+ ## 0.16.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 8f583f5: A build's log now always says the session sender exited before it says sync started. The runner waited only until the sender's process was gone, and Node can report the exit a moment later, so the two lines could swap.
8
+
9
+ ## 0.16.0
10
+
11
+ ### Minor Changes
12
+
13
+ - 87c8154: `outerlayer emit finding` and `emit findings` now record the time every finding cost. The start is `--started-at`, else the first tool output that contains the finding's `--error` text. The end is `--ended-at`, else the newest event. When the session has events and no start is found, nothing is stored, and the command lists the recent events with their ids. Events now include the session's subagents, with ids such as `a4962c00:e23`. `--find <text>` searches every event and records nothing. `--untimed` records a finding with no time on purpose. A session with no transcript on the machine records findings as before. The starter `/build` skill now tells its agents to record the factory problems they hit; `outerlayer init --update` brings it to repositories set up earlier.
14
+ - a076be0: The maintained skills now start with `outerlayer-`, so none can land on a skill of your own: `amend` is `outerlayer-amend`, `emitting-evidence` is `outerlayer-evidence`, `reporting-findings` is `outerlayer-findings`, and `outerlayer` is `outerlayer-cli`. `outerlayer context emit` writes each under its new name and deletes the old copies, so run it and commit. `--check` reports old copies as `retired`. A skill of your own with an earlier name is left alone. Governed checkouts show each skill once, under its new name, before the control plane is updated. The runner runs `/outerlayer-amend` for a command that still says `/amend`, and says so; change `runner.commands.amend` to match. `outerlayer doctor` lists skill files that still use an earlier name. See https://docs.outerlayer.ai/upgrade.
15
+
16
+ ### Patch Changes
17
+
18
+ - 7b425ca: A runner build now gives the gateway 10 seconds, and one retry, to say which control plane governs the item's repository. When the lookup still fails, `context_unavailable` says whether it timed out, what status the gateway answered, or what network error occurred. Session starts keep their 2-second limit.
19
+
20
+ ## 0.15.0
21
+
22
+ ### Minor Changes
23
+
24
+ - 9f42028: `outerlayer work status` now shows the acceptance criteria recorded for an item, in a Criteria section marked "drafted by the build" when the build wrote them, and as `criteria` in `--json`. The `get_work_item` MCP tool returns the same field.
25
+
26
+ ### Patch Changes
27
+
28
+ - e5b5713: A runner with `runner.update.maxWaitHours` set to 0 now claims nothing while a build runs and an update is pending. A clock tick between two reads in the same pass could leave the wait looking one millisecond short and let that pass claim work.
29
+ - 8d3eacb: Update the runner protocol contract to match the gateway's repository governance answer.
30
+
3
31
  ## 0.14.1
4
32
 
5
33
  ### Patch Changes
@@ -1,17 +1,18 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- export { keepHandWritten, runAgentSetup } from './chunk-SXWS25JC.js';
4
- import './chunk-HFKKFTXU.js';
3
+ export { keepHandWritten, runAgentSetup } from './chunk-5FEK6PNE.js';
4
+ import './chunk-2MNPHL23.js';
5
5
  import './chunk-XCK2YAY5.js';
6
- import './chunk-FOJGZYFC.js';
6
+ import './chunk-42ZI52JW.js';
7
7
  import './chunk-YRYMNBGQ.js';
8
- import './chunk-3NLOVYJQ.js';
9
- import './chunk-LCEXHCHD.js';
8
+ import './chunk-JEHRUE3F.js';
9
+ import './chunk-WTE3MQML.js';
10
+ import './chunk-C5Y5ZJJZ.js';
10
11
  import './chunk-ZJSNLVCE.js';
11
12
  import './chunk-YO4PSLVB.js';
12
13
  import './chunk-BYT5O5RV.js';
13
- import './chunk-ZA5CHAFY.js';
14
- import './chunk-2M63GG56.js';
14
+ import './chunk-POJMEEJJ.js';
15
+ import './chunk-OHVJA253.js';
15
16
  import './chunk-PLMTLGYH.js';
16
17
  import './chunk-J5M7BSJQ.js';
17
18
  import './chunk-EABW6AJQ.js';
@@ -1 +1 @@
1
- {"id":"2026-10-09T00:29:08.046Z+2d52691","root":"/home/runner/_work/outerlayer/outerlayer","pkg":"outerlayer"}
1
+ {"id":"2026-10-09T18:11:10.939Z+a3c670b","root":"/home/runner/_work/outerlayer/outerlayer","pkg":"outerlayer"}
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { probeCredentials } from './chunk-NHDVD7DU.js';
4
- import './chunk-4OGPT6I2.js';
3
+ import { probeCredentials } from './chunk-EHAAPRWY.js';
4
+ import './chunk-R4ZQQ7U2.js';
5
5
  import './chunk-O765JR4W.js';
6
6
  import './chunk-UGP76IZ5.js';
7
7
  import './chunk-3JVYMD4G.js';
@@ -9,24 +9,24 @@ import './chunk-YETTWTAY.js';
9
9
  import './chunk-RMWLBUCJ.js';
10
10
  import './chunk-I2UOAV7X.js';
11
11
  import './chunk-HYZRY4KZ.js';
12
- import './chunk-FI5UYJMQ.js';
13
- import './chunk-KFRM23WD.js';
14
- import './chunk-MSASO5O4.js';
12
+ import './chunk-ADJRGVZC.js';
13
+ import './chunk-ONRCEE6D.js';
14
+ import './chunk-U3HXXRTY.js';
15
15
  import './chunk-HHJDN6AU.js';
16
- import { placeholderQueues, placeholderProblem, permissionModeProblems, permissionModeProblem, needsClaudeCredential, claudeCredentialCheck, claimPermissionProblem } from './chunk-SMHOCDCI.js';
16
+ import { placeholderQueues, placeholderProblem, permissionModeProblems, permissionModeProblem, needsClaudeCredential, claudeCredentialCheck, claimPermissionProblem, formerSkillQueues, formerSkillProblem } from './chunk-FWX735W7.js';
17
17
  import './chunk-YYYRBYWG.js';
18
18
  import './chunk-TI7B7UEO.js';
19
19
  import './chunk-TBT347UY.js';
20
- import './chunk-Q2UK3C4P.js';
21
- import './chunk-JYIEHQIF.js';
22
- import './chunk-RBKIH5ST.js';
20
+ import './chunk-CA3XMYFN.js';
21
+ import './chunk-RSPXEVDX.js';
22
+ import './chunk-EWORLJMO.js';
23
23
  import './chunk-KMDLFI4P.js';
24
24
  import './chunk-QKFB4K7X.js';
25
25
  import './chunk-RSNSZ2LJ.js';
26
- import './chunk-T5VPP6H7.js';
26
+ import './chunk-OZGHL5Y5.js';
27
27
  import './chunk-RLYZLUQ7.js';
28
28
  import { parseRunnerEnv } from './chunk-6MZSX4M7.js';
29
- import './chunk-SWHQ4LUM.js';
29
+ import './chunk-6QRMLNH3.js';
30
30
  import './chunk-NPQWKGUA.js';
31
31
  import './chunk-IP7BIBXJ.js';
32
32
  import { loadRunnerConfig, RunnerConfigError, checkHooks } from './chunk-22RMZBGW.js';
@@ -50,20 +50,21 @@ import './chunk-YRYMNBGQ.js';
50
50
  import './chunk-GQD22KKN.js';
51
51
  import './chunk-WZBHBH3J.js';
52
52
  import './chunk-5QRP3MVS.js';
53
- import './chunk-3NLOVYJQ.js';
54
- import './chunk-LCEXHCHD.js';
53
+ import './chunk-JEHRUE3F.js';
54
+ import './chunk-WTE3MQML.js';
55
+ import './chunk-C5Y5ZJJZ.js';
55
56
  import './chunk-ZJSNLVCE.js';
56
57
  import './chunk-YO4PSLVB.js';
57
58
  import './chunk-BYT5O5RV.js';
58
- import './chunk-ZA5CHAFY.js';
59
- import './chunk-2M63GG56.js';
59
+ import './chunk-POJMEEJJ.js';
60
+ import './chunk-OHVJA253.js';
60
61
  import './chunk-PLMTLGYH.js';
61
62
  import './chunk-J5M7BSJQ.js';
62
63
  import './chunk-EABW6AJQ.js';
63
64
  import './chunk-RA3O54FC.js';
64
65
  import './chunk-V7NIVOFD.js';
65
66
  import './chunk-ZM2IMMYN.js';
66
- import './chunk-PQUM37BK.js';
67
+ import './chunk-6JNURGOA.js';
67
68
  import './chunk-XCCLFVXM.js';
68
69
  import './chunk-BJ3KTMDH.js';
69
70
  import './chunk-VNVZDWO3.js';
@@ -130,6 +131,7 @@ async function runRunnerCheck(configPath, deps = {}) {
130
131
  return { ok: false, check: "claim permission", message: `${configPath}: ${claimProblem.problem}` };
131
132
  }
132
133
  const unverifiedReason = probe.ok ? claimProblem.reason : probe.reason;
134
+ const formerSkill = formerSkillQueues(config);
133
135
  const lines = [
134
136
  `config ${configPath}`,
135
137
  `host ${config.host}`,
@@ -145,7 +147,8 @@ async function runRunnerCheck(configPath, deps = {}) {
145
147
  `hook cleanup ${config.hooks.cleanup}`,
146
148
  `hook report ${config.hooks.report ?? "(none)"}`,
147
149
  `repos include ${config.repos?.include?.join(", ") ?? "(all)"}`,
148
- `repos exclude ${config.repos?.exclude?.join(", ") ?? "(none)"}`
150
+ `repos exclude ${config.repos?.exclude?.join(", ") ?? "(none)"}`,
151
+ ...formerSkill.length > 0 ? [`note ${formerSkillProblem(formerSkill)}`] : []
149
152
  ];
150
153
  return { ok: true, lines, unverifiedReason, summary: `${config.url} \xB7 app ${config.appId}` };
151
154
  }
@@ -1,8 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
3
  import { C } from './chunk-YRYMNBGQ.js';
4
- import { maintainedFilesForExistingSkills, loadMaintainedFiles, writeMaintainedFiles } from './chunk-ZA5CHAFY.js';
5
- import { emitTree, parseOuterlayerConfig, classifyTree, generatedHeaderSource, CONTEXT_PIN_FILENAME, normalizePath } from './chunk-2M63GG56.js';
4
+ import { retiredSkillPaths, removeRetiredSkills } from './chunk-C5Y5ZJJZ.js';
5
+ import { maintainedFilesForExistingSkills, loadMaintainedFiles, writeMaintainedFiles } from './chunk-POJMEEJJ.js';
6
+ import { emitTree, parseOuterlayerConfig, classifyTree, generatedHeaderSource, CONTEXT_PIN_FILENAME, normalizePath } from './chunk-OHVJA253.js';
6
7
  import { existsSync, readFileSync, mkdirSync, writeFileSync, copyFileSync, readdirSync } from 'fs';
7
8
  import { join, dirname, relative, sep } from 'path';
8
9
 
@@ -49,9 +50,9 @@ function walk(dir, repoRoot, insideOuterlayer, out) {
49
50
  }
50
51
  }
51
52
  }
52
- function buildEmitInput(repoRoot, targets, maintained) {
53
+ function buildEmitInput(repoRoot, targets, maintained, excluded = /* @__PURE__ */ new Set()) {
53
54
  const bundled = new Map(maintained.map((f) => [f.path, f.content]));
54
- const discovered = [.../* @__PURE__ */ new Set([...discoverOuterlayerPaths(repoRoot), ...bundled.keys()])].sort();
55
+ const discovered = [.../* @__PURE__ */ new Set([...discoverOuterlayerPaths(repoRoot).filter((p) => !excluded.has(p)), ...bundled.keys()])].sort();
55
56
  const { entries } = classifyTree(discovered);
56
57
  const classified = new Set(entries.map((e) => e.path));
57
58
  const contents = /* @__PURE__ */ new Map();
@@ -80,12 +81,13 @@ function writeOutputs(repoRoot, result, maintained) {
80
81
  }
81
82
  return { files, copies, maintained: [...changedMaintained.created, ...changedMaintained.rewritten] };
82
83
  }
83
- function renderSuccess(targets, files, copies, maintained) {
84
+ function renderSuccess(targets, files, copies, maintained, retired) {
84
85
  const copySuffix = copies.length > 0 ? `, ${copies.length} ${copies.length === 1 ? "copy" : "copies"}` : "";
85
86
  const lines = [
86
87
  `${C.green}\u2713${C.reset} emitted ${files.length} file${files.length === 1 ? "" : "s"}${copySuffix} for ${C.dim}${targets.join(", ")}${C.reset}`
87
88
  ];
88
89
  for (const path of maintained) lines.push(` ${C.dim}updated ${path} to this CLI's version${C.reset}`);
90
+ for (const path of retired) lines.push(` ${C.dim}removed ${path}: this skill has a new name${C.reset}`);
89
91
  return lines.join("\n");
90
92
  }
91
93
  function renderFailure(errors) {
@@ -179,21 +181,24 @@ function runEmit(opts = {}) {
179
181
  if (!existsSync(cwd)) throw new EmitError(`no such directory: ${cwd}`);
180
182
  const targets = resolveTargetsFromConfig(cwd);
181
183
  const maintained = maintainedFilesForExistingSkills(cwd, loadMaintainedFiles());
182
- const built = buildEmitInput(cwd, targets, maintained);
184
+ const retired = retiredSkillPaths(cwd);
185
+ const built = buildEmitInput(cwd, targets, maintained, new Set(retired));
183
186
  const emitted = emitTree(built.input);
184
187
  const { result, kept } = withholdKept(cwd, emitted, opts.keep);
185
188
  const hasErrors = result.errors.length > 0;
186
- if (opts.check) return runCheck(cwd, opts, targets, result, hasErrors, built.sourcePaths, maintained, kept);
189
+ if (opts.check) return runCheck(cwd, opts, targets, result, hasErrors, built.sourcePaths, maintained, kept, retired);
187
190
  const written = hasErrors ? { files: [], copies: [], maintained: [] } : writeOutputs(cwd, result, maintained);
191
+ const removed = hasErrors ? [] : removeRetiredSkills(cwd);
188
192
  const exitCode = hasErrors ? 1 : 0;
189
193
  const output = opts.json ? JSON.stringify({
190
194
  targets,
191
195
  files: written.files,
192
196
  copies: written.copies,
193
197
  maintained: written.maintained,
198
+ retired: removed,
194
199
  warnings: result.warnings,
195
200
  errors: result.errors
196
- }) : hasErrors ? renderFailure(result.errors) : renderSuccess(targets, written.files, written.copies, written.maintained);
201
+ }) : hasErrors ? renderFailure(result.errors) : renderSuccess(targets, written.files, written.copies, written.maintained, removed);
197
202
  if (!opts.quiet) {
198
203
  if (opts.json) {
199
204
  process.stdout.write(output + "\n");
@@ -211,15 +216,17 @@ function runEmit(opts = {}) {
211
216
  copies: written.copies,
212
217
  maintained: written.maintained,
213
218
  kept,
219
+ retired: removed,
214
220
  warnings: result.warnings,
215
221
  errors: result.errors,
216
222
  output,
217
223
  exitCode
218
224
  };
219
225
  }
220
- function runCheck(cwd, opts, targets, result, hasErrors, sourcePaths, maintained, kept) {
226
+ function runCheck(cwd, opts, targets, result, hasErrors, sourcePaths, maintained, kept, retired) {
221
227
  const drift = [];
222
228
  if (!hasErrors) {
229
+ for (const path of retired) drift.push({ kind: "retired", path });
223
230
  for (const file of maintained) {
224
231
  const d = compareFile(cwd, file.path, file.content);
225
232
  if (d) drift.push(d);
@@ -233,7 +240,8 @@ function runCheck(cwd, opts, targets, result, hasErrors, sourcePaths, maintained
233
240
  const d = compareCopy(cwd, copy);
234
241
  if (d) drift.push(d);
235
242
  }
236
- drift.push(...findOrphans(cwd, computedFiles, sourcePaths));
243
+ const retiredPaths = new Set(retired);
244
+ drift.push(...findOrphans(cwd, computedFiles, sourcePaths).filter((d) => !retiredPaths.has(d.path)));
237
245
  drift.sort((a, b) => a.path.localeCompare(b.path) || a.kind.localeCompare(b.kind));
238
246
  }
239
247
  const exitCode = hasErrors || drift.length > 0 ? 1 : 0;
@@ -249,7 +257,7 @@ function runCheck(cwd, opts, targets, result, hasErrors, sourcePaths, maintained
249
257
  `);
250
258
  }
251
259
  }
252
- return { targets, files: [], copies: [], maintained: [], kept, warnings: result.warnings, errors: result.errors, drift, output, exitCode };
260
+ return { targets, files: [], copies: [], maintained: [], kept, retired: [], warnings: result.warnings, errors: result.errors, drift, output, exitCode };
253
261
  }
254
262
 
255
263
  export { EmitError, runEmit };
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
3
  import { C } from './chunk-YRYMNBGQ.js';
4
- import { resolvePackRoot, loadTemplateFiles, loadMaintainedFiles, TEMPLATE_SKILLS, skillDir, writeMaintainedFiles, MAINTAINED_SKILLS } from './chunk-ZA5CHAFY.js';
4
+ import { resolvePackRoot, loadTemplateFiles, loadMaintainedFiles, TEMPLATE_SKILLS, skillDir, writeMaintainedFiles, MAINTAINED_SKILLS } from './chunk-POJMEEJJ.js';
5
5
  import { resolvePackageVersion } from './chunk-RA3O54FC.js';
6
6
  import { readFileSync, existsSync, mkdirSync, writeFileSync } from 'fs';
7
7
  import { join, dirname } from 'path';
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { runEmit } from './chunk-HFKKFTXU.js';
3
+ import { runEmit } from './chunk-2MNPHL23.js';
4
4
  import { addStdioMcpEntryIfAbsent, addDocsMcpEntryIfAbsent, DOCS_MCP_SERVER_NAME } from './chunk-XCK2YAY5.js';
5
- import { installStarterPack } from './chunk-FOJGZYFC.js';
5
+ import { installStarterPack } from './chunk-42ZI52JW.js';
6
6
  import { C } from './chunk-YRYMNBGQ.js';
7
- import { resolveGitCommonDir, defaultGitRunner } from './chunk-3NLOVYJQ.js';
8
- import { pinExists, readContextManifest } from './chunk-LCEXHCHD.js';
9
- import { loadTemplateFiles, loadMaintainedFiles, skillDir } from './chunk-ZA5CHAFY.js';
10
- import { generatedHeaderSource } from './chunk-2M63GG56.js';
7
+ import { resolveGitCommonDir, defaultGitRunner } from './chunk-JEHRUE3F.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';
11
11
  import { execFileSync } from 'child_process';
12
12
  import { existsSync, mkdirSync, writeFileSync } from 'fs';
13
13
  import { join, dirname } from 'path';
@@ -634,7 +634,7 @@ async function runHookFast(event, home = homeFromEnv(), read = readStdin, env =
634
634
  recordHookErrorsSeen(home, hookErrorsBytes);
635
635
  if (contextPossiblyGoverned(sessionCwd, home)) {
636
636
  try {
637
- const { materializeContext: materialize } = await import('./context-materialize-FDHYKNDT.js');
637
+ const { materializeContext: materialize } = await import('./context-materialize-2WXTS4CW.js');
638
638
  const sessionId = typeof payload.session_id === "string" ? payload.session_id : "unknown";
639
639
  const result = await materialize({ cwd: sessionCwd, sessionId, home });
640
640
  materializeMessage = result.message;
@@ -360,7 +360,7 @@ async function runWorkLinkSession(opts) {
360
360
  return await linkSession(opts);
361
361
  } catch (err) {
362
362
  if (opts.logFailures) {
363
- const { logHookError } = await import('./hook-fast-WYQD6D7T.js');
363
+ const { logHookError } = await import('./hook-fast-D7HV4IXG.js');
364
364
  const reason = err instanceof Error ? err.message : String(err);
365
365
  logHookError(opts.home ?? homeFromEnv(opts.env ?? process.env), new Error(`work link-session #${opts.number} failed: ${reason}`));
366
366
  }
@@ -450,6 +450,24 @@ async function runWorkRemove(opts) {
450
450
  if (!opts.quiet) process.stdout.write(output + "\n");
451
451
  return { data, output };
452
452
  }
453
+ function statusOutput(data, json) {
454
+ if (json) return JSON.stringify(data);
455
+ const document = JSON.stringify(data, null, 2);
456
+ const criteria = data.criteria;
457
+ if (criteria === void 0) return document;
458
+ if (criteria === null || !Array.isArray(criteria.items)) return `${document}
459
+
460
+ Criteria: none recorded`;
461
+ const mark = criteria.drafted === true ? ` ${C.dim}(drafted by the build)${C.reset}` : "";
462
+ const lines = criteria.items.map((item) => {
463
+ const proof = typeof item.proof === "string" ? ` ${C.dim}[proof: ${sanitizeTerminal(item.proof)}]${C.reset}` : "";
464
+ return ` ${sanitizeTerminal(String(item.id))} ${sanitizeTerminal(String(item.text))}${proof}`;
465
+ });
466
+ return `${document}
467
+
468
+ Criteria${mark}
469
+ ${lines.join("\n")}`;
470
+ }
453
471
  async function runWorkStatus(opts) {
454
472
  const cwd = opts.cwd ?? process.cwd();
455
473
  await connectIfOneFits(opts);
@@ -463,7 +481,7 @@ async function runWorkStatus(opts) {
463
481
  creds.appId,
464
482
  opts.fetchImpl ?? defaultFetch
465
483
  );
466
- const body = opts.json ? JSON.stringify(data2) : JSON.stringify(data2, null, 2);
484
+ const body = statusOutput(data2, opts.json === true);
467
485
  if (!opts.quiet) process.stdout.write(body + "\n");
468
486
  return { data: data2, output: body };
469
487
  }
@@ -476,7 +494,7 @@ async function runWorkStatus(opts) {
476
494
  throw new WorkCommandError(`no live item for ${repository}#${number}`);
477
495
  }
478
496
  const { data } = await getJson(creds.url, `/v1/work-items/${item.id}`, creds.apiKey, creds.appId, fetchImpl);
479
- const output = opts.json ? JSON.stringify(data) : `${JSON.stringify(data, null, 2)}`;
497
+ const output = statusOutput(data, opts.json === true);
480
498
  if (!opts.quiet) process.stdout.write(output + "\n");
481
499
  return { data, output };
482
500
  }
@@ -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 = 16;
7
+ var RUNNER_PROTOCOL = 17;
8
8
 
9
9
  export { RUNNER_PROTOCOL };
@@ -0,0 +1,88 @@
1
+ #!/usr/bin/env node
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';
5
+ import { readFileSync, existsSync, unlinkSync, rmdirSync, readdirSync } from 'fs';
6
+ import { join, dirname, relative, sep } from 'path';
7
+
8
+ createRequire(import.meta.url);
9
+ function filesUnder(repoRoot, rel) {
10
+ try {
11
+ return readdirSync(join(repoRoot, rel), { recursive: true, withFileTypes: true }).filter((entry) => entry.isFile()).map((entry) => relative(repoRoot, join(entry.parentPath, entry.name)).split(sep).join("/"));
12
+ } catch {
13
+ return [];
14
+ }
15
+ }
16
+ function retiredSkillsPresent(repoRoot) {
17
+ return Object.keys(FORMER_MAINTAINED_NAMES).filter((former) => isMaintainedCopy(repoRoot, former));
18
+ }
19
+ function retiredSkillPaths(repoRoot, retired = retiredSkillsPresent(repoRoot)) {
20
+ const paths = /* @__PURE__ */ new Set();
21
+ for (const former of retired) {
22
+ const sources = filesUnder(repoRoot, skillDir(former));
23
+ const compiled = emitTree({
24
+ entries: classifyTree(sources).entries,
25
+ contents: new Map(sources.map((path) => [path, readFileSync(join(repoRoot, path), "utf8")])),
26
+ // A superset is safe: targets ignore a path that is not a skill asset.
27
+ assetPaths: sources,
28
+ targets: [...ALL_TARGET_IDS]
29
+ });
30
+ for (const path of [...sources, ...compiled.files.map((f) => f.path), ...compiled.copies.map((c) => c.toPath)]) paths.add(path);
31
+ }
32
+ return [...paths].filter((path) => existsSync(join(repoRoot, path))).sort();
33
+ }
34
+ function removeRetiredSkills(repoRoot, unsafe) {
35
+ const removed = retiredSkillPaths(repoRoot).filter((path) => !unsafe?.(path));
36
+ for (const path of removed) {
37
+ unlinkSync(join(repoRoot, path));
38
+ for (let dir = dirname(path); dir !== "."; dir = dirname(dir)) {
39
+ try {
40
+ rmdirSync(join(repoRoot, dir));
41
+ } catch {
42
+ break;
43
+ }
44
+ }
45
+ }
46
+ return removed;
47
+ }
48
+ function filesNamingFormerSkills(repoRoot) {
49
+ const patterns = [
50
+ ["emitting-evidence", /\bemitting-evidence\b/],
51
+ ["reporting-findings", /\breporting-findings\b/],
52
+ ["amend", /`amend` skill|(^|[\s"'`(])\/amend(?![\w-])/m],
53
+ ["outerlayer", /`outerlayer` skill|skills\/outerlayer\//]
54
+ ];
55
+ const retired = retiredSkillsPresent(repoRoot).map((former) => `${skillDir(former)}/`);
56
+ const hits = [];
57
+ for (const path of filesUnder(repoRoot, ".outerlayer/skills").sort()) {
58
+ if (retired.some((dir) => path.startsWith(dir))) continue;
59
+ const text = readFileSync(join(repoRoot, path), "utf8");
60
+ const formers = patterns.filter(([, pattern]) => pattern.test(text)).map(([former]) => former);
61
+ if (formers.length > 0) hits.push({ path, formers });
62
+ }
63
+ return hits;
64
+ }
65
+ function checkFormerSkillNames(repoRoot) {
66
+ const checks = [];
67
+ const retired = retiredSkillsPresent(repoRoot);
68
+ if (retired.length > 0) {
69
+ checks.push({
70
+ name: "Renamed skills",
71
+ status: "warn",
72
+ 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
+ });
75
+ }
76
+ const hits = filesNamingFormerSkills(repoRoot);
77
+ if (hits.length > 0) {
78
+ checks.push({
79
+ name: "Skill names",
80
+ status: "warn",
81
+ 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
+ });
84
+ }
85
+ return checks;
86
+ }
87
+
88
+ export { checkFormerSkillNames, removeRetiredSkills, retiredSkillPaths };
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { detectMachine, supportsContainerBuilds, reachDockerStep, describeMachineDocker, supportsMicroVmBuilds } from './chunk-JYIEHQIF.js';
4
- import { MIN_ENGINE_MAJOR } from './chunk-RBKIH5ST.js';
5
- import { hasStoredCredential, AGENT_COMMANDS, storeClaudeCredential, credentialFromStdin, isAgentName } from './chunk-T5VPP6H7.js';
3
+ import { detectMachine, supportsContainerBuilds, reachDockerStep, describeMachineDocker, supportsMicroVmBuilds } from './chunk-RSPXEVDX.js';
4
+ import { MIN_ENGINE_MAJOR } from './chunk-EWORLJMO.js';
5
+ import { hasStoredCredential, AGENT_COMMANDS, storeClaudeCredential, credentialFromStdin, isAgentName } from './chunk-OZGHL5Y5.js';
6
6
  import { runnerCredentialProblem } from './chunk-22RMZBGW.js';
7
7
  import { runnerDir, RUNNER_DIR_MODE, RUNNER_FILE_MODE } from './chunk-ZM2IMMYN.js';
8
8
  import { existsSync, readFileSync, mkdirSync, writeFileSync } from 'fs';
@@ -1,21 +1,21 @@
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-4OGPT6I2.js';
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
4
  import { writePendingUpdate } from './chunk-O765JR4W.js';
5
5
  import { readHousekeepingRecord, writeHousekeepingRecord } from './chunk-UGP76IZ5.js';
6
6
  import { decideInstalledSwitch } from './chunk-3JVYMD4G.js';
7
7
  import { fetchVersionMeta, npmVersion, npmSupportsProvenance, fetchTarballDigest, fetchProvenance, installVersion, auditSignatures } from './chunk-YETTWTAY.js';
8
8
  import { writeJobFile, readJobFile, readJobFileChecked } from './chunk-RMWLBUCJ.js';
9
9
  import { compareVersions, satisfiesRange } from './chunk-I2UOAV7X.js';
10
- import { RUNNER_PROTOCOL } from './chunk-FI5UYJMQ.js';
11
- import { placeholderQueues, placeholderProblem } from './chunk-SMHOCDCI.js';
10
+ import { RUNNER_PROTOCOL } from './chunk-ADJRGVZC.js';
11
+ import { currentSkillCommand, formerSkillProblem, placeholderQueues, placeholderProblem } from './chunk-FWX735W7.js';
12
12
  import { freeBytes, formatBytes } from './chunk-YYYRBYWG.js';
13
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-RBKIH5ST.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
16
  import { spawnRun } from './chunk-KMDLFI4P.js';
17
17
  import { checkFit } from './chunk-RLYZLUQ7.js';
18
- import { isSignatureRefusal, WorkCommandError, getJson, postJson } from './chunk-SWHQ4LUM.js';
18
+ import { isSignatureRefusal, WorkCommandError, getJson, postJson } from './chunk-6QRMLNH3.js';
19
19
  import { isBuiltinContainer, isBuiltinVm, isBuiltinProcess, loadRunnerConfig, checkHooks, builtinKind, DEFAULT_UPDATE_MAX_WAIT_HOURS } from './chunk-22RMZBGW.js';
20
20
  import { startTimeOf, claimPidFile, readPidFile, isSameProcess, releasePidFile } from './chunk-N5FOE5PS.js';
21
21
  import { builderName, runnerLabelValue, ensureFailureCount, builderSpec, ensureBuilder, BUILD_LABEL, RUNNER_LABEL } from './chunk-4NPZVMJU.js';
@@ -958,9 +958,9 @@ function considerNamedVersion(state, named) {
958
958
  logOf(state).line(`this runner cannot update itself to ${named}: ${blocker}`);
959
959
  }
960
960
  }
961
- function adoptUpdateWait(state, version) {
961
+ function adoptUpdateWait(state, version, nowMs) {
962
962
  const previous = state.updateWait;
963
- const wait = { version, sinceMs: previous?.sinceMs ?? nowOf(state).getTime(), holdSinceMs: previous?.holdSinceMs };
963
+ const wait = { version, sinceMs: previous?.sinceMs ?? nowMs, holdSinceMs: previous?.holdSinceMs };
964
964
  state.updateWait = wait;
965
965
  return wait;
966
966
  }
@@ -1012,7 +1012,7 @@ function runningItems(state) {
1012
1012
  function holdForUpdate(state, version, mayHold = true) {
1013
1013
  const log = logOf(state);
1014
1014
  const nowMs = nowOf(state).getTime();
1015
- const wait = adoptUpdateWait(state, version);
1015
+ const wait = adoptUpdateWait(state, version, nowMs);
1016
1016
  const failed2 = readLastUpdate(state.config.configPath);
1017
1017
  const failedAtMs = failed2?.to === version && failed2.outcome === "retrying" ? new Date(failed2.at ?? Number.NaN).getTime() : Number.NaN;
1018
1018
  if (failedAtMs < wait.sinceMs) wait.sinceMs = failedAtMs;
@@ -1315,7 +1315,7 @@ var CLAIM_REFUSAL_CODES = new Set(
1315
1315
  "pull_request_from_fork pull_request_on_default_branch pull_request_ambiguous pull_request_repository_not_connected branch_claimed_elsewhere".split(" ")
1316
1316
  );
1317
1317
  async function tryClaimAndStart(state, item, queue) {
1318
- const { postJson: postJson2 } = await import('./work-cmd-RVRQ32EH.js');
1318
+ const { postJson: postJson2 } = await import('./work-cmd-DJQJEZVB.js');
1319
1319
  const log = logOf(state);
1320
1320
  const hostKey = await loadHostKey(state.config.configPath);
1321
1321
  const claim = await retrySend(
@@ -1776,7 +1776,9 @@ async function startJob(state, item, queue, claimId, itemKey, branch, identity,
1776
1776
  log.line(`${tag} workdir is not a git checkout, so ${branch} was not checked out`);
1777
1777
  }
1778
1778
  }
1779
- const cmdline = state.config.commands[queue];
1779
+ const configured = state.config.commands[queue];
1780
+ const cmdline = configured === void 0 ? void 0 : currentSkillCommand(configured);
1781
+ if (cmdline !== configured) log.line(`${tag} ${formerSkillProblem([queue])}`);
1780
1782
  if (!cmdline) {
1781
1783
  log.error(`${tag} has no runner.commands.${queue} in the config file \xB7 ending job as failed`);
1782
1784
  await endJob(state, active, "failed", { stage: "command" });
@@ -2072,7 +2074,7 @@ async function start(configPath, deps = { fetchImpl: fetch }) {
2072
2074
  const outcome = await onStartUnderMarker({
2073
2075
  configPath,
2074
2076
  own: ownVersionOf(deps),
2075
- check: update.check ? () => update.check(configPath) : async () => (await import('./check-SRGR36KI.js')).runRunnerCheck(configPath, { fetchImpl: deps.fetchImpl }),
2077
+ check: update.check ? () => update.check(configPath) : async () => (await import('./check-CNTMSGOG.js')).runRunnerCheck(configPath, { fetchImpl: deps.fetchImpl }),
2076
2078
  now: () => (deps.now ?? (() => /* @__PURE__ */ new Date()))().getTime(),
2077
2079
  log
2078
2080
  });
@@ -3,7 +3,7 @@ import { createRequire } from 'node:module';
3
3
  import { createDockerHost, childEnvironment, spawnRun } from './chunk-KMDLFI4P.js';
4
4
  import { execCapture } from './chunk-QKFB4K7X.js';
5
5
  import { GUEST_CID } from './chunk-RSNSZ2LJ.js';
6
- import { WorkCommandError, postJson } from './chunk-SWHQ4LUM.js';
6
+ import { WorkCommandError, postJson } from './chunk-6QRMLNH3.js';
7
7
  import { hostAllowed } from './chunk-UXYLWVTQ.js';
8
8
  import { readDefaultBranchHead, cloneRepository, buildRepositoryImage } from './chunk-R7PF5OOU.js';
9
9
  import { RecipeError } from './chunk-QOZKPLVJ.js';
@@ -14,10 +14,10 @@ import { parseDuKilobytes } from './chunk-7RQ73DLO.js';
14
14
  import { repositoriesOf, primaryOf, RELAY_PORT, CHECKOUT_DIR, JOB_MOUNT, claudeCredential, buildEnvironment, startBuildServices, checkEnvironment, AGENT_CREDENTIAL_MISSING, checkoutPath } from './chunk-4Q7OMKAT.js';
15
15
  import { CLAUDE_CODE_VERSION, firecrackerArch, MICROVM_ARCHES, DEFAULT_BASE_IMAGE, GUEST_HELPER_SHA256, GUEST_ASSETS_BASE_URL, GUEST_KERNEL_SHA256, FIRECRACKER_BINARY_SHA256, FIRECRACKER_SHA256, FIRECRACKER_VERSION, GUEST_ASSETS_VERSION } from './chunk-CX22S5BA.js';
16
16
  import { setCustomScrubbers, setLocalIdentity, setRepoRoot, parseTranscript, scrubDeep, scrubText } from './chunk-JXYVA45C.js';
17
- import { defaultGitRunner, materializeContext } from './chunk-3NLOVYJQ.js';
18
- import { readContextManifest, readSourceCache } from './chunk-LCEXHCHD.js';
17
+ import { defaultGitRunner, materializeContext } from './chunk-JEHRUE3F.js';
18
+ import { readContextManifest, readSourceCache } from './chunk-WTE3MQML.js';
19
19
  import { signingFetchFor } from './chunk-YO4PSLVB.js';
20
- import { orderSessions, extractFacts, sessionsToTimeline } from './chunk-2M63GG56.js';
20
+ import { orderSessions, extractFacts, sessionsToTimeline } from './chunk-OHVJA253.js';
21
21
  import { downconvertSession } from './chunk-J5M7BSJQ.js';
22
22
  import { signerFor } from './chunk-V7NIVOFD.js';
23
23
  import { rootfsPathFor, diskTemplatesDir, RUNNER_FILE_MODE, stagedContextDir, contextHomeDir, ghConfigDir, runnerDirOfBuild, spoolDir, mirrorDir, buildDir, RUNNER_DIR_MODE, vmAssetsDir } from './chunk-ZM2IMMYN.js';
@@ -1231,6 +1231,19 @@ var NoControlPlane = class extends Error {
1231
1231
  var GatewayConflict = class extends Error {
1232
1232
  };
1233
1233
  var unavailable = (why) => ({ kind: "refused", reason: `context_unavailable: ${why}` });
1234
+ var DESIGNATION_LOOKUP = { timeoutMs: 1e4, attempts: 2 };
1235
+ function lookupFailureReason(failure, repository) {
1236
+ switch (failure?.kind) {
1237
+ case "timeout":
1238
+ return `the gateway did not answer which repository governs ${repository} within ${failure.timeoutMs / 1e3} seconds, twice`;
1239
+ case "status":
1240
+ return `the gateway answered ${failure.status} when asked which repository governs ${repository}`;
1241
+ case "network":
1242
+ return `the request asking which repository governs ${repository} failed: ${failure.message}`;
1243
+ default:
1244
+ return `the gateway did not say which repository governs ${repository}`;
1245
+ }
1246
+ }
1234
1247
  function makeReadable(tree, dir, files) {
1235
1248
  chmodSync(dir, 493);
1236
1249
  chmodSync(tree, 493);
@@ -1268,6 +1281,7 @@ async function stageGovernedContext(input) {
1268
1281
  home: contextHomeDir(configPath),
1269
1282
  cloud: { url, apiKey, appId },
1270
1283
  fetchImpl: signingFetchFor(input.fetchImpl, configPath, apiKey),
1284
+ designationLookup: DESIGNATION_LOOKUP,
1271
1285
  git: git2,
1272
1286
  now: input.now,
1273
1287
  resolveControlPlaneUrl: (repository) => input.controlPlaneUrl(repository),
@@ -1303,7 +1317,7 @@ async function stageGovernedContext(input) {
1303
1317
  if (result.authRejected === true) {
1304
1318
  return finish(unavailable(`the gateway rejected the runner's API key (401/403) when asked which repository governs ${input.repository}`));
1305
1319
  }
1306
- return finish(unavailable(`the gateway did not say which repository governs ${input.repository}`));
1320
+ return finish(unavailable(lookupFailureReason(result.lookupFailure, input.repository)));
1307
1321
  case "conflict":
1308
1322
  return finish({ kind: "refused", reason: `context_conflict: ${result.message ?? "two control planes claim this repository"}` });
1309
1323
  default: