fix(projection): the derived UUID is identity, check it before the slug
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:
parent
b53daf648a
commit
d4ca94198e
2 changed files with 63 additions and 11 deletions
|
|
@ -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()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue