@hviana/sema 0.8.3 → 0.8.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/AGENTS.md +11 -10
  2. package/README.md +17 -38
  3. package/dist/example/demo.js +85 -34
  4. package/dist/src/geometry.d.ts +0 -10
  5. package/dist/src/geometry.js +0 -12
  6. package/dist/src/meter.d.ts +11 -0
  7. package/dist/src/meter.js +11 -0
  8. package/dist/src/mind/articulation.js +1 -1
  9. package/dist/src/mind/attention.js +2 -1
  10. package/dist/src/mind/derivation.d.ts +201 -0
  11. package/dist/src/mind/derivation.js +327 -0
  12. package/dist/src/mind/graph-search.d.ts +2 -1
  13. package/dist/src/mind/graph-search.js +37 -15
  14. package/dist/src/mind/match.d.ts +2 -0
  15. package/dist/src/mind/match.js +2 -0
  16. package/dist/src/mind/mechanisms/alu.js +0 -2
  17. package/dist/src/mind/mechanisms/cast.d.ts +1 -5
  18. package/dist/src/mind/mechanisms/cast.js +15 -18
  19. package/dist/src/mind/mechanisms/confluence.d.ts +0 -3
  20. package/dist/src/mind/mechanisms/confluence.js +3 -9
  21. package/dist/src/mind/mechanisms/cover.js +17 -20
  22. package/dist/src/mind/mechanisms/extraction.d.ts +0 -1
  23. package/dist/src/mind/mechanisms/extraction.js +13 -8
  24. package/dist/src/mind/mechanisms/prefix-completion.js +0 -1
  25. package/dist/src/mind/mechanisms/recall.d.ts +0 -1
  26. package/dist/src/mind/mechanisms/recall.js +8 -9
  27. package/dist/src/mind/mechanisms/reference.js +3 -4
  28. package/dist/src/mind/pipeline-mechanism.d.ts +1 -4
  29. package/dist/src/mind/pipeline.js +106 -41
  30. package/dist/src/mind/rationale.d.ts +0 -11
  31. package/dist/src/mind/rationale.js +6 -32
  32. package/dist/src/mind/reasoning.d.ts +4 -30
  33. package/dist/src/mind/reasoning.js +183 -151
  34. package/dist/src/mind/types.js +6 -3
  35. package/docs/INDEX.md +23 -24
  36. package/docs/INVARIANTS.md +16 -17
  37. package/docs/architecture/bounded-reads.md +4 -4
  38. package/docs/architecture/closure.md +65 -0
  39. package/docs/architecture/commonality.md +27 -18
  40. package/docs/architecture/cost-model.md +5 -5
  41. package/docs/architecture/exact-vs-approximate.md +4 -4
  42. package/docs/architecture/factored-machinery.md +14 -14
  43. package/docs/architecture/mechanism-market.md +9 -9
  44. package/docs/architecture/meter.md +4 -5
  45. package/docs/architecture/store.md +2 -2
  46. package/docs/architecture/thresholds.md +1 -1
  47. package/docs/failures/tempting-but-wrong.md +11 -1
  48. package/docs/harness/gates.md +6 -6
  49. package/docs/mechanisms/cover.md +2 -2
  50. package/example/demo.ts +90 -37
  51. package/jsr.json +1 -1
  52. package/package.json +1 -1
  53. package/src/geometry.ts +0 -13
  54. package/src/meter.ts +11 -0
  55. package/src/mind/articulation.ts +0 -1
  56. package/src/mind/attention.ts +2 -1
  57. package/src/mind/derivation.ts +473 -0
  58. package/src/mind/graph-search.ts +37 -20
  59. package/src/mind/match.ts +2 -0
  60. package/src/mind/mechanisms/alu.ts +0 -2
  61. package/src/mind/mechanisms/cast.ts +17 -21
  62. package/src/mind/mechanisms/confluence.ts +3 -13
  63. package/src/mind/mechanisms/cover.ts +17 -20
  64. package/src/mind/mechanisms/extraction.ts +13 -9
  65. package/src/mind/mechanisms/prefix-completion.ts +0 -1
  66. package/src/mind/mechanisms/recall.ts +7 -9
  67. package/src/mind/mechanisms/reference.ts +2 -3
  68. package/src/mind/pipeline-mechanism.ts +1 -4
  69. package/src/mind/pipeline.ts +121 -46
  70. package/src/mind/rationale.ts +6 -36
  71. package/src/mind/reasoning.ts +208 -178
  72. package/src/mind/types.ts +5 -2
  73. package/test/133-the-decision-point-renders-the-state.test.mjs +204 -0
  74. package/test/134-the-law-explains-the-engines-own-refusal.test.mjs +237 -0
  75. package/test/135-one-law-any-producer.test.mjs +289 -0
  76. package/test/136-the-two-named-limits.test.mjs +205 -0
  77. package/test/137-the-law-lives-once-and-below.test.mjs +400 -0
  78. package/test/138-the-remainder-drains-only-what-a-move-declares.test.mjs +62 -0
  79. package/test/139-the-witness-is-engagement-not-explanation.test.mjs +51 -0
  80. package/test/140-irrelevant-supply-does-not-change-an-answer.test.mjs +48 -0
  81. package/test/141-the-question-is-paid-at-construction.test.mjs +98 -0
  82. package/test/36-already-answered-fusion.test.mjs +20 -2
  83. package/test/37-cluster-dispersion-fusion.test.mjs +30 -3
  84. package/test/38-reason-restate-guard.test.mjs +22 -2
  85. package/test/55-cost-meter.test.mjs +4 -1
