diff --git a/ingest/src/ingest.el b/ingest/src/ingest.el index 108a1eb..c143e8c 100644 --- a/ingest/src/ingest.el +++ b/ingest/src/ingest.el @@ -13,7 +13,7 @@ // relations add edges. Every node enters with PROVENANCE + grounding-level // + stewardship class from the moment of entry. // -// transduce_manifold() is THE single mechanism — one function, polymorphic, with no +// transduce_bytes() is THE single mechanism — one function, polymorphic, with no // content-type branch inside it. It does not ask whether a payload is // prose, structured data, or raw/opaque bytes (audio, or anything else); // it runs one boundary-scan-with-fixed-window-fallback chunking algorithm @@ -401,25 +401,54 @@ fn head80(s: String) -> String { // truncates at the first embedded NUL, which is routine in real binary // bytes) is a MECHANICAL fidelity concern that belongs to whatever produced // `source` (see ingest_file's file_source_string below) — not a -// content-type judgment made in here. transduce_manifold() never learns whether a +// content-type judgment made in here. transduce_bytes() never learns whether a // chunk is plain text or a base64-encoded raw-byte window; every chunk is // handled identically either way. -// RENAMED transduce -> transduce_manifold (2026-08-16). Two reasons, and the -// first is not the interesting one: +// NAMING, CORRECTED 2026-08-16 (second pass). This function was renamed +// `transduce` -> `transduce_bytes` earlier the same day, on the reasoning +// that it "was never signal->geometry — it chunks already-extracted content +// and PACKS it into a node+edge manifold, one layer up, and it had taken the +// name that belongs to the primitive underneath it." // -// 1. Mechanical: `transduce` is now a LANGUAGE primitive in el_runtime.h -// (transduce(signal, modality) -> Geometry). Every El `fn name(...)` -// compiles to a global C symbol with that exact name, so keeping this -// name here is a hard `conflicting types for 'transduce'` compile error -// the moment ingest.c links el_runtime.c. Measured, not anticipated. +// THAT REASONING WAS BACKWARDS, and it is worth recording why rather than +// quietly re-renaming. Producing a node+edge manifold is not a layer above +// transduction — it IS transduction. Transduction is not conversion. When you +// take in music you do not store the song as one discrete geometry; you break +// it into its component parts and store the geometry of each along with the +// relations between them. The song is the structure of those relations. +// Signal -> one vector is the operation UNDERNEATH transduction, and its name +// is encoding, or geometry. So the layer that was doing it right got renamed +// out of the way so the layer doing it wrong could have the name. // -// 2. Actual: this function was never signal->geometry. It chunks already- -// extracted content and PACKS it into a node+edge manifold — a real -// operation, but one layer up, and it had taken the name that belongs to -// the primitive underneath it. `transduce` is where a signal becomes -// geometry; `transduce_manifold` is where extracted content becomes -// structure. Nothing about this function's behaviour changed. -fn transduce_manifold(nodes: [String], edges: [String], source: String, +// The primitive has since been corrected: `transduce(signal, modality)` now +// returns a Manifold — components plus relations — not a Geometry +// (el_runtime.c, "Manifold"). The two layers are therefore doing the SAME KIND +// of thing, and the inversion dissolves rather than needing to be re-argued. +// +// What is left is a real distinction, and it is about MODALITY, not layering: +// +// * `transduce(signal, modality)` dispatches to a realizer that KNOWS the +// modality and can name its components — for audio: pitch, interval, +// rhythm, harmonic function. +// * `transduce_bytes` below is the OPAQUE-BYTES realizer: the decomposition +// available to a reader that knows nothing about what it is reading. It +// still yields components and relations (chunk nodes; contains / precedes +// / section_of edges), which is why it is transduction and not packing. It +// just cuts on the only structure visible without understanding — byte +// boundaries — so its components are positional rather than meaningful. +// That is a LIMITATION of this realizer, not the definition of the +// operation. +// +// The name is suffixed by its modality, not demoted to a lesser layer. Keeping +// a distinct symbol is also still mechanically required: every El `fn name` +// compiles to a global C symbol, so reusing `transduce` here is a hard +// `conflicting types` error the moment ingest.c links el_runtime.c. +// +// WHERE THIS SHOULD GO: this function should become a registered realizer +// returning a real Manifold, so ingest rides the same primitive as every other +// modality instead of carrying a parallel implementation. Not done here. +// Nothing about this function's behaviour changed in this pass. +fn transduce_bytes(nodes: [String], edges: [String], source: String, prov: String, ground: String, steward: String, root_lid: String, root_title: String) -> [String] { let tagbase: String = "prov:" + prov + " ground:" + ground + " steward:" + steward @@ -546,8 +575,8 @@ fn default_steward() -> String { // trustworthy verbatim. When they don't (silent truncation happened), // rebuild the payload as base64-encoded fixed-size windows read directly // off disk (fs_read_b64_chunk — binary-safe in C), joined with the same -// "\n\n" boundary marker transduce_manifold()'s generic scan already looks for, so -// transduce_manifold() sees one ordinary boundary-delimited payload and runs its one +// "\n\n" boundary marker transduce_bytes()'s generic scan already looks for, so +// transduce_bytes() sees one ordinary boundary-delimited payload and runs its one // algorithm on it exactly as it would on prose — it never learns that a // fidelity problem occurred upstream, let alone why. fn file_source_string(path: String, text: String, real_size: Int) -> String { @@ -556,7 +585,7 @@ fn file_source_string(path: String, text: String, real_size: Int) -> String { // 3072 raw bytes -> 4096 base64 chars (3 divides evenly into base64's // 3-byte/4-char ratio); keeps each resulting node's content a clean, // bounded, low-kilobytes unit, same order of magnitude as the fixed - // fallback window in transduce_manifold() itself. + // fallback window in transduce_bytes() itself. let win: Int = 3072 let out: String = "" let off: Int = 0 @@ -576,7 +605,7 @@ fn file_source_string(path: String, text: String, real_size: Int) -> String { } // ingest one file -> report JSON. Uniform for every file regardless of -// extension or content — transduce_manifold() decides nothing about content-type, so +// extension or content — transduce_bytes() decides nothing about content-type, so // neither does this function; it only decides whether the raw bytes made it // through the read intact (file_source_string), which is a fidelity // question, not a format one. @@ -588,14 +617,14 @@ fn ingest_file(path: String) -> String { return "{\"error\":\"empty or unreadable\",\"path\":" + j_q(path) + "}" } let prov: String = "file:" + path - let packed: [String] = transduce_manifold(el_list_empty(), el_list_empty(), + let packed: [String] = transduce_bytes(el_list_empty(), el_list_empty(), source, prov, default_ground(), default_steward(), "doc:" + basename(path), basename(path)) return merge_packed(packed) } // ingest a directory: walk one level, ingest every file found, aggregate. -// No extension filter — transduce_manifold() handles any payload uniformly now, so +// No extension filter — transduce_bytes() handles any payload uniformly now, so // there is no content-type gate at the directory boundary either. fn ingest_dir(path: String) -> String { let entries: [String] = fs_list(path) @@ -630,7 +659,7 @@ fn ingest_dir(path: String) -> String { fn ingest_url(url: String) -> String { let body: String = http_get(url) if str_eq(body, "") { return "{\"error\":\"empty fetch\",\"url\":" + j_q(url) + "}" } - let packed: [String] = transduce_manifold(el_list_empty(), el_list_empty(), + let packed: [String] = transduce_bytes(el_list_empty(), el_list_empty(), body, "url:" + url, "extracted", "public-web", "url:" + url, url) return merge_packed(packed) @@ -645,7 +674,7 @@ fn ingest_llm(query: String) -> String { let resp: String = http_post_json("http://127.0.0.1:11434/api/generate", body) let answer: String = json_get_string(resp, "response") if str_eq(answer, "") { return "{\"error\":\"no model response\"}" } - let packed: [String] = transduce_manifold(el_list_empty(), el_list_empty(), + let packed: [String] = transduce_bytes(el_list_empty(), el_list_empty(), answer, "llm:" + model + ":" + query, "candidate-provisional", "guide-provisional", "llm:" + query, "guide answer: " + query) return merge_packed(packed) @@ -697,7 +726,7 @@ fn ingest_stream(path: String) -> String { // It is NOT a content-type flag: it says nothing about what's inside the // bytes once fetched, and none of the five ingest_* functions it selects // among interpret their payload differently by content shape anymore — -// they all hand off to the single, format-agnostic transduce_manifold(). The old +// they all hand off to the single, format-agnostic transduce_bytes(). The old // "structured" value (a caller-declared alias for "file", used only to hint // the now-removed JSON-vs-prose branch) is gone along with that branch. let kind: String = env("INGEST_KIND") diff --git a/lang/examples/transduce.el b/lang/examples/transduce.el index 93eccdf..8a18ce6 100644 --- a/lang/examples/transduce.el +++ b/lang/examples/transduce.el @@ -1,67 +1,33 @@ -// transduce.el — geometry as a first-class El value, and a realizer written -// in El. Runnable: this is the worked example for the transduce surface, and -// it doubles as an executable proof because it checks every claim it makes. +// transduce.el — transduction decomposes a signal into components and the +// relations between them. Runnable: this is the worked example for the +// transduce surface, and it exits non-zero if any claim in it stops being true. // // elc lang/examples/transduce.el > transduce.c // cc -std=c11 -O2 -I lang/runtime -o transduce transduce.c \ -// lang/runtime/el_runtime.c lang/runtime/el_seed.c \ -// lang/runtime/engram_*.c -lcurl -lpthread -lm +// lang/runtime/el_runtime.c lang/runtime/el_seed.c \ +// lang/runtime/engram_store.c lang/runtime/engram_vindex.c \ +// lang/runtime/engram_cognition.c lang/runtime/engram_geometry.c \ +// lang/runtime/engram_reason.c lang/runtime/engram_verify.c \ +// -lcurl -lpthread -lm // ./transduce # exits 0 only if every check passes // -// (A `test "..."` form of the same checks lives in -// lang/tests/native/test_transduce.el, for when the native harness is -// repaired — the shipped elc currently emits calls to __el_reg_count and -// friends without emitting their definitions, which breaks every native test -// equally, test_math.el included. Verified 2026-08-16, unrelated to this work.) +// It writes to an IN-MEMORY engram (leave ENGRAM_STORE unset) and contacts no +// server. The same claims are asserted by the native harness in +// lang/tests/native/test_transduce.el. // -// WHY THIS EXISTS. Until 2026-08-16 no El ingest path could carry a vector: -// nodes took text, and geometry was DERIVED from that text. Text was the -// mandatory entry medium, so any non-text modality had to be DESCRIBED in -// prose first and the geometry we reasoned over was the geometry OF THE -// DESCRIPTION, not of the signal. Two things fix that, and both are shown -// below: geometry is a VALUE that carries its own width, and a REALIZER is an -// ordinary El function — so admitting a new modality never requires a runtime -// patch. +// WHAT CHANGED, AND WHY IT MATTERS. #144 shipped +// `transduce(signal, modality) -> Geometry`: one vector per signal. That made +// transduction a CONVERSION — take a thing, encode it, store a position — and +// what a conversion returns is a fingerprint. A fingerprint can be matched and +// ranked, and that is all it can ever do. It cannot be decomposed, cannot have +// one part grounded while another is not, and cannot be contradicted in one +// part while holding in another, because it has no parts. // -// COMPARISON DISCIPLINE (measured, not stylistic): elc lowers `a == b` -// numerically only when both operand NAMES are in the per-function int-name -// set that `let x: Int` populates. A bare `f(x) == 0` is not a registered -// name and lowers to str_eq — strcmp on two integers as pointers. `<` and `>` -// lower directly with no inference, so truthiness is written `> 0` / `< 1`. +// A song is not a point. It decomposes into pitch, interval, rhythm, harmonic +// function — components, each with its own geometry, plus the relations among +// them. THE SONG IS THE STRUCTURE OF THE RELATIONS. transduce now returns a +// Manifold, and a realizer's job is to say what its modality's components ARE. -// ── A realizer, written entirely in El ────────────────────────────────────── -// Not in the runtime. Not known to the compiler. Registered by NAME and -// dispatched to through transduce(). That is the whole claim. -fn tone_realizer(signal: String) -> Geometry { - let g: Geometry = geometry_new(4) - let n: Int = str_len(signal) - let a: Int = geometry_set(g, 0, int_to_float(n)) - let b: Int = geometry_set(g, 1, int_to_float(n * 2)) - let c: Int = geometry_set(g, 2, int_to_float(n * 3)) - let d: Int = geometry_set(g, 3, int_to_float(n * 4)) - g -} - -// A second modality, to show the registry keys on modality rather than just -// returning whatever was registered last. -fn pulse_realizer(signal: String) -> Geometry { - let g: Geometry = geometry_new(2) - let a: Int = geometry_set(g, 0, 1.0) - let b: Int = geometry_set(g, 1, 0.0) - g -} - -// A deliberately BROKEN realizer: returns something that is not a Geometry. -fn bogus_realizer(signal: String) -> Geometry { - return 12345 -} - -// Fails FAST rather than accumulating a count, for a measured reason: a first -// cut wrote `let fails: Int = fails + check(...)` and `+` lowered to STRING -// CONCAT, because elc dispatches `+` on whether both operands are known-Int and -// a user-defined fn call is not — so the counter printed 4343632752, a pointer. -// Nothing was wrong with the checks; the tally was lying. Exiting at the first -// failure needs no arithmetic at all, so there is nothing left to get wrong. fn check(ok: Int, label: String) -> Int { if ok > 0 { println(" ok " + label) @@ -84,128 +50,177 @@ fn eq_int(a: Int, b: Int) -> Int { return 0 } +// ── A DECOMPOSING realizer, written entirely in El ────────────────────────── +// "tone" signals are note letters, e.g. "CEG". This does NOT return one vector +// for the chord. It returns the PARTS — one component per note, one per +// interval between adjacent notes — and the relations that make those parts a +// chord rather than an unordered bag of pitches. +// +// The interval is deliberately a COMPONENT, not a field on a note. An interval +// is a thing with its own geometry belonging to neither endpoint; modelling it +// as an attribute of one of them is the same collapse, one level down. +fn tone_realizer(signal: String) -> Manifold { + let m: Manifold = manifold_new() + let n: Int = str_len(signal) + let i: Int = 0 + while i < n { + let code: Int = str_char_code(signal, i) + let g: Geometry = geometry_new(2) + let s0: Int = geometry_set(g, 0, int_to_float(code)) + let s1: Int = geometry_set(g, 1, int_to_float(i)) + let idx: Int = manifold_add(m, "note:" + int_to_str(i), "pitch", g) + let f: Int = geometry_free(g) + i = i + 1 + } + let j: Int = 1 + while j < n { + let a: Int = str_char_code(signal, j - 1) + let b: Int = str_char_code(signal, j) + let lo: String = "note:" + int_to_str(j - 1) + let hi: String = "note:" + int_to_str(j) + let key: String = "interval:" + int_to_str(j - 1) + "-" + int_to_str(j) + let g: Geometry = geometry_new(1) + let s: Int = geometry_set(g, 0, int_to_float(b - a)) + let idx: Int = manifold_add(m, key, "interval", g) + let f: Int = geometry_free(g) + let e1: Int = manifold_relate(m, key, "spans", lo, 0.9) + let e2: Int = manifold_relate(m, key, "spans", hi, 0.9) + let e3: Int = manifold_relate(m, lo, "sounds_before", hi, 0.8) + j = j + 1 + } + m +} + +// #144's contract, kept as a control: one vector for the whole signal. +fn fingerprint_realizer(signal: String) -> Geometry { + let g: Geometry = geometry_new(4) + let n: Int = str_len(signal) + let a: Int = geometry_set(g, 0, int_to_float(n)) + g +} + fn main() -> Void { - println("geometry is a value that carries its own width") - let g8: Geometry = geometry_new(8) - let _c: Int = check(geometry_is(g8), "geometry_new returns a live Geometry") - let d8: Int = geometry_dim(g8) - let _c: Int = check(eq_int(d8, 8), "a Geometry carries its own width (8)") - let _c: Int = check(geometry_free(g8), "geometry_free reports what it did") - - println("nonsense is refused — with no arbitrary max-dim bound") - // #141 needed `dim <= 8192` only to bound an allocation sized from a - // caller's CLAIM about a string's length. A value that carries its own - // width has nothing left to validate. - let z: Geometry = geometry_new(0) - let zi: Int = geometry_is(z) - let _c: Int = check(1 - zi, "dim 0 is not a geometry") - let ng: Geometry = geometry_new(-4) - let ngi: Int = geometry_is(ng) - let _c: Int = check(1 - ngi, "negative dim is not a geometry") - let nd: Int = geometry_dim(0) - let _c: Int = check(1 - nd, "geometry_dim of a non-geometry is 0, not a crash") - let nf: Int = geometry_free(0) - let _c: Int = check(1 - nf, "geometry_free of a non-geometry is a no-op") - - println("components round-trip, and out-of-range is refused") - let g3: Geometry = geometry_new(3) - let s0: Int = geometry_set(g3, 0, 1.5) - let s1: Int = geometry_set(g3, 1, -2.5) - let _c: Int = check(s0, "set in range succeeds") - let oob: Int = geometry_set(g3, 3, 9.0) - let _c: Int = check(1 - oob, "set out of range is refused, not silently dropped") - let _c: Int = check(near(geometry_get(g3, 0), 1.5), "component 0 round-trips") - let _c: Int = check(near(geometry_get(g3, 1), -2.5), "component 1 round-trips (negative)") - let ff3: Int = geometry_free(g3) - - println("hex is an EDGE adapter, and derives its own width") - // little-endian float32: 1.0 = 0000803f, 2.0 = 00000040 - let gh: Geometry = geometry_from_f32le_hex("0000803f00000040") - let _c: Int = check(geometry_is(gh), "valid hex decodes to a Geometry") - let dh: Int = geometry_dim(gh) - let _c: Int = check(eq_int(dh, 2), "width DERIVED from input, never supplied") - let _c: Int = check(near(geometry_get(gh, 0), 1.0), "first component decoded") - let _c: Int = check(near(geometry_get(gh, 1), 2.0), "second component decoded") - let back: String = geometry_to_f32le_hex(gh) - let _c: Int = check(str_eq(back, "0000803f00000040"), "hex round-trips exactly") - let ffh: Int = geometry_free(gh) - - println("malformed hex is refused") - let he: Geometry = geometry_from_f32le_hex("") - let hei: Int = geometry_is(he) - let _c: Int = check(1 - hei, "empty hex is not a geometry") - let hr: Geometry = geometry_from_f32le_hex("0000803f0000") - let hri: Int = geometry_is(hr) - let _c: Int = check(1 - hri, "length not a multiple of 8 is refused") - let hn: Geometry = geometry_from_f32le_hex("zzzzzzzz") - let hni: Int = geometry_is(hn) - let _c: Int = check(1 - hni, "non-hex characters are refused") - println("a realizer declared in El is a first-class realizer") let reg: Int = realizer_register("tone", "tone_realizer") - let _c: Int = check(reg, "an El fn registers as a realizer BY NAME") + let _c: Int = check(reg, "an El fn registers as a realizer by name") let _c: Int = check(realizer_has("tone"), "the modality now has an organ") - let gt: Geometry = transduce("aaa", "tone") - let _c: Int = check(geometry_is(gt), "transduce returns real geometry") - let dt: Int = geometry_dim(gt) - let _c: Int = check(eq_int(dt, 4), "the El realizer determined the width, not the runtime") - // str_len("aaa") == 3, so component 0 must be 3.0 — proof the signal - // actually reached the El function rather than a stub answering for it. - let _c: Int = check(near(geometry_get(gt, 0), 3.0), "the signal REACHED the El realizer") - let fft: Int = geometry_free(gt) - println("distinct signals transduce to distinct geometry") - let g1: Geometry = transduce("aa", "tone") - let g2: Geometry = transduce("aaaaa", "tone") - let a1: Float = geometry_get(g1, 0) - let a2: Float = geometry_get(g2, 0) - // 5 - 2 = 3. If transduction were a stub these would be equal. - let _c: Int = check(near(a2 - a1, 3.0), "different signals produce different geometry") - let ff1: Int = geometry_free(g1) - let ff2: Int = geometry_free(g2) + println("transduction decomposes a signal into parts") + let m: Manifold = transduce("CEG", "tone") + let _c: Int = check(manifold_is(m), "transduce returns a real Manifold") + let sz: Int = manifold_size(m) + let _c: Int = check(eq_int(sz, 5), "three notes and two intervals are five parts") + let rc: Int = manifold_rel_count(m) + let _c: Int = check(eq_int(rc, 6), "and they stand in six stated relations") - println("the registry keys on modality") - let r2: Int = realizer_register("pulse", "pulse_realizer") - let _c: Int = check(r2, "a second modality registers independently") - let mt: Geometry = transduce("aaa", "tone") - let mp: Geometry = transduce("aaa", "pulse") - let mdt: Int = geometry_dim(mt) - let mdp: Int = geometry_dim(mp) - let _c: Int = check(eq_int(mdt, 4), "tone still routes to its own realizer") - let _c: Int = check(eq_int(mdp, 2), "pulse routes to a different realizer") - let ffm1: Int = geometry_free(mt) - let ffm2: Int = geometry_free(mp) + println("every part is addressable BY KEY, which is what survives persistence") + let i_c: Int = manifold_index_of(m, "note:0") + let _c: Int = check(1 - eq_int(i_c, -1), "the first note is addressable on its own") + let i_iv: Int = manifold_index_of(m, "interval:0-1") + let _c: Int = check(1 - eq_int(i_iv, -1), "so is the interval between the first two") + let miss: Int = manifold_index_of(m, "never_added") + let _c: Int = check(eq_int(miss, -1), "an unknown key is -1, not component 0") - println("no organ is reported as no organ") - // A modality with no realizer must transduce to NOTHING. It must never - // fall back to embedding a description of the signal and calling that - // perception — that silent substitution is the defect this all exists to end. - let eh: Int = realizer_has("echolocation") - let _c: Int = check(1 - eh, "unregistered modality has no organ") - let ge: Geometry = transduce("anything", "echolocation") - let gei: Int = geometry_is(ge) - let _c: Int = check(1 - gei, "no realizer means NO geometry, not fake geometry") + println("parts carry their own geometry, and may differ in width") + let gn: Geometry = manifold_geometry(m, i_c) + let _c: Int = check(eq_int(geometry_dim(gn), 2), "a note component is 2 wide") + let _c: Int = check(near(geometry_get(gn, 0), 67.0), "and it is C — the signal reached the realizer") + let gi: Geometry = manifold_geometry(m, i_iv) + let _c: Int = check(eq_int(geometry_dim(gi), 1), "an interval component is 1 wide") + // A single vector per signal cannot represent parts of unequal width at all. + let _c: Int = check(near(geometry_get(gi, 0), 2.0), "C to E is two semitones") + let f1: Int = geometry_free(gn) + let f2: Int = geometry_free(gi) - println("an unresolvable realizer name fails at WIRING time") - let bad: Int = realizer_register("ghost", "no_such_function_anywhere") - let _c: Int = check(1 - bad, "unresolvable realizer name is a registration failure") - let gh2: Int = realizer_has("ghost") - let _c: Int = check(1 - gh2, "and nothing gets registered") + println("the relations are content no single part carries") + // That "2" above is not a property of C and not a property of E. It exists + // only BETWEEN them, so a representation with no relations cannot hold it. + let spans: Int = 0 + let k: Int = 0 + while k < rc { + if str_eq(manifold_rel_name(m, k), "spans") { + if str_eq(manifold_rel_from(m, k), "interval:0-1") { spans = spans + 1 } + } + k = k + 1 + } + let _c: Int = check(eq_int(spans, 2), "the interval is wired to both notes it spans") - println("a realizer returning non-geometry transduces nothing") - let rb: Int = realizer_register("bogus", "bogus_realizer") - let _c: Int = check(rb, "the symbol resolves, so registration succeeds") - let gb: Geometry = transduce("x", "bogus") - let gbi: Int = geometry_is(gb) - let _c: Int = check(1 - gbi, "contract enforced at the boundary: nothing handed back") + println("relation weight IS the grounding (correspondence-and-censorship §1)") + let wk: Int = 0 + let found: Int = 0 + while wk < rc { + if str_eq(manifold_rel_name(m, wk), "sounds_before") { + if near(manifold_rel_weight(m, wk), 0.8) > 0 { found = 1 } + } + wk = wk + 1 + } + let _c: Int = check(found, "the ordering relation carries the weight its realizer stated") - println("norm lets a caller check a realizer emitted signal, not zeros") - let gn: Geometry = geometry_new(2) - let _c: Int = check(near(geometry_norm(gn), 0.0), "a fresh geometry is zero — norm says so") - let n0: Int = geometry_set(gn, 0, 3.0) - let n1: Int = geometry_set(gn, 1, 4.0) - let _c: Int = check(near(geometry_norm(gn), 5.0), "3-4-5: norm is 5") - let ffn: Int = geometry_free(gn) + println("the decomposition persists as real, separately addressable nodes") + let ids: [String] = el_list_empty() + let n0: Int = engram_node_count() + let e0: Int = engram_edge_count() + let pi: Int = 0 + while pi < sz { + let key: String = manifold_key(m, pi) + let g: Geometry = manifold_geometry(m, pi) + let id: String = engram_node("component " + key, "Concept", 0.6) + let att: Int = node_attach_geometry(id, g) + ids = el_list_append(ids, id) + let ff: Int = geometry_free(g) + pi = pi + 1 + } + let ri: Int = 0 + while ri < rc { + let fi: Int = manifold_index_of(m, manifold_rel_from(m, ri)) + let ti: Int = manifold_index_of(m, manifold_rel_to(m, ri)) + engram_connect(el_list_get(ids, fi), el_list_get(ids, ti), + manifold_rel_weight(m, ri), manifold_rel_name(m, ri)) + ri = ri + 1 + } + let _c: Int = check(eq_int(engram_node_count() - n0, 5), "one signal became five nodes") + let _c: Int = check(eq_int(engram_edge_count() - e0, 6), "and six edges between them") + + println("each part's geometry is independently readable back off its node") + let id_c: String = el_list_get(ids, manifold_index_of(m, "note:0")) + let id_iv: String = el_list_get(ids, manifold_index_of(m, "interval:0-1")) + let _c: Int = check(eq_int(node_geometry_dim(id_c), 2), "note:0 node carries a 2-wide geometry") + let _c: Int = check(eq_int(node_geometry_dim(id_iv), 1), "interval:0-1 node carries a 1-wide one") + + println("one part can be grounded without touching its siblings") + let ear: String = engram_node("evidence: heard a C in the recording", "Memory", 0.7) + engram_connect(ear, id_c, 0.95, "corroborates") + let _c: Int = check(engram_edge_between(ear, id_c), "evidence attaches to note:0 specifically") + let id_g: String = el_list_get(ids, manifold_index_of(m, "note:2")) + let _c: Int = check(1 - engram_edge_between(ear, id_g), "and NOT to note:2 — the sibling is untouched") + // This is the whole gain, and it is impossible with a fingerprint: with one + // node per signal, "the C is corroborated" and "the G is not" have the same + // grounding target and cannot both be recorded. + let _c: Int = check(eq_int(node_geometry_dim(id_g), 2), "note:2 geometry is intact regardless") + + println("a fingerprint realizer transduces NOTHING") + // #144's contract exactly: signal in, one Geometry out. It resolves, so the + // organ is present — but it does not decompose, so it does not transduce. + // "No organ" and "an organ that only fingerprints" must not look alike. + let rf: Int = realizer_register("fingerprint", "fingerprint_realizer") + let _c: Int = check(rf, "the symbol resolves, so registration succeeds") + let mf: Manifold = transduce("x", "fingerprint") + let _c: Int = check(1 - manifold_is(mf), "a single vector is not a transduction") + + println("the one-part case is a size-one manifold, not a bare vector") + let g1: Geometry = geometry_new(3) + let s1: Int = geometry_set(g1, 0, 5.0) + let ms: Manifold = manifold_single("level", "scalar", g1) + let _c: Int = check(manifold_is(ms), "manifold_single yields a real Manifold") + let _c: Int = check(eq_int(manifold_size(ms), 1), "of size one — visibly degenerate, not hidden") + let fg: Int = geometry_free(g1) + let fs: Int = manifold_free(ms) + + println("no organ is still reported as no organ") + let me: Manifold = transduce("anything", "echolocation") + let _c: Int = check(1 - manifold_is(me), "no realizer means no manifold, not a fake one") + + let fm: Int = manifold_free(m) // Reaching here means nothing called exit(1) along the way. println("")