Skip to content

Commit cc5a084

Browse files
committed
osint: promote the dual-use axes to the 0xFFFF global-category pole
Slice-2 prototype (1 of 2) on aiwar. The 12 SchemaAxis dimensions are promoted to the CEILING pole — HEEL=HIP=0xFFFF, the axis index in TWIG — so they are cross-cutting GLOBAL categories addressable across every basin, not stranded basin-local (which is what islanded them). The address says "global" before any edge does. Bake (osint-bake): - SchemaAxis nodes get HEEL=HIP=0xFFFF, TWIG=axis grain (stable order among the axes); entities/values keep theme/anchor in HEEL/HIP, TWIG=0; family/ identity unchanged. New const GLOBAL_CEILING; the 0x0000 floor pole and the leaf grain (sentinel run through TWIG) follow the same lattice. Cockpit (OsintGraph.tsx): - Read the ceiling marker straight off the GUID (HEEL @4, HIP @6). - Render ceiling nodes as bright gold diamonds (the cross-cutting hubs), prominent in every mode (class / facet lens / reasoning). Legend entry. Verified: osint-bake 9/9 tests (new schema_axes_are_ceiling_pole_global_ categories), clippy clean, asset deterministic (3/3 SHA). Asset decode: 12 ceiling nodes, all cls 6, distinct twigs 0..11, 0 entities promoted. Cockpit `tsc && vite build` clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TzqvDqbFRzyx17EkLKBoZF
1 parent 5fdb53c commit cc5a084

3 files changed

Lines changed: 109 additions & 10 deletions

File tree

cockpit/src/OsintGraph.tsx

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ const facetColor = (code: number) =>
7474
const DIM_NODE = { background: 'rgba(10,14,23,0.55)', border: '#26323f' };
7575
const DIM_EDGE = 'rgba(50,66,84,0.12)';
7676
const ACTIVE = '#6cf0ff';
77+
// the cross-cutting global-category hubs (HEEL=HIP=0xFFFF ceiling pole) — drawn
78+
// as bright diamonds so the dual-use axes read as global, not basin-local.
79+
const CEILING_COLOR = '#ffd166';
7780

