@outerlayer/cli 0.26.3 → 0.27.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 (129) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +12 -9
  3. package/dist/{agent-setup-PZYQWN4H.js → agent-setup-UW36TAQM.js} +13 -13
  4. package/dist/{bridge-5KZ36YDG.js → bridge-B5VJVECY.js} +2 -2
  5. package/dist/build-TNM7HYCA.js +12 -0
  6. package/dist/build-info.json +1 -1
  7. package/dist/{builder-WEGLC2F2.js → builder-LDJGS2JC.js} +6 -6
  8. package/dist/{check-WJJ325EQ.js → check-JVBAWIN6.js} +44 -43
  9. package/dist/{chunk-7LVF4E5V.js → chunk-24ID7EQ2.js} +7 -4
  10. package/dist/{chunk-HXFRJKMU.js → chunk-2F762IXY.js} +2 -2
  11. package/dist/{chunk-2K3TCQHW.js → chunk-2I3LIRZP.js} +26 -8
  12. package/dist/{chunk-UKCNOAO6.js → chunk-55GNQPO6.js} +17 -6
  13. package/dist/{chunk-XSPA5ODY.js → chunk-6BLXUD56.js} +4 -3
  14. package/dist/{chunk-MWPBF2XG.js → chunk-6KKM7VGZ.js} +32 -4
  15. package/dist/{chunk-VPEGE3QZ.js → chunk-6TRNCUM4.js} +1 -1
  16. package/dist/{chunk-MLD2NA7N.js → chunk-7AQ5AM7U.js} +12 -5
  17. package/dist/{chunk-HBISTTG3.js → chunk-7OUOLGUV.js} +20 -5
  18. package/dist/{chunk-6FAP657M.js → chunk-ABXQBEYK.js} +1 -1
  19. package/dist/{chunk-TSW4DGV2.js → chunk-B6K7R5UY.js} +2 -2
  20. package/dist/chunk-BM7EC3OZ.js +181 -0
  21. package/dist/{chunk-W3NVHOCS.js → chunk-BPKO76QR.js} +4 -4
  22. package/dist/{chunk-QRZLUUNN.js → chunk-BWH36FOC.js} +8 -3
  23. package/dist/{chunk-PYSKSROG.js → chunk-D7ECMB7B.js} +4 -4
  24. package/dist/{chunk-FO7F6QSV.js → chunk-DJHNEGNM.js} +27 -3
  25. package/dist/{chunk-TPAF24PK.js → chunk-E5IJ5533.js} +2 -2
  26. package/dist/{chunk-JWRX5ZTT.js → chunk-EPPIISRD.js} +2 -2
  27. package/dist/{chunk-6M4LNO22.js → chunk-FP23SVDD.js} +6 -6
  28. package/dist/{chunk-GOSFARMS.js → chunk-G2JWZDFA.js} +9 -2
  29. package/dist/{chunk-XFGL53GU.js → chunk-G3EZA6MK.js} +56 -8
  30. package/dist/{chunk-5PMQDQFV.js → chunk-GFUE5TKO.js} +3 -3
  31. package/dist/{chunk-XLC7KEUV.js → chunk-GLUKDQS4.js} +1 -1
  32. package/dist/{chunk-ZLEXMZFW.js → chunk-JH2GQU5T.js} +5 -5
  33. package/dist/{chunk-YVZJ6GKF.js → chunk-KT4CN6OU.js} +1 -1
  34. package/dist/{chunk-JKNYTNYD.js → chunk-LOKSLO25.js} +1 -1
  35. package/dist/{chunk-665QWBNW.js → chunk-M3MHHIUW.js} +1 -1
  36. package/dist/{chunk-4IFKLYMM.js → chunk-MATUHHN4.js} +1 -1
  37. package/dist/{chunk-MQ743JX3.js → chunk-MHX7YX7Y.js} +1 -1
  38. package/dist/{chunk-TEVO3RUV.js → chunk-N4D5TMVU.js} +4 -4
  39. package/dist/{chunk-EORWWFPA.js → chunk-O2IJTY7L.js} +2 -2
  40. package/dist/{chunk-EABW6AJQ.js → chunk-PJDQPF5N.js} +18 -5
  41. package/dist/{chunk-KDDFI5MR.js → chunk-QHH4OSD4.js} +1 -1
  42. package/dist/{chunk-W7LGHNXT.js → chunk-QIVOTQOQ.js} +5 -5
  43. package/dist/{chunk-JF572PM5.js → chunk-QKIQ2R7F.js} +3 -3
  44. package/dist/{chunk-L4CW6LZQ.js → chunk-RHAGBUL5.js} +5 -2
  45. package/dist/{chunk-TKL74NLB.js → chunk-RHGF73IU.js} +1 -1
  46. package/dist/{chunk-SKZG7SAN.js → chunk-RK7FWC6B.js} +206 -42
  47. package/dist/{chunk-6MZSX4M7.js → chunk-STSLH5EJ.js} +3 -1
  48. package/dist/{chunk-K7FCZCLQ.js → chunk-TXHJ7BGR.js} +13 -13
  49. package/dist/{chunk-364XDGOK.js → chunk-UQYBCJ2L.js} +3 -3
  50. package/dist/{chunk-2AKDF6C2.js → chunk-VS27BP3E.js} +5 -5
  51. package/dist/{chunk-J7BXZLSO.js → chunk-WSYXLLA5.js} +29 -8
  52. package/dist/{chunk-WX2WEERU.js → chunk-WUL2OP5A.js} +3 -3
  53. package/dist/{chunk-ZPXI7LMG.js → chunk-WVDP6HVZ.js} +6 -6
  54. package/dist/{chunk-MXTN35XN.js → chunk-XBPUTQ7E.js} +1 -1
  55. package/dist/{chunk-UNF7MWEL.js → chunk-XS3FDWSZ.js} +1 -1
  56. package/dist/{chunk-VJBFQP3H.js → chunk-XZ6Q6ZNR.js} +9 -5
  57. package/dist/{chunk-F6DIHHBS.js → chunk-Y4OKEFAX.js} +1 -1
  58. package/dist/{chunk-XDHYZWEK.js → chunk-Y7ZCHBYB.js} +2 -2
  59. package/dist/chunk-YB3CSYXX.js +95 -0
  60. package/dist/{chunk-VHVFU6QU.js → chunk-YF56R4DV.js} +86 -31
  61. package/dist/chunk-YJLHUKYS.js +38 -0
  62. package/dist/{chunk-XF77SNB4.js → chunk-ZXRWMOJ3.js} +287 -51
  63. package/dist/{claude-launcher-O2U6P6ZD.js → claude-launcher-TKX4WCUN.js} +8 -4
  64. package/dist/{cli-2UUJM3AE.js → cli-XVXQDKZT.js} +141 -135
  65. package/dist/{command-GQBHC53U.js → command-B2T7VR77.js} +33 -32
  66. package/dist/{config-JJ3EO7SB.js → config-TWS5VZEN.js} +3 -3
  67. package/dist/{connect-cmd-2JHSLBXK.js → connect-cmd-HGS7YPA2.js} +10 -10
  68. package/dist/{container-start-AUJHF2BC.js → container-start-JE7HTKZG.js} +32 -31
  69. package/dist/{control-plane-launch-654RV5PO.js → control-plane-launch-DBQA3KLJ.js} +9 -9
  70. package/dist/{docker-NYAIIX2F.js → docker-MJEEHUUA.js} +6 -6
  71. package/dist/{doctor-NV2PUERZ.js → doctor-6ZIF2BRZ.js} +184 -37
  72. package/dist/{emit-artifact-cmd-XXTCHP6V.js → emit-artifact-cmd-ALDK55Y2.js} +14 -14
  73. package/dist/{emit-cmd-WQH2NK7H.js → emit-cmd-VAQHRWJR.js} +4 -4
  74. package/dist/{emit-criteria-cmd-VMZIRJCQ.js → emit-criteria-cmd-Q7SM6VP2.js} +11 -11
  75. package/dist/{emit-finding-cmd-KMJNYQI7.js → emit-finding-cmd-2NBAPDSV.js} +11 -11
  76. package/dist/{emit-result-cmd-HRTXGZLK.js → emit-result-cmd-KUSL56RI.js} +14 -14
  77. package/dist/{emit-step-cmd-AUHA3EXY.js → emit-step-cmd-KD4AKEAT.js} +12 -12
  78. package/dist/{exec-client-J6L5FDRR.js → exec-client-6WVS7DRZ.js} +3 -3
  79. package/dist/{governing-source-PTJ6EAA3.js → governing-source-VVUA5TKB.js} +16 -16
  80. package/dist/{guest-init-CXIHA5VI.js → guest-init-H5K2RW3P.js} +4 -4
  81. package/dist/{hook-fast-SDFXJEAW.js → hook-fast-3SUJM765.js} +1 -1
  82. package/dist/{host-key-5TKBNUZ4.js → host-key-XNKZCWTS.js} +3 -3
  83. package/dist/{image-tag-5SJ6ZKT7.js → image-tag-R34J4O3F.js} +3 -3
  84. package/dist/index.js +4 -4
  85. package/dist/init-ETKGFCXR.js +55 -0
  86. package/dist/{init-UZWRJMPZ.js → init-Q2RPUUVP.js} +33 -32
  87. package/dist/{init-cmd-SQKWPACS.js → init-cmd-M6MQRGOU.js} +19 -18
  88. package/dist/{init-update-FJDKY4SJ.js → init-update-N4HTZGVS.js} +59 -30
  89. package/dist/{inspect-6UYAAXH7.js → inspect-IPFA7AAT.js} +1 -1
  90. package/dist/{install-QSTTBUHX.js → install-6OIY3KHZ.js} +6 -5
  91. package/dist/{install-cmd-3DXJJUAA.js → install-cmd-JMT67P35.js} +5 -5
  92. package/dist/{layout-UOJQGEPW.js → layout-XNFDTOET.js} +2 -2
  93. package/dist/{login-browser-4OMZFP3U.js → login-browser-EWXSGHM7.js} +3 -3
  94. package/dist/{logout-cmd-5V5MMBSY.js → logout-cmd-5WE2N5B5.js} +2 -2
  95. package/dist/{logs-VN2HKDSH.js → logs-XHAS6LMZ.js} +2 -2
  96. package/dist/loop-2Y4CUFNP.js +79 -0
  97. package/dist/machine-Z2S47JW7.js +50 -0
  98. package/dist/machine-skills-RRF4HLAD.js +11 -0
  99. package/dist/{mcp-install-cmd-GGWB3JJ2.js → mcp-install-cmd-LD7KYAOP.js} +2 -2
  100. package/dist/{mcp-serve-cmd-U5N5DK3H.js → mcp-serve-cmd-LY5A3CE7.js} +5 -5
  101. package/dist/{paths-ZC6BMWMT.js → paths-LHSPNORF.js} +2 -2
  102. package/dist/{pending-54HC7MM3.js → pending-3YZCSKON.js} +3 -3
  103. package/dist/{pidfile-BY5Z6YH7.js → pidfile-DKMYYXLH.js} +3 -3
  104. package/dist/{record-K23IN6QN.js → record-3LPTY3G5.js} +3 -3
  105. package/dist/{runner-env-2D7MPOIJ.js → runner-env-YRRNRKF4.js} +8 -7
  106. package/dist/{runner-identity-YYENYKDH.js → runner-identity-EX7HXPUE.js} +6 -6
  107. package/dist/{runner-key-AZVXBQIB.js → runner-key-GO277GW2.js} +32 -31
  108. package/dist/{session-sender-VH2EKAT5.js → session-sender-SC5PSU2G.js} +15 -15
  109. package/dist/{spec-cmd-BOUPLX7X.js → spec-cmd-JGYHHJ4P.js} +12 -12
  110. package/dist/{starter-pack-55EFILC5.js → starter-pack-GPU4X6B7.js} +2 -2
  111. package/dist/{status-3WC2IGVI.js → status-CJCE2FHD.js} +34 -33
  112. package/dist/{sync-cmd-GT2WTQRA.js → sync-cmd-ATXJVS7S.js} +14 -14
  113. package/dist/{watch-JED7SYAA.js → watch-M7NR3DOW.js} +14 -14
  114. package/dist/{work-claim-cmd-MY4N74HA.js → work-claim-cmd-DNUDZKJA.js} +16 -16
  115. package/dist/{work-cmd-UQ45HDM4.js → work-cmd-VECTYST6.js} +12 -12
  116. package/dist/{work-comment-cmd-I7NNSNDP.js → work-comment-cmd-F3NRWKPZ.js} +12 -12
  117. package/dist/{work-logs-cmd-YIQJVENH.js → work-logs-cmd-QF6P32FE.js} +12 -12
  118. package/dist/{work-open-pr-cmd-VP5NNTCW.js → work-open-pr-cmd-XE23JA3R.js} +13 -13
  119. package/dist/{work-pr-cmd-DKTBEFHO.js → work-pr-cmd-BH56GUKN.js} +12 -12
  120. package/dist/{work-stop-cmd-GN2WX73C.js → work-stop-cmd-C3F5HNUO.js} +12 -12
  121. package/package.json +1 -1
  122. package/skill-pack/maintained/outerlayer-cli/SKILL.md +6 -5
  123. package/skill-pack/shipped.json +1 -0
  124. package/skill-pack/template/build/SKILL.md +1 -1
  125. package/dist/build-EBQYXL7Y.js +0 -12
  126. package/dist/chunk-7RQ73DLO.js +0 -23
  127. package/dist/init-KIGYMLDM.js +0 -54
  128. package/dist/loop-OE32U2IZ.js +0 -78
  129. package/dist/machine-L7INJ4JN.js +0 -49
