Follow-up from #329 (#211), reported by review on that PR.
Once dispatch claims are keyed on the work unit, a run completed through one
surface leaves a terminal row that the SAME unit arriving through the other
surface must be able to reopen. #329 made the reopen scan in
#recordCanonicalIssueState match on work-unit identity, which fixes the
direction where the reopen arrives as a Linear issue.
The originally reported direction is still broken, for two reasons that both
predate the key change:
#recordCanonicalIssueState is only called when issueSource === 'linear'
(src/orchestrator/factory.ts, in the ready-issue read loop). GitHub
ingestion never records canonical state, so the reopen cleanup is never
reached at all on a GitHub-sourced Factory.
reopenedFromTerminal is derived from issueStateKey(issue), which is
surface-scoped. A GitHub-native ref therefore cannot see a Linear mirror's
canonical-state entry even when both describe one work unit.
Consequence: a work unit completed through a Linear mirror, then reopened
GitHub-native, hits the terminal row and is refused with
dispatch lifecycle already terminal. #329 reproduced exactly that skip reason
while developing the fix.
Fixing it means giving GitHub ingestion canonical-state recording and making the
reopen gate work-unit scoped rather than surface scoped. That is a real change to
an ingestion path #329 does not otherwise touch, which is why it was filed rather
than folded in.
Worth deciding alongside: whether canonical state should be keyed per surface at
all once claims are keyed per work unit, or whether the two should share the
identity. Splitting them is what makes this reachable.
Follow-up from #329 (#211), reported by review on that PR.
Once dispatch claims are keyed on the work unit, a run completed through one
surface leaves a terminal row that the SAME unit arriving through the other
surface must be able to reopen. #329 made the reopen scan in
#recordCanonicalIssueStatematch on work-unit identity, which fixes thedirection where the reopen arrives as a Linear issue.
The originally reported direction is still broken, for two reasons that both
predate the key change:
#recordCanonicalIssueStateis only called whenissueSource === 'linear'(
src/orchestrator/factory.ts, in the ready-issue read loop). GitHubingestion never records canonical state, so the reopen cleanup is never
reached at all on a GitHub-sourced Factory.
reopenedFromTerminalis derived fromissueStateKey(issue), which issurface-scoped. A GitHub-native ref therefore cannot see a Linear mirror's
canonical-state entry even when both describe one work unit.
Consequence: a work unit completed through a Linear mirror, then reopened
GitHub-native, hits the terminal row and is refused with
dispatch lifecycle already terminal. #329 reproduced exactly that skip reasonwhile developing the fix.
Fixing it means giving GitHub ingestion canonical-state recording and making the
reopen gate work-unit scoped rather than surface scoped. That is a real change to
an ingestion path #329 does not otherwise touch, which is why it was filed rather
than folded in.
Worth deciding alongside: whether canonical state should be keyed per surface at
all once claims are keyed per work unit, or whether the two should share the
identity. Splitting them is what makes this reachable.