Object-ID Collision Policy
Checker Policy — Object-ID Collision & Addendum-vs-Fold (L3)
Generalizes: v0.2 object-governance model + the NVSZ governance fold-patch discipline. Level: 3.
Object-ID rule
Every object a macro creates is registered in the same macro. Each object carries:
{id, title, type, path, authority, may_gate:false, decision_effect:NONE, owner_class:T1|T2, rev}. Dev macros insert no production-registry
(birth_registry) row; KB-doc births are BORN-UNCERTIFIED-if-synced.
Lanes are disjoint
T1 and T2 own disjoint reserved ID ranges. A new block must be strictly above the highest reserved ID anywhere — not merely above the registry-JSON body max. The registry JSON body has its own max (e.g. 224); IDs above it are tracked via addenda + pointers. Collisions happen when a lane reserves into another lane's range, so the scan must consider reserved ranges, not just committed rows.
Known reserved ranges at build time (illustrative — re-scan against live state):
| Range | Lane |
|---|---|
| …–224 | registry JSON body (committed) |
| 182..200, 208..216, 225..253, 273..288, 305..325 | T1 |
| 201..207, 217..224, 254..262, 263..272, 289..304 | T2 |
Collision-scan procedure
- Determine the highest reserved ID across all lanes (not just the JSON body max).
- Choose the new block strictly above it.
- Assert no overlap with any other lane's reserved range.
- Record the registry-JSON rev and
00-indexrev observed at scan time. - If collision safety cannot be proven, create files without registry/index mutation and report a blocker — never guess.
Addendum vs canonical fold (the "no 55KB rewrite" rule)
- Addendum (always allowed): register new IDs via a standalone
governance-addendum doc at a fresh path (collision-free) plus a single
00-indexpointer line under the header boundary (body untouched). This births the objects at KB-governance level without rewriting the canonical registry JSON. - Canonical fold (deferred, gated): appending entries into the registry JSON
objectsarray, bumping registry-MD rev and00-indexrev. This is a separate step and is gated.
When APPLY_NOW must be NO
The canonical registry JSON and 00-index.md are shared surfaces. The fold
MUST NOT be applied when:
- another lane (e.g. T1) is concurrently mutating the shared registry/index, OR
- there is no explicit owner/operator/GPT authorization — even if the other lane is believed inactive.
A fold-apply descriptor with t1_active=true must be rejected (the NVSZ
root-validator returns exit 13 for fold-apply-while-T1-active). Until both
conditions clear, carry the fold as an action-ready blocker (e.g.
*-GOV-FOLD-1) — no fake-green.
No-orphan compliance
Every born object is registered at KB-governance level (addendum) AND the canonical insertion is carried as an action-ready blocker. A packet "governs as its contents": README / commands.sh / exit_codes.json / HASH_MANIFEST / packet_tree each have a manifest entry; by-reference modules and SUT are referenced (byte-exact, sha-pinned) not duplicated; raw logs are intentionally ungoverned (no-vector rule, carried as hash+pointer).
Fail-closed contract
- Any new ID inside an existing/reserved range → FAIL (collision).
- Any born object with no registry entry (not even addendum) → FAIL (orphan).
- Any dangling index pointer → FAIL.
- Canonical fold applied while another lane active or without authorization → FAIL.