@outerlayer/cli 0.17.0 → 0.18.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 (144) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/README.md +15 -0
  3. package/dist/agent-setup-RBTEACYU.js +28 -0
  4. package/dist/{artifact-link-cmd-2F47LT7F.js → artifact-link-cmd-AVM2EKTV.js} +4 -3
  5. package/dist/{build-BG2YENGK.js → build-TQ6X5PYN.js} +5 -4
  6. package/dist/build-info.json +1 -1
  7. package/dist/{builder-2D3WSOOY.js → builder-DUI2ZH2H.js} +5 -6
  8. package/dist/{check-5XE7XMC4.js → check-5C4YDZYV.js} +53 -50
  9. package/dist/{chunk-R7PF5OOU.js → chunk-3CWUOFV6.js} +21 -14
  10. package/dist/{chunk-G5NPRL2K.js → chunk-3OFZM4X6.js} +548 -68
  11. package/dist/{chunk-2MNPHL23.js → chunk-47TTLEDX.js} +6 -5
  12. package/dist/{chunk-PLMTLGYH.js → chunk-52NC2FIU.js} +4 -3
  13. package/dist/chunk-6CHIYEZZ.js +564 -0
  14. package/dist/{chunk-TI7B7UEO.js → chunk-AMFWYESY.js} +1 -1
  15. package/dist/{chunk-YRYMNBGQ.js → chunk-ANPNT6PM.js} +2 -1
  16. package/dist/{chunk-YU3VKZ5F.js → chunk-B3UKB46N.js} +6 -6
  17. package/dist/{chunk-JXYVA45C.js → chunk-BMYGAGBJ.js} +1050 -304
  18. package/dist/{chunk-4Q7OMKAT.js → chunk-BQXFBI7T.js} +81 -5
  19. package/dist/chunk-CRB3POP4.js +34 -0
  20. package/dist/{chunk-F47JBIAW.js → chunk-DSF2FWAZ.js} +2 -1
  21. package/dist/{chunk-N5FOE5PS.js → chunk-ECODQ7II.js} +4 -33
  22. package/dist/{chunk-NBGDBTO2.js → chunk-ESC6UR76.js} +6 -5
  23. package/dist/{chunk-HHJDN6AU.js → chunk-ESVW4MJY.js} +1 -1
  24. package/dist/{chunk-42ZI52JW.js → chunk-F4XSVQJ4.js} +4 -3
  25. package/dist/{chunk-LWSJQJC6.js → chunk-FUB7LRUE.js} +7 -7
  26. package/dist/chunk-G2YNJIGF.js +44 -0
  27. package/dist/{chunk-QKFB4K7X.js → chunk-GGOMT6KF.js} +1 -1
  28. package/dist/{chunk-VQYBXPI7.js → chunk-GOBOJMOJ.js} +5 -5
  29. package/dist/{chunk-N6LURUEF.js → chunk-GOSFARMS.js} +1 -1
  30. package/dist/chunk-JBJTC3UU.js +35 -0
  31. package/dist/{chunk-NWQTTSBB.js → chunk-JF42URPU.js} +16 -15
  32. package/dist/{chunk-ADJRGVZC.js → chunk-KDVIU23F.js} +1 -1
  33. package/dist/{chunk-S3NYLI2P.js → chunk-KK4VBOH6.js} +93 -37
  34. package/dist/{chunk-KMDLFI4P.js → chunk-L2USZT6T.js} +1 -1
  35. package/dist/{chunk-WTE3MQML.js → chunk-LXAY4A2G.js} +3 -12
  36. package/dist/{chunk-V7NIVOFD.js → chunk-M2ZWWTWZ.js} +1 -1
  37. package/dist/{chunk-ERI5GBNI.js → chunk-MLAAT4S6.js} +3 -3
  38. package/dist/{chunk-POJMEEJJ.js → chunk-MNTSH4CL.js} +1 -1
  39. package/dist/{chunk-WUYTWNMA.js → chunk-MQJSXHV7.js} +1 -1
  40. package/dist/{chunk-O765JR4W.js → chunk-MTP2QEVO.js} +1 -1
  41. package/dist/{chunk-ZM2IMMYN.js → chunk-N2PXGQRL.js} +9 -1
  42. package/dist/{chunk-J5M7BSJQ.js → chunk-N3CUDFCW.js} +9 -3
  43. package/dist/{chunk-4KSQKQXE.js → chunk-NACDBXUG.js} +19 -15
  44. package/dist/{chunk-ONKJUM6R.js → chunk-NL4XPC7W.js} +1 -1
  45. package/dist/{chunk-WVUIRTWA.js → chunk-QQM2UJ6T.js} +31 -26
  46. package/dist/{chunk-KG5ECZGJ.js → chunk-RAZTWYZN.js} +10 -9
  47. package/dist/{chunk-4NPZVMJU.js → chunk-S26M3YBJ.js} +60 -4
  48. package/dist/{chunk-UGP76IZ5.js → chunk-S5PCA3SN.js} +1 -1
  49. package/dist/{chunk-3NSNIIBE.js → chunk-S76AYB4M.js} +17 -16
  50. package/dist/{chunk-RMWLBUCJ.js → chunk-SADUQSO4.js} +1 -1
  51. package/dist/{chunk-OZGHL5Y5.js → chunk-SWCTGCSC.js} +2 -2
  52. package/dist/{chunk-GQD22KKN.js → chunk-T2Q7ISPE.js} +2 -1
  53. package/dist/{chunk-C5Y5ZJJZ.js → chunk-T4Y6SCG3.js} +5 -4
  54. package/dist/{chunk-BWQ66M6N.js → chunk-ULSIJGLS.js} +45 -13
  55. package/dist/{chunk-NNRTPG7X.js → chunk-UYOYTKE2.js} +4 -4
  56. package/dist/{chunk-PTW6W5NR.js → chunk-VYAL7PUE.js} +1 -1
  57. package/dist/{chunk-YZ5F4PIS.js → chunk-W5VPCONO.js} +146 -247
  58. package/dist/{chunk-6Y5RUTHO.js → chunk-WBT5X3NH.js} +5 -4
  59. package/dist/{chunk-RLYZLUQ7.js → chunk-WGAUY5LE.js} +2 -2
  60. package/dist/{chunk-RSNSZ2LJ.js → chunk-X5H2WYMB.js} +1 -1
  61. package/dist/{chunk-OHVJA253.js → chunk-X5N6KC6V.js} +47 -29
  62. package/dist/{chunk-22RMZBGW.js → chunk-XGP3VYOG.js} +1 -1
  63. package/dist/{chunk-HYZRY4KZ.js → chunk-XNGMQ27R.js} +16 -6
  64. package/dist/{chunk-HGECYFEI.js → chunk-Y5GE76XC.js} +131 -54
  65. package/dist/{chunk-MAK5LYRF.js → chunk-Y5MXET4M.js} +277 -535
  66. package/dist/{chunk-XCK2YAY5.js → chunk-YVZJ6GKF.js} +3 -2
  67. package/dist/{chunk-YO4PSLVB.js → chunk-ZRL6HKBY.js} +1 -1
  68. package/dist/claude-launcher-YVXI76NX.js +102 -0
  69. package/dist/{cli-A76AXELQ.js → cli-C77H54BV.js} +468 -161
  70. package/dist/{command-R2QCVX55.js → command-H5CILO4S.js} +40 -37
  71. package/dist/{config-N3C6DFQA.js → config-FXDG4NPJ.js} +2 -3
  72. package/dist/{connect-cmd-JBKAQNSF.js → connect-cmd-ZW5FV3ZW.js} +9 -8
  73. package/dist/{context-adopt-NFHCLVUB.js → context-adopt-O5OFXMKI.js} +13 -12
  74. package/dist/context-materialize-Y5IJ4MQT.js +23 -0
  75. package/dist/{dist-LKDWQWZ7.js → dist-QTX4RSCL.js} +2 -2
  76. package/dist/{docker-4J77Q2BF.js → docker-RC3PRX3Q.js} +7 -8
  77. package/dist/{doctor-4TAIARIG.js → doctor-2NQQML6P.js} +46 -39
  78. package/dist/{emit-artifact-cmd-MPZVR56N.js → emit-artifact-cmd-7MP63KXU.js} +25 -22
  79. package/dist/emit-cmd-PPN4QQF2.js +14 -0
  80. package/dist/{emit-criteria-cmd-EFGYI23V.js → emit-criteria-cmd-3RXPDLNK.js} +16 -14
  81. package/dist/{emit-finding-cmd-5GF3V4LR.js → emit-finding-cmd-OL7JB6H3.js} +18 -16
  82. package/dist/{emit-result-cmd-I4OADKMD.js → emit-result-cmd-UZVMOCF4.js} +20 -17
  83. package/dist/{exec-client-CQV746UF.js → exec-client-7UMESIE2.js} +3 -4
  84. package/dist/governing-source-BUU4IABS.js +35 -0
  85. package/dist/guest-init-KPBQOFE5.js +9 -0
  86. package/dist/{hook-fast-R4FVSZ2H.js → hook-fast-W5MKHMJT.js} +4 -1
  87. package/dist/host-key-U4B5QETR.js +8 -0
  88. package/dist/{import-capture-cmd-EQ35EARA.js → import-capture-cmd-ZO6KGHI2.js} +7 -5
  89. package/dist/{import-ruler-cmd-BGAZXCQM.js → import-ruler-cmd-KJMWL5V6.js} +5 -3
  90. package/dist/index.js +8 -4
  91. package/dist/init-VWXIZEAN.js +54 -0
  92. package/dist/{init-PWU5YVL7.js → init-WNXXYMO7.js} +38 -35
  93. package/dist/{init-cmd-XAVO7HYZ.js → init-cmd-WS6TIRYT.js} +28 -24
  94. package/dist/{init-update-CVCWD6VS.js → init-update-E3J6TVIN.js} +27 -26
  95. package/dist/{install-HDBIPHTX.js → install-CBWIEF3R.js} +4 -5
  96. package/dist/{install-cmd-5HYMXLEW.js → install-cmd-QDOTR4OM.js} +5 -4
  97. package/dist/{login-browser-QZCS3WW6.js → login-browser-O63QZN7D.js} +4 -3
  98. package/dist/{logout-cmd-QAUFDJ6J.js → logout-cmd-5V5MMBSY.js} +3 -2
  99. package/dist/{logs-H55NWW4H.js → logs-AMLKC3VP.js} +3 -1
  100. package/dist/loop-UGI2BJOT.js +76 -0
  101. package/dist/machine-JOW4RNZ7.js +49 -0
  102. package/dist/{mcp-install-cmd-FDTPQQS6.js → mcp-install-cmd-GGWB3JJ2.js} +3 -2
  103. package/dist/{mcp-serve-cmd-3KVYEUXG.js → mcp-serve-cmd-DOTY5FKY.js} +10 -8
  104. package/dist/paths-7XP63OAX.js +7 -0
  105. package/dist/pending-532ABZYC.js +8 -0
  106. package/dist/{pidfile-UZRH774M.js → pidfile-3DM4OBKO.js} +4 -2
  107. package/dist/{record-C43U4PKS.js → record-3WP6V2K5.js} +3 -2
  108. package/dist/{runner-env-EN7YE7QX.js → runner-env-4NB2GA7O.js} +5 -6
  109. package/dist/{runner-key-6SLBI7PP.js → runner-key-TC3NFWFV.js} +38 -35
  110. package/dist/{session-sender-FO3LCREV.js → session-sender-NNVPSPY7.js} +17 -14
  111. package/dist/spec-cmd-OWVTBB4J.js +116 -0
  112. package/dist/{starter-pack-KF66HGZR.js → starter-pack-OPWUDOWX.js} +7 -5
  113. package/dist/{status-7VNQN5PW.js → status-TKCLLKFG.js} +42 -39
  114. package/dist/{statusline-fast-SVTMBMD7.js → statusline-fast-KN3BX67H.js} +2 -1
  115. package/dist/{sync-cmd-GVPPFZ3G.js → sync-cmd-Q6VYNPWG.js} +16 -13
  116. package/dist/{watch-23HSAEI6.js → watch-ARAGADTF.js} +16 -13
  117. package/dist/{work-claim-cmd-LKL3GHFQ.js → work-claim-cmd-34FERLYX.js} +25 -27
  118. package/dist/work-cmd-7S5B2H2P.js +25 -0
  119. package/dist/{work-comment-cmd-AWHP56M2.js → work-comment-cmd-SZJSPM5S.js} +15 -13
  120. package/dist/{work-launch-R5HTAP6X.js → work-launch-LEQ2MPM3.js} +3 -1
  121. package/dist/{work-open-pr-cmd-IOM4AVQQ.js → work-open-pr-cmd-RPXKCBWS.js} +17 -15
  122. package/dist/work-pr-cmd-5LGANL32.js +26 -0
  123. package/package.json +3 -2
  124. package/skill-pack/maintained/outerlayer-amend/SKILL.md +4 -2
  125. package/skill-pack/shipped.json +17 -2
  126. package/skill-pack/template/build/SKILL.md +23 -10
  127. package/skill-pack/template/build/references/agent-briefs.md +3 -1
  128. package/skill-pack/template/build/references/criteria-judge.md +27 -0
  129. package/skill-pack/template/build/references/release.md +19 -28
  130. package/skill-pack/template/spec/SKILL.md +35 -10
  131. package/skill-pack/validators/acceptance-criteria.yaml +25 -26
  132. package/dist/agent-setup-T624CWPD.js +0 -27
  133. package/dist/chunk-BYT5O5RV.js +0 -61
  134. package/dist/context-materialize-IV2TUUFO.js +0 -22
  135. package/dist/emit-cmd-IJ3GVRFD.js +0 -12
  136. package/dist/guest-init-LJP5GPZF.js +0 -9
  137. package/dist/host-key-YMLXY6QB.js +0 -7
  138. package/dist/init-6XPDRDTC.js +0 -51
  139. package/dist/loop-FK3LPMMZ.js +0 -73
  140. package/dist/machine-SQXEBAM2.js +0 -46
  141. package/dist/paths-OYKMVYJP.js +0 -6
  142. package/dist/pending-MXLSRYMO.js +0 -7
  143. package/dist/work-cmd-Z2WXLZPH.js +0 -23
  144. package/dist/work-pr-cmd-HNEUIEN7.js +0 -24
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { RESERVED_EMIT_NAMES, ARTIFACT_KINDS, ArtifactCriterionIdSchema } from './chunk-J5M7BSJQ.js';
3
+ import { RESERVED_EMIT_NAMES, ARTIFACT_KINDS, ArtifactCriterionIdSchema } from './chunk-N3CUDFCW.js';
4
4
  import { __commonJS, __require, __toESM } from './chunk-Z5GEFMRW.js';
