@hviana/sema 0.8.5 → 0.8.7
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/dist/src/meter.d.ts +21 -6
- package/dist/src/meter.js +21 -6
- package/dist/src/mind/attention.d.ts +5 -0
- package/dist/src/mind/derivation.d.ts +14 -9
- package/dist/src/mind/derivation.js +10 -1
- package/dist/src/mind/pipeline.js +9 -0
- package/dist/src/mind/reasoning.js +95 -5
- package/dist/src/mind/traverse.d.ts +7 -1
- package/dist/src/mind/traverse.js +7 -1
- package/docs/INDEX.md +1 -1
- package/docs/INVARIANTS.md +1 -1
- package/docs/architecture/closure.md +17 -2
- package/docs/harness/gates.md +1 -1
- package/jsr.json +1 -1
- package/package.json +1 -1
- package/src/meter.ts +21 -6
- package/src/mind/attention.ts +5 -0
- package/src/mind/derivation.ts +28 -10
- package/src/mind/pipeline.ts +9 -0
- package/src/mind/reasoning.ts +145 -5
- package/src/mind/traverse.ts +7 -1
- package/test/121-the-extension-does-not-grow-with-the-corpus.test.mjs +3 -3
- package/test/136-the-two-named-limits.test.mjs +1 -1
- package/test/142-the-layer-offers-only-what-the-law-admits.test.mjs +155 -0
- package/test/143-cycles-terminate-and-are-not-closure.test.mjs +62 -0
- package/test/144-identity-is-content.test.mjs +55 -0
- package/test/145-the-instrument-answers.test.mjs +58 -0
- package/test/146-the-contains-gate.test.mjs +67 -0
- package/test/147-the-witness-ladder.test.mjs +76 -0
- package/test/55-cost-meter.test.mjs +2 -2
package/dist/src/meter.d.ts
CHANGED
|
@@ -199,15 +199,30 @@ 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;
|
|
208
223
|
/** Bytes of the question's REMAINDER a step CONSUMED — the drop the law's own
|
|
209
224
|
* `advance` makes when a declared move carries the material it accounts for.
|
|
210
|
-
* Read with {@link reasonSteps} and {@link
|
|
225
|
+
* Read with {@link reasonSteps} and {@link reasonAccountedBytes}: carrying is
|
|
211
226
|
* the engagement, this is the consumption, and before it the second was
|
|
212
227
|
* invisible. */
|
|
213
228
|
closureDrainedBytes: number;
|
package/dist/src/meter.js
CHANGED
|
@@ -209,15 +209,30 @@ 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;
|
|
218
233
|
/** Bytes of the question's REMAINDER a step CONSUMED — the drop the law's own
|
|
219
234
|
* `advance` makes when a declared move carries the material it accounts for.
|
|
220
|
-
* Read with {@link reasonSteps} and {@link
|
|
235
|
+
* Read with {@link reasonSteps} and {@link reasonAccountedBytes}: carrying is
|
|
221
236
|
* the engagement, this is the consumption, and before it the second was
|
|
222
237
|
* invisible. */
|
|
223
238
|
closureDrainedBytes = 0;
|
|
@@ -203,6 +203,11 @@ export interface ClimbConsensusData {
|
|
|
203
203
|
total: number;
|
|
204
204
|
};
|
|
205
205
|
regions?: ConsensusRegionTrace[];
|
|
206
|
+
/** A NAME SHARED WITH THE LAW, AND NOT THE SAME THING: these are the reaches
|
|
207
|
+
* the consensus climb took, for the trace. The law's `Continuation.reaches`
|
|
208
|
+
* (derivation.ts) is a producer's claim that a step moves — different type,
|
|
209
|
+
* different owner, no relation. Kept distinct rather than renamed because the
|
|
210
|
+
* trace's own vocabulary is about the climb, not about derivation. */
|
|
206
211
|
reaches?: ConsensusReachTrace[];
|
|
207
212
|
crossRegion?: {
|
|
208
213
|
eligibleRegions: number;
|
|
@@ -176,14 +176,19 @@ export declare function advance(d: DerivationState, t: Continuation, explains: R
|
|
|
176
176
|
/** What a layer offers the law: the next continuation of a state, or null when
|
|
177
177
|
* it has none. A layer OFFERS; the law disposes.
|
|
178
178
|
*
|
|
179
|
-
* ONE OFFER
|
|
180
|
-
*
|
|
181
|
-
*
|
|
182
|
-
*
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
*
|
|
186
|
-
*
|
|
179
|
+
* ONE OFFER AT A TIME: {@link closure} asks again only while the law admits what
|
|
180
|
+
* was offered, so a refusal ends the walk. A layer must not offer candidates
|
|
181
|
+
* one at a time and expect the walk to continue after a refusal — its own
|
|
182
|
+
* fallbacks belong inside this function, and the producers do exactly that:
|
|
183
|
+
* they choose between the forward absorb and the pivot before offering.
|
|
184
|
+
*
|
|
185
|
+
* WHAT `null` DOES NOT SAY: it is not a claim of exhaustion. A layer returns
|
|
186
|
+
* null for several distinct reasons — it exhausted its enumeration, it refused a
|
|
187
|
+
* candidate it had reached, or a read bound cut one off — and the law cannot tell
|
|
188
|
+
* them apart: it reads every one as "no continuation exists". The layer's reasons
|
|
189
|
+
* are therefore made OBSERVABLE where they happen, on the rationale's own channel
|
|
190
|
+
* (`enumerationExhausted`, `pivotCandidateRefused`, `absorbCandidateRefused`), and
|
|
191
|
+
* it is there — not here — that a reader learns which of them stopped the walk. */
|
|
187
192
|
export type Offer = (d: DerivationState) => Promise<Continuation | null>;
|
|
188
193
|
/** THE CLOSURE — the walk of {@link advance} over the continuations `offer`
|
|
189
194
|
* proposes, run until the layer has nothing further to offer or the law refuses
|
|
@@ -196,6 +201,6 @@ export type Offer = (d: DerivationState) => Promise<Continuation | null>;
|
|
|
196
201
|
* Nothing here counts steps, and nothing here decides admissibility. */
|
|
197
202
|
export declare function closure(d: DerivationState, query: Uint8Array, W: number, offer: Offer,
|
|
198
203
|
/** Called for each step the law admits, with the state before and after. */
|
|
199
|
-
onTaken?: (before: DerivationState, after: DerivationState) => void,
|
|
204
|
+
onTaken?: (before: DerivationState, after: DerivationState, witnesses: ReadonlyArray<Witness>) => void,
|
|
200
205
|
/** Called when the law refused the continuation the layer offered. */
|
|
201
206
|
onRefused?: (at: DerivationState) => void): Promise<DerivationState>;
|
|
@@ -234,6 +234,15 @@ export function closed(d) {
|
|
|
234
234
|
export function admissible(d, t, query, W) {
|
|
235
235
|
if (d.fixed)
|
|
236
236
|
return null;
|
|
237
|
+
// THE GATE THAT NEVER FIRES, AND WHY IT STAYS. `contains` is the step's claim
|
|
238
|
+
// to BE a continuation of this product at all, and the formula is stated with
|
|
239
|
+
// it (see the doc above). Every producer in the engine declares it true — the
|
|
240
|
+
// three literals in reasoning.ts are constants, measured — so this line cannot
|
|
241
|
+
// reject anything today. It stays because the claim is what makes an `Offer`
|
|
242
|
+
// answerable: a layer that handed over something it does not call a
|
|
243
|
+
// continuation would be refused here rather than trusted. What it must NOT be
|
|
244
|
+
// is a place where a producer says "false" to end a walk: the walk ends by
|
|
245
|
+
// offering nothing (`null`), which is the contract.
|
|
237
246
|
if (!t.contains)
|
|
238
247
|
return null;
|
|
239
248
|
if (closed(d))
|
|
@@ -321,7 +330,7 @@ onRefused) {
|
|
|
321
330
|
return d;
|
|
322
331
|
}
|
|
323
332
|
const next = advance(d, t, explains);
|
|
324
|
-
onTaken?.(d, next);
|
|
333
|
+
onTaken?.(d, next, explains);
|
|
325
334
|
d = next;
|
|
326
335
|
}
|
|
327
336
|
}
|
|
@@ -451,6 +451,15 @@ export async function think(ctx, query, mechs) {
|
|
|
451
451
|
meter.postGroundingRemainderSpans += uncovered.length;
|
|
452
452
|
meter.postGroundingRemainderBytes += unaccountedBytes(uncovered);
|
|
453
453
|
}
|
|
454
|
+
// THE WALK THAT DOES NOT RUN, NAMED — the audit's point 1 could not attribute
|
|
455
|
+
// real questions that stopped with no note anywhere. They never reached the
|
|
456
|
+
// offer: `decided.complete` says the grounding supplied a fixed point, so the
|
|
457
|
+
// walk is skipped BY DESIGN and the state is the grounding's own. That state
|
|
458
|
+
// carries `fixed: true` (the trace already reports it), and the law's first
|
|
459
|
+
// clause refuses any continuation against it — so there is no `null` here to
|
|
460
|
+
// read as exhaustion, and the `Offer` contract is not in play at all. The
|
|
461
|
+
// silent stop is therefore a NAMED state, not a gap.
|
|
462
|
+
//
|
|
454
463
|
// THE WALK CONSUMES AND RETURNS A STATE. It is handed the derivation's own —
|
|
455
464
|
// the grounding's product, accounting, remainder and cost — and hands back the
|
|
456
465
|
// state it advanced to, so what follows reads a state rather than bytes plus a
|
|
@@ -39,6 +39,13 @@ export async function reason(ctx, query, d0, preConsumed, pre, voiced = []) {
|
|
|
39
39
|
// broad structural gate; pinned by test/31-audit.
|
|
40
40
|
const qId = pre.queryResolved;
|
|
41
41
|
if (qId !== null && ctx.store.prevCount(qId) > 0) {
|
|
42
|
+
// THE ECHO GUARD, NAMED — the audit's point 1 could not attribute two real
|
|
43
|
+
// walks that stopped with no note at all, and this is where one of them went:
|
|
44
|
+
// the query IS a learnt continuation, so the reasoner returns the grounded
|
|
45
|
+
// read-out and never offers anything. Without this note the walk looks like
|
|
46
|
+
// an unexplained stop; with it, "no note" can only mean the offer was never
|
|
47
|
+
// asked. No decision changes: the guard returns exactly where it did.
|
|
48
|
+
ctx.trace?.step("echoGuard", [rItem(query, "query")], [], "the query is itself a learnt continuation — answering the grounded read-out without walking");
|
|
42
49
|
return d0;
|
|
43
50
|
}
|
|
44
51
|
// Consume a node and its neighbours for pivot-cycle prevention — CAPPED at
|
|
@@ -183,6 +190,8 @@ export async function reason(ctx, query, d0, preConsumed, pre, voiced = []) {
|
|
|
183
190
|
// admitted.
|
|
184
191
|
let pending = null;
|
|
185
192
|
const offer = async (d) => {
|
|
193
|
+
if (ctx.meter)
|
|
194
|
+
ctx.meter.offerRuns += 1;
|
|
186
195
|
const cur = d.product;
|
|
187
196
|
// The first step's `cur` IS the grounding's product, so the guard above
|
|
188
197
|
// already resolved it and read its reverse edges — reuse both.
|
|
@@ -196,8 +205,30 @@ export async function reason(ctx, query, d0, preConsumed, pre, voiced = []) {
|
|
|
196
205
|
// fixpoint falls through to the pivot step instead. Offered with `moves`:
|
|
197
206
|
// completing the answer's OWN learnt form is an identity step, not a claim
|
|
198
207
|
// about the asker's material.
|
|
199
|
-
|
|
200
|
-
|
|
208
|
+
// THE READ, KEPT — its LENGTH is free and it is the only instrument the
|
|
209
|
+
// bound has: a read that came back full may have been cut off, and a read
|
|
210
|
+
// that came back short did not. No second read is paid for this.
|
|
211
|
+
const outs = curId !== null ? ctx.store.nextFirst(curId, bound) : [];
|
|
212
|
+
const saturated = outs.length >= bound;
|
|
213
|
+
// THE RE-REACH, NAMED — the audit's structural-identity case (its test G), and
|
|
214
|
+
// the silent path it hid in. MEASURED, and this is the point's closure: across
|
|
215
|
+
// thirteen real questions on the trained store — the roteiro's ten plus three —
|
|
216
|
+
// this note fires ZERO times. The case, if it exists in this engine, is not on
|
|
217
|
+
// that material. It is not unimplementable, it is unobserved, and the audit's
|
|
218
|
+
// own rule is that an unobserved claim stays declared as unobserved: a
|
|
219
|
+
// distinction between legitimate convergence and a cycle cannot be implemented
|
|
220
|
+
// responsibly before it is seen, and the brief's section 13 puts measurement
|
|
221
|
+
// before code. What exists here is the instrument that will show it the moment
|
|
222
|
+
// it happens. When every successor of the current product has already
|
|
223
|
+
// been spoken for, the absorb above is skipped WITHOUT a word and the walk
|
|
224
|
+
// falls to the pivot: the same structure reached again is indistinguishable
|
|
225
|
+
// from having none. This note does not change the decision — it makes the
|
|
226
|
+
// state observable first, because the distinction between a legitimate
|
|
227
|
+
// convergence and a cycle cannot be implemented responsibly until it is seen.
|
|
228
|
+
if (curId !== null && outs.length > 0 && !outs.some((n) => !consumed.has(n))) {
|
|
229
|
+
ctx.trace?.step("reachAlreadySpokenFor", [rItem(cur, "answer")], [], `every continuation of this product (${outs.length}) has already been spoken for — the same structure, reached again`);
|
|
230
|
+
}
|
|
231
|
+
if (curId !== null && outs.some((n) => !consumed.has(n))) {
|
|
201
232
|
const fwd = await follow(ctx, curId, qv);
|
|
202
233
|
const fwdId = fwd !== null ? resolve(ctx, fwd) : null;
|
|
203
234
|
if (fwd !== null && !bytesEqual(fwd, cur) &&
|
|
@@ -207,16 +238,55 @@ export async function reason(ctx, query, d0, preConsumed, pre, voiced = []) {
|
|
|
207
238
|
pending = { kind: "absorb", cur, curId, fwd };
|
|
208
239
|
return { product: fwd, contains: true, reaches: true, cost: STEP };
|
|
209
240
|
}
|
|
241
|
+
// THE ABSORB'S OWN REFUSALS, TOLD APART — a learnt continuation existed
|
|
242
|
+
// and was declined, so the walk falls through to the pivot rather than
|
|
243
|
+
// ending. Which of the four reasons it was is exactly what the rationale
|
|
244
|
+
// could not say before: `null` at the end of the walk is one state, and
|
|
245
|
+
// this is another (AGENTS §6 — the note belongs where the mechanism emits
|
|
246
|
+
// it, not in a counter beside it).
|
|
247
|
+
const whyAbsorb = fwd === null
|
|
248
|
+
? "the unconsumed edge led nowhere"
|
|
249
|
+
: bytesEqual(fwd, cur)
|
|
250
|
+
? "the continuation reached was the product already in hand"
|
|
251
|
+
: fwdId !== null && consumed.has(fwdId)
|
|
252
|
+
? "the continuation reached had already been spoken for"
|
|
253
|
+
: "this continuation only restates the question";
|
|
254
|
+
ctx.trace?.step("absorbCandidateRefused", [rItem(cur, "answer")], [], `${whyAbsorb} — falling through to the pivot`);
|
|
255
|
+
}
|
|
256
|
+
if (saturated) {
|
|
257
|
+
// THE BUDGET, NAMED — the audit's point 2. `nextFirst` is read with a cap
|
|
258
|
+
// (`hubBound`), so a saturated read may have hidden a continuation, and the
|
|
259
|
+
// walk would end as if none existed. The note says MAY, because the length
|
|
260
|
+
// cannot tell a full read from a truncated one; it can only tell that this
|
|
261
|
+
// is where a cut would have happened.
|
|
262
|
+
ctx.trace?.step("readBoundSaturated", [rItem(cur, "answer")], [], "the read came back full — a continuation may have been cut off by the bound");
|
|
210
263
|
}
|
|
211
264
|
// Pivot: the longest unconsumed learnt context the answer contains.
|
|
212
265
|
consumeAll(curId);
|
|
213
266
|
const pivot = await pivotInto(ctx, cur, consumed, voiced);
|
|
214
|
-
if (pivot === null)
|
|
267
|
+
if (pivot === null) {
|
|
268
|
+
// THE ENUMERATION, DECLARED — the one duty the law cannot perform for the
|
|
269
|
+
// layer: only the layer knows that it has nothing left to offer. Before
|
|
270
|
+
// this note the walk ended in a bare `null`, indistinguishable from the
|
|
271
|
+
// causes below it; a reader of the rationale could not tell "exhausted"
|
|
272
|
+
// from "the candidate was refused" (AGENTS §6: a gap in instrumentation
|
|
273
|
+
// is a defect IN the instrumentation).
|
|
274
|
+
ctx.trace?.step("enumerationExhausted", [rItem(cur, "answer")], [], "the layer has no further candidate — its enumeration is exhausted");
|
|
215
275
|
return null;
|
|
276
|
+
}
|
|
216
277
|
const fc = await follow(ctx, pivot, qv);
|
|
217
278
|
consumeAll(pivot);
|
|
218
279
|
if (fc === null || bytesEqual(fc, cur) ||
|
|
219
280
|
restates(query, fc, 0, { proper: true })) {
|
|
281
|
+
// THE THREE REFUSALS, TOLD APART — a candidate was reached and declined,
|
|
282
|
+
// which is NOT the same state as having none: the law reads both as "no
|
|
283
|
+
// continuation", but the rationale should not.
|
|
284
|
+
const why = fc === null
|
|
285
|
+
? "the pivot's context carried no continuation"
|
|
286
|
+
: bytesEqual(fc, cur)
|
|
287
|
+
? "the continuation reached was the product already in hand"
|
|
288
|
+
: "this continuation only restates the question";
|
|
289
|
+
ctx.trace?.step("pivotCandidateRefused", [rItem(cur, "answer")], [], `${why} — refused`);
|
|
220
290
|
return null;
|
|
221
291
|
}
|
|
222
292
|
pending = { kind: "pivot", cur, pivot, fc };
|
|
@@ -232,8 +302,9 @@ export async function reason(ctx, query, d0, preConsumed, pre, voiced = []) {
|
|
|
232
302
|
cost: STEP,
|
|
233
303
|
};
|
|
234
304
|
};
|
|
235
|
-
const closed_ = await closure(d0, query, W, offer, (before, after) => {
|
|
305
|
+
const closed_ = await closure(d0, query, W, offer, (before, after, witnesses) => {
|
|
236
306
|
if (ctx.meter) {
|
|
307
|
+
ctx.meter.reasonCarriedBytes += witnesses.reduce((n, w) => n + (w.window ? w.window[1] - w.window[0] : 0), 0);
|
|
237
308
|
ctx.meter.closureDrainedBytes += unaccountedBytes(before.remainder) -
|
|
238
309
|
unaccountedBytes(after.remainder);
|
|
239
310
|
}
|
|
@@ -251,6 +322,10 @@ export async function reason(ctx, query, d0, preConsumed, pre, voiced = []) {
|
|
|
251
322
|
ctx.trace?.step("pivotStep", [rItem(p.cur, "answer"), rNode(ctx, p.pivot, "pivot")], [rItem(p.fc, "answer", resolve(ctx, p.fc) ?? undefined)], "pivot on the shared span this answer contains, then step forward across that fact");
|
|
252
323
|
}
|
|
253
324
|
}, (at) => {
|
|
325
|
+
// THE LAW REFUSED — counted where it happened, before the bookkeeping
|
|
326
|
+
// below decides whether there is a step to report.
|
|
327
|
+
if (ctx.meter)
|
|
328
|
+
ctx.meter.lawRejects += 1;
|
|
254
329
|
const p = pending;
|
|
255
330
|
pending = null;
|
|
256
331
|
if (p === null || p.kind !== "pivot")
|
|
@@ -266,6 +341,20 @@ export async function reason(ctx, query, d0, preConsumed, pre, voiced = []) {
|
|
|
266
341
|
ctx.trace?.step("pivotRefused", [rItem(p.cur, "answer"), rItem(query, "query")], at.remainder.map(([a, b]) => rItem(query.subarray(a, b), "uncovered")), `the step carries none of the question material the grounding left ` +
|
|
267
342
|
`unaccounted (${left} byte(s) in ${at.remainder.length} span(s)) — refused`);
|
|
268
343
|
});
|
|
344
|
+
// THE WALK'S OWN ENDING, NAMED — the audit's point 1. Every stop INSIDE the
|
|
345
|
+
// offer now has a note, but a walk can also end without the offer ever being
|
|
346
|
+
// asked, or after a step the law took and then found nothing to follow: those
|
|
347
|
+
// ended as "no note at all", indistinguishable from a mechanism that never ran.
|
|
348
|
+
// Two endings cover every remaining case, and together they make a silent stop
|
|
349
|
+
// impossible — which is what the `Offer` contract needs, because `null` is read
|
|
350
|
+
// as exhaustion and exhaustion must be a statement, not an absence.
|
|
351
|
+
t ??= ctx.trace?.enter("reason", [rItem(startedFrom, "grounded")]);
|
|
352
|
+
if (closed_.remainder.length === 0) {
|
|
353
|
+
ctx.trace?.step("walkClosed", [rItem(closed_.product, "answer")], [], "the derivation is closed — nothing is left unaccounted for");
|
|
354
|
+
}
|
|
355
|
+
else {
|
|
356
|
+
ctx.trace?.step("walkEndedWithoutOffer", [rItem(closed_.product, "answer")], closed_.remainder.map(([a, b]) => rItem(query.subarray(a, b), "uncovered")), `the walk ended with ${unaccountedBytes(closed_.remainder)} byte(s) unaccounted and no further offer — no structural continuation`);
|
|
357
|
+
}
|
|
269
358
|
// INSTRUMENTATION ONLY — the extension's two facts, untraced (meter.ts
|
|
270
359
|
// contract 1: a counter never reaches a decision). They are what a caller
|
|
271
360
|
// needs to PRICE the extension instead of taking it unconditionally, and both
|
|
@@ -279,7 +368,7 @@ export async function reason(ctx, query, d0, preConsumed, pre, voiced = []) {
|
|
|
279
368
|
// over the tail of the state's list — and computed ONLY when a meter is
|
|
280
369
|
// attached: this used to slice and MAP a fresh array on every response, for a
|
|
281
370
|
// counter that usually does not exist. One allocation, under the meter.
|
|
282
|
-
ctx.meter.
|
|
371
|
+
ctx.meter.reasonAccountedBytes += unaccountedBytes(closed_.accounted.slice(d0.accounted.length));
|
|
283
372
|
}
|
|
284
373
|
t?.done([rItem(closed_.product, "answer", resolve(ctx, closed_.product) ?? undefined)],
|
|
285
374
|
// A FIXPOINT: no further step was offered, or the law refused the one that
|
|
@@ -489,6 +578,7 @@ primarySpans = []) {
|
|
|
489
578
|
return { ...state, product: out };
|
|
490
579
|
const fused = advance(state, fusedT, fusedWitness);
|
|
491
580
|
if (ctx.meter) {
|
|
581
|
+
ctx.meter.reasonCarriedBytes += fusedWitness.reduce((n, w) => n + (w.window ? w.window[1] - w.window[0] : 0), 0);
|
|
492
582
|
ctx.meter.closureDrainedBytes += unaccountedBytes(state.remainder) -
|
|
493
583
|
unaccountedBytes(fused.remainder);
|
|
494
584
|
}
|
|
@@ -95,7 +95,13 @@ export declare function hubCap<T>(ctx: MindContext, ids: readonly T[]): readonly
|
|
|
95
95
|
/** Whether `descendant` lies within `ancestor`'s subtree — a structural DAG
|
|
96
96
|
* relation read off the hash-consed `kids` lists, by a bounded explicit-stack
|
|
97
97
|
* descent. Used by articulation to keep a voice from revoicing a fragment
|
|
98
|
-
* OF that voice.
|
|
98
|
+
* OF that voice.
|
|
99
|
+
*
|
|
100
|
+
* A HOMONYM, NOT A RELATIVE: the law's `Continuation.contains` (derivation.ts) is
|
|
101
|
+
* a producer's claim that its step IS a continuation, a boolean on one step. This
|
|
102
|
+
* is a structural relation between two nodes in the DAG. The shared word is
|
|
103
|
+
* deliberate vocabulary — "containment" is what both name — and the two must not be
|
|
104
|
+
* read as one. */
|
|
99
105
|
export declare function contains(ctx: MindContext, ancestor: number, descendant: number): boolean;
|
|
100
106
|
/** Whether a continuation edge joins the two forms, in either direction —
|
|
101
107
|
* the EXACT half's veto on calling them synonyms.
|
|
@@ -495,7 +495,13 @@ export function hubCap(ctx, ids) {
|
|
|
495
495
|
/** Whether `descendant` lies within `ancestor`'s subtree — a structural DAG
|
|
496
496
|
* relation read off the hash-consed `kids` lists, by a bounded explicit-stack
|
|
497
497
|
* descent. Used by articulation to keep a voice from revoicing a fragment
|
|
498
|
-
* OF that voice.
|
|
498
|
+
* OF that voice.
|
|
499
|
+
*
|
|
500
|
+
* A HOMONYM, NOT A RELATIVE: the law's `Continuation.contains` (derivation.ts) is
|
|
501
|
+
* a producer's claim that its step IS a continuation, a boolean on one step. This
|
|
502
|
+
* is a structural relation between two nodes in the DAG. The shared word is
|
|
503
|
+
* deliberate vocabulary — "containment" is what both name — and the two must not be
|
|
504
|
+
* read as one. */
|
|
499
505
|
export function contains(ctx, ancestor, descendant) {
|
|
500
506
|
if (ancestor === descendant)
|
|
501
507
|
return true;
|
package/docs/INDEX.md
CHANGED
|
@@ -36,7 +36,7 @@ proof in `test/` (pins that fail when the law is broken).
|
|
|
36
36
|
| 11 | `docs/architecture/memoization.md` | `Precomputed` is per-response lazy cache (promise-cached async); `beginResponse`/`endResponse` lifecycle | `test/42` |
|
|
37
37
|
| 12 | `docs/architecture/saturation.md` | Every walk names a deciding saturation beside its cap; cap is safety net, not decision | `test/27`, `test/16` |
|
|
38
38
|
| 13 | `docs/architecture/meter.md` | `meter.ts` is write-only work accounting; counts are exact, phases nest | `test/55` |
|
|
39
|
-
| 14 | `docs/architecture/closure.md` | A derivation is closed when its structure accounts for the question's remainder; every transition asks that law | `test/133`–`
|
|
39
|
+
| 14 | `docs/architecture/closure.md` | A derivation is closed when its structure accounts for the question's remainder; every transition asks that law | `test/133`–`147` |
|
|
40
40
|
|
|
41
41
|
## Mechanisms (8)
|
|
42
42
|
|
package/docs/INVARIANTS.md
CHANGED
|
@@ -15,4 +15,4 @@
|
|
|
15
15
|
| 11 | Honest degradation | `src/mind/pipeline.ts:weight=moves+PASS*unaccounted` `src/store.ts:BoundedMap:miss→re-derive` | `test/28` `test/84` | `store.md`+`caches.md` |
|
|
16
16
|
| 12 | Meter contracts | `src/meter.ts:Meter,PhaseCost,time` `src/mind/pipeline-mechanism.ts:Precomputed.shared` | `test/55` | `meter.md` |
|
|
17
17
|
| 13 | Saturation | `traverse.ts:edgeAncestors,types.ts:SaturationReason` `src/mind/junction.ts:junctionContainersFrom` `src/mind/resonance.ts:pivotInto` | `test/27` `test/16` | `saturation.md` |
|
|
18
|
-
| 14 | Closure | `src/mind/derivation.ts:closed,admissible,advance` | `test/133`–`
|
|
18
|
+
| 14 | Closure | `src/mind/derivation.ts:closed,admissible,advance` | `test/133`–`147` | `closure.md` |
|
|
@@ -23,6 +23,14 @@ field, no producer field, and no count of any kind. The witnesses `contains` and
|
|
|
23
23
|
`moves` are the LAYER's: it holds the structure and hands them in, so the law
|
|
24
24
|
never probes the store.
|
|
25
25
|
|
|
26
|
+
## The boundary
|
|
27
|
+
|
|
28
|
+
`product` (what it stands on, its identity being `resolve(product)`),
|
|
29
|
+
`accounted` (the price its steps summed) and `remainder` (the question's debt,
|
|
30
|
+
at one quantum) are the derivation's own. What it REACHED and what it SPENT are
|
|
31
|
+
the layer's (`reaches`, `consumed`), never a field here: the law decides
|
|
32
|
+
admission and consumption, the layer decides frontier and termination.
|
|
33
|
+
|
|
26
34
|
## The transition
|
|
27
35
|
|
|
28
36
|
`admissible(state, continuation, query, W)` returns the witnesses the step pays
|
|
@@ -33,6 +41,10 @@ consumes what its window proves. Whole-span draining was refuted by `test/110`,
|
|
|
33
41
|
the window alone by `test/138`. The state is BORN owing what its product does
|
|
34
42
|
not carry.
|
|
35
43
|
|
|
44
|
+
The walk ends when the layer stops offering or the law refuses; owning no
|
|
45
|
+
search, the law cannot prevent a cycle — that is the layer's, over the structure
|
|
46
|
+
it holds.
|
|
47
|
+
|
|
36
48
|
## One cost home
|
|
37
49
|
|
|
38
50
|
`moves + PASS · unaccountedBytes` is computed in ONE place (`pipeline.ts`,
|
|
@@ -60,6 +72,9 @@ vocabulary, not the tracer's.
|
|
|
60
72
|
## Pins
|
|
61
73
|
|
|
62
74
|
- `test/133`–`137` — the law's home, readings, refusal, limits.
|
|
63
|
-
- `test/138` — a cycle cannot close it
|
|
75
|
+
- `test/138` — a cycle cannot close it, a carried move can.
|
|
64
76
|
- `test/139` — carrying is ENGAGEMENT, not explanation.
|
|
65
|
-
- `test/140` — irrelevant supply changes
|
|
77
|
+
- `test/140` — irrelevant supply changes nothing.
|
|
78
|
+
- `test/142`, `test/143` — the offer's contract, and the cycles.
|
|
79
|
+
- `test/144`, `test/146`, `test/147` — identity is content, the `contains` gate,
|
|
80
|
+
the witness ladder.
|
package/docs/harness/gates.md
CHANGED
|
@@ -13,7 +13,7 @@ Guards honest silence, determinism, and every pinned contract. Silence:
|
|
|
13
13
|
unrelated queries ground to nothing (`test/28`, `50`, `56`, `67`, `76`, `84`).
|
|
14
14
|
Determinism: same seed + deposit order + query gives byte-identical answer
|
|
15
15
|
(`test/20`). Every invariant is pinned, the closure law included
|
|
16
|
-
(`test/133`–`
|
|
16
|
+
(`test/133`–`147`). §14–25 (pipeline), §64 (derived thresholds), AGENTS.md §2
|
|
17
17
|
invariants 1–5.
|
|
18
18
|
|
|
19
19
|
## 2 — Work accounting (profiler)
|
package/jsr.json
CHANGED
package/package.json
CHANGED
package/src/meter.ts
CHANGED
|
@@ -267,15 +267,30 @@ export class Meter {
|
|
|
267
267
|
* not computable at all. With it, the price of extending the answer is
|
|
268
268
|
* `reasonSteps · STEP`, the ladder's own value for following an edge. */
|
|
269
269
|
reasonSteps = 0;
|
|
270
|
-
/** Bytes
|
|
271
|
-
*
|
|
272
|
-
*
|
|
273
|
-
*
|
|
274
|
-
*
|
|
270
|
+
/** Bytes the admitted steps ACCOUNTED for — the witnesses' spans, summed by the
|
|
271
|
+
* law's own function over the tail of the state's accounting. It is NOT what
|
|
272
|
+
* they carried: a step admitted by `reaches` may declare spans it holds no
|
|
273
|
+
* window of, and then it accounts without carrying and consumes nothing (see
|
|
274
|
+
* {@link closureDrainedBytes}). Read with {@link reasonSteps}: one is the
|
|
275
|
+
* price, the other the accounting. */
|
|
276
|
+
reasonAccountedBytes = 0;
|
|
277
|
+
/** Bytes of the QUESTION's own material an admitted step CARRIED — the windows
|
|
278
|
+
* of the remainder its product holds, read by the law's one reading. The
|
|
279
|
+
* accounting may be larger (a `reaches` step declares spans it holds no window
|
|
280
|
+
* of) and the consumption is the window of a step that also reaches, so the
|
|
281
|
+
* three form a lattice: consumed ⊆ carried ⊆ accounted. */
|
|
275
282
|
reasonCarriedBytes = 0;
|
|
283
|
+
/** Times the layer OFFERED a continuation to the law. Read with
|
|
284
|
+
* {@link lawRejects}: the offers the law refused are the Model X contract being
|
|
285
|
+
* exercised, and `offerRuns - lawRejects` is the accepted transitions. */
|
|
286
|
+
offerRuns = 0;
|
|
287
|
+
/** Times the law REFUSED the continuation the layer offered. A refusal is
|
|
288
|
+
* terminal by the layer's contract, so this counts the moments the contract
|
|
289
|
+
* mattered — zero means the walk never needed it. */
|
|
290
|
+
lawRejects = 0;
|
|
276
291
|
/** Bytes of the question's REMAINDER a step CONSUMED — the drop the law's own
|
|
277
292
|
* `advance` makes when a declared move carries the material it accounts for.
|
|
278
|
-
* Read with {@link reasonSteps} and {@link
|
|
293
|
+
* Read with {@link reasonSteps} and {@link reasonAccountedBytes}: carrying is
|
|
279
294
|
* the engagement, this is the consumption, and before it the second was
|
|
280
295
|
* invisible. */
|
|
281
296
|
closureDrainedBytes = 0;
|
package/src/mind/attention.ts
CHANGED
|
@@ -347,6 +347,11 @@ export interface ClimbConsensusData {
|
|
|
347
347
|
};
|
|
348
348
|
|
|
349
349
|
regions?: ConsensusRegionTrace[];
|
|
350
|
+
/** A NAME SHARED WITH THE LAW, AND NOT THE SAME THING: these are the reaches
|
|
351
|
+
* the consensus climb took, for the trace. The law's `Continuation.reaches`
|
|
352
|
+
* (derivation.ts) is a producer's claim that a step moves — different type,
|
|
353
|
+
* different owner, no relation. Kept distinct rather than renamed because the
|
|
354
|
+
* trace's own vocabulary is about the climb, not about derivation. */
|
|
350
355
|
reaches?: ConsensusReachTrace[];
|
|
351
356
|
|
|
352
357
|
crossRegion?: {
|
package/src/mind/derivation.ts
CHANGED
|
@@ -359,6 +359,15 @@ export function admissible(
|
|
|
359
359
|
W: number,
|
|
360
360
|
): ReadonlyArray<Witness> | null {
|
|
361
361
|
if (d.fixed) return null;
|
|
362
|
+
// THE GATE THAT NEVER FIRES, AND WHY IT STAYS. `contains` is the step's claim
|
|
363
|
+
// to BE a continuation of this product at all, and the formula is stated with
|
|
364
|
+
// it (see the doc above). Every producer in the engine declares it true — the
|
|
365
|
+
// three literals in reasoning.ts are constants, measured — so this line cannot
|
|
366
|
+
// reject anything today. It stays because the claim is what makes an `Offer`
|
|
367
|
+
// answerable: a layer that handed over something it does not call a
|
|
368
|
+
// continuation would be refused here rather than trusted. What it must NOT be
|
|
369
|
+
// is a place where a producer says "false" to end a walk: the walk ends by
|
|
370
|
+
// offering nothing (`null`), which is the contract.
|
|
362
371
|
if (!t.contains) return null;
|
|
363
372
|
if (closed(d)) return (t.explains ?? []).map((span) => ({ span }));
|
|
364
373
|
// MOVES BEFORE CARRIES, and that order is not arbitrary: a transition that
|
|
@@ -429,14 +438,19 @@ export function advance(
|
|
|
429
438
|
/** What a layer offers the law: the next continuation of a state, or null when
|
|
430
439
|
* it has none. A layer OFFERS; the law disposes.
|
|
431
440
|
*
|
|
432
|
-
* ONE OFFER
|
|
433
|
-
*
|
|
434
|
-
*
|
|
435
|
-
*
|
|
436
|
-
*
|
|
437
|
-
*
|
|
438
|
-
*
|
|
439
|
-
*
|
|
441
|
+
* ONE OFFER AT A TIME: {@link closure} asks again only while the law admits what
|
|
442
|
+
* was offered, so a refusal ends the walk. A layer must not offer candidates
|
|
443
|
+
* one at a time and expect the walk to continue after a refusal — its own
|
|
444
|
+
* fallbacks belong inside this function, and the producers do exactly that:
|
|
445
|
+
* they choose between the forward absorb and the pivot before offering.
|
|
446
|
+
*
|
|
447
|
+
* WHAT `null` DOES NOT SAY: it is not a claim of exhaustion. A layer returns
|
|
448
|
+
* null for several distinct reasons — it exhausted its enumeration, it refused a
|
|
449
|
+
* candidate it had reached, or a read bound cut one off — and the law cannot tell
|
|
450
|
+
* them apart: it reads every one as "no continuation exists". The layer's reasons
|
|
451
|
+
* are therefore made OBSERVABLE where they happen, on the rationale's own channel
|
|
452
|
+
* (`enumerationExhausted`, `pivotCandidateRefused`, `absorbCandidateRefused`), and
|
|
453
|
+
* it is there — not here — that a reader learns which of them stopped the walk. */
|
|
440
454
|
export type Offer = (d: DerivationState) => Promise<Continuation | null>;
|
|
441
455
|
|
|
442
456
|
/** THE CLOSURE — the walk of {@link advance} over the continuations `offer`
|
|
@@ -454,7 +468,11 @@ export async function closure(
|
|
|
454
468
|
W: number,
|
|
455
469
|
offer: Offer,
|
|
456
470
|
/** Called for each step the law admits, with the state before and after. */
|
|
457
|
-
onTaken?: (
|
|
471
|
+
onTaken?: (
|
|
472
|
+
before: DerivationState,
|
|
473
|
+
after: DerivationState,
|
|
474
|
+
witnesses: ReadonlyArray<Witness>,
|
|
475
|
+
) => void,
|
|
458
476
|
/** Called when the law refused the continuation the layer offered. */
|
|
459
477
|
onRefused?: (at: DerivationState) => void,
|
|
460
478
|
): Promise<DerivationState> {
|
|
@@ -467,7 +485,7 @@ export async function closure(
|
|
|
467
485
|
return d;
|
|
468
486
|
}
|
|
469
487
|
const next = advance(d, t, explains);
|
|
470
|
-
onTaken?.(d, next);
|
|
488
|
+
onTaken?.(d, next, explains);
|
|
471
489
|
d = next;
|
|
472
490
|
}
|
|
473
491
|
}
|
package/src/mind/pipeline.ts
CHANGED
|
@@ -664,6 +664,15 @@ export async function think(
|
|
|
664
664
|
meter.postGroundingRemainderSpans += uncovered.length;
|
|
665
665
|
meter.postGroundingRemainderBytes += unaccountedBytes(uncovered);
|
|
666
666
|
}
|
|
667
|
+
// THE WALK THAT DOES NOT RUN, NAMED — the audit's point 1 could not attribute
|
|
668
|
+
// real questions that stopped with no note anywhere. They never reached the
|
|
669
|
+
// offer: `decided.complete` says the grounding supplied a fixed point, so the
|
|
670
|
+
// walk is skipped BY DESIGN and the state is the grounding's own. That state
|
|
671
|
+
// carries `fixed: true` (the trace already reports it), and the law's first
|
|
672
|
+
// clause refuses any continuation against it — so there is no `null` here to
|
|
673
|
+
// read as exhaustion, and the `Offer` contract is not in play at all. The
|
|
674
|
+
// silent stop is therefore a NAMED state, not a gap.
|
|
675
|
+
//
|
|
667
676
|
// THE WALK CONSUMES AND RETURNS A STATE. It is handed the derivation's own —
|
|
668
677
|
// the grounding's product, accounting, remainder and cost — and hands back the
|
|
669
678
|
// state it advanced to, so what follows reads a state rather than bytes plus a
|