@outerlayer/cli 0.19.1 → 0.22.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 (146) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +26 -7
  3. package/dist/{agent-setup-AM42SA2D.js → agent-setup-XAJH6MPW.js} +13 -12
  4. package/dist/build-GTMEADQD.js +12 -0
  5. package/dist/build-command-ND2ENDBS.js +50 -0
  6. package/dist/build-info.json +1 -1
  7. package/dist/{builder-C4QNTYMS.js → builder-OAUSTZHL.js} +7 -5
  8. package/dist/{check-W2JGXN3B.js → check-3YHMJQ3P.js} +48 -50
  9. package/dist/{chunk-F2KXHIFI.js → chunk-22DYXLU7.js} +360 -66
  10. package/dist/{chunk-P53VEAOF.js → chunk-2CMJLYV6.js} +1 -1
  11. package/dist/{chunk-FBTGMSQF.js → chunk-2HT2XGJX.js} +16 -9
  12. package/dist/{chunk-S5PCA3SN.js → chunk-2J5JGLW5.js} +1 -1
  13. package/dist/{chunk-R22NZSGA.js → chunk-34XORKFD.js} +9 -9
  14. package/dist/{chunk-QOZKPLVJ.js → chunk-3W333NFO.js} +40 -1
  15. package/dist/{chunk-HOKXGFDR.js → chunk-4JHVPFH6.js} +22 -16
  16. package/dist/{chunk-AMFWYESY.js → chunk-4NM3I3VV.js} +1 -1
  17. package/dist/{chunk-PIZRPNKR.js → chunk-4QKLMNI3.js} +5 -5
  18. package/dist/{chunk-NNLA7LLQ.js → chunk-5OCIHFGE.js} +29 -5
  19. package/dist/{chunk-PSN33ERW.js → chunk-6IO62VJS.js} +3 -3
  20. package/dist/{chunk-7YP7T6GV.js → chunk-7V7KG3YM.js} +2 -2
  21. package/dist/{chunk-QNLX477Q.js → chunk-AEKSX4EY.js} +165 -72
  22. package/dist/{chunk-JHGEBPLE.js → chunk-ATRIVTRE.js} +3 -3
  23. package/dist/{chunk-X5H2WYMB.js → chunk-BLW6GPBZ.js} +1 -1
  24. package/dist/{chunk-MLAAT4S6.js → chunk-C3HKR67W.js} +3 -3
  25. package/dist/{chunk-XZ4H4X5F.js → chunk-C3OVGKVJ.js} +15 -8
  26. package/dist/{chunk-BM63HB2M.js → chunk-EAQSOE62.js} +2 -2
  27. package/dist/{chunk-LW7G5TJB.js → chunk-EXV37PKS.js} +2 -2
  28. package/dist/{chunk-B6SCN5NY.js → chunk-FGW2774C.js} +175 -44
  29. package/dist/{chunk-KYS3TQAG.js → chunk-G2WME4RG.js} +4 -4
  30. package/dist/{chunk-LRG3ZMZD.js → chunk-G6DZCKA6.js} +4 -4
  31. package/dist/chunk-GISNHSYL.js +41 -0
  32. package/dist/{chunk-G2YNJIGF.js → chunk-HCVLP7XA.js} +10 -1
  33. package/dist/{chunk-QEFKA2QD.js → chunk-I66MQDXH.js} +2 -2
  34. package/dist/{chunk-3CWUOFV6.js → chunk-IRBNIRQJ.js} +12 -7
  35. package/dist/{chunk-CG36IONK.js → chunk-JRCSET55.js} +2 -2
  36. package/dist/{chunk-CGGPS7SI.js → chunk-JVB63NIB.js} +5 -5
  37. package/dist/{chunk-M2ZWWTWZ.js → chunk-KDHYLBRR.js} +1 -1
  38. package/dist/{chunk-N2PXGQRL.js → chunk-KIGSGZBB.js} +1 -1
  39. package/dist/{chunk-EAEELQVQ.js → chunk-KOQELWQ6.js} +5 -5
  40. package/dist/{chunk-MTP2QEVO.js → chunk-KPBQYEND.js} +1 -1
  41. package/dist/{chunk-VYAL7PUE.js → chunk-LOB2SUM3.js} +1 -1
  42. package/dist/{chunk-GGOMT6KF.js → chunk-PHHBYAL6.js} +1 -1
  43. package/dist/{chunk-IF2OSI5T.js → chunk-QOALB6ZD.js} +2 -2
  44. package/dist/{chunk-BWSUPRDK.js → chunk-TPKYTORP.js} +1 -1
  45. package/dist/{chunk-XNGMQ27R.js → chunk-UD3EXMKB.js} +2 -2
  46. package/dist/{chunk-7UWVLZXD.js → chunk-USWVXQIH.js} +1 -1
  47. package/dist/{chunk-BQXFBI7T.js → chunk-V7MQKOZY.js} +32 -7
  48. package/dist/{chunk-6X4SQ5MY.js → chunk-V7SAQ645.js} +1 -1
  49. package/dist/{chunk-TWF3RICI.js → chunk-VSUXCMMH.js} +110 -11
  50. package/dist/{chunk-FVMYKL6L.js → chunk-VWLOQ6FI.js} +1 -1
  51. package/dist/{chunk-3ZR7Y23Y.js → chunk-VX74ND77.js} +650 -70
  52. package/dist/{chunk-Z7K3L4FC.js → chunk-W3SWJ2TD.js} +2 -2
  53. package/dist/chunk-WERZMIKA.js +718 -0
  54. package/dist/{chunk-GEMQLBMW.js → chunk-WMHYIBJW.js} +6 -6
  55. package/dist/{chunk-5VML45HH.js → chunk-XCRZTXRL.js} +2 -2
  56. package/dist/{chunk-ECODQ7II.js → chunk-ZFLOGMUC.js} +1 -1
  57. package/dist/chunk-ZNPE7FW5.js +137 -0
  58. package/dist/claude-launcher-4BQNXYAF.js +267 -0
  59. package/dist/{cli-EXX2R73G.js → cli-NMGVZQPB.js} +189 -119
  60. package/dist/{command-ZQNEPDS6.js → command-GE62AJZY.js} +32 -34
  61. package/dist/{config-CLSGABD5.js → config-7Q52COZ3.js} +3 -2
  62. package/dist/{connect-cmd-UNYKGDAL.js → connect-cmd-ZFOK6HEL.js} +5 -5
  63. package/dist/{context-cleanup-CHEWNYU6.js → context-cleanup-DSA3HGQU.js} +1 -1
  64. package/dist/{control-plane-launch-34LNRJWR.js → control-plane-launch-SZTE4TUS.js} +62 -28
  65. package/dist/{dist-WO7NOJNG.js → dist-7IH56ELA.js} +1 -1
  66. package/dist/{docker-BFU3AQGY.js → docker-2OVBKVRK.js} +7 -7
  67. package/dist/{doctor-DHUM5DBB.js → doctor-3SQGZVYP.js} +35 -36
  68. package/dist/{emit-artifact-cmd-XBHM647X.js → emit-artifact-cmd-R42BE6ID.js} +19 -18
  69. package/dist/{emit-cmd-W55AEBCA.js → emit-cmd-3W5IO5ET.js} +3 -3
  70. package/dist/{emit-criteria-cmd-CRTYEF7D.js → emit-criteria-cmd-MQZE7W4Y.js} +52 -16
  71. package/dist/{emit-finding-cmd-7JHVRYOP.js → emit-finding-cmd-ZS5JEGGM.js} +13 -12
  72. package/dist/{emit-result-cmd-5NZMLCJK.js → emit-result-cmd-FUE3DXBW.js} +19 -18
  73. package/dist/{emit-step-cmd-347XNGPQ.js → emit-step-cmd-T7PRA44X.js} +14 -13
  74. package/dist/{exec-client-7UMESIE2.js → exec-client-YIDTWXMZ.js} +4 -3
  75. package/dist/{governing-source-HAA4OW57.js → governing-source-TORXL4I4.js} +19 -18
  76. package/dist/{guest-init-KPBQOFE5.js → guest-init-TO6HAWIT.js} +4 -3
  77. package/dist/{hook-fast-RL5E5OXE.js → hook-fast-WFB2ZMRB.js} +2 -2
  78. package/dist/host-key-2LXQDSBO.js +9 -0
  79. package/dist/{import-capture-cmd-TK4XY7RD.js → import-capture-cmd-Q56DDZVO.js} +1 -1
  80. package/dist/index.js +5 -5
  81. package/dist/init-2CRAVIUU.js +52 -0
  82. package/dist/{init-V6FOMD2V.js → init-AHDZCMDC.js} +32 -33
  83. package/dist/{init-cmd-Z4O4PPLZ.js → init-cmd-IXDL2ZSL.js} +25 -23
  84. package/dist/{init-update-7DVAKWW3.js → init-update-YB3PODDH.js} +69 -24
  85. package/dist/{install-4SEFIIW2.js → install-CZUIW2AF.js} +5 -4
  86. package/dist/{install-cmd-QDOTR4OM.js → install-cmd-Q7RJGFUO.js} +6 -5
  87. package/dist/{login-browser-DX35MARZ.js → login-browser-BN5UKPHS.js} +3 -3
  88. package/dist/{logout-cmd-5V5MMBSY.js → logout-cmd-RZFWTNYD.js} +2 -2
  89. package/dist/{logs-AMLKC3VP.js → logs-RJPYTVQE.js} +3 -2
  90. package/dist/loop-ZDW6TRAA.js +75 -0
  91. package/dist/machine-JCOHLASP.js +47 -0
  92. package/dist/{mcp-install-cmd-GGWB3JJ2.js → mcp-install-cmd-GD4QUP7Z.js} +2 -2
  93. package/dist/{mcp-serve-cmd-N3UTY6EE.js → mcp-serve-cmd-IULQPVHL.js} +6 -5
  94. package/dist/{paths-7XP63OAX.js → paths-N3LU4O2Z.js} +3 -2
  95. package/dist/pending-GRCV3ZR4.js +9 -0
  96. package/dist/{pidfile-3DM4OBKO.js → pidfile-IF3TCL5A.js} +4 -3
  97. package/dist/receive-files-T2BIUBQL.js +254 -0
  98. package/dist/{record-3WP6V2K5.js → record-73PQE77B.js} +4 -3
  99. package/dist/relay-PSZ4LGMW.js +210 -0
  100. package/dist/relay-protocol-K7KP2SPI.js +6 -0
  101. package/dist/{runner-env-FRZFFHDF.js → runner-env-LDOBJESN.js} +6 -5
  102. package/dist/runner-identity-RWCBTY2A.js +14 -0
  103. package/dist/{runner-key-5FOWCW7J.js → runner-key-HMYLP6WN.js} +32 -33
  104. package/dist/{session-sender-U2BBUWNO.js → session-sender-2G25JYHI.js} +20 -19
  105. package/dist/{spec-cmd-FVLJOFGC.js → spec-cmd-LBVXM6XS.js} +13 -12
  106. package/dist/{starter-pack-6LQVLBIA.js → starter-pack-5EQYGSJF.js} +2 -2
  107. package/dist/{status-BINH7MBG.js → status-QZB2GWXJ.js} +36 -38
  108. package/dist/{statusline-fast-KN3BX67H.js → statusline-fast-2OK3DVAA.js} +2 -2
  109. package/dist/{sync-cmd-VXOUFS4I.js → sync-cmd-TQQIR4PN.js} +19 -18
  110. package/dist/{watch-OH645CV2.js → watch-4JES4PCS.js} +19 -18
  111. package/dist/{work-claim-cmd-ZRPSHMPT.js → work-claim-cmd-XG6O7B63.js} +17 -16
  112. package/dist/{work-cmd-5I3J2XQQ.js → work-cmd-L6WMPAA2.js} +13 -12
  113. package/dist/{work-comment-cmd-UCCPWUSR.js → work-comment-cmd-SNTDCPGH.js} +13 -12
  114. package/dist/{work-logs-cmd-7352CJPG.js → work-logs-cmd-3S7IAVII.js} +13 -12
  115. package/dist/{work-open-pr-cmd-LSH4VHJM.js → work-open-pr-cmd-E3WMO5XT.js} +15 -14
  116. package/dist/{work-pr-cmd-H4OQR26N.js → work-pr-cmd-22T6FG4T.js} +14 -13
  117. package/dist/work-stop-cmd-WR7ESS4Z.js +53 -0
  118. package/package.json +2 -2
  119. package/skill-pack/maintained/outerlayer-build/SKILL.md +347 -0
  120. package/skill-pack/{template/build → maintained/outerlayer-build}/references/evidence.md +2 -2
  121. package/skill-pack/{template/build → maintained/outerlayer-build}/references/release.md +4 -4
  122. package/skill-pack/{template/build → maintained/outerlayer-build}/references/review-loop.md +3 -1
  123. package/skill-pack/shipped.json +2 -0
  124. package/skill-pack/template/build/SKILL.md +4 -253
  125. package/skill-pack/validators/acceptance-criteria.yaml +1 -1
  126. package/dist/build-TQ6X5PYN.js +0 -12
  127. package/dist/chunk-3UZTIRLF.js +0 -320
  128. package/dist/chunk-CX22S5BA.js +0 -45
  129. package/dist/chunk-LLM3I5YU.js +0 -89
  130. package/dist/chunk-SADUQSO4.js +0 -50
  131. package/dist/chunk-VMJPFQNE.js +0 -261
  132. package/dist/claude-launcher-J5M44PFS.js +0 -115
  133. package/dist/host-key-U4B5QETR.js +0 -8
  134. package/dist/init-XG47KCI4.js +0 -53
  135. package/dist/loop-TPUYUMSY.js +0 -77
  136. package/dist/machine-TRHBT5NE.js +0 -48
  137. package/dist/pending-532ABZYC.js +0 -8
  138. package/dist/relay-L76HDX72.js +0 -46
  139. package/dist/{chunk-YVZJ6GKF.js → chunk-DIB2WLBL.js} +1 -1
  140. package/dist/{chunk-GOSFARMS.js → chunk-F35VMF5M.js} +1 -1
  141. package/dist/{chunk-DSF2FWAZ.js → chunk-IZSVXRDR.js} +1 -1
  142. /package/skill-pack/{template/build → maintained/outerlayer-build}/references/agent-briefs.md +0 -0
  143. /package/skill-pack/{template/build → maintained/outerlayer-build}/references/criteria-judge.md +0 -0
  144. /package/skill-pack/{template/build → maintained/outerlayer-build}/references/review-briefs.md +0 -0
  145. /package/skill-pack/{template/build → maintained/outerlayer-build}/scripts/criterion-citations.mjs +0 -0
  146. /package/skill-pack/{template/build → maintained/outerlayer-build}/scripts/record-criteria.mjs +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,38 @@