package/AGENTS.md CHANGED
@@ -55,14 +55,15 @@ Five invariants. Violate one and the system degrades silently — tests pin them
55
55
  | 4 | One cost currency | Single ladder `MICRO`/`STEP`/`CONCEPT`/`PASS`; `weight = moves + PASS·unaccounted`; compare at `STEP` grade | `docs/architecture/cost-model.md` → `src/mind/graph-search.ts`, `src/derive/` |
56
56
  | 5 | Bounded reads | No per-query read grows with N; cap is `hubBound = √N` enforced at the store via `LIMIT` reads, existence probes, and `bytesPrefix` caps | `docs/architecture/bounded-reads.md` → `src/store.ts`, `src/mind/traverse.ts` |
57
57
 
58
- Cross-cutting contracts (single-definition, import everywhere): `contentLevels`
59
- in `src/geometry.ts` is the one boundary rule; `src/mind/canonical.ts` is the
60
- write/read contract for canonical segmentation; `src/mind/junction.ts` is the
61
- shared content-addressed ascent; `Precomputed` in
62
- `src/mind/pipeline-mechanism.ts` is the per-response lazy memo; `src/meter.ts`
63
- is the write-only work accounting surface. See `docs/INDEX.md` for the full
64
- contract table and `docs/architecture/factored-machinery.md` for ownership.
65
- Tie-breaks are corpus-determined, but not interchangeable (`determinism.md`).
58
+ Cross-cutting contracts (single-definition, imported everywhere):
59
+ `contentLevels` in `src/geometry.ts` is the one boundary rule;
60
+ `src/mind/derivation.ts` is the closure law; `src/mind/canonical.ts` is the
61
+ canonical segmentation contract; `src/mind/junction.ts` is the shared
62
+ content-addressed ascent; `Precomputed` in `src/mind/pipeline-mechanism.ts` is
63
+ the per-response memo; `src/meter.ts` is the write-only work accounting surface.
64
+ See `docs/INDEX.md` and `factored-machinery.md` for the contract table and
65
+ ownership. Tie-breaks are corpus-determined, not interchangeable
66
+ (`determinism.md`).
66
67
 
67
68
  ## 3. Where things live
68
69
 
@@ -97,8 +98,8 @@ methods; `mind.ts` is a thin assembly.
97
98
  ### Add a grounding mechanism or extension
98
99
 
99
100
  Implement `PipelineMechanism` (`floor` → admissible bound or `null`; `run` →
100
- candidates with `bytes`/`accounted`/`moves`/`unexplained` + optional
101
- `scaffolding`/`complete`/`used`). Register via
101
+ candidates with `bytes`/`accounted`/`moves` + optional
102
+ `scaffolding`/`complete`/`used`/`provenance`). Register via
102
103
  `new Mind({ mechanismFactories: [host => yourMechanism(host)] })`. Verify the
103
104
  four market constraints (decoupled, declared competence, visible budget,
104
105
  evidence travels). → `docs/architecture/mechanism-market.md`
package/README.md CHANGED
@@ -179,39 +179,16 @@ in the same pass — reasons onward to a separate fact about that painter. Nothi
179
179
  in the reply but the painter's own name comes from the question.
180
180
 
