@outerlayer/cli 0.2.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/CHANGELOG.md +132 -0
  2. package/README.md +229 -60
  3. package/dist/agent-setup-IFH3FB5X.js +197 -0
  4. package/dist/build-TZUUTRGH.js +9 -0
  5. package/dist/build-info.json +1 -1
  6. package/dist/check-7MFH6HNC.js +94 -0
  7. package/dist/chunk-3TFPDVTI.js +94 -0
  8. package/dist/{chunk-4TNZMO7V.js → chunk-4C4THABW.js} +5566 -754
  9. package/dist/{chunk-R5KBGVII.js → chunk-5QRP3MVS.js} +30 -14
  10. package/dist/chunk-5Y3QQRUH.js +300 -0
  11. package/dist/chunk-774HEQL6.js +178 -0
  12. package/dist/{work-pr-cmd-AZQPWH4H.js → chunk-7WERLFVR.js} +9 -26
  13. package/dist/chunk-ABIWDUMS.js +104 -0
  14. package/dist/chunk-AUFG23AA.js +534 -0
  15. package/dist/chunk-B2G7JHHB.js +42 -0
  16. package/dist/chunk-BCJNHMZT.js +34 -0
  17. package/dist/chunk-BCLJSQCV.js +56 -0
  18. package/dist/chunk-BFESLKPP.js +61 -0
  19. package/dist/chunk-BJ3KTMDH.js +63 -0
  20. package/dist/chunk-BKO6JEZI.js +47 -0
  21. package/dist/chunk-BOLTI6LR.js +37 -0
  22. package/dist/chunk-CBPPJSAR.js +89 -0
  23. package/dist/chunk-DM3VFDS3.js +1461 -0
  24. package/dist/{chunk-65WXAANR.js → chunk-DVDEBNQJ.js} +17 -2
  25. package/dist/{chunk-TFUIDMOB.js → chunk-EABW6AJQ.js} +12 -1
  26. package/dist/{chunk-KFYJV2ZG.js → chunk-EMY4I27X.js} +1 -1
  27. package/dist/{chunk-NTTPJV35.js → chunk-F47JBIAW.js} +3 -1
  28. package/dist/chunk-F6GFZXZ3.js +60 -0
  29. package/dist/{chunk-YOOSBOKS.js → chunk-F7CU5ABH.js} +1 -1
  30. package/dist/{emit-cmd-TWSYYEZI.js → chunk-H5NCNVDA.js} +68 -17
  31. package/dist/chunk-HZRNMGLF.js +2233 -0
  32. package/dist/chunk-LF6MLJCY.js +38 -0
  33. package/dist/{chunk-U32VSRLO.js → chunk-LT5TZHYH.js} +95 -634
  34. package/dist/chunk-LYCDNMOH.js +83 -0
  35. package/dist/chunk-M5POMKKW.js +1051 -0
  36. package/dist/{mcp-install-cmd-FDQH6SEN.js → chunk-MQ3IPHIZ.js} +35 -18
  37. package/dist/{chunk-D77LS3UI.js → chunk-N5FOE5PS.js} +33 -4
  38. package/dist/chunk-N6LURUEF.js +64 -0
  39. package/dist/chunk-OGFGZQA3.js +23 -0
  40. package/dist/chunk-QDQEUVUF.js +9 -0
  41. package/dist/chunk-QOZKPLVJ.js +226 -0
  42. package/dist/chunk-QY22NZUW.js +1764 -0
  43. package/dist/chunk-RA3O54FC.js +30 -0
  44. package/dist/chunk-RFUPN6KX.js +71 -0
  45. package/dist/chunk-SY4GK4SP.js +55 -0
  46. package/dist/chunk-TBT347UY.js +41 -0
  47. package/dist/chunk-TWNWNS2Q.js +1084 -0
  48. package/dist/{chunk-NXLLURA4.js → chunk-UFFXNXLQ.js} +115 -71
  49. package/dist/chunk-USO2DKBD.js +421 -0
  50. package/dist/chunk-W4SQCOZU.js +206 -0
  51. package/dist/{chunk-Q6CL5THG.js → chunk-W5FVUZXV.js} +208 -61
  52. package/dist/chunk-WFJ65NUD.js +383 -0
  53. package/dist/{chunk-A3WLZX2F.js → chunk-WIOZAJ2W.js} +15 -2
  54. package/dist/chunk-WO2BXCTQ.js +83 -0
  55. package/dist/{chunk-I3ETLSNE.js → chunk-XCCLFVXM.js} +120 -11
  56. package/dist/{context-materialize-6WKT3RBQ.js → chunk-XDDW4FRS.js} +134 -26
  57. package/dist/chunk-Y7KJLXYN.js +232 -0
  58. package/dist/chunk-YFHIIH4B.js +102 -0
  59. package/dist/chunk-YYYXRJUW.js +101 -0
  60. package/dist/chunk-ZM2IMMYN.js +76 -0
  61. package/dist/chunk-ZMYPLFG3.js +71 -0
  62. package/dist/chunk-ZNA27WEV.js +470 -0
  63. package/dist/{cli-G7DILYJY.js → cli-W62AFRSW.js} +616 -878
  64. package/dist/{paths-D2VGWWFI.js → cli-build-K56DK4DS.js} +1 -1
  65. package/dist/config-XVJYZ4IQ.js +9 -0
  66. package/dist/connect-cmd-ZTJONP37.js +16 -0
  67. package/dist/context-adopt-UMA4O5NY.js +105 -0
  68. package/dist/context-materialize-G2FUFC72.js +19 -0
  69. package/dist/dist-44CQVWGT.js +6 -0
  70. package/dist/docker-NEGDLU6D.js +7 -0
  71. package/dist/doctor-53F2PYY7.js +43 -0
  72. package/dist/doctor-ZLGZYMDK.js +426 -0
  73. package/dist/{emit-artifact-cmd-UQVT3OKW.js → emit-artifact-cmd-AKZP7TMF.js} +87 -23
  74. package/dist/emit-cmd-DCERAU27.js +9 -0
  75. package/dist/emit-criteria-cmd-7MXQVCKD.js +166 -0
  76. package/dist/{emit-finding-cmd-FDOU2OPD.js → emit-finding-cmd-N2FTGCVC.js} +34 -31
  77. package/dist/{emit-result-cmd-H2T4C2K3.js → emit-result-cmd-4CPDBMN2.js} +34 -62
  78. package/dist/exec-client-4XGXV3XN.js +8 -0
  79. package/dist/guest-init-GENRHNP7.js +8 -0
  80. package/dist/hook-fast-EYENPK6F.js +9 -0
  81. package/dist/{hook-wrap-fast-KXYNX3AD.js → hook-wrap-fast-NPLHJXFK.js} +2 -2
  82. package/dist/host-key-KDYZ5ECC.js +7 -0
  83. package/dist/import-capture-cmd-AVZ4VIVJ.js +68 -0
  84. package/dist/{import-ruler-cmd-7LH2QOMG.js → import-ruler-cmd-GUHL6IY5.js} +1 -1
  85. package/dist/index.js +4 -4
  86. package/dist/init-55Y4LHWF.js +36 -0
  87. package/dist/init-XXEKWZQP.js +221 -0
  88. package/dist/init-cmd-WLST2F7G.js +135 -0
  89. package/dist/install-cmd-7WXOIFDO.js +55 -0
  90. package/dist/lima-XN65D7GN.js +55 -0
  91. package/dist/login-browser-7XGSV7MA.js +10 -0
  92. package/dist/{config-POF7DEQW.js → logout-cmd-QAUFDJ6J.js} +3 -1
  93. package/dist/{logs-TRNPQM42.js → logs-7RYUH5A6.js} +1 -1
  94. package/dist/loop-JFIBP4B7.js +43 -0
  95. package/dist/machine-ZBPT2J3R.js +35 -0
  96. package/dist/mcp-install-cmd-RLK4SO3N.js +9 -0
  97. package/dist/{mcp-serve-cmd-57EZZOTL.js → mcp-serve-cmd-N6UD2KBX.js} +20 -9
  98. package/dist/paths-OYKMVYJP.js +6 -0
  99. package/dist/{pidfile-PTW76F56.js → pidfile-UZRH774M.js} +2 -3
  100. package/dist/real-deps-SU24ZA2K.js +21 -0
  101. package/dist/relay-L76HDX72.js +46 -0
  102. package/dist/settings-J2652U5N.js +7 -0
  103. package/dist/starter-pack-LIZYMKYQ.js +10 -0
  104. package/dist/{status-I27IST4L.js → status-UJXWZRN5.js} +30 -13
  105. package/dist/{statusline-fast-3C5OXHDD.js → statusline-fast-SVTMBMD7.js} +3 -2
  106. package/dist/sync-cmd-4G4A7EVN.js +28 -0
  107. package/dist/version-BWM6VLDI.js +6 -0
  108. package/dist/{watch-3DTPJETH.js → watch-7SKJKGAA.js} +19 -8
  109. package/dist/{work-claim-cmd-5AUNCLS2.js → work-claim-cmd-5F7VZ42N.js} +34 -21
  110. package/dist/work-cmd-QAUZ7MTD.js +17 -0
  111. package/dist/work-comment-cmd-BNCSBTLH.js +106 -0
  112. package/dist/{work-launch-LT663PB3.js → work-launch-YI4CJDAP.js} +1 -1
  113. package/dist/work-open-pr-cmd-VFYZHIIW.js +156 -0
  114. package/dist/work-pr-cmd-PV32ZLSI.js +16 -0
  115. package/package.json +13 -3
  116. package/skill-pack/maintained/amend/SKILL.md +104 -0
  117. package/skill-pack/maintained/emitting-evidence/SKILL.md +108 -0
  118. package/skill-pack/maintained/emitting-evidence/references/agents-snippet.md +20 -0
  119. package/skill-pack/maintained/outerlayer/SKILL.md +55 -0
  120. package/skill-pack/maintained/reporting-findings/SKILL.md +148 -0
  121. package/skill-pack/template/build/SKILL.md +193 -0
  122. package/skill-pack/template/build/references/agent-briefs.md +243 -0
  123. package/skill-pack/template/build/references/criteria-judge.md +91 -0
  124. package/skill-pack/template/build/references/evidence.md +42 -0
  125. package/skill-pack/template/build/references/release.md +74 -0
  126. package/skill-pack/template/build/references/review-briefs.md +275 -0
  127. package/skill-pack/template/build/references/review-loop.md +158 -0
  128. package/skill-pack/template/build/scripts/record-criteria.mjs +235 -0
  129. package/skill-pack/template/spec/SKILL.md +84 -0
  130. package/skill-pack/template/writing-specs/SKILL.md +134 -0
  131. package/dist/chunk-DCNOXRMV.js +0 -589
  132. package/dist/chunk-JJP7YLMN.js +0 -25
  133. package/dist/chunk-OZ7C3XUE.js +0 -34
  134. package/dist/chunk-WQ6VGRGZ.js +0 -150
  135. package/dist/hook-fast-J5LCDHUJ.js +0 -8
  136. package/dist/import-capture-cmd-EUMBGIV3.js +0 -176
  137. package/dist/init-PTBITAUO.js +0 -103
  138. package/dist/login-cmd-IRX6LZT7.js +0 -62
  139. package/dist/loop-ASZRX3CZ.js +0 -648
  140. package/dist/sync-cmd-BBAUZ5JD.js +0 -17
  141. package/dist/work-cmd-2P4BVX47.js +0 -18