1
1
  # @outerlayer/cli
2
2
 
3
+ ## 0.22.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 520123a: The build process now ships as a maintained `outerlayer-build` skill that `outerlayer init --update` rewrites with each CLI release. Your repository's `build` skill keeps only your own changes to it, and `outerlayer doctor` reports a `build` skill that no longer points at the maintained one. Run `outerlayer init --update` after upgrading to move to the new layout.
8
+
9
+ ### Patch Changes
10
+
11
+ - 807c89d: `outerlayer work build --instructions <text>` gives the agent that runs a host build instructions from you, up to 2000 characters. The build skill reads them at intake as guidance; the issue and its criteria win when the two disagree. With `--local`, the command refuses `--instructions` before any network call.
12
+ - 540fd26: A container build keeps running when its runner restarts or crashes, and the runner picks it up when it comes back.
13
+ - 1a8d9ac: `outerlayer doctor` names its checks `Control plane` and `Control plane degradation`, the term the dashboard uses.
14
+ - 5301041: On a macOS runner, a container build's session that breaks HTTP/2 framing now ends at once and counts toward ending the build. Before, the session stayed open, so a build that kept breaking framing was never ended.
15
+ - 8697753: A container or microVM build whose command fails at once ends without a 30-second wait for its session sender. The runner asks the sender to stop again each second until the request reaches it.
16
+ - 5301041: The runner logs a line for each repository a claim left out because its GitHub organization's App installation is suspended, and builds in the repositories it was given. It now reports runner protocol 22.
17
+
18
+ ## 0.21.0
19
+
20
+ ### Minor Changes
21
+
22
+ - befe174: A container build receives its gh configuration, commit hooks, staged context and check input through `docker exec`, into `/outerlayer/job` inside the container. Nothing from the runner's disk is mounted into it. A build an older runner started keeps its mount until it ends.
23
+ - 5481fcb: A container build reaches the runner through `docker exec`, with no socket shared through the runner's disk. The relay in the build runs as its own user, which the agent cannot be. A build an older runner started keeps working after the runner updates.
24
+
25
+ ### Patch Changes
26
+
27
+ - f046dea: A control plane or repository can keep its skills in `.agents/skills/`. `outerlayer claude` and host builds give them to Claude Code under their own names. Every host build now starts its agent through `outerlayer claude`.
28
+
29
+ ## 0.20.0
30
+
31
+ ### Minor Changes
32
+
33
+ - 89270e0: `outerlayer emit criteria` reads an acceptance file ending in `.md`, so a person can record or replace an item's criteria from the file a build committed.
34
+ - bf0bf30: `outerlayer work stop --item <n>` asks the host building an item to stop. The runner reports what it is doing, so an item can say why nothing is building it.
35
+
3
36
  ## 0.19.1