5
5
 
6
6
  createRequire(import.meta.url);
@@ -7950,31 +7950,12 @@ function mergeCopies(perTarget) {
7950
7950
  const copies = [...byPath.entries()].filter(([path]) => !conflicted.has(path)).map(([toPath, fromSourcePath]) => ({ toPath, fromSourcePath })).sort((a, b) => a.toPath.localeCompare(b.toPath));
7951
7951
  return { copies, errors };
7952
7952
  }
7953
- var CONTEXT_SOURCE_CONFIG_PATH = ".outerlayer/config.json";
7954
- function parseGoverns(content) {
7955
- let parsed;
7956
- try {
7957
- parsed = JSON.parse(content);
7958
- } catch {
7959
- return { error: `${CONTEXT_SOURCE_CONFIG_PATH} is not valid JSON` };
7960
- }
7961
- if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
7962
- return { error: `${CONTEXT_SOURCE_CONFIG_PATH} must be a JSON object` };
7963
- }
7964
- const governs = parsed["governs"];
7965
- if (governs === void 0) {
7966
- return { governs: [] };
7967
- }
7968
- if (!Array.isArray(governs) || governs.some((entry) => typeof entry !== "string")) {
7969
- return { error: `"governs" must be an array of "owner/repo" strings` };
7970
- }
7971
- return { governs };
7972
- }
7973
7953
  function normalizeRepoName(repo) {
7974
7954
  return repo.trim().toLowerCase();
7975
7955
  }
