@outerlayer/cli 0.33.0-next.20261022194605 → 0.33.0-next.20261023002325

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 (111) hide show
  1. package/README.md +5 -0
  2. package/dist/{agent-setup-32F2JJIL.js → agent-setup-55ZDEXCS.js} +6 -6
  3. package/dist/{bridge-BCG2EB7F.js → bridge-NBCXFTT4.js} +2 -2
  4. package/dist/{build-GKCVFHF4.js → build-G4GUF6LT.js} +4 -4
  5. package/dist/{build-disk-6QAXMA2J.js → build-disk-3GL3KKEB.js} +5 -5
  6. package/dist/build-info.json +1 -1
  7. package/dist/{builder-DPNHJXG3.js → builder-3CUKTVSY.js} +4 -4
  8. package/dist/{check-KD5PLAVL.js → check-64FD5G3X.js} +35 -37
  9. package/dist/{chunk-A33USDCE.js → chunk-2N67C6IV.js} +5 -4
  10. package/dist/{chunk-ZQOSIMKU.js → chunk-2WMZPJVE.js} +6 -3
  11. package/dist/{chunk-5BNWAIHN.js → chunk-3DCB3GOV.js} +41 -3
  12. package/dist/{chunk-UOFBHIOZ.js → chunk-57L2YAJA.js} +1 -1
  13. package/dist/{chunk-6NWS455T.js → chunk-5THSC6BD.js} +1 -1
  14. package/dist/{chunk-QL3LPZ67.js → chunk-6LBSAW6I.js} +1 -1
  15. package/dist/{chunk-WPGBDY73.js → chunk-6RKD7YZ6.js} +1 -1
  16. package/dist/{chunk-6YHUMNUB.js → chunk-6Z4SZHV2.js} +4 -3
  17. package/dist/{chunk-DETKDTNL.js → chunk-AU346ENF.js} +3 -2
  18. package/dist/chunk-B2JURP6A.js +41 -0
  19. package/dist/{chunk-BCCI32ME.js → chunk-BALIE3BA.js} +36 -7
  20. package/dist/{chunk-BY36DVJV.js → chunk-BKADJZ7F.js} +3 -2
  21. package/dist/{chunk-RXUZD7DC.js → chunk-CANYZTD5.js} +39 -22
  22. package/dist/{chunk-IYH4R4EZ.js → chunk-DGI66PGY.js} +46 -21
  23. package/dist/{chunk-GN2R5Z7G.js → chunk-DXJTBU7A.js} +3 -3
  24. package/dist/{chunk-EYW2ZRDL.js → chunk-EUVE2EAE.js} +53 -21
  25. package/dist/{chunk-DDS2ISML.js → chunk-F5UL23I2.js} +1 -1
  26. package/dist/{chunk-43PV5KDB.js → chunk-GFVDC5S3.js} +3 -3
  27. package/dist/{chunk-JEKENLLA.js → chunk-GH246BGV.js} +1 -1
  28. package/dist/{chunk-W5DOK7BL.js → chunk-HVRQQOMH.js} +3 -3
  29. package/dist/{chunk-6IKSUAIA.js → chunk-HXA5GIHK.js} +61 -3
  30. package/dist/{chunk-2QT4JUW3.js → chunk-IP7BIBXJ.js} +1 -35
  31. package/dist/{chunk-KLXWS5Z7.js → chunk-JPG43G6Y.js} +3 -3
  32. package/dist/{chunk-SVXFSQRD.js → chunk-JRZCRIEO.js} +1058 -641
  33. package/dist/{chunk-LWTBE5J6.js → chunk-L26V6ILJ.js} +1 -1
  34. package/dist/{chunk-ESEUG62R.js → chunk-LJUIG5K4.js} +14 -9
  35. package/dist/{chunk-ZRRUWNJS.js → chunk-LYE3KB6L.js} +3 -3
  36. package/dist/{chunk-SK4TWCN3.js → chunk-MZBQTVFG.js} +1 -1
  37. package/dist/{chunk-YKYCE4HY.js → chunk-MZYOUIY5.js} +1 -1
  38. package/dist/{chunk-OWDSO3PE.js → chunk-NBZ7XBT6.js} +1 -1
  39. package/dist/{chunk-6C2YWM6N.js → chunk-OOCAF3ID.js} +1 -1
  40. package/dist/{chunk-AGZNCIIJ.js → chunk-PA6CK6WQ.js} +1 -1
  41. package/dist/{chunk-JR4TZLG6.js → chunk-Q2CMEQV7.js} +2 -2
  42. package/dist/{chunk-V3MMJT4T.js → chunk-QFQC5K4J.js} +6 -113
  43. package/dist/{chunk-WB7LPDXR.js → chunk-QPWFVE3X.js} +1 -1
  44. package/dist/{chunk-AA6LYZC4.js → chunk-SOI6K5DY.js} +1 -1
  45. package/dist/{chunk-4XQ6F3HD.js → chunk-SVDOA4W2.js} +1 -1
  46. package/dist/{chunk-RAHE2AYU.js → chunk-T5REPMNL.js} +49 -19
  47. package/dist/{chunk-6KLPC4U7.js → chunk-ULBNTSAD.js} +3 -2
  48. package/dist/{chunk-TDVG6MCO.js → chunk-VT4TTJPG.js} +6 -5
  49. package/dist/{chunk-FAZDYI2D.js → chunk-XL2XWWU7.js} +3 -2
  50. package/dist/{chunk-P5FC7VUO.js → chunk-XWFSAOC7.js} +2 -2
  51. package/dist/{chunk-CUBIZBMF.js → chunk-YERR22SY.js} +3 -3
  52. package/dist/{chunk-GWDS42JC.js → chunk-Z5IW4DHH.js} +1 -1
  53. package/dist/{claude-launcher-B4L7ELIF.js → claude-launcher-NTYHJUJM.js} +1 -1
  54. package/dist/{cli-3ZPYMRUZ.js → cli-WKRURGHC.js} +126 -102
  55. package/dist/{command-YLXBWLAR.js → command-WG54AUHK.js} +23 -23
  56. package/dist/{config-DUY2PT7K.js → config-LZSFW2O3.js} +2 -3
  57. package/dist/{connect-cmd-ADRPR6ES.js → connect-cmd-P5GASVAF.js} +5 -5
  58. package/dist/{container-start-G363VW47.js → container-start-DQKFQ3CL.js} +21 -23
  59. package/dist/context-show-cmd-3EPJ7CJC.js +115 -0
  60. package/dist/{control-plane-launch-PSFYCKYH.js → control-plane-launch-A3YCHQNQ.js} +5 -5
  61. package/dist/{docker-GGRJHHBP.js → docker-4ERXWTRW.js} +4 -4
  62. package/dist/{doctor-N36BHNH3.js → doctor-GRCEYJXA.js} +24 -26
  63. package/dist/{emit-artifact-cmd-DX6RNKGK.js → emit-artifact-cmd-FDPJKGOO.js} +11 -10
  64. package/dist/{emit-criteria-cmd-D7OR356Y.js → emit-criteria-cmd-3SVGCMJN.js} +8 -7
  65. package/dist/{emit-demo-cmd-KSIAJ25G.js → emit-demo-cmd-JSVI56WY.js} +11 -10
  66. package/dist/{emit-finding-cmd-GEPRJ6KO.js → emit-finding-cmd-TLJWBGQE.js} +8 -7
  67. package/dist/{emit-result-cmd-TSUOZSYJ.js → emit-result-cmd-CJNVDV5V.js} +10 -9
  68. package/dist/{emit-step-cmd-CC6MUJ2S.js → emit-step-cmd-347CZO7Y.js} +8 -7
  69. package/dist/{exec-client-KLI262IX.js → exec-client-7PT4W7JR.js} +3 -3
  70. package/dist/{findings-cmd-7I72XX2H.js → findings-cmd-LHTYEHYB.js} +8 -7
  71. package/dist/{fleet-readiness-EZAGL32M.js → fleet-readiness-KGR5AC2J.js} +5 -5
  72. package/dist/{governing-source-G2I3ZT6M.js → governing-source-JZQZUTMA.js} +10 -9
  73. package/dist/{guest-init-ZJIE6MU3.js → guest-init-J3F3AEEY.js} +4 -4
  74. package/dist/{hook-fast-6GE5LEJI.js → hook-fast-6WDMNZG5.js} +1 -1
  75. package/dist/{pending-I5TY6SQH.js → host-key-UERIQRE6.js} +3 -3
  76. package/dist/{image-tag-MORUQ4LF.js → image-tag-ADSLWXBA.js} +3 -3
  77. package/dist/index.js +4 -4
  78. package/dist/{init-YMXM4D7K.js → init-OKJAI77M.js} +20 -22
  79. package/dist/{init-COSYLOVV.js → init-WNO4NAO7.js} +20 -22
  80. package/dist/{init-cmd-SWFTXZC7.js → init-cmd-PFW4XTG7.js} +11 -10
  81. package/dist/{init-update-DWZMXIBG.js → init-update-X7YLZL6H.js} +8 -8
  82. package/dist/{install-NLVYISAV.js → install-GQUCHIGE.js} +4 -5
  83. package/dist/{install-cmd-HFGINYEE.js → install-cmd-FV7IZ7XF.js} +5 -5
  84. package/dist/{logs-QSKJ4G6M.js → logs-HI46FO6Z.js} +2 -2
  85. package/dist/{loop-KNITSCYU.js → loop-2SITCQ6H.js} +35 -37
  86. package/dist/{machine-3YU7HXUQ.js → machine-YHBCNRUO.js} +20 -18
  87. package/dist/{mcp-serve-cmd-DQSO6MOL.js → mcp-serve-cmd-7ABBV2QE.js} +4 -4
  88. package/dist/{paths-KHDFSBEI.js → paths-7HVTDE6J.js} +2 -2
  89. package/dist/{host-key-REZADWAM.js → pending-5HZACM2V.js} +3 -3
  90. package/dist/{pidfile-BSY63HIC.js → pidfile-5UDLYPMC.js} +3 -3
  91. package/dist/{record-7CNTGRLD.js → record-PPZEXAVA.js} +3 -3
  92. package/dist/{runner-env-26NLQI35.js → runner-env-QYE7KZFP.js} +5 -6
  93. package/dist/{runner-identity-WGH73DTV.js → runner-identity-FIHOECSH.js} +4 -4
  94. package/dist/{runner-key-2QWPUKQM.js → runner-key-YUKU2MWK.js} +20 -22
  95. package/dist/{session-sender-CMDAHNLE.js → session-sender-7B3ZDWMC.js} +11 -10
  96. package/dist/{spec-cmd-WFS64ZCI.js → spec-cmd-Q26NE22H.js} +9 -8
  97. package/dist/{status-X3RGH6MZ.js → status-VBQJMFEX.js} +27 -25
  98. package/dist/{sync-cmd-XCGNHOGU.js → sync-cmd-SSUYTMLJ.js} +10 -9
  99. package/dist/{watch-6O6LTIBM.js → watch-L5NCO46E.js} +10 -9
  100. package/dist/{work-claim-cmd-ABYB5RGL.js → work-claim-cmd-MFND6Z4S.js} +12 -12
  101. package/dist/{work-cmd-H7LLCT2W.js → work-cmd-W7WEHMQJ.js} +8 -7
  102. package/dist/{work-comment-cmd-QW745J2A.js → work-comment-cmd-SSUOGVDD.js} +8 -7
  103. package/dist/{work-logs-cmd-GMPGBFLO.js → work-logs-cmd-WPMWMDX6.js} +8 -7
  104. package/dist/{work-open-pr-cmd-75XO4DL2.js → work-open-pr-cmd-NO5YLOXD.js} +9 -8
  105. package/dist/{work-pr-cmd-KBNFVRB4.js → work-pr-cmd-37B5KECR.js} +8 -7
  106. package/dist/{work-stop-cmd-C65WG6NY.js → work-stop-cmd-3BJLXUJ3.js} +8 -7
  107. package/package.json +1 -1
  108. package/skill-pack/maintained/outerlayer-build/SKILL.md +4 -2
  109. package/dist/chunk-FMH6LSUE.js +0 -107
  110. package/dist/chunk-JMZZLICN.js +0 -146
  111. package/dist/chunk-UXYLWVTQ.js +0 -43
