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
4 changes: 2 additions & 2 deletions .claude/board/STATUS_BOARD.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ Plan: `.claude/plans/nal-polyfill-v1.md`. Template: D-SQLP. No opcode, tenant or
| D-id | scope | status | gate / falsifier |
|---|---|---|---|
| **D-NALP-0** | Plan, board rows | In PR | docs only |
| **D-NALP-1** | Statement layout + declared ClassView reading; additive `WideFieldMask` projection path on `ClassView`; binder's mask; term width decision | Queued | only the mask's lanes are read; undeclared reading and masked-out field refuse; Small = Wide answers |
| **D-NALP-2** | Query procedures: select, truth threshold, choice by confidence, support count | Queued | equal to a row-at-a-time oracle; one-pattern threshold disable red; no new opcode |
| **D-NALP-1** | Statement layout + declared ClassView reading; additive `WideFieldMask` projection path on `ClassView`; binder's mask; term width decision | In PR #1525 (NodeGuid reading `nal-statement-v1`, term width u16, aperture selection; ClassView wide projection and binder mask still queued) | only the mask's lanes are read; undeclared reading and masked-out field refuse; Small = Wide answers |
| **D-NALP-2** | Query procedures: select, truth threshold, choice by confidence, support count | In PR #1525 (`crates/lance-graph-nal`: NodeGuid key, byte apertures; 7 oracle tests, 7 disable runs red; 19–248 ns at 1,048,576 rows) | equal to a row-at-a-time oracle; one-pattern threshold disable red; no new opcode |
| **D-NALP-3** | Revision as `GroupCrossPowerSumsI32` over stored `w`/`f` | Queued | equal to exact integer revision; OpenNARS revision points; duplicate evidence counts once |
| **D-NALP-4** | Per-row truth law into a lane: `MapPairU8` vs fixed-point multiply-high | Queued | insufficiency proof; per-row parity with `isa::truth`, error in codes; one shape also serves SQL nullable arithmetic |
| **D-NALP-5** | Deduction / induction / abduction / analogy over populations | Queued (after D-NALP-4) | equals pairwise scalar rule; abduction direction test red for the reversed statement |
Expand Down
27 changes: 27 additions & 0 deletions .claude/board/entries/2026-10-12-nal-coordinate-queries.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# 2026-10-12 — NAL query operations as coordinate ranges (D-NALP-1/2)

