@outerlayer/cli 0.13.0 → 0.14.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 (78) hide show
  1. package/CHANGELOG.md +19 -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 +75 -0
  67. package/skill-pack/template/build/SKILL.md +8 -3
  68. package/skill-pack/template/build/references/release.md +42 -11
  69. package/skill-pack/template/build/references/review-loop.md +1 -1
  70. package/skill-pack/template/build/scripts/criterion-citations.mjs +184 -0
  71. package/skill-pack/template/spec/SKILL.md +33 -22
  72. package/skill-pack/template/writing-specs/SKILL.md +36 -3
  73. package/skill-pack/template/writing-specs/references/agents-snippet.md +57 -0
  74. package/skill-pack/template/writing-tests/SKILL.md +117 -0
  75. package/skill-pack/validators/acceptance-criteria.yaml +35 -0
  76. package/dist/mcp-install-cmd-VXVIH7PH.js +0 -9
  77. package/dist/{chunk-NX57IBNK.js → chunk-4NPZVMJU.js} +2 -2
  78. package/dist/{chunk-3FMPZPJQ.js → chunk-R7PF5OOU.js} +1 -1
@@ -4,7 +4,7 @@ import { LaunchFilter } from './chunk-HHJDN6AU.js';
4
4
  import { RepoFilter } from './chunk-TBT347UY.js';
5
5
  import { hookExecSpoolPath } from './chunk-F7CU5ABH.js';
6
6
  import { applyReportedCost } from './chunk-BKO6JEZI.js';
7
- import { migrateLegacyArtifactSidecars, planArtifactUpload, artifactsStatePath, sanitizeTerminal, acquireArtifactSpoolLock, artifactBlobsDir, resolveArtifactTurnIndex, isArtifactTombstoned, ARTIFACT_RETRY_MAX_AGE_MS, writeArtifactSpoolState, reclaimUnneededArtifactBlobs, neededArtifactShas } from './chunk-CNFVHDHG.js';
7
+ import { migrateLegacyArtifactSidecars, planArtifactUpload, artifactsStatePath, sanitizeTerminal, acquireArtifactSpoolLock, artifactBlobsDir, resolveArtifactTurnIndex, isArtifactTombstoned, ARTIFACT_RETRY_MAX_AGE_MS, writeArtifactSpoolState, reclaimUnneededArtifactBlobs, neededArtifactShas } from './chunk-WUYTWNMA.js';
8
8
  import { setCustomScrubbers, setLocalIdentity, tailTranscript, enrichSessionRepo, scanAll, setRepoRoot, resolveRepoIdentity, sessionIdFromPath, scrubDeep, SOURCE_ADAPTERS } from './chunk-JXYVA45C.js';
9
9
  import { C } from './chunk-YRYMNBGQ.js';
10
10
  import { readLaunchSpoolState, launchStatusIsDecisive, launchedItemsBySession, launchesPath } from './chunk-GQD22KKN.js';
@@ -14,7 +14,7 @@ import { resolveGatewayCredentials, unauthorizedMessage } from './chunk-PLMTLGYH
14
14
  import { CAPTURE_TIERS, inferArtifactKind, bannedPathsForTier, downconvertSession, isHumanUserTurn, turnCountBound, EVENT_TYPES } from './chunk-J5M7BSJQ.js';
15
15
  import { readCloudConfig, cloudConfigPath, writeCloudConfig } from './chunk-EABW6AJQ.js';
16
16
  import { signerFor, signRunnerRequest } from './chunk-V7NIVOFD.js';
17
- import { writeSyncStatus, spoolDir } from './chunk-SFFHGX3G.js';
17
+ import { writeSyncStatus, spoolDir } from './chunk-PQUM37BK.js';
18
18
  import { removeJournalHooks } from './chunk-XCCLFVXM.js';
19
19
  import { readRepoConnection, findGitDirs } from './chunk-BJ3KTMDH.js';
20
20
  import { homeFromEnv } from './chunk-VNVZDWO3.js';
@@ -928,6 +928,21 @@ var NEVER_REACHED_SERVER_ERROR_CODES = /* @__PURE__ */ new Set([
928
928
  "payload_too_large",
929
929
  "unreadable_test_results"
930
930
  ]);
931
+ async function readUploadedIdentity(response) {
932
+ let data;
933
+ try {
934
+ data = (await response.json()).data;
935
+ } catch {
936
+ }
937
+ return {
938
+ id: typeof data?.id === "string" ? data.id : null,
939
+ url: typeof data?.url === "string" ? data.url : null
940
+ };
941
+ }
942
+ function uploadedArtifactLine(artifact) {
943
+ const where = artifact.url !== null ? sanitizeTerminal(artifact.url) : artifact.id !== null ? `id ${sanitizeTerminal(artifact.id)} ${C.dim}(the gateway returned no link)${C.reset}` : `${C.dim}(the gateway returned no link)${C.reset}`;
944
+ return ` ${C.green}\u2191${C.reset} ${sanitizeTerminal(artifact.filename)} ${C.dim}\xB7${C.reset} ${sanitizeTerminal(artifact.caption)} ${C.dim}\xB7${C.reset} ${where}`;
945
+ }
931
946
  function splitPayload(payload) {
932
947
  const mid = Math.ceil(payload.sessions.length / 2);
933
948
  const first = payload.sessions.slice(0, mid);
@@ -1553,10 +1568,12 @@ ${C.yellow}!${C.reset} batch ${shippedBatches + 1}/${batches.length} accounting
1553
1568
  }
1554
1569
  let artifactsUploaded;
1555
1570
  let artifactsHeld;