@@ -1,30 +1,30 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { releaseLease, isUnfinished, attemptNote, setStage, jobEnv, runHook, describeHookEnd, provisionMicroVm, deliverCommitHooks, provisionProcess, provisionEnvironment, readProvisionOut, resolveHostBuild, workdirProblem, listenOnBroker, hostEnvironment, deliverExecMaven, runWithSpawn, hostCommandEnvironment, execArgv, MICROVM_COMMAND_DIR, commandLogOffset, startMicroVmCommand, microVmCommandLine, runCommand, execCommandLine, startSender, startHostServices, finishJob, sampleGuest, foldSample, isContainerTracked, isMicroVmTracked, probeMicroVmCommand, probeCommand, appendCommandLog, judgeProbe, EXIT_CODE_FILE, isTracked, isGroupAlive, outcomeFromExitCode, isTimedOut, readCpuUsec, isIdle, stopOrphanedMicroVms, unfinishedJobs, listUnreadableJobs, listAdoptableJobs, retryFailedReleases, recoverLostJobs, GUEST_USAGE_INTERVAL_MS, hookLimitsFor, AttemptLogBook, microVmOomKills, needsRenew, renewLease, RENEW_INTERVAL_SECONDS, listTrackedJobs, restartSender, serveLease, vmAlive, writeGuestGhConfig, ALREADY_RELEASED, inTeardown } from './chunk-IYH4R4EZ.js';
3
+ import { releaseLease, isUnfinished, attemptNote, setStage, jobEnv, runHook, describeHookEnd, provisionMicroVm, deliverCommitHooks, provisionProcess, provisionEnvironment, readProvisionOut, resolveHostBuild, workdirProblem, listenOnBroker, hostEnvironment, deliverExecMaven, runWithSpawn, hostCommandEnvironment, execArgv, MICROVM_COMMAND_DIR, commandLogOffset, startMicroVmCommand, microVmCommandLine, runCommand, execCommandLine, startSender, startHostServices, finishJob, sampleGuest, foldSample, isContainerTracked, isMicroVmTracked, probeMicroVmCommand, probeCommand, appendCommandLog, judgeProbe, EXIT_CODE_FILE, isTracked, isGroupAlive, outcomeFromExitCode, isTimedOut, readCpuUsec, isIdle, stopOrphanedMicroVms, unfinishedJobs, listUnreadableJobs, listAdoptableJobs, retryFailedReleases, recoverLostJobs, GUEST_USAGE_INTERVAL_MS, hookLimitsFor, AttemptLogBook, microVmOomKills, needsRenew, renewLease, RENEW_INTERVAL_SECONDS, listTrackedJobs, restartSender, serveLease, vmAlive, writeGuestGhConfig, ALREADY_RELEASED, inTeardown } from './chunk-DGI66PGY.js';
4
4
  import { JOB_STATE_FORMAT, readsJobState, jobStateFormatOf } from './chunk-ZVB57WI6.js';
5
- import { readHousekeepingRecord, writeHousekeepingRecord } from './chunk-UOFBHIOZ.js';
5
+ import { readHousekeepingRecord, writeHousekeepingRecord } from './chunk-57L2YAJA.js';
6
6
  import { decideInstalledSwitch } from './chunk-3JVYMD4G.js';
7
7
  import { fetchVersionMeta, npmVersion, npmSupportsProvenance, fetchTarballDigest, fetchProvenance, installVersion, auditSignatures } from './chunk-E7R2GIAW.js';
8
- import { fitImageBuildMemory } from './chunk-6C2YWM6N.js';
9
- import { RUNNER_PROTOCOL } from './chunk-YKYCE4HY.js';
10
- import { writePendingUpdate } from './chunk-JEKENLLA.js';
11
- import { currentSkillCommand, formerSkillProblem, realBlockedProbes, checkBlocked } from './chunk-V3MMJT4T.js';
12
- import { writeMarker, readMarker, currentVersion, removeMarker, entryIn, versionDir, startedThroughCurrent, switchCurrent, isInLayout, cleanVersions, stagingDir } from './chunk-OWDSO3PE.js';
8
+ import { fitImageBuildMemory } from './chunk-OOCAF3ID.js';
9
+ import { RUNNER_PROTOCOL } from './chunk-MZYOUIY5.js';
10
+ import { writePendingUpdate } from './chunk-GH246BGV.js';
11
+ import { realBlockedProbes, checkBlocked } from './chunk-QFQC5K4J.js';
12
+ import { writeMarker, readMarker, currentVersion, removeMarker, entryIn, versionDir, startedThroughCurrent, switchCurrent, isInLayout, cleanVersions, stagingDir } from './chunk-NBZ7XBT6.js';
13
13
  import { RepoFilter } from './chunk-TBT347UY.js';
