fix(canary-rollout): an unresolvable source commit in a data gap is INDETERMINATE, not PRE_EXISTING

Merged
DO
21d ago
+137-11

Summary

Implements the decision on #1249 (item 14 of the #1244 tracker): a pending pair whose source commit is unresolvable, seen while run history is unreadable, carries triage - (indeterminate) and no longer PRE_EXISTING.

_reusable_differs answers 0 for an empty candidate, so classify_failure 0 unknown 0 returned PRE_EXISTING. That claims the reusable is byte-identical to the prior channel when nothing was compared.

What changes

  • classify_failure accepts differs=unknown and returns -. An environmental category still decides first.
  • _frontier_state_resilient passes unknown for an empty candidate and does not call _reusable_differs. The pair is still emitted BLOCKED with datagap=1.
  • New pure triage_label: - reads INDETERMINATE in the blocker issue title.
  • The data-gap banner says there is no triage verdict when the candidate is unresolvable. With a resolvable candidate it keeps the "derived from the reusable diff alone" wording.

- is not a new triage value. A non-BLOCKED pair, the tag-lookup hold and the unresolved-cut-date hold already carry it, and _blocker_body already renders it.

Checked against the issue's claim

The issue says sync-issues and promote --allow-pre-existing rank - and PRE_EXISTING the same.

ConsumerResult
sync-issuesSame. Only REGRESSION and SUSPECT add needs-human.
promote --allow-pre-existingDifferent in general: PRE_EXISTING is the one triage it can advance. It never sees this case, because promote reads _frontier_state directly and refuses a - candidate before it reads the triage.

So this changes issue text and title only. No promotion decision changes.

One pinned test flipped on purpose

_frontier_state_resilient keeps an unresolvable (empty) src commit tracked BLOCKED with triage PRE_EXISTING (added by #1243 to keep that refactor behavior-neutral) now asserts triage - on the full state line. The #1249 acceptance criteria ask for this flip.

Test plan

  • 7 new or changed tests in tests/canary_rollout.bats; 492 of 494 pass locally. The two failures (grep -P in the #1054 and #1023 tests) are a macOS BSD grep limitation and fail the same way on unmodified main.
  • shellcheck --severity=warning -x scripts/canary-rollout.sh scripts/lib/canary-rollout.sh clean.
  • CI on Linux.

Refs #1249
Refs #1244

🤖 Generated with Claude Code

Problem

See the linked issue.

Risk

Low — changes automation shell logic under scripts/, covered by shellcheck (--severity=warning) and the bats suite.

Test plan

Tests added/updated: tests/canary_rollout.bats. Verification: bash scripts/dev-lead-lint.sh (shellcheck --severity=warning) ran pre-commit; the bats suite runs in CI.

Rollback

Revert this PR. No non-revertible side effects (no tags, migrations, or external state).

Monitoring

This PR's Lint (shellcheck) and bats checks show pass/fail; watch subsequent dev-lead / pr-review runs for behavioral regressions.