181
181
  ```ts
182
- // demo.ts — one short session that drives the WHOLE pipeline from one memory.
183
-
184
- import { Mind } from "../src/index.js";
185
- import { SQliteStore } from "../src/store-sqlite.js";
186
-
187
- async function main(): Promise<void> {
188
- const mind = new Mind({ store: new SQliteStore({ path: ":memory:" }) });
189
- const ask = async (q: string) => (await mind.respondText(q)).trim();
190
-
191
- // ── Jot down what we know. Each line is just (context → what follows). ──
192
- await mind.ingest([
193
- // One relation, shown three times — a pattern taught purely by example:
194
- ["The Mona Lisa was painted by Leonardo da Vinci.", "Leonardo da Vinci"],
195
- ["The Starry Night was painted by Vincent van Gogh.", "Vincent van Gogh"],
196
- [
197
- "The Night Watch was painted by Rembrandt van Rijn.",
198
- "Rembrandt van Rijn",
199
- ],
200
- // One stray fact, keyed on a name none of the examples mention:
201
- ["Pablo Picasso", "Pablo Picasso co-founded the Cubist movement"],
202
- ]);
203
-
204
- // 1) GENERALIZE — apply the learned pattern to an unseen sentence and read out
205
- // the painter, then keep going into what is known about him.
206
- console.log(await ask("The Weeping Woman was painted by Pablo Picasso."));
207
-
208
- // 2) COMPUTE — exact arithmetic, grounded right where the notes go silent.
209
- console.log(await ask("a museum charges 12*4 for a family ticket"));
210
-
211
- await mind.store.close();
212
- }
213
-
214
- main();
182
+ // demo.ts — a corpus goes in, and the memory is read back out.
183
+
184
+ import { Mind, SQliteStore } from "../src/index.js";
185
+
186
+ const mind = new Mind({ store: new SQliteStore({ path: ":memory:" }) });
187
+ await mind.ingest(CORPUS); // (context -> what follows) notes, the deposit shape
188
+
189
+ mind.sampleCorpus(4); // what the memory HOLDS
190
+ mind.searchCorpusText("Pablo Picasso"); // which notes a question REACHES
191
+ await mind.respond("The Weeping Woman was painted by Pablo Picasso.");
215
192
  ```
216
193
 
217
194
  ```text
@@ -224,7 +201,7 @@ Ask for the receipt instead of the text, and each answer says how it was reached
224
201
  the route, and, on request, the complete replayable trace behind it:
225
202
 
226
203
  ```text
227
- "The Weeping Woman was painted by Pablo Picasso." → provenance: cast
204
+ "The Weeping Woman was painted by Pablo Picasso." → provenance: cover
228
205
  ( structure carried across the three worked examples )
229
206
 
230
207
  "a museum charges 12*4 for a family ticket" → provenance: cover
@@ -233,10 +210,12 @@ the route, and, on request, the complete replayable trace behind it:
233
210
 
234
211
  > [!NOTE]
235
212
  > This is **[example/demo.ts](example/demo.ts)** — run it with `npm run demo`.
236
- > The first question names a painting Sema was never shown, and asks nothing
237
- > explicit; what comes back is a fact about Cubism that appears **nowhere** in
238
- > it. The second is exact, not a plausible-looking guess. Every step traces back
239
- > to the four notes above.
213
+ > It reads the memory back two ways: `sampleCorpus` browses what it holds, and
214
+ > `searchCorpusText` reports which stored notes a question reaches — exactly, so
215
+ > a question overlapping nothing is answered with a note saying so, never with
216
+ > an invention. The first answer names a painting Sema was never shown and still
217
+ > returns a fact about Cubism that appears **nowhere** in it; the second is
218
+ > computed. Every step traces back to the five notes above.
240
219
 
241
220
  ---
242
221
 
@@ -1,39 +1,90 @@
1
- // demo.ts — one short session that drives the WHOLE pipeline from one memory.
1
+ // demo.ts — a corpus goes in, and the memory is read back out.
2
2
  //
