repo-manager/docs/work-record-uuid-derivation_v1.md
tegwick 8f3b8ac2f6 prepare fleet identifier completion batch
Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a053ff-1d6f-7fe2-ac1c-a6eb40a42a0c
2026-08-31 17:02:19 +02:00

5.4 KiB

id type title version status created updated workplan_task
RMGR-CONTRACT-UUID-0001 contract Deterministic work-record UUID derivation 1 active 2026-08-21 2026-08-21 RMGR-WP-0005-T03

Work-record UUID derivation v1

For a live workplan or task, implementations derive the existing state_hub_workstream_id or state_hub_task_id field with UUIDv5:

namespace UUID: a4058507-5c4a-5a00-ab06-fffa4fb46009
name bytes:      UTF-8(<fleet-namespace> + "\n" + <canonical-identifier>)

The fixed UUID is itself UUIDv5(URL, https://helixforge.org/repo-manager/work-record/v1), but consumers use the fixed value above rather than recomputing it. Fleet namespace names are lowercase DNS-label style. Canonical identifiers are PREFIX-WP-NNNN, PREFIX-WP-NNNN-TNN, or the repository-qualified daily forms PREFIX-WP-ADHOC-YYYY-MM-DD[-TNN]. Historic unqualified ADHOC-* records are grandfathered and keep their minted identifiers; new records never use that collision-prone form.

The repository is not a namespace. The fleet owner declared the current shared namespace as helixforge on 2026-08-21; the versioned declaration is config/fleet-namespace.yaml. This raises the namespace posture from implied N1 to declared N2. A future fork uses its own namespace name and therefore derives different UUIDs for the same unqualified identifier, as required by ADR-011.

Only proposed, ready, active, blocked, or backlog workplans and their unfinished tasks enter the live derivation set. Finished and archived history retains its minted identifiers. Before creating, re-deriving, or unarchiving a record, run the live-collision preflight. Any duplicate is a hard refusal; it is never silently disambiguated with a repository slug.

rmgr identifier derive --record-id RMGR-WP-0005
rmgr identifier preflight --root /path/to/fleet
rmgr identifier migration-plan --root /path/to/fleet --output uuid-migration.json
rmgr identifier migration-verify --plan uuid-migration.json
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 \
  --batch batch.json

migration-plan is non-mutating. Its versioned JSON output preserves every current-to-derived UUID mapping and marks each repository as one atomic apply unit. A collision or malformed live identifier makes that whole repository ineligible while leaving unaffected repositories visible in the plan. Existing output files are not replaced unless --force is explicit.

Plans carry a canonical UTC creation time, SHA-256 integrity seal, and per-repo Git HEAD/source fingerprints. migration-verify rejects a modified plan, a namespace mismatch, an ineligible repository, or authoritative-source drift. HEAD movement is reported but is not a hard failure when the source fingerprint is unchanged; otherwise committing the plan itself would invalidate its own repository. --repo verifies one atomic apply unit, so unrelated fleet churn does not invalidate a stable repository. A new plan is required for each unit whose authoritative source drifts.

migration-batch-plan converts selected atomic units into a bounded approval 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. Repeat --projection-api-base for every hub in the cutover. Each replacement is classified as legacy_source, derived_target, duplicate_target, both_present, or neither_present. The first three may coexist inside one repository-atomic migration: State Hub migrates legacy rows, verifies already-derived rows against their canonical record identity, and may coalesce a duplicate_target task only when both business payloads are equal and the legacy row has zero inbound references. Other both-present and all neither-present states are refused. Durable aliases are recorded for every converged replacement. Saved projection endpoints are rechecked by migration-batch-verify; omitting the option retains the offline source/Git-only planning mode. A projection-aware batch containing UUID assignments fails closed until an assignment-specific projection identity check is implemented.

After approval, apply the sealed database phase and then the atomic file phase:

rmgr identifier migration-projection --plan PLAN.json --repo REPO \
  --confirm-plan-sha256 SHA256 --api-base http://127.0.0.1:8000
rmgr identifier migration-files --plan PLAN.json --repo REPO \
  --confirm-plan-sha256 SHA256 --execute

If the file phase fails, run migration-projection with --direction reverse before changing the sealed plan or retrying. Routine rmgr sync never performs this migration implicitly.

Activation and applying a bulk migration remain separate governed steps. Publishing or planning this function does not retroactively rewrite existing identifiers. --namespace remains an explicit override for a foreign/forked fleet; omitting it uses the checked-in helixforge declaration.