feat(identifiers): verify batch projections

Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a023c0-a0a3-7c03-b395-5a0d2757214d
This commit is contained in:
tegwick 2026-08-22 23:50:34 +02:00
parent e6cc18bf18
commit 055c6971ab
11 changed files with 2964 additions and 9 deletions

View file

@ -0,0 +1,55 @@
# RMGR-WP-0005 batch 0005 projection preflight
**Observed at:** `2026-08-22T21:46:30Z`
**Scope:** `adaptive-pricing` only
## Outcome
Batch 0005 is source-ready but **not ready for approval**. No database or
repository identifier changed.
The refreshed fleet plan is sealed as
`28cd01bdbc66c53ad5ef11b9821a74ebadd7c8cfdae4c227f37ce7f9d67cbf18`.
The adaptive-pricing unit is clean, synchronized with `origin/main`, and pinned
at `c65a2f1ff9a0b30700ee14818e36e931eb71cae3`. It contains five replacements:
`ADAPTIVE-WP-0010` and its four unfinished tasks.
The projection-aware batch manifest is sealed as
`20decab5521ea5477826d1b2a9c9670912a96c4b8245faf5d270c8d1efc988c5`.
It records `ready_for_approval: false` and `apply_authorized: false`.
## Projection evidence
| Projection | Five current UUIDs | Five derived UUIDs | Result |
| --- | --- | --- | --- |
| Workstation `:8000` | HTTP 200 | HTTP 404 | ready |
| Production tunnel `:18000` | HTTP 404 | HTTP 404 | blocked |
A governed `registrar-reconcile --repair-workplan ADAPTIVE-WP-0010` attempt
used clean source revision `c65a2f1...` and correlation id
`b708a73e-fc09-48ee-aa2d-ff8b3c642466`. State Hub retained the conservative
C-03 rule for the pre-derivation random UUID and did not create it. This is the
correct ordinary-consistency behavior, but it means the existing transactional
migration executor cannot run: that executor requires every old source row to
exist in the target repository projection.
The attempt also exposed a Repo Manager result bug: a failed exact repair could
be labeled `applied` because an empty ordinary-registration set passed
verification vacuously. The wrapper now requires repair/bootstrap mode's own
exact projection proof and does not run ordinary requested-record verification
for an empty request.
## Owner-ready resolution
`helixforge.identifiers.state-hub-sealed-projection-repair.v1` offers State Hub
a bounded repair task. It preserves the default C-03 refusal and permits old-row
restoration only from one clean source revision plus one exact sealed migration
unit, with primary confirmation, atomicity, idempotency, and a receipt. Once
adopted, repeat this batch plan against both projections; only a new manifest
with all current lookups 200 and all derived lookups 404 may be proposed for
approval.
The fleet scan found one other projection-complete candidate, `state-hub`, but
its checkout contains unrelated uncommitted owner evidence. The Git preflight
therefore excludes it until the owner publishes or dispositions that work.

View file

