cargo-hauler 0.4.3 → 0.4.5

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 (62) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +76 -13
  3. package/artifact/agent-bundle.manifest.json +1 -1
  4. package/artifact/claude/.claude-plugin/marketplace.json +1 -1
  5. package/artifact/claude/.claude-plugin/plugin.json +1 -1
  6. package/artifact/claude/INSTALL.md +1 -1
  7. package/artifact/claude/bin/cargo-hauler-flight.mjs +1269 -359
  8. package/artifact/claude/bin/cargo-hauler.mjs +2180 -807
  9. package/artifact/claude/hooks/event-route-session-start.mjs +21 -10
  10. package/artifact/claude/hooks/event-route-stop.mjs +21 -10
  11. package/artifact/claude/hooks/event-route-tool-after.mjs +21 -10
  12. package/artifact/claude/hooks/event-route-tool-before.mjs +21 -10
  13. package/artifact/claude/hooks/hooks-flight.mjs +445 -40
  14. package/artifact/claude/mcp/mcp-hauler-2b8242f9-flight.mjs +1194 -382
  15. package/artifact/claude/mcp/mcp-hauler-2b8242f9.mjs +1804 -412
  16. package/artifact/claude/mcp-apps/dashboard.html +1 -1
  17. package/artifact/claude/scripts/hauler.mjs +1418 -518
  18. package/artifact/claude/skills/cargo-hauler/SKILL.md +32 -0
  19. package/artifact/codex/.codex-plugin/plugin.json +1 -1
  20. package/artifact/codex/INSTALL.md +1 -1
  21. package/artifact/codex/bin/cargo-hauler-flight.mjs +1269 -359
  22. package/artifact/codex/bin/cargo-hauler.mjs +2180 -807
  23. package/artifact/codex/hooks/event-route-session-start.mjs +21 -10
  24. package/artifact/codex/hooks/event-route-stop.mjs +21 -10
  25. package/artifact/codex/hooks/event-route-tool-after.mjs +21 -10
  26. package/artifact/codex/hooks/event-route-tool-before.mjs +21 -10
  27. package/artifact/codex/hooks/hooks-flight.mjs +445 -40
  28. package/artifact/codex/mcp/mcp-hauler-2b8242f9-flight.mjs +1194 -382
  29. package/artifact/codex/mcp/mcp-hauler-2b8242f9.mjs +1804 -412
  30. package/artifact/codex/mcp-apps/dashboard.html +1 -1
  31. package/artifact/codex/scripts/hauler.mjs +1418 -518
  32. package/artifact/codex/skills/cargo-hauler/SKILL.md +32 -0
  33. package/artifact/cursor/.cursor-plugin/plugin.json +1 -1
  34. package/artifact/cursor/INSTALL.md +1 -1
  35. package/artifact/cursor/bin/cargo-hauler-flight.mjs +1269 -359
  36. package/artifact/cursor/bin/cargo-hauler.mjs +2180 -807
  37. package/artifact/cursor/hooks/event-route-session-start.mjs +21 -10
  38. package/artifact/cursor/hooks/event-route-stop.mjs +21 -10
  39. package/artifact/cursor/hooks/event-route-tool-after.mjs +21 -10
  40. package/artifact/cursor/hooks/event-route-tool-before.mjs +21 -10
  41. package/artifact/cursor/hooks/hooks-flight.mjs +445 -40
  42. package/artifact/cursor/install.mjs +1 -1
  43. package/artifact/cursor/mcp/mcp-hauler-2b8242f9-flight.mjs +1194 -382
  44. package/artifact/cursor/mcp/mcp-hauler-2b8242f9.mjs +1804 -412
  45. package/artifact/cursor/mcp-apps/dashboard.html +1 -1
  46. package/artifact/cursor/scripts/hauler.mjs +1418 -518
  47. package/artifact/cursor/skills/cargo-hauler/SKILL.md +32 -0
  48. package/artifact/portable/INSTALL.md +1 -1
  49. package/artifact/portable/bin/cargo-hauler-flight.mjs +1269 -359
  50. package/artifact/portable/bin/cargo-hauler.mjs +2180 -807
  51. package/artifact/portable/install.mjs +1 -1
  52. package/artifact/portable/mcp/mcp-hauler-2b8242f9-flight.mjs +1154 -359
  53. package/artifact/portable/mcp/mcp-hauler-2b8242f9.mjs +1777 -396
  54. package/artifact/portable/mcp-apps/dashboard.html +1 -1
  55. package/artifact/portable/plugin.json +1 -1
  56. package/artifact/portable/scripts/hauler.mjs +1418 -518
  57. package/artifact/portable/skills/cargo-hauler/SKILL.md +32 -0
  58. package/dist/bin/cargo-hauler-flight.mjs +1269 -359
  59. package/dist/bin/cargo-hauler-install.js +27 -6
  60. package/dist/bin/cargo-hauler.js +2180 -807
  61. package/dist/bin/hauler.js +1418 -518
  62. package/package.json +3 -3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.5
