Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .claude/board/STATUS_BOARD.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,9 @@ Plan: `.claude/plans/v3-mandatory-hotplug-reading-v1.md`.
| **D-HPR-3** | Consumers move (lance-graph, q2, MedCare); `classid_read_mode` deprecated | Queued (2026-10-11 census: MedCare has 0 callers; q2's are offline bake mints; deepnsm-v2 is blocked on a concept mint, not code) | no NEW reading selected through the table (rule 5 keeps stored keys readable) |
| **D-HPR-4** | `0x1000` / render prefixes documented as deprecated, kept (no eviction) | Shipped for `0x1000` (#1464; doc notes on `CLASSID_*_V3` + `classid_read_mode`); render prefixes, `NodeGuid::read_mode` and OGAR/q2 sites still carry no note | — |
| **D-HPR-5** | Stored legacy keys keep resolving; a `SlabDeclaration` may override for its own data; no forced removal | Holds today (status quo). Caveat: a `SlabDeclaration` overrides `value_schema` only, never the tail, so it cannot protect a V1/V2-tail slab (`hotplug.rs:231-257, 392`) | — |
| **D-HPR-6** | No V1 default for an unknown classid; `guid-v3-tail` not a gate | Queued — split: **6a** un-gate `guid-v3-tail` (default-on, and no fleet consumer disables it, so only `--no-default-features` builds change; there the 5 V3 fossils read `DEFAULT` today); **6b** unknown classid → error. Decided 2026-10-11: go, staged after 6a, D-HPR-3 and a stored-classid check | unknown classid → `NoReadingFor` |
| **D-HPR-7** | Storage readings leave the concept key: out of `concept_override`, into the slab's `SlabDeclaration` or the owning consumer's plug (O3, decided (a) 2026-10-11) | In PR (#1474; the five domain arms removed; the domain models differed from plug-and-play only in `value_schema`, which `SlabDeclaration` overrides; tests red before, green after) | a non-Odoo plug of `0x0202` reads `PLUG_AND_PLAY_V3`; Odoo's slab still reads `ERP_V3` |
| **D-HPR-8** | A plug that asks only for a reading succeeds (reading is not a capability; decided 2026-10-11) | In PR (#1474; `OgarAuthority::activate` skips the capability join when `covered` is empty; ids still must be minted; red before the fix with `NoCapabilitiesFor(0x0103)`; disable run turns the twin red) | `[0x0103]` with `covered: &[]` → `Ok`, `PLUG_AND_PLAY_V3`; with a covered capability → refused as today |
| **D-HPR-6** | No V1 default for an unknown classid; `guid-v3-tail` not a gate | **6a** In PR (un-gated: `guid-v2-tail`/`guid-v3-tail` are empty names, `new_v2` + the five V3 constants + `codebook` unconditional, the panic arm gone; scope ruled 2026-10-11: the 128-bit opt-in — identity and edge facet as 16×u8, lo = is_a, hi = part_of — is not touched, and the new guard `v3_mint_is_the_128_bit_facet` pins that a V3 mint is byte-identical to `FacetCascade` for key and edge; a byte-swap in `new_v2` turns 2 of its tests red). **6b** Queued — unknown classid → error. Decided 2026-10-11: go, staged after 6a, D-HPR-3 and a stored-classid check | unknown classid → `NoReadingFor` |
| **D-HPR-7** | Storage readings leave the concept key: out of `concept_override`, into the slab's `SlabDeclaration` or the owning consumer's plug (O3, decided (a) 2026-10-11) | Shipped (#1474; the five domain arms removed; the domain models differed from plug-and-play only in `value_schema`, which `SlabDeclaration` overrides; tests red before, green after) | a non-Odoo plug of `0x0202` reads `PLUG_AND_PLAY_V3`; Odoo's slab still reads `ERP_V3` |
| **D-HPR-8** | A plug that asks only for a reading succeeds (reading is not a capability; decided 2026-10-11) | Shipped (#1474; `OgarAuthority::activate` skips the capability join when `covered` is empty; ids still must be minted; red before the fix with `NoCapabilitiesFor(0x0103)`; disable run turns the twin red) | `[0x0103]` with `covered: &[]` → `Ok`, `PLUG_AND_PLAY_V3`; with a covered capability → refused as today |

## D-XGP — Cross-glove business parity: Odoo × SAP over one Quack algebra (2026-10-10)

Expand Down
1 change: 1 addition & 0 deletions .claude/plans/v3-mandatory-hotplug-reading-v1.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ What it means, in rules:
- [ ] **W6 — D-HPR-6: V1 cannot be reached by default.** `ReadMode::DEFAULT` stops being the fallback for an unknown classid (it becomes `NoReadingFor`, as on the plug path), and `guid-v3-tail` stops being a feature gate.
- Split (2026-10-11). **W6a**: un-gate `guid-v3-tail`. It is default-on and no fleet consumer disables it, so only `--no-default-features` builds change; there the 5 V3 fossils read `DEFAULT` today (coresearch probe P-X3). **W6b**: an unknown classid errors. This is a behaviour change, and both q2 and MedCare have already hit the V1 default once, so it needs operator approval.
- **Decided (operator, 2026-10-11: "Recommended accepted"): go, staged.** 1. W6a. 2. W3 moves the remaining mint paths onto plug readings. 3. A check that every stored artifact's classid resolves. 4. Only then W6b.
- **W6a scope (2026-10-11, decision):** removing the gate must not move a byte. The identity key and the edge facet are each already read as 16×u8 through the 128-bit opt-in (`facet::FacetCascade`, `classid(4) | 6×(8:8)`, lo = is_a, hi = part_of); `new_v2` writes those same bytes. W6a therefore only drops the cfg gates (the feature names stay empty for consumers) and adds a byte-identity guard; it does not re-carve the key.
- [x] **W7 — D-HPR-7: storage readings leave the concept key** (O3, decided (a)). **Shipped (#1474):** the five domain arms are removed from `concept_override`. The domain models differed from `PLUG_AND_PLAY_V3` only in `value_schema`, which a `SlabDeclaration` overrides, so no new mechanism was needed. Test `canon_domains_read_plug_and_play_and_their_slab_restores_the_domain_model`. The five domain storage readings move out of `concept_override` (keyed by concept) into the slab's `SlabDeclaration` or the owning consumer's plug. A consumer plugging a shared concept then reads `PLUG_AND_PLAY_V3`. Falsifier: a plug of `0x0202` by a non-Odoo consumer reads `PLUG_AND_PLAY_V3`, and Odoo's own slab still reads `ERP_V3`.
- [x] **W8 — D-HPR-8: a plug that asks only for a reading succeeds** (decided). **Shipped:** `lance-graph-ogar` `OgarAuthority::activate`, tests `a_plug_covering_nothing_activates_for_its_reading_only` (SAP glove on `0x0103`, a non-executor on `0x0901`) and `a_plug_that_covers_a_capability_is_still_refused_without_its_table`. The glove-parity pin now says both glove plugs activate for their reading; claiming a capability on `0x0103` is still `NoCapabilitiesFor`. Reading is not a capability. A plug with `covered` empty gets readings only, also for a concept that has a capability table. A plug that names a capability still needs the table. Falsifier: `[0x0103]` with `covered: &[]` → `Ok` and `read_mode_for(0x0103) == PLUG_AND_PLAY_V3`; with `covered: &["anything"]` → refused as today.

Expand Down
35 changes: 11 additions & 24 deletions crates/lance-graph-contract/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,37 +36,24 @@ name = "i4_batch"
harness = false

[features]
# default-on `guid-v3-tail` (operator ruling 2026-07-04, ISS-V1-TAIL-RESIDUE):
# every normal build mints real V3 keys via `mint_for`. `--no-default-features`
# still compiles (mint_for's V1 arm is un-gated; V2/V3 arms fall back to V1).
default = ["guid-v3-tail"]
# No default features. The V2/V3 tail is unconditional since D-HPR-6a
# (2026-10-11); `--no-default-features` and a default build compile the same.
default = []

# A-unlock-stepdomain — `step_trajectory_hash` forward stub for the E4
# cross-PR bridge between PR #278 audit log + PR #279 grammar trajectory.
# No-op alias today; concrete impl lands once the bridge PR ships.
trajectory-audit = []

# guid-v2-tail (D-GV2-1, plan: guid-v2-tail-per-family-codebook-v1.md) — the v2
# basin tail leaf(u16)·family(u16)·identity(u16) replacing v1 family(u24)·
# identity(u24), leaf as the 4th HHTL tier. Default OFF; additive v2 accessors
# (`leaf`/`*_v2`) coexist with v1 until cutover (D-GV2-5). Layout reclaim →
# I-LEGACY-API-FEATURE-GATED (field-isolation matrix + version gate).
# guid-v2-tail / guid-v3-tail — EMPTY since D-HPR-6a (2026-10-11). They gated
# the v2/v3 tail constructor (`new_v2`), the five V3 classid constants and the
# `codebook` module; all of that is now unconditional. The names stay so the
# consumers that request them (deepnsm-v2, MedCare-rs, q2) still resolve.
# `new_v2` writes the same 16 bytes `facet::FacetCascade` holds
# (`classid(4) | 6×(8:8)`, lo = is_a, hi = part_of); see
# `canonical_node::v3_mint_is_the_128_bit_facet`.
guid-v2-tail = []

# guid-v3-tail (P-A, plan: soa-value-tenant-migration-v2.md §2.1/§2.2) — gates the
# V3 cascade-key per-classid entries. The V3 identity AXIS itself (TailVariant::V3
# + ReadMode::tail_variant) is unconditional, latent (nothing reads tail_variant
# yet) → non-breaking. Since the classid half-order flip (P1, 2026-07-02,
# classid-canon-custom-flip-v1.md) the CANON `domain:appid` sits in the HIGH u16
# and the gen-marker 0x1000 in the LOW (custom) u16: OSINT-V3 = 0x0701_1000,
# FMA-V3 = 0x0A01_1000, CPIC-V3 = 0x0E01_1000; the pre-flip 0x1000_DDCC forms
# stay registered as read-only legacy aliases (mint-forward). Default OFF.
#
# Implies `guid-v2-tail`: V3 is a *reading* of the SAME leaf·family·identity 3×u16
# tail bytes v2 mints (the (part_of:is_a) cascade reinterprets them, never re-carves),
# so the V3 mint path (`NodeGuid::mint_for`'s V3 arm) dispatches to `new_v2`. The
# tail constructor must exist whenever a V3 classid can be minted.
guid-v3-tail = ["guid-v2-tail"]
guid-v3-tail = []

# tenant-counters — per-ValueTenant update counters for debug instrumentation of
# the SoA write cascade (the capstone NaN-census / seam-wiring measurement). OFF
Expand Down
13 changes: 2 additions & 11 deletions crates/lance-graph-contract/src/aiwar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,8 @@ pub fn aiwar_node_rows(graph: &LiteralGraph) -> Vec<NodeRow> {
// ONE OSINT class, minted V3 (ISS-V1-TAIL-RESIDUE): route through `mint_for`
// so the classid's registered `tail_variant` drives the tail. `OSINT_GOTHAM`
// filters on the SAME selector, and `family_of`/`identity_of` decode the V3
// basin tail-aware — so the round-trip is consistent. `--no-default-features`
// falls back to the V1 `CLASSID_OSINT` (the V3 class is gated out there).
#[cfg(feature = "guid-v3-tail")]
// basin tail-aware — so the round-trip is consistent.
let osint_classid = NodeGuid::CLASSID_OSINT_V3;
#[cfg(not(feature = "guid-v3-tail"))]
let osint_classid = NodeGuid::CLASSID_OSINT;
aiwar_node_rows_with(graph, osint_classid, classid_read_mode(osint_classid))
}

Expand Down Expand Up @@ -213,12 +209,8 @@ mod tests {

#[test]
fn rows_are_osint_class_and_head_only() {
// ONE OSINT class: V3 in a normal build, V1 under `--no-default-features`
// (mirrors `aiwar_node_rows` + `OSINT_GOTHAM`).
#[cfg(feature = "guid-v3-tail")]
// ONE OSINT class, V3 (mirrors `aiwar_node_rows` + `OSINT_GOTHAM`).
let expected_classid = NodeGuid::CLASSID_OSINT_V3;
#[cfg(not(feature = "guid-v3-tail"))]
let expected_classid = NodeGuid::CLASSID_OSINT;
let g = ingest_aiwar_json(SAMPLE).unwrap();
for row in aiwar_node_rows(&g) {
assert_eq!(row.key.classid(), expected_classid);
Expand All @@ -228,7 +220,6 @@ mod tests {

/// D-HPR-1: `aiwar_node_rows_with` reproduces `aiwar_node_rows` when handed
/// the same reading, and follows a different reading when handed one.
#[cfg(feature = "guid-v3-tail")]
#[test]
fn with_form_follows_the_handed_reading() {
use crate::canonical_node::{EdgeCodecFlavor, TailVariant, ValueSchema};
Expand Down
Loading
Loading