@hviana/sema 0.8.3 → 0.8.6
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.
- package/AGENTS.md +11 -10
- package/README.md +17 -38
- package/dist/example/demo.js +85 -34
- package/dist/src/geometry.d.ts +0 -10
- package/dist/src/geometry.js +0 -12
- package/dist/src/meter.d.ts +31 -5
- package/dist/src/meter.js +31 -5
- package/dist/src/mind/articulation.js +1 -1
- package/dist/src/mind/attention.js +2 -1
- package/dist/src/mind/derivation.d.ts +201 -0
- package/dist/src/mind/derivation.js +327 -0
- package/dist/src/mind/graph-search.d.ts +2 -1
- package/dist/src/mind/graph-search.js +37 -15
- package/dist/src/mind/match.d.ts +2 -0
- package/dist/src/mind/match.js +2 -0
- package/dist/src/mind/mechanisms/alu.js +0 -2
- package/dist/src/mind/mechanisms/cast.d.ts +1 -5
- package/dist/src/mind/mechanisms/cast.js +15 -18
- package/dist/src/mind/mechanisms/confluence.d.ts +0 -3
- package/dist/src/mind/mechanisms/confluence.js +3 -9
- package/dist/src/mind/mechanisms/cover.js +17 -20
- package/dist/src/mind/mechanisms/extraction.d.ts +0 -1
- package/dist/src/mind/mechanisms/extraction.js +13 -8
- package/dist/src/mind/mechanisms/prefix-completion.js +0 -1
- package/dist/src/mind/mechanisms/recall.d.ts +0 -1
- package/dist/src/mind/mechanisms/recall.js +8 -9
- package/dist/src/mind/mechanisms/reference.js +3 -4
- package/dist/src/mind/pipeline-mechanism.d.ts +1 -4
- package/dist/src/mind/pipeline.js +106 -41
- package/dist/src/mind/rationale.d.ts +0 -11
- package/dist/src/mind/rationale.js +6 -32
- package/dist/src/mind/reasoning.d.ts +4 -30
- package/dist/src/mind/reasoning.js +191 -151
- package/dist/src/mind/types.js +6 -3
- package/docs/INDEX.md +23 -24
- package/docs/INVARIANTS.md +16 -17
- package/docs/architecture/bounded-reads.md +4 -4
- package/docs/architecture/closure.md +78 -0
- package/docs/architecture/commonality.md +27 -18
- package/docs/architecture/cost-model.md +5 -5
- package/docs/architecture/exact-vs-approximate.md +4 -4
- package/docs/architecture/factored-machinery.md +14 -14
- package/docs/architecture/mechanism-market.md +9 -9
- package/docs/architecture/meter.md +4 -5
- package/docs/architecture/store.md +2 -2
- package/docs/architecture/thresholds.md +1 -1
- package/docs/failures/tempting-but-wrong.md +11 -1
- package/docs/harness/gates.md +6 -6
- package/docs/mechanisms/cover.md +2 -2
- package/example/demo.ts +90 -37
- package/jsr.json +1 -1
- package/package.json +1 -1
- package/src/geometry.ts +0 -13
- package/src/meter.ts +31 -5
- package/src/mind/articulation.ts +0 -1
- package/src/mind/attention.ts +2 -1
- package/src/mind/derivation.ts +477 -0
- package/src/mind/graph-search.ts +37 -20
- package/src/mind/match.ts +2 -0
- package/src/mind/mechanisms/alu.ts +0 -2
- package/src/mind/mechanisms/cast.ts +17 -21
- package/src/mind/mechanisms/confluence.ts +3 -13
- package/src/mind/mechanisms/cover.ts +17 -20
- package/src/mind/mechanisms/extraction.ts +13 -9
- package/src/mind/mechanisms/prefix-completion.ts +0 -1
- package/src/mind/mechanisms/recall.ts +7 -9
- package/src/mind/mechanisms/reference.ts +2 -3
- package/src/mind/pipeline-mechanism.ts +1 -4
- package/src/mind/pipeline.ts +121 -46
- package/src/mind/rationale.ts +6 -36
- package/src/mind/reasoning.ts +220 -178
- package/src/mind/types.ts +5 -2
- package/test/121-the-extension-does-not-grow-with-the-corpus.test.mjs +3 -3
- package/test/133-the-decision-point-renders-the-state.test.mjs +204 -0
- package/test/134-the-law-explains-the-engines-own-refusal.test.mjs +237 -0
- package/test/135-one-law-any-producer.test.mjs +289 -0
- package/test/136-the-two-named-limits.test.mjs +205 -0
- package/test/137-the-law-lives-once-and-below.test.mjs +400 -0
- package/test/138-the-remainder-drains-only-what-a-move-declares.test.mjs +62 -0
- package/test/139-the-witness-is-engagement-not-explanation.test.mjs +51 -0
- package/test/140-irrelevant-supply-does-not-change-an-answer.test.mjs +48 -0
- package/test/141-the-question-is-paid-at-construction.test.mjs +98 -0
- package/test/142-the-layer-offers-only-what-the-law-admits.test.mjs +93 -0
- package/test/143-cycles-terminate-and-are-not-closure.test.mjs +62 -0
- package/test/36-already-answered-fusion.test.mjs +20 -2
- package/test/37-cluster-dispersion-fusion.test.mjs +30 -3
- package/test/38-reason-restate-guard.test.mjs +22 -2
- package/test/55-cost-meter.test.mjs +6 -3
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,
|
|
59
|
-
in `src/geometry.ts` is the one boundary rule;
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
`src/mind/pipeline-mechanism.ts` is
|
|
63
|
-
is the write-only work accounting surface.
|
|
64
|
-
|
|
65
|
-
Tie-breaks are corpus-determined,
|
|
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
|
|
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 —
|
|
183
|
-
|
|
184
|
-
import { Mind } from "../src/index.js";
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
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:
|
|
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
|
-
>
|
|
237
|
-
>
|
|
238
|
-
>
|
|
239
|
-
>
|
|
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
|
|
package/dist/example/demo.js
CHANGED
|
@@ -1,39 +1,90 @@
|
|
|
1
|
-
// demo.ts —
|
|
1
|
+
// demo.ts — a corpus goes in, and the memory is read back out.
|
|
2
2
|
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
|
|
11
|
-
|
|
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({
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
//
|
|
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();
|
package/dist/src/geometry.d.ts
CHANGED
|
@@ -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
|
package/dist/src/geometry.js
CHANGED
|
@@ -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
|
package/dist/src/meter.d.ts
CHANGED
|
@@ -199,12 +199,38 @@ export declare class Meter {
|
|
|
199
199
|
* not computable at all. With it, the price of extending the answer is
|
|
200
200
|
* `reasonSteps · STEP`, the ladder's own value for following an edge. */
|
|
201
201
|
reasonSteps: number;
|
|
202
|
-
/** Bytes
|
|
203
|
-
*
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
*
|
|
202
|
+
/** Bytes the admitted steps ACCOUNTED for — the witnesses' spans, summed by the
|
|
203
|
+
* law's own function over the tail of the state's accounting. It is NOT what
|
|
204
|
+
* they carried: a step admitted by `reaches` may declare spans it holds no
|
|
205
|
+
* window of, and then it accounts without carrying and consumes nothing (see
|
|
206
|
+
* {@link closureDrainedBytes}). Read with {@link reasonSteps}: one is the
|
|
207
|
+
* price, the other the accounting. */
|
|
208
|
+
reasonAccountedBytes: number;
|
|
209
|
+
/** Bytes of the QUESTION's own material an admitted step CARRIED — the windows
|
|
210
|
+
* of the remainder its product holds, read by the law's one reading. The
|
|
211
|
+
* accounting may be larger (a `reaches` step declares spans it holds no window
|
|
212
|
+
* of) and the consumption is the window of a step that also reaches, so the
|
|
213
|
+
* three form a lattice: consumed ⊆ carried ⊆ accounted. */
|
|
207
214
|
reasonCarriedBytes: number;
|
|
215
|
+
/** Times the layer OFFERED a continuation to the law. Read with
|
|
216
|
+
* {@link lawRejects}: the offers the law refused are the Model X contract being
|
|
217
|
+
* exercised, and `offerRuns - lawRejects` is the accepted transitions. */
|
|
218
|
+
offerRuns: number;
|
|
219
|
+
/** Times the law REFUSED the continuation the layer offered. A refusal is
|
|
220
|
+
* terminal by the layer's contract, so this counts the moments the contract
|
|
221
|
+
* mattered — zero means the walk never needed it. */
|
|
222
|
+
lawRejects: number;
|
|
223
|
+
/** Bytes of the question's REMAINDER a step CONSUMED — the drop the law's own
|
|
224
|
+
* `advance` makes when a declared move carries the material it accounts for.
|
|
225
|
+
* Read with {@link reasonSteps} and {@link reasonAccountedBytes}: carrying is
|
|
226
|
+
* the engagement, this is the consumption, and before it the second was
|
|
227
|
+
* invisible. */
|
|
228
|
+
closureDrainedBytes: number;
|
|
229
|
+
/** Bytes of the question the grounding PRICED but whose material its answer does
|
|
230
|
+
* NOT carry, at or above one quantum — the debt the construction leaves for the
|
|
231
|
+
* walk to pay by carrying it. Zero means the grounding's coverage is honest:
|
|
232
|
+
* everything it priced is either held by the answer or under the W floor. */
|
|
233
|
+
groundingWithheldBytes: number;
|
|
208
234
|
/** Branch-node probes the pivot sweep actually spent looking for the learnt
|
|
209
235
|
* context an answer contains (one `resonate` per probe). The untraced view
|
|
210
236
|
* of what the multi-hop's shortlist costs. */
|
package/dist/src/meter.js
CHANGED
|
@@ -209,12 +209,38 @@ export class Meter {
|
|
|
209
209
|
* not computable at all. With it, the price of extending the answer is
|
|
210
210
|
* `reasonSteps · STEP`, the ladder's own value for following an edge. */
|
|
211
211
|
reasonSteps = 0;
|
|
212
|
-
/** Bytes
|
|
213
|
-
*
|
|
214
|
-
*
|
|
215
|
-
*
|
|
216
|
-
*
|
|
212
|
+
/** Bytes the admitted steps ACCOUNTED for — the witnesses' spans, summed by the
|
|
213
|
+
* law's own function over the tail of the state's accounting. It is NOT what
|
|
214
|
+
* they carried: a step admitted by `reaches` may declare spans it holds no
|
|
215
|
+
* window of, and then it accounts without carrying and consumes nothing (see
|
|
216
|
+
* {@link closureDrainedBytes}). Read with {@link reasonSteps}: one is the
|
|
217
|
+
* price, the other the accounting. */
|
|
218
|
+
reasonAccountedBytes = 0;
|
|
219
|
+
/** Bytes of the QUESTION's own material an admitted step CARRIED — the windows
|
|
220
|
+
* of the remainder its product holds, read by the law's one reading. The
|
|
221
|
+
* accounting may be larger (a `reaches` step declares spans it holds no window
|
|
222
|
+
* of) and the consumption is the window of a step that also reaches, so the
|
|
223
|
+
* three form a lattice: consumed ⊆ carried ⊆ accounted. */
|
|
217
224
|
reasonCarriedBytes = 0;
|
|
225
|
+
/** Times the layer OFFERED a continuation to the law. Read with
|
|
226
|
+
* {@link lawRejects}: the offers the law refused are the Model X contract being
|
|
227
|
+
* exercised, and `offerRuns - lawRejects` is the accepted transitions. */
|
|
228
|
+
offerRuns = 0;
|
|
229
|
+
/** Times the law REFUSED the continuation the layer offered. A refusal is
|
|
230
|
+
* terminal by the layer's contract, so this counts the moments the contract
|
|
231
|
+
* mattered — zero means the walk never needed it. */
|
|
232
|
+
lawRejects = 0;
|
|
233
|
+
/** Bytes of the question's REMAINDER a step CONSUMED — the drop the law's own
|
|
234
|
+
* `advance` makes when a declared move carries the material it accounts for.
|
|
235
|
+
* Read with {@link reasonSteps} and {@link reasonAccountedBytes}: carrying is
|
|
236
|
+
* the engagement, this is the consumption, and before it the second was
|
|
237
|
+
* invisible. */
|
|
238
|
+
closureDrainedBytes = 0;
|
|
239
|
+
/** Bytes of the question the grounding PRICED but whose material its answer does
|
|
240
|
+
* NOT carry, at or above one quantum — the debt the construction leaves for the
|
|
241
|
+
* walk to pay by carrying it. Zero means the grounding's coverage is honest:
|
|
242
|
+
* everything it priced is either held by the answer or under the W floor. */
|
|
243
|
+
groundingWithheldBytes = 0;
|
|
218
244
|
/** Branch-node probes the pivot sweep actually spent looking for the learnt
|
|
219
245
|
* context an answer contains (one `resonate` per probe). The untraced view
|
|
220
246
|
* 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,
|
|
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 (
|
|
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, witnesses: ReadonlyArray<Witness>) => void,
|
|
200
|
+
/** Called when the law refused the continuation the layer offered. */
|
|
201
|
+
onRefused?: (at: DerivationState) => void): Promise<DerivationState>;
|