14
- import { leaseTimeLeftMs, createContainerRuntime, withTunnelLog, LEASE_SECONDS, provisionContainer, leaseExpiresAtMs, deliverContainerHooks, lifecycleSteps, lifecycleFailureReason, prepareBranch, containerCommandExec, setUpRunnerCgroup, sweepImageBuilders, measureDisk, parseCpuList, ensureTunnel, keepGhConfigCurrent, filesAreCopied, gitRemoteFor, startServicesFor, createLeaseChannel } from './chunk-SVXFSQRD.js';
15
- import { claimPidFile, writePidFile, readPidFile, releasePidFile } from './chunk-DDS2ISML.js';
14
+ import { leaseTimeLeftMs, createContainerRuntime, withTunnelLog, LEASE_SECONDS, needsBuildSkill, provisionContainer, leaseExpiresAtMs, deliverContainerHooks, lifecycleSteps, lifecycleFailureReason, decideHostBuildSkill, prepareBranch, currentSkillCommand, formerSkillProblem, containerCommandExec, setUpRunnerCgroup, sweepImageBuilders, measureDisk, parseCpuList, ensureTunnel, keepGhConfigCurrent, filesAreCopied, gitRemoteFor, startServicesFor, createLeaseChannel } from './chunk-JRZCRIEO.js';
15
+ import { claimPidFile, writePidFile, readPidFile, releasePidFile } from './chunk-F5UL23I2.js';
16
16
  import { startTimeOf, isSameProcess } from './chunk-JBJTC3UU.js';
17
- import { describeCallFailure, retrySend, shortClaim, relativeToRunner, formatDuration, BuildTokens, classifyRefusal, refusalCode, createRunnerLog, formatClock } from './chunk-RAHE2AYU.js';
18
- import { tagToPull, pullInstruction, imageTag, writeUpdateStatus } from './chunk-SK4TWCN3.js';
17
+ import { describeCallFailure, retrySend, shortClaim, relativeToRunner, formatDuration, resolveGoverningSource, BuildTokens, classifyRefusal, refusalCode, createRunnerLog, formatClock } from './chunk-T5REPMNL.js';
18
+ import { tagToPull, pullInstruction, imageTag, writeUpdateStatus } from './chunk-MZBQTVFG.js';
19
19
  import { isVersion, compareVersions, satisfiesRange } from './chunk-TQMI335S.js';
20
20
  import { freeBytes, formatBytes } from './chunk-YYYRBYWG.js';
21
- import { writeJobFile, ensureRunnerIdentity, readJobFile, builderName, runnerLabelValue, ensureFailureCount, builderSpec, ensureBuilder, spawnRun, BUILD_LABEL, RUNNER_LABEL, readJobFileChecked } from './chunk-43PV5KDB.js';
22
- import { isBuiltinContainer, isBuiltinVm, isBuiltinProcess, loadRunnerConfig, checkHooks, builtinKind, DEFAULT_UPDATE_MAX_WAIT_HOURS } from './chunk-5BNWAIHN.js';
21
+ import { writeJobFile, ensureRunnerIdentity, readJobFile, builderName, runnerLabelValue, ensureFailureCount, builderSpec, ensureBuilder, spawnRun, BUILD_LABEL, RUNNER_LABEL, readJobFileChecked } from './chunk-GFVDC5S3.js';
22
+ import { isBuiltinContainer, isBuiltinVm, isBuiltinProcess, loadRunnerConfig, checkHooks, builtinKind, DEFAULT_UPDATE_MAX_WAIT_HOURS } from './chunk-3DCB3GOV.js';
23
23
  import { exceedsDisk } from './chunk-YJLHUKYS.js';
24
- import { isSignatureRefusal, WorkCommandError, getJson, postJson } from './chunk-TDVG6MCO.js';
25
- import { loadHostKey, ensureHostKey, signerFor } from './chunk-AA6LYZC4.js';
26
- import { RUNNER_DIR_MODE, runnerDir, buildDir, attemptStamp, jobDir, RUNNER_FILE_MODE, jobsDir, pidFilePath, spoolDir, imagesDir, rootfsDir, builderCacheDiskPath } from './chunk-AGZNCIIJ.js';
27
- import { parseClaimIdentity, parseClaimedRepositories, parseUnreachable, repositoriesOf, primaryOf, sharedUserEnvironment, JOB_MOUNT, takeClaudeCredential, heldClaudeCredential, currentClaudeCredential } from './chunk-BCCI32ME.js';
24
+ import { isSignatureRefusal, WorkCommandError, getJson, postJson } from './chunk-VT4TTJPG.js';
25
+ import { loadHostKey, ensureHostKey, signerFor } from './chunk-SOI6K5DY.js';
26
+ import { RUNNER_DIR_MODE, runnerDir, buildDir, attemptStamp, jobDir, RUNNER_FILE_MODE, jobsDir, pidFilePath, spoolDir, imagesDir, rootfsDir, builderCacheDiskPath } from './chunk-PA6CK6WQ.js';
27
+ import { parseClaimIdentity, parseClaimedRepositories, parseUnreachable, repositoriesOf, primaryOf, sharedUserEnvironment, JOB_MOUNT, takeClaudeCredential, heldClaudeCredential, currentClaudeCredential } from './chunk-BALIE3BA.js';
28
28
  import { resolveVersion } from './chunk-RA3O54FC.js';
29
29
  import { fdName } from './chunk-HACGUL52.js';
30
30
  import { COMMAND_LOST_REASON, CONTAINER_STOPPED_REASON } from './chunk-MESOOLF4.js';
@@ -1837,7 +1837,7 @@ var CLAIM_REFUSAL_CODES = new Set(
1837
1837
  "pull_request_from_fork pull_request_on_default_branch pull_request_ambiguous pull_request_repository_not_connected repository_not_reachable branch_claimed_elsewhere".split(" ")
1838
1838
  );