**Status:** In PR (#1525). Plan: `.claude/plans/nal-polyfill-v1.md` (status note before § 5).

**Decision (operator, 2026-10-12):** the NodeGuid is always the address and the
distinguished name; a selection is the 16-byte key minus an `n`-byte aperture.
A belief's key carries only its name (classid, S, copula, P, id); its truth
value lives in value lanes in the sealed order.

**Finding (MEASURED):** a statement, a subject or a whole class is an aperture
of 10, 6 or 4 cared bytes and one witnessed range
(`SealedFacetLane::bound_aperture`). The typed `nal::` operations bind once
(R2IL procedure → kept mask-risc program) and each call runs only that program
over the range as its execution extent. At 1,048,576 beliefs: range counts
19–20 ns, a confidence threshold over a 245-row subject 127 ns, the maximum
confidence 248 ns, against 495–559 µs for the row loop
(`crates/lance-graph-nal/examples/nal_cost.rs`, AVX-512, release).

**Tests:** `crates/lance-graph-nal/tests/w2.rs`, 7 row-oracle tests over the
unsorted input; 7 disable runs red (statement aperture too narrow, aperture
one byte short, threshold off by one, threshold without its extent, choice
reading `f`, truth lanes misaligned with keys, witness not validated).

**OPEN:** R2IL `RANGE` takes `u8` immediates and cannot name a range past row
255 (request to `ogar-r2il`); no argmax fold (which belief holds the maximum);
the rest of D-NALP-1 (ClassView `WideFieldMask` projection, binder mask) and
W3+ are queued.
3 changes: 2 additions & 1 deletion .claude/board/entries/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ index row, (3) no duplicate entry id. Checks 1 and 2 are deliberately
opposite directions; the stranding this convention prevents shows up in
exactly one of them, never both.

324 entries, 2026-08-06 .. 2026-10-12.
325 entries, 2026-08-06 .. 2026-10-12.

| date | entry id | finding | file |
|---|---|---|---|
Expand All @@ -36,6 +36,7 @@ exactly one of them, never both.
| 2026-10-12 | `D-CMH-G1-6` | | [2026-10-12-ordered-conditions-and-extrema.md](2026-10-12-ordered-conditions-and-extrema.md) |
| 2026-10-12 | `opencog-pln-entropy-research-map` | Source inventory and falsifiable PLN/ECAN/Shannon/Moore attention comparison: entropy target, evidence overlap, graph projection, resource fairness | [2026-10-12-opencog-pln-entropy-research-map.md](2026-10-12-opencog-pln-entropy-research-map.md) |
| 2026-10-12 | `nars-self-evidence-literature` | NARS internal trace versus evidence, Jøsang dependent/independent fusion and fission, and the snapshot-stable fold assumption; source-grounded red tests for merged #1496 | [2026-10-12-nars-self-evidence-literature.md](2026-10-12-nars-self-evidence-literature.md) |
| 2026-10-12 | `D-NALP-1` | | [2026-10-12-nal-coordinate-queries.md](2026-10-12-nal-coordinate-queries.md) |
| 2026-10-12 | `D-SAG-CF-1` | counterfactual dependency = factual W0 vs detached W_X; RFC + Boolean smoke oracle (F0/F7/F8 unverified) | [2026-10-12-inverted-temporal-ablation.md](2026-10-12-inverted-temporal-ablation.md) |
| 2026-10-12 | `D-IAM-SAG-0` | IAM categories as read-only projections over dir_sim/OGAR/SAG; observed != inferred != authorized | [2026-10-12-iam-substrate-sag-dir-sim.md](2026-10-12-iam-substrate-sag-dir-sim.md) |
| 2026-10-12 | `hyperon-metta-lg-translation` | Hyperon/MeTTa to LG sibling map: atom/hypergraph roundtrip, binding and rewrite parity, typed folds, scoped effects and 15 open questions | [2026-10-12-hyperon-metta-lg-translation.md](2026-10-12-hyperon-metta-lg-translation.md) |
Expand Down
44 changes: 44 additions & 0 deletions .claude/plans/nal-polyfill-v1.md
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,50 @@ Rules that follow, each enforced in W6:
- **`PROC_DEF` execution.** The same OPEN item as D-SQLP: until it exists,
procedures are inlined call sequences.

### Status 2026-10-12 (D-NALP-1/2, `crates/lance-graph-nal`)

- **NAL operations are global core methods** (operator, 2026-10-12: "NARS
ist global"). They run over any belief population, check no classid, and
need no hot-plug and no minted concept; they read the one canonical reading
`nal-statement-v1`. Classid-dependent methods are the other kind: declared at
compile time through a consumer's `HotPlug` and checked against the row's
classid (the D-CMH path, not this crate). This removes W8's concept-id mint
request; W8 keeps only the bytes W4/W5 earn.
- **The NodeGuid is the address and the distinguished name** (operator,
2026-10-12). Reading `nal-statement-v1`: semantic tiles `[classid hi,
classid lo, S, copula, P, id, 0, 0]`. The key names the belief and nothing
else; `f` and `c` are value lanes written in the key's sealed order, so key
row `i` and truth row `i` are one belief by construction. Truth is never
part of a name.
- **A selection is the 16-byte key minus an aperture** (operator,
2026-10-12): `Aperture { key, bytes }` cares the leading `bytes` bytes and
frees the rest. On the witnessed HHTL order (classid, then each tile coarse
to fine) the matches are one range, found by the contract's
`SealedFacetLane::bound_aperture`: 4 bytes = the class, 6 = a subject, 10 =
a statement. This replaces the §4 A lowering column for the belief query:
it is a range, not a lane predicate.
- **Term width (OPEN above): decided `u16` per tile.** A vocabulary past
65,536 terms scales through the classid prefix, not by widening a tile.
- **Bind once, run the kept program.** `nal::{Question, TruthAtLeast, Choice}`
run their R2IL procedure once at bind and keep the mask-risc `Program`; a
call runs only `execute_compiled`. The aperture's range is the execution
extent, so the confidence predicate and the `MAX` fold read only its rows
(a range passed as an ANDed mask instead cost 195 µs at 1,048,576 rows;
as the extent, 127 ns).
- **Measured** (`examples/nal_cost.rs`, release, AVX-512, median of 101,
answers asserted first), n = 1,048,576: range counts 19–20 ns; confidence
threshold over one statement 81 ns, over a 245-row subject 127 ns; choice
(max confidence) over the subject 248 ns; bind 274 ns; the row loop
495–559 µs.
- **OPEN, found here:** R2IL `RANGE` (arity 0) takes its bounds from two `u8`
immediates, so through the byte it cannot name a range past row 255. The
procedures emit the bound with `FoldDialect::emit_pred(Pred::Range)`. An
`ogar-r2il` request, not minted here.
- **OPEN:** which belief holds the maximum (argmax) is not a mask-risc fold;
`Choice` answers the maximum confidence only.
- Not yet: the ClassView `WideFieldMask` projection and the binder's mask
(rest of D-NALP-1); W3 onwards.

## 5. Waves

| Wave | D-id | Repo | Work | Gate (all must pass) |
Expand Down
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ exclude = [
# the OGAR sibling. Verify via
# `cargo test --manifest-path crates/lance-graph-r2il/Cargo.toml`.
"crates/lance-graph-r2il",
# NAL over the fold path (D-NALP-1/2): path-deps lance-graph-r2il, so it
# needs the OGAR checkout too. Own workspace root; verify via
# `cargo test --manifest-path crates/lance-graph-nal/Cargo.toml`.
"crates/lance-graph-nal",
"crates/symbiont",
# OGAR (Open Graph of Active Record) activation crate — re-exports OGAR's full
# AR surface (ogar-vocab Class/codebook + ogar-class-view impl ClassView +
Expand Down
39 changes: 39 additions & 0 deletions crates/lance-graph-mask-risc/src/ir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1416,6 +1416,45 @@ impl<'p> Compiled<'p> {
}
}

/// A [`Program`] owned together with its recognised lowering.
///
/// [`Compiled`] borrows its program, so a caller that keeps a prepared query
/// (bound once, run many times) cannot keep a `Compiled` beside the program
/// it borrows from. This type holds both; [`CompiledProgram::compiled`] hands
/// out a `Compiled` without recognising the lowering again. The program is
/// private, so it cannot change after the lowering was recognised.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CompiledProgram {
program: Program,
lowering: Lowering,
}

impl CompiledProgram {
/// Recognise `program`'s lowering once and keep both.
pub fn new(program: Program) -> Self {
let lowering = program.lowering();
CompiledProgram { program, lowering }
}

/// The program.
pub fn program(&self) -> &Program {
&self.program
}

/// The lowering recognised at construction.
pub fn lowering(&self) -> Lowering {
self.lowering
}

/// The compiled view for [`crate::exec::execute_compiled`]; no recognition.
pub fn compiled(&self) -> Compiled<'_> {
Compiled {
program: &self.program,
lowering: self.lowering,
}
}
}