3
- // We give Sema a handful of plain notes, then ask things that no single note
4
- // answers. The headline query is the third one: from three worked examples Sema
5
- // learns the shape of "X was painted by Y", lifts the painter out of a sentence
6
- // it has NEVER seen, and then — in the same pass — reasons forward to a separate
7
- // fact about that painter. The reply contains no word from the question. That is
8
- // retrieval, generalization, and reasoning composing as a single act, with every
9
- // step traceable back to the notes behind it.
10
- import { Mind } from "../src/index.js";
11
- import { SQliteStore } from "../src/store-sqlite.js";
3
+ // Sema is given a small corpus of plain notes, each one the shape every deposit
4
+ // has: a context, and what follows it. Then the memory is read two ways — what
5
+ // it HOLDS (`sampleCorpus`), and which of its notes a question REACHES
6
+ // (`searchCorpusText`). Both run through the same content-addressed machinery an
7
+ // answer uses (src/mind/corpus.ts); nothing is indexed and nothing is written.
8
+ //
9
+ // The search addresses content EXACTLY, not by keyword: a question reaches a
10
+ // note when it shares chunk-aligned content with it, so a question with no such
11
+ // overlap is reported as exactly that — a STATE, rendered by the text layer
12
+ // (`CorpusTextResult.note`), never as prose the engine invented.
13
+ //
14
+ // The last act is two ordinary answers, each with its derivation streamed as it
15
+ // unfolds, the PROVENANCE that names the route it grounded on, and the work it
16
+ // cost read off the meter: the rationale and the meter ARE the explanation
17
+ // surface (AGENTS.md §6).
18
+ import { decodeText, formatReport, Mind, SQliteStore } from "../src/index.js";
19
+ // One relation shown three times — a pattern taught purely by example — plus a
20
+ // stray fact keyed on a name none of the examples mention.
21
+ const CORPUS = [
22
+ ["The Mona Lisa was painted by Leonardo da Vinci.", "Leonardo da Vinci"],
23
+ ["The Starry Night was painted by Vincent van Gogh.", "Vincent van Gogh"],
24
+ [
25
+ "The Night Watch was painted by Rembrandt van Rijn.",
26
+ "Rembrandt van Rijn",
27
+ ],
28
+ ["Pablo Picasso", "Pablo Picasso co-founded the Cubist movement"],
29
+ ["The Weeping Woman was painted by Pablo Picasso.", "Pablo Picasso"],
30
+ ];
31
+ // Questions the corpus can address, and one it cannot — the honest miss.
32
+ const QUERIES = [
33
+ "The Mona Lisa was painted by Leonardo da Vinci.",
34
+ "Pablo Picasso",
35
+ "xylophone",
36
+ ];
37
+ // One question answered by composing across the notes, and one answered by
38
+ // computing: the two routes the corpus search does not take.
39
+ const ASKS = [
40
+ "The Weeping Woman was painted by Pablo Picasso.",
41
+ "a museum charges 12*4 for a family ticket",
42
+ ];
12
43
  async function main() {
13
- const mind = new Mind({ store: new SQliteStore({ path: ":memory:" }) });
14
- const ask = async (q) => (await mind.respondText(q)).trim();
15
- // ── Jot down what we know. Each line is just (context → what follows). ──
16
- await mind.ingest([
17
- // One relation, shown three times — a pattern taught purely by example:
18
- ["The Mona Lisa was painted by Leonardo da Vinci.", "Leonardo da Vinci"],
19
- ["The Starry Night was painted by Vincent van Gogh.", "Vincent van Gogh"],
20
- [
21
- "The Night Watch was painted by Rembrandt van Rijn.",
22
- "Rembrandt van Rijn",
23
- ],
24
- // One stray fact, keyed on a name none of the examples mention:
25
- ["Pablo Picasso", "Pablo Picasso co-founded the Cubist movement"],
26
- ]);
27
- // 1) GENERALIZE — apply the learned pattern to an unseen sentence and read out
28
- // the painter. "Pablo Picasso" was never given as an answer; Sema locates it
29
- // by analogy to the three examples.
30
- console.log(await ask("The Weeping Woman was painted by Pablo Picasso."));
31
- // → "Pablo Picasso co-founded the Cubist movement"
32
- // …and, having found the painter, it KEEPS GOING: the name bridges into the
33
- // one fact it holds about him. The answer appears in no word of the question.
34
- // 2) COMPUTE — exact arithmetic, grounded right where the notes go silent.
35
- console.log(await ask("a museum charges 12*4 for a family ticket"));
36
- // → "48"
44
+ const mind = new Mind({
45
+ store: new SQliteStore({ path: ":memory:" }),
46
+ profile: true,
47
+ });
48
+ await mind.ingest(CORPUS);
49
+ // 1) WHAT THE MEMORY HOLDS — real pairs, browsed, no query and no random draw.
50
+ console.log("— the corpus, as the memory holds it —");
51
+ for (const p of mind.sampleCorpus(4).pairs) {
52
+ console.log(` ${decodeText(p.context)} → ${decodeText(p.continuation)}`);
53
+ }
54
+ // 2) SEARCH — which stored notes does a question reach? A question that
55
+ // addresses the corpus answers with pairs; one that shares nothing with it
56
+ // answers with a note saying so.
57
+ for (const q of QUERIES) {
58
+ const r = mind.searchCorpusText(q, 3);
59
+ console.log(`\n— "${q}" — ${r.resolved} resolved / ${r.reached} reached`);
60
+ if (r.note !== undefined)
61
+ console.log(` ${r.note}`);
62
+ for (const p of r.pairs) {
63
+ console.log(` ${p.context} → ${p.continuation} (${p.matchedBytes} matched)`);
64
+ }
65
+ }
66
+ // 3) ANSWERS, WITH THEIR DERIVATION — the same pipeline, read as data. Steps
67
+ // repeat (recognise re-enters under every mechanism that needs it), so each
68
+ // distinct mechanism-and-note is printed once, in the order it first ran.
69
+ for (const q of ASKS) {
70
+ const seen = new Set();
71
+ const trace = [];
72
+ const r = await mind.respond(q, (s) => {
73
+ const line = `${s.mechanism.join(" › ")}${s.note ? ` — ${s.note}` : ""}`;
74
+ if (seen.has(line))
75
+ return;
76
+ seen.add(line);
77
+ trace.push(`${" ".repeat(Math.max(0, s.mechanism.length - 1))}${line}`);
78
+ });
79
+ console.log(`\n— "${q}" — ${r.provenance ?? "no answer"}`);
80
+ console.log(` ${decodeText(r.bytes).trim()}`);
81
+ console.log("— how —");
82
+ for (const s of trace)
83
+ console.log(s);
84
+ if (mind.lastCost !== null) {
85
+ console.log(`— what it cost —\n${formatReport(mind.lastCost)}`);
86
+ }
87
+ }
37
88
  await mind.store.close();
38
89
  }
