Skip to content

Pull-request closure and explicit continuation: worker evidence

Task: e8f3d82b-2244-487b-b30f-9367e21e8430, frozen version 2. Execution: 77267a78-6310-4c70-874b-39415cc81299. Repository: h8v6/heyaira; branch: heyaira/e8f3d82b. Source and starting HEAD: 56d0899023c1d069daa5fa4aa652e0837ab5b761. Starting worktree was clean. No carried candidate and no subagents. Server identity matched the supplied resource, instance and project.

Commands below ran on 2026-10-13 in /Users/jablonskib/HeyAira-agents/.heyaira-worktrees/heyaira/e8f3d82b-worker, except the explicitly identified base archive. Python is the prepared Python 3.12.7 environment; PostgreSQL uses the prepared Unix-socket maintenance endpoint and randomly named disposable databases. No installation, production mutation, push, PR, merge or deployment was performed. DSNs and credentials are not included.

The candidate tests were first run against the intended working-tree contents. The same K2 command is repeated after the local commit; the final HEAD SHA and that run's actual outcome are recorded in the task RESULT/receipt. This report is part of the candidate commit.

K1 — real regressions on base and candidate

Preparation used git archive 56d0899023c1d069daa5fa4aa652e0837ab5b761 (exit 0), extracted by tar -xf - -C <base archive> (exit 0), then copied only the final tests/test_pull_request_closed.py and tests/test_github_webhooks.py over their archive paths. The archive was under the prepared writable TMPDIR: .../heyaira-tmp/pr-base-l3yn14jg. Its application source remained exactly base. The HEAD-only file was not run on base.

Command in that base archive:

python scripts/test_postgres.py tests/test_pull_request_closed.py tests/test_github_webhooks.py -p no:cacheprovider --tb=short -v

Actual exit 1; 23 failed, 5 passed in 19.96s. No import errors, collection errors, skips or empty selection. An earlier run of the initially written regressions also exited 1: 23 failed, 5 passed in 23.69s. The final run above uses the final committed test contents.

Spec case Actual base assertion/behavior Candidate
P1 No merged publication entry: “merged delivery must record the candidate's merged publication” pass
P1b Added task_checks_failed: “merged candidate must not push Checks failed” pass; no push/re-arm, no unfinished entry
P2, both variants No evidence-only entry: “different head merge must leave evidence” pass; delayed close/redelivery unchanged; manual finish works
P3 Workflow still current: “merge must retire the CI-blocked workflow” pass; preserved handoff, done stage, one completion push
P3b Empty handoff does not start with “Pull request #7 merged on GitHub” pass
P4 ('blocked','blocked') != ('confirmed','done') pass; no CI schedule or more rechecks
P5 No merged entry: “held task still needs merge evidence” pass; hold preserved, explicit release/manual finish works
P6, both variants Publication retained: “closed PR must withdraw the publication” pass; one blocking notification, withdrawal, re-send
P7 Unrelated deliveries leave task/workflow unchanged pass on both
P8, four tests Invalid/held/active continuation accepted instead of exact refusal; blocked predecessor stays current pass; retirement, handoff, no push, replay and conflict verified
P9, both variants workflow_control: workflow_not_retirable pass; grandfathered done completion and receipted blocked completion
P10 route-accepts half Both simultaneous signed deliveries accepted pass on both
P10 completion half len(merged_entries) == 0, expected 1 pass; one entry and one task version increment
P11, six cases KeyError: 'pull_request' pass; includes deleted fork and malformed number
P12–P14 HEAD-only, not run on base pass; project isolation, three terminal evidence shapes, handoff/notification semantics

Observed spec prediction difference: base MCP silently ignores the unknown supersedes_task_id field rather than rejecting it as an unexpected argument. P8 still fails on the asserted wrong behavior (accepting an invalid continuation or leaving its predecessor current); HEAD requires the exact named refusal codes. No base implementation was modified to manufacture an error.

Actual final base failure list:

FAILED test_P1_merged_publication_completes_once_without_push
FAILED test_P1b_merged_candidate_ci_never_pushes_or_rearms
FAILED test_P2_other_head_is_terminal_evidence_only[False]
FAILED test_P2_other_head_is_terminal_evidence_only[True]
FAILED test_P3_merge_retires_ci_blocked_workflow
FAILED test_P3b_empty_handoff_gets_merge_fallback
FAILED test_P4_merge_confirms_stuck_publication_without_ci
FAILED test_P5_hold_preserves_blocked_task_with_merge_evidence
FAILED test_P6_close_withdraws_publication_and_blocks_once[False]
FAILED test_P6_close_withdraws_publication_and_blocks_once[True]
FAILED test_P8_explicit_continuation_retires_only_named_predecessor
FAILED test_P8_continuation_gates[blocked]
FAILED test_P8_continuation_gates[held]
FAILED test_P8_continuation_gates[active]
FAILED test_P9_manual_finish_accepts_every_done_shape[False]
FAILED test_P9_manual_finish_accepts_every_done_shape[True]
FAILED test_P10_concurrent_merge_changes_once
FAILED test_P11_pull_request_fields[head_repo0]
FAILED test_P11_pull_request_fields[None]
FAILED test_P11_malformed_pull_request_still_has_empty_fields[None]
FAILED test_P11_malformed_pull_request_still_has_empty_fields[pull1]
FAILED test_P11_malformed_pull_request_still_has_empty_fields[pull2]
FAILED test_P11_malformed_pull_request_still_has_empty_fields[pull3]
23 failed, 5 passed in 19.96s

