Summary
fm-contributions.sh poll never reaches a terminal observation state for a merged PR. Every poll cycle stamps error: forge observation unavailable or changed during read on a record whose observation payload is actually correct and complete, so the authenticated check surfaces a check: contributions: observation unavailable for <url> wake forever.
Observed 3 times in ~30 minutes for one merged PR, each time waking supervision for a contribution that needs no attention.
The contradiction
The stored record carries the error alongside correct data:
error: forge observation unavailable or changed during read
checked_at: 2026-09-16T20:02:20Z # fresh on every wake, seconds old
observation: present
head = 6c842af66f572da8be017cb3627c535afcc9f513 # matches the merged head exactly
state = merged
checks = [{name: "Lint & Test", status: completed, conclusion: success}, ...]
pending_events is empty and no event token exists, so ack has nothing to consume — there is no supported way to retire the signal.
What was refuted
- Not budget or slowness. Direct forge reads measured 1.24s (
pulls/<n>) and 1.56s (commits/<sha>/check-runs) — well inside the documented 5s per-call cap and the 20s FM_CONTRIBUTIONS_BUDGET.
- Not staleness/expiry.
checked_at is seconds old at each wake, nowhere near the 900s FM_CONTRIBUTIONS_MAX_AGE.
- Not a failed read. The observation payload is complete and matches the forge exactly.
Probable cause
The help states an observation is "one coherent forge read (a PR head is rechecked after fetching checks/reviews)". For a merged PR that recheck appears to classify the terminal state as changed during read. Because the owning task's backlog row legitimately retains its completion artifact link (links: "pr:<url>"), the URL stays owned and is re-polled indefinitely, failing the same benign way each cycle.
Impact
A merged PR on a closed task generates an unclearable supervision wake on every poll cadence. The only workarounds are both wrong: deleting the completion artifact link (which AGENTS.md §10 requires preserving, and which destroys the record of what shipped), or fabricating an event token to ack.
Suggested fix
Treat a terminal PR state (merged, or closed + merged: true) as a coherent, final observation rather than re-erroring, so the record settles and stops producing wakes.
Summary
fm-contributions.sh pollnever reaches a terminal observation state for a merged PR. Every poll cycle stampserror: forge observation unavailable or changed during readon a record whose observation payload is actually correct and complete, so the authenticated check surfaces acheck: contributions: observation unavailable for <url>wake forever.Observed 3 times in ~30 minutes for one merged PR, each time waking supervision for a contribution that needs no attention.
The contradiction
The stored record carries the error alongside correct data:
pending_eventsis empty and no event token exists, soackhas nothing to consume — there is no supported way to retire the signal.What was refuted
pulls/<n>) and 1.56s (commits/<sha>/check-runs) — well inside the documented 5s per-call cap and the 20sFM_CONTRIBUTIONS_BUDGET.checked_atis seconds old at each wake, nowhere near the 900sFM_CONTRIBUTIONS_MAX_AGE.Probable cause
The help states an observation is "one coherent forge read (a PR head is rechecked after fetching checks/reviews)". For a merged PR that recheck appears to classify the terminal state as changed during read. Because the owning task's backlog row legitimately retains its completion artifact link (
links: "pr:<url>"), the URL stays owned and is re-polled indefinitely, failing the same benign way each cycle.Impact
A merged PR on a closed task generates an unclearable supervision wake on every poll cadence. The only workarounds are both wrong: deleting the completion artifact link (which
AGENTS.md§10 requires preserving, and which destroys the record of what shipped), or fabricating an event token toack.Suggested fix
Treat a terminal PR state (
merged, orclosed+merged: true) as a coherent, final observation rather than re-erroring, so the record settles and stops producing wakes.