/// A program the executor folds without writing membership bits: see
/// [`Program::fused_terminal`].
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
Expand Down
8 changes: 4 additions & 4 deletions crates/lance-graph-mask-risc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,10 @@ pub use exec::{
};
pub use fuse::{fuse, fuse_program, ternlog_imm, BoolExpr, FuseError, Fused};
pub use ir::{
touched_words, Compiled, Foreign, ForeignPlane, FusedFold, FusedKeep, FusedTerminal,
FusedTern2, FusedTern3, FusedTernlog, GroupFold, GroupKey, LaneRef, Lowering, MaskOp, Operand,
Planes, Pred, Program, StridedRef, Terminal, Tern2Fold, Tern3In, Tern3Step, FUSED_SLOT_CAP,
GROUP_SUM_SYM_MAX_ROWS, MASKED_SUM_I32_MAX_ROWS, MAX_SCRATCH_SLOTS,
touched_words, Compiled, CompiledProgram, Foreign, ForeignPlane, FusedFold, FusedKeep,
FusedTerminal, FusedTern2, FusedTern3, FusedTernlog, GroupFold, GroupKey, LaneRef, Lowering,
MaskOp, Operand, Planes, Pred, Program, StridedRef, Terminal, Tern2Fold, Tern3In, Tern3Step,
FUSED_SLOT_CAP, GROUP_SUM_SYM_MAX_ROWS, MASKED_SUM_I32_MAX_ROWS, MAX_SCRATCH_SLOTS,
};
pub use reference::{
reference_execute, reference_execute_into, reference_scratch, reference_scratch_with_foreign,
Expand Down
52 changes: 52 additions & 0 deletions crates/lance-graph-mask-risc/tests/compiled_program.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//! `CompiledProgram`: a program owned with its recognised lowering.

use lance_graph_mask_risc::{
execute_compiled, CompiledProgram, Foreign, Lowering, MaskOp, Operand, Out, Planes, Pred,
Program, Scratch, Terminal, Value,
};

fn range_count(lo: u32, hi: u32) -> Program {
Program::new(
vec![MaskOp::Pred {
pred: Pred::Range { lo, hi },
under: None,
dst: 0,
}],
Terminal::Count {
mask: Operand::Scratch(0),
},
)
}

/// FAILS IF: the owned lowering differs from the one the program recognises,
/// or the compiled view does not answer like `Program::compile`.
#[test]
fn the_owned_lowering_is_the_recognised_one_and_answers_alike() {
let p = range_count(3, 70);
let owned = CompiledProgram::new(p.clone());
assert_eq!(owned.lowering(), p.lowering());
assert!(matches!(owned.lowering(), Lowering::Range(_)));
assert_eq!(owned.program(), &p);
let planes = Planes {
n_rows: 100,
masks: &[],
lanes: &[],
};
let foreign = Foreign {
planes: &[],
lanes: &[],
};
let mut s = Scratch::for_program(&p, 100).unwrap();
let a = execute_compiled(
&owned.compiled(),
&planes,
&foreign,
&mut s,
Out::None,
0..100,
)
.unwrap();
let b = execute_compiled(&p.compile(), &planes, &foreign, &mut s, Out::None, 0..100).unwrap();
assert_eq!(a, b);
assert_eq!(a, Value::Count(67));
}
26 changes: 26 additions & 0 deletions crates/lance-graph-nal/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[package]
name = "lance-graph-nal"
version = "0.1.0"
edition = "2021"
publish = false
description = "NAL over the fold path: Narsese statements as sealed facet coordinates, NAL operations as R2IL procedures compiled once into mask-risc programs (D-NALP-1/2)."

# Its OWN workspace root, like `lance-graph-r2il`: it path-deps the r2il crate,
# which path-deps the OGAR sibling. Verify via
# `cargo test --manifest-path crates/lance-graph-nal/Cargo.toml`.
[workspace]

[dependencies]
# The coordinate machinery: FacetCascade keys, the sealed ordered lane and its witness.
lance-graph-contract = { path = "../lance-graph-contract" }
# The only bulk engine.
lance-graph-mask-risc = { path = "../lance-graph-mask-risc" }
# The procedure executor: NAL operations are R2IL call sequences over it.
lance-graph-r2il = { path = "../lance-graph-r2il" }
ogar-loco = { path = "../../../OGAR/crates/ogar-loco" }

[patch."https://github.com/AdaWorldAPI/lance-graph"]
lance-graph-contract = { path = "../lance-graph-contract" }

[patch."https://github.com/AdaWorldAPI/ndarray"]
ndarray = { path = "../../../ndarray" }
Loading
Loading