4
+
5
+ ### Patch Changes
6
+
7
+ - 62d4e16: Add `--after <ticket>[,<ticket>…]` to `hauler exec` and `hauler request` (and `after: string[]` on `hauler_request`) to declare explicit ticket dependencies: the request stays `queued` — skipped by lane admission and batch folding — until every named ticket has settled, fails with `prerequisite cc-N failed`/`killed` (exit code `null`) if one of them does, resolves at once when they already finished, and is rejected as a `bad-intent` error naming an unknown ticket. Prerequisites may live in another lane; the ledger stores them (`after` on every request record) and `hauler status`/`hauler result`/await heartbeats show `waits for cc-N (running 2m/~5m)` while a dependent is held. The `exec --bg` and `request` acknowledgements now name the tickets ahead in the lane (`queued behind cc-3281 (~13m)`, `ahead` on the ack and `queue` on the request result) so a cost-ordered reorder is visible, and `hauler request` reports the daemon's rejection reason instead of a generic submit failure. (#45)
8
+ - 1135585: The daemon rejects a path-shaped program that is not cargo (`bad-intent`) instead of running it and recording the path as the subcommand; the dashboard's by-command table shows legacy rows by basename, and the all-time latency tile reads "latency added by attaching" when riders waited longer than their solo estimate instead of showing a negative "saved" value. Dashboard screenshots refreshed.
9
+ - d86d8b6: The shared fifo jobserver is armed only when the host `make` can speak it (GNU make 4.4+, or no make at all); on older makes the daemon falls back to per-run `CARGO_BUILD_JOBS` grants so `-sys` crates whose build scripts run `make` (jemalloc, openssl, …) build again. `CARGO_HAULER_JOBSERVER=fifo|off|auto` overrides the detection (#76).
10
+ - b13db35: Detect stalled tickets and end orphaned ones. The daemon samples every running ticket's process-tree CPU time (Linux `/proc`, macOS `ps`) and flags a run `stalled` once it is past `CARGO_HAULER_STALL_ESTIMATE_FACTOR` (3) times its estimate with no CPU and no output for `CARGO_HAULER_STALL_IDLE_MS` (10 min). `hauler status` / `hauler_status`, the dashboard, and `hauler await` heartbeats show `stalled` with the idle duration; `hauler result` / `hauler_result` answer `ticket looks stalled (no CPU for Nm) — hauler kill cc-N`. A stalled ticket whose submitting connection has disconnected is killed automatically through the `hauler kill` path with the error `stalled: no CPU for Nm after owner disconnected; killed automatically`; `CARGO_HAULER_STALL_AUTO_KILL=0` only flags. Status records gain optional `stall` and `orphaned` fields. (#46)
11
+ - cfb6967: Keep every ticket's whole output on disk and make it readable after the fact. The daemon writes a leader run's combined stdout+stderr, as emitted (rendered diagnostics for demultiplexed runs, ANSI as captured), to `<state dir>/tickets/<ticket>.log`, bounded by the new `CARGO_HAULER_TICKET_LOG_MAX_BYTES` (default 64 MiB, then one truncation line; `0` disables). The ledger gains `output_path`, exposed as `outputPath` on every request record (attached followers carry their leader's path); the startup retention pass removes the logs of pruned rows and any log without a row. `hauler result <ticket>` now shows `Full output: <path> (size)` and `--json` carries `request.outputPath`; `hauler result <ticket> --full` and `hauler_result { ticket, full: true }` render the whole log as the document body (the last ~768 KiB when it does not fit, with the path for the rest). When a synchronous command is auto-backgrounded and the caller's stdout is not a terminal, the exit-75 notice adds that the redirect receives no output and to read it with `hauler result cc-N --full`. (#68)
12
+
13
+ ## 0.4.4
14
+
15
+ ### Patch Changes
16
+
17
+ - 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.
18
+
3
19
  ## 0.4.3
4
20
 
5
21
  ### Patch Changes
package/README.md CHANGED
@@ -90,6 +90,7 @@ assertion share one derivation.
90
90
  | `<AdmissionState>` | permits in use, load, memory clamp, sharing savings; calls out a paused admission gate |
91
91
  | `<KacheStats>` | kache coverage and freshness, slowest crates by profile, or an honest "not detected" |
92
92
  | `<LogTail>` | the captured output tail, labelled live while the run is in progress |
93
+ | `<FullOutput>` | where the ticket's whole output log lives and how large it is; under `full`, the log itself in code-block chunks |
93
94
  | `<BuildDiagnostics>` | an index of cargo `error[E…]`/`warning:` blocks (level / code / message / location) followed by every captured block verbatim |
94
95
  | `<DashboardLink>` | where the MCP App lives and how to open it elsewhere |
95
96
  | `<TicketGuidance>` | what to do next, one component per ticket status |
@@ -135,7 +136,7 @@ the same filter as its `session` field). Results carry
135
136
  | `tool:hauler/hauler_log` · `cli:log` | recent requests | `LogStream` → `LogDocument` |
136
137
  | `tool:hauler/hauler_last` · `cli:last` | most recent request | `LastDocument` |
137
138
  | `tool:hauler/hauler_await` · `cli:await` | long-poll a ticket (≤ 2 h) | `AwaitStream` → `AwaitDocument` |
138
- | `tool:hauler/hauler_result` · `cli:result` | one ticket, live tail while running | `ResultDocument` |
139
+ | `tool:hauler/hauler_result` · `cli:result` | one ticket, live tail while running; `full` renders the whole on-disk output log | `ResultDocument` (`<FullOutput>`) |
139
140
  | `tool:hauler/hauler_kill` · `cli:kill` | stop a queued or running ticket | `KillDocument` |
140
141
  | `tool:hauler/hauler_request` · `cli:request` | submit a background request | `RequestDocument` |
141
142
  | `cli:daemon` | `run` / `start` / `stop` / `status` | plain JSON, exit code from the result |
@@ -216,14 +217,14 @@ executable beside it (`dist/bin/cargo-hauler.js` in the package,
216
217
 
217
218
  | Command | Behavior |
218
219
  | --- | --- |
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
+ | `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. |
220
221
  | `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
222
  | `hauler log [--limit N]` | Recent requests from the ledger. |
222
223
  | `hauler last` | The most recent request. |
223
224
  | `hauler await <ticket> [--max-wait-ms N]` | Long-poll until the ticket finishes or the wait expires (default 30 s, ceiling 55 s per call — the rendered-route budget; call again to keep waiting). |
224
- | `hauler result <ticket>` | A stored ticket; running tickets include a live output tail. |
225
+ | `hauler result <ticket> [--full]` | A stored ticket; running tickets include a live output tail. The document names the full on-disk output log (`Full output: <path> (size)`) and `--json` carries it as `request.outputPath`; `--full` prints that whole log instead of the tail (the last ~768 KiB when it does not fit, with the path for the rest). |
225
226
  | `hauler kill <ticket>` | Stop a ticket: drop it from the queue or SIGTERM (then SIGKILL) its cargo process group, freeing the lane. Riders return to their lane or fail with it. |
226
- | `hauler request [--session ID] [--host HOST] [--cwd DIR] -- <cargo …>` | Submit a background request and return its ticket. |
227
+ | `hauler request [--session ID] [--host HOST] [--cwd DIR] [--after TICKET …] -- <cargo …>` | Submit a background request and return its ticket, with where it landed in its lane (`queued behind cc-3281 (~13m)`, `waiting for cc-3281`, or `attached to cc-3281`). `--after` works as for `exec`. |
227
228
  | `hauler daemon <run\|start\|stop\|status>` | Manage the daemon lifecycle. |
228
229
  | `hauler install-shim [--dir DIR] [--real-cargo PATH] [--force]` | Install the optional PATH shim. |
229
230
 
@@ -330,6 +331,26 @@ callers, dependency-unblocking work, and recently edited packages receive a
330
331
  lower scheduling score. Waiting time lowers the score further so broad work
331
332
  eventually runs.
332
333
 
334
+ Admission within a lane is therefore cost-ordered, not first-in-first-out: a
335
+ queued `cargo test -p foo` (a cheap estimate) normally starts before a queued
336
+ `cargo build --workspace` submitted a minute earlier, even when the test
337
+ spawns a binary that build produces. The acknowledgement makes the order
338
+ visible — `ticket cc-3289 queued behind cc-3281 (1 ahead, wait ~780s)` on
339
+ `exec`, `cc-3289 submitted, queued behind cc-3281 (~13m)` on `request` — and
340
+ `--after` makes the dependency explicit: `hauler exec --after cc-3281 -- cargo
341
+ test …` (or `hauler request --after`, or `after: ["cc-3281"]` on
342
+ `hauler_request`) stays `queued` and is skipped by admission and batch folding
343
+ until every named ticket has settled. Prerequisites may live in any lane; a
344
+ prerequisite in the same lane also scores higher while a ticket waits on it,
345
+ like a dependency-closure leaf. A prerequisite
346
+ that ends `failed` or `killed` settles the dependent `failed` with
347
+ `prerequisite cc-N failed` and no exit code, without spawning cargo; its riders
348
+ follow the normal attachment rules. A prerequisite that already finished
349
+ resolves immediately; an unknown ticket is rejected as a bad intent. A blocked
350
+ ticket never attaches to a run already in flight (that run started before the
351
+ prerequisite finished), and `hauler status`, `hauler result`, and await
352
+ heartbeats show `waits for cc-N (running 2m/~5m)` while it is held.
353
+
333
354
  Admission is separate from lane scheduling. It observes one-minute load per
334
355
  core and, on Linux, CPU PSI `some avg10`, then applies the configured thresholds
335
356
  and the global permit cap. Load and CPU pressure never defer below
@@ -363,18 +384,31 @@ own `-j` flag or `CARGO_BUILD_JOBS` always wins over both.
363
384
  | Lane isolation | A workspace-root and target-directory pair is serialized independently from other lanes. |
364
385
  | 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. |
365
386
  | 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. |
366
- | Scheduling | EWMA estimates, optional kache priors, fan-out, dependency topology, recent edits, and request age determine lane order. |
367
- | Persistence | Tickets, output tails, timings, outcomes, and savings are stored in SQLite. |
387
+ | Scheduling | EWMA estimates, 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. |
388
+ | Persistence | Tickets, output tails, timings, outcomes, and savings are stored in SQLite; every leader run's whole combined output is kept on disk as `<state dir>/tickets/<ticket>.log`. |
368
389
  | 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. |
369
- | Wait escalation | A queued request waiting longer than the larger of twice its own estimate and ten minutes is flagged as delayed; running jobs silent for more than five minutes show a quiet-duration hint. Nothing is killed automatically. |
390
+ | Wait escalation | A queued request waiting longer than the larger of twice its own estimate and ten minutes is flagged as delayed; running jobs silent for more than five minutes show a quiet-duration hint. A running job past three times its estimate whose process tree has burned no CPU and printed nothing for ten minutes is flagged `stalled`; only a stalled job whose submitting connection is gone is killed automatically. |
370
391
  | Daemon status | `running`, `stopped`, or `unresponsive`: a socket that exists but does not answer within its budget is reported as unresponsive, never as stopped. |
371
392
 
372
393
  ### Tickets and long-running requests
373
394
 
395
+ ![cargo-hauler dashboard detail drawer streaming a running ticket's live output](docs/media/dashboard-live-output.png)
396
+
374
397
  Every request has a durable ticket (`cc-<n>`). Its status, exit code, output
375
398
  tail, estimate, and timestamps are stored in SQLite and can be read from later
376
- sessions. `hauler exec --bg -- cargo …` and `hauler_request` return the ticket
377
- immediately. A synchronous request also switches to background mode when a
399
+ sessions. The ledger keeps only a bounded tail (16 KiB); the run's whole
400
+ combined stdout+stderr goes to `<state dir>/tickets/<ticket>.log` as the daemon
401
+ emits it — for a demultiplexed `check`/`build`/`clippy` that is the rendered
402
+ diagnostics stream, not cargo's JSON — up to `CARGO_HAULER_TICKET_LOG_MAX_BYTES`
403
+ (64 MiB by default; the file then ends with one truncation line). A request
404
+ that attached to an in-flight run shares its leader's log, and the row records
405
+ that path. `hauler result cc-N` names the file and its size, `--json` carries
406
+ it as `request.outputPath`, and `hauler result cc-N --full` (or `hauler_result`
407
+ with `full: true`) renders the log itself — so a red `cargo test` is triaged
408
+ from the ticket's own `failures:` list and panic sections instead of a second
409
+ run. The startup retention pass that prunes old ledger rows removes their logs
410
+ too, along with any log whose row is gone. `hauler exec --bg -- cargo …` and
411
+ `hauler_request` return the ticket immediately. A synchronous request also switches to background mode when a
378
412
  *measured* estimate — EWMA history or kache priors, never the cold-start
379
413
  default — exceeds the host's shell-tool cap (nine minutes for Claude, ten for
380
414
  Codex, fourteen for Cursor; the PATH shim uses `CARGO_HAULER_HOST` when it is
@@ -383,7 +417,9 @@ whole wait: the work queued ahead in the lane plus the job's own runtime,
383
417
  which the queued line reports as `wait ~Ns, run ~Ns`. That conversion exits
384
418
  `75` (`EX_TEMPFAIL`) with the ticket on stderr, so `cargo build && …` chains
385
419
  and scripts cannot mistake "submitted" for "built"; explicit `--bg` keeps exit
386
- `0`. Failed runs feed the estimate history too, so a broken build is not
420
+ `0`. When the caller's stdout is not a terminal (`cargo test > out.log`), the
421
+ notice adds that the redirect receives no output and to read it with
422
+ `hauler result cc-N --full`. Failed runs feed the estimate history too, so a broken build is not
387
423
  re-estimated cold on every retry.
388
424
 
389
425
  A foreground `hauler exec` that receives SIGINT or SIGTERM (Ctrl-C, or a
@@ -396,6 +432,28 @@ start cargo at all. If the connection drops after the ticket was accepted, the
396
432
  client prints `connection to daemon lost; ticket cc-N continues — hauler
397
433
  result cc-N` and exits `1`; the daemon finishes the ticket on its own.
398
434
 
435
+ A deadlocked test binary holds its lane for ever at 0% CPU with nothing on
436
+ stdout, and neither the estimate overrun nor the output silence alone can
437
+ tell it from a slow build. The daemon therefore samples the CPU time of every
438
+ running ticket's process tree every 30 seconds (`/proc` on Linux, `ps` on
439
+ macOS; other platforms do not detect stalls). A ticket is flagged `stalled`
440
+ when its elapsed time exceeds `CARGO_HAULER_STALL_ESTIMATE_FACTOR` (3) times
441
+ its estimate, the tree's CPU time has not changed for
442
+ `CARGO_HAULER_STALL_IDLE_MS` (ten minutes), and it printed nothing in that
443
+ window. `hauler status`, `hauler_status`, and the dashboard show `stalled`
444
+ with the idle duration; `hauler result` and `hauler_result` answer `ticket
445
+ looks stalled (no CPU for Nm) — hauler kill cc-N`; `hauler await` heartbeats
446
+ say the same. Riders of a stalled leader report the leader's stall and its
447
+ ticket, since killing a rider only detaches it. A stalled ticket whose
448
+ submitting connection is still open is only flagged. When that connection has
449
+ disconnected (a dead agent shell, a killed hook), the ticket is marked
450
+ orphaned, and once it is also stalled the daemon kills it through the normal
451
+ `hauler kill` path — riders settle or requeue as for any kill — with the
452
+ error `stalled: no CPU for Nm after owner disconnected; killed automatically`.
453
+ `CARGO_HAULER_STALL_AUTO_KILL=0` keeps the flag and never kills. Background
454
+ tickets (`--bg`, `hauler_request`) have no streaming connection and are only
455
+ ever flagged.
456
+
399
457
  The `tool/after` route checks the session's background tickets — `--bg`,
400
458
  `hauler_request`, and synchronous requests the client converted to a ticket
401
459
  — and, on the first tool call after one finishes, adds its result to the
@@ -469,10 +527,11 @@ is reported as unavailable and never rejects a request.
469
527
 
470
528
  | Variable | Default | Meaning |
471
529
  | --- | --- | --- |
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. |
530
+ | `CARGO_HAULER_STATE_DIR` | Per-user cache directory | Unix socket or Windows named pipe source, SQLite ledger, daemon log, pid lock, `hook-state.json`, `hook-events.jsonl`, and the per-ticket output logs under `tickets/`. No legacy alias. |
473
531
  | `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
532
  | `CARGO_HAULER_MAX_CONCURRENT` | `5` | Global admission permits for Cargo processes across all lanes; an integer >= 1. |
475
533
  | `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. |
534
+ | `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). |
476
535
  | `CARGO_HAULER_LOAD_THRESHOLD` | Disabled | Per-core one-minute load threshold for deferring new admissions. |
477
536
  | `CARGO_HAULER_LOAD_MIN` | `2` | Active Cargo processes below which load, CPU PSI, and soft memory pressure do not defer admission. |
478
537
  | `CARGO_HAULER_CPU_PRESSURE_THRESHOLD` | `75` | Linux CPU PSI `some avg10` percentage for deferring new admissions; `0` or `off` disables. |
@@ -487,9 +546,13 @@ is reported as unavailable and never rejects a request.
487
546
  | `CARGO_HAULER_BATCH` | Enabled | `0`, `false`, `off`, or `no` disables the batch composer. |
488
547
  | `CARGO_HAULER_BATCH_WINDOW_MS` | `150` | Delay applied to a batchable lane head so nearby requests can fold; `0` disables. |
489
548
  | `CARGO_HAULER_KILL_GRACE_MS` | `8000` | Time between SIGTERM and SIGKILL when the daemon stops a Cargo process. |
549
+ | `CARGO_HAULER_STALL_ESTIMATE_FACTOR` | `3` | A running ticket becomes a stall candidate once its elapsed time exceeds this multiple of its estimate. |
550
+ | `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. |
551
+ | `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. |
490
552
  | `CARGO_HAULER_STOP_WAIT_MS` | `30000` | Maximum wait for one stop-hook invocation; values above the 7200000 ms await ceiling are clamped. |
491
553
  | `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. |
554
+ | `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. |
555
+ | `CARGO_HAULER_TICKET_LOG_MAX_BYTES` | `67108864` (64 MiB) | Bytes of a leader run's combined output written to `<state dir>/tickets/<ticket>.log` before the log stops with one truncation line; `0` writes no ticket logs (`hauler result` then has only the tail). |
493
556
  | `CARGO_HAULER_LOG_LEVEL` | `Info` | Daemon log level. |
494
557
  | `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. |
495
558
 
@@ -552,7 +615,7 @@ data is the daemon's own. The repository ships no preview harness of its own.
552
615
 
553
616
  agent-bundle does not yet have an npm release; this repository pins the
554
617
  [pkg.pr.new](https://pkg.pr.new) preview of main commit
555
- [`5775351fb`](https://github.com/ScriptedAlchemy/agent-bundle/commit/5775351fbc1c82e2861a9d69cad78adb086d052d)
618
+ [`42539ff5f`](https://github.com/ScriptedAlchemy/agent-bundle/commit/42539ff5fbafdff0656317b841a50100ac0fc141)
556
619
  for both `agent-bundle` and `@agent-bundle/runtime`. `inspect` reports the
557
620
  `agent` component kind as unavailable on every host (agent-bundle G5
558
621
  deferral); this plugin defines no agents. Two framework limitations observed