7881
interface Soa {
7982
nodeCount: number;
@@ -84,6 +87,8 @@ interface Soa {
8487
// per-node facet tenant: 6 codes (value[1..=6]) × nodeCount, or null if the
8588
// asset predates the tenant tail. The dynamic attribute the facet lens groups by.
8689
tenants: Uint8Array | null;
90+
// per-node global-category flag (HEEL=HIP=0xFFFF ceiling pole): 1 = cross-cutting.
91+
ceiling: Uint8Array;
8792
}
8893

8994
/** One readable step of the reasoning traversal, streamed into the readout. */
@@ -120,7 +125,14 @@ function decodeSoa(buf: ArrayBuffer): Soa {
120125
const edgeCount = dv.getUint32(8, true);
121126
let off = 12;
122127
const cls = new Uint8Array(nodeCount);
128+
// ceiling[i] = 1 when the GUID's HEEL and HIP are both the 0xFFFF sentinel —
129+
// the node is a cross-cutting GLOBAL category (the dual-use axes), not
130+
// basin-local. Read straight off the 16-byte GUID (HEEL @4, HIP @6).
131+
const ceiling = new Uint8Array(nodeCount);
123132
for (let i = 0; i < nodeCount; i++) {
133+
const heel = dv.getUint16(off + 4, true);
134+
const hip = dv.getUint16(off + 6, true);
135+
if (heel === 0xffff && hip === 0xffff) ceiling[i] = 1;
124136
cls[i] = dv.getUint8(off + 16);
125137
off += 17;
126138
}
@@ -150,7 +162,7 @@ function decodeSoa(buf: ArrayBuffer): Soa {
150162
tenants = new Uint8Array(buf, off, nodeCount * 6);
151163
off += nodeCount * 6;
152164
}
153-
return { nodeCount, edgeCount, cls, edges, labels, tenants };
165+
return { nodeCount, edgeCount, cls, edges, labels, tenants, ceiling };
154166
}
155167

156168
// vis-network options tuned to the Palantir look: hollow ring nodes (dark fill
@@ -348,22 +360,26 @@ export function OsintGraph() {
348360
// code on that axis (categorical, computed live across every node); else the
349361
// class colour. This is the dynamic group-by — no baked edges involved.
350362
const nodeBorder = (i: number) => {
363+
if (soa.ceiling[i]) return CEILING_COLOR; // global hubs stay prominent in every mode
351364
const ax = facetAxisRef.current;
352365
if (ax != null && soa.tenants) return facetColor(soa.tenants[i * 6 + ax]);
353366
return classColor(soa.cls[i]);
354367
};
368+
const nodeKind = (i: number) =>
369+
soa.ceiling[i] ? '◈ global category (cross-cutting)' : CLASS[soa.cls[i]]?.name ?? 'concept';
355370
const baseNode = (i: number) => ({
356371
id: i,
357372
label: soa.labels[i] || `#${i}`,
373+
shape: soa.ceiling[i] ? 'diamond' : 'dot',
358374
color: {
359-
background: 'rgba(10,14,23,0.88)',
375+
background: soa.ceiling[i] ? 'rgba(255,209,102,0.14)' : 'rgba(10,14,23,0.88)',
360376
border: nodeBorder(i),
361377
highlight: { background: 'rgba(10,14,23,0.96)', border: '#9fe8ff' },
362378
hover: { background: 'rgba(10,14,23,0.82)', border: nodeBorder(i) },
363379
},
364-
size: baseSize(i),
365-
font: { color: '#d9e9f9' },
366-
title: `${soa.labels[i] || `#${i}`}\n${CLASS[soa.cls[i]]?.name ?? 'concept'} · ${degree.get(i) ?? 0} links`,
380+
size: baseSize(i) + (soa.ceiling[i] ? 7 : 0),
381+
font: { color: soa.ceiling[i] ? '#ffe9b0' : '#d9e9f9' },
382+
title: `${soa.labels[i] || `#${i}`}\n${nodeKind(i)} · ${degree.get(i) ?? 0} links`,
367383
});
368384
const baseEdge = (e: { id: number; s: number; t: number; r: number }) => ({
369385
id: e.id,
@@ -993,6 +1009,20 @@ export function OsintGraph() {
9931009
{k.name}
9941010
</span>
9951011
))}
1012+
<span style={{ marginRight: 12, whiteSpace: 'nowrap' }}>
1013+
<span
1014+
style={{
1015+
display: 'inline-block',
1016+
width: 9,
1017+
height: 9,
1018+
border: `2px solid ${CEILING_COLOR}`,
1019+
marginRight: 5,
1020+
verticalAlign: 'middle',
1021+
transform: 'rotate(45deg)',
1022+
}}
1023+
/>
1024+
◈ global axis
1025+
</span>
9961026
</div>
9971027

9981028
{/* alternative-view link */}
0 Bytes
Binary file not shown.

crates/osint-bake/src/lib.rs

Lines changed: 74 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,14 @@ fn plan_basins(graph: &AiWarGraph, rounds: &[EncounterRound]) -> BasinPlan {
507507
}
508508
}
509509

510+
/// The CEILING global-category pole. `HEEL = HIP = 0xFFFF` marks a node as a
511+
/// **cross-cutting global category** (not basin-local); the first non-sentinel
512+
/// tier below — here TWIG — sets its grain (run the sentinel deeper, through
513+
/// TWIG, to reach a leaf-limited category). Mirrors the existing `0xFF` hub
514+
/// convention lifted from the basin byte to the HHTL tiers; `0x0000` is the
515+
/// opposite **floor** pole (default / fall-through).
516+
const GLOBAL_CEILING: u16 = 0xFFFF;
517+
510518
/// Build the classid-`0x0700` OSINT node rows (one per entity, in `graph.nodes`
511519
/// order so `identity == index`). The GUID-v2 tail is `leaf=0 | family=basin |
512520
/// identity=index`; HEEL/HIP carry the theme/anchor for deterministic HHTL
@@ -525,14 +533,31 @@ pub fn osint_node_rows(graph: &AiWarGraph, plan: &BasinPlan) -> Vec<NodeRow> {
525533
.push(e.target.as_str());
526534
}
527535

536+
// SchemaAxis nodes (the dual-use dimensions) are promoted to the CEILING
537+
// global-category pole at TWIG grain: each gets a stable TWIG (its order
538+
// among the SchemaAxis nodes, in graph.nodes order — deterministic). They
539+
// become cross-cutting categories addressable across every basin, instead
540+
// of being stranded basin-local (which is what islanded them).
541+
let axis_twig: HashMap<&str, u16> = graph
542+
.nodes
543+
.iter()
544+
.filter(|n| n.node_type == "SchemaAxis")
545+
.enumerate()
546+
.map(|(k, n)| (n.id.as_str(), k as u16))
547+
.collect();
548+
528549
graph
529550
.nodes
530551
.iter()
531552
.enumerate()
532553
.map(|(i, n)| {
533554
let basin = basin_of(&n.id);
534-
let theme_hi = u16::from(basin >> 4);
535-
let anchor_lo = u16::from(basin & 0x0F);
555+
// ceiling pole (HEEL=HIP=0xFFFF, TWIG=axis grain) for the dimensions;
556+
// theme/anchor (TWIG=0) for everything basin-local.
557+
let (heel, hip, twig) = match axis_twig.get(n.id.as_str()) {
558+
Some(&t) => (GLOBAL_CEILING, GLOBAL_CEILING, t),
559+
None => (u16::from(basin >> 4), u16::from(basin & 0x0F), 0),
560+
};
536561

537562
// 16×8bit mixin-node adapters (FLAT — the old 12+4 in/out split is
538563
// waived). The distinct nonzero *other* basins this node connects
@@ -571,9 +596,9 @@ pub fn osint_node_rows(graph: &AiWarGraph, plan: &BasinPlan) -> Vec<NodeRow> {
571596
NodeRow {
572597
key: NodeGuid::new_v2(
573598
NodeGuid::CLASSID_OSINT, // classid 0x0700 — the ONE OSINT class
574-
theme_hi, // HEEL — coarse HHTL routing by theme
575-
anchor_lo, // HIP — anchor tier
576-
0, // TWIG
599+
heel, // HEEL — theme, or 0xFFFF ceiling for a dimension
600+
hip, // HIP — anchor, or 0xFFFF ceiling for a dimension
601+
twig, // TWIG — axis grain for a ceiling-pole dimension
577602
0, // LEAF (4th HHTL tier)
578603
u16::from(basin), // family = basin relay (mixin)
579604
i as u16, // identity = node index
@@ -1097,4 +1122,48 @@ mod tests {
10971122
"basin hubs carry a zero tenant"
10981123
);
10991124
}
1125+
1126+
#[test]
1127+
fn schema_axes_are_ceiling_pole_global_categories() {
1128+
// The dual-use dimensions are promoted to the 0xFFFF CEILING pole at
1129+
// TWIG grain: cross-cutting global categories (HEEL=HIP=sentinel), the
1130+
// axis index in TWIG. Entities stay basin-local (theme/anchor in
1131+
// HEEL/HIP, TWIG unused). The address says "global" without an edge.
1132+
let node = |id: &str, ty: &str| aiwar_ingest::GraphNode {
1133+
id: id.to_string(),
1134+
label: id.to_string(),
1135+
node_type: ty.to_string(),
1136+
properties: HashMap::new(),
1137+
};
1138+
let g = AiWarGraph {
1139+
nodes: vec![
1140+
node("Lattice", "System"),
1141+
node("militaryUse", "SchemaAxis"),
1142+
node("civicUse", "SchemaAxis"),
1143+
],
1144+
edges: vec![],
1145+
};
1146+
let plan = plan_basins(&g, &[]);
1147+
let rows = osint_node_rows(&g, &plan);
1148+
1149+
let mu = g.nodes.iter().position(|n| n.id == "militaryUse").unwrap();
1150+
let cu = g.nodes.iter().position(|n| n.id == "civicUse").unwrap();
1151+
// both axes sit at the ceiling pole, with DISTINCT twig grains.
1152+
assert_eq!(rows[mu].key.heel(), 0xFFFF, "axis HEEL = ceiling sentinel");
1153+
assert_eq!(rows[mu].key.hip(), 0xFFFF, "axis HIP = ceiling sentinel");
1154+
assert_eq!(rows[cu].key.heel(), 0xFFFF);
1155+
assert_eq!(rows[cu].key.hip(), 0xFFFF);
1156+
assert_ne!(
1157+
rows[mu].key.twig(),
1158+
rows[cu].key.twig(),
1159+
"each axis is a distinct twig-grain category"
1160+
);
1161+
// identity/family are still the fine address (unchanged).
1162+
assert_eq!(rows[mu].key.identity_v2(), mu as u16);
1163+
1164+
// a normal entity stays basin-local — NOT the ceiling sentinel.
1165+
let sys = g.nodes.iter().position(|n| n.id == "Lattice").unwrap();
1166+
assert_ne!(rows[sys].key.heel(), 0xFFFF, "entity is basin-local");
1167+
assert_eq!(rows[sys].key.twig(), 0, "entity TWIG unused");
1168+
}
11001169
}

0 commit comments

Comments
 (0)