Skip to content

fix(kanban): refuse a receipt-less worker completion (no_receipt, rc 4) - #1621

Merged
ang-fleet-lander[bot] merged 2 commits into
mainfrom
daedalus/t_e21aa11c-receipt-gate
Oct 2, 2026
Merged

ang-fleet-lander[bot] merged 2 commits into
mainfrom
daedalus/t_e21aa11c-receipt-gate

Conversation

@ang-fleet-workers

@ang-fleet-workers ang-fleet-workers Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

A dispatcher-owned worker handoff (expected_run_id set) that closes a running
card done with prose only -- no PR ref, survivor claim, attachment, or
structured metadata beyond bookkeeping (worker_session_id/pool/no_pr/
no_pr_reason/review_skipped) -- is refused before any mutation with
ReceiptRequiredError (reason code no_receipt) and a
completion_blocked_no_receipt event. hermes kanban complete and
request-review (milestone_only in-place completion) exit 4 on it.
Operator closes, superseded closes and reviewer approvals are not gated.
Board knob kanban.receipt_gate (default true).

hermes_cli/kanban_receipt.py also lints a board:
python -m hermes_cli.kanban_receipt --days 7 [--db PATH] [--json]
rc 0 none / 1 found / 2 unreadable.

Verified: tests/hermes_cli/test_kanban_receipt_gate.py 10/10; 3 go red with
the kernel gate reverted. 20 complete_task/expected_run_id kanban test files

  • tools/plugins/gateway kanban suites: 1025 passed, 6 failed, all 6 also
    fail on fork/main 264dcef. Six existing worker-path tests now pass a
    minimal metadata receipt.

Card t_e21aa11c.

Incident: t_c18e4162 / t_872b6b83 (2026-10-01). Both of those cards DID carry receipts (4 and 5 attachments, plus pcv_before/pcv_after sha tables and live_evidence in run metadata). The session overview printed 'no receipt on card' because it reads only tasks.result, which is empty when a worker hands off via summary. That reader is hermes-home scripts/session-overview.py; it is fixed in a separate hermes-home PR.

Override: kanban.receipt_gate: false in the board-home config.yaml (a reason field is not needed: it is a config knob, visible in the config diff and in git history) — operators who must close prose-only; per card, an operator hermes kanban complete (no dispatcher run id) is not gated, and every refusal leaves a completion_blocked_no_receipt event on the card.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

A dispatcher-owned worker handoff (expected_run_id set) that closes a running
card done with prose only -- no PR ref, survivor claim, attachment, or
structured metadata beyond bookkeeping (worker_session_id/pool/no_pr/
no_pr_reason/review_skipped) -- is refused before any mutation with
ReceiptRequiredError (reason code no_receipt) and a
completion_blocked_no_receipt event. `hermes kanban complete` and
`request-review` (milestone_only in-place completion) exit 4 on it.
Operator closes, superseded closes and reviewer approvals are not gated.
Board knob kanban.receipt_gate (default true).

hermes_cli/kanban_receipt.py also lints a board:
  python -m hermes_cli.kanban_receipt --days 7 [--db PATH] [--json]
rc 0 none / 1 found / 2 unreadable.

Verified: tests/hermes_cli/test_kanban_receipt_gate.py 10/10; 3 go red with
the kernel gate reverted. 20 complete_task/expected_run_id kanban test files
+ tools/plugins/gateway kanban suites: 1025 passed, 6 failed, all 6 also
fail on fork/main 264dcef. Six existing worker-path tests now pass a
minimal metadata receipt.

Card t_e21aa11c.
…pt (t_e21aa11c)

CI on 42c64f6 caught 8 more worker-path tests completing with prose only;
each now passes metadata={tests_run: 1}. Verified: the 4 files pass locally.
@ang-prism

ang-prism Bot commented Oct 2, 2026

Copy link
Copy Markdown

PRism

Prism, formerly FleetReview — same reviewers, new name (until 2026-10-13)

