Skip to content

Commit dee1fc5

Browse files
authored
Merge pull request #176 from AdaWorldAPI/claude/happy-hamilton-0azlw4
Board discipline: hot-plug consumer-migration doc + E-HOTPLUG-GENERIC-1 (missed the #175 train)
2 parents 27ad054 + 46e127e commit dee1fc5

2 files changed

Lines changed: 159 additions & 0 deletions

File tree

.claude/board/EPIPHANIES.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,31 @@
77
88
---
99

10+
## 2026-07-07 — E-HOTPLUG-GENERIC-1 — hot-plug is THE consumer migration pattern; OGAR is the authoritative store; migration doc is board discipline
11+
12+
**Status:** RULING (operator 2026-07-07; shipped #174 `ocr_actions` + #175 `resolve_hotplug`; consumers: tesseract-rs #13/#14, socket+bridge lance-graph #658).
13+
14+
The consumer tells OGAR **which classids are hot-plugged** and receives BOTH
15+
the vocab rows and the action surface for exactly those ids —
16+
`capability_registry::resolve_hotplug(consumer, classids, covered)`, domain
17+
tables registered append-only in `domain_tables()` (OCR first; thinking-styles
18+
is one entry away). Five named drift arms (`UnknownClassid` /
19+
`NoCapabilitiesFor` — "the table was forgotten" — / `UnexpectedConsumer` /
20+
`Uncovered` / `Undeclared`), each a test-time bang in the consumer's own
21+
binary. No serialization, no git pins (sibling path deps), no per-consumer
22+
plug crates; the classid low u16 is the APP render prefix, never a shape
23+
ordinal. lance-graph stays agnostic: wire mirror + roundtrip green light only,
24+
no ontology payload.
25+
26+
**Board discipline:** `.claude/knowledge/hotplug-consumer-migration.md`
27+
(mirrored in lance-graph `.claude/knowledge/`) is MANDATORY READING before
28+
migrating any consumer, adding a domain table, or wiring capabilities
29+
cross-repo. It also carries the evaluated ruff synergies: ActionDef
30+
plug-and-play via `ogar-from-ruff::lift_actions` (+ the missing C++ arm as
31+
the natural fourth `ruff_cpp_spo` harvest arm), `walk_enums` param fidelity,
32+
and ontology plug-and-play over the `vocab/exports → OGIT → vocab/imports`
33+
tier (ontologies through that pipeline — harvests stay in consumer repos).
34+
1035
## 2026-07-06 — E-NEVER-PIN-BUMP — float-on-main is doctrine; non_exhaustive rejected
1136

1237
**Status:** RULING (`[G]`, operator 2026-07-06).
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
# Hot-Plug Consumer Migration — the generic plug-and-play pattern
2+
3+
> READ BY: any session migrating a consumer (woa-rs, medcare-rs,
4+
> smb-office-rs, odoo-rs, tesseract-rs, osm-website-rs, …) onto the
5+
> OGAR-authoritative capability surface; any session adding a new
6+
> authoritative domain table (thinking-styles best practices, …);
7+
> integration-lead / baton-handoff-auditor before any cross-repo
8+
> capability wiring.
9+
>
10+
> Shipped 2026-07-07 (operator-ruled same day). Reference PRs:
11+
> OGAR #174 (ocr_actions) + #175 (resolve_hotplug), lance-graph #658
12+
> (hotplug socket + OgarAuthority + CI fuse gate), tesseract-rs #13/#14
13+
> (executor + HOT_PLUG migration — the template consumer).
14+
15+
## The model — three roles, three homes, one binary
16+
17+
Everything links into ONE binary (lance-graph + OGAR + consumer +
18+
ndarray). Nothing serializes; every check is a compile-time const or a
19+
test in the consumer's own suite. "Wenn's knallt, dann einmal — nicht
20+
200 Pins monitoren."
21+
22+
| Role | Home | Surface |
23+
|---|---|---|
24+
| **SOCKET** (agnostic, zero-dep) | `lance_graph_contract::hotplug` | `HotPlug { consumer, classids, covered }`, `Activation`, `ActivationDrift`, trait `CapabilityAuthority` |
25+
| **AUTHORITY** (declares + resolves) | OGAR `ogar_vocab` | domain action tables (e.g. `ocr_actions`) + `capability_registry::{domain_tables, resolve_hotplug, HotplugDrift}` |
26+
| **BRIDGE** (socket ⇄ authority) | `lance-graph-ogar` (workspace-EXCLUDED) | `OgarAuthority: CapabilityAuthority`; also owns COUNT_FUSE + per-entry mirror parity + the roundtrip green light |
27+
| **CONSUMER** | your repo | ONE `HOT_PLUG` const + ONE activation test + your executor |
28+
29+
The classid is the join key on BOTH sides: the consumer says "these
30+
canon-high ids are hot", the authority returns BOTH the vocab rows and
31+
every capability whose subject is one of those ids.
32+
33+
## Migration recipe (per consumer, ~1 hour)
34+
35+
1. **Authority side (OGAR PR #1):** declare your domain's action table
36+
in `ogar-vocab` next to `ocr_actions` — one `ActionDef` per
37+
capability on YOUR already-minted canon-high concepts (mint via the
38+
normal codebook process if missing; hi u16 = concept, lo u16 = APP
39+
render prefix, NEVER a shape ordinal). Export `<DOMAIN>_ACTION_NAMES`
40+
(const fingerprint), `<DOMAIN>_SUBJECT_CLASSIDS`,
41+
`<DOMAIN>_EXPECTED_EXECUTORS = ["<your-crate>"]`. Register ONE entry
42+
in `capability_registry::domain_tables()` mapping
43+
`(capability, subject classid)`. That's the whole authority change.
44+
2. **Consumer side:** add path deps (NO PINS — local siblings):
45+
`ogar-vocab = { path = "<rel>/OGAR/crates/ogar-vocab" }` and
46+
`lance-graph-contract = { path = "<rel>/lance-graph/crates/lance-graph-contract" }`.
47+
3. Declare the plug:
48+
```rust
49+
pub const HOT_PLUG: lance_graph_contract::hotplug::HotPlug =
50+
lance_graph_contract::hotplug::HotPlug {
51+
consumer: "<your-crate>",
52+
classids: ogar_vocab::<domain>_actions::<DOMAIN>_SUBJECT_CLASSIDS,
53+
covered: COVERED_CAPABILITIES, // your executor's arms
54+
};
55+
```
56+
4. Close the loop with ONE test:
57+
```rust
58+
let (concepts, capabilities) = ogar_vocab::capability_registry::resolve_hotplug(
59+
HOT_PLUG.consumer, HOT_PLUG.classids, HOT_PLUG.covered,
60+
).expect("hot-plug drifted from the authoritative OGAR tables");
61+
```
62+
(Or through the socket: `OgarAuthority.activate(&HOT_PLUG)` via
63+
`dyn CapabilityAuthority` when you want authority-agnostic code.)
64+
5. **CI:** your workflows need the sibling checkouts (OGAR +
65+
lance-graph), same as tesseract-rs `rust.yml` / lance-graph
66+
`rust-test.yml`. Sibling layout: check the repo out into a subdir
67+
(`path: <repo>`) so `path: OGAR` lands as a true sibling.
68+
69+
## The drift arms (each one named bang, test-time, in YOUR binary)
70+
71+
| Arm | Meaning |
72+
|---|---|
73+
| `UnknownClassid(id)` | plugged id not minted in the codebook |
74+
| `NoCapabilitiesFor(id)` | id resolves to no capability — the table/ontology was forgotten |
75+
| `UnexpectedConsumer` | you are not in the table's expected-executor list |
76+
| `Uncovered(cap)` | authority declares it, your executor has no arm |
77+
| `Undeclared(cap)` | your executor claims it, authority doesn't declare it |
78+
79+
Plus, CI-side (lance-graph `rust-test.yml`): COUNT_FUSE + per-entry
80+
mirror parity + the roundtrip green light run against the real OGAR
81+
sibling on every push.
82+
83+
## What NOT to do (each burned once, 2026-07-07)
84+
85+
- **No bespoke per-consumer plug crate/mechanism.** The registration
86+
surface is the `HOT_PLUG` const + one test. (tesseract-ogar's first
87+
`CapabilityRegistration` draft was replaced for exactly this.)
88+
- **No path/optional deps on `lance-graph-contract` toward OGAR.** The
89+
contract is a workspace MEMBER; any path dep there (even optional) is
90+
resolved at workspace-load time and kills every CI cargo invocation.
91+
The contract stays zero-dep; armed things live in excluded crates.
92+
- **No shape ordinals in the classid low u16.** Low half = APP render
93+
prefix (`PortSpec::APP_PREFIX`). Distinct shapes are distinct hi-u16
94+
concepts or ClassView payload readings.
95+
- **No ontology payload in lance-graph.** lance-graph carries the wire
96+
mirror + the green light, nothing else. Authority checks live in OGAR.
97+
- **No git deps on OGAR.** git+branch always writes a rev pin into
98+
Cargo.lock. Path deps to the sibling, always.
99+
100+
## Future synergies (evaluated 2026-07-07 — next arcs, not shipped)
101+
102+
1. **ActionDef plug-and-play from ruff (HIGH, near-term).**
103+
`ogar-from-ruff::lift_actions` already lifts ActionDefs from
104+
Rails/Python model graphs — the OCR table is hand-declared only
105+
because tesseract has no AR source. The generic path: ruff harvest
106+
(`ruff_*_spo`) → fuzzy-recipe codebook (`(verb, criteria)` recipes,
107+
ruff `.claude/knowledge/fuzzy-recipe-codebook.md`) → `lift_actions`
108+
the domain table auto-derives instead of being hand-written; a
109+
consumer migration then starts with a harvest, not an authorship
110+
session. Missing piece: a C++ arm for `lift_actions` (ruff_cpp_spo
111+
has walk_tu/walk_free_functions/walk_enums; an action-lift over the
112+
method-body facts is the natural fourth arm) and a
113+
`derive_domain_table!`-style bridge from lifted ActionDefs into
114+
`domain_tables()`.
115+
2. **Param-enum fidelity via `walk_enums` (MEDIUM).** Capability params
116+
that are C/C++ enums (PSM modes, connectivity 4/8, …) can carry
117+
their variants from the ruff enum harvest instead of free-form
118+
names — the same shapes-from-ruff discipline the dawg/dict arc used.
119+
3. **Ontology plug-and-play (MEDIUM, design needed).** Today
120+
`resolve_hotplug` returns vocab rows + capability names. The same
121+
join can return ONTOLOGY fragments per classid: OGAR's
122+
`vocab/exports → OGIT promote → vocab/imports` pipeline already
123+
stages TTL per domain, and `ogar-adapter-ttl` renders it. A
124+
`resolve_hotplug_with_ontology` returning the OGIT NTO fragment
125+
references for the plugged classids would let a consumer pull
126+
concepts + actions + ontology in one activation — still zero
127+
serialization in-binary; the TTL stays an OGAR-internal artifact
128+
(imports/ tier), never hauled through lance-graph. Gate: needs the
129+
imports/ tier populated for the domain (ontologies, not harvests —
130+
harvests stay in the consumer repo).
131+
4. **Thinking-styles best practices (HIGH, planned all along).** One
132+
`domain_tables()` entry + a `<STYLES>_EXPECTED_EXECUTORS` list arms
133+
the thinking-style table for whichever engine executes styles —
134+
same recipe as step 1 above, zero new machinery.

0 commit comments

Comments
 (0)