@outerlayer/cli 0.22.1 → 0.23.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 (114) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +4 -1
  3. package/dist/{agent-setup-LTSLXPS3.js → agent-setup-SNDCEHG2.js} +14 -12
  4. package/dist/{artifact-link-cmd-OWRI5AJX.js → artifact-link-cmd-LEI6EOZE.js} +2 -2
  5. package/dist/bridge-QFN3KJP6.js +8 -0
  6. package/dist/{build-6WRNZPVR.js → build-WHHFA7KM.js} +2 -2
  7. package/dist/build-info.json +1 -1
  8. package/dist/{builder-G3MLDMTI.js → builder-7FBQAWQZ.js} +3 -3
  9. package/dist/{check-UYKEMQNR.js → check-3CGLWMHM.js} +37 -37
  10. package/dist/{chunk-ZPSLJFGL.js → chunk-2TT7DEMZ.js} +2 -2
  11. package/dist/{chunk-3V5C64Y5.js → chunk-6AOZD3LY.js} +3 -4
  12. package/dist/{chunk-5NJIWKD4.js → chunk-BOG4ENP7.js} +9 -9
  13. package/dist/{chunk-G3IJ3N6F.js → chunk-BUP5N3X6.js} +1 -1
  14. package/dist/{chunk-FRNYCJ4W.js → chunk-C2XZBNHY.js} +1 -1
  15. package/dist/{chunk-BET347JZ.js → chunk-C64D7HR3.js} +6 -7
  16. package/dist/{chunk-AEKSX4EY.js → chunk-CBCKD6DO.js} +1 -1
  17. package/dist/{chunk-56X5TOJY.js → chunk-D64E222W.js} +5 -6
  18. package/dist/{chunk-URAKVDSI.js → chunk-DJYOCD65.js} +9 -10
  19. package/dist/{chunk-IZSVXRDR.js → chunk-DXDF43YG.js} +1 -1
  20. package/dist/{chunk-F7CU5ABH.js → chunk-DYEFPYME.js} +1 -1
  21. package/dist/{chunk-ORNJJ7XN.js → chunk-FX6IHR5C.js} +11 -12
  22. package/dist/{chunk-ENTHEUKT.js → chunk-G3LHWUBK.js} +4 -4
  23. package/dist/{chunk-5QRP3MVS.js → chunk-GNPTU4BM.js} +9 -4
  24. package/dist/{chunk-JRCSET55.js → chunk-GXV73IIS.js} +6 -6
  25. package/dist/{chunk-5OCIHFGE.js → chunk-HBISTTG3.js} +32 -23
  26. package/dist/chunk-JKNYTNYD.js +151 -0
  27. package/dist/{chunk-CUFFDEF3.js → chunk-KGKFEONR.js} +4 -4
  28. package/dist/{chunk-USWVXQIH.js → chunk-MQ743JX3.js} +3 -3
  29. package/dist/{chunk-XR56WEA5.js → chunk-OGMZJWWD.js} +1 -1
  30. package/dist/chunk-QS43O4DR.js +113 -0
  31. package/dist/{chunk-FOCML5FI.js → chunk-QSEPKZXR.js} +15 -14
  32. package/dist/{chunk-7VUK5RFS.js → chunk-QZBXLLTV.js} +36 -1
  33. package/dist/{chunk-WFSUUUAN.js → chunk-RKOTJQVG.js} +1 -1
  34. package/dist/{chunk-7FEY33MY.js → chunk-TFGXOHF6.js} +13 -13
  35. package/dist/{chunk-V7SAQ645.js → chunk-VJBFQP3H.js} +21 -12
  36. package/dist/{chunk-ZNPE7FW5.js → chunk-VPEGE3QZ.js} +1 -1
  37. package/dist/{chunk-W3SWJ2TD.js → chunk-VWFOKRYS.js} +5 -2
  38. package/dist/{chunk-XCRZTXRL.js → chunk-WX2WEERU.js} +63 -43
  39. package/dist/chunk-WXJXHZVB.js +73 -0
  40. package/dist/{chunk-BOMRFYTZ.js → chunk-WY7HFY62.js} +3 -3
  41. package/dist/{chunk-VSUXCMMH.js → chunk-XFGL53GU.js} +51 -33
  42. package/dist/{chunk-6YBLN4TR.js → chunk-XGPC3IOR.js} +4 -5
  43. package/dist/{chunk-QC72I5GQ.js → chunk-XOEV4FVK.js} +3 -3
  44. package/dist/{chunk-EAQSOE62.js → chunk-XSPA5ODY.js} +21 -19
  45. package/dist/{chunk-JZGFDTNC.js → chunk-Z42JY3LQ.js} +20 -3
  46. package/dist/{chunk-O6RJ3QMU.js → chunk-ZKWKQIJU.js} +86 -6
  47. package/dist/{chunk-QOALB6ZD.js → chunk-ZLZ3XVPI.js} +3 -3
  48. package/dist/{claude-launcher-TBWV3YL3.js → claude-launcher-KEESTJHO.js} +5 -5
  49. package/dist/{cli-U253V422.js → cli-44WGGICQ.js} +126 -112
  50. package/dist/{command-IQTPFSXY.js → command-4FAP2D3P.js} +22 -23
  51. package/dist/connect-cmd-6DUTUK63.js +22 -0
  52. package/dist/{context-cleanup-DSA3HGQU.js → context-cleanup-LTH77FC3.js} +3 -3
  53. package/dist/{control-plane-launch-OWSNH6YA.js → control-plane-launch-SEYCOZFH.js} +8 -9
  54. package/dist/{dist-7IH56ELA.js → dist-SOH3O24Y.js} +2 -2
  55. package/dist/{docker-JU422JL7.js → docker-KMK4LOET.js} +3 -3
  56. package/dist/{doctor-FZTS57ZO.js → doctor-4H77CEB7.js} +24 -25
  57. package/dist/{emit-artifact-cmd-YLZ5WLSF.js → emit-artifact-cmd-XCZ3ALLV.js} +15 -15
  58. package/dist/emit-cmd-WQH2NK7H.js +15 -0
  59. package/dist/{emit-criteria-cmd-MF6TVE7C.js → emit-criteria-cmd-JE72JHKJ.js} +10 -10
  60. package/dist/{emit-finding-cmd-S3YMFTZT.js → emit-finding-cmd-ILIDRMYN.js} +10 -10
  61. package/dist/{emit-result-cmd-JHEUFTPX.js → emit-result-cmd-WPKG5YAS.js} +15 -15
  62. package/dist/{emit-step-cmd-TUI2T3DS.js → emit-step-cmd-OVMLQSL6.js} +11 -11
  63. package/dist/{governing-source-XSEIRSBE.js → governing-source-EQBKPME7.js} +16 -17
  64. package/dist/{guest-init-DF7V5D2R.js → guest-init-HWSE7W6L.js} +3 -2
  65. package/dist/{hook-fast-O3UUN6SO.js → hook-fast-27SHD72I.js} +1 -1
  66. package/dist/{hook-wrap-fast-NPLHJXFK.js → hook-wrap-fast-NOOGDNSW.js} +2 -2
  67. package/dist/{import-capture-cmd-Q56DDZVO.js → import-capture-cmd-TCOKNVBM.js} +12 -7
  68. package/dist/{import-ruler-cmd-T6LLO6Q7.js → import-ruler-cmd-VJOHOJQ7.js} +2 -2
  69. package/dist/index.js +6 -6
  70. package/dist/{init-ZZZPYGUH.js → init-HAAHIQFN.js} +23 -24
  71. package/dist/{init-VZE72CR4.js → init-WQ62BXDN.js} +23 -24
  72. package/dist/{init-cmd-W5VV62ZN.js → init-cmd-VPFIDY64.js} +24 -24
  73. package/dist/init-update-UZIJ2FMU.js +529 -0
  74. package/dist/layout-UOJQGEPW.js +10 -0
  75. package/dist/{login-browser-BN5UKPHS.js → login-browser-4OMZFP3U.js} +4 -3
  76. package/dist/{logout-cmd-RZFWTNYD.js → logout-cmd-5V5MMBSY.js} +2 -2
  77. package/dist/{loop-6WENRS5S.js → loop-JPW2QJ64.js} +37 -37
  78. package/dist/{machine-M4MQBV5A.js → machine-PGDRWPI2.js} +22 -23
  79. package/dist/{mcp-install-cmd-GD4QUP7Z.js → mcp-install-cmd-GGWB3JJ2.js} +2 -2
  80. package/dist/{mcp-serve-cmd-SBW7HYKD.js → mcp-serve-cmd-CNRC5AL5.js} +3 -3
  81. package/dist/{runner-identity-FTHZFMGY.js → runner-identity-IIZ3RK7M.js} +3 -3
  82. package/dist/{runner-key-QT7GKGEE.js → runner-key-BPP5XRYR.js} +23 -24
  83. package/dist/{session-sender-BK6TGNVO.js → session-sender-EKKZ5DEU.js} +16 -16
  84. package/dist/{settings-J2652U5N.js → settings-AKYEOCC2.js} +1 -1
  85. package/dist/{spec-cmd-ZNJ3GXWC.js → spec-cmd-JDHGNFVJ.js} +11 -11
  86. package/dist/{starter-pack-5EQYGSJF.js → starter-pack-55EFILC5.js} +7 -4
  87. package/dist/{status-JOO7MGIC.js → status-UCQDEMFX.js} +30 -30
  88. package/dist/{statusline-fast-2OK3DVAA.js → statusline-fast-GVRSBHAF.js} +2 -2
  89. package/dist/{sync-cmd-W2FPY3T5.js → sync-cmd-NSVXOYFJ.js} +15 -15
  90. package/dist/{watch-WLH5ZUZU.js → watch-NQVZWPBJ.js} +15 -15
  91. package/dist/{work-claim-cmd-4PLDTEZR.js → work-claim-cmd-FPJXQAXP.js} +13 -13
  92. package/dist/{work-cmd-KWHAYUYB.js → work-cmd-FMPDXPU6.js} +11 -11
  93. package/dist/{work-comment-cmd-4CUI7ZDE.js → work-comment-cmd-ZVUE2IUN.js} +11 -11
  94. package/dist/{work-logs-cmd-AF253WLM.js → work-logs-cmd-CQH2SYT4.js} +11 -11
  95. package/dist/{work-open-pr-cmd-JETE6HRL.js → work-open-pr-cmd-YY2OGJOI.js} +12 -12
  96. package/dist/{work-pr-cmd-V5G4CPMG.js → work-pr-cmd-EHFTEVJO.js} +11 -11
  97. package/dist/{work-stop-cmd-FIEKUDGE.js → work-stop-cmd-LGWSBSBT.js} +11 -11
  98. package/package.json +1 -1
  99. package/skill-pack/maintained/outerlayer-amend/SKILL.md +83 -82
  100. package/skill-pack/maintained/outerlayer-build/SKILL.md +4 -2
  101. package/skill-pack/maintained/outerlayer-build/references/agent-briefs.md +17 -4
  102. package/skill-pack/maintained/outerlayer-build/references/criteria-judge.md +10 -0
  103. package/skill-pack/maintained/outerlayer-build/references/release.md +7 -4
  104. package/skill-pack/maintained/outerlayer-build/references/review-briefs.md +10 -3
  105. package/skill-pack/maintained/outerlayer-cli/SKILL.md +13 -4
  106. package/skill-pack/maintained/outerlayer-cli/references/merge-base-branch.md +54 -0
  107. package/dist/chunk-NTRCK4NH.js +0 -38
  108. package/dist/chunk-QF7WZUU6.js +0 -56
  109. package/dist/connect-cmd-ZFOK6HEL.js +0 -17
  110. package/dist/emit-cmd-3W5IO5ET.js +0 -14
  111. package/dist/init-update-YFPIQS5G.js +0 -211
  112. package/dist/{chunk-F35VMF5M.js → chunk-GOSFARMS.js} +1 -1
  113. package/dist/{chunk-3AZYLAJC.js → chunk-QILR6TZP.js} +1 -1
  114. package/dist/{chunk-DIB2WLBL.js → chunk-YVZJ6GKF.js} +1 -1