4
37
 
5
38
  ### Patch Changes
package/README.md CHANGED
@@ -91,8 +91,10 @@ content:
91
91
  work item's general thread or a criterion thread — the detected session id
92
92
  rides along the same way it does for `emit`, only ever narrowing what the
93
93
  comment may do; `outerlayer work threads` reads them back. `outerlayer work logs`
94
- reads the runner's log for a host attempt. A runner key
95
- needs `git.read` and `work.read` to
94
+ reads the runner's log for a host attempt. `outerlayer work stop` sends
95
+ `POST /v1/work-items/<n>/claim/stop` with the optional note, and the
96
+ gateway records the request against the item's live host build. A runner
97
+ key needs `git.read` and `work.read` to
96
98
  list and read items, and `work.claim` to claim, renew or release — `work.claim`
97
99
  is not granted to a dashboard role by default, since a claim is a host's
98
100
  lease, not a person's.
@@ -118,6 +120,12 @@ content:
118
120
  off for want of disk it adds the free and needed bytes. While a check of
119
121
  its own stops it claiming, it adds one sentence saying why, which can
120
122
  include the host's usable memory and Docker's own error text, unscrubbed.
123
+ Every heartbeat also says what the runner is doing about new work (taking
124
+ work, draining, restarting, holding for an update, blocked or low on
125
+ disk), the queues and repository patterns it takes, and, while draining,
126
+ the numbers of the items it waits on. The reply can name a build that
127
+ someone stopped with `outerlayer work stop`; the runner then ends that
128
+ build and releases it as stopped, with the name of whoever stopped it.
121
129
  When a build's command exits 0, it reads that work item once more, for its