1839
1839
  async function tryClaimAndStart(state, item, queue) {
1840
- const { postJson: postJson2 } = await import('./work-cmd-H7LLCT2W.js');
1840
+ const { postJson: postJson2 } = await import('./work-cmd-W7WEHMQJ.js');
1841
1841
  const log = logOf(state);
1842
1842
  const hostKey = await loadHostKey(state.config.configPath);
1843
1843
  const claim = await retrySend(
@@ -2070,6 +2070,7 @@ async function startJob(state, item, queue, claimId, itemKey, branch, identity,
2070
2070
  log.line(`${tag} provision started`);
2071
2071
  const provisionStartedMs = nowOf(state).getTime();
2072
2072
  const processMode = isBuiltinProcess(state.config.hooks.provision);
2073
+ const requireBuildSkill = needsBuildSkill(queue, state.config.commands[queue]);
2073
2074
  const cliVersion = state.deps.cliVersion ?? resolveVersion();
2074
2075
  let workdir;
2075
2076
  let cgroup;
@@ -2094,7 +2095,8 @@ async function startJob(state, item, queue, claimId, itemKey, branch, identity,
2094
2095
  deadlineMs: startedAt.getTime() + state.config.timeLimitMinutes * 6e4,
2095
2096
  fetchImpl: state.deps.fetchImpl,
2096
2097
  now: state.deps.now,
2097
- leaseExpiryMs: () => leaseExpiresAtMs(active.job)
2098
+ leaseExpiryMs: () => leaseExpiresAtMs(active.job),
2099
+ requireBuildSkill
2098
2100
  }).catch((err) => ({ ok: false, reason: `provision failed: ${describeCallFailure(err)}`, aborted: false }));
2099
2101
  const provisionTook = formatDuration(nowOf(state).getTime() - provisionStartedMs);
2100
2102
  if (active.ending) return;
@@ -2133,7 +2135,8 @@ async function startJob(state, item, queue, claimId, itemKey, branch, identity,
2133
2135
  deadlineMs: startedAt.getTime() + state.config.timeLimitMinutes * 6e4,
2134
2136
  fetchImpl: state.deps.fetchImpl,
2135
2137
  now: state.deps.now,
2136
- leaseTimeLeftMs: leaseTimeLeftFor(state, active)
2138
+ leaseTimeLeftMs: leaseTimeLeftFor(state, active),
2139
+ requireBuildSkill
2137
2140
  }).catch((err) => ({ ok: false, reason: `provision failed: ${describeCallFailure(err)}`, aborted: false }));
2138
2141
  const provisionTook = formatDuration(nowOf(state).getTime() - provisionStartedMs);
2139
2142
  if (active.ending) return;
@@ -2318,6 +2321,20 @@ async function startJob(state, item, queue, claimId, itemKey, branch, identity,
2318
2321
  job = { ...active.job, workdir, cgroup };
2319
2322
  active.job = job;
2320
2323
  writeJobFile(jobFilePath, job);
2324
+ const skillDecision = await decideHostBuildSkill({
2325
+ requireBuildSkill,
2326
+ containerMode,
2327
+ vmMode,
2328
+ workdir,
2329
+ repository: primary?.repository,
2330
+ lookup: (repository) => resolveGoverningSource({ config: state.config, repository, fetchImpl: state.deps.fetchImpl }).catch(() => void 0)
2331
+ });
2332
+ if (skillDecision.kind === "refuse") {
2333
+ log.error(`${tag} ${skillDecision.reason} \xB7 ending job as failed`);
2334
+ await endJob(state, active, "failed", { stage: "provision", reason: skillDecision.reason });
2335
+ return;
2336
+ }
2337
+ if (skillDecision.kind === "warn") log.line(`${tag} warning: the clone has no \`build\` skill; the control plane's context may deliver one, so the command starts`);
2321
2338
  if (!containerMode && !vmMode) {
2322
2339
  if (existsSync(join(workdir, ".git"))) {
2323
2340
  try {
@@ -2492,7 +2509,7 @@ async function startHostBuild(state, active, repository) {
2492
2509
  const runtime = runtimeOf(state);
2493
2510
  let failed2;
2494
2511
  try {
2495
- await startHostServices({ runtime, config: state.config, build, jobDir: active.dirPath, itemKey: active.job.itemKey, process: false });
2512
+ await startHostServices({ runtime, config: state.config, build, jobDir: active.dirPath, itemKey: active.job.itemKey, process: false, routeLog: (line) => logOf(state).line(`#${active.job.item} ${line}`) });
2496
2513
  } catch (err) {
2497
2514
  failed2 = describeCallFailure(err);
2498
2515
  logOf(state).error(`#${active.job.item} the tunnel and destination servers could not start: ${failed2} \xB7 continuing`);
@@ -3037,7 +3054,7 @@ async function start(configPath, deps = { fetchImpl: fetch }) {
3037
3054
  check: update.check ? () => update.check(configPath) : async () => {
3038
3055
  const held = heldClaudeCredential();
3039
3056
  const env = held === void 0 ? process.env : { ...process.env, [held.variable]: held.value };
3040
- return (await import('./check-KD5PLAVL.js')).runRunnerCheck(configPath, { fetchImpl: deps.fetchImpl, env });
3057
+ return (await import('./check-64FD5G3X.js')).runRunnerCheck(configPath, { fetchImpl: deps.fetchImpl, env });
3041
3058
  },
3042
3059
  now: () => (deps.now ?? (() => /* @__PURE__ */ new Date()))().getTime(),
3043
3060
  log
@@ -1,28 +1,28 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
3
  import { readsJobState, READ_JOB_STATE_FORMATS, jobStateFormatOf } from './chunk-ZVB57WI6.js';
4
- import { DOCKERD_LOG, HELPER_PATH, HELPER_RECORD } from './chunk-W5DOK7BL.js';
5
- import { writeDockerClientConfig } from './chunk-QL3LPZ67.js';
4
+ import { DOCKERD_LOG, HELPER_PATH, HELPER_RECORD } from './chunk-HVRQQOMH.js';
5
+ import { writeDockerClientConfig } from './chunk-6LBSAW6I.js';
6
6
  import { zodProblem } from './chunk-I3LTIAOR.js';
7
- import { senderPidfile } from './chunk-JR4TZLG6.js';
8
- import { installScrubContext } from './chunk-A33USDCE.js';
9
- import { ADDED_USER, shellQuote, GH_CONFIG_YML, ghHostsYml, AssetError, obtainImage, ensureRootfs, makeBuildsDirPrivate, gitRemoteFor, startServicesFor, createLeaseChannel, createBuildDisk, machineConfig, startJailedInto, resolveAgentUser, AgentUserError, runBuildSteps, LEASE_SECONDS, createContainerRuntime, stopContainer, cleanupContainer, outOfMemoryReason, containerSenderCommand, signalInContainer, syncInContainer, copyTranscriptsFromContainer, MANAGED_UNJAILED_REASON, senderAliveScript, helperFirecrackerNote, isLiteralAddress, stopJailed, deleteBuildDisk, startCheckContainer, lifecycleSteps, lifecycleFailureReason, writeEvalInput, DeliveryFailure, EVAL_INPUT_NAME, copyTranscripts, senderSignalScript, containerJudgeEnvironment, ROOT_DISK_ID_PREFIX, copyJudgeTree } from './chunk-SVXFSQRD.js';
10
- import { readBranchHead, fetchCommit, diffBetween } from './chunk-KLXWS5Z7.js';
7
+ import { senderPidfile } from './chunk-Q2CMEQV7.js';
8
+ import { installScrubContext } from './chunk-2N67C6IV.js';
9
+ import { ADDED_USER, shellQuote, GH_CONFIG_YML, ghHostsYml, AssetError, obtainImage, ensureRootfs, makeBuildsDirPrivate, gitRemoteFor, startServicesFor, createLeaseChannel, createBuildDisk, machineConfig, startJailedInto, resolveAgentUser, AgentUserError, runBuildSteps, LEASE_SECONDS, createContainerRuntime, stopContainer, cleanupContainer, outOfMemoryReason, containerSenderCommand, signalInContainer, syncInContainer, copyTranscriptsFromContainer, MANAGED_UNJAILED_REASON, senderAliveScript, helperFirecrackerNote, isLiteralAddress, stopJailed, deleteBuildDisk, startCheckContainer, lifecycleSteps, lifecycleFailureReason, writeEvalInput, DeliveryFailure, EVAL_INPUT_NAME, copyTranscripts, senderSignalScript, containerJudgeEnvironment, ROOT_DISK_ID_PREFIX, copyJudgeTree } from './chunk-JRZCRIEO.js';
10
+ import { readBranchHead, fetchCommit, diffBetween } from './chunk-JPG43G6Y.js';
11
11
  import { isSameProcess, startTimeOf } from './chunk-JBJTC3UU.js';
12
- import { waitForAgent, vmExecArgs } from './chunk-6NWS455T.js';
13
- import { socketPathProblem, vsockLinks, LEASE_LINK, linkVsockSockets } from './chunk-LWTBE5J6.js';
14
- import { describeCallFailure, resolveGoverningSource, refusalCode, removeStagedContext, stageGovernedContext, pinnedSourceOf, commandWithShim, logStamp, createRunnerLog, removeKeptContext, formatDuration, retrySend, formatClock, WORKFLOW_PERMISSION_REASON, keptContextTree } from './chunk-RAHE2AYU.js';
15
- import { HASH_ARGV, parseProgramHash, JUDGE_PROGRAM, writeJobFile, readJobFile, childEnvironment, withAnswerProtocol, judgeCommand, MAX_REPORT_BYTES, JUDGE_MAX_TURNS, JUDGE_DIR, COMMAND_DIR, MAX_ITEMS_BYTES } from './chunk-43PV5KDB.js';
12
+ import { waitForAgent, vmExecArgs } from './chunk-5THSC6BD.js';
13
+ import { socketPathProblem, vsockLinks, LEASE_LINK, linkVsockSockets } from './chunk-L26V6ILJ.js';
14
+ import { describeCallFailure, resolveGoverningSource, prefetchGovernedContext, refusalCode, removeStagedContext, stageGovernedContext, pinnedSourceOf, commandWithShim, logStamp, createRunnerLog, removeKeptContext, formatDuration, retrySend, formatClock, WORKFLOW_PERMISSION_REASON, keptContextTree } from './chunk-T5REPMNL.js';
15
+ import { HASH_ARGV, parseProgramHash, JUDGE_PROGRAM, writeJobFile, readJobFile, childEnvironment, withAnswerProtocol, judgeCommand, MAX_REPORT_BYTES, JUDGE_MAX_TURNS, JUDGE_DIR, COMMAND_DIR, MAX_ITEMS_BYTES } from './chunk-GFVDC5S3.js';
16
16
  import { CLAUDE_CODE_VERSION, FIRECRACKER_VERSION } from './chunk-TGHBOXKJ.js';
17
- import { imageBuildOf, isBuiltinContainer, isBuiltinProcess, isBuiltinVm, DEFAULT_CHECK_TIME_LIMIT_MINUTES } from './chunk-5BNWAIHN.js';
17
+ import { imageBuildOf, isBuiltinContainer, isBuiltinProcess, isBuiltinVm, DEFAULT_CHECK_TIME_LIMIT_MINUTES } from './chunk-3DCB3GOV.js';
18
18
  import { parseSize } from './chunk-YJLHUKYS.js';
19
- import { WorkCommandError, postJson, isSignatureRefusal, getJson } from './chunk-TDVG6MCO.js';
19
+ import { WorkCommandError, postJson, isSignatureRefusal, getJson } from './chunk-VT4TTJPG.js';
20
20
  import { planArtifactUpload } from './chunk-EWVYQLD3.js';
21
21
  import { scrubText } from './chunk-5DNCFOXA.js';
22
22
  import { readCloudConfig } from './chunk-PJDQPF5N.js';
23
- import { signerFor } from './chunk-AA6LYZC4.js';
24
- import { RUNNER_FILE_MODE, runnerDir, buildDir, vsockPath, jobConsolePath } from './chunk-AGZNCIIJ.js';
25
- import { JOB_MOUNT, claudeCredential, repositoriesOf, primaryOf, buildEnvironment, CHECKOUT_DIR, parseIsolation, proxyEnvironment, withProxyWarningHidden, containerLocalAddress, destinationEnvironment, CLAUDE_CREDENTIAL_VARIABLES, builtInEnvironment, withHooksPath, startBuildServices, BUILT_IN_NAMES, AGENT_CREDENTIAL_MISSING, sharedUserEnvironment, headerVariables, authorEnvironment, withTunnelRecord, commitIdentityRecord, buildMavenSettingsXml, mavenSettingsXml, namesGlobalSettings, MAVEN_NO_PROXY_NOTE, mavenArgs, MAVEN_SPACE_NOTE, writeMavenSettings, RELAY_PORT, repositoryPath, lifecycleWorkdir, CHECK_ITEMS_FILE, MAVEN_SETTINGS_FILE, currentClaudeCredential, removedClaudeCredentialValues, checkEnvironment, EVAL_INPUT_DIR } from './chunk-BCCI32ME.js';
23
+ import { signerFor } from './chunk-SOI6K5DY.js';
24
+ import { RUNNER_FILE_MODE, runnerDir, buildDir, vsockPath, jobConsolePath } from './chunk-PA6CK6WQ.js';
25
+ import { JOB_MOUNT, claudeCredential, repositoriesOf, primaryOf, buildEnvironment, CHECKOUT_DIR, parseIsolation, proxyEnvironment, withProxyWarningHidden, containerLocalAddress, destinationEnvironment, CLAUDE_CREDENTIAL_VARIABLES, builtInEnvironment, withHooksPath, startBuildServices, BUILT_IN_NAMES, AGENT_CREDENTIAL_MISSING, sharedUserEnvironment, headerVariables, authorEnvironment, withTunnelRecord, commitIdentityRecord, buildMavenSettingsXml, mavenSettingsXml, namesGlobalSettings, MAVEN_NO_PROXY_NOTE, mavenArgs, MAVEN_SPACE_NOTE, writeMavenSettings, RELAY_PORT, repositoryPath, lifecycleWorkdir, CHECK_ITEMS_FILE, MAVEN_SETTINGS_FILE, currentClaudeCredential, removedClaudeCredentialValues, checkEnvironment, EVAL_INPUT_DIR } from './chunk-BALIE3BA.js';
26
26
  import { resolvePackRoot } from './chunk-G63KT5I5.js';
27
27
  import { MAINTAINED_SKILLS } from './chunk-CDDED64E.js';
28
28
  import { resolveVersion } from './chunk-RA3O54FC.js';
@@ -314,6 +314,19 @@ async function provisionMicroVm(input) {
314
314
  const governing = await resolveGoverningSource({ config, repository, fetchImpl: input.fetchImpl });
315
315
  if (!governing.ok) return fail(governing.reason);
316
316
  const governingSource = governing.source;
317
+ const controlPlaneUrl = (controlPlane) => runtime.remoteFor?.(controlPlane) ?? `${runtime.github.gitUrl}/${controlPlane}.git`;
318
+ if (governingSource.kind === "governed") {
319
+ const unfetched = await prefetchGovernedContext({
320
+ configPath: config.configPath,
321
+ repository,
322
+ source: governingSource,
323
+ controlPlaneUrl,
324
+ controlPlaneToken: () => tokens.controlPlane(),
325
+ log,
326
+ tag
327
+ });
328
+ if (unfetched !== void 0) return fail(unfetched);
329
+ }
317
330
  const limits = {
318
331
  cpus: config.build?.cpus ?? DEFAULT_CPUS,
319
332
  memoryBytes: buildMemoryBytes(config),
@@ -429,7 +442,7 @@ async function provisionMicroVm(input) {
429
442
  let services;
430
443
  try {
431
444
  const gitRemote = gitRemoteFor(runtime, { repositories, tokens, buildDir: buildDir2, log: (line) => log.line(`${tag} ${line}`) });
432
- services = await startServicesFor(runtime, config, buildDir2, jobDir, itemKey, true, gitRemote);
445
+ services = await startServicesFor(runtime, config, buildDir2, jobDir, itemKey, true, gitRemote, "socket", void 0, void 0, (line) => log.line(`${tag} ${line}`));
433
446
  runtime.tunnels.set(buildId, services);
434
447
  } catch (err) {
435
448
  return bail(`the tunnel could not start: ${describeCallFailure(err)}`);
@@ -599,7 +612,7 @@ async function provisionMicroVm(input) {
599
612
  buildId,
600
613
  buildDir: buildDir2,
601
614
  fetchImpl: input.fetchImpl,
602
- controlPlaneUrl: (controlPlane) => runtime.remoteFor?.(controlPlane) ?? `${runtime.github.gitUrl}/${controlPlane}.git`,
615
+ controlPlaneUrl,
603
616
  controlPlaneToken: () => tokens.controlPlane(),
604
617
  log,
605
618
  tag
@@ -614,7 +627,8 @@ async function provisionMicroVm(input) {
614
627
  }
615
628
  },
616
629
  removeStagedContext: () => removeStagedContext(buildDir2),
617
- keepIn: jobDir
630
+ keepIn: jobDir,
631
+ ...input.requireBuildSkill === true ? { requireBuildSkill: true } : {}
618
632
  });
619
633
  if (!steps.ok) return bail(steps.reason, steps.aborted === true);
620
634
  state.startCommit = steps.startCommit;
@@ -1433,7 +1447,8 @@ async function startHostServices(input) {
1433
1447
  builtIns: Object.fromEntries((build.destinations ?? []).filter((d) => BUILT_IN_NAMES.includes(d.name)).map((d) => [d.name, d.port]))
1434
1448
  },
1435
1449
  hostEnv: runtime.hostEnv,
1436
- destinationOptions: runtime.destinationOptions
1450
+ destinationOptions: runtime.destinationOptions,
1451
+ ...input.routeLog === void 0 ? {} : { log: input.routeLog }
1437
1452
  });
1438
1453
  build.proxyPort = services.proxyPort;
1439
1454
  build.destinations = [
@@ -1551,6 +1566,7 @@ function isTailedStage(stage) {
1551
1566
  const tailed = ["provision", "sync", "cleanup", "report"];
1552
1567
  return tailed.includes(stage);
1553
1568
  }
1569
+ var PROVISION_PROBLEM = /\b(warn(ing)?|error|fail(ed|ure)?|refused)\b/i;
1554
1570
  var READ_LIMIT_BYTES = 1048576;
1555
1571
  var ITEM_LINE = /^#(\d+)\b/;
1556
1572
  var AttemptLogBook = class {
@@ -1655,6 +1671,11 @@ function buildReleaseLog(jobDirPath, endStage, scrub) {
1655
1671
  const tail = stage === void 0 ? [] : lastLines(stage);
1656
1672
  if (tail.length > 0) parts.push(`--- the last ${tail.length} lines of ${file} ---`, ...tail);
1657
1673
  }
1674
+ if (endStage !== "provision") {
1675
+ const provision = readEnd(join(jobDirPath, "provision.log"), READ_LIMIT_BYTES);
1676
+ const problems = provision === void 0 ? [] : provision.split("\n").filter((line) => PROVISION_PROBLEM.test(line)).slice(-50);
1677
+ if (problems.length > 0) parts.push(`--- provision problems (${problems.length} lines of provision.log) ---`, ...problems);
1678
+ }
1658
1679
  if (parts.length === 0) return void 0;
1659
1680
  return capRunnerLog(scrub(parts.join("\n")) + "\n");
1660
1681
  }
@@ -1683,7 +1704,7 @@ async function provisionProcess(input) {
1683
1704
  mkdirSync(buildDir2, { recursive: true });
1684
1705
  chmodSync(buildDir2, 493);
1685
1706
  try {
1686
- await startHostServices({ runtime, config, build: state, jobDir, itemKey: input.itemKey, process: true });
1707
+ await startHostServices({ runtime, config, build: state, jobDir, itemKey: input.itemKey, process: true, routeLog: (line) => input.log.line(`#${item.number} ${line}`) });
1687
1708
  } catch (err) {
1688
1709
  return bail(`the tunnel could not start: ${describeCallFailure(err)}`);
1689
1710
  }
@@ -2906,7 +2927,8 @@ function scrubTunnelRecord(record, config) {
2906
2927
  hostsMore: record.hostsMore,
2907
2928
  refusalsMore: record.refusalsMore,
2908
2929
  refusals: record.refusals.map((r) => ({ ...r, host: scrubText(r.host) })),
2909
- destinations: (record.destinations ?? []).map((name) => scrubText(name))
2930
+ destinations: (record.destinations ?? []).map((name) => scrubText(name)),
2931
+ ...record.routes === void 0 ? {} : { routes: Object.fromEntries(Object.entries(record.routes).map(([name, counts]) => [scrubText(name), counts])) }
2910
2932
  };
2911
2933
  }
2912
2934
  function runCommand(cmdline, env, cwd, logPath, spawnFn = spawn) {
@@ -3041,6 +3063,9 @@ async function releaseLease(config, item, outcome, detail, fetchImpl) {
3041
3063
  sent = "ok";
3042
3064
  } else if (log !== void 0 && /\blog\b/.test(err.message)) {
3043
3065
  log = void 0;
3066
+ } else if (environment?.routes !== void 0) {
3067
+ const { routes: _omittedRoutes, ...withoutRoutes } = environment;
3068
+ environment = withoutRoutes;
3044
3069
  } else if (environment?.guestUsage !== void 0) {
3045
3070
  const { guestUsage: _omittedUsage, ...withoutUsage } = environment;
3046
3071
  environment = withoutUsage;
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { launcherPath, writeLauncher, LauncherWriteError, pathNotes } from './chunk-GWDS42JC.js';
4
- import { currentVersion, currentLink, isInLayout, packageRootIn, versionDir, switchCurrent, execStartLine } from './chunk-OWDSO3PE.js';
3
+ import { launcherPath, writeLauncher, LauncherWriteError, pathNotes } from './chunk-Z5IW4DHH.js';
4
+ import { currentVersion, currentLink, isInLayout, packageRootIn, versionDir, switchCurrent, execStartLine } from './chunk-NBZ7XBT6.js';
5
5
  import { compareVersions } from './chunk-TQMI335S.js';
6
- import { RUNNER_DIR_MODE } from './chunk-AGZNCIIJ.js';
6
+ import { RUNNER_DIR_MODE } from './chunk-PA6CK6WQ.js';
7
7
  import { realpathSync, readFileSync, mkdirSync, rmSync, cpSync, existsSync } from 'fs';
8
8
  import { dirname, sep, join } from 'path';
9
9
 
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
3
  import { removeRetiredSkills } from './chunk-UIUGTW5C.js';
4
- import { defaultFetch, resolveGatewayCredentials } from './chunk-WPGBDY73.js';
5
- import { withTokenHeader } from './chunk-BCCI32ME.js';
4
+ import { defaultFetch, resolveGatewayCredentials } from './chunk-6RKD7YZ6.js';
5
+ import { withTokenHeader } from './chunk-BALIE3BA.js';
6
6
  import { appendContextProvenance } from './chunk-ZJSNLVCE.js';
7
7
  import { loadMaintainedFiles, writeMaintainedFiles } from './chunk-G63KT5I5.js';
8
8
  import { cliInvocation } from './chunk-CRB3POP4.js';
@@ -79,10 +79,12 @@ var defaultGitRunner = (args, opts) => {
79
79
  return { ok: true, stdout: Buffer.isBuffer(stdout) ? stdout : Buffer.from(stdout), stderr: "" };
80
80
  } catch (err) {
81
81
  const e = err;
82
+ const stderr = e.stderr ? Buffer.from(e.stderr).toString("utf8") : "";
82
83
  return {
83
84
  ok: false,
84
85
  stdout: e.stdout ? Buffer.from(e.stdout) : Buffer.alloc(0),
85
- stderr: e.stderr ? Buffer.from(e.stderr).toString("utf8") : e.message ?? String(err)
86
+ stderr: stderr === "" ? e.message ?? String(err) : stderr,
87
+ ...e.code === "ETIMEDOUT" ? { timedOut: true } : {}
86
88
  };
87
89
  }
88
90
  };
@@ -90,6 +92,36 @@ function gitText(git, cwd, args, timeoutMs) {
90
92
  const result = git(args, { cwd, timeoutMs });
91
93
  return result.ok ? result.stdout.toString("utf8").trim() : void 0;
92
94
  }
95
+ function fetchFailureDetail(result, timeoutMs) {
96
+ if (result.timedOut === true) return `git fetch did not finish within ${timeoutMs / 1e3} seconds`;
97
+ const lines = result.stderr.split("\n").map((line2) => line2.trim()).filter((line2) => line2 !== "");
98
+ const line = lines.find((candidate) => /^(fatal|error):/.test(candidate)) ?? lines.at(-1) ?? "git fetch failed";
99
+ return line.replace(/(\w+:\/\/)[^/@\s]+@/g, "$1").slice(0, 300);
100
+ }
101
+ async function fetchControlPlaneCommit(input) {
102
+ const { git, home, repository, sha, remoteUrl, policy } = input;
103
+ const cacheHost = parseRemoteHost(remoteUrl).host || "unknown-host";
104
+ const cacheRepoDir = ensureBareCache(git, home, repository, cacheHost);
105
+ const localRef = `refs/outerlayer/sha-${sanitizeRefName(sha)}`;
106
+ if (policy.reuseCached && gitText(git, cacheRepoDir, ["rev-parse", "--verify", "--quiet", localRef], 2e3) === sha) {
107
+ return { ok: true, cacheRepoDir, localRef, fetched: false };
108
+ }
109
+ const token = await input.token();
110
+ const attempts = Math.max(1, policy.attempts);
111
+ for (let attempt = 1; ; attempt++) {
112
+ const result = git(["fetch", "--depth", "1", remoteUrl, `+${sha}:${localRef}`], {
113
+ cwd: cacheRepoDir,
114
+ timeoutMs: policy.timeoutMs,
115
+ ...token === void 0 ? {} : { env: (base) => withTokenHeader(base, remoteUrl, token) }
116
+ });
117
+ if (result.ok) return { ok: true, cacheRepoDir, localRef, fetched: true };
118
+ const kind = result.timedOut === true ? "unreachable" : classifyGitFailure(result.stderr);
119
+ if (kind === "no-access" || attempt >= attempts) {
120
+ const detail = fetchFailureDetail(result, policy.timeoutMs);
121
+ return { ok: false, kind, detail: attempt > 1 ? `${detail} (${attempt} attempts)` : detail };
122
+ }
123
+ }
124
+ }
93
125
  var GATEWAY_TOO_OLD_MESSAGE = "the OuterLayer this machine talks to is too old to name the control plane \u2014 ask whoever runs it to upgrade; context written earlier is kept";
94
126
  var CANNOT_IDENTIFY_MESSAGE = "this repository is governed, but the control plane cannot be identified \u2014 check OuterLayer connectivity/config";
95
127
  function designationAuthRejectedMessage(credential) {
@@ -97,9 +129,6 @@ function designationAuthRejectedMessage(credential) {
97
129
  }
98
130
  var PARTIAL_WRITE_MESSAGE = "control-plane content could not be fully written";
99
131
  var OVERLAY_FAILED_MESSAGE = "control-plane content was written but the maintained skills could not be refreshed";
100
- function isStagingWriteFault(message) {
101
- return message === PARTIAL_WRITE_MESSAGE || message === OVERLAY_FAILED_MESSAGE;
102
- }
103
132
  function hasSymlinkComponent(root, relPath) {
104
133
  let current = root;
105
134
  for (const segment of relPath.split("/")) {
@@ -121,7 +150,7 @@ function noAccessMessage() {
121
150
  return "you do not have access to the control plane \u2014 check your git credentials (SSH key or token) and org/SSO access, then retry";
122
151
  }
123
152
  function classifyGitFailure(stderr) {
124
- if (/authentication failed|permission denied \(publickey\)|\b403\b|saml sso|access denied/i.test(stderr)) {
153
+ if (/authentication failed|permission denied \(publickey\)|\b403\b|saml sso|access denied|could not read (username|password)|repository .*not found/i.test(stderr)) {
125
154
  return "no-access";
126
155
  }
127
156
  return "unreachable";
@@ -216,25 +245,28 @@ async function materializeContext(deps) {
216
245
  }
217
246
  };
218
247
  const remoteUrl = deps.resolveControlPlaneUrl ? deps.resolveControlPlaneUrl(repository, ref, repoRoot) : buildControlPlaneUrl(git, repoRoot, repository);
219
- const cacheHost = parseRemoteHost(remoteUrl).host || "unknown-host";
220
- const cacheRepoDir = ensureBareCache(git, home, repository, cacheHost);
221
- const localRef = `refs/outerlayer/sha-${sanitizeRefName(storedSha)}`;
222
- const wanted = `+${storedSha}:${localRef}`;
223
- const access = await deps.controlPlaneAccess?.([{ repository, ref }]);
224
- const token = access !== void 0 && normalizeRepoName(access.repository) === normalizeRepoName(repository) ? access.token : void 0;
225
- const fetchResult = git(["fetch", "--depth", "1", remoteUrl, wanted], {
226
- cwd: cacheRepoDir,
227
- timeoutMs: 1e4,
228
- ...token === void 0 ? {} : { env: (base) => withTokenHeader(base, remoteUrl, token) }
248
+ const fetched = await fetchControlPlaneCommit({
249
+ git,
250
+ home,
251
+ repository,
252
+ sha: storedSha,
253
+ remoteUrl,
254
+ // A runner reads the control plane with a token for it, not the host's git login.
255
+ token: async () => {
256
+ const access = await deps.controlPlaneAccess?.([{ repository, ref }]);
257
+ return access !== void 0 && normalizeRepoName(access.repository) === normalizeRepoName(repository) ? access.token : void 0;
258
+ },
259
+ policy: deps.controlPlaneFetch ?? { timeoutMs: 1e4, attempts: 1, reuseCached: false }
229
260
  });
230
261
  const commitNote = (message) => `could not fetch commit \`${storedSha.slice(0, 7)}\` of ${repository}; ${message}`;
231
- if (!fetchResult.ok) {
232
- const kind = classifyGitFailure(fetchResult.stderr);
233
- const doctorMessage = commitNote(kind === "no-access" ? noAccessMessage() : unreachableMessage());
262
+ if (!fetched.ok) {
263
+ const { kind } = fetched;
264
+ const doctorMessage = commitNote(kind === "no-access" ? noAccessMessage() : `${unreachableMessage()}: ${fetched.detail}`);
234
265
  writeDegraded(gitCommonDir, { at: new Date(now()).toISOString(), kind, message: doctorMessage, repository, ref });
235
266
  record(null, "none", repository, ref);
236
267
  return { status: kind, message: doctorMessage, sha: null, verification: "none" };
237
268
  }
269
+ const { cacheRepoDir, localRef } = fetched;
238
270
  const fetchedSha = gitText(git, cacheRepoDir, ["rev-parse", localRef], 2e3);
239
271
  if (fetchedSha !== storedSha) {
240
272
  const doctorMessage = commitNote(unreachableMessage());
@@ -498,4 +530,4 @@ function writeFilesVerbatim(git, cacheRepoDir, files, workpieceRoot) {
498
530
  return { writtenPaths, ok: !anySkipped };
499
531
  }
500
532
 
501
- export { defaultGitRunner, isStagingWriteFault, lookupGoverningSource, materializeContext, parseOwnerRepo, resolveGitCommonDir };
533
+ export { defaultGitRunner, fetchControlPlaneCommit, lookupGoverningSource, materializeContext, parseOwnerRepo, resolveGitCommonDir };
@@ -1,7 +1,7 @@
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-AGZNCIIJ.js';
4
+ import { RUNNER_DIR_MODE, RUNNER_FILE_MODE } from './chunk-PA6CK6WQ.js';
5
5
  import { existsSync, readFileSync, mkdirSync, writeFileSync, rmSync } from 'fs';
6
6
  import { dirname } from 'path';
7
7
 
@@ -4,9 +4,9 @@ import { RecipeError } from './chunk-3Z3MPR55.js';
4
4
  import { BUILDKIT_IMAGE } from './chunk-TGHBOXKJ.js';
5
5
  import { parseSize } from './chunk-YJLHUKYS.js';
6
6
  import { compareVersions } from './chunk-5DNCFOXA.js';
7
- import { ensureHostKey } from './chunk-AA6LYZC4.js';
8
- import { RUNNER_DIR_MODE, RUNNER_FILE_MODE, runnerDir, jobsDir } from './chunk-AGZNCIIJ.js';
9
- import { CLAUDE_PORT, JOB_MOUNT, GATEWAY_PORT, GATEWAY_SOCKET, CLAUDE_SOCKET, RELAY_PORT, DESTINATION_BASE_PORT } from './chunk-BCCI32ME.js';
7
+ import { ensureHostKey } from './chunk-SOI6K5DY.js';
8
+ import { RUNNER_DIR_MODE, RUNNER_FILE_MODE, runnerDir, jobsDir } from './chunk-PA6CK6WQ.js';
9
+ import { CLAUDE_PORT, JOB_MOUNT, GATEWAY_PORT, GATEWAY_SOCKET, CLAUDE_SOCKET, RELAY_PORT, DESTINATION_BASE_PORT } from './chunk-BALIE3BA.js';
10
10
  import { JOIN_DIR, RELAY_ID, JOIN_SOCKET, TARGET_GATEWAY, TARGET_CLAUDE, destinationTarget, RELAY_USER } from './chunk-MESOOLF4.js';
11
11
  import { createHash } from 'crypto';
12
12
  import { existsSync, mkdirSync, createWriteStream, rmSync, readFileSync, chmodSync, writeFileSync, realpathSync, readdirSync, renameSync } from 'fs';
@@ -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-AGZNCIIJ.js';
3
+ import { RUNNER_DIR_MODE, RUNNER_FILE_MODE } from './chunk-PA6CK6WQ.js';
4
4
  import { readFileSync, existsSync, rmSync, mkdirSync, writeFileSync, renameSync } from 'fs';
5
5
  import { join } from 'path';
6
6
 
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { TUNNEL_PORT, BRIDGE_ADDRESS, BRIDGE_CIDR } from './chunk-QL3LPZ67.js';
3
+ import { TUNNEL_PORT, BRIDGE_ADDRESS, BRIDGE_CIDR } from './chunk-6LBSAW6I.js';
4
4
  import { startTimeOf } from './chunk-JBJTC3UU.js';
5
- import { EXEC_PORT } from './chunk-LWTBE5J6.js';
6
- import { RELAY_PORT } from './chunk-BCCI32ME.js';
5
+ import { EXEC_PORT } from './chunk-L26V6ILJ.js';
6
+ import { RELAY_PORT } from './chunk-BALIE3BA.js';
7
7
  import { spawn, spawnSync } from 'child_process';
8
8
  import { symlinkSync, lstatSync, writeFileSync, chmodSync, mkdirSync, existsSync } from 'fs';
9
9
 
@@ -2,7 +2,7 @@
2
2
  import { createRequire } from 'node:module';
3
3
  import { sanitizeTerminal } from './chunk-EWVYQLD3.js';
4
4
  import { isAgentsMdLayout } from './chunk-HJYBWJAS.js';
5
- import { resolveGatewayCredentials, defaultFetch } from './chunk-WPGBDY73.js';
5
+ import { resolveGatewayCredentials, defaultFetch } from './chunk-6RKD7YZ6.js';
6
6
  import { versionAtLeast } from './chunk-HCVLP7XA.js';
7
7
  import { findGitDirs } from './chunk-BJ3KTMDH.js';
8
8
  import { machineSkillsState, staleClaudeSkills } from './chunk-GFYEMCPP.js';
@@ -11,8 +11,9 @@ import { MAINTAINED_SKILLS } from './chunk-CDDED64E.js';
11
11
  import { cliInvocation } from './chunk-CRB3POP4.js';
12
12
  import { hasSymlinkComponent } from './chunk-AVTI3FL5.js';
13
13
  import { emitTree, ALL_TARGET_IDS, classifyTree, splitRawFile } from './chunk-LJG6EMLJ.js';
14
+ import { execFileSync } from 'child_process';
14
15
  import { existsSync, readFileSync, writeFileSync, realpathSync, readdirSync } from 'fs';
15
- import { join, dirname, posix } from 'path';
16
+ import { join, dirname, posix, basename, isAbsolute, relative } from 'path';
16
17
 
17
18
  createRequire(import.meta.url);
18
19
  var PROSE_FILE = /\.mdc?$/;
@@ -220,6 +221,63 @@ function checkMachineSkills(opts) {
220
221
  }
221
222
  ];
222
223
  }
224
+ var SKILL_BASES2 = [".agents/skills", ".claude/skills"];
225
+ function ignoreRuleFor(repoRoot, path) {
226
+ let out;
227
+ try {
228
+ out = execFileSync("git", ["-C", repoRoot, "check-ignore", "-v", "--", path], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], timeout: 5e3 });
229
+ } catch {
230
+ return void 0;
231
+ }
232
+ const match = /^(.*?):(\d+):([^\t]*)\t/.exec(out);
233
+ if (match === null || match[3].startsWith("!")) return void 0;
234
+ return { source: match[1], line: match[2], pattern: match[3] };
235
+ }
236
+ function ignoredSkillFolders(repoRoot) {
237
+ const found = [];
238
+ let any = false;
239
+ const ruleFor = (path) => ignoreRuleFor(repoRoot, path);
240
+ for (const base of SKILL_BASES2) {
241
+ let names;
242
+ try {
243
+ names = readdirSync(join(repoRoot, base), { withFileTypes: true }).filter((entry) => entry.isDirectory() || entry.isSymbolicLink()).map((entry) => entry.name).sort();
244
+ } catch {
245
+ continue;
246
+ }
247
+ for (const name of names) {
248
+ const folder = `${base}/${name}`;
249
+ any = true;
250
+ const file = existsSync(join(repoRoot, folder, "SKILL.md")) ? `${folder}/SKILL.md` : folder;
251
+ if (ruleFor(file) === void 0) continue;
252
+ const parts = file.split("/");
253
+ const ignored = parts.map((_, i) => parts.slice(0, i + 1).join("/")).find((path) => ruleFor(path) !== void 0);
254
+ found.push({ folder, ignored, ...ruleFor(ignored) });
255
+ }
256
+ }
257
+ return { found, any };
258
+ }
259
+ function ignoredSkillFix({ folder, ignored, source, line }) {
260
+ if (folder.startsWith(`${ignored}/`)) {
261
+ return `${ignored}/ is ignored as a whole, and git cannot bring back a folder inside an ignored one: change line ${line} of ${source} so it no longer matches ${ignored}/, or run \`git add -f ${folder}\`, then commit.`;
262
+ }
263
+ const target = ignored === folder ? `${folder}/` : ignored;
264
+ if (basename(source) !== ".gitignore" || isAbsolute(source)) return `Add the line \`!${target}\` to .gitignore, then commit the folder.`;
265
+ const path = relative(dirname(source), target) + (target.endsWith("/") ? "/" : "");
266
+ const anchored = path.slice(0, -1).includes("/") ? path : `/${path}`;
267
+ return `Add the line \`!${anchored}\` to ${source} below line ${line}, then commit the folder.`;
268
+ }
269
+ function checkIgnoredSkillFolders(repoRoot) {
270
+ const { found, any } = ignoredSkillFolders(repoRoot);
271
+ if (found.length === 0) {
272
+ return !any ? [] : [{ name: "Skills", status: "pass", detail: `no folder under ${SKILL_BASES2.join(" or ")} is ignored by git` }];
273
+ }
274
+ return found.map((ignored) => ({
275
+ name: "Skills",
276
+ status: "warn",
277
+ detail: `${ignored.folder} is ignored by ${ignored.source} line ${ignored.line} (\`${ignored.pattern}\`), so git never commits it and a build's clone has no ${ignored.folder.split("/").at(-1)} skill`,
278
+ fix: ignoredSkillFix(ignored)
279
+ }));
280
+ }
223
281
 
224
282
  // src/fleet-readiness.ts
225
283
  var FIRST_VERSION_WITH_MACHINE_SKILLS = "0.27.0";
@@ -297,4 +355,4 @@ async function fleetCheck(opts = {}) {
297
355
  return [{ name: CHECK_NAME, status: "pass", detail }];
298
356
  }
299
357
 
300
- export { applyReferenceRewrites, checkBuildSkill, checkCommittedMaintainedSkills, checkMachineSkills, checkMaintainedReferences, committedMaintainedFolders, describeFleet, fleetCheck, fleetReadiness, maintainedReferenceRewrites, skillsFolders };
358
+ export { applyReferenceRewrites, checkBuildSkill, checkCommittedMaintainedSkills, checkIgnoredSkillFolders, checkMachineSkills, checkMaintainedReferences, committedMaintainedFolders, describeFleet, fleetCheck, fleetReadiness, maintainedReferenceRewrites, skillsFolders };
@@ -1,11 +1,5 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { fetchFactories, selectFactory, saveFactoryConnection, autoConnectedLine } from './chunk-ZQOSIMKU.js';
4
- import { resolveRepoIdentity } from './chunk-5DNCFOXA.js';
5
- import { resolveGatewayCredentials } from './chunk-WPGBDY73.js';
6
- import { findGitDirs, readRepoConnection } from './chunk-BJ3KTMDH.js';
7
- import { cliInvocation } from './chunk-CRB3POP4.js';
8
- import { homeFromEnv } from './chunk-VNVZDWO3.js';
9
3
  import { openSync, fstatSync, readSync, closeSync } from 'fs';
10
4
  import { join } from 'path';
11
5
 
@@ -82,32 +76,4 @@ function transcriptPathForSession(sessionId, home, readTailImpl = readTail) {
82
76
  return found;
83
77
  }
84
78
 
85
- // src/auto-connect.ts
86
- async function autoConnect(opts) {
87
- const env = opts.env ?? process.env;
88
- const home = opts.home ?? homeFromEnv(env);
89
- const cwd = opts.cwd ?? process.cwd();
90
- const resolved = resolveGatewayCredentials({ url: opts.url, apiKey: opts.apiKey, appId: opts.appId, home, env, cwd });
91
- if (resolved.ok || resolved.kind !== "login" || !resolved.credential || !resolved.url) return void 0;
92
- const dirs = findGitDirs(cwd);
93
- const repository = opts.repository ?? resolveRepoIdentity(cwd).gitRepo;
94
- if (dirs === void 0 || repository === void 0) return void 0;
95
- const listed = await fetchFactories(opts.fetchImpl ?? fetch, resolved.url, resolved.credential, repository);
96
- if (!listed.ok || listed.factories.length === 0) return void 0;
97
- const chosen = selectFactory(listed.factories, readRepoConnection(cwd), repository);
98
- if (chosen.factory === void 0) {
99
- return `you are logged in, but no factory is chosen for this repository, and more than one fits. Run \`${cliInvocation()} connect --factory <org>/<factory>\` with one of:
100
- ${chosen.text}
101
- Or pass --app-id / set OUTERLAYER_APP_ID.`;
102
- }
103
- try {
104
- saveFactoryConnection(dirs.gitCommonDir, void 0, chosen.factory, /* @__PURE__ */ new Date());
105
- } catch {
106
- return void 0;
107
- }
108
- process.stderr.write(`${autoConnectedLine(repository, chosen.factory, chosen.reason)}
109
- `);
110
- return void 0;
111
- }
112
-
113
- export { autoConnect, detectActiveSession, transcriptPathForSession };
79
+ export { detectActiveSession, transcriptPathForSession };
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { claimPidFile, RunnerAlreadyRunningError, releasePidFile } from './chunk-DDS2ISML.js';
3
+ import { claimPidFile, RunnerAlreadyRunningError, releasePidFile } from './chunk-F5UL23I2.js';
4
4
  import { startTimeOf } from './chunk-JBJTC3UU.js';
5
5
  import { RecipeError, locateRecipe, readRecipe, assertBuildable, writeSanitizedRecipe, classifyProperties, SANITIZED_NAME } from './chunk-3Z3MPR55.js';
6
6
  import { GH_VERSION, VOICE_PACK_FILES, VOICE_PACK_VERSION, FFMPEG_STATIC, FFMPEG_BUILD_TAG, GH_SHA256, TINI_SHA256, TINI_VERSION, CLAUDE_CODE_VERSION, NODE_IMAGE, DEFAULT_BASE_IMAGE, MEDIA_PINS, PLAYWRIGHT_VERSION } from './chunk-TGHBOXKJ.js';
7
- import { RUNNER_DIR_MODE, RUNNER_FILE_MODE, repoCacheDir, imagesDir, imageBuildLogsDir, attemptStamp, runnerDir, rootfsPathFor } from './chunk-AGZNCIIJ.js';
8
- import { PROXY_WARNING_FLAG, withGitConfig, tokenHeader } from './chunk-BCCI32ME.js';
7
+ import { RUNNER_DIR_MODE, RUNNER_FILE_MODE, repoCacheDir, imagesDir, imageBuildLogsDir, attemptStamp, runnerDir, rootfsPathFor } from './chunk-PA6CK6WQ.js';
8
+ import { PROXY_WARNING_FLAG, withGitConfig, tokenHeader } from './chunk-BALIE3BA.js';
9
9
  import { RELAY_ID, RELAY_USER } from './chunk-MESOOLF4.js';
10
10
  import { mkdirSync, rmSync, writeFileSync, existsSync, mkdtempSync, cpSync, readFileSync, readdirSync, lstatSync, readlinkSync } from 'fs';
11
11
  import { tmpdir } from 'os';