@@ -1,11 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { deadHooksState, huskyPrepareScript, preparePackageManagerCommand } from './chunk-I3ETLSNE.js';
3
+ import { deadHooksState, huskyPrepareScript, preparePackageManagerCommand } from './chunk-XCCLFVXM.js';
4
+ import { readRepoConnection, findGitDirs } from './chunk-BJ3KTMDH.js';
4
5
  import { homeFromEnv } from './chunk-VNVZDWO3.js';
5
6
  import { readFileSync, mkdirSync, writeFileSync, renameSync, existsSync, statSync, appendFileSync, openSync, opendirSync, unlinkSync } from 'fs';
6
7
  import { spawn, execFileSync } from 'child_process';
7
8
  import { createHash } from 'crypto';
8
- import { join, dirname, isAbsolute, resolve } from 'path';
9
+ import { join, dirname, resolve } from 'path';
9
10
 
10
11
  createRequire(import.meta.url);
11
12
  var SYNC_STALE_AFTER_MS = 6 * 60 * 60 * 1e3;
@@ -354,11 +355,17 @@ function appendFd(path) {
354
355
  return "ignore";
355
356
  }
356
357
  }
357
- var spawnDetached = (command, args, stderrPath) => {
358
- const child = spawn(command, args, { detached: true, stdio: ["ignore", "ignore", appendFd(stderrPath)] });
358
+ var spawnDetached = (command, args, stderrPath, cwd) => {
359
+ const child = spawn(command, args, {
360
+ detached: true,
361
+ stdio: ["ignore", "ignore", appendFd(stderrPath)],
362
+ ...cwd !== void 0 ? { cwd } : {}
363
+ });
364
+ child.on("error", () => {
365
+ });
359
366
  child.unref();
360
367
  };
361
- function maybeAutoSync(event, home = homeFromEnv(), spawnImpl = spawnDetached, now = Date.now()) {
368
+ function maybeAutoSync(event, home = homeFromEnv(), spawnImpl = spawnDetached, now = Date.now(), cwd = process.cwd()) {
362
369
  try {
363
370
  if (event !== "SessionEnd" && event !== "Stop") return;
364
371
  const marker = join(spoolDir(home), "last-auto-sync");
@@ -370,55 +377,114 @@ function maybeAutoSync(event, home = homeFromEnv(), spawnImpl = spawnDetached, n
370
377
  if (!existsSync(configPath)) return;
371
378
  const config = JSON.parse(readFileSync(configPath, "utf8"));
372
379
  if (config.autoSync === false) return;
373
- if (!config.url || !config.apiKey || !config.appId) return;
380
+ if (!config.url) return;
381
+ if (config.apiKey) {
382
+ if (!config.appId) return;
383
+ } else if (!config.accountToken || readRepoConnection(cwd) === void 0) return;
374
384
  writeFileSync(marker, String(now));
375
- spawnImpl(process.execPath, [process.argv[1], "sync", "--quiet"]);
385
+ spawnImpl(process.execPath, [process.argv[1], "sync", "--quiet"], void 0, cwd);
376
386
  } catch {
377
387
  }
378
388
  }
379
- var WORK_ADD_RETRIES = 4;
389
+ var WORK_LINK_RETRIES = 4;
380
390
  function hookErrorsContext(home, writtenBytes, seenBytes) {
381
391
  if (writtenBytes === 0) return null;
382
392
  if (writtenBytes === seenBytes) return null;
383
393
  const path = join(spoolDir(home), "hook-errors.log");
384
- return `OuterLayer recorded a hook failure since your last session started \u2014 a refused OUTERLAYER_WORK value, or a work-item session link that could not reach the Floor. The log is ${path}.`;
394
+ return `OuterLayer recorded a hook failure since your last session started \u2014 a refused OUTERLAYER_WORK value, or a work-item session link that could not reach Work. The log is ${path}.`;
385
395
  }
386
- async function handleWorkLaunch(sessionId, home, env, spawnImpl = spawnDetached) {
396
+ async function handleWorkLaunch(sessionId, home, env, spawnImpl = spawnDetached, cwd = process.cwd()) {
387
397
  if (!sessionId || env.OUTERLAYER_WORK === void 0) return void 0;
388
- const { parseWorkItemEnv, appendLaunchRecord } = await import('./work-launch-LT663PB3.js');
398
+ const { parseWorkItemEnv, appendLaunchRecord } = await import('./work-launch-YI4CJDAP.js');
389
399
  const parsed = parseWorkItemEnv(env.OUTERLAYER_WORK);
390
400
  if ("reason" in parsed) {
391
401
  logHookError(home, new Error(`OUTERLAYER_WORK ignored: ${parsed.reason}`));
392
402
  return `OuterLayer ignored this session's OUTERLAYER_WORK value: ${sanitizeForContext(parsed.reason)}. The session is not attached to a work item and will not upload. Hook failures are logged to ${join(spoolDir(home), "hook-errors.log")}.`;
393
403
  }
394
404
  appendLaunchRecord({ sessionId, item: parsed.number }, home);
405
+ const args = [
406
+ process.argv[1],
407
+ "work",
408
+ "link-session",
409
+ String(parsed.number),
410
+ "--session-id",
411
+ sessionId,
412
+ // The ordinary failure is a gateway that is briefly unreachable — a
413
+ // laptop that has not joined the network yet, a restart. Nothing else
414
+ // ever retries this link: the launch record is already written, so
415
+ // the session uploads whether or not Work ever hears about the
416
+ // link. Retrying costs nothing here (this process is detached; the
417
+ // hook has already returned) and cannot double-link, because the
418
+ // link is keyed by the session id passed above.
419
+ "--retry",
420
+ String(WORK_LINK_RETRIES)
421
+ ];
422
+ if (env.OUTERLAYER_JOB_DIR !== void 0) args.push("--no-lease");
395
423
  spawnImpl(
396
424
  process.execPath,
397
- [
398
- process.argv[1],
399
- "work",
400
- "link-session",
401
- String(parsed.number),
402
- "--session-id",
403
- sessionId,
404
- // The ordinary failure is a gateway that is briefly unreachable — a
405
- // laptop that has not joined the network yet, a restart. Nothing else
406
- // ever retries this link: the launch record is already written, so
407
- // the session uploads whether or not the Floor ever hears about the
408
- // link. Retrying costs nothing here (this process is detached; the
409
- // hook has already returned) and cannot double-link, because the
410
- // link is keyed by the session id passed above.
411
- "--retry",
412
- String(WORK_ADD_RETRIES)
413
- ],
425
+ args,
414
426
  // The link runs after this hook has exited, so its own failure
415
427
  // (offline, revoked key, unknown item number) has nowhere else to be
416
- // seen: without this the session uploads later with no Floor link and
428
+ // seen: without this the session uploads later with no Work link and
417
429
  // no trace of why.
418
- join(spoolDir(home), "hook-errors.log")
430
+ join(spoolDir(home), "hook-errors.log"),
431
+ cwd
419
432
  );
420
433
  return void 0;
421
434
  }
435
+ async function missingRenewalHookContext(home, cwd) {
436
+ try {
437
+ const { settingsPath, readSettings, isOurHookCommand } = await import('./settings-J2652U5N.js');
438
+ const userSettings = readSettings(settingsPath("user", { home }));
439
+ const projectSettings = readSettings(settingsPath("project", { cwd }));
440
+ if (userSettings === null && projectSettings === null) return void 0;
441
+ const registeredIn = (settings) => (settings.hooks?.PostToolUse ?? []).some((block) => (block.hooks ?? []).some((h) => isOurHookCommand(h)));
442
+ const registered = userSettings !== null && registeredIn(userSettings) || projectSettings !== null && registeredIn(projectSettings);
443
+ if (registered) return void 0;
444
+ return "This install has no PostToolUse hook, so this session's work-item lease will never be renewed while it works and may be lost to another worker mid-session. Run `outerlayer init` to register it.";
445
+ } catch {
446
+ return void 0;
447
+ }
448
+ }
449
+ var WORK_LEASE_RENEW_DEBOUNCE_MS = 5 * 60 * 1e3;
450
+ async function maybeRenewWorkLease(event, sessionId, home = homeFromEnv(), env = process.env, spawnImpl = spawnDetached, now = Date.now(), cwd = process.cwd()) {
451
+ try {
452
+ if (event !== "PostToolUse") return;
453
+ if (!sessionId || env.OUTERLAYER_WORK === void 0 || env.OUTERLAYER_JOB_DIR !== void 0) return;
454
+ const marker = join(spoolDir(home), `work-lease-renew-${sessionId}`);
455
+ try {
456
+ if (now - statSync(marker).mtimeMs < WORK_LEASE_RENEW_DEBOUNCE_MS) return;
457
+ } catch {
458
+ }
459
+ const { parseWorkItemEnv } = await import('./work-launch-YI4CJDAP.js');
460
+ const parsed = parseWorkItemEnv(env.OUTERLAYER_WORK);
461
+ if ("reason" in parsed) return;
462
+ writeFileSync(marker, String(now));
463
+ spawnImpl(
464
+ process.execPath,
465
+ [process.argv[1], "work", "link-session", String(parsed.number), "--session-id", sessionId],
466
+ join(spoolDir(home), "hook-errors.log"),
467
+ cwd
468
+ );
469
+ } catch {
470
+ }
471
+ }
472
+ async function handleWorkSessionEnd(event, sessionId, home = homeFromEnv(), env = process.env, spawnImpl = spawnDetached, cwd = process.cwd()) {
473
+ try {
474
+ if (event !== "SessionEnd") return;
475
+ if (!sessionId || env.OUTERLAYER_WORK === void 0) return;
476
+ const { parseWorkItemEnv } = await import('./work-launch-YI4CJDAP.js');
477
+ const parsed = parseWorkItemEnv(env.OUTERLAYER_WORK);
478
+ if ("reason" in parsed) return;
479
+ spawnImpl(
480
+ process.execPath,
481
+ [process.argv[1], "work", "link-session", String(parsed.number), "--session-id", sessionId, "--ended"],
482
+ join(spoolDir(home), "hook-errors.log"),
483
+ cwd
484
+ );
485
+ } catch {
486
+ }
487
+ }
422
488
  function syncHealthContext(home) {
423
489
  if (!existsSync(join(home, ".outerlayer", "config.json"))) return null;
424
490
  const health = assessSyncHealth(readSyncStatus(home));
@@ -479,7 +545,7 @@ function clearHealFailureMarker(home, repoRoot) {
479
545
  }
480
546
  }
481
547
  function deadHooksAutoHealContext(cwd, home) {
482
- if (findGitRoot(cwd) === void 0) return null;
548
+ if (findGitDirs(cwd) === void 0) return null;
483
549
  const state = deadHooksState(cwd);
484
550
  if (!state.dead || state.repoRoot === void 0 || state.hooksDir === void 0) return null;
485
551
  const hooksDirLabel = sanitizeForContext(state.hooksDir);
@@ -510,41 +576,9 @@ var PIN_FILENAME = ".outerlayer-pin.json";
510
576
  function sourceCachePath(gitCommonDir) {
511
577
  return join(gitCommonDir, "outerlayer", "source.json");
512
578
  }
513
- function findGitRoot(cwd) {
514
- let dir = cwd;
515
- for (; ; ) {
516
- const gitPath = join(dir, ".git");
517
- let stat;
518
- try {
519
- stat = statSync(gitPath);
520
- } catch {
521
- stat = void 0;
522
- }
523
- if (stat?.isDirectory()) return { repoRoot: dir, gitCommonDir: gitPath };
524
- if (stat?.isFile()) {
525
- try {
526
- const content = readFileSync(gitPath, "utf8").trim();
527
- const match = /^gitdir:\s*(.+)$/.exec(content);
528
- if (match) {
529
- const gitdir = isAbsolute(match[1]) ? match[1] : join(dir, match[1]);
530
- try {
531
- const commondir = readFileSync(join(gitdir, "commondir"), "utf8").trim();
532
- return { repoRoot: dir, gitCommonDir: isAbsolute(commondir) ? commondir : join(gitdir, commondir) };
533
- } catch {
534
- return { repoRoot: dir, gitCommonDir: gitdir };
535
- }
536
- }
537
- } catch {
538
- }
539
- }
540
- const parent = dirname(dir);
541
- if (parent === dir) return void 0;
542
- dir = parent;
543
- }
544
- }
545
579
  function contextPossiblyGoverned(cwd, home = homeFromEnv()) {
546
580
  try {
547
- const found = findGitRoot(cwd);
581
+ const found = findGitDirs(cwd);
548
582
  if (found === void 0) return false;
549
583
  const { repoRoot, gitCommonDir } = found;
550
584
  if (existsSync(join(repoRoot, PIN_FILENAME))) return true;
@@ -566,8 +600,6 @@ function contextPossiblyGoverned(cwd, home = homeFromEnv()) {
566
600
  }
567
601
  async function runHookFast(event, home = homeFromEnv(), read = readStdin, env = process.env, spawnImpl = spawnDetached) {
568
602
  try {
569
- const dir = spoolDir(home);
570
- mkdirSync(dir, { recursive: true });
571
603
  const stdin = read();
572
604
  let payload = {};
573
605
  try {
@@ -576,6 +608,11 @@ async function runHookFast(event, home = homeFromEnv(), read = readStdin, env =
576
608
  payload = {};
577
609
  }
578
610
  const resolvedEvent = String(event ?? payload.hook_event_name ?? "unknown");
611
+ if (resolvedEvent === "PostToolUse" && (env.OUTERLAYER_WORK === void 0 || env.OUTERLAYER_JOB_DIR !== void 0)) {
612
+ return;
613
+ }
614
+ const dir = spoolDir(home);
615
+ mkdirSync(dir, { recursive: true });
579
616
  const record = {
580
617
  t: (/* @__PURE__ */ new Date()).toISOString(),
581
618
  event: resolvedEvent,
@@ -585,19 +622,23 @@ async function runHookFast(event, home = homeFromEnv(), read = readStdin, env =
585
622
  };
586
623
  appendFileSync(join(dir, "events.jsonl"), JSON.stringify(record) + "\n");
587
624
  markHookFired(resolvedEvent, home);
588
- maybeAutoSync(resolvedEvent, home, spawnImpl);
589
625
  const sessionCwd = typeof payload.cwd === "string" ? payload.cwd : process.cwd();
626
+ maybeAutoSync(resolvedEvent, home, spawnImpl, Date.now(), sessionCwd);
627
+ const hookSessionId = typeof payload.session_id === "string" ? payload.session_id : void 0;
628
+ await maybeRenewWorkLease(resolvedEvent, hookSessionId, home, env, spawnImpl, Date.now(), sessionCwd);
629
+ await handleWorkSessionEnd(resolvedEvent, hookSessionId, home, env, spawnImpl, sessionCwd);
590
630
  let materializeMessage;
591
631
  let deadHooksMessage;
592
632
  let workLaunchMessage;
593
633
  let hookErrorsMessage;
634
+ let renewalHookMessage;
594
635
  if (resolvedEvent === "SessionStart") {
595
636
  const hookErrorsBytes = fileSizeBytes(join(dir, "hook-errors.log"));
596
637
  const hookErrorsSeen = hookErrorsSeenBytes(home);
597
638
  recordHookErrorsSeen(home, hookErrorsBytes);
598
639
  if (contextPossiblyGoverned(sessionCwd, home)) {
599
640
  try {
600
- const { materializeContext: materialize } = await import('./context-materialize-6WKT3RBQ.js');
641
+ const { materializeContext: materialize } = await import('./context-materialize-G2FUFC72.js');
601
642
  const sessionId = typeof payload.session_id === "string" ? payload.session_id : "unknown";
602
643
  const result = await materialize({ cwd: sessionCwd, sessionId, home });
603
644
  materializeMessage = result.message;
@@ -612,20 +653,23 @@ async function runHookFast(event, home = homeFromEnv(), read = readStdin, env =
612
653
  }
613
654
  try {
614
655
  const sessionId = typeof payload.session_id === "string" ? payload.session_id : void 0;
615
- workLaunchMessage = await handleWorkLaunch(sessionId, home, env, spawnImpl);
656
+ workLaunchMessage = await handleWorkLaunch(sessionId, home, env, spawnImpl, sessionCwd);
616
657
  } catch (err) {
617
658
  logHookError(home, err);
618
659
  }
619
660
  if (workLaunchMessage === void 0) {
620
661
  hookErrorsMessage = hookErrorsContext(home, hookErrorsBytes, hookErrorsSeen) ?? void 0;
621
662
  }
663
+ if (env.OUTERLAYER_WORK !== void 0 && env.OUTERLAYER_JOB_DIR === void 0 && workLaunchMessage === void 0) {
664
+ renewalHookMessage = await missingRenewalHookContext(home, sessionCwd);
665
+ }
622
666
  }
623
667
  writeSessionStartContext(
624
668
  resolvedEvent,
625
669
  home,
626
670
  sessionCwd,
627
671
  (out) => process.stdout.write(out),
628
- [materializeMessage, deadHooksMessage, workLaunchMessage, hookErrorsMessage].filter(
672
+ [materializeMessage, deadHooksMessage, workLaunchMessage, hookErrorsMessage, renewalHookMessage].filter(
629
673
  (s) => s !== void 0
630
674
  )
631
675
  );
@@ -647,4 +691,4 @@ function logHookError(home, err) {
647
691
  }
648
692
  }
649
693
 
650
- export { AUTO_SYNC_DEBOUNCE_MS, SYNC_STALE_AFTER_MS, WORK_ADD_RETRIES, assessSyncHealth, checkInstalledCliStaleness, contextPossiblyGoverned, formatAgo, handleWorkLaunch, hookFiredMarkerPath, installedCliDistDir, maybeAutoSync, readSyncStatus, refreshCommand, runHookFast, sanitizeForContext, spoolDir, workspaceRootOf, writeSyncStatus };
694
+ export { AUTO_SYNC_DEBOUNCE_MS, SYNC_STALE_AFTER_MS, WORK_LEASE_RENEW_DEBOUNCE_MS, WORK_LINK_RETRIES, assessSyncHealth, checkInstalledCliStaleness, contextPossiblyGoverned, formatAgo, handleWorkLaunch, handleWorkSessionEnd, hookFiredMarkerPath, installedCliDistDir, maybeAutoSync, maybeRenewWorkLease, readSyncStatus, refreshCommand, runHookFast, sanitizeForContext, spoolDir, workspaceRootOf, writeSyncStatus };