39
90
  main();
@@ -128,16 +128,6 @@ export declare function profileCapacity(D: number): number;
128
128
  * root.
129
129
  */
130
130
  export declare function consensusFloor(N: number): number;
131
- /** The coverage bar for the reach (interior) index, when vector-similarity
132
- * gating is used. Returns the concept threshold — the structural midpoint
133
- * (~0.5 at D=1024) where two forms are "more similar than not."
134
- *
135
- * Currently UNUSED in the hot training path: interior nodes are indexed
136
- * unconditionally (hash-cons dedup bounds the index naturally).
137
- * Post-hoc structural compaction ({@link Store.compactContentIndex})
138
- * replaces runtime coverage gating with a batch pass that removes
139
- * structurally-isolated entries. Derived, never tuned. */
140
- export declare function coverageBar(_maxGroup: number, D: number): number;
141
131
  export interface Folded {
142
132
  tree: Sema;
143
133
  /** Byte length of the subtree — carried incrementally so the stable-prefix
@@ -167,18 +167,6 @@ export function profileCapacity(D) {
167
167
  export function consensusFloor(N) {
168
168
  return Math.log(N) + 1 / 2;
169
169
  }
170
- /** The coverage bar for the reach (interior) index, when vector-similarity
171
- * gating is used. Returns the concept threshold — the structural midpoint
172
- * (~0.5 at D=1024) where two forms are "more similar than not."
173
- *
174
- * Currently UNUSED in the hot training path: interior nodes are indexed
175
- * unconditionally (hash-cons dedup bounds the index naturally).
176
- * Post-hoc structural compaction ({@link Store.compactContentIndex})
177
- * replaces runtime coverage gating with a batch pass that removes
178
- * structurally-isolated entries. Derived, never tuned. */
179
- export function coverageBar(_maxGroup, D) {
180
- return conceptThreshold(D);
181
- }
182
170
  // ---- folding ----
183
171
  //
184
172
  // The river fold is a hierarchical prefix network: each level contracts
@@ -205,6 +205,17 @@ export declare class Meter {
205
205
  * this is that fact, accumulated. Read with {@link reasonSteps}: one is the
206
206
  * price, the other the explanation. */
207
207
  reasonCarriedBytes: number;
208
+ /** Bytes of the question's REMAINDER a step CONSUMED — the drop the law's own
209
+ * `advance` makes when a declared move carries the material it accounts for.
210
+ * Read with {@link reasonSteps} and {@link reasonCarriedBytes}: carrying is
211
+ * the engagement, this is the consumption, and before it the second was
212
+ * invisible. */
213
+ closureDrainedBytes: number;
214
+ /** Bytes of the question the grounding PRICED but whose material its answer does
215
+ * NOT carry, at or above one quantum — the debt the construction leaves for the
216
+ * walk to pay by carrying it. Zero means the grounding's coverage is honest:
217
+ * everything it priced is either held by the answer or under the W floor. */
218
+ groundingWithheldBytes: number;
208
219
  /** Branch-node probes the pivot sweep actually spent looking for the learnt
209
220
  * context an answer contains (one `resonate` per probe). The untraced view
210
221
  * of what the multi-hop's shortlist costs. */
package/dist/src/meter.js CHANGED
@@ -215,6 +215,17 @@ export class Meter {
215
215
  * this is that fact, accumulated. Read with {@link reasonSteps}: one is the
216
216
  * price, the other the explanation. */
217
217
  reasonCarriedBytes = 0;
218
+ /** Bytes of the question's REMAINDER a step CONSUMED — the drop the law's own
219
+ * `advance` makes when a declared move carries the material it accounts for.
220
+ * Read with {@link reasonSteps} and {@link reasonCarriedBytes}: carrying is
221
+ * the engagement, this is the consumption, and before it the second was
222
+ * invisible. */
223
+ closureDrainedBytes = 0;
224
+ /** Bytes of the question the grounding PRICED but whose material its answer does
225
+ * NOT carry, at or above one quantum — the debt the construction leaves for the
226
+ * walk to pay by carrying it. Zero means the grounding's coverage is honest:
227
+ * everything it priced is either held by the answer or under the W floor. */
228
+ groundingWithheldBytes = 0;
218
229
  /** Branch-node probes the pivot sweep actually spent looking for the learnt
219
230
  * context an answer contains (one `resonate` per probe). The untraced view
220
231
  * of what the multi-hop's shortlist costs. */
@@ -96,7 +96,7 @@ export async function articulate(ctx, answer, query) {
96
96
  s.end,
97
97
  ])),
98
98
  ]);
99
- const solved = ctx.search.cover(answer.length, voicedSites, new Map(), ans.leaves, ans.splits, ans.starts, substitutions, undefined, undefined, ctx.trace ? (steps) => traceDerivation(ctx, steps) : undefined);
99
+ const solved = ctx.search.cover(answer.length, voicedSites, new Map(), ans.leaves, ans.splits, substitutions, undefined, undefined, ctx.trace ? (steps) => traceDerivation(ctx, steps) : undefined);
100
100
  const segs = solved && solved.segs;
