@hviana/sema 0.8.2 → 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.
- package/AGENTS.md +38 -37
- package/README.md +17 -38
- package/TRADEMARKS.md +0 -1
- package/dist/example/demo.js +85 -34
- package/dist/src/config.d.ts +11 -0
- package/dist/src/config.js +2 -0
- package/dist/src/geometry.d.ts +21 -10
- package/dist/src/geometry.js +21 -12
- package/dist/src/meter.d.ts +62 -0
- package/dist/src/meter.js +62 -0
- package/dist/src/mind/articulation.js +1 -1
- package/dist/src/mind/attention.d.ts +4 -0
- package/dist/src/mind/attention.js +167 -17
- package/dist/src/mind/canonical.d.ts +16 -0
- package/dist/src/mind/canonical.js +41 -0
- 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 +70 -29
- package/dist/src/mind/match.d.ts +3 -1
- package/dist/src/mind/match.js +7 -3
- 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 +16 -19
- package/dist/src/mind/mechanisms/confluence.d.ts +0 -3
- package/dist/src/mind/mechanisms/confluence.js +27 -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 +40 -13
- package/dist/src/mind/mechanisms/reference.js +3 -4
- package/dist/src/mind/mind.d.ts +4 -2
- package/dist/src/mind/mind.js +5 -4
- package/dist/src/mind/pipeline-mechanism.d.ts +7 -3
- package/dist/src/mind/pipeline.js +136 -44
- package/dist/src/mind/primitives.js +9 -1
- package/dist/src/mind/rationale.d.ts +21 -5
- package/dist/src/mind/rationale.js +16 -21
- package/dist/src/mind/reasoning.d.ts +12 -20
- package/dist/src/mind/reasoning.js +190 -106
- package/dist/src/mind/recognition.js +4 -8
- package/dist/src/mind/resonance.js +20 -1
- package/dist/src/mind/trace.js +1 -0
- package/dist/src/mind/traverse.js +6 -2
- package/dist/src/mind/types.d.ts +36 -13
- 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 +5 -5
- package/docs/architecture/closure.md +65 -0
- package/docs/architecture/commonality.md +29 -20
- package/docs/architecture/cost-model.md +7 -7
- package/docs/architecture/determinism.md +7 -7
- package/docs/architecture/exact-vs-approximate.md +4 -4
- package/docs/architecture/factored-machinery.md +14 -14
- package/docs/architecture/match-project.md +2 -3
- package/docs/architecture/mechanism-market.md +16 -16
- package/docs/architecture/meter.md +10 -11
- package/docs/architecture/store.md +4 -4
- package/docs/architecture/thresholds.md +1 -1
- package/docs/failures/tempting-but-wrong.md +14 -5
- package/docs/harness/gates.md +7 -7
- package/docs/mechanisms/cast.md +2 -2
- package/docs/mechanisms/cover.md +4 -5
- package/docs/mechanisms/extraction.md +7 -7
- package/docs/mechanisms/recall.md +8 -9
- package/example/demo.ts +90 -37
- package/jsr.json +1 -1
- package/package.json +1 -1
- package/src/alu/README.md +11 -12
- package/src/config.ts +13 -0
- package/src/geometry.ts +21 -13
- package/src/meter.ts +62 -0
- package/src/mind/articulation.ts +0 -1
- package/src/mind/attention.ts +169 -17
- package/src/mind/canonical.ts +43 -0
- package/src/mind/derivation.ts +473 -0
- package/src/mind/graph-search.ts +76 -34
- package/src/mind/match.ts +7 -3
- package/src/mind/mechanisms/alu.ts +0 -2
- package/src/mind/mechanisms/cast.ts +20 -22
- package/src/mind/mechanisms/confluence.ts +27 -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 +39 -13
- package/src/mind/mechanisms/reference.ts +2 -3
- package/src/mind/mind.ts +6 -4
- package/src/mind/pipeline-mechanism.ts +7 -3
- package/src/mind/pipeline.ts +160 -52
- package/src/mind/primitives.ts +9 -1
- package/src/mind/rationale.ts +27 -23
- package/src/mind/reasoning.ts +227 -120
- package/src/mind/recognition.ts +4 -8
- package/src/mind/resonance.ts +19 -1
- package/src/mind/trace.ts +1 -0
- package/src/mind/traverse.ts +7 -5
- package/src/mind/types.ts +41 -15
- package/test/105-derive-through-reports-its-refusal.test.mjs +24 -0
- package/test/118-the-join-reaches-a-key-off-the-cut.test.mjs +74 -0
- package/test/119-the-work-does-not-grow-with-the-corpus.test.mjs +122 -0
- package/test/120-composition-is-consequence.test.mjs +132 -0
- package/test/121-the-extension-does-not-grow-with-the-corpus.test.mjs +128 -0
- package/test/122-the-climb-search-does-not-grow-with-the-corpus.test.mjs +117 -0
- package/test/123-the-paired-formulas-agree.test.mjs +90 -0
- package/test/125-the-post-grounding-branch-publishes-its-operand.test.mjs +51 -0
- package/test/126-the-pipeline-does-not-name-mechanisms.test.mjs +42 -0
- package/test/128-the-leads-somewhere-pair-agrees.test.mjs +83 -0
- package/test/129-the-trace-payload-shape.test.mjs +164 -0
- 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/32-confluence.test.mjs +68 -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 +28 -2
- package/test/43-cast-analog-seat.test.mjs +10 -0
- package/test/55-cost-meter.test.mjs +862 -0
|
@@ -12,8 +12,9 @@ import { PASS, STEP } from "./graph-search.js";
|
|
|
12
12
|
import { gistOf, read, resolve } from "./primitives.js";
|
|
13
13
|
import { recognise } from "./recognition.js";
|
|
14
14
|
import { fuseAttention, reason } from "./reasoning.js";
|
|
15
|
-
import { unexplainedSpans } from "./
|
|
15
|
+
import { closed, remainderOf, unaccountedBytes, unexplainedSpans, windowOf, } from "./derivation.js";
|
|
16
16
|
import { rItem } from "./trace.js";
|
|
17
|
+
import { unexplainedLabel } from "./rationale.js";
|
|
17
18
|
import { hubBound } from "./traverse.js";
|
|
18
19
|
import { Precomputed } from "./pipeline-mechanism.js";
|
|
19
20
|
import { coverMechanism } from "./mechanisms/cover.js";
|
|
@@ -124,8 +125,7 @@ export async function think(ctx, query, mechs) {
|
|
|
124
125
|
// (meter.md); the trace already represents structure.
|
|
125
126
|
const pre = new Precomputed(ctx, query, rec, computed, ctx._edgeGuide);
|
|
126
127
|
const grade = (w) => Math.floor(w / STEP);
|
|
127
|
-
const unaccounted = (spans) => unexplainedSpans(query.length, spans)
|
|
128
|
-
.reduce((sum, [s, e]) => sum + (e - s), 0);
|
|
128
|
+
const unaccounted = (spans) => unaccountedBytes(unexplainedSpans(query.length, spans));
|
|
129
129
|
const weigh = (accounted, moves) => moves + PASS * unaccounted(accounted);
|
|
130
130
|
const candidates = [];
|
|
131
131
|
let best = null;
|
|
@@ -243,14 +243,16 @@ export async function think(ctx, query, mechs) {
|
|
|
243
243
|
? await meter.time(`${mech.name}.run`, () => mech.run(ctx, query, pre))
|
|
244
244
|
: await mech.run(ctx, query, pre);
|
|
245
245
|
for (const r of results) {
|
|
246
|
-
|
|
246
|
+
// ONE FORMULA, EVERY CANDIDATE: the chart's derivation reports how many
|
|
247
|
+
// discrete moves it made and which bytes it could not recognise; the
|
|
248
|
+
// currency prices both. No mechanism passes a price of its own.
|
|
249
|
+
const weight = weigh(r.accounted, r.moves);
|
|
247
250
|
consider({
|
|
248
251
|
bytes: r.bytes,
|
|
249
252
|
provenance: r.provenance ?? mech.provenance,
|
|
250
253
|
weight,
|
|
251
254
|
used: r.used,
|
|
252
255
|
accounted: r.accounted,
|
|
253
|
-
unexplained: r.unexplained,
|
|
254
256
|
complete: r.complete,
|
|
255
257
|
scaffolding: r.scaffolding,
|
|
256
258
|
});
|
|
@@ -281,7 +283,17 @@ export async function think(ctx, query, mechs) {
|
|
|
281
283
|
const margin = decided !== null && runnerUp !== null
|
|
282
284
|
? grade(runnerUp.weight) - grade(decided.weight)
|
|
283
285
|
: null;
|
|
284
|
-
ctx.trace?.step("decideGrounding",
|
|
286
|
+
ctx.trace?.step("decideGrounding",
|
|
287
|
+
// THE LABEL IS RENDERED WHERE IT IS SHOWN. It was a field on every
|
|
288
|
+
// mechanism's result, and at every one of them it was exactly
|
|
289
|
+
// `unexplainedLabel(query, accounted)` — a second representation of a
|
|
290
|
+
// quantity one pure function already yields, computed on every response
|
|
291
|
+
// whether or not anyone looked. Here it is computed only when a rationale
|
|
292
|
+
// is attached, because `trace?.step` short-circuits its arguments.
|
|
293
|
+
candidates.map((c) => {
|
|
294
|
+
const label = unexplainedLabel(query, c.accounted);
|
|
295
|
+
return rItem(c.bytes, `${c.provenance} (weight ${c.weight.toFixed(3)}${label ? `, unexplained: "${label}"` : ""})`);
|
|
296
|
+
}), decided ? [rItem(decided.bytes, decided.provenance)] : [], "the lightest grounding derivation wins — every mechanism weighed in the one cost ladder", undefined, {
|
|
285
297
|
version: 1,
|
|
286
298
|
candidates: candidates.map((c) => ({
|
|
287
299
|
provenance: c.provenance,
|
|
@@ -317,13 +329,57 @@ export async function think(ctx, query, mechs) {
|
|
|
317
329
|
}
|
|
318
330
|
const answer = decided.bytes;
|
|
319
331
|
const provenance = decided.provenance;
|
|
320
|
-
const
|
|
321
|
-
// ──
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
332
|
+
const declaredUsed = decided.used;
|
|
333
|
+
// ── THE DERIVATION STATE ─────────────────────────────────────────────
|
|
334
|
+
//
|
|
335
|
+
// THE REASONER JUDGES ITS OWN EXTENSIONS BY THE PIPELINE'S REMAINDER, not by
|
|
336
|
+
// the ladder's `accounted` — and by the SAME reading the fuse gate below uses,
|
|
337
|
+
// with the same W floor. `accounted` is a COST quantity (measured: a query
|
|
338
|
+
// fully explained by one computed span plus bridged connectors reports
|
|
339
|
+
// `accounted: []` while nothing is unexplained), and a remainder under one
|
|
340
|
+
// river-fold quantum is bridging punctuation, never a second topic — so it
|
|
341
|
+
// licenses no extension and blocks none.
|
|
342
|
+
//
|
|
343
|
+
// The state is built HERE, where these quantities are already computed, so it
|
|
344
|
+
// costs nothing new: `accounted` is what the winning transition priced,
|
|
345
|
+
// `remainder` is the coverage reading over `accounted ∪ the response's
|
|
346
|
+
// computed spans` (the union is what makes the two different quantities, and
|
|
347
|
+
// both are kept), `cost` is the ladder position, and the two declarations are
|
|
348
|
+
// the producer's own (`fixed`, `used`). What follows reads THIS state rather
|
|
349
|
+
// than a tuple rebuilt at each call site.
|
|
350
|
+
// A DERIVATION IS BORN OWING WHAT ITS ANSWER DOES NOT CARRY. The winning
|
|
351
|
+
// transition PRICED these spans, and pricing is not carrying: coverage claimed
|
|
352
|
+
// without evidence stays owed, and a later transition pays it only by carrying
|
|
353
|
+
// it (the law reads the window; see derivation.ts). Same reading, one
|
|
354
|
+
// definition — not a second spelling of it here.
|
|
355
|
+
const explained = [
|
|
356
|
+
...decided.accounted,
|
|
357
|
+
...pre.computed.map((u) => [u.i, u.j]),
|
|
358
|
+
].filter(([a, b]) => windowOf([a, b], answer, query, ctx.space.maxGroup) !== null);
|
|
359
|
+
// WHAT THE CONSTRUCTION WITHHOLDS, at or above one quantum: the difference between
|
|
360
|
+
// the remainder paid in full and the remainder paid by carrying. Both readings
|
|
361
|
+
// are the law's, so the floor is applied once and in one place.
|
|
362
|
+
const paidInFull = remainderOf(query.length, [
|
|
363
|
+
...decided.accounted,
|
|
364
|
+
...pre.computed.map((u) => [u.i, u.j]),
|
|
365
|
+
], ctx.space.maxGroup);
|
|
366
|
+
const paid = remainderOf(query.length, explained, ctx.space.maxGroup);
|
|
367
|
+
if (ctx.meter) {
|
|
368
|
+
ctx.meter.groundingWithheldBytes += unaccountedBytes(paid) -
|
|
369
|
+
unaccountedBytes(paidInFull);
|
|
370
|
+
}
|
|
371
|
+
const state = {
|
|
372
|
+
product: answer,
|
|
373
|
+
accounted: decided.accounted,
|
|
374
|
+
remainder: paid,
|
|
375
|
+
cost: decided.weight,
|
|
376
|
+
fixed: decided.complete,
|
|
377
|
+
used: decided.used,
|
|
378
|
+
};
|
|
379
|
+
const uncovered = state.remainder;
|
|
380
|
+
// ── Post-grounding, gated by the declaration and the remainder ────────
|
|
381
|
+
const preConsumed = declaredUsed ??
|
|
382
|
+
new Set(recognise(ctx, answer).sites.map((s) => s.payload));
|
|
327
383
|
// A grounding that DECLARED itself complete is not extended: the answer is
|
|
328
384
|
// already a trained form's own continuation, reached through an identity
|
|
329
385
|
// claim about the query, so a multi-hop pivot could only chain past the
|
|
@@ -352,9 +408,32 @@ export async function think(ctx, query, mechs) {
|
|
|
352
408
|
// `preConsumed` is derived by re-recognising the answer — "everything in
|
|
353
409
|
// it", not "what it voiced" — and a containment rule over that would
|
|
354
410
|
// suppress every pivot the answer legitimately contains.
|
|
355
|
-
const voiced =
|
|
356
|
-
|
|
357
|
-
|
|
411
|
+
const voiced = declaredUsed === undefined ? [] : [...declaredUsed].flatMap((id) => ctx.store.nextFirst(id, hubBound(ctx)).map((n) => read(ctx, n)));
|
|
412
|
+
// WHAT THIS BRANCH READ, published where it was read. Post-grounding decides
|
|
413
|
+
// by the DECLARATION (`decided.used`, which becomes `voiced`), by what the
|
|
414
|
+
// recognition already consumed (`preConsumed`) and by the derivation's own
|
|
415
|
+
// remainder — never by the provenance NAME, which is REPORTED throughout and
|
|
416
|
+
// compared nowhere (a stale comment here claimed otherwise; the register caught
|
|
417
|
+
// it, and this is the correction). The operands were invisible in the trace, so
|
|
418
|
+
// a change to the branching could not be shown equivalent or otherwise from
|
|
419
|
+
// outside — three separate investigations failed on exactly that gap. A gap in instrumentation is a defect IN the instrumentation
|
|
420
|
+
// (AGENTS.md §6): closed here, once, as counts only — never content.
|
|
421
|
+
ctx.trace?.step("postGrounding", [rItem(answer, provenance)], [], `used=${decided.used !== undefined ? "declared" : "absent"} · ` +
|
|
422
|
+
`preConsumed=${preConsumed.size} · voiced=${voiced.length}`, undefined, {
|
|
423
|
+
version: 1,
|
|
424
|
+
provenance,
|
|
425
|
+
usedDeclared: decided.used !== undefined,
|
|
426
|
+
preConsumed: preConsumed.size,
|
|
427
|
+
voiced: voiced.length,
|
|
428
|
+
// THE STATE THE LAW GOVERNS, rendered where it is decided: what the asker
|
|
429
|
+
// said that no step has accounted for, in spans at or above one quantum,
|
|
430
|
+
// and whether the producer supplied a fixed point. Counts only, like
|
|
431
|
+
// every other operand here — and the spans are the state's, so a reader
|
|
432
|
+
// can check them against the meter's aggregate of the same remainder.
|
|
433
|
+
remainderSpans: state.remainder.length,
|
|
434
|
+
remainderBytes: unaccountedBytes(state.remainder),
|
|
435
|
+
fixed: state.fixed === true,
|
|
436
|
+
});
|
|
358
437
|
// REPORTABLE, NOT SILENT. A declared-complete grounding ends the derivation
|
|
359
438
|
// here, and that decision is part of the derivation's shape: the reader of a
|
|
360
439
|
// rationale must be able to see that the chain stopped because the mechanism
|
|
@@ -365,22 +444,22 @@ export async function think(ctx, query, mechs) {
|
|
|
365
444
|
ctx.trace?.step("completeGrounding", [rItem(answer, provenance)], [], "grounding declared complete — the query IS the context, so " +
|
|
366
445
|
"post-grounding extension is skipped");
|
|
367
446
|
}
|
|
368
|
-
//
|
|
369
|
-
//
|
|
370
|
-
//
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
447
|
+
// PUBLISHED, NOT RECOMPUTED: the same `uncovered` the gates below read. A
|
|
448
|
+
// write-only accounting (meter contract 1), so the number that licenses an
|
|
449
|
+
// extension or a fusion stops being invisible.
|
|
450
|
+
if (meter) {
|
|
451
|
+
meter.postGroundingRemainderSpans += uncovered.length;
|
|
452
|
+
meter.postGroundingRemainderBytes += unaccountedBytes(uncovered);
|
|
453
|
+
}
|
|
454
|
+
// THE WALK CONSUMES AND RETURNS A STATE. It is handed the derivation's own —
|
|
455
|
+
// the grounding's product, accounting, remainder and cost — and hands back the
|
|
456
|
+
// state it advanced to, so what follows reads a state rather than bytes plus a
|
|
457
|
+
// tuple rebuilt here. A supplied fixed point is the one case where the walk
|
|
458
|
+
// does not run at all, and then the state is the grounding's own.
|
|
459
|
+
const extension = decided.complete ? undefined : meter
|
|
460
|
+
? await meter.time("reason", () => reason(ctx, query, state, preConsumed, pre, voiced))
|
|
461
|
+
: await reason(ctx, query, state, preConsumed, pre, voiced);
|
|
462
|
+
const reasoned = extension ?? state;
|
|
384
463
|
// Fuse only when the query has a genuine REMAINDER no mechanism's
|
|
385
464
|
// structural evidence touched at all. `decided.accounted` alone
|
|
386
465
|
// undercounts this: it is a COST-LADDER quantity (cover.ts prices its
|
|
@@ -397,7 +476,15 @@ export async function think(ctx, query, mechs) {
|
|
|
397
476
|
// observed: a single space between two fully-computed arithmetic spans
|
|
398
477
|
// ("2+2 3+3") registered as "unaccounted" and pulled in an unrelated
|
|
399
478
|
// corpus fact, corrupting "4 6" into "4 63".
|
|
400
|
-
|
|
479
|
+
// THE GATE ASKS THE LAW, and that is an OPTIMISATION, not a tidy-up: the state
|
|
480
|
+
// above ALREADY carries the remainder (`remainderOf`, per-span, with the W
|
|
481
|
+
// floor applied), so asking it costs nothing, while the total this line used to
|
|
482
|
+
// compute (`unaccounted(explained)`) was one more sum over the spans on every
|
|
483
|
+
// response. The two readings are the same condition, not two: the ACCOUNTING
|
|
484
|
+
// applies the same W floor the gate does, so a gap below one quantum never
|
|
485
|
+
// survives into `explained` and the total cannot reach W without some single
|
|
486
|
+
// gap reaching it. Measured over twelve constructions at W = 4 (test/136.3,
|
|
487
|
+
// which pins the equivalence and both sides of it).
|
|
401
488
|
// Whether the winning candidate's entire recognised substance is
|
|
402
489
|
// COMPUTED — every accounted span exactly a pre.computed span, nothing
|
|
403
490
|
// from a genuinely recognised/climbed site. fuseAttention's lone-root
|
|
@@ -407,8 +494,8 @@ export async function think(ctx, query, mechs) {
|
|
|
407
494
|
// `unclimbed` parameter, gated there by Attention.breadth so a
|
|
408
495
|
// coincidental echo (which this flag alone cannot distinguish) is still
|
|
409
496
|
// rejected.
|
|
410
|
-
const unclimbed =
|
|
411
|
-
|
|
497
|
+
const unclimbed = state.accounted.length > 0 &&
|
|
498
|
+
state.accounted.every(([i, j]) => pre.computed.some((u) => u.i === i && u.j === j));
|
|
412
499
|
// Where the winning grounding stands in the query — fusion places primary
|
|
413
500
|
// by it (see fuseAttention's `primarySpans`). `accounted` is the
|
|
414
501
|
// cost-ladder read and is authoritative when non-empty; when it is empty
|
|
@@ -416,14 +503,19 @@ export async function think(ctx, query, mechs) {
|
|
|
416
503
|
// Exactly the cost-ladder-vs-coverage distinction `explained` above draws,
|
|
417
504
|
// read here for POSITION instead of for coverage — and resolved here, where
|
|
418
505
|
// both readings are in hand, rather than inside fuseAttention.
|
|
419
|
-
const primarySpans =
|
|
420
|
-
?
|
|
506
|
+
const primarySpans = state.accounted.length > 0
|
|
507
|
+
? state.accounted
|
|
421
508
|
: pre.computed.map((u) => [u.i, u.j]);
|
|
422
|
-
const fused =
|
|
423
|
-
? reasoned
|
|
424
|
-
:
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
509
|
+
const fused = closed(state) ? reasoned : meter
|
|
510
|
+
? await meter.time("fuse", () => fuseAttention(ctx, query, reasoned, pre, unclimbed, primarySpans))
|
|
511
|
+
: await fuseAttention(ctx, query, reasoned, pre, unclimbed, primarySpans);
|
|
512
|
+
done(fused.product,
|
|
513
|
+
// NO CLAIM ABOUT FUSION HERE. `fuseAttention` is entered whenever a
|
|
514
|
+
// remainder ≥ W exists and returns early when there is nothing to bridge, so
|
|
515
|
+
// this note used to assert a fusion that frequently did not happen (measured:
|
|
516
|
+
// "What is the capital of France famous for" fuses 0 times). The fusion is
|
|
517
|
+
// reported by `fuseAttention`'s own `done` when it happens — the layer that
|
|
518
|
+
// did the work is the layer that says so.
|
|
519
|
+
"grounded, reasoned forward");
|
|
520
|
+
return { bytes: fused.product, provenance };
|
|
429
521
|
}
|
|
@@ -297,7 +297,15 @@ export function canonResolve(ctx, bytes) {
|
|
|
297
297
|
// on exactly the node the canonical-case query would have found.
|
|
298
298
|
const folded = foldTree(ctx, perceive(ctx, bytesOf), 0).node;
|
|
299
299
|
const use = folded ?? id;
|
|
300
|
-
|
|
300
|
+
// THE ADMISSION PREDICATE, by its own pair of probes: `traverse.ts`'s
|
|
301
|
+
// `leadsSomewhere` is edge-or-halo, and `hasHalo` is the one that carries
|
|
302
|
+
// the mass bar (`mass >= minHaloMass`). Asking `haloMass(use) > 0` instead
|
|
303
|
+
// is the same answer only while `minHaloMass <= 1` (its default): raise the
|
|
304
|
+
// bar and this site would rank a node as leading on evidence the law
|
|
305
|
+
// refuses. Calling `leadsSomewhere` here is not possible — `traverse.ts`
|
|
306
|
+
// imports THIS file, so it would be a cycle — which is why the pair is
|
|
307
|
+
// spelled out rather than named.
|
|
308
|
+
const leads = store.hasNext(use) || store.hasHalo(use);
|
|
301
309
|
if (best === null || (leads && !bestLeads) ||
|
|
302
310
|
(leads === bestLeads && use < best)) {
|
|
303
311
|
best = use;
|
|
@@ -26,6 +26,17 @@ export interface RationaleItem {
|
|
|
26
26
|
* caller asked to carry it (off by default — a D-float array per item would
|
|
27
27
|
* bury the reasoning it is meant to explain). */
|
|
28
28
|
v?: Vec;
|
|
29
|
+
/** The element's OWN bytes, attached BY REFERENCE when the step was built from
|
|
30
|
+
* bytes (a `rationale.ts` item made from a node carries none: read it back
|
|
31
|
+
* through `node`). `text` is a RENDERING and cannot stand in for them — it
|
|
32
|
+
* decodes UTF-8 and DROPS NUL bytes, so a key containing one is unrecoverable
|
|
33
|
+
* from it, which is exactly how a join refusal (`deriveThroughMiss`) became
|
|
34
|
+
* impossible to test exactly without re-encoding. Treat as READ-ONLY: the
|
|
35
|
+
* array belongs to the caller (and may be a view into the query).
|
|
36
|
+
*
|
|
37
|
+
* Costs nothing when nothing inspects: items exist only while a rationale
|
|
38
|
+
* sink is attached, and this holds a reference rather than a copy. */
|
|
39
|
+
bytes?: Uint8Array;
|
|
29
40
|
}
|
|
30
41
|
/** A single completed act of inference — one mechanism, run once.
|
|
31
42
|
*
|
|
@@ -72,10 +83,6 @@ export type InspectRationale = (step: RationaleStep) => void;
|
|
|
72
83
|
/** Decode bytes to text for display, dropping the NUL padding the encoder uses
|
|
73
84
|
* (the same cleanup {@link Mind.respondText} does for its result). */
|
|
74
85
|
export declare function decodeText(bytes: Uint8Array): string;
|
|
75
|
-
/** The `[start, end)` gaps of `[0, queryLen)` NOT covered by `accounted` —
|
|
76
|
-
* the same union-of-spans reading think's grounding decider prices at PASS
|
|
77
|
-
* per byte, exposed here so a mechanism can turn it into a human label. */
|
|
78
|
-
export declare function unexplainedSpans(queryLen: number, accounted: ReadonlyArray<[number, number]>): Array<[number, number]>;
|
|
79
86
|
/** A human-readable label for the query bytes a mechanism's `accounted`
|
|
80
87
|
* spans leave unexplained — purely diagnostic (Task 2's negative evidence):
|
|
81
88
|
* it never changes a candidate's weight, only what the rationale trace
|
|
@@ -133,7 +140,16 @@ export declare class Rationale {
|
|
|
133
140
|
* now; the matching {@link Scope.done} supplies the outputs when it finishes.
|
|
134
141
|
* `deps` overrides the default data-flow edge (previous sibling / parent). */
|
|
135
142
|
enter(name: string, inputs: RationaleItem[], deps?: number[]): Scope;
|
|
136
|
-
/**
|
|
143
|
+
/** WHY THIS NAME IS A FREE STRING, when the derivation's moves are a closed
|
|
144
|
+
* union: a mechanism name is WRITTEN and DISPLAYED, and it COMPOSES with
|
|
145
|
+
* the nesting — `mechanism` is the whole path (`["respond", "think",
|
|
146
|
+
* "recognise"]`), which no fixed union can express. Nothing branches on it:
|
|
147
|
+
* `nothing here drives the inference; it only WITNESSES it`. A vocabulary
|
|
148
|
+
* that is only witnessed needs no union; one that is read does
|
|
149
|
+
* (`DerivationMove`, in graph-search.ts). The asymmetry is the design, not
|
|
150
|
+
* a drift.
|
|
151
|
+
*
|
|
152
|
+
* Record a mechanism that has no sub-steps — its inputs and outputs are both
|
|
137
153
|
* known at the call site. Returns its index, for a later step to depend on. */
|
|
138
154
|
step(name: string, inputs: RationaleItem[], outputs: RationaleItem[], note?: string, deps?: number[], data?: unknown): number;
|
|
139
155
|
}
|
|
@@ -19,31 +19,17 @@
|
|
|
19
19
|
// out into a ranked list of hits. So a step's `inputs` and `outputs` are each a
|
|
20
20
|
// VECTOR — an ordered list of {@link RationaleItem}s, one per element — and the
|
|
21
21
|
// fan-out / fan-in is visible in their lengths.
|
|
22
|
+
import { unexplainedSpans } from "./derivation.js";
|
|
22
23
|
/** Decode bytes to text for display, dropping the NUL padding the encoder uses
|
|
23
24
|
* (the same cleanup {@link Mind.respondText} does for its result). */
|
|
24
25
|
export function decodeText(bytes) {
|
|
25
26
|
return new TextDecoder().decode(bytes.filter((b) => b !== 0x00));
|
|
26
27
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
.map(([s, e]) => [Math.max(0, s), Math.min(queryLen, e)])
|
|
33
|
-
.filter(([s, e]) => e > s)
|
|
34
|
-
.sort((a, b) => a[0] - b[0]);
|
|
35
|
-
const gaps = [];
|
|
36
|
-
let reach = 0;
|
|
37
|
-
for (const [s, e] of sorted) {
|
|
38
|
-
if (s > reach)
|
|
39
|
-
gaps.push([reach, s]);
|
|
40
|
-
if (e > reach)
|
|
41
|
-
reach = e;
|
|
42
|
-
}
|
|
43
|
-
if (reach < queryLen)
|
|
44
|
-
gaps.push([reach, queryLen]);
|
|
45
|
-
return gaps;
|
|
46
|
-
}
|
|
28
|
+
// THE SPAN ALGEBRA LIVES IN derivation.ts. `unaccountedBytes` and
|
|
29
|
+
// `unexplainedSpans` are the closure law's vocabulary — gap arithmetic over the
|
|
30
|
+
// asker's own bytes — and they moved to the layer that owns the law, so they
|
|
31
|
+
// have ONE home and are no longer asked of the tracer. This module keeps the
|
|
32
|
+
// inference TOLD as it happens, and reads the gaps only to render a label.
|
|
47
33
|
/** A human-readable label for the query bytes a mechanism's `accounted`
|
|
48
34
|
* spans leave unexplained — purely diagnostic (Task 2's negative evidence):
|
|
49
35
|
* it never changes a candidate's weight, only what the rationale trace
|
|
@@ -151,7 +137,16 @@ export class Rationale {
|
|
|
151
137
|
},
|
|
152
138
|
};
|
|
153
139
|
}
|
|
154
|
-
/**
|
|
140
|
+
/** WHY THIS NAME IS A FREE STRING, when the derivation's moves are a closed
|
|
141
|
+
* union: a mechanism name is WRITTEN and DISPLAYED, and it COMPOSES with
|
|
142
|
+
* the nesting — `mechanism` is the whole path (`["respond", "think",
|
|
143
|
+
* "recognise"]`), which no fixed union can express. Nothing branches on it:
|
|
144
|
+
* `nothing here drives the inference; it only WITNESSES it`. A vocabulary
|
|
145
|
+
* that is only witnessed needs no union; one that is read does
|
|
146
|
+
* (`DerivationMove`, in graph-search.ts). The asymmetry is the design, not
|
|
147
|
+
* a drift.
|
|
148
|
+
*
|
|
149
|
+
* Record a mechanism that has no sub-steps — its inputs and outputs are both
|
|
155
150
|
* known at the call site. Returns its index, for a later step to depend on. */
|
|
156
151
|
step(name, inputs, outputs, note, deps, data) {
|
|
157
152
|
const mechanism = this.path(name);
|
|
@@ -1,35 +1,27 @@
|
|
|
1
1
|
import type { MindContext } from "./types.js";
|
|
2
2
|
import type { Precomputed } from "./pipeline-mechanism.js";
|
|
3
|
-
|
|
4
|
-
* the question, so voicing it back only restates part of what was asked,
|
|
5
|
-
* never answers it. The exact guard recallByResonance already applies to
|
|
6
|
-
* its OWN grounding candidates (tier 1's `restates`, tier 2's subspan
|
|
7
|
-
* check, tier 0b's argument-binding subspan check) — every mechanism that
|
|
8
|
-
* walks a LEARNT CONTINUATION EDGE past an already-vetted grounding
|
|
9
|
-
* (reason()'s own hops below, and CAST's `projectCounterfactual` seat
|
|
10
|
-
* substitution — see cast.ts) needs the same guard applied to what the
|
|
11
|
-
* walk turns up, since `follow()`/`chooseNext`/`pivotInto` know nothing of
|
|
12
|
-
* the query at all — only of what structurally continues what. */
|
|
13
|
-
export declare function restatesQuery(query: Uint8Array, bytes: Uint8Array): boolean;
|
|
3
|
+
import { type DerivationState, type Span } from "./derivation.js";
|
|
14
4
|
/** Extend a grounded answer forward across facts (multi-hop reasoning).
|
|
15
5
|
* Pivots on the longest unconsumed learnt context each answer contains,
|
|
16
|
-
* then follows the pivot's continuation to the next fact.
|
|
17
|
-
*
|
|
6
|
+
* then follows the pivot's continuation to the next fact. **The chain ends
|
|
7
|
+
* when it STOPS, never when a count runs out**: every exit is a refusal (no
|
|
8
|
+
* pivot, no forward step, no question material carried) and the walk is bounded
|
|
9
|
+
* by the material and the graph — `consumed` refuses to revisit a node. There
|
|
10
|
+
* is no hop allowance, so this doc deliberately names no `cfg` capacity: the
|
|
11
|
+
* cover prices every hop at `STEP` and lets the search decide the depth, and a
|
|
12
|
+
* second count here would be a second decision about the same thing.
|
|
13
|
+
* `preConsumed` carries node ids already
|
|
18
14
|
* spoken for by the grounding stage (cover/extract/CAST). `voiced` carries
|
|
19
15
|
* the BYTES of the anchors a mechanism declared it voiced (its `used` set),
|
|
20
16
|
* when it declared one — see the pivot's own containment rule. `pre` is the
|
|
21
17
|
* response's shared pre-computation — the post-grounding stages read the
|
|
22
18
|
* same container the mechanisms did. */
|
|
23
|
-
export declare function reason(ctx: MindContext, query: Uint8Array,
|
|
24
|
-
/** The query material the GROUNDING left uncovered — the cost ladder's own
|
|
25
|
-
* `unaccounted` spans. Only the reasoner's OWN extensions are judged
|
|
26
|
-
* against it; a mechanism carrying its own `used` set owns its shape. */
|
|
27
|
-
uncovered?: readonly (readonly [number, number])[]): Promise<Uint8Array>;
|
|
19
|
+
export declare function reason(ctx: MindContext, query: Uint8Array, d0: DerivationState, preConsumed: ReadonlySet<number>, pre: Precomputed, voiced?: readonly Uint8Array[]): Promise<DerivationState>;
|
|
28
20
|
/** Fuse independent points of attention into one answer (multi-topic).
|
|
29
21
|
* When the consensus climb finds more than one dominant point, each
|
|
30
22
|
* independent point grounds its own answer; they are bridged together
|
|
31
23
|
* by any learnt connector the graph holds between them. */
|
|
32
|
-
export declare function fuseAttention(ctx: MindContext, query: Uint8Array,
|
|
24
|
+
export declare function fuseAttention(ctx: MindContext, query: Uint8Array, state: DerivationState, pre: Precomputed,
|
|
33
25
|
/** True when `primary` never touched the consensus climb at all — e.g. a
|
|
34
26
|
* pure ALU computation, which has no anchor of its own. commitVotes
|
|
35
27
|
* ALWAYS admits the dominant root regardless of its vote (attention.ts:
|
|
@@ -43,4 +35,4 @@ unclimbed?: boolean,
|
|
|
43
35
|
* which is the layer that knows how a given grounding records its evidence;
|
|
44
36
|
* fuseAttention just reads a position from it. Empty or absent preserves
|
|
45
37
|
* the original behaviour exactly. */
|
|
46
|
-
primarySpans?: ReadonlyArray<
|
|
38
|
+
primarySpans?: ReadonlyArray<Span>): Promise<DerivationState>;
|