feat(issue-33): the job budget travels and the two clocks carry different labels

- wrapper: TIMEOUT falls back to MAM_JOB_TIMEOUT_S (--timeout > env > 3600);
  an invalid value warns and keeps 3600.
- loop: --job-timeout <sec> (run_loop.sh passes it on; refused in the legacy
  shell loop). The runner always hands the wrapper --timeout, so the budget
  the wrapper registers is the one its wait caps come from.
- runner: wait_for_job and the MAM_CHILD_WAIT_S default are budget + 300 s
  (MAM_WAIT_GRACE_S), today's 3900 with no option; an explicit
  MAM_CHILD_WAIT_S still wins.
- subscriber: the wall-clock budget returns 4 (RC_WALL_CLOCK), silence keeps
  2 (RC_NO_EVENT). The wrapper maps both to caller rc 2 and labels the close
  from the rc: wall_clock_timeout vs deadline_timeout; the disk-heartbeat
  grace that ends on the deadline is the wall clock too.
- registry close accepts wall_clock_timeout (engine: -> error); the remote
  runner's deadline and command-timeout details lead with wall_clock_timeout;
  the sub-job table files it CLOSED-UNCONFIRMED (first token, colon stripped).

Test expectations changed only where the contract changed: the loop's
contract_args now starts with --timeout, the subscriber's exit-code docstring
names rc 2/4, and the registry --help capture lists the new close kind.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
GodopuandClaude Opus 5.5 committed 2026-09-25 11:43:10 +00:00
1 parent 8ea65bb238
commit ec9586bb9b
11 files changed
+409 -23

No files matched your search

+1 -1
View File
@@ -359,7 +359,7 @@ def test_job_subscriber_cli_contract_snapshot(mam_sandbox):
assert job_subscriber.TERMINAL_EVENTS == ("completed", "error")
src = Path(job_subscriber.__file__).read_text(encoding="utf-8")
for doc in (" 0 all watched jobs reached", " 1 any watched job reached",
" 2 timed out"):
" 2 no event for the idle window", " 4 the wall-clock budget"):
assert doc in src, doc
assert 'return 3' in src, "fatal-error exit code 3 must survive"