K2 — exact zero-skip selection and separately counted TCP suites

Exact required command:

python scripts/test_postgres.py tests/test_pull_request_closed.py tests/test_pull_request_closed_head.py tests/test_github_webhooks.py tests/test_ci_correction.py tests/test_merge_ready.py tests/test_merge_ready_head.py tests/test_schema_guard.py tests/test_notification_docs_contract.py tests/test_docs_contract.py -p no:cacheprovider

Actual exit 0:

133 passed in 101.70s (0:01:41)
postgres_acceptance=passed: selected tests, zero skipped tests

The HEAD-only tests also cover NOWAIT refusal without predecessor mutation, legacy request hashes (omitted/None field), idempotency conflicts, both interactive claim statuses, no implicit superseding, repository mismatch, evidence-only withdrawn/other/active publications, and multiple current matches without starvation.

Each file below was run separately with the exact form python -m pytest tests/<file> -p no:cacheprovider -rs, with PYTHONPATH=src and an isolated disposable execution database derived from the prepared test maintenance endpoint. Every command exited 0.

File Passed Skipped
test_publication_end_state.py 0 17
test_ci_follow_up.py 0 27
test_server_checks.py 0 8
test_workflow_e2e.py 1 56
test_org_v1_b4.py 0 10
test_workflow_retire.py 0 18
test_catalog_workflow.py 1 2

Actual skip reason: listening sockets are not permitted here (agent sandbox); runs in CI. These integration cases did not pass in this execution. An initial separate-file run without a prepared execution database had the same counts, with the missing-database skip reason; the prepared rerun above reached the sandbox listener check. The required ASGI selection is independently zero-skip.

tests/test_backup_state_marker.py was not run, as required. No table was added; MARKER_TABLES and migrations are untouched. No full-suite run was performed.

Earlier candidate checks, retained for transparency:

Command Actual result Correction
python scripts/test_postgres.py tests/test_pull_request_closed.py tests/test_github_webhooks.py -p no:cacheprovider --tb=short -v exit 1; 3 failed, 25 passed Tests now read history/stage through the proper MCP/SQL views
Exact K2 selection above, first attempt exit 1; 8 failed, 121 passed HEAD-only fixture SQL types/required fields and stale generated contract
python scripts/test_postgres.py tests/test_pull_request_closed_head.py -p no:cacheprovider --tb=short, first rerun exit 1; 6 failed, 7 passed Synthetic history actor field
Same HEAD-only command, next rerun exit 1; 2 failed, 15 passed Synthetic workflow version aligned with inserted event sequence

K3 — contracts and whitespace

Commands in the candidate worktree:

PYTHONPATH=src python scripts/export_mcp_contract.py
exit 0: wrote contracts/mcp-tools.json

PYTHONPATH=src python scripts/export_mcp_contract.py --check
exit 0: MCP contract is up to date

PYTHONPATH=src python scripts/check_docs_contract.py
exit 0: documentation contract passed: 50 MCP tools covered

git diff --check
exit 0: no output

Git uses the prepared readable executable /Applications/Xcode.app/Contents/Developer/usr/bin/git. The initial /usr/bin/git wrapper attempted denied xcrun-cache writes; using the actual Git executable avoided that wrapper without changing permissions.

K4 — closed scope and ancestry

Required final-HEAD commands (actual final outputs retained in RESULT):

git diff --name-only 56d0899023c1d069daa5fa4aa652e0837ab5b761..HEAD
git merge-base --is-ancestor 56d0899023c1d069daa5fa4aa652e0837ab5b761 HEAD
git diff 56d0899023c1d069daa5fa4aa652e0837ab5b761..HEAD -- src/heyaira/workflow.py

The intended paths are only the four authorized source files, the two new PR-closure test files, the three specified existing test files, the five specified documentation pages, this evidence report, and the regenerated contracts/mcp-tools.json. No migration, new tool, notification kind, dedupe format, model field or contract-digest shape was added.

A Python AST comparison of git show <base>:src/heyaira/workflow.py with the candidate exited 0 with the actual output:

Existing workflow definitions changed: _apply_ci, _apply_recheck, _ci_unfinished, control, dispatch
Frozen SQL projections unchanged

All other existing function/class ASTs match base, including follow_ci, _ready_to_merge, _known_merged, record_ci_result, _publication_confirmed, recheck_publications, transition and set_task_status. _KNOWN_MERGED_SQL, CI_GREEN_SQL and MERGE_READY_SQL match base. The new code makes no GitHub API call and adds no CI scheduling write. The matching query has no LIMIT; the second dispatch task lock uses NOWAIT.

Limits and next actor

Cause: the signed webhook only recorded Actions runs, and finished workflows could not be retired for manual completion. The candidate implements the frozen own-publication/head-equality rule, terminal evidence/idempotence, notification gates, CI guards and explicit validated continuation. Confidence is high for the exercised PostgreSQL/ASGI paths; the separately skipped listener tests remain unverified locally.

Bridge performs independent verification and publication. Owner/DevOps must enable the App's Pull request subscription with Pull requests: Read, rebuild server/beat images, and perform the documented post-deploy PR check. No backfill or automatic merge is provided. Existing stuck tasks need the documented manual retire/completion procedure or an explicit continuation.

Execution limitation: what: TCP integration coverage is unavailable because the sandbox denies listening. who_moves: Bridge/CI environment operator. needed: run the seven separately counted files in the existing listener-enabled CI environment.

No implementation blocker remains. No subagent was used.