RESULT: Bridge pickup stalls and durable refusal metadata¶
Historical report: bridge.pickup and bridge.polling were retired in S2 (decisions a9f0e60e and 6cab5c63).
Frozen task: df574214-aa01-4af3-9ff7-c47952edf87c v4.
Execution: d5d105ea-ca64-487e-8f00-780aac1dbb74.
Repository: h8v6/heyaira; branch: heyaira/df574214.
Source and starting HEAD: 7b4efed323e84558279ad67f14257eaa7bab5938.
The starting worktree was clean, with no carried candidate. No existing commit
was amended, rebased or reset. Subagents: none. Lead model: gpt-6.1-sol.
All commands ran in
/Users/jablonskib/HeyAira-agents/.heyaira-worktrees/heyaira/df574214-worker.
The result SHA and final HEAD scope output are recorded in the HeyAira RESULT
and receipt after the local commit; this file cannot contain its own commit SHA.
Cause and implemented behavior¶
A fresh heartbeat previously hid pickup stalls: the registered checks did not
observe unclaimed offers or a reported pickup pause. Bridge refusals also lacked
a durable common observer. The new registered bridge.pickup handler observes
real offered rows through identity device/anchor-project attribution, across
execution projects, and optional ISO-8601 pause timestamps. It uses the existing
scheduler, confirmation and recovery machinery with no repair actions.
Unsafe original reasons cannot become acceptable through the shared skip
helper's whitespace/control-character normalization. Details contain only the
four specified bounded fields; summaries identify the worst node and others.
One outer ASGI observer sees middleware-generated responses and the application's
500 handler. It writes only allowlisted metadata with one deadline covering
pool acquisition, node attribution and INSERT. The migration is now 061 (renamed by follow-up task d5f04d8e for fresh databases only).
Tick retention deletes at most 1000 rows older than 14 days. The operator query,
best-effort limitations and the unavailable-pool 503 gap are documented in
docs/operations/bridge-request-failures.md.
Confidence: high for the tested behavior. This is a worker report; independent acceptance belongs to Bridge's verifier. No push, PR, merge, installation, deployment or production mutation was performed.
Baseline regression (before implementation)¶
Command:
python scripts/test_postgres.py tests/test_bridge_pickup.py -p no:cacheprovider
At base 7b4efed, with only the new regression prepared, exit 1:
FAILED tests/test_bridge_pickup.py::test_registered_pickup_offers
KeyError: 'bridge.pickup'
ValueError: unknown check
1 failed in 2.78s
The same regression after implementation exited 0:
1 passed in 2.76s
postgres_acceptance=passed: selected tests, zero skipped tests
Final focused K1 command, on the completed implementation:
python scripts/test_postgres.py tests/test_bridge_pickup.py::test_registered_pickup_offers -p no:cacheprovider
exit: 0
1 passed in 0.54s
postgres_acceptance=passed: selected tests, zero skipped tests
Final frozen acceptance command¶
python scripts/test_postgres.py tests/test_bridge_pickup.py tests/test_bridge_request_failures.py tests/test_schema_guard.py -p no:cacheprovider
exit: 0
........................................... [100%]
43 passed in 11.42s
postgres_acceptance=passed: selected tests, zero skipped tests
This runs every new test and the complete schema-guard file. There is no filter,
deselection or skip. PostgreSQL is real, using disposable databases prepared by
the existing runner. HTTP tests use create_app() and an in-process ASGI
transport, actual registered routes and actual credential lookups. They need
no listening socket. Tests do not replace the registered pickup result with a
synthetic CheckResult. The lifecycle test selects the actual registered check
in a focused registry and runs ServerBeat.tick() and the real runner.
criterion_id: K1
outcome: pass
evidence_path: tests/test_bridge_pickup.py
feedback: Final focused command above exited 0 (1 passed); real linked offered rows, NULL lease/deadline, skipped reason, young offer, offline node and cross-project bound offer all asserted. Baseline exited 1 because the registered check was absent.
criterion_id: K2
outcome: pass
evidence_path: tests/test_bridge_pickup.py
feedback: Final frozen command exited 0 (43 passed, zero skips); no-offer pause, optional/malformed fields, disallowed/long reasons and _bounded_detail asserted. Additional regressions cover unsafe original skip reasons, naive ISO timestamps, worst-node name and bounded summary count.
criterion_id: K3
outcome: pass
evidence_path: tests/test_bridge_pickup.py
feedback: Final frozen command exited 0; two real scheduled FAIL cycles yield one incident and only notify/down. Continuous scheduled OK observations spanning the configured 120-second window yield recovered status and exactly one notify/recovered; two sends total and no repair notification.
criterion_id: K4
outcome: pass
evidence_path: tests/test_bridge_request_failures.py
feedback: Final frozen command exited 0; execution 409, claim 404, heartbeat invalid_heartbeat 400, unauthorized 401, retirement middleware 410, unmatched 404 and forced 500 each yield exactly one row with route/status/error/UUID/node assertions. Every stored column is checked for synthetic body/header markers. INSERT error, two-second INSERT stall and acquisition stall preserve response bytes/status with elapsed <=1.5 seconds. Parser bounds, unavailable-pool gap, unread retired request body and retention batches also pass.
criterion_id: K5
outcome: pass
evidence_path: docs/reports/df574214-bridge-stall-evidence.md
feedback: Exact final frozen command above exited 0: 43 passed, zero skipped tests. Two earlier runs passed all assertions but exited 1 during database cleanup with InsufficientPrivilegeError; those are retained below and are not claimed as passing acceptance.
criterion_id: K6
outcome: pass
evidence_path: docs/reports/df574214-bridge-stall-evidence.md
feedback: Source ancestry was checked with exit 0. The staged path check below covers the intended commit; the required HEAD diff and ancestry check are repeated after commit and recorded in RESULT. All intended paths are within the frozen scope.
Supplemental checks and intermediate results¶
Nearby compatibility command (before the final alias regression):
python scripts/test_postgres.py tests/test_bridge_pickup.py tests/test_bridge_request_failures.py tests/test_schema_guard.py tests/test_server_beat.py tests/test_server_beat_e2e.py tests/test_server_beat_timing.py tests/test_bridge_request_limits.py -p no:cacheprovider
exit: 0
72 passed in 26.88s
postgres_acceptance=passed: selected tests, zero skipped tests
Intermediate results retained truthfully:
- Pickup file: exit 0,
16 passed in 6.15s, zero skips. - The first combined run: exit 1,
23 passed, 13 errors in 21.43s. Observer fixture creation used an HTTP non-loopback OAuth issuer, rejected by the SDK withValueError: Issuer URL must be HTTPS. The fixture now uses HTTPS with an in-process transport. - A shell heredoc edit failed with
can't create temp file for here document: operation not permitted; the subsequently started observer rerun used the unchanged fixture and exited 1,13 errors in 10.00s. The edit was applied with the permitted patch tool. - Observer rerun after fixture correction: exit 0,
13 passed in 6.88s, zero skips. - First nearby compatibility run: exit 1,
2 failed, 64 passed in 34.85s. The old cadence test'sMagicMockpool lacked an async retention execute method (TypeError: object MagicMock can't be used in 'await' expression). Its fixture now providespool.execute = AsyncMock(); the corrected compatibility command above passed. - Two runs of the frozen command before the final alias test each passed all
42 assertions with zero skips (
42 passed in 21.21sand42 passed in 9.08s) but exited 1. The runner printed bothpostgres_acceptance=passed: selected tests, zero skipped testsandpostgres_acceptance=failed: InsufficientPrivilegeError. The latter occurs after pytest success in the runner's disposable-database cleanup. It is an environment execution limitation, not an assertion failure. The final 43-test command completed cleanup and exited 0.
The full repository suite, listener-based HTTP/MCP suites, production canaries and deployment were not run. Listening-socket availability was not probed; the required new ASGI regressions run without a listener. No tests were deselected to compensate for socket restrictions.
Git's macOS launcher could not write its xcrun cache in the sandbox. Git checks and the commit use the existing Xcode Git binary directly; the sandbox also warned about the unavailable global ignore file. These do not change the criterion scope or grant extra permissions.
Git scope checks¶
/Applications/Xcode.app/Contents/Developer/usr/bin/git diff --check
exit: 0
output: none
/Applications/Xcode.app/Contents/Developer/usr/bin/git merge-base --is-ancestor 7b4efed323e84558279ad67f14257eaa7bab5938 HEAD
exit: 0
output: none
/Applications/Xcode.app/Contents/Developer/usr/bin/git diff --cached --name-only 7b4efed323e84558279ad67f14257eaa7bab5938
exit: 0
docs/operations/bridge-request-failures.md
docs/reports/df574214-bridge-stall-evidence.md
migrations/061_bridge_request_failures.sql
src/heyaira/bridge_request_failures.py
src/heyaira/server.py
src/heyaira/server_beat.py
tests/test_bridge_pickup.py
tests/test_bridge_request_failures.py
tests/test_server_beat.py
tests/test_server_beat_timing.py
/Applications/Xcode.app/Contents/Developer/usr/bin/git diff --cached --check
exit: 0
output: none
These paths are checked again against HEAD in RESULT. Every path is within
src/heyaira/, tests/, docs/ or the single authorized migration.