@@ -1,8 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { resolvePackRoot, loadTemplateFiles, loadMaintainedFiles, TEMPLATE_SKILLS, skillDir, writeMaintainedFiles, MAINTAINED_SKILLS } from './chunk-5OCIHFGE.js';
4
3
  import { C } from './chunk-ANPNT6PM.js';
4
+ import { resolvePackRoot, OUTERLAYER_SKILLS_BASE, loadTemplateFiles, loadMaintainedFiles, rewriteSkillPaths, TEMPLATE_SKILLS, skillDir, writeMaintainedFiles, MAINTAINED_SKILLS } from './chunk-HBISTTG3.js';
5
5
  import { cliInvocation } from './chunk-CRB3POP4.js';
6
+ import { linkedAgentsPath } from './chunk-VWFOKRYS.js';
6
7
  import { resolvePackageVersion } from './chunk-RA3O54FC.js';
7
8
  import { readFileSync, existsSync, mkdirSync, writeFileSync } from 'fs';
8
9
  import { join, dirname } from 'path';
@@ -26,16 +27,19 @@ function assertKnownTemplate(name) {
26
27
  function installStarterPack(opts) {
27
28
  const packRoot = opts.packRoot ?? resolvePackRoot();
28
29
  const version = opts.version ?? resolvePackageVersion();
29
- const templateFiles = loadTemplateFiles(packRoot, version);
30
- const maintainedFiles = loadMaintainedFiles(packRoot, version);
30
+ const base = opts.base ?? OUTERLAYER_SKILLS_BASE;
31
+ const linked = base.startsWith(".agents/") ? linkedAgentsPath(opts.repoRoot) : void 0;
32
+ if (linked !== void 0) throw new StarterPackError(`${linked} is a link, and a write there would land outside the repository; replace it with a folder and run this again`);
33
+ const templateFiles = loadTemplateFiles(packRoot, version, base);
34
+ const maintainedFiles = loadMaintainedFiles(packRoot, version, base);
31
35
  const validatorFiles = VALIDATOR_FILES.map(({ name }) => ({
32
36
  path: `${VALIDATORS_DIR}/${name}`,
33
- content: readFileSync(join(packRoot, "validators", name), "utf8")
37
+ content: rewriteSkillPaths(readFileSync(join(packRoot, "validators", name), "utf8"), base)
34
38
  }));
35
39
  const copied = [];
36
40
  const kept = [];
37
41
  for (const skill of TEMPLATE_SKILLS) {
38
- if (existsSync(join(opts.repoRoot, skillDir(skill)))) {
42
+ if (existsSync(join(opts.repoRoot, skillDir(skill, base)))) {
39
43
  kept.push(skill);
40
44
  continue;
41
45
  }
@@ -67,6 +71,7 @@ function installStarterPack(opts) {
67
71
  validatorsWritten.push(file.path);
68
72
  }
69
73
  return {
74
+ base,
70
75
  copied,
71
76
  kept,
72
77
  maintained: [...written.created, ...written.rewritten],
@@ -75,21 +80,23 @@ function installStarterPack(opts) {
75
80
  validatorsKept
76
81
  };
77
82
  }
78
- var skillFile = (skill) => `${skillDir(skill)}/SKILL.md`;
83
+ var skillFile = (skill, base) => `${skillDir(skill, base)}/SKILL.md`;
79
84
  function validatorLabel(path) {
80
85
  return VALIDATOR_FILES.find(({ name }) => path === `${VALIDATORS_DIR}/${name}`)?.label ?? "a check";
81
86
  }
82
87
  function formatStarterPackOutput(result) {
83
88
  const lines = [];
84
- lines.push(`${C.green}\u2713${C.reset} Installed the starter skills in .outerlayer/skills/`, "");
89
+ const { base } = result;
90
+ lines.push(`${C.green}\u2713${C.reset} Installed the starter skills in ${base}/`, "");
85
91
  lines.push("Yours to edit \u2014 copied once, never overwritten:");
86
92
  for (const skill of TEMPLATE_SKILLS) {
87
93
  lines.push(
88
- result.kept.includes(skill) ? ` ${C.dim}kept${C.reset} ${skillDir(skill)}/ ${C.dim}(already exists, left exactly as it is)${C.reset}` : ` ${skillFile(skill)}`
94
+ result.kept.includes(skill) ? ` ${C.dim}kept${C.reset} ${skillDir(skill, base)}/ ${C.dim}(already exists, left exactly as it is)${C.reset}` : ` ${skillFile(skill, base)}`
89
95
  );
90
96
  }
91
- lines.push("", "Rewritten on every emit \u2014 edits are overwritten by the installed CLI:");
92
- for (const skill of MAINTAINED_SKILLS) lines.push(` ${skillFile(skill)}`);
97
+ const rewriter = base === OUTERLAYER_SKILLS_BASE ? "emit" : "`init --update`";
98
+ lines.push("", `Rewritten on every ${rewriter} \u2014 edits are overwritten by the installed CLI:`);
99
+ for (const skill of MAINTAINED_SKILLS) lines.push(` ${skillFile(skill, base)}`);
93
100
  lines.push(
94
101
  "",
95
102
  result.policy === "written" ? `${C.green}\u2713${C.reset} Wrote ${POLICY_PATH} (review required)` : `${C.dim}${POLICY_PATH} already exists \u2014 left as it is${C.reset}`,
@@ -98,8 +105,10 @@ function formatStarterPackOutput(result) {
98
105
  ),
99
106
  ...result.validatorsKept.map((path) => `${C.dim}${path} already exists \u2014 left as it is${C.reset}`),
100
107
  "",
101
- `Next: create .outerlayer/config.json naming your agent tools, for example {"targets": ["claude-code"]},`,
102
- `then run ${C.yellow}${cliInvocation()} context emit${C.reset} to compile the skills into their native files.`
108
+ ...base === OUTERLAYER_SKILLS_BASE ? [
109
+ `Next: create .outerlayer/config.json naming your agent tools, for example {"targets": ["claude-code"]},`,
110
+ `then run ${C.yellow}${cliInvocation()} context emit${C.reset} to compile the skills into their native files.`
111
+ ] : [`Agents read these skills from ${base}/ as they are. Nothing needs compiling.`]
103
112
  );
104
113
  return lines.join("\n") + "\n";
105
114
  }
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
3
  import { rewriteControlPlanePaths, rewriteAgentsFilePaths, SUPPORTED_CONTROL_PLANE_LAYOUT, rewriteHookCommand } from './chunk-HCVLP7XA.js';
4
- import { MAINTAINED_SKILLS } from './chunk-5OCIHFGE.js';
4
+ import { MAINTAINED_SKILLS } from './chunk-HBISTTG3.js';
5
5
  import { existsSync, mkdirSync, copyFileSync, lstatSync, readdirSync, writeFileSync, readFileSync } from 'fs';
6
6
  import { join, dirname } from 'path';
7
7
 
@@ -2,7 +2,7 @@
2
2
  import { createRequire } from 'node:module';
3
3
  import { readContextManifest, removeContextManifest } from './chunk-YQR6E6OV.js';
4
4
  import { removePreCommitGuardHook } from './chunk-TUSYOL2O.js';
5
- import { CONTEXT_PIN_FILENAME } from './chunk-WFSUUUAN.js';
5
+ import { CONTEXT_PIN_FILENAME } from './chunk-RKOTJQVG.js';
6
6
  import { execFileSync } from 'child_process';
7
7
  import { lstatSync, existsSync, unlinkSync, readdirSync, rmdirSync, readFileSync, mkdirSync, writeFileSync } from 'fs';
8
8
  import { join, dirname, isAbsolute } from 'path';
@@ -80,6 +80,9 @@ function hasSymlinkComponent(root, rel) {
80
80
  }
81
81
  return false;
82
82
  }
83
+ function linkedAgentsPath(root) {
84
+ return [".agents", ".agents/skills"].find((rel) => hasSymlinkComponent(root, rel));
85
+ }
83
86
  function trackedPaths(repoRoot) {
84
87
  try {
85
88
  const out = execFileSync("git", ["ls-files", "-z", "--", "AGENTS.md", ".claude", ".outerlayer"], {
@@ -171,4 +174,4 @@ function cleanupEarlierCopies(input) {
171
174
  return result;
172
175
  }
173
176
 
174
- export { cleanupEarlierCopies, hasSymlinkComponent };
177
+ export { cleanupEarlierCopies, hasSymlinkComponent, linkedAgentsPath };
@@ -1,12 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { retiredSkillPaths, removeRetiredSkills } from './chunk-USWVXQIH.js';
4
- import { maintainedFilesForExistingSkills, loadMaintainedFiles, writeMaintainedFiles } from './chunk-5OCIHFGE.js';
3
+ import { retiredSkillPaths, removeRetiredSkills } from './chunk-MQ743JX3.js';
5
4
  import { C } from './chunk-ANPNT6PM.js';
5
+ import { isAgentsMdLayout, discoverOuterlayerPaths, isForeignTree, toRepoRelative } from './chunk-JKNYTNYD.js';
6
+ import { maintainedFilesForExistingSkills, loadMaintainedFiles, writeMaintainedFiles } from './chunk-HBISTTG3.js';
6
7
  import { cliInvocation } from './chunk-CRB3POP4.js';
7
- import { emitTree, parseOuterlayerConfig, classifyTree, generatedHeaderSource, CONTEXT_PIN_FILENAME, normalizePath } from './chunk-WFSUUUAN.js';
8
+ import { emitTree, generatedHeaderSource, parseOuterlayerConfig, classifyTree } from './chunk-RKOTJQVG.js';
8
9
  import { existsSync, readFileSync, mkdirSync, writeFileSync, copyFileSync, unlinkSync, rmdirSync, readdirSync } from 'fs';
9
- import { join, dirname, relative, sep } from 'path';
10
+ import { join, dirname } from 'path';
10
11
 
11
12
  createRequire(import.meta.url);
12
13
  var CONTENT_KINDS = /* @__PURE__ */ new Set(["instructions", "skill", "skill-reference", "command", "mcp"]);
@@ -14,6 +15,13 @@ var SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", ".git"]);
14
15
  var NO_CONFIG_MESSAGE = 'no .outerlayer/config.json with a non-empty targets array \u2014 create one, e.g. {"targets": ["claude-code"]}';
15
16
  var EmitError = class extends Error {
16
17
  };
18
+ var EMIT_NOT_NEEDED_NOTICE = `Claude Code and Codex read AGENTS.md and .agents/skills/ without a generated copy. Run \`${cliInvocation()} init --update\` to move this repository there and stop committing generated files.`;
19
+ var NATIVE_TARGETS = /* @__PURE__ */ new Set(["claude-code", "codex"]);
20
+ function noticeFor(repoRoot, targets) {
21
+ if (targets.length === 0 || !targets.every((t) => NATIVE_TARGETS.has(t))) return void 0;
22
+ return isAgentsMdLayout(repoRoot) ? void 0 : EMIT_NOT_NEEDED_NOTICE;
23
+ }
24
+ var HAND_OWNED_OUTPUT = /(^|\/)(CLAUDE\.md|AGENTS\.md|\.claude\/skills\/|\.agents\/skills\/)/;
17
25
  function resolveTargetsFromConfig(repoRoot) {
18
26
  const configPath = join(repoRoot, ".outerlayer", "config.json");
19
27
  if (!existsSync(configPath)) throw new EmitError(NO_CONFIG_MESSAGE);
@@ -24,36 +32,6 @@ function resolveTargetsFromConfig(repoRoot) {
24
32
  const detail = result.errors.map((e) => `${e.path}: ${e.message}`).join("; ");
25
33
  throw new EmitError(`invalid .outerlayer/config.json \u2014 ${detail}`);
26
34
  }
27
- function toRepoRelative(repoRoot, absPath) {
28
- return normalizePath(relative(repoRoot, absPath).split(sep).join("/"));
29
- }
30
- function discoverOuterlayerPaths(repoRoot) {
31
- const out = [];
32
- walk(repoRoot, repoRoot, false, out);
33
- return out.sort();
34
- }
35
- function isForeignTree(dir) {
36
- return existsSync(join(dir, ".git")) || existsSync(join(dir, CONTEXT_PIN_FILENAME));
37
- }
38
- function walk(dir, repoRoot, insideOuterlayer, out) {
39
- let entries;
40
- try {
41
- entries = readdirSync(dir, { withFileTypes: true });
42
- } catch {
43
- return;
44
- }
45
- for (const entry of entries) {
46
- if (entry.isSymbolicLink()) continue;
47
- const full = join(dir, entry.name);
48
- if (entry.isDirectory()) {
49
- if (!insideOuterlayer && SKIP_DIRS.has(entry.name)) continue;
50
- if (!insideOuterlayer && isForeignTree(full)) continue;
51
- walk(full, repoRoot, insideOuterlayer || entry.name === ".outerlayer", out);
52
- } else if (entry.isFile() && insideOuterlayer) {
53
- out.push(toRepoRelative(repoRoot, full));
54
- }
55
- }
56
- }
57
35
  function buildEmitInput(repoRoot, targets, maintained, excluded = /* @__PURE__ */ new Set()) {
58
36
  const bundled = new Map(maintained.map((f) => [f.path, f.content]));
59
37
  const discovered = [.../* @__PURE__ */ new Set([...discoverOuterlayerPaths(repoRoot).filter((p) => !excluded.has(p)), ...bundled.keys()])].sort();
@@ -143,10 +121,10 @@ function walkAll(dir, repoRoot, out) {
143
121
  }
144
122
  }
145
123
  }
146
- function findOrphans(repoRoot, computedFiles, sourcePaths) {
124
+ function findOrphans(repoRoot, computedFiles, sourcePaths, ignore) {
147
125
  const orphans = [];
148
126
  for (const path of discoverAllFiles(repoRoot)) {
149
- if (computedFiles.has(path)) continue;
127
+ if (computedFiles.has(path) || ignore?.(path) === true) continue;
150
128
  let content;
151
129
  try {
152
130
  content = readFileSync(join(repoRoot, path), "utf8");
@@ -200,17 +178,20 @@ function runEmit(opts = {}) {
200
178
  const cwd = opts.cwd ?? process.cwd();
201
179
  if (!existsSync(cwd)) throw new EmitError(`no such directory: ${cwd}`);
202
180
  const targets = resolveTargetsFromConfig(cwd);
203
- const maintained = maintainedFilesForExistingSkills(cwd, loadMaintainedFiles());
181
+ const agentsMd = isAgentsMdLayout(cwd);
182
+ const ignoreOrphan = agentsMd ? (path) => HAND_OWNED_OUTPUT.test(path) : void 0;
183
+ const maintained = agentsMd ? [] : maintainedFilesForExistingSkills(cwd, loadMaintainedFiles());
184
+ const notice = noticeFor(cwd, targets);
204
185
  const retired = retiredSkillPaths(cwd);
205
186
  const built = buildEmitInput(cwd, targets, maintained, new Set(retired));
206
187
  const emitted = emitTree(built.input);
207
188
  const { result, kept } = withholdKept(cwd, emitted, opts.keep);
208
189
  const hasErrors = result.errors.length > 0;
209
190
  const outputs = new Set(emitted.files.map((f) => f.path));
210
- if (opts.check) return runCheck(cwd, opts, targets, result, hasErrors, outputs, built.sourcePaths, maintained, kept, retired);
191
+ if (opts.check) return runCheck(cwd, opts, targets, result, hasErrors, outputs, built.sourcePaths, maintained, kept, retired, notice, ignoreOrphan);
211
192
  const written = hasErrors ? { files: [], copies: [], maintained: [] } : writeOutputs(cwd, result, maintained);
212
193
  const removed = hasErrors ? [] : removeRetiredSkills(cwd);
213
- const orphaned = hasErrors ? [] : removeOrphans(cwd, findOrphans(cwd, outputs, built.sourcePaths));
194
+ const orphaned = hasErrors ? [] : removeOrphans(cwd, findOrphans(cwd, outputs, built.sourcePaths, ignoreOrphan));
214
195
  const exitCode = hasErrors ? 1 : 0;
215
196
  const output = opts.json ? JSON.stringify({
216
197
  targets,
@@ -232,8 +213,11 @@ function runEmit(opts = {}) {
232
213
  for (const w of result.warnings) process.stderr.write(` ${C.yellow}!${C.reset} ${w.path}: ${w.message}
233
214
  `);
234
215
  }
216
+ if (notice !== void 0 && !opts.json) process.stderr.write(`${C.dim}${notice}${C.reset}
217
+ `);
235
218
  }
236
219
  return {
220
+ ...notice === void 0 ? {} : { notice },
237
221
  targets,
238
222
  files: written.files,
239
223
  copies: written.copies,
@@ -247,7 +231,7 @@ function runEmit(opts = {}) {
247
231
  exitCode
248
232
  };
249
233
  }
250
- function runCheck(cwd, opts, targets, result, hasErrors, outputs, sourcePaths, maintained, kept, retired) {
234
+ function runCheck(cwd, opts, targets, result, hasErrors, outputs, sourcePaths, maintained, kept, retired, notice, ignoreOrphan) {
251
235
  const drift = [];
252
236
  if (!hasErrors) {
253
237
  for (const path of retired) drift.push({ kind: "retired", path });
@@ -264,7 +248,7 @@ function runCheck(cwd, opts, targets, result, hasErrors, outputs, sourcePaths, m
264
248
  if (d) drift.push(d);
265
249
  }
266
250
  const retiredPaths = new Set(retired);
267
- drift.push(...findOrphans(cwd, outputs, sourcePaths).filter((d) => !retiredPaths.has(d.path)));
251
+ drift.push(...findOrphans(cwd, outputs, sourcePaths, ignoreOrphan).filter((d) => !retiredPaths.has(d.path)));
268
252
  drift.sort((a, b) => a.path.localeCompare(b.path) || a.kind.localeCompare(b.kind));
269
253
  }
270
254
  const exitCode = hasErrors || drift.length > 0 ? 1 : 0;
@@ -279,8 +263,44 @@ function runCheck(cwd, opts, targets, result, hasErrors, outputs, sourcePaths, m
279
263
  for (const w of result.warnings) process.stderr.write(` ${C.yellow}!${C.reset} ${w.path}: ${w.message}
280
264
  `);
281
265
  }
266
+ if (notice !== void 0 && !opts.json) process.stderr.write(`${C.dim}${notice}${C.reset}
267
+ `);
268
+ }
269
+ return { ...notice === void 0 ? {} : { notice }, targets, files: [], copies: [], maintained: [], kept, retired: [], orphaned: [], warnings: result.warnings, errors: result.errors, drift, output, exitCode };
270
+ }
271
+ var REPLACED_OUTPUT = /^(?:(?:.*\/)?(?:CLAUDE|AGENTS)\.md|(?:.*\/)?\.(?:claude|agents)\/skills\/.+)$/;
272
+ function inspectReplacedOutputs(repoRoot) {
273
+ let configured = [];
274
+ try {
275
+ configured = resolveTargetsFromConfig(repoRoot);
276
+ } catch {
277
+ }
278
+ const targets = [.../* @__PURE__ */ new Set([...configured, "claude-code", "codex"])];
279
+ const maintained = maintainedFilesForExistingSkills(repoRoot, loadMaintainedFiles());
280
+ const maintainedPaths = new Set(maintained.map((f) => f.path));
281
+ const built = buildEmitInput(repoRoot, targets, maintained, new Set(retiredSkillPaths(repoRoot)));
282
+ const emitted = emitTree(built.input);
283
+ const generated = [];
284
+ const edited = [];
285
+ const replacedDiffering = [];
286
+ const classify = (path, same) => {
287
+ (same ? generated : edited).push(path);
288
+ };
289
+ for (const file of emitted.files) {
290
+ if (!REPLACED_OUTPUT.test(file.path) || !existsSync(join(repoRoot, file.path))) continue;
291
+ const disk = readFileSync(join(repoRoot, file.path), "utf8");
292
+ const source = generatedHeaderSource(disk);
293
+ const stale = source !== null && maintainedPaths.has(source);
294
+ const same = stale ? true : disk === file.content;
295
+ if (stale && disk !== file.content) replacedDiffering.push(file.path);
296
+ classify(file.path, same);
297
+ }
298
+ for (const copy of emitted.copies) {
299
+ if (!REPLACED_OUTPUT.test(copy.toPath) || !existsSync(join(repoRoot, copy.toPath))) continue;
300
+ const source = join(repoRoot, copy.fromSourcePath);
301
+ classify(copy.toPath, existsSync(source) && readFileSync(join(repoRoot, copy.toPath)).equals(readFileSync(source)));
282
302
  }
283
- return { targets, files: [], copies: [], maintained: [], kept, retired: [], orphaned: [], warnings: result.warnings, errors: result.errors, drift, output, exitCode };
303
+ return { generated: generated.sort(), edited: edited.sort(), replacedDiffering: replacedDiffering.sort() };
284
304
  }
285
305
 
286
- export { EmitError, runEmit };
306
+ export { EMIT_NOT_NEEDED_NOTICE, EmitError, inspectReplacedOutputs, runEmit };
@@ -0,0 +1,73 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire } from 'node:module';
3
+ import { RELAY_PORT, BUILD_HOME } from './chunk-URWYRAIC.js';
4
+ import { createServer, connect } from 'net';
5
+
6
+ createRequire(import.meta.url);
7
+ var BRIDGE_ADDRESS = "172.17.0.1";
8
+ var BRIDGE_CIDR = "172.17.0.1/16";
9
+ var TUNNEL_PORT = RELAY_PORT;
10
+ var CONTAINER_PROXY = `http://${BRIDGE_ADDRESS}:${TUNNEL_PORT}`;
11
+ var CONTAINER_NO_PROXY = ["localhost", "127.0.0.1", "::1", "10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"];
12
+ function dockerClientConfig() {
13
+ const proxies = { default: { httpProxy: CONTAINER_PROXY, httpsProxy: CONTAINER_PROXY, noProxy: CONTAINER_NO_PROXY.join(",") } };
14
+ return `${JSON.stringify({ proxies }, null, 2)}
15
+ `;
16
+ }
17
+ async function writeDockerClientConfig(run, agentUser) {
18
+ const dir = `${BUILD_HOME}/.docker`;
19
+ const script = [
20
+ "set -e",
21
+ "umask 077",
22
+ `mkdir -p ${dir}`,
23
+ `cat > ${dir}/config.json.partial`,
24
+ `mv ${dir}/config.json.partial ${dir}/config.json`,
25
+ `chown "$(id -u "$1"):$(id -g "$1")" ${dir} ${dir}/config.json`,
26
+ `chmod 700 ${dir}`,
27
+ `chmod 600 ${dir}/config.json`
28
+ ].join("\n");
29
+ const result = await run(["/bin/sh", "-c", script, "sh", agentUser], dockerClientConfig());
30
+ if (result.status === 0) return void 0;
31
+ return `the Docker client configuration could not be written in the microVM (exit ${result.status}): ${result.stderr.trim().split("\n")[0]}`;
32
+ }
33
+ function parseAddress(text) {
34
+ const match = /^(.+):(\d+)$/.exec(text);
35
+ const port = Number(match?.[2]);
36
+ if (match === null || port > 65535) throw new Error(`${JSON.stringify(text)} is not host:port`);
37
+ return { host: match[1], port };
38
+ }
39
+ async function startBridgeForward(opts) {
40
+ const listen = parseAddress(opts.listen);
41
+ const to = parseAddress(opts.to);
42
+ const open = /* @__PURE__ */ new Set();
43
+ const server = createServer({ allowHalfOpen: true }, (client) => {
44
+ const upstream = connect({ host: to.host, port: to.port, allowHalfOpen: true });
45
+ open.add(client);
46
+ client.on("error", () => void 0);
47
+ upstream.on("error", () => void 0);
48
+ client.on("close", () => {
49
+ open.delete(client);
50
+ upstream.destroy();
51
+ });
52
+ upstream.on("close", () => client.destroy());
53
+ client.pipe(upstream);
54
+ upstream.pipe(client);
55
+ });
56
+ await new Promise((resolve, reject) => {
57
+ server.once("error", reject);
58
+ server.listen(listen.port, listen.host, () => {
59
+ resolve();
60
+ });
61
+ });
62
+ server.on("error", (error) => process.stderr.write(`outerlayer: the bridge forwarder hit an error: ${error.message}
63
+ `));
64
+ return {
65
+ port: server.address().port,
66
+ close: () => new Promise((resolve) => {
67
+ for (const socket of open) socket.destroy();
68
+ server.close(() => resolve());
69
+ })
70
+ };
71
+ }
72
+
73
+ export { BRIDGE_ADDRESS, BRIDGE_CIDR, CONTAINER_NO_PROXY, CONTAINER_PROXY, TUNNEL_PORT, dockerClientConfig, startBridgeForward, writeDockerClientConfig };
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { LiveUploader } from './chunk-URAKVDSI.js';
4
- import { spoolDir } from './chunk-QC72I5GQ.js';
5
- import { CaptureDaemon } from './chunk-AEKSX4EY.js';
3
+ import { LiveUploader } from './chunk-DJYOCD65.js';
4
+ import { spoolDir } from './chunk-XOEV4FVK.js';
5
+ import { CaptureDaemon } from './chunk-CBCKD6DO.js';
6
6
  import { parseWorkItemEnv } from './chunk-T2Q7ISPE.js';
7
7
  import { homeFromEnv } from './chunk-VNVZDWO3.js';
8
8
  import { mkdirSync, writeFileSync, rmSync } from 'fs';
@@ -1,29 +1,30 @@
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
4
  import { findGitDirs } from './chunk-BJ3KTMDH.js';
4
- import { mcpTargetPath, INIT_STDIO_ENTRY, INIT_DOCS_ENTRY, DOCS_MCP_SERVER_NAME } from './chunk-DIB2WLBL.js';
5
- import { POLICY_CONTENT, VALIDATOR_FILES, VALIDATORS_DIR, POLICY_PATH } from './chunk-V7SAQ645.js';
6
- import { resolvePackRoot, skillDir, namesCore, loadTemplateFiles, TEMPLATE_SKILLS } from './chunk-5OCIHFGE.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';
7
8
  import { cliInvocation } from './chunk-CRB3POP4.js';
8
- import { hasSymlinkComponent } from './chunk-W3SWJ2TD.js';
9
+ import { hasSymlinkComponent } from './chunk-VWFOKRYS.js';
9
10
  import { cloneIsGoverned } from './chunk-YQR6E6OV.js';
10
- import { emitTree, ALL_TARGET_IDS, classifyTree, splitRawFile } from './chunk-WFSUUUAN.js';
11
+ import { emitTree, ALL_TARGET_IDS, classifyTree, splitRawFile } from './chunk-RKOTJQVG.js';
11
12
  import { createHash } from 'crypto';
12
- import { existsSync, readFileSync } from 'fs';
13
+ import { existsSync, readFileSync, realpathSync } from 'fs';
13
14
  import { join, dirname } from 'path';
14
15
 
15
16
  createRequire(import.meta.url);
16
17
  var SHIPPED_MANIFEST = "shipped.json";
17
- function currentStarterFiles(packRoot = resolvePackRoot(), policy = POLICY_CONTENT) {
18
- const templates = loadTemplateFiles(packRoot).map((f) => ({
18
+ function currentStarterFiles(packRoot = resolvePackRoot(), policy = POLICY_CONTENT, base = OUTERLAYER_SKILLS_BASE) {
19
+ const templates = loadTemplateFiles(packRoot, void 0, base).map((f) => ({
19
20
  path: f.path,
20
21
  content: f.content,
21
22
  skill: f.skill,
22
- source: join(packRoot, "template", f.skill, f.path.slice(skillDir(f.skill).length + 1))
23
+ source: join(packRoot, "template", f.skill, f.path.slice(skillDir(f.skill, base).length + 1))
23
24
  }));
24
25
  const validators = VALIDATOR_FILES.map(({ name }) => {
25
26
  const source = join(packRoot, "validators", name);
26
- return { path: `${VALIDATORS_DIR}/${name}`, content: readFileSync(source, "utf8"), source };
27
+ return { path: `${VALIDATORS_DIR}/${name}`, content: rewriteSkillPaths(readFileSync(source, "utf8"), base), source };
27
28
  });
28
29
  return [...templates, ...validators, { path: POLICY_PATH, content: policy }];
29
30
  }
@@ -66,12 +67,17 @@ function canonical(value) {
66
67
  }
67
68
  return JSON.stringify(value);
68
69
  }
69
- function fileState(root, file, manifest) {
70
+ function shippedPath(path, base) {
71
+ return path.startsWith(`${base}/`) ? `${OUTERLAYER_SKILLS_BASE}/${path.slice(base.length + 1)}` : path;
72
+ }
73
+ function fileState(root, file, manifest, base) {
70
74
  const abs = join(root, file.path);
71
75
  if (!existsSync(abs)) return "missing";
72
- const hash = contentHash(readFileSync(abs, "utf8"));
73
- if (hash === contentHash(file.content)) return "current";
74
- if (manifest.ok && manifest.files.get(file.path)?.has(hash) === true) return "outdated";
76
+ const disk = readFileSync(abs, "utf8");
77
+ if (contentHash(disk) === contentHash(file.content)) return "current";
78
+ const hash = contentHash(restoreSkillPaths(disk, base));
79
+ if (hash === contentHash(restoreSkillPaths(file.content, base))) return "outdated";
80
+ if (manifest.ok && manifest.files.get(shippedPath(file.path, base))?.has(hash) === true) return "outdated";
75
81
  return "edited";
76
82
  }
77
83
  function mcpItems(root) {
@@ -98,17 +104,18 @@ function mcpItems(root) {
98
104
  return { ...base, state: "edited" };
99
105
  });
100
106
  }
101
- function retiredFiles(root, shipped, manifest) {
107
+ function retiredFiles(root, shipped, manifest, base) {
102
108
  if (!manifest.ok) return [];
103
- const current = new Set(shipped.map((f) => f.path));
109
+ const current = new Set(shipped.map((f) => shippedPath(f.path, base)));
104
110
  const prefixes = TEMPLATE_SKILLS.map((skill) => `${skillDir(skill)}/`);
105
111
  const retired = [];
106
- for (const [path, hashes] of manifest.files) {
107
- if (current.has(path) || !prefixes.some((prefix) => path.startsWith(prefix))) continue;
112
+ for (const [known, hashes] of manifest.files) {
113
+ if (current.has(known) || !prefixes.some((prefix) => known.startsWith(prefix))) continue;
114
+ const path = base === OUTERLAYER_SKILLS_BASE ? known : `${base}/${known.slice(OUTERLAYER_SKILLS_BASE.length + 1)}`;
108
115
  const abs = join(root, path);
109
116
  if (!existsSync(abs) || hasSymlinkComponent(root, path)) continue;
110
117
  try {
111
- retired.push({ path, state: hashes.has(contentHash(readFileSync(abs, "utf8"))) ? "unedited" : "edited" });
118
+ retired.push({ path, state: hashes.has(contentHash(restoreSkillPaths(readFileSync(abs, "utf8"), base))) ? "unedited" : "edited" });
112
119
  } catch {
113
120
  }
114
121
  }
@@ -116,13 +123,14 @@ function retiredFiles(root, shipped, manifest) {
116
123
  }
117
124
  function inspectStarterFiles(root, opts = {}) {
118
125
  const packRoot = opts.packRoot ?? resolvePackRoot();
126
+ const base = opts.base ?? skillsBaseFor(root);
119
127
  const manifest = readShippedManifest(packRoot);
120
- const shipped = currentStarterFiles(packRoot);
121
- const files = shipped.map((file) => ({ kind: "file", path: file.path, state: fileState(root, file, manifest), file }));
122
- const buildEdited = files.some((f) => f.path === `${skillDir("build")}/SKILL.md` && f.state === "edited");
123
- const buildPrefix = `${skillDir("build")}/`;
124
- const retired = retiredFiles(root, shipped, manifest).filter((f) => !(buildEdited && f.path.startsWith(buildPrefix)));
125
- return { items: [...files, ...mcpItems(root)], retired, manifest: manifest.ok ? "ok" : manifest.problem };
128
+ const shipped = currentStarterFiles(packRoot, void 0, base);
129
+ const files = shipped.map((file) => ({ kind: "file", path: file.path, state: fileState(root, file, manifest, base), file }));
130
+ const buildEdited = files.some((f) => f.path === `${skillDir("build", base)}/SKILL.md` && f.state === "edited");
131
+ const buildPrefix = `${skillDir("build", base)}/`;
132
+ const retired = retiredFiles(root, shipped, manifest, base).filter((f) => !(buildEdited && f.path.startsWith(buildPrefix)));
133
+ return { base, items: [...files, ...mcpItems(root)], retired, manifest: manifest.ok ? "ok" : manifest.problem };
126
134
  }
127
135
  function itemLabel(item) {
128
136
  return item.kind === "file" ? item.path : `${item.path} "${item.server}" server`;
@@ -132,7 +140,7 @@ function contextIsGoverned(gitCommonDir) {
132
140
  }
133
141
  var NAME = "Starter files";
134
142
  var UPDATE = `${cliInvocation()} init --update`;
135
- function shownPaths(items, all) {
143
+ function shownPaths(items, all, base) {
136
144
  const shown = [];
137
145
  const whole = /* @__PURE__ */ new Set();
138
146
  for (const item of items) {
@@ -140,7 +148,7 @@ function shownPaths(items, all) {
140
148
  if (skill !== void 0) {
141
149
  const ofSkill = all.filter((i) => i.kind === "file" && i.file.skill === skill);
142
150
  if (ofSkill.every((i) => items.includes(i))) {
143
- if (!whole.has(skill)) shown.push(`${skillDir(skill)}/`);
151
+ if (!whole.has(skill)) shown.push(`${skillDir(skill, base)}/`);
144
152
  whole.add(skill);
145
153
  continue;
146
154
  }
@@ -164,8 +172,8 @@ function checkStarterFiles(cwd, opts = {}) {
164
172
  const retired = report.retired.filter((f) => f.state === "unedited");
165
173
  const parts = [];
166
174
  if (current.length > 0) parts.push(`${current.length} current`);
167
- if (outdated.length > 0) parts.push(`outdated and unedited: ${shownPaths(outdated, report.items).join(", ")}`);
168
- if (missing.length > 0) parts.push(`missing: ${shownPaths(missing, report.items).join(", ")}`);
175
+ if (outdated.length > 0) parts.push(`outdated and unedited: ${shownPaths(outdated, report.items, report.base).join(", ")}`);
176
+ if (missing.length > 0) parts.push(`missing: ${shownPaths(missing, report.items, report.base).join(", ")}`);
169
177
  if (retired.length > 0) parts.push(`no longer shipped, unedited: ${retired.map((f) => f.path).join(", ")}`);
170
178
  if (edited.length > 0) parts.push(`edited by you, left as they are: ${edited.map(itemLabel).join(", ")}`);
171
179
  if (unreadable.length > 0) parts.push(`${unreadable[0].path} is not valid JSON, so its servers were not read`);
@@ -244,15 +252,25 @@ ${shortBuild()}`
244
252
  fix: `Rename each heading to a phase: ${BUILD_PHASES.join(", ")}.`
245
253
  });
246
254
  }
247
- const lacking = folders.filter(
248
- (folder) => namesCore(read(join(repoRoot, folder, "build", "SKILL.md")) ?? "") && !existsSync(join(repoRoot, folder, "outerlayer-build", "SKILL.md"))
249
- );
255
+ const agentsMd = isAgentsMdLayout(repoRoot);
256
+ const seen = /* @__PURE__ */ new Set();
257
+ 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;
259
+ let key = folder;
260
+ try {
261
+ key = realpathSync(join(repoRoot, folder));
262
+ } catch {
263
+ }
264
+ if (seen.has(key)) return false;
265
+ seen.add(key);
266
+ return true;
267
+ });
250
268
  if (lacking.length > 0) {
251
269
  checks.push({
252
270
  name: NAME2,
253
271
  status: "warn",
254
272
  detail: `${lacking.join(", ")} holds build with no outerlayer-build beside it`,
255
- fix: `Run \`${cliInvocation()} context emit\` to write outerlayer-build, then commit.`
273
+ fix: `Run \`${cliInvocation()} ${agentsMd ? "init --update" : "context emit"}\` to write outerlayer-build, then commit.`
256
274
  });
257
275
  }
258
276
  return checks;
@@ -1,13 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { removeRetiredSkills } from './chunk-USWVXQIH.js';
4
- import { defaultFetch } from './chunk-QF7WZUU6.js';
5
- import { resolveGatewayCredentials } from './chunk-NTRCK4NH.js';
3
+ import { removeRetiredSkills } from './chunk-MQ743JX3.js';
4
+ import { defaultFetch, resolveGatewayCredentials } from './chunk-QS43O4DR.js';
6
5
  import { appendContextProvenance } from './chunk-ZJSNLVCE.js';
7
- import { loadMaintainedFiles, writeMaintainedFiles } from './chunk-5OCIHFGE.js';
6
+ import { loadMaintainedFiles, writeMaintainedFiles } from './chunk-HBISTTG3.js';
8
7
  import { cliInvocation } from './chunk-CRB3POP4.js';
9
8
  import { writeDegraded, writeSourceCache, SOURCE_CACHE_TTL_RETRY_MS, writeContextManifest, SOURCE_CACHE_TTL_SUCCESS_MS, readSourceCache, isSourceCacheFresh, clearDegraded } from './chunk-YQR6E6OV.js';
10
- import { normalizeRepoName, parseOuterlayerConfig, classifyTree, emitTree } from './chunk-WFSUUUAN.js';
9
+ import { normalizeRepoName, parseOuterlayerConfig, classifyTree, emitTree } from './chunk-RKOTJQVG.js';
11
10
  import { homeFromEnv } from './chunk-VNVZDWO3.js';
12
11
  import { withTokenHeader } from './chunk-URWYRAIC.js';
13
12
  import { execFileSync } from 'child_process';
@@ -429,7 +429,7 @@ async function handleWorkLaunch(sessionId, home, env, spawnImpl = spawnDetached,
429
429
  }
430
430
  async function missingRenewalHookContext(home, cwd) {
431
431
  try {
432
- const { settingsPath, readSettings, isOurHookCommand } = await import('./settings-J2652U5N.js');
432
+ const { settingsPath, readSettings, isOurHookCommand } = await import('./settings-AKYEOCC2.js');
433
433
  const userSettings = readSettings(settingsPath("user", { home }));
434
434
  const projectSettings = readSettings(settingsPath("project", { cwd }));
435
435
  if (userSettings === null && projectSettings === null) return void 0;
@@ -624,11 +624,11 @@ async function missingControlPlane(cwd, sessionId, home, env) {
624
624
  const dirs = findGitDirs(cwd);
625
625
  if (dirs === void 0) return void 0;
626
626
  if (existsSync(join(dirs.gitCommonDir, "outerlayer", "materialized.json")) || hasExcludeBlock(dirs.gitCommonDir)) {
627
- const { cleanupEarlierCopies } = await import('./context-cleanup-DSA3HGQU.js');
627
+ const { cleanupEarlierCopies } = await import('./context-cleanup-LTH77FC3.js');
628
628
  cleanupEarlierCopies(dirs);
629
629
  }
630
630
  if (!contextPossiblyGoverned(cwd, home)) return void 0;
631
- const { governanceOf } = await import('./control-plane-launch-OWSNH6YA.js');
631
+ const { governanceOf } = await import('./control-plane-launch-SEYCOZFH.js');
632
632
  if (await governanceOf({ cwd, env, home }) !== "governed") return void 0;
633
633
  recordMissingContext(dirs, sessionId, home);
634
634
  const launcher = `${cliInvocation()} claude`;