Review: pre-merge · head fbed8e7b88dd · duration 22m 00s
Profile: light (merit: default light: lines 413<800, files 15<1000000, hunks 22<1000000, no hot path) · policy: changed-lines>400
Roster: B-state → gpt-6.1-sol (openai), C-assert-xhigh → claude-code-opus-5-5 (anthropic), F → grok-4.7 (xai), G → grok-4.7 (xai)

profile: light (rule: default light: lines 413<800, files 15<1000000, hunks 22<1000000, no hot path) · round 0 · members: B-state, C-assert-xhigh, F, G · families: anthropic,openai,xai

Confidence: 3/5

Findings

  • P1 hermes_cli/kanban_db.py:11519 — Routing Regression · agreed: B-state,C-assert-xhigh,F,G (openai, anthropic, xai)
  • P2 hermes_cli/kanban_receipt.py:123 — Lint drops survivor receipts · agreed: F,G (xai)

Prism provenance · models: B-state=gpt-6.1-sol, C-assert-xhigh=claude-code-opus-5-5, F=grok-4.7, G=grok-4.7 · cost: $1.85 · duration: 21m 54s · rounds: 1 · files examined: 15

@ang-fleet-lander

Copy link
Copy Markdown

🤖 merged-by: apollo · lane: kanban-merge-pass · gate: ADVISORY (FleetReview not green for fbed8e7): fleetreview-advisory-20260927-standing.md · why: t_e21aa11c: Kanban: two deploy cards today (t_, t_) closed 'done — no receip; Argus off card review (Ace 13:08), CI green

@ang-fleet-lander
ang-fleet-lander Bot added this pull request to the merge queue Oct 2, 2026
Merged via the queue into main with commit c18da2f Oct 2, 2026
57 of 59 checks passed
@ang-fleet-lander
ang-fleet-lander Bot deleted the daedalus/t_e21aa11c-receipt-gate branch October 2, 2026 01:44
ang-fleet-workers Bot added a commit that referenced this pull request Oct 2, 2026
…ts, #1584..#1621)

20 conflicted files resolved onto the upstream-extracted modules. Per-commit
carry audit (tools/e45-foldcommits.py + symbol greps): every fork/main commit's
behavior present in the merged tree; #1595 steer accept/withdraw re-threaded
into tools/delegate_tool_registry.steer_subagent and steer_ledger kept out of
the RPC snapshot. Test imports repointed tests.run_agent -> tests.agent for
the moved incremental-persistence helpers. 0 markers, py_compile clean.
Fix-forward of fold reds follows. (t_e45c8c8d)
ang-fleet-workers Bot added a commit that referenced this pull request Oct 2, 2026
…ed contracts

All six files are fork-only tests that arrived with the fork/main fold and
asserted pre-sync shapes; the production behaviour each guards is present:
- test_plugins: #819 per-event refusal text (callback/elapsed/budget) and the
  named 'worker failed to start' skip, instead of the unformatted template.