7976
7956
  var CONTEXT_PIN_FILENAME = ".outerlayer-pin.json";
7977
7957
  var CONTEXT_PIN_SCHEMA_VERSION = 1;
7958
+ var MAX_BRIEF_LENGTH = 300;
7978
7959
  var MAX_COMMAND_LENGTH = 2e3;
7979
7960
  var EXTENDS_PROBLEM = '"extends" is not a policy key \u2014 every check is a file in .outerlayer/validators/. Run outerlayer init --template default to write .outerlayer/validators/code-review.yaml, then delete the extends line';
7980
7961
  var FREED_BUILTINS = /* @__PURE__ */ new Set(["ci-passed", "acceptance-criteria", "code-review-ran"]);
@@ -7994,6 +7975,8 @@ var MAX_ROW_LENGTH = 200;
7994
7975
  var MAX_NAME_LENGTH = 40;
7995
7976
  var MAX_GLOB_LENGTH = 200;
7996
7977
  var MAX_WHEN_PATHS = 20;
7978
+ var MAX_WHEN_REPOSITORIES = 20;
7979
+ var REPOSITORY_NAME = /^[\w.-]+\/[\w.-]+$/;
7997
7980
  var NEEDS_ALIASES = {
7998
7981
  "tool-calls.commands": "commands",
7999
7982
  "tool-calls.edits": "edits",
@@ -8276,13 +8259,14 @@ function parseCustomFile(file, problems) {
8276
8259
  let whenPaths = null;
8277
8260
  let whenIssueType = null;
8278
8261
  let whenIssueLabels = null;
8262
+ let whenRepositories;
8279
8263
  if (root["when"] !== void 0) {
8280
8264
  const when = root["when"];
8281
8265
  if (!isRecord(when) || Object.keys(when).some(
8282
- (key) => key !== "paths" && key !== "issue.type" && key !== "issue.labels"
8266
+ (key) => key !== "paths" && key !== "repositories" && key !== "issue.type" && key !== "issue.labels"
8283
8267
  ) || Object.keys(when).length === 0) {
8284
8268
  return fail(
8285
- `"${id}" when: only "paths", "issue.type", and "issue.labels" scoping is supported`
8269
+ `"${id}" when: only "paths", "repositories", "issue.type", and "issue.labels" scoping is supported`
8286
8270
  );
8287
8271
  }
8288
8272
  const paths = when["paths"];
@@ -8301,6 +8285,18 @@ function parseCustomFile(file, problems) {
8301
8285
  }
8302
8286
  whenPaths = paths.map((p) => p.trim());
8303
8287
  }
8288
+ const repositories = when["repositories"];
8289
+ if (repositories !== void 0) {
8290
+ if (!Array.isArray(repositories) || repositories.length === 0 || repositories.some((name2) => typeof name2 !== "string" || !REPOSITORY_NAME.test(name2.trim()))) {
8291
+ return fail(`"${id}" when.repositories must be a non-empty list of owner/repo names`);
8292
+ }
8293
+ if (repositories.length > MAX_WHEN_REPOSITORIES) {
8294
+ return fail(
8295
+ `"${id}" when.repositories lists ${repositories.length} names \u2014 the cap is ${MAX_WHEN_REPOSITORIES}`
8296
+ );
8297
+ }
8298
+ whenRepositories = repositories.map((name2) => name2.trim());
8299
+ }
8304
8300
  const issueType = when["issue.type"];
8305
8301
  if (issueType !== void 0) {
8306
8302
  if (typeof issueType !== "string" || issueType.trim() === "") {
@@ -8325,10 +8321,11 @@ function parseCustomFile(file, problems) {
8325
8321
  let declaresEmit = null;
8326
8322
  let runWhere;
8327
8323
  let command;
8324
+ let judge;
8328
8325
  if (hasRun) {
8329
8326
  const run = root["run"];
8330
- if (!isRecord(run) || Object.keys(run).some((key) => key !== "where" && key !== "emit" && key !== "command")) {
8331
- return fail(`"${id}" run: must be a mapping of "where", "emit" and, for where: host, "command"`);
8327
+ if (!isRecord(run) || Object.keys(run).some((key) => key !== "where" && key !== "emit" && key !== "command" && key !== "judge")) {
8328
+ return fail(`"${id}" run: must be a mapping of "where", "emit" and, for where: host, "command" or "judge"`);
8332
8329
  }
8333
8330
  const where = run["where"];
8334
8331
  if (where !== "ci" && where !== "host") {
@@ -8346,10 +8343,29 @@ function parseCustomFile(file, problems) {
8346
8343
  if (where === "ci" && run["command"] !== void 0) {
8347
8344
  return fail(`"${id}" run.command is only for run.where: host \u2014 a where: ci check runs in your own CI`);
8348
8345
  }
8349
- if (where === "host") {
8346
+ if (where === "ci" && run["judge"] !== void 0) {
8347
+ return fail(`"${id}" run.judge is only for run.where: host \u2014 a where: ci check runs in your own CI`);
8348
+ }
8349
+ if (where === "host" && run["judge"] !== void 0) {
8350
+ if (run["command"] !== void 0) {
8351
+ return fail(`"${id}" run declares both "judge" and "command" \u2014 a host check has one or the other`);
8352
+ }
8353
+ const rawJudge = run["judge"];
8354
+ if (!isRecord(rawJudge) || Object.keys(rawJudge).some((key) => key !== "brief")) {
8355
+ return fail(`"${id}" run.judge must be a mapping with a "brief"`);
8356
+ }
8357
+ const brief = rawJudge["brief"];
8358
+ if (typeof brief !== "string" || brief.trim() === "" || brief.length > MAX_BRIEF_LENGTH || brief.startsWith("/") || brief.split("/").includes("..")) {
8359
+ return fail(
8360
+ `"${id}" run.judge.brief must be a relative path inside the repository, of at most ${MAX_BRIEF_LENGTH} characters, with no ".." segment`
8361
+ );
8362
+ }
8363
+ judge = { brief: brief.trim() };
8364
+ runWhere = "host";
8365
+ } else if (where === "host") {
8350
8366
  const rawCommand = run["command"];
8351
8367
  if (rawCommand === void 0) {
8352
- return fail(`"${id}" run.where: host needs a "command" \u2014 the shell line the host runs`);
8368
+ return fail(`"${id}" run.where: host needs a "command" or a "judge" \u2014 what the host runs`);
8353
8369
  }
8354
8370
  if (typeof rawCommand !== "string" || rawCommand.trim() === "" || rawCommand.length > MAX_COMMAND_LENGTH) {
8355
8371
  return fail(`"${id}" run.command must be a non-empty string of at most ${MAX_COMMAND_LENGTH} characters`);
@@ -8375,6 +8391,7 @@ function parseCustomFile(file, problems) {
8375
8391
  whenPaths,
8376
8392
  whenIssueType,
8377
8393
  whenIssueLabels,
8394
+ ...whenRepositories === void 0 ? {} : { whenRepositories, whenRepositoriesFile: file.path },
8378
8395
  requireAny,
8379
8396
  // Declared needs only — the author's own statement of what the rule
8380
8397
  // reads. A session.ran alternative is guarded per-alternative at
@@ -8384,7 +8401,8 @@ function parseCustomFile(file, problems) {
8384
8401
  needs: [...new Set(declaredNeeds)].sort(),
8385
8402
  declaresEmit,
8386
8403
  ...runWhere === void 0 ? {} : { runWhere },
8387
- ...command === void 0 ? {} : { command }
8404
+ ...command === void 0 ? {} : { command },
8405
+ ...judge === void 0 ? {} : { judge }
8388
8406
  },
8389
8407
  file: file.path,
8390
8408
  validatorRefs: requireAny.flatMap((alt) => alt.type === "validator" ? [alt.id] : []),
@@ -8685,4 +8703,4 @@ function sessionsToTimeline(sessions) {
8685
8703
  return out;
8686
8704
  }
8687
8705
 
8688
- export { ALL_TARGET_IDS, CONTEXT_PIN_FILENAME, CONTEXT_PIN_SCHEMA_VERSION, CONTEXT_SOURCE_CONFIG_PATH, classifyTree, emitTree, extractFacts, generatedHeaderSource, normalizePath, normalizeRepoName, orderSessions, parseGoverns, parseOuterlayerConfig, parsePolicy, sessionsToTimeline, splitRawFile };
8706
+ export { ALL_TARGET_IDS, CONTEXT_PIN_FILENAME, CONTEXT_PIN_SCHEMA_VERSION, classifyTree, emitTree, extractFacts, generatedHeaderSource, normalizePath, normalizeRepoName, orderSessions, parseOuterlayerConfig, parsePolicy, sessionsToTimeline, splitRawFile };
@@ -2,7 +2,7 @@
2
2
  import { createRequire } from 'node:module';
3
3
  import { MAX_ALLOW_HOSTS, allowHostProblem } from './chunk-UXYLWVTQ.js';
4
4
  import { parseSize } from './chunk-7RQ73DLO.js';
5
- import { isRefusedInConfig, resolveDestinations, isReservedVariable } from './chunk-4Q7OMKAT.js';
5
+ import { isRefusedInConfig, resolveDestinations, isReservedVariable } from './chunk-BQXFBI7T.js';
6
6
  import { homeFromEnv } from './chunk-VNVZDWO3.js';
7
7
  import { existsSync, statSync, accessSync, constants, readFileSync } from 'fs';
8
8
  import { hostname } from 'os';
@@ -1,12 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { EXEC_PORT } from './chunk-RSNSZ2LJ.js';
4
- import { RELAY_PORT } from './chunk-4Q7OMKAT.js';
3
+ import { EXEC_PORT } from './chunk-X5H2WYMB.js';
4
+ import { startTimeOf } from './chunk-JBJTC3UU.js';
5
+ import { RELAY_PORT } from './chunk-BQXFBI7T.js';
5
6
  import { spawn, spawnSync } from 'child_process';
6
7
  import { writeFileSync, chmodSync, mkdirSync } from 'fs';
7
8
 
8
9
  createRequire(import.meta.url);
9
10
  var HELPER_PATH = "/opt/outerlayer/bin/outerlayer-guest";
11
+ var HELPER_RECORD = "/run/outerlayer-helpers";
10
12
  var KERNEL_FLAG = "outerlayer.relay";
11
13
  var DOCKER_FLAG = "outerlayer.docker";
12
14
  var DOCKERD_CONFIG = "/run/outerlayer-dockerd.json";
@@ -62,9 +64,11 @@ function runGuestInit(host, cmdline) {
62
64
  }
63
65
  host.writeFile("/proc/sys/kernel/hostname", HOSTNAME);
64
66
  host.mount({ source: "tmpfs", target: "/outerlayer/job", type: "tmpfs", options: "mode=0755" });
65
- host.spawnDetached([HELPER_PATH, "relay", ...ports.flatMap((port) => ["--forward", String(port)])]);
67
+ const relay = host.spawnDetached([HELPER_PATH, "relay", ...ports.flatMap((port) => ["--forward", String(port)])]);
66
68
  if (dockerRequestedBy(cmdline)) startDocker(host);
67
- host.spawnDetached([HELPER_PATH, "exec-agent", "--port", String(EXEC_PORT)]);
69
+ const agent = host.spawnDetached([HELPER_PATH, "exec-agent", "--port", String(EXEC_PORT)]);
70
+ host.writeFile(HELPER_RECORD, [relay, agent].map((started) => `${started.pid} ${started.start}
71
+ `).join(""));
68
72
  }
69
73
  function realGuestHost() {
70
74
  return {
@@ -81,9 +85,15 @@ function realGuestHost() {
81
85
  chmod: (path, mode) => chmodSync(path, mode),
82
86
  writeFile: (path, text) => writeFileSync(path, text),
83
87
  spawnDetached(argv) {
84
- spawn(argv[0], argv.slice(1), { detached: true, stdio: ["ignore", "inherit", "inherit"] }).unref();
88
+ const child = spawn(argv[0], argv.slice(1), { detached: true, stdio: ["ignore", "inherit", "inherit"] });
89
+ child.unref();
90
+ child.once("error", () => {
91
+ });
92
+ const start = child.pid === void 0 ? null : startTimeOf(child.pid);
93
+ if (child.pid === void 0 || start === null) throw new Error(`${argv[0]} did not start`);
94
+ return { pid: child.pid, start };
85
95
  }
86
96
  };
87
97
  }
88
98
 
89
- export { DOCKERD_LOG, HELPER_PATH, realGuestHost, relayPortsFrom, runGuestInit };
99
+ export { DOCKERD_LOG, HELPER_PATH, HELPER_RECORD, realGuestHost, relayPortsFrom, runGuestInit };