1571
+ let uploadedArtifacts;
1556
1572
  const artifactLock = combinedRecords.length > 0 || artifactPlan.held.length > 0 ? await acquireArtifactSpoolLock(home, { waitMs: opts.artifactLockWaitMs }) : void 0;
1557
1573
  if (artifactLock !== void 0 && !artifactLock.ok) {
1558
1574
  artifactsUploaded = 0;
1559
1575
  artifactsHeld = combinedRecords.length + artifactPlan.held.length;
1576
+ uploadedArtifacts = [];
1560
1577
  if (!opts.quiet) {
1561
1578
  process.stderr.write(
1562
1579
  `${C.yellow}!${C.reset} artifacts not attempted: ${artifactLock.reason} \u2014 ${artifactsHeld} record(s) stay queued for the next sync
@@ -1575,6 +1592,7 @@ ${C.yellow}!${C.reset} batch ${shippedBatches + 1}/${batches.length} accounting
1575
1592
  let uploadedCount = 0;
1576
1593
  let heldCount = livePlan.held.length;
1577
1594
  let droppedCount = 0;
1595
+ const uploadedThisRun = [];
1578
1596
  const warn = (message) => {
1579
1597
  if (!opts.quiet) process.stderr.write(`${C.yellow}!${C.reset} ${message}
1580
1598
  `);
@@ -1651,6 +1669,7 @@ ${C.yellow}!${C.reset} batch ${shippedBatches + 1}/${batches.length} accounting
1651
1669
  let status;
1652
1670
  let errorCode = "";
1653
1671
  let serverMessage = "";
1672
+ let accepted;
1654
1673
  try {
1655
1674
  const response = await fetchImpl(artifactEndpoint, {
1656
1675
  method: "POST",
@@ -1670,19 +1689,31 @@ ${C.yellow}!${C.reset} batch ${shippedBatches + 1}/${batches.length} accounting
1670
1689
  if (typeof body.error?.message === "string") serverMessage = body.error.message;
1671
1690
  } catch {
1672
1691
  }
1692
+ } else {
1693
+ accepted = response;
1673
1694
  }
1674
1695
  } catch (err) {
1675
1696
  failure = String(err);
1676
1697
  }
1677
- if (!failure) {
1698
+ if (accepted !== void 0) {
1699
+ const identity = await readUploadedIdentity(accepted);
1678
1700
  state.set(record.artifactId, {
1679
1701
  state: "uploaded",
1680
1702
  attempts: (existing?.attempts ?? 0) + 1,
1681
1703
  firstSeen: firstSeenIso,
1682
1704
  sha256: record.sha256,
1683
- reachedServer: true
1705
+ reachedServer: true,
1706
+ ...identity.id !== null ? { serverId: identity.id } : {},
1707
+ ...identity.url !== null ? { url: identity.url } : {}
1684
1708
  });
1685
1709
  uploadedCount += 1;
1710
+ uploadedThisRun.push({
1711
+ artifactId: record.artifactId,
1712
+ filename: record.filename,
1713
+ caption: record.caption,
1714
+ id: identity.id,
1715
+ url: identity.url
1716
+ });
1686
1717
  continue;
1687
1718
  }
1688
1719
  if (status === 401) {
@@ -1739,11 +1770,15 @@ ${C.yellow}!${C.reset} batch ${shippedBatches + 1}/${batches.length} accounting
1739
1770
  artifactsUploaded = uploadedCount;
1740
1771
  artifactsHeld = heldCount;
1741
1772
  artifactsDropped = droppedCount;
1773
+ uploadedArtifacts = uploadedThisRun;
1742
1774
  if (!opts.quiet) {
1743
1775
  process.stderr.write(
1744
1776
  `${C.dim}artifacts${C.reset} ${uploadedCount} uploaded \xB7 ${heldCount} held \xB7 ${droppedCount} dropped
1745
1777
  `
1746
1778
  );
1779
+ if (!opts.json) {
1780
+ for (const uploaded of uploadedThisRun) process.stdout.write(uploadedArtifactLine(uploaded) + "\n");
1781
+ }
1747
1782
  }
1748
1783
  }
1749
1784
  const persisted = writeArtifactSpoolState(state, home);
@@ -1776,6 +1811,7 @@ ${C.yellow}!${C.reset} batch ${shippedBatches + 1}/${batches.length} accounting
1776
1811
  );
1777
1812
  }
1778
1813
  }
1814
+ const artifactReport = artifactsUploaded !== void 0 ? { artifactsUploaded, artifactsHeld, uploadedArtifacts } : {};
1779
1815
  let output;
1780
1816
  if (opts.json) {
1781
1817
  output = JSON.stringify({
@@ -1787,7 +1823,7 @@ ${C.yellow}!${C.reset} batch ${shippedBatches + 1}/${batches.length} accounting
1787
1823
  artifactsDropped,
1788
1824
  tier,
1789
1825
  url,
1790
- ...artifactsUploaded !== void 0 ? { artifactsUploaded, artifactsHeld } : {}
1826
+ ...artifactReport
1791
1827
  });
1792
1828
  } else {
1793
1829
  const lines = [];
@@ -1826,7 +1862,7 @@ ${C.yellow}!${C.reset} batch ${shippedBatches + 1}/${batches.length} accounting
1826
1862
  url,
1827
1863
  dryRun: false,
1828
1864
  watermarkMs,
1829
- ...artifactsUploaded !== void 0 ? { artifactsUploaded, artifactsHeld } : {},
1865
+ ...artifactReport,
1830
1866
  output
1831
1867
  };
1832
1868
  }
@@ -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) {