101
101
  tArtCover?.done(segs === null
102
102
  ? []
@@ -15,6 +15,7 @@ import { leafIdRun } from "./canonical.js";
15
15
  import { atomIsHub, corpusN, edgeAncestors, hubBound, sharedReachMemo, } from "./traverse.js";
16
16
  import { cachedRead, junctionContainersFrom, junctionSeeds, junctionSynonyms, loadJunctionSynonymSides, walkCache, } from "./junction.js";
17
17
  import { indexOf } from "../bytes.js";
18
+ import { restates } from "./derivation.js";
18
19
  import { rItem, rNode, traceDerivation } from "./trace.js";
19
20
  function newTraceDraft(perceivedCount) {
20
21
  return {
@@ -2279,7 +2280,7 @@ async function crossRegionVotes(ctx, query, regions, rvs, k, N, reachMemo, td) {
2279
2280
  const ri = indexOf(bytes, right, 0);
2280
2281
  if (li >= 0 && ri >= 0) {
2281
2282
  const joined = bytes.subarray(Math.min(li, ri), Math.max(li + left.length, ri + right.length));
2282
- if (indexOf(query, joined, 0) >= 0) {
2283
+ if (restates(query, joined, 0)) {
2283
2284
  if (structuralTrace)
2284
2285
  structuralTrace.selfEvidenceRejected++;
2285
2286
  continue; // query says it itself
@@ -0,0 +1,201 @@
1
+ /** A half-open `[start, end)` span of the asker's own bytes. */
2
+ export type Span = readonly [number, number];
3
+ /** The BYTE COUNT of a span list — what the currency calls `unaccounted` in
4
+ * `weight = moves + PASS·unaccounted`. ONE definition: this was four copies of
5
+ * the same `reduce` before the architecture audit collapsed them. */
6
+ export declare function unaccountedBytes(spans: ReadonlyArray<Span>): number;
7
+ /** The `[start, end)` gaps of `[0, queryLen)` NOT covered by `accounted` — the
8
+ * union-of-spans reading the ladder prices at PASS per byte, and the raw
9
+ * material every closure decision measures. Clipped to the question, sorted
10
+ * and merged, so two overlapping spans account for their union once. */
11
+ export declare function unexplainedSpans(queryLen: number, accounted: ReadonlyArray<Span>): Array<[number, number]>;
12
+ /** THE REMAINDER: what no step has accounted for, with every span below one
13
+ * river-fold quantum dropped. `W` is the mind's own line between bridging
14
+ * punctuation and a substantive phrase — the same floor `liftedScaffolding`
15
+ * and the honesty-density bar use — so a remainder under it licenses nothing
16
+ * and blocks nothing. This is the law's measure. */
17
+ export declare function remainderOf(queryLen: number, explained: ReadonlyArray<Span>, W: number): Array<[number, number]>;
18
+ /** A WITNESS — what a transition carries, in one reading: the SPAN it accounts
19
+ * for, and the WINDOW of the question the product itself holds. The window is
20
+ * present only when the product holds question material, and it is the ONLY
21
+ * thing the question's remainder may be consumed by. */
22
+ export interface Witness {
23
+ readonly span: Span;
24
+ readonly window?: Span;
25
+ }
26
+ /** The window of `span` that `product` holds, or null: the ONE reading of
27
+ * coverage — used by {@link carries}, by the move branch, and by the GROUNDING
28
+ * when it decides what its answer has actually paid for. */
29
+ export declare function windowOf(span: Span, product: Uint8Array, query: Uint8Array, W: number): Span | null;
30
+ /** PROGRESS, by coverage: the first member of `remainder` that `product` carries
31
+ * a whole quantum of, or null when it carries none. The window is taken from
32
+ * `query`, the asker's own bytes, so the test is "this product restates a
33
+ * quantum of what was left unaccounted", never a similarity score.
34
+ *
35
+ * One witness per step, deterministically the FIRST in remainder order: the
36
+ * measure stays a single member of a finite list, which is what makes the walk
37
+ * reviewable — and, because the remainder is not drained, it is the walker's
38
+ * cycle protection (not this) that terminates a chain. */
39
+ export declare function carries(remainder: ReadonlyArray<Span>, product: Uint8Array, query: Uint8Array, W: number): Array<Witness> | null;
40
+ /** Whether `bytes` RESTATES the question — says nothing the asker did not just
41
+ * say — and is therefore not an answer. This is a closure condition: a
42
+ * derivation whose product is already the question has added nothing, and the
43
+ * engine asks it in five places. ONE definition, asked everywhere, with the
44
+ * DIFFERENCES between those places supplied as WITNESSES by the caller — never
45
+ * as a mechanism or a producer. If this function ever needs to know who
46
+ * produced the bytes to decide, the right conclusion is that a witness is
47
+ * missing, not that it should dispatch.
48
+ *
49
+ * `floor` is one river-fold quantum: below it, byte overlap is chance, not
50
+ * evidence — the same line `identityBar`, the bridge's `attestedQ` and
51
+ * recognition's site floor all draw. `0` disables the floor, which is the
52
+ * reading the callers that ask before any structure exists use.
53
+ *
54
+ * THE THREE READINGS the callers need, and why each is a witness rather than a
55
+ * branch here:
56
+ *
57
+ * • `proper` — a PROPER part of the question (strictly shorter). This is the
58
+ * reading every tier that rejects a fragment uses.
59
+ * • `whole` — the EQUALITY reading: only "the answer IS the question" counts,
60
+ * because the caller has already handled a proper fragment elsewhere (a
61
+ * recall tier's own subspan tests).
62
+ * • `equate` — the response's own notion of "the same text" (whatever
63
+ * `src/canon.ts` equates: case, width, whitespace). A caller that has one
64
+ * passes it; a caller that does not gets the byte-exact reading. It is the
65
+ * same fallback `resolve` already makes when an exact lookup misses.
66
+ *
67
+ * The LITERAL EXEMPTION is deliberately NOT here: whether a span is the site's
68
+ * own bytes at its own position is the CALLER's knowledge, and a caller states
69
+ * it by not asking (see `segRestatesQuery` in types.ts, which returns false for
70
+ * a literal span before reaching this). */
71
+ export declare function restates(query: Uint8Array, bytes: Uint8Array, floor?: number, witnesses?: {
72
+ equate?: ((b: Uint8Array) => Uint8Array) | null;
73
+ proper?: boolean;
74
+ whole?: boolean;
75
+ /** THE POSITIONAL WITNESS: search from this offset, because the caller has
76
+ * established that only material at or after it counts. A transcript pasted
77
+ * into a single response is the case that needs it — a caller's own prior
78
+ * answer lies LATER in the query, after the root that would restate it — and
79
+ * the reasoner's per-root `alreadyAnswered` guard asks exactly that question.
80
+ * Omitted, the search starts at 0 and the reading is the plain one. */
81
+ from?: number;
82
+ }): boolean;
83
+ /** Whether the query span `[from, to)` lies inside a COMPLETED ASSISTANT TURN —
84
+ * material the engine has already produced, so it is context rather than
85
+ * something the asker is asserting. Recognition and attention still see the
86
+ * full transcript; what excludes these spans is the closure reading "this was
87
+ * already answered", and it is a closure reading rather than a budget: a window
88
+ * inside a prior reply is not a fresh constraint.
89
+ *
90
+ * ONE definition of it. `cursor` is the CALLER's own progress through `turns`
91
+ * (they are ascending and each caller scans its candidates in ascending order),
92
+ * so the amortised search is preserved exactly and a caller passes the same
93
+ * holder for a whole scan: extracting the reading must not cost the scan. */
94
+ export declare function insideAnsweredTurn(turns: ReadonlyArray<Span>, cursor: {
95
+ at: number;
96
+ }, from: number, to: number): boolean;
97
+ /** THE derivation state — the unit that crosses one inference.
98
+ *
99
+ * Every field is read by the law or by the market's one cost ladder, and
100
+ * nothing else travels. A count of steps is a consequence (the cost), and
101
+ * cycle protection belongs to the layer that walks a graph. */
102
+ export interface DerivationState {
103
+ /** PRODUCT — the structure produced: what this derivation stands on. */
104
+ readonly product: Uint8Array;
105
+ /** ACCOUNTED — the asker's spans the producing transition priced. A COST
106
+ * quantity, and the producing mechanism's own judgement of what its answer
107
+ * explains: cover leaves its computed spans out so the PASS-bridged bytes
108
+ * they account for stay charged, while a corroborated substitution DOES
109
+ * account for its span, because the mechanism paid a move for it. */
110
+ readonly accounted: ReadonlyArray<Span>;
111
+ /** REMAINDER — the asker's material no step has accounted for, each member at
112
+ * or above one quantum. Empty means the derivation is CLOSED. */
113
+ readonly remainder: ReadonlyArray<Span>;
114
+ /** COST — position on the one ladder (`graph-search.ts`'s MICRO/STEP/CONCEPT/
115
+ * PASS); the market takes the lattice minimum over it. */
116
+ readonly cost: number;
117
+ /** FIXED — the producer SUPPLIED a fixed point: the query IS the context, so
118
+ * no transition may consume this state. Declared, never inferred. */
119
+ readonly fixed?: boolean;
120
+ /** USED — what the product speaks for. An EMPTY set is itself a declaration
121
+ * ("this answer voices nothing"); omitted means the layer must re-recognise
122
+ * the product to decide for itself. */
123
+ readonly used?: ReadonlySet<number>;
124
+ }
125
+ /** A candidate continuation, as reported by the layer that knows the structure.
126
+ * The layer says what it has; the law decides. */
127
+ export interface Continuation {
128
+ /** The structure the transition would make the derivation's product. */
129
+ readonly product: Uint8Array;
130
+ /** CONTAINS — the transition's structure holds the product: a node in its
131
+ * tree, or one contiguous byte run of it. Resolved by the reporter.
132
+ *
133
+ * SUFFICIENT FOR EVERY DECISION THIS CORE MAKES, and a boolean is the minimum:
134
+ * the law reads it ONCE, as the admission gate, and that decision is binary —
135
+ * may this state be consumed by this transition at all? Every other decision
136
+ * is fed by other witnesses, never by this one: the product's identity is
137
+ * `resolve(product)`, progress is the window a move carries or the
138
+ * `reaches` declaration, accounting is the span. Carrying the reporter's
139
+ * structure here would therefore be a dump of mechanism internals bought for
140
+ * nothing. The producers make it true by construction — a continuation is
141
+ * built from the CURRENT product's own structure, never from a different one
142
+ * — and test/133 pins the refusal when a reporter declares false. */
143
+ readonly contains: boolean;
144
+ /** REACHES — the transition MOVES: it reaches structure this derivation has
145
+ * not consumed
146
+ * (a node outside the walker's own set). The second species of progress: a
147
+ * step need not excuse itself with question material when it moves to new
148
+ * structure. Resolved by the reporter, declared by the transition — never
149
+ * inferred from its producer. */
150
+ readonly reaches?: boolean;
151
+ /** What the transition accounts for, when it declares it. A transition
152
+ * taken from a CLOSED state has nothing to progress on, so it is the one
153
+ * case that must say what it accounts for; a transition that carries the
154
+ * remainder declares nothing and the law's own witness is used. */
155
+ readonly explains?: ReadonlyArray<Span>;
156
+ /** The transition's own moves, in ladder units. */
157
+ readonly cost: number;
158
+ }
159
+ /** CLOSED — nothing of the asker's material is left unaccounted. */
160
+ export declare function closed(d: DerivationState): boolean;
161
+ /** THE LAW, evaluated once.
162
+ *
163
+ * Returns the spans the transition accounts for — the witness that lets it be
164
+ * taken — or `null` when it is inadmissible. Evaluating it once and advancing
165
+ * the state with {@link advance} is the whole of a transition; asking twice for
166
+ * the same pair would repeat the scan, which this module must not make anyone
167
+ * do.
168
+ *
169
+ * ¬FIXED ∧ CONTAINS ∧ ( CLOSED ∨ CARRIES ∨ MOVES )
170
+ *
171
+ * Cost is not a term: it is the lattice order the market minimises over, and
172
+ * neither is any budget — a cap decides with a number of work, this decides
173
+ * with the remainder. */
174
+ export declare function admissible(d: DerivationState, t: Continuation, query: Uint8Array, W: number): ReadonlyArray<Witness> | null;
175
+ export declare function advance(d: DerivationState, t: Continuation, explains: ReadonlyArray<Witness>): DerivationState;
176
+ /** What a layer offers the law: the next continuation of a state, or null when
177
+ * it has none. A layer OFFERS; the law disposes.
178
+ *
179
+ * ONE OFFER, AND IT IS THE LAYER'S LAST: {@link closure} stops when the law
180
+ * refuses what was offered, so a refusal is read as "no continuation exists".
181
+ * A layer must not offer candidates one at a time and expect the walk to
182
+ * continue after a refusal — its own fallbacks belong inside this function.
183
+ * The producers do exactly that: they choose between the forward absorb and the
184
+ * pivot before offering, and return null only when neither exists, which is why
185
+ * the one offer the law can still refuse (a pivot without ownership, whose
186
+ * material the answer does not carry) really is the last one. */
187
+ export type Offer = (d: DerivationState) => Promise<Continuation | null>;
188
+ /** THE CLOSURE — the walk of {@link advance} over the continuations `offer`
189
+ * proposes, run until the layer has nothing further to offer or the law refuses
190
+ * the one it offered.
191
+ *
192
+ * ADMISSION is entirely the law's; TERMINATION is the layer's, and deliberately
193
+ * so. The remainder does not descend (draining it was implemented and refuted
194
+ * — see the module note), so a walk cannot run forever only because the layer
195
+ * offering continuations keeps its own cycle protection over a finite graph.
196
+ * Nothing here counts steps, and nothing here decides admissibility. */
197
+ export declare function closure(d: DerivationState, query: Uint8Array, W: number, offer: Offer,
198
+ /** Called for each step the law admits, with the state before and after. */
199
+ onTaken?: (before: DerivationState, after: DerivationState) => void,
200
+ /** Called when the law refused the continuation the layer offered. */
201
+ onRefused?: (at: DerivationState) => void): Promise<DerivationState>;