@@ -1,8 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { builtinKind } from './chunk-JWRX5ZTT.js';
4
- import { parseSize } from './chunk-7RQ73DLO.js';
5
- import { runnerDir } from './chunk-L4CW6LZQ.js';
3
+ import { FD_SLOTS_PER_BUILD, FD_STORE_ENV } from './chunk-YB3CSYXX.js';
4
+ import { builtinKind } from './chunk-EPPIISRD.js';
5
+ import { parseSize } from './chunk-YJLHUKYS.js';
6
+ import { runnerDir } from './chunk-RHAGBUL5.js';
6
7
  import { dirname } from 'path';
7
8
  import { spawnSync } from 'child_process';
8
9
 
@@ -28,6 +29,7 @@ ${helperService === void 0 ? "" : `Wants=${helperService}
28
29
  User=${unit.user}
29
30
  ExecStart=${unit.execStart}
30
31
  ${unit.helper === void 0 ? "" : `Environment=OUTERLAYER_HELPER_SOCKET=${unit.helper.socket}
32
+ `}${unit.fdStore === void 0 ? "" : `Environment=${FD_STORE_ENV}=${unit.fdStore}
31
33
  `}EnvironmentFile=-${escapeUnitPath(`${unit.configDir}/runner.env`)}
32
34
  Restart=on-failure
33
35
  RestartForceExitStatus=75
@@ -37,7 +39,10 @@ KillMode=mixed
37
39
  TimeoutStopSec=${unit.timeLimitMinutes + STOP_MARGIN_MINUTES}min
38
40
  OOMPolicy=continue
39
41
  Delegate=yes
40
-
42
+ ${unit.fdStore === void 0 ? "" : `NotifyAccess=all
43
+ FileDescriptorStoreMax=${unit.fdStore}
44
+ FileDescriptorStorePreserve=yes
45
+ `}
41
46
  [Install]
42
47
  WantedBy=multi-user.target
43
48
  `;
@@ -147,7 +152,9 @@ function installService(request, deps) {
147
152
  execStart: request.execStart,
148
153
  timeLimitMinutes: request.timeLimitMinutes,
149
154
  docker: kind === "container" || kind === "vm" || builtinKind(request.hooks.cleanup) === "container" || builtinKind(request.hooks.cleanup) === "vm",
150
- ...request.helperSocket !== void 0 && request.helperUnit !== void 0 ? { helper: { unit: request.helperUnit, socket: request.helperSocket } } : {}
155
+ ...request.helperSocket !== void 0 && request.helperUnit !== void 0 ? { helper: { unit: request.helperUnit, socket: request.helperSocket } } : {},
156
+ // A microVM build under the helper keeps its sockets in the descriptor store, so the runner can restart and the build goes on.
157
+ ...kind === "vm" && request.helperSocket !== void 0 && request.helperUnit !== void 0 ? { fdStore: Math.max(1, request.concurrency) * FD_SLOTS_PER_BUILD } : {}
151
158
  });