122
130
  evidence verdict, before releasing it: it sends nothing but the request.
123
131
  Just before that read, the runner runs the repository's host checks. A host
@@ -217,10 +225,20 @@ content:
217
225
  connections from the host only, and the runner runs every step of the build
218
226
  through it, including the build's command (`outerlayer vm-exec` on the host).
219
227
  - **`outerlayer runner start` with `builtin:container` hooks** runs each
220
- build in its own Docker container, which has no network but loopback. The
221
- build reaches the network only through a tunnel the runner serves on a
222
- Unix socket, which the container's own `outerlayer broker-relay` process
223
- reaches from loopback. The tunnel refuses loopback, private, link-local,
228
+ build in its own Docker container, which has no network but loopback. A
229
+ container build reaches the runner through `docker exec`: the runner starts
230
+ `outerlayer broker-relay join` in the container and serves one HTTP/2
231
+ session over that process's standard input and output. The container's own
232
+ `outerlayer broker-relay` process, which runs as a separate unprivileged
233
+ user, sends each loopback connection to the runner as one stream, and no
234
+ socket file is shared between the runner and the container. The build's
235
+ files (gh's configuration with the read token, the commit hooks, the staged
236
+ context, a check's input) are copied into `/outerlayer/job` by piping a tar
237
+ stream into `docker exec -i` running `outerlayer receive-files` as that
238
+ unprivileged user, so nothing from the runner's disk is mounted into the
239
+ container and the agent cannot change what it reads. (A build an older
240
+ runner started keeps its mounted folder and its Unix sockets until it ends.) The build
241
+ reaches the network only through a tunnel the runner serves. The tunnel refuses loopback, private, link-local,
224
242
  shared-address, multicast and unique-local addresses and the host's own,
225
243
  and it terminates no TLS. The tunnel also serves the build a local git
226
244
  remote. Git in the container still shows
@@ -408,6 +426,7 @@ before it gives up.
408
426
  | `outerlayer emit artifact <file> --caption <text> [--for <criterion-id>] [--pr <n>]` | Upload a proof artifact — screenshot, recording, report, or log — with its caption. Inside a recorded session it spools locally and ships on the next `sync`; otherwise it uploads immediately, anchored to a pull request or the current checkout. `--replaces` retires artifacts an earlier run uploaded. A JUnit XML file bound with `--for` proves a criterion that declares `test` proof; `--test <name[=path:line]>` binds only the named tests. |
409
427
  | `outerlayer emit <name> --result <pass\|fail> [--link <url>] [--body <text>\|--body-file <path>] --item <number>` | Record one named check's outcome on a work item. A check that ran carries the run URL as its proof (`--link`); a judgment you are making yourself carries one sentence (`--body`, or `--body-file` to read it from a file — `-` reads standard input). A `fail` needs at least one of the two; a `pass` needs neither. `--item` names the work item by the number printed when the item was created — always required, in or out of a recorded session; a session records checks on its own item like any other, stored as the session's, but cannot clear a person's fail. Prints the recorded check's id. Who recorded it comes from your API key, never from what you send. |
410
428
  | `outerlayer work comment --item <n> [--criterion <id>] --body <text> [--artifact <id>] [--pass\|--fail\|--attach\|--ready]` | Post one comment on a work item's general thread, or on one acceptance criterion's own thread with `--criterion`. `--pass`/`--fail` need a person's own credential and apply to the whole item, so they work on the general thread only and the gateway refuses them with `--criterion`; `--attach` makes the named artifact that criterion's current proof; `--ready` hands a thread back to a person. The detected session id rides along automatically, only ever narrowing what the comment may do. |
429
+ | `outerlayer work stop --item <n> [--note <text>]` | Ask the host that holds the item's build to end it. The host reads the request at its next heartbeat and ends the build with outcome `stopped`, so the build may run a little longer. The item is not built again until a new build request. Needs `work.update`. Exits 1 when no host build is running for the item. |
411
430
  | `outerlayer work logs --item <n> [--attempt <claim id>]` | Print the runner's log for a host attempt on a work item: the newest attempt a runner made, or the one `--attempt` names (an `id` from `claims` in `work status --json`). The log is what the runner did around the agent, with secrets removed on the host. Exits 1 for an attempt that is still running or that an older runner released without a log. |
412
431
  | `outerlayer work threads --item <n>` | Read a work item's threads back — the general thread first, then one per criterion with proof or a comment, each with its `waitingOn`. |
413
432
  | `outerlayer emit finding --id <id> --category <context\|flaky-test\|tooling\|environment\|defect\|other> --title <text> --file <path> --where <label> [--line <n>] [--item <number>] [--cause <text>] [--detail <text>] [--suggestion <text>] [--command <text>] [--error <text>] [--test <name>] [--symbol <name>] [--started-at <event> --ended-at <event>] [--problem <id> … --link-reason <text> \| --new] …` | Record one problem you hit in the factory. `--category` is one of `context` (an instruction that is wrong, broken or missing), `flaky-test`, `tooling`, `environment`, `defect` (a bug outside your own change) or `other`. A `context` finding also needs `--rule-path` and `--rule-relation` (`wrong`, `broken` or `missing`), and `--rule-quote` unless the relation is `missing`. `--cause`, `--detail`, `--suggestion`, `--command`, `--error` (the first error line), `--test` and `--symbol` carry what a fix needs. Every finding joins a factory-level problem: when a key of the finding matches a known problem it joins that problem; otherwise nothing is stored, the closest problems are printed, and the command exits with code 3. Run it again with `--problem <id> --link-reason <text>` (repeat `--problem` for each problem the finding reports) or with `--new`. Without `--started-at`, it prints the session's recent events with ids and times; name the event where you hit the problem and the one where you got past it with `--started-at` and `--ended-at`. Findings are informational; nothing reads one to pass or fail the work. `--item` names the work item; without it, inside a recorded session, the item that session was launched for is used automatically. Re-emitting the same `--id` on the item replaces that finding and keeps its problems. |
@@ -429,7 +448,7 @@ before it gives up.
429
448
  | `outerlayer runner check [--config <path>]` | Validates the config, the hooks and the key, prints the settings the runner would use, and exits non-zero on a problem. Takes no work and writes no pid file. |
430
449
  | `outerlayer runner start [--config <path>]` | Runs the loop: claim work, run it, sync, clean up, report, release with an outcome. Repeat. Reads the `runner` block from the config file (default `~/.outerlayer/config.json`). Refuses to start on a bad config, an unrunnable hook, or a refused key. |
431
450
  | `outerlayer runner image --repository <owner/name> [--remote <url>] [--config <path>] [--json]` | Builds the image a repository's builds run in. Fetches the head of the default branch into the runner's cache, builds its `.devcontainer/devcontainer.json` with the devcontainer CLI, ignores every setting that reaches the host or widens the container's privileges, and adds this CLI and a pinned Claude Code. Reuses the image until the recipe or the tools change, keeps the newest three, and writes `recipe.json` beside the image record. Refuses a Compose recipe (`recipe_needs_docker`) and a repository with only named configurations (`recipe_ambiguous`). |
432
- | `outerlayer runner stop [--config <path>] [--now]` | Takes no more work and waits for running jobs to finish, naming each every five seconds. `--now` ends them immediately with outcome `stopped`. Ctrl-C on a foreground runner drains; a second one stops now. |
451
+ | `outerlayer runner stop [--config <path>] [--now]` | Takes no more work and waits for running jobs to finish, naming each every five seconds. `--now` ends them immediately with outcome `stopped`. Ctrl-C on a foreground runner drains; a second one stops now. A container build keeps running when its runner restarts or crashes, and stops when its lease expires with no runner. |
433
452
  | `outerlayer runner status [--config <path>] [--recent] [--json]` | A header naming the runner's own state, then a row per running job — item, queue, stage, elapsed, started, lease, job directory. `--recent` adds finished jobs, newest first, capped at 20, with their outcomes. |
434
453
  | `outerlayer runner logs <item> [--config <path>] [-f]` | Prints the newest attempt's log for one item, following it with `-f`. |
435
454
 
@@ -1,27 +1,28 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- export { keepHandWritten, runAgentSetup } from './chunk-CGGPS7SI.js';
4
- import './chunk-5VML45HH.js';
5
- import './chunk-YVZJ6GKF.js';
6
- import './chunk-6X4SQ5MY.js';
7
- import './chunk-ANPNT6PM.js';
8
- import './chunk-EAEELQVQ.js';
9
- import './chunk-7UWVLZXD.js';
10
- import './chunk-FVMYKL6L.js';
3
+ export { keepHandWritten, runAgentSetup } from './chunk-JVB63NIB.js';
4
+ import './chunk-XCRZTXRL.js';
5
+ import './chunk-KOQELWQ6.js';
6
+ import './chunk-USWVXQIH.js';
7
+ import './chunk-VWLOQ6FI.js';
11
8
  import './chunk-NTRCK4NH.js';
12
9
  import './chunk-ZJSNLVCE.js';
13
10
  import './chunk-BJ3KTMDH.js';
14
- import './chunk-NNLA7LLQ.js';
11
+ import './chunk-DIB2WLBL.js';
15
12
  import './chunk-EABW6AJQ.js';
13
+ import './chunk-V7SAQ645.js';
14
+ import './chunk-5OCIHFGE.js';
15
+ import './chunk-ANPNT6PM.js';
16
16
  import './chunk-CRB3POP4.js';
17
17
  import './chunk-YQR6E6OV.js';
18
18
  import './chunk-WFSUUUAN.js';
19
19
  import './chunk-7VUK5RFS.js';
20
20
  import './chunk-VNVZDWO3.js';
21
21
  import './chunk-RA3O54FC.js';
22
- import './chunk-M2ZWWTWZ.js';
23
- import './chunk-N2PXGQRL.js';
24
- import './chunk-BQXFBI7T.js';
22
+ import './chunk-KDHYLBRR.js';
23
+ import './chunk-KIGSGZBB.js';
24
+ import './chunk-V7MQKOZY.js';
25
+ import './chunk-GISNHSYL.js';
25
26
  import './chunk-Z5GEFMRW.js';
26
27
 
27
28
  createRequire(import.meta.url);
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire } from 'node:module';
3
+ export { buildRepositoryImage } from './chunk-IRBNIRQJ.js';
4
+ export { RecipeError } from './chunk-3W333NFO.js';
5
+ import './chunk-ZFLOGMUC.js';
6
+ import './chunk-JBJTC3UU.js';
7
+ import './chunk-KIGSGZBB.js';
8
+ import './chunk-V7MQKOZY.js';
9
+ import './chunk-GISNHSYL.js';
10
+ import './chunk-Z5GEFMRW.js';
11
+
12
+ createRequire(import.meta.url);
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire } from 'node:module';
3
+ import './chunk-Z5GEFMRW.js';
4
+ import { spawn } from 'child_process';
5
+ import { mkdirSync, openSync, closeSync, writeFileSync, renameSync } from 'fs';
6
+ import { constants } from 'os';
7
+ import { join } from 'path';
8
+
9
+ createRequire(import.meta.url);
10
+ var COMMAND_LOG_FILE = "command.log";
11
+ var COMMAND_PID_FILE = "command.pid";
12
+ var COMMAND_EXIT_FILE = "exit-code";
13
+ var NOT_FOUND = 127;
14
+ var NOT_RUNNABLE = 126;
15
+ function writeWhole(dir, name, text) {
16
+ const partial = join(dir, `${name}.partial`);
17
+ writeFileSync(partial, text);
18
+ renameSync(partial, join(dir, name));
19
+ }
20
+ function runBuildCommand(input) {
21
+ const { dir, argv } = input;
22
+ mkdirSync(dir, { recursive: true });
23
+ writeWhole(dir, COMMAND_PID_FILE, `${process.pid}
24
+ `);
25
+ const log = openSync(join(dir, COMMAND_LOG_FILE), "a");
26
+ return new Promise((resolve) => {
27
+ const [program, ...args] = argv;
28
+ const child = spawn(program, args, { stdio: ["ignore", log, log], env: process.env });
29
+ const forwarded = ["SIGTERM", "SIGINT", "SIGHUP"];
30
+ const forward = (signal) => void child.kill(signal);
31
+ for (const signal of forwarded) process.on(signal, forward);
32
+ let settled = false;
33
+ const finish = (status) => {
34
+ if (settled) return;
35
+ settled = true;
36
+ for (const signal of forwarded) process.off(signal, forward);
37
+ closeSync(log);
38
+ try {
39
+ writeWhole(dir, COMMAND_EXIT_FILE, `${status}
40
+ `);
41
+ } catch {
42
+ }
43
+ resolve(status);
44
+ };
45
+ child.once("error", (err) => finish(err.code === "ENOENT" ? NOT_FOUND : NOT_RUNNABLE));
46
+ child.once("close", (code, signal) => finish(code ?? 128 + (signal === null ? 0 : constants.signals[signal] ?? 0)));
47
+ });
48
+ }
49
+
50
+ export { runBuildCommand };
@@ -1 +1 @@
1
- {"id":"2026-10-13T20:24:21.442Z+3c40b5d","root":"/home/runner/_work/outerlayer/outerlayer","pkg":"outerlayer"}
1
+ {"id":"2026-10-14T18:45:24.867Z+6bab5c0","root":"/home/runner/_work/outerlayer/outerlayer","pkg":"outerlayer"}
@@ -1,12 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- export { MIN_BUILDX_VERSION, builderName, builderSpec, buildxState, ensureBuilder, ensureFailureCount, isOutOfMemory, proxyEnvironment, trackImageBuild } from './chunk-3UZTIRLF.js';
3
+ export { MIN_BUILDX_VERSION, builderName, builderSpec, buildxState, ensureBuilder, ensureFailureCount, isOutOfMemory, proxyEnvironment, trackImageBuild } from './chunk-WERZMIKA.js';
4
+ import './chunk-3W333NFO.js';
4
5
  import './chunk-7RQ73DLO.js';
