@outerlayer/cli 0.13.0 → 0.14.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 (77) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/agent-setup-CN2HUBEJ.js +26 -0
  3. package/dist/{build-LELVCWHV.js → build-BG2YENGK.js} +2 -2
  4. package/dist/build-info.json +1 -1
  5. package/dist/{builder-UUS4ORDH.js → builder-2D3WSOOY.js} +4 -4
  6. package/dist/{check-63IDCEEV.js → check-SRGR36KI.js} +30 -30
  7. package/dist/{chunk-GI4XXD4I.js → chunk-3NLOVYJQ.js} +4 -4
  8. package/dist/{chunk-C6IV5BV7.js → chunk-4OGPT6I2.js} +11 -11
  9. package/dist/{chunk-DXQ5MHCO.js → chunk-FOJGZYFC.js} +11 -5
  10. package/dist/{chunk-HDTVTA6I.js → chunk-HFKKFTXU.js} +11 -15
  11. package/dist/{chunk-DPKX26LT.js → chunk-HFKQIZXL.js} +9 -6
  12. package/dist/{chunk-6S3H3J6H.js → chunk-JJEGKEFV.js} +5 -7
  13. package/dist/{chunk-P6FX4D43.js → chunk-JYIEHQIF.js} +1 -1
  14. package/dist/{chunk-XJKL4BNU.js → chunk-KFRM23WD.js} +2 -2
  15. package/dist/{chunk-3KTA5UU2.js → chunk-KMDLFI4P.js} +1 -1
  16. package/dist/{chunk-3D4OYFCD.js → chunk-MSASO5O4.js} +42 -6
  17. package/dist/chunk-MTF3PHVZ.js +161 -0
  18. package/dist/{chunk-SVEP7PVH.js → chunk-NHDVD7DU.js} +9 -9
  19. package/dist/{chunk-EFZLAYPE.js → chunk-NPQWKGUA.js} +1 -1
  20. package/dist/{chunk-SFFHGX3G.js → chunk-PQUM37BK.js} +1 -1
  21. package/dist/{chunk-MJXXRX4M.js → chunk-Q2UK3C4P.js} +2 -2
  22. package/dist/{chunk-MZN7AQOB.js → chunk-RBKIH5ST.js} +11 -11
  23. package/dist/{chunk-TOPDNXHZ.js → chunk-SMHOCDCI.js} +4 -4
  24. package/dist/{chunk-P4MM66C6.js → chunk-SWHQ4LUM.js} +4 -4
  25. package/dist/{agent-setup-QE6PSCEZ.js → chunk-SXWS25JC.js} +6 -19
  26. package/dist/{chunk-CNFVHDHG.js → chunk-WUYTWNMA.js} +3 -1
  27. package/dist/{chunk-R7OQTKWT.js → chunk-XCK2YAY5.js} +12 -3
  28. package/dist/{chunk-4QVZCVWT.js → chunk-YDSMROTB.js} +1 -1
  29. package/dist/{chunk-TCIW27FM.js → chunk-ZA5CHAFY.js} +1 -1
  30. package/dist/{cli-WSBIAVZU.js → cli-UW2H3UUW.js} +79 -62
  31. package/dist/{command-N7BAB4XJ.js → command-5LD7G2QQ.js} +22 -22
  32. package/dist/{connect-cmd-FGYRLLXL.js → connect-cmd-JUAW6MU4.js} +2 -2
  33. package/dist/{context-adopt-B3PWGFHL.js → context-adopt-PJUMW2EZ.js} +5 -5
  34. package/dist/{context-materialize-7S6NLLRO.js → context-materialize-FDHYKNDT.js} +5 -5
  35. package/dist/{docker-BZ55BMBJ.js → docker-4J77Q2BF.js} +5 -5
  36. package/dist/{doctor-3H25Q7WT.js → doctor-H7REBSLQ.js} +24 -24
  37. package/dist/{emit-artifact-cmd-IQCRXOH7.js → emit-artifact-cmd-FOGNJXVR.js} +15 -18
  38. package/dist/{emit-cmd-KDSM5VAO.js → emit-cmd-ZEYWLC2C.js} +3 -2
  39. package/dist/{emit-criteria-cmd-EYUXME26.js → emit-criteria-cmd-HBP6XS5C.js} +5 -8
  40. package/dist/{emit-finding-cmd-P4RKBPBB.js → emit-finding-cmd-DLI4MKMN.js} +5 -8
  41. package/dist/{emit-result-cmd-6XYENU6H.js → emit-result-cmd-MUSL7GQA.js} +9 -12
  42. package/dist/{hook-fast-PXWKQPN6.js → hook-fast-WYQD6D7T.js} +1 -1
  43. package/dist/{import-capture-cmd-2BKM5I2N.js → import-capture-cmd-6QVCOIHK.js} +8 -11
  44. package/dist/{import-ruler-cmd-IXR7YK47.js → import-ruler-cmd-KLRGRBCP.js} +5 -8
  45. package/dist/index.js +3 -3
  46. package/dist/{init-2LWVS4AH.js → init-NTXA3SN7.js} +23 -23
  47. package/dist/{init-ZL7ORPTF.js → init-UBXK6MF7.js} +23 -23
  48. package/dist/{init-cmd-JXOBCOIB.js → init-cmd-NARDUPIG.js} +13 -8
  49. package/dist/init-update-O5YYFGF4.js +165 -0
  50. package/dist/{loop-XOAE6ZIY.js → loop-SW2M5VDD.js} +30 -30
  51. package/dist/{machine-G6PY2J2J.js → machine-U66FKVDP.js} +21 -21
  52. package/dist/mcp-install-cmd-FDTPQQS6.js +9 -0
  53. package/dist/{runner-key-TDTLNAKJ.js → runner-key-3JSMDRJA.js} +23 -23
  54. package/dist/{session-sender-XVGZFWRK.js → session-sender-4M247XSV.js} +5 -5
  55. package/dist/{starter-pack-B7JPGEDO.js → starter-pack-IB4UUIX3.js} +2 -2
  56. package/dist/{status-MRTPG34B.js → status-STZYPU3W.js} +26 -26
  57. package/dist/{sync-cmd-UBUZMMDN.js → sync-cmd-UWD5JOFU.js} +4 -4
  58. package/dist/{watch-STNPEWD6.js → watch-DBNB7R6X.js} +4 -4
  59. package/dist/{work-claim-cmd-CWGYEIJE.js → work-claim-cmd-LY4U6QHN.js} +11 -11
  60. package/dist/{work-cmd-X7NMJDFL.js → work-cmd-RVRQ32EH.js} +4 -4
  61. package/dist/{work-comment-cmd-FI2TMAYQ.js → work-comment-cmd-FFUM4TJU.js} +7 -10
  62. package/dist/{work-open-pr-cmd-OVHJ5I5H.js → work-open-pr-cmd-HLDWP4T2.js} +7 -10
  63. package/dist/{work-pr-cmd-Y5TDMQ4O.js → work-pr-cmd-L77K32WK.js} +4 -4
  64. package/package.json +1 -1
  65. package/skill-pack/maintained/emitting-evidence/SKILL.md +8 -2
  66. package/skill-pack/shipped.json +70 -0
  67. package/skill-pack/template/build/SKILL.md +6 -2
  68. package/skill-pack/template/build/references/release.md +36 -8
  69. package/skill-pack/template/build/references/review-loop.md +1 -1
  70. package/skill-pack/template/spec/SKILL.md +33 -22
  71. package/skill-pack/template/writing-specs/SKILL.md +36 -3
  72. package/skill-pack/template/writing-specs/references/agents-snippet.md +57 -0
  73. package/skill-pack/template/writing-tests/SKILL.md +117 -0
  74. package/skill-pack/validators/acceptance-criteria.yaml +35 -0
  75. package/dist/mcp-install-cmd-VXVIH7PH.js +0 -9
  76. package/dist/{chunk-NX57IBNK.js → chunk-4NPZVMJU.js} +2 -2
  77. package/dist/{chunk-3FMPZPJQ.js → chunk-R7PF5OOU.js} +1 -1