152
159
  if (request.print === true) return outcome(true, "printed", [], unit);
153
160
  if (own) return outcome(false, "refused", [OWN_HOOKS]);
@@ -13,13 +13,20 @@ function templateClassLine(version) {
13
13
  return `<!-- yours to edit. Copied once from the default template by outerlayer init ${version}; never overwritten. -->`;
14
14
  }
15
15
  function maintainedClassLine(version, base) {
16
+ if (base === MACHINE_SKILL_PATH) return `<!-- maintained by OuterLayer ${version}. Edits are overwritten by the next outerlayer command. -->`;
16
17
  const command = base === AGENTS_SKILLS_BASE ? "outerlayer init --update" : "outerlayer context emit";
17
18
  return `<!-- maintained by OuterLayer ${version}. Edits are overwritten on the next ${command}. -->`;
18
19
  }
19
20
  var OUTERLAYER_SKILLS_BASE = ".outerlayer/skills";
20
21
  var AGENTS_SKILLS_BASE = ".agents/skills";
22
+ var MACHINE_SKILL_PATH = "~/.agents/skills";
23
+ var MAINTAINED_SKILL_PATH_IN_PACK = new RegExp(`${OUTERLAYER_SKILLS_BASE.replace(".", "\\.")}/(outerlayer-[a-z]+)/`, "g");
21
24
  function rewriteSkillPaths(content, base) {
22
- return base === OUTERLAYER_SKILLS_BASE ? content : content.split(`${OUTERLAYER_SKILLS_BASE}/`).join(`${base}/`);
25
+ if (base === OUTERLAYER_SKILLS_BASE) return content;
26
+ if (base === MACHINE_SKILL_PATH) {
27
+ return content.replace(MAINTAINED_SKILL_PATH_IN_PACK, `${MACHINE_SKILL_PATH}/$1/`).split(`${OUTERLAYER_SKILLS_BASE}/`).join(`${AGENTS_SKILLS_BASE}/`);
28
+ }
29
+ return content.split(`${OUTERLAYER_SKILLS_BASE}/`).join(`${base}/`);
23
30
  }