5
- import './chunk-CX22S5BA.js';
6
- import './chunk-QNLX477Q.js';
6
+ import './chunk-AEKSX4EY.js';
7
7
  import './chunk-7VUK5RFS.js';
8
- import './chunk-N2PXGQRL.js';
9
- import './chunk-BQXFBI7T.js';
8
+ import './chunk-KDHYLBRR.js';
9
+ import './chunk-KIGSGZBB.js';
10
+ import './chunk-V7MQKOZY.js';
11
+ import './chunk-GISNHSYL.js';
10
12
  import './chunk-Z5GEFMRW.js';
11
13
 
12
14
  createRequire(import.meta.url);
@@ -1,77 +1,75 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { probeCredentials } from './chunk-F2KXHIFI.js';
4
- import './chunk-B6SCN5NY.js';
5
- import './chunk-MTP2QEVO.js';
6
- import './chunk-S5PCA3SN.js';
3
+ import { probeCredentials } from './chunk-22DYXLU7.js';
4
+ import './chunk-FGW2774C.js';
7
5
  import './chunk-3JVYMD4G.js';
8
- import './chunk-YETTWTAY.js';
9
- import './chunk-SADUQSO4.js';
10
6
  import './chunk-I2UOAV7X.js';
11
- import './chunk-BWSUPRDK.js';
12
- import './chunk-JHGEBPLE.js';
13
- import './chunk-XNGMQ27R.js';
14
- import './chunk-R22NZSGA.js';
15
- import './chunk-KYS3TQAG.js';
7
+ import './chunk-YETTWTAY.js';
8
+ import './chunk-TPKYTORP.js';
9
+ import './chunk-KPBQYEND.js';
10
+ import './chunk-2J5JGLW5.js';
11
+ import './chunk-ATRIVTRE.js';
12
+ import './chunk-UD3EXMKB.js';
13
+ import './chunk-34XORKFD.js';
14
+ import './chunk-G2WME4RG.js';
16
15
  import './chunk-ESVW4MJY.js';
