cargo-hauler 0.6.17 → 0.7.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.
- package/CHANGELOG.md +54 -0
- package/README.md +39 -5
- package/dist/.claude-plugin/marketplace.json +1 -1
- package/dist/.claude-plugin/plugin.json +1 -1
- package/dist/.codex-plugin/plugin.json +1 -1
- package/dist/.cursor-plugin/plugin.json +1 -1
- package/dist/INSTALL.md +1 -1
- package/dist/README.md +39 -5
- package/dist/agent-bundle.compile-evidence.json +1 -1
- package/dist/agent-bundle.manifest.json +1 -1
- package/dist/agent-bundle.package-compile-evidence.json +1 -1
- package/dist/bin/cargo-hauler-flight.mjs +446 -396
- package/dist/bin/cargo-hauler.mjs +1025 -683
- package/dist/bin/hauler.js +1230 -758
- package/dist/hooks/event-route-session-start.claude.mjs +2 -2
- package/dist/hooks/event-route-session-start.codex.mjs +2 -2
- package/dist/hooks/event-route-session-start.cursor.mjs +2 -2
- package/dist/hooks/event-route-stop.claude.mjs +2 -2
- package/dist/hooks/event-route-stop.codex.mjs +2 -2
- package/dist/hooks/event-route-stop.cursor.mjs +2 -2
- package/dist/hooks/event-route-tool-after.claude.execute.mjs +2 -2
- package/dist/hooks/event-route-tool-after.claude.mjs +12 -13
- package/dist/hooks/event-route-tool-after.codex.execute.mjs +2 -2
- package/dist/hooks/event-route-tool-after.codex.mjs +12 -13
- package/dist/hooks/event-route-tool-after.cursor.execute.mjs +2 -2
- package/dist/hooks/event-route-tool-after.cursor.mjs +12 -13
- package/dist/hooks/event-route-tool-before.claude.execute.mjs +2 -2
- package/dist/hooks/event-route-tool-before.codex.execute.mjs +2 -2
- package/dist/hooks/event-route-tool-before.cursor.execute.mjs +2 -2
- package/dist/hooks/hooks-flight.mjs +49 -43
- package/dist/install.mjs +1 -1
- package/dist/mcp/mcp-hauler-2b8242f9-flight.mjs +468 -419
- package/dist/mcp/mcp-hauler-2b8242f9.mjs +126 -76
- package/dist/mcp-apps/dashboard.html +7 -7
- package/dist/package.json +1 -2
- package/dist/plugin.json +1 -1
- package/dist/scripts/hauler.mjs +1230 -758
- package/dist/skills/cargo-hauler/SKILL.md +7 -3
- package/dist/skills/hauler-dashboard/SKILL.md +1 -1
- package/package.json +1 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,59 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.7.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 80939ab: A `hauler exec` whose daemon connection drops after the ticket was accepted now
|
|
8
|
+
reattaches instead of giving up. The client prints `connection to daemon lost;
|
|
9
|
+
reattaching to ticket cc-N…`, reconnects (starting the daemon again if it is
|
|
10
|
+
gone, a few attempts one second apart), and sends the new `reattach` message;
|
|
11
|
+
the daemon rebinds the ticket, replays the output the client had not yet
|
|
12
|
+
received, and streams the rest, so the caller's exit code is cargo's as if the
|
|
13
|
+
connection had held. Output the replay buffer no longer holds is announced as
|
|
14
|
+
`N bytes of output missed while reconnecting; full log: <path>`, never
|
|
15
|
+
invented. A ticket that finished in the meantime yields its exit code and log
|
|
16
|
+
path.
|
|
17
|
+
|
|
18
|
+
The daemon no longer kills a queued ticket the moment its submitter
|
|
19
|
+
disconnects: it keeps its queue position (and may start) for
|
|
20
|
+
`CARGO_HAULER_REATTACH_GRACE_MS` (default 30000; `0` restores the immediate
|
|
21
|
+
kill) and is killed as `killed while queued: submitter disconnected and did
|
|
22
|
+
not reattach within 30s` only if nobody reattaches. A running ticket continues
|
|
23
|
+
as before, marked orphaned; a reattach clears the flag.
|
|
24
|
+
|
|
25
|
+
When the ticket cannot be reattached — it never ran cargo and was killed at
|
|
26
|
+
the daemon's shutdown or `orphaned by daemon restart`, the daemon does not
|
|
27
|
+
know it, the daemon predates this release and answers the message with
|
|
28
|
+
`bad-message`, or no daemon answered within the budget — the client fails
|
|
29
|
+
closed with `brokered run aborted: daemon connection lost; ticket cc-N
|
|
30
|
+
<reason>` and the new exit code `69` (`EX_UNAVAILABLE`), distinct from cargo's
|
|
31
|
+
`1` and from `2`/`75`/`130`/`143`. It no longer prints `ticket cc-N continues
|
|
32
|
+
— hauler result cc-N` and exits `1` while the daemon records `killed while
|
|
33
|
+
queued`. `--bg` and auto-backgrounded tickets are detached, not owned, and
|
|
34
|
+
are unchanged. (#187)
|
|
35
|
+
- 3758d82: Refuse a target directory shared across workspace roots (#185). When a request's target dir lies outside its own workspace and another lane with a different workspace root already uses that dir, the daemon refuses it as a bad intent (client exit 2) with a message naming both roots, the dir, and the mechanism: cargo's `-C metadata` hash is relative to the workspace root, so same-layout worktrees write identical artifact filenames into a shared target dir and whichever compiled last runs as "fresh" in the others — a stale-binary collision, not a kache miss. `hauler exec --allow-shared-target` or `CARGO_HAULER_ALLOW_SHARED_TARGET=1` (per request, or in the daemon's environment for all requests) admits the request with one warning line on stderr that cargo's `--quiet` cannot hide. `hauler status` and the dashboard flag every lane on a shared dir with `sharedTargetWith` (optional; older daemons omit it). Refused intents — this one and the existing bad-intent rejections — are now ledgered as `denied` rows instead of `failed` runs under lane `invalid`, so `hauler log` no longer shows a command that never ran as a failed run.
|
|
36
|
+
|
|
37
|
+
### Patch Changes
|
|
38
|
+
|
|
39
|
+
- f84e901: `hauler exec --allow-shared-target` (and `CARGO_HAULER_ALLOW_SHARED_TARGET=1`
|
|
40
|
+
in the caller's environment) now reaches the daemon: the server dropped the
|
|
41
|
+
request field, so only the daemon-side setting could admit a shared target dir.
|
|
42
|
+
The shared-target warning has one wording everywhere — the daemon's refusal
|
|
43
|
+
and ack line, the lane board, and the dashboard's lane cell (other roots, full
|
|
44
|
+
text on hover) — and `hauler request` shows the daemon's warning in its summary
|
|
45
|
+
when the daemon admitted a shared target. The `hauler status` summary string
|
|
46
|
+
no longer carries extra warning lines the document never rendered; the lane
|
|
47
|
+
board is where the warning shows.
|
|
48
|
+
Detection no longer re-resolves already-canonical lane paths on every submit
|
|
49
|
+
and status poll.
|
|
50
|
+
|
|
51
|
+
## 0.6.18
|
|
52
|
+
|
|
53
|
+
### Patch Changes
|
|
54
|
+
|
|
55
|
+
- d344246: The `cargo-hauler` skill no longer tells agents how to set `CARGO_TARGET_DIR`. The one bullet that did ("do not hand-roll `CARGO_TARGET_DIR` isolation … the daemon already serializes per (workspace, target dir)") read as if sharing one target dir across checkouts were safe because runs are serialized; it is not — cargo's `-C metadata` hash is relative to the workspace root, so worktrees of one repo with the same layout collide on artifact names and stale binaries run silently (#185). Target-dir policy belongs to the operator and, where hauler can detect the footgun, to the daemon, not to the prompt. (#186)
|
|
56
|
+
|
|
3
57
|
## 0.6.17
|
|
4
58
|
|
|
5
59
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -77,8 +77,8 @@ The CLI is `hauler` on PATH from `npm i -g cargo-hauler`. Never run
|
|
|
77
77
|
|
|
78
78
|
| Command | Behavior |
|
|
79
79
|
| --- | --- |
|
|
80
|
-
| `hauler exec [--session ID] [--host HOST] [--cwd DIR] [--bg] [--after TICKET[,TICKET…]] -- <cargo …>` | Submit Cargo through the daemon and stream output; hooks rewrite commands to this form. A relative `--cwd` is resolved against the caller's directory. `--after` (repeatable or comma-separated) keeps the request queued until every named ticket has finished; it fails with `prerequisite cc-N <status>` if one of them fails or is killed, and an unknown ticket is rejected as a bad intent. Exits with cargo's code; `130`/`143` after a SIGINT/SIGTERM (the ticket is killed first); `75` when auto-backgrounded. |
|
|
81
|
-
| `hauler status [--limit N] [--cwd DIR] [--session ID] [--lane KEY] [--ticket ID …] [--status S …] [--command-contains TEXT]` | Queue, active runs, lanes, admission, kache, optionally filtered. Rows are bounded summaries: no row carries an output tail; a running row carries `outputPreview`, the last 8 lines (at most 512 bytes) of its live output, cut at a line boundary, and every other row has `outputPreview: null`. Read a ticket's whole tail with `hauler result`. |
|
|
80
|
+
| `hauler exec [--session ID] [--host HOST] [--cwd DIR] [--bg] [--after TICKET[,TICKET…]] [--allow-shared-target] -- <cargo …>` | Submit Cargo through the daemon and stream output; hooks rewrite commands to this form. A relative `--cwd` is resolved against the caller's directory. `--after` (repeatable or comma-separated) keeps the request queued until every named ticket has finished; it fails with `prerequisite cc-N <status>` if one of them fails or is killed, and an unknown ticket is rejected as a bad intent. `--allow-shared-target` accepts the stale-artifact risk described below and prints a warning. Exits with cargo's code; `130`/`143` after a SIGINT/SIGTERM (the ticket is killed first); `75` when auto-backgrounded; `69` when the daemon connection was lost and the ticket could not be reattached (see below). |
|
|
81
|
+
| `hauler status [--limit N] [--cwd DIR] [--session ID] [--lane KEY] [--ticket ID …] [--status S …] [--command-contains TEXT]` | Queue, active runs, lanes, admission, kache, optionally filtered. Lanes sharing one external target directory across workspace roots carry `sharedTargetWith` and render a warning naming the target and roots. Rows are bounded summaries: no row carries an output tail; a running row carries `outputPreview`, the last 8 lines (at most 512 bytes) of its live output, cut at a line boundary, and every other row has `outputPreview: null`. Read a ticket's whole tail with `hauler result`. |
|
|
82
82
|
| `hauler log [--limit N]` | Recent requests from the ledger, as the same bounded summary rows. |
|
|
83
83
|
| `hauler last` | The most recent request, as a detail record (from the daemon while it is running, otherwise from the ledger) — its output tail included. |
|
|
84
84
|
| `hauler await <ticket> [--max-wait-ms N]` | Long-poll until the ticket finishes or the wait expires (default 30 s, ceiling 2 h per call — the daemon's await ceiling; call again to keep waiting). A host with its own per-call deadline still bounds one call: Codex stops a tool call at `tool_timeout_sec` (60 s unless raised). |
|
|
@@ -187,6 +187,14 @@ arms defer admission under load. Attached requests (riders) do not hold
|
|
|
187
187
|
permits; the admission meter counts permit holders and reports riders
|
|
188
188
|
separately.
|
|
189
189
|
|
|
190
|
+
Different workspace roots must not share a target directory outside the
|
|
191
|
+
requesting workspace by default. Cargo's `-C metadata` hash is relative to the
|
|
192
|
+
workspace root, so same-layout git worktrees can write identical artifact
|
|
193
|
+
filenames there; whichever worktree compiled last may then be treated as fresh
|
|
194
|
+
and run by another. This is a stale-binary collision, not a kache miss. Use a
|
|
195
|
+
target directory per worktree, or opt in with `--allow-shared-target` /
|
|
196
|
+
`CARGO_HAULER_ALLOW_SHARED_TARGET=1` when that risk is intentional.
|
|
197
|
+
|
|
190
198
|
Within a lane, the daemon can reduce work in three ways:
|
|
191
199
|
|
|
192
200
|
1. **Identity attachment:** a byte-identical request attaches to an in-flight
|
|
@@ -327,6 +335,7 @@ own `-j` flag or `CARGO_BUILD_JOBS` always wins over both.
|
|
|
327
335
|
| --- | --- |
|
|
328
336
|
| Work sharing | Identical requests attach, covered checks and compile-only `test --no-run` requests attach, and compatible queued compile or test requests fold. |
|
|
329
337
|
| Lane isolation | A workspace-root and target-directory pair is serialized independently from other lanes. |
|
|
338
|
+
| Shared target safety | If different workspace roots use the same target directory outside the requesting workspace, the daemon refuses the later request unless explicitly allowed and status flags both lanes. |
|
|
330
339
|
| Admission | Per-core load, Linux CPU PSI, Linux memory PSI and `MemAvailable`, macOS VM pressure, configured thresholds, and the global permit cap control new starts. |
|
|
331
340
|
| Parallelism | One daemon-owned jobserver FIFO shared by every spawned Cargo; a per-run `CARGO_BUILD_JOBS` grant only when the FIFO could not be armed. |
|
|
332
341
|
| Scheduling | Per-phase EWMA estimates (compile vs execute), optional kache priors, fan-out, dependency topology, recent edits, and request age determine lane order; `--after cc-N` holds a request until the named tickets settle. |
|
|
@@ -381,9 +390,32 @@ answer, and exits `130` or `143`; in a direct run it terminates the cargo
|
|
|
381
390
|
process group the same way. A ticket that ends other than `done` is reported
|
|
382
391
|
on stderr as `ticket cc-N <status>[ (signal)][: reason]`, and its exit code is
|
|
383
392
|
cargo's, `128 + signal` for a signaled run, or `1` when the daemon could not
|
|
384
|
-
start cargo at all.
|
|
385
|
-
|
|
386
|
-
|
|
393
|
+
start cargo at all.
|
|
394
|
+
|
|
395
|
+
If the connection drops after the ticket was accepted (a daemon restart or
|
|
396
|
+
replacement, a dropped socket), the client keeps the ticket rather than the
|
|
397
|
+
connection: it prints `connection to daemon lost; reattaching to ticket
|
|
398
|
+
cc-N…`, reconnects — starting the daemon again if it is gone, a few attempts
|
|
399
|
+
one second apart — and sends `reattach`. The daemon meanwhile holds a ticket
|
|
400
|
+
whose submitter vanished: one still queued keeps its place for
|
|
401
|
+
`CARGO_HAULER_REATTACH_GRACE_MS` (30 s; it may start in the meantime) and is
|
|
402
|
+
killed as `killed while queued: submitter disconnected and did not reattach
|
|
403
|
+
within 30s` only if nobody comes back; one already running continues, marked
|
|
404
|
+
orphaned as before. A reattach rebinds the ticket to the new connection,
|
|
405
|
+
clears the orphan flag, replays the output the client had not yet received
|
|
406
|
+
from the replay buffer, and streams the rest, so the exit code is cargo's as
|
|
407
|
+
if nothing had happened; output the buffer no longer holds is announced as
|
|
408
|
+
`N bytes of output missed while reconnecting; full log: <path>` rather than
|
|
409
|
+
invented. A ticket that finished in the meantime yields its exit code and log
|
|
410
|
+
path. When the ticket cannot be reattached — it never ran cargo and was
|
|
411
|
+
killed at the daemon's shutdown, `orphaned by daemon restart`, unknown to the
|
|
412
|
+
daemon that answered, the daemon predates the message, or no daemon answered
|
|
413
|
+
within the budget — the client exits `69` (`EX_UNAVAILABLE`) with `brokered
|
|
414
|
+
run aborted: daemon connection lost; ticket cc-N <reason>`; it never claims
|
|
415
|
+
the build ran. `CARGO_HAULER_REATTACH_GRACE_MS=0` restores the earlier policy
|
|
416
|
+
of killing a queued ticket the moment its connection closes. `--bg` and
|
|
417
|
+
auto-backgrounded tickets are detached, not owned, and are untouched by any
|
|
418
|
+
of this.
|
|
387
419
|
|
|
388
420
|
A deadlocked test binary holds its lane for ever at 0% CPU with nothing on
|
|
389
421
|
stdout, and neither the estimate overrun nor the output silence alone can
|
|
@@ -606,6 +638,7 @@ Per-host notes and hook timeouts are in [docs/install.md](docs/install.md).
|
|
|
606
638
|
| `CARGO_HAULER_CARGO_BIN` | `$CARGO_HOME/bin/cargo` | Cargo binary for daemon-started work; bare `cargo` is the last fallback. Never resolved through `PATH`. Read from the daemon's own environment (export it where the daemon starts, or before `hauler daemon start`); clients do not forward it. |
|
|
607
639
|
| `CARGO_HAULER_MAX_CONCURRENT` | cores ÷ 8, clamped to 5–16 | Global admission permits for Cargo processes across all lanes; an integer >= 1. |
|
|
608
640
|
| `CARGO_HAULER_OVERLAP_EXECUTION` | `1` | Hand a lane to its next request once a `test`/`nextest`/`bench`/`run` leader reports its build finished, overlapping the next compile with the leader's execution phase. `0` keeps a lane strictly one process at a time. |
|
|
641
|
+
| `CARGO_HAULER_ALLOW_SHARED_TARGET` | `0` | Allow different workspace roots to use one external target directory. The daemon still warns and status flags the lanes because Cargo artifacts can collide. Set on the request as `1`, or in the daemon environment to allow all requests. |
|
|
609
642
|
| `CARGO_HAULER_JOBS_GRANT` | `max(4, cores / max concurrent)` | `CARGO_BUILD_JOBS` added to each Cargo process only while the shared jobserver FIFO is not armed; an armed daemon injects `MAKEFLAGS` instead and leaves `CARGO_BUILD_JOBS` unset. `0` disables injection. |
|
|
610
643
|
| `CARGO_HAULER_JOBSERVER` | `auto` | Machine-wide fifo jobserver for daemon-spawned cargo: `auto` arms it only when the host `make` is 4.4+ (or absent) because older makes reject `--jobserver-auth=fifo:` in build scripts; `fifo` forces it on, `off` disables it (per-run `CARGO_BUILD_JOBS` grants apply instead). |
|
|
611
644
|
| `CARGO_HAULER_LOAD_THRESHOLD` | Disabled | Per-core one-minute load threshold for deferring new admissions. |
|
|
@@ -625,6 +658,7 @@ Per-host notes and hook timeouts are in [docs/install.md](docs/install.md).
|
|
|
625
658
|
| `CARGO_HAULER_STALL_ESTIMATE_FACTOR` | `3` | A running ticket becomes a stall candidate once its elapsed time exceeds this multiple of its estimate. |
|
|
626
659
|
| `CARGO_HAULER_STALL_IDLE_MS` | `600000` | Window with no process-tree CPU time and no output after which a stall candidate is flagged `stalled`; `0` or `off` disables stall detection. |
|
|
627
660
|
| `CARGO_HAULER_STALL_AUTO_KILL` | Enabled | Kill a stalled ticket automatically once the connection that submitted it has disconnected. `0`, `false`, `off`, or `no` only flags it. |
|
|
661
|
+
| `CARGO_HAULER_REATTACH_GRACE_MS` | `30000` | How long a queued ticket keeps its place after its submitting connection dropped, waiting for the client to `reattach`; then it is killed as abandoned. `0` kills it the moment the connection closes. |
|
|
628
662
|
| `CARGO_HAULER_STOP_WAIT_MS` | `30000` | Maximum wait for one stop-hook invocation; values above the 7200000 ms await ceiling are clamped. |
|
|
629
663
|
| `CARGO_HAULER_LEDGER_RETENTION_DAYS` | `30` | Finished ledger rows older than this many days are deleted when the daemon starts; `0` disables the age limit. |
|
|
630
664
|
| `CARGO_HAULER_LEDGER_MAX_ROWS` | `50000` | Total ledger rows beyond which the oldest finished rows are deleted when the daemon starts; `0` disables the row cap. Pruned rows take their `tickets/<ticket>.log` files with them. |
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"description":"Coalesce, schedule, and stream cargo so concurrent agent sessions share compiles instead of fighting locks.","name":"cargo-hauler-marketplace","owner":{"name":"cargo-hauler"},"plugins":[{"description":"Coalesce, schedule, and stream cargo so concurrent agent sessions share compiles instead of fighting locks.","name":"cargo-hauler","source":"./","version":"0.
|
|
1
|
+
{"description":"Coalesce, schedule, and stream cargo so concurrent agent sessions share compiles instead of fighting locks.","name":"cargo-hauler-marketplace","owner":{"name":"cargo-hauler"},"plugins":[{"description":"Coalesce, schedule, and stream cargo so concurrent agent sessions share compiles instead of fighting locks.","name":"cargo-hauler","source":"./","version":"0.7.0"}]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"author":{"name":"cargo-hauler"},"description":"Coalesce, schedule, and stream cargo so concurrent agent sessions share compiles instead of fighting locks.","name":"cargo-hauler","version":"0.
|
|
1
|
+
{"author":{"name":"cargo-hauler"},"description":"Coalesce, schedule, and stream cargo so concurrent agent sessions share compiles instead of fighting locks.","name":"cargo-hauler","version":"0.7.0"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"author":{"name":"cargo-hauler"},"description":"Coalesce, schedule, and stream cargo so concurrent agent sessions share compiles instead of fighting locks.","hooks":"./.codex-plugin/hooks.json","interface":{"capabilities":["mcp","hooks","skills"],"category":"Productivity","defaultPrompt":["Help me use cargo-hauler."],"developerName":"cargo-hauler","displayName":"cargo-hauler","longDescription":"Coalesce, schedule, and stream cargo so concurrent agent sessions share compiles instead of fighting locks.","shortDescription":"Coalesce, schedule, and stream cargo so concurrent agent sessions share compiles instead of fighting locks."},"mcpServers":"./.codex-plugin/mcp.json","name":"cargo-hauler","skills":"./skills/","version":"0.
|
|
1
|
+
{"author":{"name":"cargo-hauler"},"description":"Coalesce, schedule, and stream cargo so concurrent agent sessions share compiles instead of fighting locks.","hooks":"./.codex-plugin/hooks.json","interface":{"capabilities":["mcp","hooks","skills"],"category":"Productivity","defaultPrompt":["Help me use cargo-hauler."],"developerName":"cargo-hauler","displayName":"cargo-hauler","longDescription":"Coalesce, schedule, and stream cargo so concurrent agent sessions share compiles instead of fighting locks.","shortDescription":"Coalesce, schedule, and stream cargo so concurrent agent sessions share compiles instead of fighting locks."},"mcpServers":"./.codex-plugin/mcp.json","name":"cargo-hauler","skills":"./skills/","version":"0.7.0"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"description":"Coalesce, schedule, and stream cargo so concurrent agent sessions share compiles instead of fighting locks.","displayName":"cargo-hauler","hooks":"./.cursor-plugin/hooks.json","mcpServers":"./.cursor-plugin/mcp.json","name":"cargo-hauler","skills":"./skills/","version":"0.
|
|
1
|
+
{"description":"Coalesce, schedule, and stream cargo so concurrent agent sessions share compiles instead of fighting locks.","displayName":"cargo-hauler","hooks":"./.cursor-plugin/hooks.json","mcpServers":"./.cursor-plugin/mcp.json","name":"cargo-hauler","skills":"./skills/","version":"0.7.0"}
|
package/dist/INSTALL.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Coalesce, schedule, and stream cargo so concurrent agent sessions share compiles instead of fighting locks.
|
|
4
4
|
|
|
5
|
-
Version: `0.
|
|
5
|
+
Version: `0.7.0`
|
|
6
6
|
|
|
7
7
|
Run these commands from this bundle directory. The bundle is self-contained: every command below is
|
|
8
8
|
a host command or the bundled installer, and nothing requires the `agent-bundle` CLI. Where that CLI is
|
package/dist/README.md
CHANGED
|
@@ -77,8 +77,8 @@ The CLI is `hauler` on PATH from `npm i -g cargo-hauler`. Never run
|
|
|
77
77
|
|
|
78
78
|
| Command | Behavior |
|
|
79
79
|
| --- | --- |
|
|
80
|
-
| `hauler exec [--session ID] [--host HOST] [--cwd DIR] [--bg] [--after TICKET[,TICKET…]] -- <cargo …>` | Submit Cargo through the daemon and stream output; hooks rewrite commands to this form. A relative `--cwd` is resolved against the caller's directory. `--after` (repeatable or comma-separated) keeps the request queued until every named ticket has finished; it fails with `prerequisite cc-N <status>` if one of them fails or is killed, and an unknown ticket is rejected as a bad intent. Exits with cargo's code; `130`/`143` after a SIGINT/SIGTERM (the ticket is killed first); `75` when auto-backgrounded. |
|
|
81
|
-
| `hauler status [--limit N] [--cwd DIR] [--session ID] [--lane KEY] [--ticket ID …] [--status S …] [--command-contains TEXT]` | Queue, active runs, lanes, admission, kache, optionally filtered. Rows are bounded summaries: no row carries an output tail; a running row carries `outputPreview`, the last 8 lines (at most 512 bytes) of its live output, cut at a line boundary, and every other row has `outputPreview: null`. Read a ticket's whole tail with `hauler result`. |
|
|
80
|
+
| `hauler exec [--session ID] [--host HOST] [--cwd DIR] [--bg] [--after TICKET[,TICKET…]] [--allow-shared-target] -- <cargo …>` | Submit Cargo through the daemon and stream output; hooks rewrite commands to this form. A relative `--cwd` is resolved against the caller's directory. `--after` (repeatable or comma-separated) keeps the request queued until every named ticket has finished; it fails with `prerequisite cc-N <status>` if one of them fails or is killed, and an unknown ticket is rejected as a bad intent. `--allow-shared-target` accepts the stale-artifact risk described below and prints a warning. Exits with cargo's code; `130`/`143` after a SIGINT/SIGTERM (the ticket is killed first); `75` when auto-backgrounded; `69` when the daemon connection was lost and the ticket could not be reattached (see below). |
|
|
81
|
+
| `hauler status [--limit N] [--cwd DIR] [--session ID] [--lane KEY] [--ticket ID …] [--status S …] [--command-contains TEXT]` | Queue, active runs, lanes, admission, kache, optionally filtered. Lanes sharing one external target directory across workspace roots carry `sharedTargetWith` and render a warning naming the target and roots. Rows are bounded summaries: no row carries an output tail; a running row carries `outputPreview`, the last 8 lines (at most 512 bytes) of its live output, cut at a line boundary, and every other row has `outputPreview: null`. Read a ticket's whole tail with `hauler result`. |
|
|
82
82
|
| `hauler log [--limit N]` | Recent requests from the ledger, as the same bounded summary rows. |
|
|
83
83
|
| `hauler last` | The most recent request, as a detail record (from the daemon while it is running, otherwise from the ledger) — its output tail included. |
|
|
84
84
|
| `hauler await <ticket> [--max-wait-ms N]` | Long-poll until the ticket finishes or the wait expires (default 30 s, ceiling 2 h per call — the daemon's await ceiling; call again to keep waiting). A host with its own per-call deadline still bounds one call: Codex stops a tool call at `tool_timeout_sec` (60 s unless raised). |
|
|
@@ -187,6 +187,14 @@ arms defer admission under load. Attached requests (riders) do not hold
|
|
|
187
187
|
permits; the admission meter counts permit holders and reports riders
|
|
188
188
|
separately.
|
|
189
189
|
|
|
190
|
+
Different workspace roots must not share a target directory outside the
|
|
191
|
+
requesting workspace by default. Cargo's `-C metadata` hash is relative to the
|
|
192
|
+
workspace root, so same-layout git worktrees can write identical artifact
|
|
193
|
+
filenames there; whichever worktree compiled last may then be treated as fresh
|
|
194
|
+
and run by another. This is a stale-binary collision, not a kache miss. Use a
|
|
195
|
+
target directory per worktree, or opt in with `--allow-shared-target` /
|
|
196
|
+
`CARGO_HAULER_ALLOW_SHARED_TARGET=1` when that risk is intentional.
|
|
197
|
+
|
|
190
198
|
Within a lane, the daemon can reduce work in three ways:
|
|
191
199
|
|
|
192
200
|
1. **Identity attachment:** a byte-identical request attaches to an in-flight
|
|
@@ -327,6 +335,7 @@ own `-j` flag or `CARGO_BUILD_JOBS` always wins over both.
|
|
|
327
335
|
| --- | --- |
|
|
328
336
|
| Work sharing | Identical requests attach, covered checks and compile-only `test --no-run` requests attach, and compatible queued compile or test requests fold. |
|
|
329
337
|
| Lane isolation | A workspace-root and target-directory pair is serialized independently from other lanes. |
|
|
338
|
+
| Shared target safety | If different workspace roots use the same target directory outside the requesting workspace, the daemon refuses the later request unless explicitly allowed and status flags both lanes. |
|
|
330
339
|
| Admission | Per-core load, Linux CPU PSI, Linux memory PSI and `MemAvailable`, macOS VM pressure, configured thresholds, and the global permit cap control new starts. |
|
|
331
340
|
| Parallelism | One daemon-owned jobserver FIFO shared by every spawned Cargo; a per-run `CARGO_BUILD_JOBS` grant only when the FIFO could not be armed. |
|
|
332
341
|
| Scheduling | Per-phase EWMA estimates (compile vs execute), optional kache priors, fan-out, dependency topology, recent edits, and request age determine lane order; `--after cc-N` holds a request until the named tickets settle. |
|
|
@@ -381,9 +390,32 @@ answer, and exits `130` or `143`; in a direct run it terminates the cargo
|
|
|
381
390
|
process group the same way. A ticket that ends other than `done` is reported
|
|
382
391
|
on stderr as `ticket cc-N <status>[ (signal)][: reason]`, and its exit code is
|
|
383
392
|
cargo's, `128 + signal` for a signaled run, or `1` when the daemon could not
|
|
384
|
-
start cargo at all.
|
|
385
|
-
|
|
386
|
-
|
|
393
|
+
start cargo at all.
|
|
394
|
+
|
|
395
|
+
If the connection drops after the ticket was accepted (a daemon restart or
|
|
396
|
+
replacement, a dropped socket), the client keeps the ticket rather than the
|
|
397
|
+
connection: it prints `connection to daemon lost; reattaching to ticket
|
|
398
|
+
cc-N…`, reconnects — starting the daemon again if it is gone, a few attempts
|
|
399
|
+
one second apart — and sends `reattach`. The daemon meanwhile holds a ticket
|
|
400
|
+
whose submitter vanished: one still queued keeps its place for
|
|
401
|
+
`CARGO_HAULER_REATTACH_GRACE_MS` (30 s; it may start in the meantime) and is
|
|
402
|
+
killed as `killed while queued: submitter disconnected and did not reattach
|
|
403
|
+
within 30s` only if nobody comes back; one already running continues, marked
|
|
404
|
+
orphaned as before. A reattach rebinds the ticket to the new connection,
|
|
405
|
+
clears the orphan flag, replays the output the client had not yet received
|
|
406
|
+
from the replay buffer, and streams the rest, so the exit code is cargo's as
|
|
407
|
+
if nothing had happened; output the buffer no longer holds is announced as
|
|
408
|
+
`N bytes of output missed while reconnecting; full log: <path>` rather than
|
|
409
|
+
invented. A ticket that finished in the meantime yields its exit code and log
|
|
410
|
+
path. When the ticket cannot be reattached — it never ran cargo and was
|
|
411
|
+
killed at the daemon's shutdown, `orphaned by daemon restart`, unknown to the
|
|
412
|
+
daemon that answered, the daemon predates the message, or no daemon answered
|
|
413
|
+
within the budget — the client exits `69` (`EX_UNAVAILABLE`) with `brokered
|
|
414
|
+
run aborted: daemon connection lost; ticket cc-N <reason>`; it never claims
|
|
415
|
+
the build ran. `CARGO_HAULER_REATTACH_GRACE_MS=0` restores the earlier policy
|
|
416
|
+
of killing a queued ticket the moment its connection closes. `--bg` and
|
|
417
|
+
auto-backgrounded tickets are detached, not owned, and are untouched by any
|
|
418
|
+
of this.
|
|
387
419
|
|
|
388
420
|
A deadlocked test binary holds its lane for ever at 0% CPU with nothing on
|
|
389
421
|
stdout, and neither the estimate overrun nor the output silence alone can
|
|
@@ -606,6 +638,7 @@ Per-host notes and hook timeouts are in [docs/install.md](docs/install.md).
|
|
|
606
638
|
| `CARGO_HAULER_CARGO_BIN` | `$CARGO_HOME/bin/cargo` | Cargo binary for daemon-started work; bare `cargo` is the last fallback. Never resolved through `PATH`. Read from the daemon's own environment (export it where the daemon starts, or before `hauler daemon start`); clients do not forward it. |
|
|
607
639
|
| `CARGO_HAULER_MAX_CONCURRENT` | cores ÷ 8, clamped to 5–16 | Global admission permits for Cargo processes across all lanes; an integer >= 1. |
|
|
608
640
|
| `CARGO_HAULER_OVERLAP_EXECUTION` | `1` | Hand a lane to its next request once a `test`/`nextest`/`bench`/`run` leader reports its build finished, overlapping the next compile with the leader's execution phase. `0` keeps a lane strictly one process at a time. |
|
|
641
|
+
| `CARGO_HAULER_ALLOW_SHARED_TARGET` | `0` | Allow different workspace roots to use one external target directory. The daemon still warns and status flags the lanes because Cargo artifacts can collide. Set on the request as `1`, or in the daemon environment to allow all requests. |
|
|
609
642
|
| `CARGO_HAULER_JOBS_GRANT` | `max(4, cores / max concurrent)` | `CARGO_BUILD_JOBS` added to each Cargo process only while the shared jobserver FIFO is not armed; an armed daemon injects `MAKEFLAGS` instead and leaves `CARGO_BUILD_JOBS` unset. `0` disables injection. |
|
|
610
643
|
| `CARGO_HAULER_JOBSERVER` | `auto` | Machine-wide fifo jobserver for daemon-spawned cargo: `auto` arms it only when the host `make` is 4.4+ (or absent) because older makes reject `--jobserver-auth=fifo:` in build scripts; `fifo` forces it on, `off` disables it (per-run `CARGO_BUILD_JOBS` grants apply instead). |
|
|
611
644
|
| `CARGO_HAULER_LOAD_THRESHOLD` | Disabled | Per-core one-minute load threshold for deferring new admissions. |
|
|
@@ -625,6 +658,7 @@ Per-host notes and hook timeouts are in [docs/install.md](docs/install.md).
|
|
|
625
658
|
| `CARGO_HAULER_STALL_ESTIMATE_FACTOR` | `3` | A running ticket becomes a stall candidate once its elapsed time exceeds this multiple of its estimate. |
|
|
626
659
|
| `CARGO_HAULER_STALL_IDLE_MS` | `600000` | Window with no process-tree CPU time and no output after which a stall candidate is flagged `stalled`; `0` or `off` disables stall detection. |
|
|
627
660
|
| `CARGO_HAULER_STALL_AUTO_KILL` | Enabled | Kill a stalled ticket automatically once the connection that submitted it has disconnected. `0`, `false`, `off`, or `no` only flags it. |
|
|
661
|
+
| `CARGO_HAULER_REATTACH_GRACE_MS` | `30000` | How long a queued ticket keeps its place after its submitting connection dropped, waiting for the client to `reattach`; then it is killed as abandoned. `0` kills it the moment the connection closes. |
|
|
628
662
|
| `CARGO_HAULER_STOP_WAIT_MS` | `30000` | Maximum wait for one stop-hook invocation; values above the 7200000 ms await ceiling are clamped. |
|
|
629
663
|
| `CARGO_HAULER_LEDGER_RETENTION_DAYS` | `30` | Finished ledger rows older than this many days are deleted when the daemon starts; `0` disables the age limit. |
|
|
630
664
|
| `CARGO_HAULER_LEDGER_MAX_ROWS` | `50000` | Total ledger rows beyond which the oldest finished rows are deleted when the daemon starts; `0` disables the row cap. Pruned rows take their `tickets/<ticket>.log` files with them. |
|