24
31
  function restoreSkillPaths(content, base) {
25
32
  return base === OUTERLAYER_SKILLS_BASE ? content : content.split(`${base}/`).join(`${OUTERLAYER_SKILLS_BASE}/`);
@@ -74,6 +81,9 @@ function loadTemplateFiles(packRoot = resolvePackRoot(), version = resolvePackag
74
81
  function loadMaintainedFiles(packRoot = resolvePackRoot(), version = resolvePackageVersion(), base = OUTERLAYER_SKILLS_BASE) {
75
82
  return loadClass(packRoot, "maintained", MAINTAINED_SKILLS, version, base);
76
83
  }
84
+ function loadMachineSkillFiles(packRoot = resolvePackRoot(), version = resolvePackageVersion()) {
85
+ return loadClass(packRoot, "maintained", MAINTAINED_SKILLS, version, MACHINE_SKILL_PATH).map((file) => ({ ...file, path: file.path.slice(skillDir(file.skill, MACHINE_SKILL_PATH).length + 1) }));
86
+ }
77
87
  function writeMaintainedFiles(repoRoot, files) {
78
88
  const created = [];
79
89
  const rewritten = [];
@@ -92,19 +102,20 @@ function maintainedFilesForExistingSkills(repoRoot, files, base = OUTERLAYER_SKI
92
102
  (file) => existsSync(join(repoRoot, skillDir(file.skill, base))) || formerNameExists(repoRoot, file.skill, base) || requiredByBuild(repoRoot, file.skill, base)
93
103
  );
94
104
  }
105
+ var RELATIVE_CORE = "../outerlayer-build/SKILL.md";
95
106
  function namesCore(text) {
96
107
  return text.includes("outerlayer-build");
97
108
  }
98
109
  function requiredByBuild(repoRoot, skill, base) {
99
110
  if (skill !== "outerlayer-build") return false;
100
- const named = (file) => {
111
+ const named = (file, pattern = "outerlayer-build") => {
101
112
  try {
102
- return namesCore(readFileSync(file, "utf8"));
113
+ return readFileSync(file, "utf8").includes(pattern);
103
114
  } catch {
104
115
  return false;
105
116
  }
106
117
  };
107
- if (named(join(repoRoot, skillDir("build", base), "SKILL.md"))) return true;
118
+ if (named(join(repoRoot, skillDir("build", base), "SKILL.md"), RELATIVE_CORE)) return true;
108
119
  const dir = join(repoRoot, ".outerlayer", "validators");
109
120
  try {
110
121
  return readdirSync(dir).some((name) => name.endsWith(".yaml") && named(join(dir, name)));
@@ -119,6 +130,10 @@ var FORMER_MAINTAINED_NAMES = {
119
130
  outerlayer: "outerlayer-cli"
120
131
  };
121
132
  var MAINTAINED_LINE = /^<!-- maintained by OuterLayer \S+?\. /m;
133
+ var MAINTAINED_LINE_VERSION = /^<!-- maintained by OuterLayer (\S+?)\. /m;
134
+ function maintainedLineVersion(text) {
135
+ return MAINTAINED_LINE_VERSION.exec(text)?.[1];
136
+ }
122
137
  function isMaintainedCopy(repoRoot, skill, base = OUTERLAYER_SKILLS_BASE) {
123
138
  try {
124
139
  return MAINTAINED_LINE.test(readFileSync(join(repoRoot, skillDir(skill, base), "SKILL.md"), "utf8"));
@@ -130,4 +145,4 @@ function formerNameExists(repoRoot, skill, base) {
130
145
  return Object.entries(FORMER_MAINTAINED_NAMES).some(([former, current]) => current === skill && isMaintainedCopy(repoRoot, former, base));
131
146
  }
132
147
 
133
- export { AGENTS_SKILLS_BASE, FORMER_MAINTAINED_NAMES, MAINTAINED_SKILLS, OUTERLAYER_SKILLS_BASE, TEMPLATE_SKILLS, isMaintainedCopy, loadMaintainedFiles, loadTemplateFiles, maintainedFilesForExistingSkills, namesCore, resolvePackRoot, restoreSkillPaths, rewriteSkillPaths, skillDir, writeMaintainedFiles };
148
+ export { AGENTS_SKILLS_BASE, FORMER_MAINTAINED_NAMES, MACHINE_SKILL_PATH, MAINTAINED_SKILLS, OUTERLAYER_SKILLS_BASE, TEMPLATE_SKILLS, isMaintainedCopy, loadMachineSkillFiles, loadMaintainedFiles, loadTemplateFiles, maintainedFilesForExistingSkills, maintainedLineVersion, namesCore, resolvePackRoot, restoreSkillPaths, rewriteSkillPaths, skillDir, writeMaintainedFiles };
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { RUNNER_DIR_MODE, RUNNER_FILE_MODE } from './chunk-L4CW6LZQ.js';
3
+ import { RUNNER_DIR_MODE, RUNNER_FILE_MODE } from './chunk-RHAGBUL5.js';
4
4
  import { readFileSync, mkdirSync, writeFileSync, renameSync } from 'fs';
5
5
  import { join } from 'path';
6
6
 
@@ -264,10 +264,10 @@ function guestAssetsPinned(arch) {
264
264
  var JAILER_BINARY_SHA256 = {
265
265
  x86_64: "65ef226e96f0ceda55ba643f445801ef2cc0ea667ef67cad8ac4f406c9c8434f"
266
266
  };
267
- var HOST_HELPER_ASSETS_VERSION = "5";
267
+ var HOST_HELPER_ASSETS_VERSION = "8";
268
268
  var HOST_HELPER_BASE_URL = `https://github.com/outerlayerai/guest-assets/releases/download/guest-${HOST_HELPER_ASSETS_VERSION}`;
269
269
  var HOST_HELPER_SHA256 = {
270
- x86_64: "f2ec1c6a7ff29353045fad617ac1a6bf0155d6f3eb6a6259272a15342feaf957"
270
+ x86_64: "7c3a80da5e68adf3eb1eb407df0c770ccef589eb2da2f11735a9f9c05dc0d650"
271
271
  };
272
272
  function hostHelperPinned(arch = "x86_64", hashes = HOST_HELPER_SHA256) {
273
273
  return hashes[arch] !== "0".repeat(64);
@@ -0,0 +1,181 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire } from 'node:module';
3
+ import { MAINTAINED_SKILLS, loadMachineSkillFiles, resolvePackRoot, maintainedLineVersion } from './chunk-7OUOLGUV.js';
4
+ import { homeFromEnv } from './chunk-VNVZDWO3.js';
5
+ import { resolvePackageVersion } from './chunk-RA3O54FC.js';
6
+ import { randomBytes } from 'crypto';
7
+ import { existsSync, symlinkSync, lstatSync, readFileSync, mkdirSync, realpathSync, rmSync, renameSync, writeFileSync, cpSync } from 'fs';
8
+ import { join, resolve, dirname, relative } from 'path';
9
+
10
+ createRequire(import.meta.url);
11
+ var machineSkillsBase = (home) => join(home, ".agents", "skills");
12
+ var claudeSkillsBase = (home) => join(home, ".claude", "skills");
13
+ var errorMessage = (err) => err instanceof Error ? err.message : String(err);
14
+ var defaultLink = (target, path) => {
15
+ if (process.platform === "win32") symlinkSync(resolve(dirname(path), target), path, "junction");
16
+ else symlinkSync(target, path, "dir");
17
+ };
18
+ function installedVersion(folder) {
19
+ try {
20
+ return maintainedLineVersion(readFileSync(join(folder, "SKILL.md"), "utf8"));
21
+ } catch {
22
+ return void 0;
23
+ }
24
+ }
25
+ function entryExists(path) {
26
+ try {
27
+ lstatSync(path);
28
+ return true;
29
+ } catch {
30
+ return false;
31
+ }
32
+ }
33
+ function folderExists(path) {
34
+ try {
35
+ return lstatSync(path).isDirectory();
36
+ } catch {
37
+ return false;
38
+ }
39
+ }
40
+ function tempName(base, label) {
41
+ return join(base, `.${label}-${process.pid}-${randomBytes(4).toString("hex")}`);
42
+ }
43
+ var REPLACE_ATTEMPTS = 3;
44
+ function replaceWith(final, build) {
45
+ const base = dirname(final);
46
+ mkdirSync(base, { recursive: true });
47
+ const temporary = tempName(base, "tmp");
48
+ try {
49
+ build(temporary);
50
+ for (let attempt = 0; ; attempt += 1) {
51
+ try {
52
+ renameSync(temporary, final);
53
+ return;
54
+ } catch (err) {
55
+ if (attempt >= REPLACE_ATTEMPTS - 1) throw err;
56
+ const old = tempName(base, "old");
57
+ try {
58
+ renameSync(final, old);
59
+ rmSync(old, { recursive: true, force: true });
60
+ } catch {
61
+ }
62
+ }
63
+ }
64
+ } finally {
65
+ rmSync(temporary, { recursive: true, force: true });
66
+ }
67
+ }
68
+ function writeSkill(final, files) {
69
+ replaceWith(final, (temporary) => {
70
+ for (const file of files) {
71
+ const abs = join(temporary, file.path);
72
+ mkdirSync(dirname(abs), { recursive: true });
73
+ writeFileSync(abs, file.content);
74
+ }
75
+ });
76
+ }
77
+ function sameFolder(a, b) {
78
+ try {
79
+ return realpathSync(a) === realpathSync(b);
80
+ } catch {
81
+ return false;
82
+ }
83
+ }
84
+ function linksTo(entry, target) {
85
+ try {
86
+ return lstatSync(entry).isSymbolicLink() && sameFolder(entry, target);
87
+ } catch {
88
+ return false;
89
+ }
90
+ }
91
+ function reachFromClaude(home, name, version, link, mode) {
92
+ const claude = claudeSkillsBase(home);
93
+ const folder = join(machineSkillsBase(home), name);
94
+ if (sameFolder(claude, machineSkillsBase(home))) return;
95
+ const entry = join(claude, name);
96
+ if (mode === "refresh" && !entryExists(entry)) return;
97
+ if (linksTo(entry, folder)) return;
98
+ if (folderExists(entry) && installedVersion(entry) === version) return;
99
+ mkdirSync(claude, { recursive: true });
100
+ try {
101
+ const temporary = tempName(claude, "tmp");
102
+ try {
103
+ link(relative(realpathSync(claude), realpathSync(folder)), temporary);
104
+ rmSync(entry, { recursive: true, force: true });
105
+ renameSync(temporary, entry);
106
+ } finally {
107
+ rmSync(temporary, { recursive: true, force: true });
108
+ }
109
+ } catch {
110
+ replaceWith(entry, (temporary) => cpSync(folder, temporary, { recursive: true }));
111
+ }
112
+ }
113
+ function installMachineSkills(opts) {
114
+ const result = { written: [], failures: [] };
115
+ const version = opts.version ?? resolvePackageVersion();
116
+ const base = machineSkillsBase(opts.home);
117
+ const link = opts.link ?? defaultLink;
118
+ let files;
119
+ const filesOf = (name) => {
120
+ files ??= loadMachineSkillFiles(opts.packRoot ?? resolvePackRoot(), version);
121
+ return files.filter((file) => file.skill === name);
122
+ };
123
+ for (const name of MAINTAINED_SKILLS) {
124
+ const folder = join(base, name);
125
+ try {
126
+ if (opts.mode === "refresh" && !folderExists(folder)) continue;
127
+ if (installedVersion(folder) !== version) {
128
+ writeSkill(folder, filesOf(name));
129
+ result.written.push(name);
130
+ }
131
+ } catch (err) {
132
+ result.failures.push(`${folder}: ${errorMessage(err)}`);
133
+ continue;
134
+ }
135
+ try {
136
+ reachFromClaude(opts.home, name, version, link, opts.mode);
137
+ } catch (err) {
138
+ result.failures.push(`${join(claudeSkillsBase(opts.home), name)}: ${errorMessage(err)}`);
139
+ }
140
+ }
141
+ return result;
142
+ }
143
+ function machineSkillsState(home, version = resolvePackageVersion()) {
144
+ return MAINTAINED_SKILLS.map((name) => {
145
+ const folder = join(machineSkillsBase(home), name);
146
+ if (!existsSync(join(folder, "SKILL.md"))) return { name, state: "missing" };
147
+ return { name, state: installedVersion(folder) === version ? "current" : "stale" };
148
+ });
149
+ }
150
+ function staleClaudeSkills(home, version = resolvePackageVersion()) {
151
+ const claude = claudeSkillsBase(home);
152
+ if (sameFolder(claude, machineSkillsBase(home))) return [];
153
+ return MAINTAINED_SKILLS.filter((name) => {
154
+ const entry = join(claude, name);
155
+ if (!entryExists(entry)) return false;
156
+ if (linksTo(entry, join(machineSkillsBase(home), name))) return false;
157
+ return installedVersion(entry) !== version;
158
+ });
159
+ }
160
+ function setupMachineSkills(home = homeFromEnv()) {
161
+ try {
162
+ return installMachineSkills({ home, mode: "setup" });
163
+ } catch (err) {
164
+ return { written: [], failures: [errorMessage(err)] };
165
+ }
166
+ }
167
+ function refreshMachineSkills(home = homeFromEnv()) {
168
+ try {
169
+ installMachineSkills({ home, mode: "refresh" });
170
+ } catch {
171
+ }
172
+ }
173
+ function machineRefreshSkipped(commandNames, hidden, argv) {
174
+ const top = commandNames.at(-1);
175
+ if (top === "daemon" || top === "watch" || commandNames[0] === "daemon" || commandNames[0] === "watch") return true;
176
+ if (hidden) return true;
177
+ if (argv.includes("--log-failures")) return true;
178
+ return top === "sync" && argv.includes("--quiet");
179
+ }
180
+
181
+ export { installMachineSkills, machineRefreshSkipped, machineSkillsState, refreshMachineSkills, setupMachineSkills, staleClaudeSkills };
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { removeRetiredSkills } from './chunk-MQ743JX3.js';
4
- import { defaultFetch, resolveGatewayCredentials } from './chunk-QRZLUUNN.js';
3
+ import { removeRetiredSkills } from './chunk-MHX7YX7Y.js';
4
+ import { defaultFetch, resolveGatewayCredentials } from './chunk-BWH36FOC.js';
5
5
  import { appendContextProvenance } from './chunk-ZJSNLVCE.js';
6
- import { loadMaintainedFiles, writeMaintainedFiles } from './chunk-HBISTTG3.js';
6
+ import { loadMaintainedFiles, writeMaintainedFiles } from './chunk-7OUOLGUV.js';
7
7
  import { cliInvocation } from './chunk-CRB3POP4.js';
8
8
  import { writeDegraded, writeSourceCache, SOURCE_CACHE_TTL_RETRY_MS, writeContextManifest, SOURCE_CACHE_TTL_SUCCESS_MS, readSourceCache, isSourceCacheFresh, clearDegraded } from './chunk-YQR6E6OV.js';
9
9
  import { normalizeRepoName, parseOuterlayerConfig, classifyTree, emitTree } from './chunk-RKOTJQVG.js';
10
10
  import { homeFromEnv } from './chunk-VNVZDWO3.js';
11
- import { withTokenHeader } from './chunk-2K3TCQHW.js';
11
+ import { withTokenHeader } from './chunk-2I3LIRZP.js';
12
12
  import { execFileSync } from 'child_process';
13
13
  import { existsSync, mkdirSync, writeFileSync, chmodSync, lstatSync, readFileSync, copyFileSync } from 'fs';
14
14
  import { isAbsolute, join, dirname } from 'path';
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
3
  import { readRepoConnection, findGitDirs } from './chunk-BJ3KTMDH.js';
4
- import { readCloudConfig, cloudConfigPath } from './chunk-EABW6AJQ.js';
4
+ import { readCloudConfigStrict, readCloudConfig, cloudConfigPath } from './chunk-PJDQPF5N.js';
5
5
  import { cliInvocation } from './chunk-CRB3POP4.js';
6
6
  import { homeFromEnv } from './chunk-VNVZDWO3.js';
7
7
  import { resolvePackageVersion } from './chunk-RA3O54FC.js';
8
- import { signRunnerRequest, signerFor } from './chunk-F6DIHHBS.js';
8
+ import { signRunnerRequest, signerFor } from './chunk-Y4OKEFAX.js';
9
9
 
10
10
  createRequire(import.meta.url);
11
11
 
@@ -27,7 +27,12 @@ function unauthorizedMessage(credential) {
27
27
  }
28
28
  function resolveGatewayCredentials(sources = {}) {
29
29
  const env = sources.env ?? process.env;
30
- const config = readCloudConfig(sources.home ?? homeFromEnv(env));
30
+ let config;
31
+ try {
32
+ config = readCloudConfigStrict(sources.home ?? homeFromEnv(env));
33
+ } catch (err) {
34
+ return { ok: false, message: err.message, kind: "key" };
35
+ }
31
36
  const url = sources.url ?? env.OUTERLAYER_URL ?? config.url;
32
37
  const key = sources.apiKey ?? (env.OUTERLAYER_API_KEY || void 0) ?? config.apiKey;
33
38
  const kind = key ? "key" : "login";
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
3
  import { isSameProcess } from './chunk-JBJTC3UU.js';
4
- import { RUNNER_DIR_MODE, RUNNER_FILE_MODE } from './chunk-L4CW6LZQ.js';
5
- import { existsSync, readFileSync, rmSync, mkdirSync, writeFileSync } from 'fs';
4
+ import { RUNNER_DIR_MODE, RUNNER_FILE_MODE } from './chunk-RHAGBUL5.js';
5
+ import { existsSync, readFileSync, mkdirSync, writeFileSync, rmSync } from 'fs';
6
6
  import { dirname } from 'path';
7
7
 
8
8
  createRequire(import.meta.url);
@@ -11,7 +11,7 @@ function readPidFile(path) {
11
11
  try {
12
12
  const parsed = JSON.parse(readFileSync(path, "utf8"));
13
13
  if (typeof parsed.pid !== "number" || typeof parsed.start !== "string") return null;
14
- return { pid: parsed.pid, start: parsed.start };
14
+ return { pid: parsed.pid, start: parsed.start, ...parsed.leaves === true ? { leaves: true } : {} };
15
15
  } catch {
16
16
  return null;
17
17
  }
@@ -39,4 +39,4 @@ function claimPidFile(path, self, isSameProcessFn = isSameProcess) {
39
39
  writePidFile(path, self);
40
40
  }
41
41
 
42
- export { RunnerAlreadyRunningError, claimPidFile, readPidFile, releasePidFile };
42
+ export { RunnerAlreadyRunningError, claimPidFile, readPidFile, releasePidFile, writePidFile };
@@ -554,6 +554,24 @@ function writeSessionStartContext(event, home, cwd, write, systemMessage, extraP
554
554
  } catch {
555
555
  }
556
556
  }
557
+ var MACHINE_CORE = "~/.agents/skills/outerlayer-build/SKILL.md";
558
+ var BUILD_SKILL_FILES = [".agents/skills/build/SKILL.md", ".outerlayer/skills/build/SKILL.md", ".claude/skills/build/SKILL.md"];
559
+ function machineSkillsContext(home, cwd) {
560
+ for (let dir = cwd; ; dir = join(dir, "..")) {
561
+ for (const file of BUILD_SKILL_FILES) {
562
+ let text;
563
+ try {
564
+ text = readFileSync(join(dir, file), "utf8");
565
+ } catch {
566
+ continue;
567
+ }
568
+ if (!text.includes(MACHINE_CORE)) return null;
569
+ if (existsSync(join(home, ".agents", "skills", "outerlayer-build", "SKILL.md"))) return null;
570
+ return `This repository's build skill reads ${MACHINE_CORE}, and that file does not exist. Tell the person that the maintained skills are not installed on this machine, and ask them to run \`${cliInvocation()} init --local\`.`;
571
+ }
572
+ if (join(dir, "..") === dir) return null;
573
+ }
574
+ }
557
575
  var HEAL_RETRY_INTERVAL_MS = 6 * 60 * 60 * 1e3;
558
576
  function healFailureMarkerPath(home, repoRoot) {
559
577
  const key = createHash("sha256").update(repoRoot).digest("hex").slice(0, 16);
@@ -664,7 +682,7 @@ async function missingControlPlane(cwd, sessionId, home, env) {
664
682
  cleanupEarlierCopies(dirs);
665
683
  }
666
684
  if (!contextPossiblyGoverned(cwd, home)) return void 0;
667
- const { governanceOf } = await import('./control-plane-launch-654RV5PO.js');
685
+ const { governanceOf } = await import('./control-plane-launch-DBQA3KLJ.js');
668
686
  if (await governanceOf({ cwd, env, home }) !== "governed") return void 0;
669
687
  recordMissingContext(dirs, sessionId, home);
670
688
  const launcher = `${cliInvocation()} claude`;
@@ -735,6 +753,7 @@ async function runHookFast(event, home = homeFromEnv(), read = readStdin, env =
735
753
  let workLaunchMessage;
736
754
  let hookErrorsMessage;
737
755
  let renewalHookMessage;
756
+ let machineSkillsMessage;
738
757
  if (resolvedEvent === "SessionStart") {
739
758
  const hookErrorsBytes = fileSizeBytes(join(dir, "hook-errors.log"));
740
759
  const hookErrorsSeen = hookErrorsSeenBytes(home);
@@ -752,6 +771,11 @@ async function runHookFast(event, home = homeFromEnv(), read = readStdin, env =
752
771
  logHookError(home, err);
753
772
  }
754
773
  }
774
+ try {
775
+ machineSkillsMessage = machineSkillsContext(home, sessionCwd) ?? void 0;
776
+ } catch (err) {
777
+ logHookError(home, err);
778
+ }
755
779
  try {
756
780
  deadHooksMessage = deadHooksAutoHealContext(sessionCwd, home) ?? void 0;
757
781
  } catch (err) {
@@ -776,7 +800,7 @@ async function runHookFast(event, home = homeFromEnv(), read = readStdin, env =
776
800
  sessionCwd,
777
801
  (out) => process.stdout.write(out),
778
802
  missingPlane?.person,
779
- [missingPlane?.agent, deadHooksMessage, workLaunchMessage, hookErrorsMessage, renewalHookMessage].filter(
803
+ [missingPlane?.agent, machineSkillsMessage, deadHooksMessage, workLaunchMessage, hookErrorsMessage, renewalHookMessage].filter(
780
804
  (s) => s !== void 0
781
805
  )
782
806
  );
@@ -810,4 +834,4 @@ function recordLinkExitFailure(argv, home = homeFromEnv(), target = process) {
810
834
  });
811
835
  }
812
836
 
813
- export { AUTO_SYNC_DEBOUNCE_MS, DUPLICATE_RUN_WINDOW_MS, SYNC_STALE_AFTER_MS, WORK_LEASE_RENEW_DEBOUNCE_MS, WORK_LINK_RETRIES, assessSyncHealth, checkInstalledCliStaleness, contextPossiblyGoverned, formatAgo, handleWorkLaunch, handleWorkSessionEnd, hookFiredMarkerPath, installedCliDistDir, isDuplicateRun, logHookError, markWorkLeaseRenewed, maybeAutoSync, maybeRenewWorkLease, readSyncStatus, recordLinkExitFailure, refreshCommand, runHookFast, sanitizeForContext, spoolDir, workspaceRootOf, writeSyncStatus };
837
+ export { AUTO_SYNC_DEBOUNCE_MS, DUPLICATE_RUN_WINDOW_MS, SYNC_STALE_AFTER_MS, WORK_LEASE_RENEW_DEBOUNCE_MS, WORK_LINK_RETRIES, assessSyncHealth, checkInstalledCliStaleness, contextPossiblyGoverned, formatAgo, handleWorkLaunch, handleWorkSessionEnd, hookFiredMarkerPath, installedCliDistDir, isDuplicateRun, logHookError, machineSkillsContext, markWorkLeaseRenewed, maybeAutoSync, maybeRenewWorkLease, readSyncStatus, recordLinkExitFailure, refreshCommand, runHookFast, sanitizeForContext, spoolDir, workspaceRootOf, writeSyncStatus };
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { autoConnect, detectActiveSession } from './chunk-HXFRJKMU.js';
4
- import { defaultFetch, unauthorizedMessage, resolveGatewayCredentials } from './chunk-QRZLUUNN.js';
3
+ import { autoConnect, detectActiveSession } from './chunk-2F762IXY.js';
4
+ import { defaultFetch, unauthorizedMessage, resolveGatewayCredentials } from './chunk-BWH36FOC.js';
5
5
  import { resolveRepoIdentity } from './chunk-QE3UQAHK.js';
6
6
  import { C } from './chunk-ANPNT6PM.js';
7
7
  import { parseWorkItemEnv } from './chunk-T2Q7ISPE.js';
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
3
  import { MAX_ALLOW_HOSTS, allowHostProblem } from './chunk-UXYLWVTQ.js';
4
- import { parseSize } from './chunk-7RQ73DLO.js';
4
+ import { parseSize } from './chunk-YJLHUKYS.js';
5
5
  import { homeFromEnv } from './chunk-VNVZDWO3.js';
6
- import { isRefusedInConfig, resolveDestinations, isReservedVariable } from './chunk-2K3TCQHW.js';
6
+ import { isRefusedInConfig, resolveDestinations, isReservedVariable } from './chunk-2I3LIRZP.js';
7
7
  import { existsSync, statSync, accessSync, constants, readFileSync } from 'fs';
8
8
  import { hostname } from 'os';
9
9
  import { join } from 'path';
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { runEmit } from './chunk-WX2WEERU.js';
4
- import { installStarterPack } from './chunk-VJBFQP3H.js';
5
- import { resolveGitCommonDir, defaultGitRunner } from './chunk-W3NVHOCS.js';
6
- import { addStdioMcpEntryIfAbsent, addDocsMcpEntryIfAbsent, DOCS_MCP_SERVER_NAME } from './chunk-YVZJ6GKF.js';
3
+ import { runEmit } from './chunk-WUL2OP5A.js';
4
+ import { installStarterPack } from './chunk-XZ6Q6ZNR.js';
5
+ import { AGENTS_MD_LAYOUT, declareAgentsMdLayout, linkClaudeSkills, SKILLS_LINK_PATH, describeSkillsLink, isAgentsMdLayout, holdsTodaysLayoutSources, discoverOuterlayerPaths } from './chunk-LOKSLO25.js';
6
+ import { resolveGitCommonDir, defaultGitRunner } from './chunk-BPKO76QR.js';
7
+ import { loadTemplateFiles, loadMaintainedFiles, skillDir, AGENTS_SKILLS_BASE } from './chunk-7OUOLGUV.js';
8
+ import { addStdioMcpEntryIfAbsent, addDocsMcpEntryIfAbsent, DOCS_MCP_SERVER_NAME } from './chunk-KT4CN6OU.js';
7
9
  import { C } from './chunk-ANPNT6PM.js';
8
- import { AGENTS_MD_LAYOUT, declareAgentsMdLayout, linkClaudeSkills, SKILLS_LINK_PATH, describeSkillsLink, isAgentsMdLayout, holdsTodaysLayoutSources, discoverOuterlayerPaths } from './chunk-JKNYTNYD.js';
9
- import { loadTemplateFiles, loadMaintainedFiles, skillDir, AGENTS_SKILLS_BASE } from './chunk-HBISTTG3.js';
10
10
  import { cliInvocation } from './chunk-CRB3POP4.js';
11
11
  import { linkedAgentsPath } from './chunk-VWFOKRYS.js';
12
12
  import { cloneIsGoverned } from './chunk-YQR6E6OV.js';
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
3
  import { C } from './chunk-ANPNT6PM.js';
4
- import { readCloudConfig, removeCloudConfigKeys } from './chunk-EABW6AJQ.js';
4
+ import { readCloudConfigStrict, removeCloudConfigKeys } from './chunk-PJDQPF5N.js';
5
5
  import { homeFromEnv } from './chunk-VNVZDWO3.js';
6
6
 
7
7
  createRequire(import.meta.url);
@@ -27,7 +27,14 @@ async function revokeTokenOnDashboard(fetchImpl, dashboard, token) {
27
27
  }
28
28
  async function runLogoutCommand(deps) {
29
29
  const home = deps.home ?? homeFromEnv();
30
- const config = readCloudConfig(home);
30
+ let config;
31
+ try {
32
+ config = readCloudConfigStrict(home);
33
+ } catch (err) {
34
+ deps.stderr.write(`${C.red}\u2717${C.reset} ${err.message}
35
+ `);
36
+ return 1;
37
+ }
31
38
  const token = config.accountToken;
32
39
  if (!token) {
33
40
  deps.stdout.write("Not logged in.\n");
@@ -1,10 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { POLICY_CONTENT, VALIDATOR_FILES, VALIDATORS_DIR, POLICY_PATH } from './chunk-VJBFQP3H.js';
3
+ import { POLICY_CONTENT, VALIDATOR_FILES, VALIDATORS_DIR, POLICY_PATH } from './chunk-XZ6Q6ZNR.js';
4
+ import { skillsBaseFor, isAgentsMdLayout } from './chunk-LOKSLO25.js';
4
5
  import { findGitDirs } from './chunk-BJ3KTMDH.js';
5
- import { mcpTargetPath, INIT_STDIO_ENTRY, INIT_DOCS_ENTRY, DOCS_MCP_SERVER_NAME } from './chunk-YVZJ6GKF.js';
6
- import { skillsBaseFor, isAgentsMdLayout } from './chunk-JKNYTNYD.js';
7
- import { resolvePackRoot, OUTERLAYER_SKILLS_BASE, skillDir, namesCore, loadTemplateFiles, rewriteSkillPaths, restoreSkillPaths, TEMPLATE_SKILLS } from './chunk-HBISTTG3.js';
6
+ import { machineSkillsState, staleClaudeSkills } from './chunk-BM7EC3OZ.js';
7
+ import { resolvePackRoot, OUTERLAYER_SKILLS_BASE, skillDir, namesCore, MACHINE_SKILL_PATH, AGENTS_SKILLS_BASE, MAINTAINED_SKILLS, isMaintainedCopy, loadTemplateFiles, rewriteSkillPaths, restoreSkillPaths, TEMPLATE_SKILLS } from './chunk-7OUOLGUV.js';
8
+ import { mcpTargetPath, INIT_STDIO_ENTRY, INIT_DOCS_ENTRY, DOCS_MCP_SERVER_NAME } from './chunk-KT4CN6OU.js';
8
9
  import { cliInvocation } from './chunk-CRB3POP4.js';
9
10
  import { hasSymlinkComponent } from './chunk-VWFOKRYS.js';
10
11
  import { cloneIsGoverned } from './chunk-YQR6E6OV.js';
@@ -190,6 +191,7 @@ function checkStarterFiles(cwd, opts = {}) {
190
191
  return { checks: [{ name: NAME, status: "warn", detail: parts.join("; "), fix }], mcpOutdated };
191
192
  }
192
193
  var BUILD_PHASES = ["Intake", "Criteria", "Implement", "Review", "Pull request", "Evidence"];
194
+ var MACHINE_CORE = `${MACHINE_SKILL_PATH}/outerlayer-build/SKILL.md`;
193
195
  var CHANGES_HEADING = "## Changes for this repository";
194
196
  var NAME2 = "Build skill";
195
197
  function changeHeadings(text) {
@@ -226,10 +228,13 @@ var read = (abs) => {
226
228
  return void 0;
227
229
  }
228
230
  };
231
+ function buildsOf(repoRoot, folders) {
232
+ const source = `${folders[0]}/build/SKILL.md`;
233
+ return (existsSync(join(repoRoot, source)) ? [source] : folders.slice(1).map((f) => `${f}/build/SKILL.md`)).map((path) => ({ path, text: read(join(repoRoot, path)) })).filter((b) => b.text !== void 0);
234
+ }
229
235
  function checkBuildSkill(repoRoot) {
230
236
  const folders = [".outerlayer/skills", ...skillsFolders()];
231
- const source = `${folders[0]}/build/SKILL.md`;
232
- const builds = (existsSync(join(repoRoot, source)) ? [source] : folders.slice(1).map((f) => `${f}/build/SKILL.md`)).map((path) => ({ path, text: read(join(repoRoot, path)) })).filter((b) => b.text !== void 0);
237
+ const builds = buildsOf(repoRoot, folders);
233
238
  const checks = [];
234
239
  const detached = builds.filter((b) => !namesCore(b.text));
235
240
  if (detached.length > 0) {
@@ -255,7 +260,8 @@ ${shortBuild()}`
255
260
  const agentsMd = isAgentsMdLayout(repoRoot);
256
261
  const seen = /* @__PURE__ */ new Set();
257
262
  const lacking = folders.filter((folder) => {
258
- if (!namesCore(read(join(repoRoot, folder, "build", "SKILL.md")) ?? "") || existsSync(join(repoRoot, folder, "outerlayer-build", "SKILL.md"))) return false;
263
+ const text = read(join(repoRoot, folder, "build", "SKILL.md")) ?? "";
264
+ if (!namesCore(text) || text.includes(MACHINE_CORE) || existsSync(join(repoRoot, folder, "outerlayer-build", "SKILL.md"))) return false;
259
265
  let key = folder;
260
266
  try {
261
267
  key = realpathSync(join(repoRoot, folder));
@@ -275,5 +281,47 @@ ${shortBuild()}`
275
281
  }
276
282
  return checks;
277
283
  }
284
+ function committedMaintainedFolders(repoRoot) {
285
+ const found = [];
286
+ for (const base of [AGENTS_SKILLS_BASE, ".claude/skills"]) {
287
+ for (const name of MAINTAINED_SKILLS) {
288
+ const folder = skillDir(name, base);
289
+ if (!hasSymlinkComponent(repoRoot, folder) && isMaintainedCopy(repoRoot, name, base)) found.push(folder);
290
+ }
291
+ }
292
+ return found;
293
+ }
294
+ function checkCommittedMaintainedSkills(repoRoot) {
295
+ if (!isAgentsMdLayout(repoRoot)) return [];
296
+ const folders = committedMaintainedFolders(repoRoot);
297
+ if (folders.length === 0) return [];
298
+ return [
299
+ {
300
+ name: "Committed maintained skills",
301
+ status: "warn",
302
+ detail: `${folders.join(", ")} ${folders.length === 1 ? "is a maintained skill" : "are maintained skills"} that every machine keeps in ${MACHINE_SKILL_PATH}/ now`,
303
+ fix: `Run \`${cliInvocation()} init --update\` to remove ${folders.length === 1 ? "it" : "them"}, then commit. Before you commit, every machine and runner host must run this CLI version or later, and each machine a person works on must run \`${cliInvocation()} init --local\`.`
304
+ }
305
+ ];
306
+ }
307
+ function checkMachineSkills(opts) {
308
+ const build = buildsOf(opts.repoRoot, [".outerlayer/skills", ...skillsFolders()]).find((b) => b.text.includes(MACHINE_CORE));
309
+ if (build === void 0) return [];
310
+ const problems = machineSkillsState(opts.home, opts.version).filter((s) => s.state !== "current");
311
+ const claudeStale = staleClaudeSkills(opts.home, opts.version);
312
+ if (problems.length === 0 && claudeStale.length === 0) return [];
313
+ const parts = [
314
+ ...problems.map((s) => `${MACHINE_SKILL_PATH}/${s.name} ${s.state === "missing" ? "is missing" : "is from another CLI version"}`),
315
+ ...claudeStale.map((name) => `~/.claude/skills/${name} is not this CLI version's copy`)
316
+ ];
317
+ return [
318
+ {
319
+ name: "Maintained skills on this machine",
320
+ status: "warn",
321
+ detail: `${build.path} reads ${MACHINE_CORE}, but ${parts.join(", ")}`,
322
+ fix: `Run \`${cliInvocation()} init --local\` on this machine. If it reports a failed write, fix the permissions on the folder it names first.`
323
+ }
324
+ ];
325
+ }
278
326
 
279
- export { canonical, checkBuildSkill, checkStarterFiles, contentHash, contextIsGoverned, inspectStarterFiles, readShippedManifest, skillsFolders };
327
+ export { canonical, checkBuildSkill, checkCommittedMaintainedSkills, checkMachineSkills, checkStarterFiles, committedMaintainedFolders, contentHash, contextIsGoverned, inspectStarterFiles, readShippedManifest, skillsFolders };
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { DEFAULT_UNIT_NAME } from './chunk-MLD2NA7N.js';
4
- import { parseRunnerEnv } from './chunk-6MZSX4M7.js';
5
- import { RUNNER_FILE_MODE } from './chunk-L4CW6LZQ.js';
3
+ import { DEFAULT_UNIT_NAME } from './chunk-7AQ5AM7U.js';
4
+ import { parseRunnerEnv } from './chunk-STSLH5EJ.js';
5
+ import { RUNNER_FILE_MODE } from './chunk-RHAGBUL5.js';
6
6
  import { existsSync, readFileSync, writeFileSync, renameSync, rmSync } from 'fs';
7
7
  import { join, dirname } from 'path';
8
8