@ -0,0 +1,182 @@
{
"schema": "repo-manager.identifier-migration-batch.v1",
"ok": false,
"ready_for_approval": false,
"apply_authorized": false,
"approval_required": true,
"projection_api_bases": [
"http://127.0.0.1:8000",
"http://127.0.0.1:18000"
],
"namespace": "helixforge",
"source_plan_sha256": "28cd01bdbc66c53ad5ef11b9821a74ebadd7c8cfdae4c227f37ce7f9d67cbf18",
"batch_policy": "repository-atomic, sequential, stop on first failure",
"rollback_order": "reverse files if written, then reverse central projection",
"generated_at": "2026-08-22T21:45:54.917855Z",
"totals": {
"repositories": 1,
"records": 5,
"replace": 5,
"assign": 0,
"unchanged": 0
},
"repositories": [
{
"repo": "adaptive-pricing",
"path": "/home/worsch/adaptive-pricing",
"planned_head_sha": "c65a2f1ff9a0b30700ee14818e36e931eb71cae3",
"source_fingerprint": "977e94daeb0a6955a3d4ba76393d0b273d285537d0789eb59350d5c283901887",
"source_verified": true,
"git_preflight": {
"ok": true,
"head_sha": "c65a2f1ff9a0b30700ee14818e36e931eb71cae3",
"expected_head_sha": "c65a2f1ff9a0b30700ee14818e36e931eb71cae3",
"upstream": "origin/main",
"behind": 0,
"ahead": 0,
"origin": "forgejo-remote:coulomb/adaptive-pricing.git",
"errors": []
},
"projection_preflight": {
"required": true,
"ok": false,
"projections": [
{
"api_base": "http://127.0.0.1:8000",
"ok": true,
"replacement_checks": [
{
"record_id": "ADAPTIVE-WP-0010",
"kind": "workplan",
"current_status": 200,
"derived_status": 404,
"ok": true
},
{
"record_id": "ADAPTIVE-WP-0010-T01",
"kind": "task",
"current_status": 200,
"derived_status": 404,
"ok": true
},
{
"record_id": "ADAPTIVE-WP-0010-T02",
"kind": "task",
"current_status": 200,
"derived_status": 404,
"ok": true
},
{
"record_id": "ADAPTIVE-WP-0010-T03",
"kind": "task",
"current_status": 200,
"derived_status": 404,
"ok": true
},
{
"record_id": "ADAPTIVE-WP-0010-T04",
"kind": "task",
"current_status": 200,
"derived_status": 404,
"ok": true
}
]
},
{
"api_base": "http://127.0.0.1:18000",
"ok": false,
"replacement_checks": [
{
"record_id": "ADAPTIVE-WP-0010",
"kind": "workplan",
"current_status": 404,
"derived_status": 404,
"ok": false
},
{
"record_id": "ADAPTIVE-WP-0010-T01",
"kind": "task",
"current_status": 404,
"derived_status": 404,
"ok": false
},
{
"record_id": "ADAPTIVE-WP-0010-T02",
"kind": "task",
"current_status": 404,
"derived_status": 404,
"ok": false
},
{
"record_id": "ADAPTIVE-WP-0010-T03",
"kind": "task",
"current_status": 404,
"derived_status": 404,
"ok": false
},
{
"record_id": "ADAPTIVE-WP-0010-T04",
"kind": "task",
"current_status": 404,
"derived_status": 404,
"ok": false
}
]
}
],
"errors": [
{
"scope": "http://127.0.0.1:18000:ADAPTIVE-WP-0010",
"reason": "projection requires current UUID=200 and derived UUID=404"
},
{
"scope": "http://127.0.0.1:18000:ADAPTIVE-WP-0010-T01",
"reason": "projection requires current UUID=200 and derived UUID=404"
},
{
"scope": "http://127.0.0.1:18000:ADAPTIVE-WP-0010-T02",
"reason": "projection requires current UUID=200 and derived UUID=404"
},
{
"scope": "http://127.0.0.1:18000:ADAPTIVE-WP-0010-T03",
"reason": "projection requires current UUID=200 and derived UUID=404"
},
{
"scope": "http://127.0.0.1:18000:ADAPTIVE-WP-0010-T04",
"reason": "projection requires current UUID=200 and derived UUID=404"
}
]
},
"mapping_counts": {
"records": 5,
"replace": 5,
"assign": 0,
"unchanged": 0
},
"ready": false
}
],
"errors": [
{
"scope": "http://127.0.0.1:18000:ADAPTIVE-WP-0010",
"reason": "projection requires current UUID=200 and derived UUID=404"
},
{
"scope": "http://127.0.0.1:18000:ADAPTIVE-WP-0010-T01",
"reason": "projection requires current UUID=200 and derived UUID=404"
},
{
"scope": "http://127.0.0.1:18000:ADAPTIVE-WP-0010-T02",
"reason": "projection requires current UUID=200 and derived UUID=404"
},
{
"scope": "http://127.0.0.1:18000:ADAPTIVE-WP-0010-T03",
"reason": "projection requires current UUID=200 and derived UUID=404"
},
{
"scope": "http://127.0.0.1:18000:ADAPTIVE-WP-0010-T04",
"reason": "projection requires current UUID=200 and derived UUID=404"
}
],
"batch_sha256": "20decab5521ea5477826d1b2a9c9670912a96c4b8245faf5d270c8d1efc988c5"
}

File diff suppressed because it is too large Load diff

View file

@ -47,6 +47,8 @@ rmgr identifier migration-verify --plan uuid-migration.json --repo repo-manager
rmgr identifier migration-batch-plan \
--plan uuid-migration.json \
--repo whynot-design \
--projection-api-base http://127.0.0.1:8000 \
--projection-api-base http://127.0.0.1:18000 \
--output batch.json
rmgr identifier migration-batch-verify \
--plan uuid-migration.json \
@ -73,7 +75,12 @@ package. Each selected repository must still match the planned Git HEAD, have a
clean worktree, exactly match its configured upstream, and use a non-retired
origin. The batch records these facts and its own SHA-256 seal, but always emits
`apply_authorized: false`. An explicit decision must cite that batch hash before
any database or file mutation.
any database or file mutation. Repeat `--projection-api-base` for every hub in
the cutover: each replacement must resolve its current UUID with HTTP 200 and
its derived target with HTTP 404 on every named projection, or the manifest is
not ready for approval. Saved projection endpoints are rechecked by
`migration-batch-verify`; omitting the option retains the offline source/Git-only
planning mode.
Activation and applying a bulk migration remain separate governed steps.
Publishing or planning this function does not retroactively rewrite existing