- worker_leftover_reap: facade -> kanban_db_dispatch repoint (e45-kbrepoint);
  worker completions pass expected_run_id (upstream LiveClaimError fence) and
  a metadata receipt (#1621 no_receipt gate).
- needs_input_pager: link the parent before the dependency wait (upstream
  42a778a re-kinds a parent-less dependency block to needs_input).
- edit_skills lint contract: allow_real_home_io marker (upstream home I/O guard).
- steer_persist: steer is a standalone persisted user row (NousResearch#110979), tool row clean.
- followup_timestamp AST: the recursive _run_agent now lives in gateway/run_turn.py.
Fold-surface subset: 11 failed -> 0 (targeted reruns). (t_e45c8c8d)
ang-fleet-workers Bot added a commit that referenced this pull request Oct 2, 2026
…t + provenance gates

- dispatcher-owned completions (fixture pins HERMES_KANBAN_RUN_ID) carry a
  metadata receipt (#1621 no_receipt gate).
- the session-provenance test seeds its session in state.db (upstream
  3c33231 rejects phantom session ids).
test_kanban_tools: 90 passed / 1 failed. The one left
(test_worker_the_dispatcher_never_recorded..., upstream-only) needs a ruling:
upstream's self-registered worker (adopt_worker_pid, no spawned event) fails
the fork's claim-window identity rule (t_0ae83825), so release_stale_claims
reclaims it. (t_e45c8c8d)
ang-fleet-workers Bot added a commit that referenced this pull request Oct 2, 2026
…nd_message seal, adapt tests to fork gates / upstream shapes

- tools/send_message_tool.py: restore `_is_dispatcher_owned_worker_process` / `_check_send_message`
  verbatim from fork/main (#636 worker notify-channel seal; fork-only, dropped by the merge).
- tests (upstream-only, adapted to fork contracts): test_kanban_provenance — a dispatched worker cannot
  mint on the placeholder 'default' lane (kanban_worker_policy) and a worker-created card is homed on
  the owning task (kanban_db._resolve_birth_session C6 #1118), not a tool-supplied session_id;
  test_kanban_descendant_scope / test_kanban_redaction — completions carry a structured receipt
  (fork receipt gate #1621, prose alone is refused).
- tests (fork-only, adapted to upstream shapes, property kept): test_kanban_authority_ambient_reads —
  `_require_orchestrator_tool` raises _Reject (handlers return it); sandbox passthrough seal asserts
  the property (never "task var present + owner marker absent": fork stamped an owner pid, upstream
  strips the var and fences the lineage); test_kanban_comment_provenance_tools — forged attribution
  is now refused by the strict-parameter gate instead of silently dropped, and nothing lands;
  test_kanban_session_attribution — spawn source scan repointed to kanban_db_dispatch (split).

Verified via scripts/test-gate: provenance+descendant_scope+redaction 17 passed;
authority_ambient_reads+comment_provenance_tools+session_attribution 36 passed.
ang-fleet-workers Bot added a commit that referenced this pull request Oct 2, 2026
…ins, launch bound follows claim TTL, cron catch-up opt-out

Proved on ace-ai (Linux; these files skip on darwin):
- tests/e2e/core/kanban/*: _helpers.Board writes KANBAN_FAST_CONFIG
  (kanban.rate_limit_cooldown_seconds: 0 — the fork's config beats the
  FAST_ENV env bridge and load_config fills the 300 s default; receipt_gate:
  false — #1621 refused the rigs' prose-only kanban_complete). dispatcher
  restart: body check strips the fork's `origin:` provenance line.
  rate_limit_review 3 passed; worker_contract 2 passed/2 xfailed;
  decompose_billing 1 passed/3 xfailed; dispatcher_restart 2 passed.
- hermes_cli/kanban_db.py: _dead_claimer_launch_bound_seconds() — the #983
  pid-less dead-claimer hold (900 s) follows HERMES_KANBAN_CLAIM_TTL_SECONDS
  when set; the SIGKILL-mid-tick rig (3 s TTL) otherwise strands claims
  15 min. Default unchanged; tests/hermes_cli kanban_db +
  reclaim_unprovable_liveness + quota_exit: 255 passed.
- tests/e2e/core/delivery/test_cron_virtual_clock_soak.py: fixtures pin
  cron.oneshot_catchup_s: 0 (fork #1087 fires a missed one-shot late; the
  oracle models the upstream never-fires contract). 5 passed/1 xfailed.
- tests/e2e/core/providers/test_openai_codex_pool.py: two cells xfail
  (strict=False) — they pin upstream's dead-row-on-disk + stdout re-login
  model that fork #673 (codex_owner receipts) replaced. 1 passed/2 xfailed.
Ledger updated: upgrade/git reds are the fork remote lacking release tags
newer than v2026.5.7 (N-1 installer predates --non-interactive) -> FOLLOWUP.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants