cargo-hauler 0.4.2 → 0.4.4
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 +18 -0
- package/README.md +110 -36
- package/artifact/agent-bundle.manifest.json +1 -1
- package/artifact/claude/.claude-plugin/marketplace.json +1 -1
- package/artifact/claude/.claude-plugin/plugin.json +1 -1
- package/artifact/claude/INSTALL.md +1 -1
- package/artifact/claude/bin/cargo-hauler-flight.mjs +645 -214
- package/artifact/claude/bin/cargo-hauler.mjs +1495 -675
- package/artifact/claude/hooks/event-route-session-start.mjs +21 -11
- package/artifact/claude/hooks/event-route-stop.mjs +21 -11
- package/artifact/claude/hooks/event-route-tool-after.mjs +21 -11
- package/artifact/claude/hooks/event-route-tool-before.mjs +21 -11
- package/artifact/claude/hooks/hooks-flight.mjs +674 -200
- package/artifact/claude/mcp/mcp-hauler-2b8242f9-flight.mjs +987 -357
- package/artifact/claude/mcp/mcp-hauler-2b8242f9.mjs +1398 -295
- package/artifact/claude/mcp-apps/dashboard.html +1 -1
- package/artifact/claude/scripts/hauler.mjs +1676 -693
- package/artifact/claude/skills/cargo-hauler/SKILL.md +11 -6
- package/artifact/codex/.codex-plugin/plugin.json +1 -1
- package/artifact/codex/INSTALL.md +1 -1
- package/artifact/codex/bin/cargo-hauler-flight.mjs +645 -214
- package/artifact/codex/bin/cargo-hauler.mjs +1495 -675
- package/artifact/codex/hooks/event-route-session-start.mjs +21 -11
- package/artifact/codex/hooks/event-route-stop.mjs +21 -11
- package/artifact/codex/hooks/event-route-tool-after.mjs +21 -11
- package/artifact/codex/hooks/event-route-tool-before.mjs +21 -11
- package/artifact/codex/hooks/hooks-flight.mjs +674 -200
- package/artifact/codex/mcp/mcp-hauler-2b8242f9-flight.mjs +987 -357
- package/artifact/codex/mcp/mcp-hauler-2b8242f9.mjs +1398 -295
- package/artifact/codex/mcp-apps/dashboard.html +1 -1
- package/artifact/codex/scripts/hauler.mjs +1676 -693
- package/artifact/codex/skills/cargo-hauler/SKILL.md +11 -6
- package/artifact/cursor/.cursor-plugin/plugin.json +1 -1
- package/artifact/cursor/INSTALL.md +1 -1
- package/artifact/cursor/bin/cargo-hauler-flight.mjs +645 -214
- package/artifact/cursor/bin/cargo-hauler.mjs +1495 -675
- package/artifact/cursor/hooks/event-route-session-start.mjs +21 -11
- package/artifact/cursor/hooks/event-route-stop.mjs +21 -11
- package/artifact/cursor/hooks/event-route-tool-after.mjs +21 -11
- package/artifact/cursor/hooks/event-route-tool-before.mjs +21 -11
- package/artifact/cursor/hooks/hooks-flight.mjs +674 -200
- package/artifact/cursor/install.mjs +1 -1
- package/artifact/cursor/mcp/mcp-hauler-2b8242f9-flight.mjs +987 -357
- package/artifact/cursor/mcp/mcp-hauler-2b8242f9.mjs +1398 -295
- package/artifact/cursor/mcp-apps/dashboard.html +1 -1
- package/artifact/cursor/scripts/hauler.mjs +1676 -693
- package/artifact/cursor/skills/cargo-hauler/SKILL.md +11 -6
- package/artifact/portable/INSTALL.md +1 -1
- package/artifact/portable/bin/cargo-hauler-flight.mjs +645 -214
- package/artifact/portable/bin/cargo-hauler.mjs +1495 -675
- package/artifact/portable/install.mjs +1 -1
- package/artifact/portable/mcp/mcp-hauler-2b8242f9-flight.mjs +646 -215
- package/artifact/portable/mcp/mcp-hauler-2b8242f9.mjs +1375 -282
- package/artifact/portable/mcp-apps/dashboard.html +1 -1
- package/artifact/portable/plugin.json +1 -1
- package/artifact/portable/scripts/hauler.mjs +1676 -693
- package/artifact/portable/skills/cargo-hauler/SKILL.md +11 -6
- package/dist/bin/cargo-hauler-flight.mjs +645 -214
- package/dist/bin/cargo-hauler-install.js +27 -6
- package/dist/bin/cargo-hauler.js +1495 -675
- package/dist/bin/hauler.js +1676 -693
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 92e168c: Bump `agent-bundle` and `@agent-bundle/runtime` to the pkg.pr.new preview at `42539ff5f`. With agent-bundle#461 a pass-through `tool/before` result no longer auto-approves, so the hook now answers `allow` only when every command in the input was rewritten onto (or already runs through) the hauler exec path, `continue` + `updatedInput` when a rewritten cargo command shares the input with something the daemon does not govern (`cd … && cargo build`, `cargo test | tail`), and plain `continue` (no decision) for every other tool call; it never returns `ask`. Accept the `confirmed` lineage resolution (agent-bundle#486) in ticket attribution.
|
|
8
|
+
|
|
9
|
+
## 0.4.3
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- a2c39f3: Bump `agent-bundle` and `@agent-bundle/runtime` to the pkg.pr.new preview at `5775351fb`, which drops the Claude `plugin.json` `hooks` pointer so Claude Code no longer rejects the plugin with "Duplicate hooks file"
|
|
14
|
+
- ccd6a50: Start the auto-spawned daemon with a curated environment (`PATH`, `HOME`, `USER`, `LOGNAME`, `SHELL`, `TMPDIR`, `LANG`/`LC_*`, `XDG_*`, `CARGO_HOME`, `RUSTUP_HOME`, `SSL_CERT_*`, `*_proxy`, `CARGO_HAULER_*`) and the state directory as its cwd, so the first client's `RUSTFLAGS`, `CARGO_TARGET_DIR`, `RUSTC_WRAPPER`, or fd-based `MAKEFLAGS` no longer become the base of every other session's builds. `hauler exec` now relays SIGINT/SIGTERM: a brokered ticket is killed before the client exits `130`/`143`, a direct run's cargo process group is terminated instead of orphaned. A ticket that ends other than `done` prints `ticket cc-N <status>[: reason]` with `128 + signal` for signaled runs; a connection lost after the ack names the ticket (`hauler result cc-N`); a direct run prints its spawn error. The ack carries `waitEtaMs` and auto-background decides on queue wait plus runtime, shown as `wait ~Ns, run ~Ns`. A daemon that never accepted within 60 s goes straight to a direct run instead of a start attempt and a second cycle. `--cwd` is resolved against the caller. `CARGO_HAULER_CARGO_BIN` is read from the daemon's own environment. The PATH shim falls back to the real cargo when its hauler entry is gone and `install-shim` says to re-run `--force` after upgrades. Descriptor-based `MAKEFLAGS`/`MFLAGS`/`CARGO_MAKEFLAGS` jobservers are not transported. Heartbeats count from `started`; a failed or unconfirmed detach is reported; `hauler request --session` no longer holds the stop hook (matching `exec --bg`); `await`/`result`/`kill` fail fast on a daemon `error` reply (#55)
|
|
15
|
+
- ab91d88: Harden the daemon's socket and singleton-lock lifecycle. The daemon now listens on `daemon.sock.<pid>` and atomically renames it over `daemon.sock`, so a daemon that lost socket ownership no longer deletes its replacement's socket on the way out (previously both daemons died and their in-flight tickets were reaped as orphaned). `hauler daemon run` acquires the singleton lock before opening the ledger, running migrations, or draining the passthrough spool, so a losing instance touches neither; it re-checks a held lock about once a second for up to ~20 s instead of giving up on the first look, treats a lock written before the current boot as stale whatever its recorded pid, treats a pid it cannot signal (`EPERM`) as unknown rather than alive, and reclaims a stale lock atomically so two cold starters can no longer both start. A second Ctrl-C during shutdown is now swallowed instead of skipping finalizers and leaving the lock and socket behind (#50)
|
|
16
|
+
- d09b2fb: Harden the `tool/before` shell rewrite and its companions. The rewrite now leaves a command untouched when the pinned `bashjsast` parser cannot round-trip it — background `&`, the `time` keyword, `|&`, `coproc`, and a heredoc feeding a pipeline previously came back as a blocking, un-timed, or syntactically broken command. It no longer passes `--cwd`, so `cd crates/foo && cargo build` builds in `crates/foo`; it skips `command -v/-V cargo`, `type cargo`, and `which cargo`; wraps the unbrokered half of `hauler exec -- cargo build && cargo test`, `while ! cargo build`, and `rustup run <toolchain> -- cargo`. The `cargo clean` guard distinguishes a busy daemon (probe timeout → brokered so the lane serializes the clean) from an absent one (raw run). `tool/after` announces only background or detached tickets, never a foreground run the agent just watched. The stop route clamps `CARGO_HAULER_STOP_WAIT_MS` to the 2 h await ceiling, and `hook-state.json` is written atomically with per-session deny-counter pruning. (#56)
|
|
17
|
+
- df912ae: Honour `hauler kill` for a job parked at the admission gate or on the permit semaphore (it settles `killed` at once instead of blocking its lane until a permit frees), never fold a kill-requested queued job into a batch, clamp the queue ETA so an overrunning lane head no longer cancels queued work and count a head parked at the gate, and finish every settlement step (waiters, lane release, follower exits) even when a ledger write fails. Late attachers receive each replayed chunk exactly once, a follower whose leader exits during registration stays settled (attach/running ledger writes never reopen a terminal row), an early follower release can no longer surface as a `pump failed` cargo termination, and identity attach requires callers to agree on `mergeStderr`. When the shared jobserver FIFO is armed the daemon no longer sets `CARGO_BUILD_JOBS`; `CARGO_HAULER_JOBS_GRANT` applies only while the FIFO is unavailable. (#51, #52, #54)
|
|
18
|
+
- 3f70b60: Keep the daemon responsive and its storage bounded. Kache priors are refreshed without blocking the event loop: the `events.jsonl` tail is read asynchronously from a persisted byte offset and parsed in yielding slices, and the `index.db` aggregate is recomputed only when the file changes on disk. The ledger gains a startup retention pass — finished requests older than `CARGO_HAULER_LEDGER_RETENTION_DAYS` (default `30`) or beyond `CARGO_HAULER_LEDGER_MAX_ROWS` (default `50000`) are deleted with their transitions; `0` disables either limit — the attachment-savings backfill runs once per database (`PRAGMA user_version`) through the rowid index instead of on every open, and request/transition writes commit atomically. NDJSON client lines are capped at 16 MiB: an oversize line gets a `bad-message` error and the connection is closed. Numeric `CARGO_HAULER_*` overrides that do not parse or fall outside their range now log a warning and keep the default instead of silently disabling the arm; `0` or `off` still disables where documented, `CARGO_HAULER_MEM_PRESSURE_SOFT` must stay below `CARGO_HAULER_MEM_PRESSURE_HARD`, and `CARGO_HAULER_BATCH=false|off|no` disables batching like `0` (#57).
|
|
19
|
+
- dd778ab: Fold `cargo test` / `cargo nextest run` requests only when their test selection is identical — same `--test` targets, name filters, arguments after `--`, and nextest filterset — so a composite runs exactly what each participant asked for over the union of their packages (`cargo test -p a` + `cargo test -p b` → `cargo test -p a -p b --no-fail-fast`), never a foreign target or filter. When a composite fails, a folded participant inherits the failure only if it named every package the composite ran; otherwise it is requeued and runs alone instead of reporting another package's failure as its own. Unmodeled post-subcommand options that take a value (`-j`/`--jobs`, `--color`, `--message-format`, `-Z`, `--config`, and nextest's `--retries`, `--test-threads`, `-P`, …) now consume that value instead of recording it as a test-name filter (#53).
|
|
20
|
+
|
|
3
21
|
## 0.4.2
|
|
4
22
|
|
|
5
23
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -140,8 +140,8 @@ the same filter as its `session` field). Results carry
|
|
|
140
140
|
| `tool:hauler/hauler_request` · `cli:request` | submit a background request | `RequestDocument` |
|
|
141
141
|
| `cli:daemon` | `run` / `start` / `stop` / `status` | plain JSON, exit code from the result |
|
|
142
142
|
| `event:session/start` | new session | daemon state and the no-kill rule as context |
|
|
143
|
-
| `event:tool/before` | shell tool about to run | rewrites `cargo …` to `hauler exec --session … --host … -- cargo …`; denies `cargo clean` during in-flight builds |
|
|
144
|
-
| `event:tool/after` | shell tool finished | injects finished-ticket results once per session |
|
|
143
|
+
| `event:tool/before` | shell tool about to run | rewrites `cargo …` to `hauler exec --session … --host … -- cargo …`; denies `cargo clean` during in-flight builds, brokers it while the daemon is too busy to answer |
|
|
144
|
+
| `event:tool/after` | shell tool finished | injects finished background-ticket results once per session |
|
|
145
145
|
| `event:stop` | agent stopping | holds the stop while a foreground ticket is pending (bounded, re-deniable) |
|
|
146
146
|
|
|
147
147
|
### Skills
|
|
@@ -216,7 +216,7 @@ executable beside it (`dist/bin/cargo-hauler.js` in the package,
|
|
|
216
216
|
|
|
217
217
|
| Command | Behavior |
|
|
218
218
|
| --- | --- |
|
|
219
|
-
| `hauler exec [--session ID] [--host HOST] [--cwd DIR] [--bg] -- <cargo …>` | Submit Cargo through the daemon and stream output; hooks rewrite commands to this form. |
|
|
219
|
+
| `hauler exec [--session ID] [--host HOST] [--cwd DIR] [--bg] -- <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. Exits with cargo's code; `130`/`143` after a SIGINT/SIGTERM (the ticket is killed first); `75` when auto-backgrounded. |
|
|
220
220
|
| `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. |
|
|
221
221
|
| `hauler log [--limit N]` | Recent requests from the ledger. |
|
|
222
222
|
| `hauler last` | The most recent request. |
|
|
@@ -264,9 +264,23 @@ The hook parses the shell command and rewrites each Cargo invocation to
|
|
|
264
264
|
`hauler exec --session … --host … -- cargo …`. It recognizes `cargo` behind an
|
|
265
265
|
absolute path (`~/.cargo/bin/cargo`), and behind the wrappers agents actually
|
|
266
266
|
use: `env -u VAR X=y cargo …`, `timeout 600 cargo …`,
|
|
267
|
-
`rustup run <toolchain> cargo …`, `stdbuf`, `nice`, `ionice`, `nohup`,
|
|
268
|
-
|
|
269
|
-
`
|
|
267
|
+
`rustup run <toolchain> [--] cargo …`, `stdbuf`, `nice`, `ionice`, `nohup`,
|
|
268
|
+
`/usr/bin/time`, `strace`, `sudo`, `xargs`, `command`, `exec`, `builtin`,
|
|
269
|
+
and a negated test (`while ! cargo build; do …`). Other `rustup`
|
|
270
|
+
subcommands, lookups (`command -v cargo`, `type cargo`, `which cargo`), and
|
|
271
|
+
already-wrapped invocations are left alone; in a partially wrapped list
|
|
272
|
+
(`hauler exec -- cargo build && cargo test`) only the unwrapped half is
|
|
273
|
+
rewritten. The rewrite never passes `--cwd`: the command runs in the same
|
|
274
|
+
shell, so `hauler exec` inherits the working directory and
|
|
275
|
+
`cd crates/foo && cargo build` builds in `crates/foo`.
|
|
276
|
+
|
|
277
|
+
Before rewriting, the hook checks that the parser can reproduce the original
|
|
278
|
+
command token for token. Constructs the pinned parser cannot round-trip —
|
|
279
|
+
a background `&` (`nohup cargo build … &`, `cargo build & pid=$!`), the
|
|
280
|
+
`time` keyword, `|&`, `coproc`, a heredoc that feeds a pipeline or is
|
|
281
|
+
followed by another statement, `elif`, and `function name { … }` — are left
|
|
282
|
+
untouched and run as plain Cargo rather than risk emitting a changed
|
|
283
|
+
command.
|
|
270
284
|
|
|
271
285
|
A lane is keyed by workspace root and resolved target directory. It runs one
|
|
272
286
|
job at a time. Different lanes may run concurrently after acquiring one of the
|
|
@@ -288,8 +302,17 @@ Each admitted leader starts one Cargo process. Identity, coverage, and folded
|
|
|
288
302
|
batch requests share that process and receive its streamed output. A failed
|
|
289
303
|
stronger compile does not satisfy a coverage or compile-batch attachment; the
|
|
290
304
|
attached request returns to its lane unless its required compilation units were
|
|
291
|
-
already observed as successful. Folded tests share the composite process
|
|
292
|
-
output
|
|
305
|
+
already observed as successful. Folded tests share the composite process and
|
|
306
|
+
output. `cargo test` / `cargo nextest run` requests fold only when their test
|
|
307
|
+
selection is identical — the same `--test` targets, name filters, arguments
|
|
308
|
+
after `--`, and nextest filterset — so only the package set differs:
|
|
309
|
+
`cargo test -p a` and `cargo test -p b` become
|
|
310
|
+
`cargo test -p a -p b --no-fail-fast`. On success every participant shares
|
|
311
|
+
the exit. When the composite fails, a participant inherits that failure only
|
|
312
|
+
if it named every package the composite ran; otherwise the failing tests may
|
|
313
|
+
belong to another participant's package, so it is requeued and runs alone
|
|
314
|
+
(cargo's test output does not attribute failures to packages). The leader
|
|
315
|
+
keeps the composite exit, as compile-batch leaders do.
|
|
293
316
|
|
|
294
317
|
Brokered output keeps cargo's stdout and stderr as separate channels. When the
|
|
295
318
|
caller's own stdout and stderr are the same open file (`cargo run 2>&1`, a
|
|
@@ -324,18 +347,22 @@ heartbeats. Non-compiling cargo subcommands (`fmt`, `update`, `fetch`, `add`,
|
|
|
324
347
|
`remove`, `generate-lockfile`, `vendor`, `new`, `init`, `info`, `uninstall`)
|
|
325
348
|
run locally instead of queueing for a permit.
|
|
326
349
|
|
|
327
|
-
The
|
|
328
|
-
across the configured permit count, with a floor of four jobs. Separately, the
|
|
329
|
-
daemon arms one GNU make jobserver FIFO with `cores - 1` tokens when it
|
|
350
|
+
The daemon arms one GNU make jobserver FIFO with `cores - 1` tokens when it
|
|
330
351
|
acquires the singleton lock and passes it to every Cargo it spawns through
|
|
331
352
|
`MAKEFLAGS`, so concurrent lanes share one global rustc parallelism budget.
|
|
353
|
+
While the FIFO is armed no `CARGO_BUILD_JOBS` is injected, because Cargo only
|
|
354
|
+
joins an inherited jobserver when `-j`/`build.jobs` is unset. The per-run
|
|
355
|
+
`CARGO_BUILD_JOBS` grant — the available cores divided across the configured
|
|
356
|
+
permit count, with a floor of four jobs — is the fallback for a daemon that
|
|
357
|
+
could not arm the FIFO (no `mkfifo`, unwritable state directory). A caller's
|
|
358
|
+
own `-j` flag or `CARGO_BUILD_JOBS` always wins over both.
|
|
332
359
|
|
|
333
360
|
| Capability | Behavior |
|
|
334
361
|
| --- | --- |
|
|
335
362
|
| Work sharing | Identical requests attach, covered checks attach, and compatible queued compile or test requests fold. |
|
|
336
363
|
| Lane isolation | A workspace-root and target-directory pair is serialized independently from other lanes. |
|
|
337
364
|
| 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. |
|
|
338
|
-
| Parallelism |
|
|
365
|
+
| 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. |
|
|
339
366
|
| Scheduling | EWMA estimates, optional kache priors, fan-out, dependency topology, recent edits, and request age determine lane order. |
|
|
340
367
|
| Persistence | Tickets, output tails, timings, outcomes, and savings are stored in SQLite. |
|
|
341
368
|
| Caller output and status | Output streams to attached callers; late callers receive buffered replay. After 30 seconds without output, the client emits a progress heartbeat every 15 seconds with lane queue position, the lane-head ticket, and an aggregate wait ETA. |
|
|
@@ -351,19 +378,37 @@ immediately. A synchronous request also switches to background mode when a
|
|
|
351
378
|
*measured* estimate — EWMA history or kache priors, never the cold-start
|
|
352
379
|
default — exceeds the host's shell-tool cap (nine minutes for Claude, ten for
|
|
353
380
|
Codex, fourteen for Cursor; the PATH shim uses `CARGO_HAULER_HOST` when it is
|
|
354
|
-
exported, otherwise the Claude cap).
|
|
355
|
-
|
|
356
|
-
|
|
381
|
+
exported, otherwise the Claude cap). The estimate that is compared is the
|
|
382
|
+
whole wait: the work queued ahead in the lane plus the job's own runtime,
|
|
383
|
+
which the queued line reports as `wait ~Ns, run ~Ns`. That conversion exits
|
|
384
|
+
`75` (`EX_TEMPFAIL`) with the ticket on stderr, so `cargo build && …` chains
|
|
385
|
+
and scripts cannot mistake "submitted" for "built"; explicit `--bg` keeps exit
|
|
357
386
|
`0`. Failed runs feed the estimate history too, so a broken build is not
|
|
358
387
|
re-estimated cold on every retry.
|
|
359
388
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
389
|
+
A foreground `hauler exec` that receives SIGINT or SIGTERM (Ctrl-C, or a
|
|
390
|
+
`timeout N …` wrapper) asks the daemon to kill its ticket, waits for the
|
|
391
|
+
answer, and exits `130` or `143`; in a direct run it terminates the cargo
|
|
392
|
+
process group the same way. A ticket that ends other than `done` is reported
|
|
393
|
+
on stderr as `ticket cc-N <status>[ (signal)][: reason]`, and its exit code is
|
|
394
|
+
cargo's, `128 + signal` for a signaled run, or `1` when the daemon could not
|
|
395
|
+
start cargo at all. If the connection drops after the ticket was accepted, the
|
|
396
|
+
client prints `connection to daemon lost; ticket cc-N continues — hauler
|
|
397
|
+
result cc-N` and exits `1`; the daemon finishes the ticket on its own.
|
|
398
|
+
|
|
399
|
+
The `tool/after` route checks the session's background tickets — `--bg`,
|
|
400
|
+
`hauler_request`, and synchronous requests the client converted to a ticket
|
|
401
|
+
— and, on the first tool call after one finishes, adds its result to the
|
|
402
|
+
agent context. A foreground ticket streamed its exit to the shell the agent
|
|
403
|
+
just watched, so it is never re-announced. For foreground tickets, the
|
|
404
|
+
`stop` route waits for the lower of the remaining estimate and
|
|
405
|
+
`CARGO_HAULER_STOP_WAIT_MS` (clamped to the daemon's two-hour await
|
|
406
|
+
ceiling); if the ticket finishes it denies the stop and returns the result,
|
|
407
|
+
otherwise it denies with status and ETA. `stopHookActive` and an
|
|
408
|
+
eight-denial cap per ticket prevent a repeated stop loop; the per-ticket
|
|
409
|
+
counters live in `hook-state.json`, written atomically and pruned once a
|
|
410
|
+
session's tickets are no longer pending. `--bg` tickets never hold a stop.
|
|
411
|
+
Codex 0.147.0 stop-hold behaviour is verified in
|
|
367
412
|
[docs/codex-hooks.md](docs/codex-hooks.md).
|
|
368
413
|
|
|
369
414
|
### PATH shim
|
|
@@ -375,7 +420,11 @@ When the daemon starts Cargo it sets `CARGO_HAULER_INSIDE=1`, and the shim then
|
|
|
375
420
|
invokes the embedded Cargo directly, so the daemon's own Cargo never returns
|
|
376
421
|
through the broker. The shim is POSIX-only; its directory must appear before
|
|
377
422
|
rustup's Cargo directory on `PATH`; replacing an existing destination requires
|
|
378
|
-
`--force`.
|
|
423
|
+
`--force`. The embedded `hauler` entry lives in a versioned plugin directory:
|
|
424
|
+
when that file no longer exists (an upgrade replaced the directory), the shim
|
|
425
|
+
runs the embedded Cargo directly instead of failing, and `install-shim` says
|
|
426
|
+
so — re-run `hauler install-shim --force` after such an upgrade to route
|
|
427
|
+
scripted Cargo through the broker again.
|
|
379
428
|
|
|
380
429
|
### Caller environment
|
|
381
430
|
|
|
@@ -388,10 +437,24 @@ Cargo, so `FOO=bar cargo build` reaches `build.rs`, `env!()`, `cargo run`, and
|
|
|
388
437
|
for coalescing is digested from the build-relevant subset only (`CARGO_*`,
|
|
389
438
|
`RUST*`, `CC`/`CXX`/`AR`/`CFLAGS`/`CXXFLAGS`/`LDFLAGS` with target-suffixed
|
|
390
439
|
forms, and `PKG_CONFIG_PATH`); pass knobs a `build.rs` reads through
|
|
391
|
-
`--config 'env.FOO="bar"'` when they must also split identity.
|
|
440
|
+
`--config 'env.FOO="bar"'` when they must also split identity. One value is
|
|
441
|
+
filtered rather than forwarded: a `MAKEFLAGS`, `MFLAGS`, or `CARGO_MAKEFLAGS`
|
|
442
|
+
carrying a descriptor-based jobserver (`--jobserver-auth=R,W`,
|
|
443
|
+
`--jobserver-fds=R,W`) names file descriptors that exist only in the caller,
|
|
444
|
+
so it is dropped and the daemon's shared FIFO jobserver applies; a
|
|
445
|
+
`fifo:PATH` jobserver travels as-is.
|
|
392
446
|
`hauler request` and `hauler_request` submit without a caller environment;
|
|
393
447
|
their Cargo processes run with the daemon's environment.
|
|
394
448
|
|
|
449
|
+
The daemon's own environment is deliberately small. When a client starts it,
|
|
450
|
+
the daemon receives only `PATH`, `HOME`, `USER`, `LOGNAME`, `SHELL`, `TMPDIR`,
|
|
451
|
+
`LANG` and `LC_*`, `XDG_*`, `CARGO_HOME`, `RUSTUP_HOME`, `SSL_CERT_*`, the
|
|
452
|
+
`*_proxy` variables, and every `CARGO_HAULER_*` setting, with the state
|
|
453
|
+
directory as its working directory. The starting shell's `RUSTFLAGS`,
|
|
454
|
+
`CARGO_TARGET_DIR`, `RUSTC_WRAPPER`, `CARGO_BUILD_*`, `MAKEFLAGS`, `CC`, and
|
|
455
|
+
similar build knobs are not inherited, so they cannot become the silent base of
|
|
456
|
+
every other session's builds.
|
|
457
|
+
|
|
395
458
|
### Kache integration
|
|
396
459
|
|
|
397
460
|
When [kache](https://github.com/ScriptedAlchemy/kache) is available,
|
|
@@ -407,27 +470,32 @@ is reported as unavailable and never rejects a request.
|
|
|
407
470
|
| Variable | Default | Meaning |
|
|
408
471
|
| --- | --- | --- |
|
|
409
472
|
| `CARGO_HAULER_STATE_DIR` | Per-user cache directory | Unix socket or Windows named pipe source, SQLite ledger, daemon log, pid lock, `hook-state.json`, and `hook-events.jsonl`. No legacy alias. |
|
|
410
|
-
| `CARGO_HAULER_CARGO_BIN` | `$CARGO_HOME/bin/cargo` | Cargo binary for daemon-started work; bare `cargo` is the last fallback. Never resolved through `PATH`. |
|
|
411
|
-
| `CARGO_HAULER_MAX_CONCURRENT` | `5` | Global admission permits for Cargo processes across all lanes. |
|
|
412
|
-
| `CARGO_HAULER_JOBS_GRANT` | `max(4, cores / max concurrent)` | `CARGO_BUILD_JOBS` added to each Cargo process; `0` disables injection. |
|
|
473
|
+
| `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. |
|
|
474
|
+
| `CARGO_HAULER_MAX_CONCURRENT` | `5` | Global admission permits for Cargo processes across all lanes; an integer >= 1. |
|
|
475
|
+
| `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. |
|
|
413
476
|
| `CARGO_HAULER_LOAD_THRESHOLD` | Disabled | Per-core one-minute load threshold for deferring new admissions. |
|
|
414
477
|
| `CARGO_HAULER_LOAD_MIN` | `2` | Active Cargo processes below which load, CPU PSI, and soft memory pressure do not defer admission. |
|
|
415
|
-
| `CARGO_HAULER_CPU_PRESSURE_THRESHOLD` | `75` | Linux CPU PSI `some avg10` percentage for deferring new admissions; `0` disables. |
|
|
416
|
-
| `CARGO_HAULER_MEM_PRESSURE_SOFT` | `10` (Linux) | Memory PSI `full avg10` percentage for soft deferral; `0` disables. |
|
|
417
|
-
| `CARGO_HAULER_MEM_PRESSURE_HARD` | `20` (Linux) | Memory PSI `full avg10` percentage for hard deferral, confirmed by `full avg60` at half the value; `0` disables. |
|
|
418
|
-
| `CARGO_HAULER_MEM_AVAILABLE_MIN_GB` | `8` (Linux) | `MemAvailable` floor in GiB for hard deferral; `0` disables. |
|
|
419
|
-
| `CARGO_HAULER_MEM_PRESSURE_LEVEL` | `2` (macOS) | Kernel VM pressure level that starts soft deferral (`2` warn, `4` critical). |
|
|
478
|
+
| `CARGO_HAULER_CPU_PRESSURE_THRESHOLD` | `75` | Linux CPU PSI `some avg10` percentage for deferring new admissions; `0` or `off` disables. |
|
|
479
|
+
| `CARGO_HAULER_MEM_PRESSURE_SOFT` | `10` (Linux) | Memory PSI `full avg10` percentage for soft deferral; `0` or `off` disables. Must stay below the hard threshold, otherwise both revert to their defaults. |
|
|
480
|
+
| `CARGO_HAULER_MEM_PRESSURE_HARD` | `20` (Linux) | Memory PSI `full avg10` percentage for hard deferral, confirmed by `full avg60` at half the value; `0` or `off` disables. |
|
|
481
|
+
| `CARGO_HAULER_MEM_AVAILABLE_MIN_GB` | `8` (Linux) | `MemAvailable` floor in GiB for hard deferral; `0` or `off` disables. |
|
|
482
|
+
| `CARGO_HAULER_MEM_PRESSURE_LEVEL` | `2` (macOS) | Kernel VM pressure level that starts soft deferral (`2` warn, `4` critical); `0` or `off` disables. |
|
|
420
483
|
| `CARGO_HAULER_HEAVY_MEM_AVAILABLE_GB` | `16` (Linux) | `MemAvailable` in GiB below which concurrent heavy leaders (release/perf/bench profiles, workspace-wide runs) are capped; `0` or `off` disables the cap. |
|
|
421
484
|
| `CARGO_HAULER_HEAVY_MAX_CONCURRENT` | `1` | Heavy leaders admitted at once while the cap is active. |
|
|
422
485
|
| `CARGO_HAULER_REPLAY_BUFFER_BYTES` | `4194304` | Leader output retained in memory for late-attacher replay. |
|
|
423
486
|
| `CARGO_HAULER_KACHE_INDEX` | kache's configured store | kache index for per-crate timing priors; an empty string disables it. |
|
|
424
|
-
| `CARGO_HAULER_BATCH` | Enabled | `0` disables the batch composer. |
|
|
487
|
+
| `CARGO_HAULER_BATCH` | Enabled | `0`, `false`, `off`, or `no` disables the batch composer. |
|
|
425
488
|
| `CARGO_HAULER_BATCH_WINDOW_MS` | `150` | Delay applied to a batchable lane head so nearby requests can fold; `0` disables. |
|
|
426
489
|
| `CARGO_HAULER_KILL_GRACE_MS` | `8000` | Time between SIGTERM and SIGKILL when the daemon stops a Cargo process. |
|
|
427
|
-
| `CARGO_HAULER_STOP_WAIT_MS` | `30000` | Maximum wait for one stop-hook invocation. |
|
|
490
|
+
| `CARGO_HAULER_STOP_WAIT_MS` | `30000` | Maximum wait for one stop-hook invocation; values above the 7200000 ms await ceiling are clamped. |
|
|
491
|
+
| `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. |
|
|
492
|
+
| `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. |
|
|
428
493
|
| `CARGO_HAULER_LOG_LEVEL` | `Info` | Daemon log level. |
|
|
429
494
|
| `CARGO_HAULER_HOST`, `CARGO_HAULER_SESSION` | Unset | Default `--host` and `--session` attribution for `hauler exec`; the PATH shim also borrows `CARGO_HAULER_HOST`'s shell cap for auto-background. |
|
|
430
495
|
|
|
496
|
+
A numeric value that does not parse or falls outside its range is reported
|
|
497
|
+
as a warning (daemon log, or stderr for hand-run commands) and the default
|
|
498
|
+
applies; only `0` or `off` disables an arm that documents that contract.
|
|
431
499
|
Each `CARGO_HAULER_*` tuning value takes precedence over its retained legacy
|
|
432
500
|
`CARGO_CONDUCTOR_*` alias; `CARGO_CONDUCTOR_STATE_DIR` is ignored and hand-run
|
|
433
501
|
commands warn when it is still exported (see
|
|
@@ -445,7 +513,8 @@ unset, the daemon reads kache's configured local store from
|
|
|
445
513
|
command through, and a client that cannot reach the daemon makes one
|
|
446
514
|
auto-start attempt and then invokes Cargo directly. A daemon that is alive
|
|
447
515
|
but too loaded to accept within 2 seconds is not treated as absent: `exec`
|
|
448
|
-
retries for up to 60 seconds
|
|
516
|
+
retries for up to 60 seconds, then runs Cargo directly without a start
|
|
517
|
+
attempt or a second retry cycle.
|
|
449
518
|
- The plugin's own documents never fail open: `hauler_result` and
|
|
450
519
|
`hauler_await` fail loudly when the daemon is unreachable instead of
|
|
451
520
|
reporting a ticket as not found; `hauler_status`, `hauler_log`, and
|
|
@@ -454,6 +523,11 @@ unset, the daemon reads kache's configured local store from
|
|
|
454
523
|
- Test sharing uses identity attachment or batch folding, never coverage.
|
|
455
524
|
Folded `test` and `nextest` requests receive the composite output and exit
|
|
456
525
|
code, so a failure may come from another package in the batch.
|
|
526
|
+
- The `cargo clean` guard probes the daemon for 250 ms. Active work denies
|
|
527
|
+
the clean; an idle daemon brokers it; a daemon that accepts but does not
|
|
528
|
+
answer in time is busy, so the clean is brokered and the lane serializes
|
|
529
|
+
it behind the builds it would otherwise race; only a socket nobody listens
|
|
530
|
+
on (`ECONNREFUSED`, `ENOENT`) lets a raw `cargo clean` run.
|
|
457
531
|
- Hook rewrites, policy denials such as `cargo clean` during an active build,
|
|
458
532
|
and malformed requests are recorded (`hook-events.jsonl`; a failed ledger
|
|
459
533
|
row).
|
|
@@ -478,7 +552,7 @@ data is the daemon's own. The repository ships no preview harness of its own.
|
|
|
478
552
|
|
|
479
553
|
agent-bundle does not yet have an npm release; this repository pins the
|
|
480
554
|
[pkg.pr.new](https://pkg.pr.new) preview of main commit
|
|
481
|
-
[`
|
|
555
|
+
[`42539ff5f`](https://github.com/ScriptedAlchemy/agent-bundle/commit/42539ff5fbafdff0656317b841a50100ac0fc141)
|
|
482
556
|
for both `agent-bundle` and `@agent-bundle/runtime`. `inspect` reports the
|
|
483
557
|
`agent` component kind as unavailable on every host (agent-bundle G5
|
|
484
558
|
deferral); this plugin defines no agents. Two framework limitations observed
|