pi-fovea 0.29.2 → 0.30.0
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/LAWS.bend +110 -0
- package/PROOF.bend +118 -0
- package/README.md +11 -1
- package/THIRD_PARTY_NOTICES.md +12 -0
- package/dist/cli.mjs +835 -697
- package/docs/licenses/bend-apache-2.0.txt +202 -0
- package/docs/proofs.md +256 -0
- package/package.json +17 -5
- package/proofs/basis.bend +29 -0
- package/proofs/counts-proof.bend +71 -0
- package/proofs/counts.bend +24 -0
- package/proofs/disclosure.bend +31 -0
- package/proofs/heat.bend +54 -0
- package/proofs/kernel-abi.json +6 -0
- package/proofs/kernel-types.d.ts +3 -0
- package/proofs/kernel.bend +25 -0
- package/proofs/nat-proof.bend +65 -0
- package/scripts/check-proofs.mjs +123 -0
- package/scripts/compile-bend.mjs +61 -0
- package/src/core/disclosure.ts +20 -0
- package/src/core/heat.ts +20 -10
- package/src/core/render.ts +16 -12
- package/src/verified/generated/kernel.d.ts +9 -0
- package/src/verified/generated/kernel.js +81 -0
- package/src/verified/generated/manifest.json +29 -0
- package/src/verified/policy.ts +37 -0
package/LAWS.bend
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import Base
|
|
2
|
+
import ./proofs/disclosure.bend as D
|
|
3
|
+
import ./proofs/heat.bend as H
|
|
4
|
+
import ./proofs/kernel.bend as K
|
|
5
|
+
import ./proofs/basis.bend as B
|
|
6
|
+
|
|
7
|
+
# Proposed specifications extracted from render.ts and heat.ts. Review these independently
|
|
8
|
+
# of PROOF.bend; do not weaken a law to make an implementation pass.
|
|
9
|
+
|
|
10
|
+
# Disclosure: these six laws cover the entire five-Boolean input domain.
|
|
11
|
+
law scope_wins:
|
|
12
|
+
for excluded: Bool
|
|
13
|
+
for seen: Bool
|
|
14
|
+
for repeat: Bool
|
|
15
|
+
for nucleus: Bool
|
|
16
|
+
{K.disclosure(False{}, excluded, seen, repeat, nucleus) == D.Drop{} : D.Decision}
|
|
17
|
+
|
|
18
|
+
law exclusion_wins:
|
|
19
|
+
for scope: Bool
|
|
20
|
+
for seen: Bool
|
|
21
|
+
for repeat: Bool
|
|
22
|
+
for nucleus: Bool
|
|
23
|
+
{K.disclosure(scope, True{}, seen, repeat, nucleus) == D.Drop{} : D.Decision}
|
|
24
|
+
|
|
25
|
+
law fresh_revealed:
|
|
26
|
+
for repeat: Bool
|
|
27
|
+
for nucleus: Bool
|
|
28
|
+
{K.disclosure(True{}, False{}, False{}, repeat, nucleus) == D.Reveal{} : D.Decision}
|
|
29
|
+
|
|
30
|
+
law seen_suppressed:
|
|
31
|
+
for nucleus: Bool
|
|
32
|
+
{K.disclosure(True{}, False{}, True{}, False{}, nucleus) == D.Suppress{} : D.Decision}
|
|
33
|
+
|
|
34
|
+
law periphery_suppressed:
|
|
35
|
+
for repeat: Bool
|
|
36
|
+
{K.disclosure(True{}, False{}, True{}, repeat, False{}) == D.Suppress{} : D.Decision}
|
|
37
|
+
|
|
38
|
+
law nucleus_repeated:
|
|
39
|
+
for seen: Bool
|
|
40
|
+
{K.disclosure(True{}, False{}, seen, True{}, True{}) == D.Reveal{} : D.Decision}
|
|
41
|
+
|
|
42
|
+
# Executed natural-number accounting. This does NOT prove token estimation,
|
|
43
|
+
# renderer formatting, or binary-search monotonicity. Keep boundary tests.
|
|
44
|
+
law shown_bounded_by_total:
|
|
45
|
+
for +total: Nat
|
|
46
|
+
for requested: Nat
|
|
47
|
+
{Nat.is_le(K.shownCount(total, requested), total) == True{} : Bool}
|
|
48
|
+
|
|
49
|
+
law shown_bounded_by_request:
|
|
50
|
+
for total: Nat
|
|
51
|
+
for +requested: Nat
|
|
52
|
+
{Nat.is_le(K.shownCount(total, requested), requested) == True{} : Bool}
|
|
53
|
+
|
|
54
|
+
law counts_conserved:
|
|
55
|
+
for +total: Nat
|
|
56
|
+
for +requested: Nat
|
|
57
|
+
{Nat.add(K.shownCount(total, requested), K.remainingCount(total, requested)) == total : Nat}
|
|
58
|
+
|
|
59
|
+
law full_prefix_omits_nothing:
|
|
60
|
+
for +total: Nat
|
|
61
|
+
{K.remainingCount(total, total) == 0n : Nat}
|
|
62
|
+
|
|
63
|
+
law cap_idempotent:
|
|
64
|
+
for +total: Nat
|
|
65
|
+
for +cap: Nat
|
|
66
|
+
{K.shownCount(K.shownCount(total, cap), cap) == K.shownCount(total, cap) : Nat}
|
|
67
|
+
|
|
68
|
+
# Exact nonnegative rational transport model, not IEEE-754 or the exponential.
|
|
69
|
+
law heat_vector_add_mass:
|
|
70
|
+
for +xs: +List<Nat>
|
|
71
|
+
for +ys: +List<Nat>
|
|
72
|
+
{H.sum(H.add(xs, ys)) == Nat.add(H.sum(xs), H.sum(ys)) : Nat}
|
|
73
|
+
|
|
74
|
+
law heat_scale_mass:
|
|
75
|
+
for +mass: Nat
|
|
76
|
+
for +weights: +List<Nat>
|
|
77
|
+
{H.sum(H.scale(mass, weights)) == Nat.mul(mass, H.sum(weights)) : Nat}
|
|
78
|
+
|
|
79
|
+
# D = 1 + denominator is strictly positive. For source numerators a over Q,
|
|
80
|
+
# transport returns numerators over D*Q; this equality conserves rational mass.
|
|
81
|
+
law heat_transport_mass:
|
|
82
|
+
for +columns: +List<H.Column>
|
|
83
|
+
for +denominator: Nat
|
|
84
|
+
for normalized: H.Normalized(columns, 1n+denominator)
|
|
85
|
+
{H.sum(H.transport(columns)) == Nat.mul(H.input_mass(columns), 1n+denominator) : Nat}
|
|
86
|
+
|
|
87
|
+
law heat_singleton_mass:
|
|
88
|
+
for +mass: Nat
|
|
89
|
+
{H.sum(H.transport([H.Source{mass, [1n]}])) == mass : Nat}
|
|
90
|
+
|
|
91
|
+
# Executed basis-extension commands. Float64 evaluation remains host code.
|
|
92
|
+
law basis_empty_refused:
|
|
93
|
+
for order: Nat
|
|
94
|
+
{K.basisStep(0n, order) == B.Empty{} : B.Step}
|
|
95
|
+
|
|
96
|
+
law basis_complete_retained:
|
|
97
|
+
for +have: Nat
|
|
98
|
+
for +order: Nat
|
|
99
|
+
for complete: {Nat.is_le(1n+have, order) == False{} : Bool}
|
|
100
|
+
{K.basisStep(1n+have, order) == B.Done{} : B.Step}
|
|
101
|
+
|
|
102
|
+
law basis_first_order:
|
|
103
|
+
for order: Nat
|
|
104
|
+
{K.basisStep(1n, 1n+order) == B.First{} : B.Step}
|
|
105
|
+
|
|
106
|
+
law basis_next_exact:
|
|
107
|
+
for +have: Nat
|
|
108
|
+
for +order: Nat
|
|
109
|
+
for missing: {Nat.is_le(2n+have, order) == True{} : Bool}
|
|
110
|
+
{K.basisStep(2n+have, order) == B.Next{2n+have, 1n+have, have} : B.Step}
|
package/PROOF.bend
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import Base
|
|
2
|
+
import ./LAWS.bend as Laws
|
|
3
|
+
import ./proofs/disclosure.bend as D
|
|
4
|
+
import ./proofs/counts.bend as C
|
|
5
|
+
import ./proofs/counts-proof.bend as CP
|
|
6
|
+
import ./proofs/heat.bend as H
|
|
7
|
+
import ./proofs/nat-proof.bend as N
|
|
8
|
+
import ./proofs/kernel.bend as K
|
|
9
|
+
import ./proofs/basis.bend as B
|
|
10
|
+
|
|
11
|
+
def Laws.scope_wins(excluded, seen, repeat, nucleus):
|
|
12
|
+
{==}
|
|
13
|
+
|
|
14
|
+
def Laws.exclusion_wins(scope, seen, repeat, nucleus):
|
|
15
|
+
match scope:
|
|
16
|
+
case False{}:
|
|
17
|
+
{==}
|
|
18
|
+
case True{}:
|
|
19
|
+
{==}
|
|
20
|
+
|
|
21
|
+
def Laws.fresh_revealed(repeat, nucleus):
|
|
22
|
+
{==}
|
|
23
|
+
|
|
24
|
+
def Laws.seen_suppressed(nucleus):
|
|
25
|
+
{==}
|
|
26
|
+
|
|
27
|
+
def Laws.periphery_suppressed(repeat):
|
|
28
|
+
match repeat:
|
|
29
|
+
case False{}:
|
|
30
|
+
{==}
|
|
31
|
+
case True{}:
|
|
32
|
+
{==}
|
|
33
|
+
|
|
34
|
+
def Laws.nucleus_repeated(seen):
|
|
35
|
+
match seen:
|
|
36
|
+
case False{}:
|
|
37
|
+
{==}
|
|
38
|
+
case True{}:
|
|
39
|
+
{==}
|
|
40
|
+
|
|
41
|
+
def Laws.shown_bounded_by_total(total, requested):
|
|
42
|
+
+requested = requested
|
|
43
|
+
%Equal.sym(Nat, C.fastShown(total, requested), C.shown(total, requested), CP.shown_equiv(total, requested)) : {Nat.is_le(_, total) == True{} : Bool}
|
|
44
|
+
CP.bounded_total(total, requested)
|
|
45
|
+
|
|
46
|
+
def Laws.shown_bounded_by_request(total, requested):
|
|
47
|
+
+total = total
|
|
48
|
+
%Equal.sym(Nat, C.fastShown(total, requested), C.shown(total, requested), CP.shown_equiv(total, requested)) : {Nat.is_le(_, requested) == True{} : Bool}
|
|
49
|
+
CP.bounded_request(total, requested)
|
|
50
|
+
|
|
51
|
+
def Laws.counts_conserved(total, requested):
|
|
52
|
+
%Equal.sym(Nat, C.fastShown(total, requested), C.shown(total, requested), CP.shown_equiv(total, requested)) : {Nat.add(_, C.fastRemaining(total, requested)) == total : Nat}
|
|
53
|
+
%Equal.sym(Nat, C.fastRemaining(total, requested), C.remaining(total, requested), CP.remaining_equiv(total, requested)) : {Nat.add(C.shown(total, requested), _) == total : Nat}
|
|
54
|
+
CP.conserved(total, requested)
|
|
55
|
+
|
|
56
|
+
def Laws.full_prefix_omits_nothing(total):
|
|
57
|
+
%Equal.sym(Nat, C.fastRemaining(total, total), C.remaining(total, total), CP.remaining_equiv(total, total)) : {_ == 0n : Nat}
|
|
58
|
+
CP.full(total)
|
|
59
|
+
|
|
60
|
+
def Laws.cap_idempotent(total, cap):
|
|
61
|
+
%Equal.sym(Nat, C.fastShown(C.fastShown(total, cap), cap), C.shown(C.fastShown(total, cap), cap), CP.shown_equiv(C.fastShown(total, cap), cap)) : {_ == C.fastShown(total, cap) : Nat}
|
|
62
|
+
%Equal.sym(Nat, C.fastShown(total, cap), C.shown(total, cap), CP.shown_equiv(total, cap)) : {C.shown(_, cap) == C.fastShown(total, cap) : Nat}
|
|
63
|
+
%Equal.sym(Nat, C.fastShown(total, cap), C.shown(total, cap), CP.shown_equiv(total, cap)) : {C.shown(C.shown(total, cap), cap) == _ : Nat}
|
|
64
|
+
CP.idempotent(total, cap)
|
|
65
|
+
|
|
66
|
+
def Laws.heat_vector_add_mass(xs, ys):
|
|
67
|
+
match xs ys:
|
|
68
|
+
case Nil{} _:
|
|
69
|
+
{==}
|
|
70
|
+
case x <> tail Nil{}:
|
|
71
|
+
Equal.sym(Nat, Nat.add(H.sum(x <> tail), 0n), H.sum(x <> tail), N.add_zero(H.sum(x <> tail)))
|
|
72
|
+
case x <> xt y <> yt:
|
|
73
|
+
%N.add_shuffle(x, y, H.sum(xt), H.sum(yt)) : {Nat.add(Nat.add(x, y), H.sum(H.add(xt, yt))) == _ : Nat}
|
|
74
|
+
%Laws.heat_vector_add_mass(xt, yt) : {Nat.add(Nat.add(x, y), H.sum(H.add(xt, yt))) == Nat.add(Nat.add(x, y), _) : Nat}
|
|
75
|
+
{==}
|
|
76
|
+
|
|
77
|
+
def Laws.heat_scale_mass(mass, weights):
|
|
78
|
+
match mass:
|
|
79
|
+
case 0n:
|
|
80
|
+
{==}
|
|
81
|
+
case 1n+p:
|
|
82
|
+
%Laws.heat_scale_mass(p, weights) : {H.sum(H.add(weights, H.scale(p, weights))) == Nat.add(H.sum(weights), _) : Nat}
|
|
83
|
+
Laws.heat_vector_add_mass(weights, H.scale(p, weights))
|
|
84
|
+
|
|
85
|
+
def Laws.heat_transport_mass(columns, denominator, normalized):
|
|
86
|
+
match columns:
|
|
87
|
+
case Nil{}:
|
|
88
|
+
{==}
|
|
89
|
+
case H.Source{mass, weights} <> tail:
|
|
90
|
+
(column_norm, tail_norm) = normalized
|
|
91
|
+
%N.mul_add(mass, H.input_mass(tail), 1n+denominator) : {H.sum(H.add(H.scale(mass, weights), H.transport(tail))) == _ : Nat}
|
|
92
|
+
%Equal.cong(Nat, Nat, x => Nat.mul(mass, x), H.sum(weights), 1n+denominator, column_norm) : {H.sum(H.add(H.scale(mass, weights), H.transport(tail))) == Nat.add(_, Nat.mul(H.input_mass(tail), 1n+denominator)) : Nat}
|
|
93
|
+
%Laws.heat_scale_mass(mass, weights) : {H.sum(H.add(H.scale(mass, weights), H.transport(tail))) == Nat.add(_, Nat.mul(H.input_mass(tail), 1n+denominator)) : Nat}
|
|
94
|
+
%Laws.heat_transport_mass(tail, denominator, tail_norm) : {H.sum(H.add(H.scale(mass, weights), H.transport(tail))) == Nat.add(H.sum(H.scale(mass, weights)), _) : Nat}
|
|
95
|
+
Laws.heat_vector_add_mass(H.scale(mass, weights), H.transport(tail))
|
|
96
|
+
|
|
97
|
+
def Laws.heat_singleton_mass(mass):
|
|
98
|
+
%N.mul_one(mass) : {H.sum(H.transport([H.Source{mass, [1n]}])) == _ : Nat}
|
|
99
|
+
%N.add_zero(mass) : {H.sum(H.transport([H.Source{mass, [1n]}])) == Nat.mul(_, 1n) : Nat}
|
|
100
|
+
Laws.heat_transport_mass([H.Source{mass, [1n]}], 0n, ({==}, Unit{}))
|
|
101
|
+
|
|
102
|
+
def Laws.basis_empty_refused(order):
|
|
103
|
+
{==}
|
|
104
|
+
|
|
105
|
+
def Laws.basis_complete_retained(have, order, complete):
|
|
106
|
+
%Equal.sym(Bool, Nat.is_le(1n+have, order), False{}, complete) : {B.choose(_, 1n+have) == B.Done{} : B.Step}
|
|
107
|
+
{==}
|
|
108
|
+
|
|
109
|
+
def Laws.basis_first_order(order):
|
|
110
|
+
match order:
|
|
111
|
+
case 0n:
|
|
112
|
+
{==}
|
|
113
|
+
case 1n+p:
|
|
114
|
+
{==}
|
|
115
|
+
|
|
116
|
+
def Laws.basis_next_exact(have, order, missing):
|
|
117
|
+
%Equal.sym(Bool, Nat.is_le(2n+have, order), True{}, missing) : {B.choose(_, 2n+have) == B.Next{2n+have, 1n+have, have} : B.Step}
|
|
118
|
+
{==}
|
package/README.md
CHANGED
|
@@ -544,12 +544,22 @@ calls and proof checking are not modeled; Bend 1/HVM syntax is not supported.
|
|
|
544
544
|
|
|
545
545
|
```sh
|
|
546
546
|
bun install
|
|
547
|
-
bun run check:fast #
|
|
547
|
+
bun run check:fast # Bend laws + artifact parity + typecheck + affected tests
|
|
548
548
|
bun run test:smoke # curated scan-to-render floor, seconds
|
|
549
549
|
bun run bench # rate–distortion and refresh bench against ../pi-fabric
|
|
550
550
|
bun run bench tests/fixtures/mini # self-contained smoke run
|
|
551
551
|
```
|
|
552
552
|
|
|
553
|
+
Development checks require **Bend 2.0.26** (`bend guide`). See [laws, proofs, and
|
|
554
|
+
which tests they can replace](docs/proofs.md). Bend is development-only; the
|
|
555
|
+
extension and published CLI need no Bend installation or generation step.
|
|
556
|
+
Production executes the committed Bend-compiled disclosure, prefix-accounting,
|
|
557
|
+
and heat-basis command kernels. After changing their sources or adapters, run
|
|
558
|
+
`bun run proofs:generate`; `bun run proofs:artifact` checks the receipt without
|
|
559
|
+
Bend. CLI builds check that receipt; publishing also proves and reproduces the
|
|
560
|
+
artifact. The Float64 heat solver still relies on numerical tests, not a proof
|
|
561
|
+
of its approximation or rounding errors.
|
|
562
|
+
|
|
553
563
|
The [warm-path performance report](docs/performance.md) compares the coverage-complete implementation with the optimized version. `bun run corpus:performance <coverage-work> <before-source> <after-source> [rounds]` runs alternating, isolated comparisons with a shared extraction snapshot, independent Git indexes, and exact graph, focus/dwell/sketch, and overflow-content checks. It does not trade fewer candidates or weaker freshness checks for speed. For Node, run `NODE_OPTIONS='--import tsx' node scripts/performance-corpus.mjs ...`; development dependencies are required.
|
|
554
564
|
|
|
555
565
|
Warm matching derives query terms once and caches normalized symbol names by weak node identity, checking renames before reuse. Focus builds only the heat orders currently needed; dwell appends missing orders without replacing its existing basis. No new kernel or review state is introduced. Independent cold extraction can select different literal-join locations when capture order varies, so this paired benchmark deliberately makes no cold-extraction speedup claim.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Third-party notices
|
|
2
|
+
|
|
3
|
+
## Bend 2.0.26
|
|
4
|
+
|
|
5
|
+
The generated policy kernel contains Bend's emitted JavaScript trampoline and
|
|
6
|
+
compiled Base primitives from [Bend 2.0.26](https://github.com/bendlang/bend/tree/v2.0.26),
|
|
7
|
+
Copyright 2026 HigherOrderCO, licensed under Apache-2.0. Pi Fovea removes the
|
|
8
|
+
CLI invocations, adds library exports, and tree-shakes/minifies unused runtime
|
|
9
|
+
code using the bridge pattern developed in Pi Fabric.
|
|
10
|
+
|
|
11
|
+
The complete license is distributed at
|
|
12
|
+
[docs/licenses/bend-apache-2.0.txt](docs/licenses/bend-apache-2.0.txt).
|