fix(projection): the derived UUID is identity, check it before the slug
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Build and Publish Multi-Context Image / build-and-push (push) Successful in 26s

Two rows were being proposed for retirement that were correct all along.
`testdrive-jsui-publication` and `three-phoenix-ha-cluster` carry legacy title
slugs, but their UUIDs are exactly uuid5 of MARKITECT-WP-0002 and
RCLUSTER-WP-0007 — they are those records. `_identity_is_derived` short-circuits
on the UUID *version* before the slug rule ever runs, so both read as re-keys.
Acknowledging retirements for either repository would have retired a live
record on the strength of its slug.

The derived UUID is the strongest key available and was not used in matching at
all. It is now checked first: if a row's id equals uuid5 of a wanted
identifier, that row is that record, whatever its slug says. The slug and path
heuristics now only decide rows the UUID cannot identify.

This also corrects a claim I made from the retirement list alone: those files
derive normally. Nothing was wrong with them.

738 pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 2583210@bnt-lap001
Assistant-Session: f2bff2d5-e9b2-4338-92ca-10282a927006
This commit is contained in:
tegwick 2026-08-28 03:17:21 +02:00
parent b53daf648a
commit d4ca94198e
2 changed files with 63 additions and 11 deletions

View file

@ -680,12 +680,34 @@ async def reset_repository_projection(
).scalars()
)
# Release identifiers held by rows retired before retirement freed them.
# This runs here, ahead of every refusal path, because it completes a
# decision already taken rather than making a new one — gating it behind an
# unrelated pending decision left four identifiers locked in repositories
# that refuse for reasons having nothing to do with them.
for r in rows:
if r.projection_retired_at is not None and RETIRED_SLUG_MARK not in (r.slug or ""):
before = r.slug
r.slug = _tombstone_slug(r.slug or str(r.id), r.projection_retired_at)
outcome.released.append(before)
want = {w.record_id.strip().lower(): w for w in derived.workplans}
want_paths = {_path_key(w.relative_path): k for k, w in want.items()}
# The derived UUID is the strongest key there is: if a row's id equals
# uuid5 of a wanted record's identifier, that row *is* that record, whatever
# its slug says. Checking it first is what stops a correct record with a
# legacy title slug — `testdrive-jsui-publication` for MARKITECT-WP-0002 —
# from being read as a re-key and proposed for retirement.
want_by_uuid = {w.uuid: k for k, w in want.items()}
matched: dict[str, Any] = {}
for row in rows:
key = (row.slug or "").strip().lower()
by_uuid = want_by_uuid.get(str(row.id))
if by_uuid is not None:
matched[by_uuid] = row
continue
if key not in want:
if _identity_is_derived(row) or _slug_is_identifier(row.slug or ""):
# ADR-007: a record identified by an identifier *is* that
@ -889,16 +911,6 @@ async def reset_repository_projection(
if changed:
outcome.updated.append(w.record_id)
# Rows retired before retirement released identifiers still hold theirs, and
# `stale` excludes anything already retired — so nothing would ever revisit
# them. Completing a decision already taken is not a new retirement, so this
# runs without acknowledgement and is reported on its own.
for r in rows:
if r.projection_retired_at is not None and RETIRED_SLUG_MARK not in (r.slug or ""):
before = r.slug
r.slug = _tombstone_slug(r.slug or str(r.id), r.projection_retired_at)
outcome.released.append(before)
for r in stale:
outcome.retired.append(r.slug or str(r.id))
r.projection_retired_at = now
@ -980,7 +992,11 @@ async def reset_fleet_projection(
acknowledge_retirements=acknowledge_retirements,
forge_base=forge_base,
)
if result.status == "applied":
# A released identifier is a repair that stands on its own, so
# it must survive a refusal in the same repository — otherwise
# moving the release ahead of the refusal returns achieves
# nothing and the rollback quietly undoes it.
if result.status == "applied" or result.released:
await session.commit()
else:
await session.rollback()

View file

@ -809,3 +809,39 @@ class TestRetirementReleasesTheIdentifier:
"repo-wp-0001@retired-20260828", datetime(2026, 8, 28, tzinfo=timezone.utc)
)
assert fp.RETIRED_SLUG_MARK in row.slug
def test_a_release_is_committed_even_when_the_repo_refuses(self):
"""The fleet driver commits only on `applied` and rolls back otherwise.
Moving the release ahead of the refusal returns achieves nothing if the
rollback then discards it which is the state railiance-cluster and
inter-hub were in.
"""
import inspect
src = inspect.getsource(fp.reset_fleet_projection)
assert 'result.status == "applied" or result.released' in src
class TestUuidMatchWins:
"""A row whose UUID is uuid5 of the identifier IS that record.
`testdrive-jsui-publication` and `three-phoenix-ha-cluster` carry legacy
title slugs while their UUIDs are derived from MARKITECT-WP-0002 and
RCLUSTER-WP-0007. The slug-identifier rule alone reads them as re-keys and
proposes retiring records that were correct all along.
"""
def test_a_title_slugged_row_is_still_its_derived_record(self):
import uuid as _u
rid = "MARKITECT-WP-0002"
row_id = _u.UUID(fp.derived_record_uuid(rid))
# The slug says one thing, the UUID says another; the UUID is identity.
assert not fp._slug_is_identifier("testdrive-jsui-publication")
assert str(row_id) == fp.derived_record_uuid(rid)
def test_uuid_match_is_checked_before_the_rekey_rules(self):
import inspect
src = inspect.getsource(fp.reset_repository_projection)
uuid_at = src.index("want_by_uuid.get(str(row.id))")
rekey_at = src.index("_identity_is_derived(row) or _slug_is_identifier")
assert uuid_at < rekey_at, "UUID match must precede the re-key heuristics"