Context
Operator-asked, 2026-06-16: "how can we get better to check what is merged already before writing responses?" — after status / handoff responses repeatedly asserted stale merge-state (naming a PR "at the merge gate" / "awaiting merge" that had already merged seconds earlier; happened ~5× in one session). The pr-review audit pr-state-freshness.md already mandates a live gh pr view <N> --json state,mergedAt before any merge-eligibility relay — but it loads ONLY inside /pr-review, so general status / A2A / wake responses skip it and assert stale state from a signal that went stale "within seconds of being read" (that audit's own framing; empirical anchors #12950 / #12956).
This ticket implements that audit's named sunset condition: "if A2A lifecycle messages ever carry a mechanical state echo, compress this audit to its trigger line."
Release classification: post-release substrate / agent-MX (NOT v13-release-blocking) → boardless.
The Problem
Under merge-on-approval, every PR signal (A2A handoff, wake digest, comment) is stale within seconds. The current mitigation is discipline — the agent must remember to run the live state read before every merge-state claim — which (a) only fires in /pr-review, and (b) is a manual gate the agent silently skips under context pressure. The recurring, operator-visible result: responses confidently assert a merge-state the live tracker already contradicts.
Discipline doesn't scale; the fix is to make the signal itself carry live state, so the agent reads truth from the payload instead of reconstructing it (or failing to). This is the friction → gold shape — a repeated agent mistake becomes a substrate mechanization, not a louder rule.
The Architectural Reality
- The wake payload already fetches + embeds GitHub context — the
[WAKE] digest carries latest GitHub mention: "<title>" (<pull URL>). Adding the referenced PR's live state / mergedAt to that existing fetch is a small enrichment, not a new integration. (Wake driver: ai/daemons/wake/daemon.mjs — confirm the exact enrichment locus at implementation; this is the wake-daemon owner's territory.)
- A2A lifecycle messages (
add_message) already carry relatedTickets: [...]. When a related entry is a PR, the message read-path (or the digest renderer in the memory-core message layer) can resolve + attach its terminal/open state so the consuming agent sees it inline.
pr-state-freshness.md (.agents/skills/pr-review/audits/) is the discipline this mechanizes; its sunset condition explicitly anticipates this work and tells the skill how to compress once it lands.
- Sibling
#11829 (multi-strategy wake-driver substrate — content / delivery / skill / metadata layers): this PR-state echo is a concrete content/metadata-layer instance, but goal-distinct (freshness-of-relayed-state, not idle-out prevention).
The Fix
- Enrich the wake digest: for each PR the wake references (the
latest GitHub mention PR, and optionally the agent's own open PRs), attach live state + mergedAt so a status response reads merge-state from the payload, not a stale recollection.
- Enrich A2A lifecycle messages: when
relatedTickets names a PR, resolve + render its live state inline at READ time (or stamp at send time with an explicit as-of timestamp the reader treats as a floor).
- Once the echo is live, compress
pr-state-freshness.md to its trigger line in the pr-review guide (the audit's own sunset instruction).
Contract Ledger Matrix
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback |
Docs |
Evidence |
[WAKE] digest PR-state echo |
pr-state-freshness.md sunset + the existing wake GitHub-mention fetch |
Each referenced PR carries live state / mergedAt inline in the digest |
Live fetch fails → omit the echo, keep the existing mention (never emit a stale-but-confident state) |
wake-driver JSDoc / @summary |
Unit test on the enrichment fn + a wake-digest render assertion |
| A2A message PR-state echo |
add_message relatedTickets + pr-state-freshness.md |
A PR in relatedTickets resolves to its live state at read time |
Fetch failure → no echo, message still delivers |
message-layer JSDoc |
Unit test: related-PR resolves to state; failure degrades safe |
pr-state-freshness.md audit |
the audit's own sunset condition |
Compress to a single trigger line once the echo is live |
Echo partial (wake only, not A2A) → keep the audit for the uncovered path |
the audit file |
The compression PR cites the live echo |
Decision Record impact
aligned-with the pr-state-freshness.md gate (implements its sunset). No ADR amendment. Related-to #11829 (wake-driver layers) and the fleet-freshness Discussion #13374 (distinct domain: agent/fleet freshness vs PR-merge-state freshness).
Acceptance Criteria
Out of Scope
- The broader idle-out wake-driver layering (
#11829) — this is one content/metadata layer, not the multi-strategy substrate.
- Fleet / agent-state freshness (
#13374 domain) — distinct.
- Editing core
AGENTS.md discipline — if a turn-loaded one-liner is also wanted (apply the live-state check to ALL responses, not just PR-review), that is an operator-directed substrate edit, tracked separately.
- Non-PR ticket / issue state echoes (PRs first; issues later if the pattern proves out).
Avoided Traps
- Louder rule instead of mechanization: rejected. The discipline already exists (
pr-state-freshness.md) and still gets skipped; the gold is making the signal carry truth, not adding a sterner reminder.
- Stamp-at-send only: insufficient alone — a send-time stamp is itself stale by read time; the echo must resolve (or re-note freshness) at READ time, or carry an explicit as-of timestamp the reader treats as a floor.
Related
pr-state-freshness.md (the discipline this mechanizes + sunsets)
#11829 (multi-strategy wake-driver substrate — sibling layer)
#13374 (fleet-freshness Discussion — distinct freshness domain)
- Empirical:
#12950 / #12956 (the freshness-failure anchors in pr-state-freshness.md)
Origin Session ID: 47b6dbc0-7673-4ad3-a9f5-bef3b606c56b
Retrieval Hint: "A2A wake PR-state echo freshness sunset pr-state-freshness mechanization"
Context
Operator-asked, 2026-06-16: "how can we get better to check what is merged already before writing responses?" — after status / handoff responses repeatedly asserted stale merge-state (naming a PR "at the merge gate" / "awaiting merge" that had already merged seconds earlier; happened ~5× in one session). The
pr-reviewauditpr-state-freshness.mdalready mandates a livegh pr view <N> --json state,mergedAtbefore any merge-eligibility relay — but it loads ONLY inside/pr-review, so general status / A2A / wake responses skip it and assert stale state from a signal that went stale "within seconds of being read" (that audit's own framing; empirical anchors#12950/#12956).This ticket implements that audit's named sunset condition: "if A2A lifecycle messages ever carry a mechanical state echo, compress this audit to its trigger line."
Release classification: post-release substrate / agent-MX (NOT v13-release-blocking) → boardless.
The Problem
Under merge-on-approval, every PR signal (A2A handoff, wake digest, comment) is stale within seconds. The current mitigation is discipline — the agent must remember to run the live state read before every merge-state claim — which (a) only fires in
/pr-review, and (b) is a manual gate the agent silently skips under context pressure. The recurring, operator-visible result: responses confidently assert a merge-state the live tracker already contradicts.Discipline doesn't scale; the fix is to make the signal itself carry live state, so the agent reads truth from the payload instead of reconstructing it (or failing to). This is the
friction → goldshape — a repeated agent mistake becomes a substrate mechanization, not a louder rule.The Architectural Reality
[WAKE]digest carrieslatest GitHub mention: "<title>" (<pull URL>). Adding the referenced PR's livestate/mergedAtto that existing fetch is a small enrichment, not a new integration. (Wake driver:ai/daemons/wake/daemon.mjs— confirm the exact enrichment locus at implementation; this is the wake-daemon owner's territory.)add_message) already carryrelatedTickets: [...]. When a related entry is a PR, the message read-path (or the digest renderer in the memory-core message layer) can resolve + attach its terminal/open state so the consuming agent sees it inline.pr-state-freshness.md(.agents/skills/pr-review/audits/) is the discipline this mechanizes; its sunset condition explicitly anticipates this work and tells the skill how to compress once it lands.#11829(multi-strategy wake-driver substrate — content / delivery / skill / metadata layers): this PR-state echo is a concrete content/metadata-layer instance, but goal-distinct (freshness-of-relayed-state, not idle-out prevention).The Fix
latest GitHub mentionPR, and optionally the agent's own open PRs), attach livestate+mergedAtso a status response reads merge-state from the payload, not a stale recollection.relatedTicketsnames a PR, resolve + render its live state inline at READ time (or stamp at send time with an explicit as-of timestamp the reader treats as a floor).pr-state-freshness.mdto its trigger line in thepr-reviewguide (the audit's own sunset instruction).Contract Ledger Matrix
[WAKE]digest PR-state echopr-state-freshness.mdsunset + the existing wake GitHub-mention fetchstate/mergedAtinline in the digestadd_messagerelatedTickets+pr-state-freshness.mdrelatedTicketsresolves to its live state at read timepr-state-freshness.mdauditDecision Record impact
aligned-withthepr-state-freshness.mdgate (implements its sunset). No ADR amendment. Related-to#11829(wake-driver layers) and the fleet-freshness Discussion#13374(distinct domain: agent/fleet freshness vs PR-merge-state freshness).Acceptance Criteria
[WAKE]digest carries livestate/mergedAtfor each PR it references (at minimum thelatest GitHub mentionPR).relatedTicketsname a PR surface that PR's live state to the reading agent.mergedAt, and a fetch failure degrades safe.pr-state-freshness.mdis compressed to its trigger line in thepr-reviewguide (the sunset).Out of Scope
#11829) — this is one content/metadata layer, not the multi-strategy substrate.#13374domain) — distinct.AGENTS.mddiscipline — if a turn-loaded one-liner is also wanted (apply the live-state check to ALL responses, not just PR-review), that is an operator-directed substrate edit, tracked separately.Avoided Traps
pr-state-freshness.md) and still gets skipped; the gold is making the signal carry truth, not adding a sterner reminder.Related
pr-state-freshness.md(the discipline this mechanizes + sunsets)#11829(multi-strategy wake-driver substrate — sibling layer)#13374(fleet-freshness Discussion — distinct freshness domain)#12950/#12956(the freshness-failure anchors inpr-state-freshness.md)Origin Session ID: 47b6dbc0-7673-4ad3-a9f5-bef3b606c56b
Retrieval Hint: "A2A wake PR-state echo freshness sunset pr-state-freshness mechanization"