17
- import { placeholderQueues, placeholderProblem, permissionModeProblems, permissionModeProblem, needsClaudeCredential, claudeCredentialCheck, claimPermissionProblem, formerSkillQueues, formerSkillProblem } from './chunk-GEMQLBMW.js';
16
+ import { placeholderQueues, placeholderProblem, permissionModeProblems, permissionModeProblem, needsClaudeCredential, claudeCredentialCheck, claimPermissionProblem, formerSkillQueues, formerSkillProblem } from './chunk-WMHYIBJW.js';
18
17
  import './chunk-YYYRBYWG.js';
19
- import './chunk-AMFWYESY.js';
18
+ import './chunk-4NM3I3VV.js';
20
19
  import './chunk-TBT347UY.js';
21
- import './chunk-PIZRPNKR.js';
22
- import './chunk-7YP7T6GV.js';
23
- import './chunk-LW7G5TJB.js';
24
- import './chunk-3ZR7Y23Y.js';
25
- import './chunk-OGFGZQA3.js';
26
- import './chunk-VMJPFQNE.js';
27
- import './chunk-3UZTIRLF.js';
28
- import './chunk-GGOMT6KF.js';
29
- import './chunk-X5H2WYMB.js';
30
- import './chunk-XZ4H4X5F.js';
31
- import './chunk-QEFKA2QD.js';
20
+ import './chunk-4QKLMNI3.js';
21
+ import './chunk-7V7KG3YM.js';
22
+ import './chunk-I66MQDXH.js';
32
23
  import { parseRunnerEnv } from './chunk-6MZSX4M7.js';
