Back out the worst of the unsound nonsense

This commit is contained in:
2026-07-10 18:26:38 -05:00
parent 34aee3bf93
commit c6e4a43178
9 changed files with 152 additions and 1297 deletions

View File

@@ -94,108 +94,35 @@ view envelope is well-formed, and recursively validates the `baseView`, but it
must treat the guard payload/reference as opaque executable data, not as another
View.
## 4. Polymorphic and Abstract Views
## 4. Soundness Boundary
View Contracts support portable polymorphism over Views. The View language is
interpreted by the same portable checker model implemented in `tricu` terms.
Views are descriptive boundary metadata, not types and not proofs about opaque
Tree Calculus terms. In particular, the checker does not claim parametricity,
representation independence, or existential abstraction.
Source syntax may use underscore-prefixed names as View variables inside
annotations:
Raw Tree Calculus observation can distinguish values by their tree
representation. A term advertised as `Fn [A] A` can inspect its argument and
choose a representation-dependent result; a metadata-only checker cannot rule
that out. The same issue applies transitively through higher-order arguments and
dynamically constructed observers.
```tri
id x@_a =@_a x
const x@_a y@_b =@_a x
compose f@(Fn [_b] _c) g@(Fn [_a] _b) x@_a =@_c f (g x)
```
The checker therefore accepts only monomorphic Views. Legacy `Var`, `Forall`,
and `Exists` tags remain reserved so old artifacts fail deterministically, but
they are not well-formed checker inputs.
In the portable artifact, these lower to scoped View binders rather than
unscoped source-name conventions. This fits the existing View encoding style:
Views are tagged records with numeric tags and tagged fields. Polymorphic forms
are View records such as:
The guarantees retained here are narrower:
```text
Var localId
Forall binders body
Exists binders body
```
- View and typed-program envelopes are structurally well formed.
- Declared monomorphic Views flow consistently across explicit typed nodes.
- Guarded Views execute their predicates at represented boundaries.
- Artifact references bind metadata to particular stored objects.
The current durable encoding uses stable local binder IDs. For example,
`id x@_a =@_a x` exports a shape equivalent to:
```text
Forall [0] (Fn [Var 0] (Var 0))
```
Source names like `_a` are for authoring; the artifact carries binder scope and
local IDs rather than relying on source-name identity.
`Forall` supports generic contracts:
```tri
map f@(Fn [_a] _b) xs@(List _a) =@(List _b) ...
head xs@(NonEmptyList _a) =@_a ...
```
At each checked use, the checker instantiates quantified variables into
use-local internal variables and solves View compatibility constraints. The
portable checker uses structural use-local IDs rather than expensive numeric
freshening, and treats unconstrained variable-variable matches as constraints
that do not create substitution cycles. Concrete observations still bind these
variables when enough information is available. This is what lets explicitly
annotated higher-order boundaries accept polymorphic values, for example
`compose id id "x"`, and lets quantified values satisfy concrete requirements
such as `Fn [String] String`. It gives useful polymorphic contracts for
explicitly declared/imported View facts.
`Exists` supports checked abstraction boundaries. A module can expose a value as
"some representation `_repr` plus capabilities over `_repr`":
```text
Exists _repr.
Pair
(Fn [String] _repr) -- constructor
(Fn [_repr] String) -- renderer / eliminator
```
This does not make raw Tree Calculus inspection impossible. Unchecked code can
always inspect trees. It means checked clients cannot justify
representation-specific operations through the View system unless the package
exports an appropriate capability or eliminator.
This leads to an important distinction for future checked subsets:
```text
controlled observation: Bool/List/Maybe/Result/etc. eliminators with Views
raw observation: direct tree-shape inspection through triage-like power
```
Useful application code can live mostly in the controlled fragment and receive
explicit View validation over lambdas, application, let, and typed eliminators.
Low-level library code may still use raw intensionality, but should expose
disciplined Views and capabilities above it. Scott-encoded constructors and
eliminators are a natural tricu-native representation for these APIs.
Tree Calculus terms do not carry intrinsic principal Views, and raw intensional
code can invalidate parametric claims. View Contracts are an explicit evidence
and contract layer over tricu programs; limited polymorphic Views are supported
when they are declared or imported as facts with provenance.
The first stdlib annotation island starts with parametric functions that do not
inspect representation:
```tri
id x@_a =@_a x
const x@_a y@_b =@_a x
compose f@(Fn [_b] _c) g@(Fn [_a] _b) x@_a =@_c f (g x)
```
Re-export-only modules preserve imported View metadata, so these contracts flow
through `prelude` rather than only through direct `base` imports.
Functions built on raw `t`/`triage` should enter the checked world through
trusted, controlled eliminator contracts rather than by treating arbitrary raw
inspection as parametric.
These guarantees do not establish that an opaque payload has an unguarded
structural View such as `List` or `Fn`. Such Views are conventions/assertions
used to place and compose checks. Only an executed guard observes the value.
See [the intensionality analysis](../notes/view-contract-trust-provenance.md) for
the rationale and remaining limitations.
## 5. Guards
@@ -259,81 +186,22 @@ A node may contain opaque executable fields. Those fields are tree terms, but
they are not recursively decoded as view-tree nodes or Views unless the node's
semantics explicitly says so.
View facts may also carry explicit per-fact trust provenance:
View facts may carry per-fact provenance:
```text
Checked -- derived by checked lowering / checker validation
Trusted -- asserted by a trusted boundary, e.g. a primitive eliminator API
Unchecked -- raw or assumed; no parametricity/abstraction guarantee
Checked
Trusted
Unchecked
```
In the portable view-tree envelope this provenance is represented as an optional
field on `typedValue` / `typedRequire` facts. In module manifests the same
provenance is carried beside the exported View Contract object reference so that
imports and re-exports preserve it without relying on module-level convention.
Absent provenance is interpreted conservatively as `Unchecked` at use sites.
These labels are retained for artifact compatibility and auditing. They identify
the source of an assertion; they do not prove semantic membership, parametricity,
or abstraction. An absent label is interpreted conservatively as `Unchecked`.
For parametric checked definitions, the frontend now performs a conservative
raw-intensionality dependency pass over local definitions. If a definition with
scoped View variables depends directly or indirectly on raw `triage` / raw `t`
construction, or on an imported `Unchecked` fact, lowering fails and asks the
author to route observation through a trusted eliminator boundary. This is
intentionally provenance/dependency based; it is not an attempt to decide
whether arbitrary Tree Calculus reduction will ever reach rule 3.
View facts can be authored as ordinary value-level Tree Calculus metadata under
one conventional top-level name:
```text
viewFacts = [fact ...]
fact = pair exportName (pair provenance view)
```
where `exportName` is a string naming a value exported by the module,
`provenance` is `0 = Checked`, `1 = Trusted`, or `2 = Unchecked`, and `view` is
the same portable View record used by `view-tree` artifacts. The host evaluates
this value and decodes the data schema; it does not infer trust from source
syntax, AST shape, module name, or a Haskell-side catalog.
The initial trusted eliminator facts are authored this way in clearly separated
stdlib `viewFacts` sections:
```text
matchBool : forall r. r -> r -> Bool -> r
matchMaybe : forall a r. r -> (a -> r) -> Maybe a -> r
matchList : forall a r. r -> (a -> List a -> r) -> List a -> r
```
The `base` module provides small `facts*` authoring helpers for this advanced
metadata, e.g. `factsFact`, `factsChecked`, `factsTrusted`, `factsUnchecked`,
`factsForall`, `factsFn`, `factsVar`, `factsBool`, `factsString`, `factsByte`,
`factsUnit`, `factsMaybe`, and `factsList`. These helpers construct ordinary
Tree data; authority comes from the exported `viewFacts` value and its explicit
provenance tags. Loader validation rejects duplicate fact names and facts for
names the module does not export.
Initial derived stdlib annotations using this trusted kernel include:
```text
maybeMap : forall a b. (a -> b) -> Maybe a -> Maybe b
maybeBind : forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
maybeOr : forall a. a -> Maybe a -> a
```
Recursive list combinators are currently published as explicit `Trusted`
value-level facts rather than `Checked` source annotations, because their bodies
pass through raw fixed-point machinery that the conservative parametric taint
pass intentionally does not prove safe. This is the stabilized boundary: raw
stdlib kernels establish conventions with explicit authority; ordinary checked
clients consume those facts rather than re-proving the internals.
```text
headMaybe / lastMaybe / nthMaybe
append / map / filter / foldl / foldr
length / reverse / snoc / count / all? / any? / intersect
take / drop / splitAt / concatMap / find / partition / zipWith
string/list-byte helpers such as strLength, startsWith?, lines, words
```
The former value-level polymorphic `viewFacts` catalogs and frontend
raw-intensionality taint pass have been removed. Monomorphic imported facts may
still be attached to exports, but consumers must treat them as assertions unless
an executable guard enforces the relevant property.
## 7. Checker Semantics