@@ -0,0 +1,161 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire } from 'node:module';
3
+ import { mcpTargetPath, INIT_STDIO_ENTRY, INIT_DOCS_ENTRY, DOCS_MCP_SERVER_NAME } from './chunk-XCK2YAY5.js';
4
+ import { POLICY_CONTENT, VALIDATOR_FILES, VALIDATORS_DIR, POLICY_PATH } from './chunk-FOJGZYFC.js';
5
+ import { pinExists, readContextManifest } from './chunk-LCEXHCHD.js';
6
+ import { resolvePackRoot, loadTemplateFiles, skillDir } from './chunk-ZA5CHAFY.js';
7
+ import { findGitDirs } from './chunk-BJ3KTMDH.js';
8
+ import { createHash } from 'crypto';
9
+ import { existsSync, readFileSync } from 'fs';
10
+ import { join } from 'path';
11
+
12
+ createRequire(import.meta.url);
13
+ var SHIPPED_MANIFEST = "shipped.json";
14
+ function currentStarterFiles(packRoot = resolvePackRoot(), policy = POLICY_CONTENT) {
15
+ const templates = loadTemplateFiles(packRoot).map((f) => ({
16
+ path: f.path,
17
+ content: f.content,
18
+ skill: f.skill,
19
+ source: join(packRoot, "template", f.skill, f.path.slice(skillDir(f.skill).length + 1))
20
+ }));
21
+ const validators = VALIDATOR_FILES.map(({ name }) => {
22
+ const source = join(packRoot, "validators", name);
23
+ return { path: `${VALIDATORS_DIR}/${name}`, content: readFileSync(source, "utf8"), source };
24
+ });
25
+ return [...templates, ...validators, { path: POLICY_PATH, content: policy }];
26
+ }
27
+ function contentHash(content) {
28
+ return createHash("sha256").update(content.replace(/\r\n/g, "\n")).digest("hex");
29
+ }
30
+ function readShippedManifest(packRoot = resolvePackRoot()) {
31
+ const path = join(packRoot, SHIPPED_MANIFEST);
32
+ if (!existsSync(path)) return { ok: false, problem: "missing" };
33
+ try {
34
+ const doc = JSON.parse(readFileSync(path, "utf8"));
35
+ if (doc.schemaVersion !== 1 || doc.files === null || typeof doc.files !== "object" || Array.isArray(doc.files)) {
36
+ return { ok: false, problem: "unreadable" };
37
+ }
38
+ const files = /* @__PURE__ */ new Map();
39
+ for (const [file, hashes] of Object.entries(doc.files)) {
40
+ if (!Array.isArray(hashes) || !hashes.every((h) => typeof h === "string" && /^[0-9a-f]{64}$/.test(h))) {
41
+ return { ok: false, problem: "unreadable" };
42
+ }
43
+ files.set(file, new Set(hashes));
44
+ }
45
+ return { ok: true, files };
46
+ } catch {
47
+ return { ok: false, problem: "unreadable" };
48
+ }
49
+ }
50
+ function mcpItemsInit() {
51
+ return [
52
+ // Through 0.12.0 `init` wrote a command that needs a global install on every teammate's machine.
53
+ { name: "outerlayer", current: INIT_STDIO_ENTRY, shipped: [{ type: "stdio", command: "outerlayer", args: ["mcp", "serve"] }] },
54
+ { name: DOCS_MCP_SERVER_NAME, current: INIT_DOCS_ENTRY, shipped: [] }
55
+ ];
56
+ }
57
+ function canonical(value) {
58
+ if (Array.isArray(value)) return `[${value.map(canonical).join(",")}]`;
59
+ if (value !== null && typeof value === "object") {
60
+ const entries = Object.entries(value).sort(([a], [b]) => a.localeCompare(b));
61
+ return `{${entries.map(([k, v]) => `${JSON.stringify(k)}:${canonical(v)}`).join(",")}}`;
62
+ }
63
+ return JSON.stringify(value);
64
+ }
65
+ function fileState(root, file, manifest) {
66
+ const abs = join(root, file.path);
67
+ if (!existsSync(abs)) return "missing";
68
+ const hash = contentHash(readFileSync(abs, "utf8"));
69
+ if (hash === contentHash(file.content)) return "current";
70
+ if (manifest.ok && manifest.files.get(file.path)?.has(hash) === true) return "outdated";
71
+ return "edited";
72
+ }
73
+ function mcpItems(root) {
74
+ const path = mcpTargetPath(root);
75
+ let servers;
76
+ let unreadable = false;
77
+ if (existsSync(join(root, path))) {
78
+ try {
79
+ const doc = JSON.parse(readFileSync(join(root, path), "utf8"));
80
+ const value = doc.mcpServers;
81
+ if (value !== void 0 && (value === null || typeof value !== "object" || Array.isArray(value))) unreadable = true;
82
+ else servers = value ?? {};
83
+ } catch {
84
+ unreadable = true;
85
+ }
86
+ }
87
+ return mcpItemsInit().map((item) => {
88
+ const base = { kind: "mcp", path, server: item.name, entry: item.current };
89
+ if (unreadable) return { ...base, state: "unreadable" };
90
+ if (servers === void 0 || !(item.name in servers)) return { ...base, state: "missing" };
91
+ const have = canonical(servers[item.name]);
92
+ if (have === canonical(item.current)) return { ...base, state: "current" };
93
+ if (item.shipped.some((entry) => canonical(entry) === have)) return { ...base, state: "outdated" };
94
+ return { ...base, state: "edited" };
95
+ });
96
+ }
97
+ function inspectStarterFiles(root, opts = {}) {
98
+ const packRoot = opts.packRoot ?? resolvePackRoot();
99
+ const manifest = readShippedManifest(packRoot);
100
+ const files = currentStarterFiles(packRoot).map(
101
+ (file) => ({ kind: "file", path: file.path, state: fileState(root, file, manifest), file })
102
+ );
103
+ return { items: [...files, ...mcpItems(root)], manifest: manifest.ok ? "ok" : manifest.problem };
104
+ }
105
+ function itemLabel(item) {
106
+ return item.kind === "file" ? item.path : `${item.path} "${item.server}" server`;
107
+ }
108
+ function contextIsGoverned(root, gitCommonDir) {
109
+ return pinExists(root) || readContextManifest(gitCommonDir) !== void 0;
110
+ }
111
+ var NAME = "Starter files";
112
+ var UPDATE = "outerlayer init --update";
113
+ function shownPaths(items, all) {
114
+ const shown = [];
115
+ const whole = /* @__PURE__ */ new Set();
116
+ for (const item of items) {
117
+ const skill = item.kind === "file" ? item.file.skill : void 0;
118
+ if (skill !== void 0) {
119
+ const ofSkill = all.filter((i) => i.kind === "file" && i.file.skill === skill);
120
+ if (ofSkill.every((i) => items.includes(i))) {
121
+ if (!whole.has(skill)) shown.push(`${skillDir(skill)}/`);
122
+ whole.add(skill);
123
+ continue;
124
+ }
125
+ }
126
+ shown.push(itemLabel(item));
127
+ }
128
+ return shown;
129
+ }
130
+ function checkStarterFiles(cwd, opts = {}) {
131
+ const none = { checks: [], mcpOutdated: false };
132
+ const dirs = findGitDirs(cwd ?? process.cwd());
133
+ if (dirs === void 0 || contextIsGoverned(dirs.repoRoot, dirs.gitCommonDir)) return none;
134
+ const report = inspectStarterFiles(dirs.repoRoot, opts);
135
+ if (report.items.every((i) => i.kind === "mcp" || i.state === "missing")) return none;
136
+ const by = (state) => report.items.filter((i) => i.state === state);
137
+ const current = by("current");
138
+ const outdated = by("outdated");
139
+ const missing = by("missing");
140
+ const edited = by("edited");
141
+ const unreadable = by("unreadable");
142
+ const parts = [];
143
+ if (current.length > 0) parts.push(`${current.length} current`);
144
+ if (outdated.length > 0) parts.push(`outdated and unedited: ${shownPaths(outdated, report.items).join(", ")}`);
145
+ if (missing.length > 0) parts.push(`missing: ${shownPaths(missing, report.items).join(", ")}`);
146
+ if (edited.length > 0) parts.push(`edited by you, left as they are: ${edited.map(itemLabel).join(", ")}`);
147
+ if (unreadable.length > 0) parts.push(`${unreadable[0].path} is not valid JSON, so its servers were not read`);
148
+ if (report.manifest !== "ok") {
149
+ parts.push(`this CLI's record of earlier versions is ${report.manifest}, so an outdated file cannot be told from an edited one`);
150
+ }
151
+ const mcpOutdated = outdated.some((i) => i.kind === "mcp" && i.server === "outerlayer");
152
+ const actionable = outdated.length + missing.length > 0;
153
+ const compare = edited.length > 0 ? ` Compare an edited file with this CLI's version: \`${UPDATE} --dry-run\`.` : "";
154
+ if (!actionable && report.manifest === "ok") {
155
+ return { checks: [{ name: NAME, status: "pass", detail: parts.join("; ") + (compare === "" ? "" : `.${compare}`) }], mcpOutdated };
156
+ }
157
+ const fix = actionable ? `Run \`${UPDATE}\` to update the outdated files and write the missing ones. It never changes a file you edited.${compare}` : "Reinstall the CLI: `npm install -g @outerlayer/cli`, or run it with `npx -y @outerlayer/cli`.";
158
+ return { checks: [{ name: NAME, status: "warn", detail: parts.join("; "), fix }], mcpOutdated };
159
+ }
160
+
161
+ export { canonical, checkStarterFiles, contextIsGoverned, inspectStarterFiles };
@@ -1,6 +1,6 @@
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-C6IV5BV7.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-4OGPT6I2.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';
@@ -8,17 +8,17 @@ import { fetchVersionMeta, npmVersion, npmSupportsProvenance, fetchTarballDigest
8
8
  import { writeJobFile, readJobFile, readJobFileChecked } from './chunk-RMWLBUCJ.js';
9
9
  import { compareVersions, satisfiesRange } from './chunk-I2UOAV7X.js';
10
10
  import { RUNNER_PROTOCOL } from './chunk-FI5UYJMQ.js';
11
- import { placeholderQueues, placeholderProblem } from './chunk-TOPDNXHZ.js';
11
+ import { placeholderQueues, placeholderProblem } from './chunk-SMHOCDCI.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-MZN7AQOB.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';
16
+ import { spawnRun } from './chunk-KMDLFI4P.js';
16
17
  import { checkFit } from './chunk-RLYZLUQ7.js';
17
- import { startTimeOf, claimPidFile, readPidFile, isSameProcess, releasePidFile } from './chunk-N5FOE5PS.js';
18
- import { spawnRun } from './chunk-3KTA5UU2.js';
19
- import { builderName, runnerLabelValue, ensureFailureCount, builderSpec, ensureBuilder, BUILD_LABEL, RUNNER_LABEL } from './chunk-NX57IBNK.js';
20
- import { isSignatureRefusal, WorkCommandError, getJson, postJson } from './chunk-P4MM66C6.js';
18
+ import { isSignatureRefusal, WorkCommandError, getJson, postJson } from './chunk-SWHQ4LUM.js';
21
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';
22
22
  import { exceedsDisk } from './chunk-7RQ73DLO.js';
23
23
  import { parseClaimedRepositories, repositoriesOf, primaryOf, sharedUserEnvironment, JOB_MOUNT, claudeCredential } from './chunk-4Q7OMKAT.js';
24
24
  import { parseClaimIdentity } from './chunk-BYT5O5RV.js';
@@ -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-X7NMJDFL.js');
1318
+ const { postJson: postJson2 } = await import('./work-cmd-RVRQ32EH.js');
1319
1319
  const log = logOf(state);
1320
1320
  const hostKey = await loadHostKey(state.config.configPath);
1321
1321
  const claim = await retrySend(
@@ -2072,7 +2072,7 @@ async function start(configPath, deps = { fetchImpl: fetch }) {
2072
2072
  const outcome = await onStartUnderMarker({
2073
2073
  configPath,
2074
2074
  own: ownVersionOf(deps),
2075
- check: update.check ? () => update.check(configPath) : async () => (await import('./check-63IDCEEV.js')).runRunnerCheck(configPath, { fetchImpl: deps.fetchImpl }),
2075
+ check: update.check ? () => update.check(configPath) : async () => (await import('./check-SRGR36KI.js')).runRunnerCheck(configPath, { fetchImpl: deps.fetchImpl }),
2076
2076
  now: () => (deps.now ?? (() => /* @__PURE__ */ new Date()))().getTime(),
2077
2077
  log
2078
2078
  });
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { fetchFactories, selectFactory, saveFactoryConnection, autoConnectedLine } from './chunk-4QVZCVWT.js';
3
+ import { fetchFactories, selectFactory, saveFactoryConnection, autoConnectedLine } from './chunk-YDSMROTB.js';
4
4
  import { resolveRepoIdentity } from './chunk-JXYVA45C.js';
5
5
  import { resolveGatewayCredentials } from './chunk-PLMTLGYH.js';
6
6
  import { findGitDirs, readRepoConnection } from './chunk-BJ3KTMDH.js';
@@ -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-7S6NLLRO.js');
637
+ const { materializeContext: materialize } = await import('./context-materialize-FDHYKNDT.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;
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { detectMachine, supportsContainerBuilds, reachDockerStep, describeMachineDocker, supportsMicroVmBuilds } from './chunk-P6FX4D43.js';
4
- import { MIN_ENGINE_MAJOR } from './chunk-MZN7AQOB.js';
3
+ import { detectMachine, supportsContainerBuilds, reachDockerStep, describeMachineDocker, supportsMicroVmBuilds } from './chunk-JYIEHQIF.js';
4
+ import { MIN_ENGINE_MAJOR } from './chunk-RBKIH5ST.js';
5
5
  import { hasStoredCredential, AGENT_COMMANDS, storeClaudeCredential, credentialFromStdin, isAgentName } from './chunk-T5VPP6H7.js';
6
6
  import { runnerCredentialProblem } from './chunk-22RMZBGW.js';
7
7
  import { runnerDir, RUNNER_DIR_MODE, RUNNER_FILE_MODE } from './chunk-ZM2IMMYN.js';
@@ -1,23 +1,23 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { readDefaultBranchHead, cloneRepository, buildRepositoryImage } from './chunk-3FMPZPJQ.js';
4
- import { startTimeOf, isSameProcess } from './chunk-N5FOE5PS.js';
5
- import { currentCliBuild } from './chunk-OGFGZQA3.js';
6
- import { createDockerHost, childEnvironment, spawnRun } from './chunk-3KTA5UU2.js';
7
- import { RecipeError } from './chunk-QOZKPLVJ.js';
8
- import { builderSpec, runnerLabelValue, RUNNER_LABEL, BUILD_LABEL, prepareRunArgs, containerRunArgs, containerExecArgs } from './chunk-NX57IBNK.js';
9
- 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';
3
+ import { createDockerHost, childEnvironment, spawnRun } from './chunk-KMDLFI4P.js';
10
4
  import { execCapture } from './chunk-QKFB4K7X.js';
11
5
  import { GUEST_CID } from './chunk-RSNSZ2LJ.js';
12
- import { WorkCommandError, postJson } from './chunk-P4MM66C6.js';
13
- import { setCustomScrubbers, setLocalIdentity, setRepoRoot, parseTranscript, scrubDeep, scrubText } from './chunk-JXYVA45C.js';
6
+ import { WorkCommandError, postJson } from './chunk-SWHQ4LUM.js';
14
7
  import { hostAllowed } from './chunk-UXYLWVTQ.js';
8
+ import { readDefaultBranchHead, cloneRepository, buildRepositoryImage } from './chunk-R7PF5OOU.js';
9
+ import { RecipeError } from './chunk-QOZKPLVJ.js';
10
+ import { startTimeOf, isSameProcess } from './chunk-N5FOE5PS.js';
11
+ import { currentCliBuild } from './chunk-OGFGZQA3.js';
12
+ import { builderSpec, runnerLabelValue, RUNNER_LABEL, BUILD_LABEL, prepareRunArgs, containerRunArgs, containerExecArgs } from './chunk-4NPZVMJU.js';
15
13
  import { parseDuKilobytes } from './chunk-7RQ73DLO.js';
16
14
  import { repositoriesOf, primaryOf, RELAY_PORT, CHECKOUT_DIR, JOB_MOUNT, claudeCredential, buildEnvironment, startBuildServices, checkEnvironment, AGENT_CREDENTIAL_MISSING, checkoutPath } from './chunk-4Q7OMKAT.js';
17
- import { defaultGitRunner, materializeContext } from './chunk-GI4XXD4I.js';
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
+ import { setCustomScrubbers, setLocalIdentity, setRepoRoot, parseTranscript, scrubDeep, scrubText } from './chunk-JXYVA45C.js';
17
+ import { defaultGitRunner, materializeContext } from './chunk-3NLOVYJQ.js';
18
18
  import { readContextManifest, readSourceCache } from './chunk-LCEXHCHD.js';
19
- import { orderSessions, extractFacts, sessionsToTimeline } from './chunk-2M63GG56.js';
20
19
  import { signingFetchFor } from './chunk-YO4PSLVB.js';
20
+ import { orderSessions, extractFacts, sessionsToTimeline } from './chunk-2M63GG56.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';
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { isPlaceholderCommand } from './chunk-MJXXRX4M.js';
4
- import { describeCallFailure } from './chunk-MZN7AQOB.js';
5
- import { WorkCommandError, getJson } from './chunk-P4MM66C6.js';
6
- import { sanitizeTerminal } from './chunk-CNFVHDHG.js';
3
+ import { isPlaceholderCommand } from './chunk-Q2UK3C4P.js';
4
+ import { describeCallFailure } from './chunk-RBKIH5ST.js';
5
+ import { WorkCommandError, getJson } from './chunk-SWHQ4LUM.js';
7
6
  import { builtinKind } from './chunk-22RMZBGW.js';
8
7
  import { CLAUDE_CREDENTIAL_VARIABLES, claudeCredential } from './chunk-4Q7OMKAT.js';
8
+ import { sanitizeTerminal } from './chunk-WUYTWNMA.js';
9
9
  import { signerFor } from './chunk-V7NIVOFD.js';
10
10
 
11
11
  createRequire(import.meta.url);
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { autoConnect } from './chunk-EFZLAYPE.js';
3
+ import { autoConnect } from './chunk-NPQWKGUA.js';
4
4
  import { detectActiveSession } from './chunk-IP7BIBXJ.js';
5
- import { workPageUrl } from './chunk-4QVZCVWT.js';
6
- import { sanitizeTerminal } from './chunk-CNFVHDHG.js';
5
+ import { workPageUrl } from './chunk-YDSMROTB.js';
6
+ import { sanitizeTerminal } from './chunk-WUYTWNMA.js';
7
7
  import { resolveRepoIdentity } from './chunk-JXYVA45C.js';
8
8
  import { C } from './chunk-YRYMNBGQ.js';
9
9
  import { parseTrackerNumber, trackerNumberError } from './chunk-WZBHBH3J.js';
@@ -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-PXWKQPN6.js');
363
+ const { logHookError } = await import('./hook-fast-WYQD6D7T.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
  }
@@ -1,26 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { runEmit } from './chunk-HDTVTA6I.js';
4
- import { addStdioMcpEntryIfAbsent, addDocsMcpEntryIfAbsent, DOCS_MCP_SERVER_NAME } from './chunk-R7OQTKWT.js';
5
- import { installStarterPack } from './chunk-DXQ5MHCO.js';
3
+ import { runEmit } from './chunk-HFKKFTXU.js';
4
+ import { addStdioMcpEntryIfAbsent, addDocsMcpEntryIfAbsent, DOCS_MCP_SERVER_NAME } from './chunk-XCK2YAY5.js';
5
+ import { installStarterPack } from './chunk-FOJGZYFC.js';
6
6
  import { C } from './chunk-YRYMNBGQ.js';
7
- import { resolveGitCommonDir, defaultGitRunner } from './chunk-GI4XXD4I.js';
8
- import './chunk-ZJSNLVCE.js';
9
- import { loadTemplateFiles, loadMaintainedFiles, skillDir } from './chunk-TCIW27FM.js';
7
+ import { resolveGitCommonDir, defaultGitRunner } from './chunk-3NLOVYJQ.js';
10
8
  import { pinExists, readContextManifest } from './chunk-LCEXHCHD.js';
9
+ import { loadTemplateFiles, loadMaintainedFiles, skillDir } from './chunk-ZA5CHAFY.js';
11
10
  import { generatedHeaderSource } from './chunk-2M63GG56.js';
12
- import './chunk-YO4PSLVB.js';
13
- import './chunk-PLMTLGYH.js';
14
- import './chunk-J5M7BSJQ.js';
15
- import './chunk-EABW6AJQ.js';
16
- import './chunk-BYT5O5RV.js';
17
- import './chunk-RA3O54FC.js';
18
- import './chunk-V7NIVOFD.js';
19
- import './chunk-ZM2IMMYN.js';
20
- import './chunk-XCCLFVXM.js';
21
- import './chunk-BJ3KTMDH.js';
22
- import './chunk-VNVZDWO3.js';
23
- import './chunk-Z5GEFMRW.js';
24
11
  import { execFileSync } from 'child_process';
25
12
  import { existsSync, mkdirSync, writeFileSync } from 'fs';
26
13
  import { join, dirname } from 'path';
@@ -201,4 +188,4 @@ ${renderPaths(paths, kept)}${mcpNote}`;
201
188
  `;
202
189
  }
203
190
 
204
- export { runAgentSetup };
191
+ export { keepHandWritten, runAgentSetup };
@@ -214,7 +214,9 @@ function readPersistedArtifactSpoolState(home) {
214
214
  attempts: typeof e.attempts === "number" && Number.isFinite(e.attempts) ? e.attempts : 0,
215
215
  firstSeen: typeof e.firstSeen === "string" ? e.firstSeen : (/* @__PURE__ */ new Date(0)).toISOString(),
216
216
  sha256: typeof e.sha256 === "string" ? e.sha256 : "",
217
- reachedServer: e.reachedServer === true
217
+ reachedServer: e.reachedServer === true,
218
+ ...typeof e.serverId === "string" ? { serverId: e.serverId } : {},
219
+ ...typeof e.url === "string" ? { url: e.url } : {}
218
220
  });
219
221
  }
220
222
  return { state, corrupt: false };
@@ -2,7 +2,7 @@
2
2
  import { createRequire } from 'node:module';
3
3
  import { C } from './chunk-YRYMNBGQ.js';
4
4
  import { readCloudConfig } from './chunk-EABW6AJQ.js';
5
- import { existsSync, writeFileSync, mkdirSync, readFileSync } from 'fs';
5
+ import { existsSync, writeFileSync, readFileSync, mkdirSync } from 'fs';
6
6
  import { join, dirname } from 'path';
7
7
 
8
8
  createRequire(import.meta.url);
@@ -62,14 +62,23 @@ function addMcpEntryIfAbsent(repoRoot, name, entry) {
62
62
  `);
63
63
  return { path: relPath, added: true };
64
64
  }
65
+ function setMcpEntry(repoRoot, name, entry) {
66
+ const relPath = mcpTargetPath(repoRoot);
67
+ const absPath = join(repoRoot, relPath);
68
+ const doc = readMcpDoc(absPath, relPath);
69
+ const servers = doc.mcpServers ?? {};
70
+ writeFileSync(absPath, `${JSON.stringify({ ...doc, mcpServers: { ...servers, [name]: entry } }, null, 2)}
71
+ `);
72
+ }
65
73
  var INIT_STDIO_ENTRY = { type: "stdio", command: "npx", args: ["-y", "@outerlayer/cli", "mcp", "serve"] };
66
74
  function addStdioMcpEntryIfAbsent(repoRoot, name = "outerlayer") {
67
75
  return addMcpEntryIfAbsent(repoRoot, name, { ...INIT_STDIO_ENTRY, args: [...INIT_STDIO_ENTRY.args] });
68
76
  }
69
77
  var DOCS_MCP_SERVER_NAME = "outerlayer-docs";
70
78
  var DOCS_MCP_URL = "https://docs.outerlayer.ai/mcp";
79
+ var INIT_DOCS_ENTRY = { type: "http", url: DOCS_MCP_URL };
71
80
  function addDocsMcpEntryIfAbsent(repoRoot) {
72
- return addMcpEntryIfAbsent(repoRoot, DOCS_MCP_SERVER_NAME, { type: "http", url: DOCS_MCP_URL });
81
+ return addMcpEntryIfAbsent(repoRoot, DOCS_MCP_SERVER_NAME, { ...INIT_DOCS_ENTRY });
73
82
  }
74
83
  function runMcpInstall(opts = {}) {
75
84
  const cwd = opts.cwd ?? process.cwd();
@@ -100,4 +109,4 @@ function handleMcpInstallError(err) {
100
109
  process.exitCode = 1;
101
110
  }
102
111
 
103
- export { DEFAULT_MCP_COMMAND, DOCS_MCP_SERVER_NAME, McpInstallError, addDocsMcpEntryIfAbsent, addStdioMcpEntryIfAbsent, buildServerEntry, buildStdioServerEntry, defaultMcpUrl, handleMcpInstallError, runMcpInstall };
112
+ export { DEFAULT_MCP_COMMAND, DOCS_MCP_SERVER_NAME, INIT_DOCS_ENTRY, INIT_STDIO_ENTRY, McpInstallError, addDocsMcpEntryIfAbsent, addStdioMcpEntryIfAbsent, buildServerEntry, buildStdioServerEntry, defaultMcpUrl, handleMcpInstallError, mcpTargetPath, runMcpInstall, setMcpEntry };
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { sanitizeTerminal } from './chunk-CNFVHDHG.js';
3
+ import { sanitizeTerminal } from './chunk-WUYTWNMA.js';
4
4
  import { remoteLookupFailed } from './chunk-JXYVA45C.js';
5
5
  import { DEFAULT_DASHBOARD } from './chunk-4KSQKQXE.js';
6
6
  import { resolveGatewayCredentials } from './chunk-PLMTLGYH.js';
@@ -7,7 +7,7 @@ import { join, dirname } from 'path';
7
7
  import { fileURLToPath } from 'url';
8
8
 
9
9
  createRequire(import.meta.url);
10
- var TEMPLATE_SKILLS = ["spec", "writing-specs", "build"];
10
+ var TEMPLATE_SKILLS = ["spec", "writing-specs", "writing-tests", "build"];
11
11
  var MAINTAINED_SKILLS = ["emitting-evidence", "amend", "reporting-findings", "outerlayer"];
12
12
  var TEMPLATE_CLASS_LINE = "<!-- yours to edit. Copied once from the default template by outerlayer init; never overwritten. -->";
13
13
  function maintainedClassLine(version) {