33
- import './chunk-FBTGMSQF.js';
34
- import './chunk-IF2OSI5T.js';
35
- import './chunk-CG36IONK.js';
24
+ import './chunk-EXV37PKS.js';
25
+ import './chunk-VX74ND77.js';
26
+ import './chunk-IRBNIRQJ.js';
27
+ import './chunk-OGFGZQA3.js';
28
+ import './chunk-WERZMIKA.js';
29
+ import './chunk-3W333NFO.js';
30
+ import './chunk-PHHBYAL6.js';
31
+ import './chunk-BLW6GPBZ.js';
32
+ import './chunk-C3OVGKVJ.js';
33
+ import './chunk-2HT2XGJX.js';
34
+ import './chunk-QOALB6ZD.js';
35
+ import './chunk-JRCSET55.js';
36
36
  import './chunk-G3IJ3N6F.js';
37
- import './chunk-BM63HB2M.js';
38
- import { loadRunnerConfig, RunnerConfigError, checkHooks } from './chunk-P53VEAOF.js';
37
+ import './chunk-EAQSOE62.js';
38
+ import './chunk-F35VMF5M.js';
39
+ import { loadRunnerConfig, RunnerConfigError, checkHooks } from './chunk-2CMJLYV6.js';
39
40
  import './chunk-UXYLWVTQ.js';
40
41
  import './chunk-7RQ73DLO.js';
41
- import './chunk-3CWUOFV6.js';
42
- import './chunk-QOZKPLVJ.js';
43
- import './chunk-CX22S5BA.js';
44
- import './chunk-ECODQ7II.js';
42
+ import './chunk-ZFLOGMUC.js';
45
43
  import './chunk-JBJTC3UU.js';
46
- import './chunk-PSN33ERW.js';
44
+ import './chunk-KOQELWQ6.js';
45
+ import './chunk-USWVXQIH.js';
46
+ import './chunk-VWLOQ6FI.js';
47
+ import './chunk-NTRCK4NH.js';
48
+ import './chunk-6IO62VJS.js';
49
+ import './chunk-ZJSNLVCE.js';
47
50
  import './chunk-F7CU5ABH.js';
48
51
  import './chunk-BKO6JEZI.js';
49
- import './chunk-QNLX477Q.js';
50
- import './chunk-GOSFARMS.js';
52
+ import './chunk-ZNPE7FW5.js';
53
+ import './chunk-HCVLP7XA.js';
54
+ import './chunk-BJ3KTMDH.js';
55
+ import './chunk-AEKSX4EY.js';
56
+ import './chunk-EABW6AJQ.js';
57
+ import './chunk-5OCIHFGE.js';
51
58
  import './chunk-ANPNT6PM.js';
52
59
  import './chunk-T2Q7ISPE.js';
53
60
  import './chunk-WZBHBH3J.js';
54
- import './chunk-5QRP3MVS.js';
55
- import './chunk-LLM3I5YU.js';
56
- import './chunk-EAEELQVQ.js';
57
- import './chunk-7UWVLZXD.js';
58
- import './chunk-FVMYKL6L.js';
59
- import './chunk-NTRCK4NH.js';
60
- import './chunk-ZJSNLVCE.js';
61
- import './chunk-BJ3KTMDH.js';
62
- import './chunk-G2YNJIGF.js';
63
- import './chunk-NNLA7LLQ.js';
64
- import './chunk-EABW6AJQ.js';
65
61
  import './chunk-CRB3POP4.js';
62
+ import './chunk-5QRP3MVS.js';
66
63
  import './chunk-YQR6E6OV.js';
67
64
  import './chunk-TUSYOL2O.js';
68
65
  import './chunk-WFSUUUAN.js';
69
66
  import './chunk-7VUK5RFS.js';
70
67
  import './chunk-VNVZDWO3.js';
71
68
  import './chunk-RA3O54FC.js';
72
- import './chunk-M2ZWWTWZ.js';
73
- import './chunk-N2PXGQRL.js';
74
- import './chunk-BQXFBI7T.js';
69
+ import './chunk-KDHYLBRR.js';
70
+ import './chunk-KIGSGZBB.js';
71
+ import './chunk-V7MQKOZY.js';
72
+ import './chunk-GISNHSYL.js';
75
73
  import './chunk-Z5GEFMRW.js';
76
74
  import { readFileSync } from 'fs';
77
75
  import { join, dirname } from 'path';