Skip to content

Complete the open-record acceptance review - #146

Merged
biuld merged 11 commits into
masterfrom
open-records-acceptance
Oct 17, 2026
Merged

biuld merged 11 commits into
masterfrom
open-records-acceptance

Conversation

@biuld

@biuld biuld commented Oct 17, 2026

Copy link
Copy Markdown
Owner

Closes #124.

What lands here

The open-record topic work from the handoff snapshot plus its integrated acceptance review:

  1. 3c31db7e..b7778658 — one immutable labelled record store; open-row record patterns select by label.
  2. 7dd45e4b — checked record-storage primitives and the official Record.Unsafe wrappers in the library (OR-08/OR-09/OR-10).
  3. e5972241 — the shared pattern-coverage engine (psrs-coverage) consumed by both the type checker and CC; Partial exhaustiveness with the official wording; Let/ShadowedTCOLet/Where recover.
  4. e331f9ba — generic local rows lower without mandatory specialization (OR-07), with the negative control retained.
  5. 3030b12 + ebcea009 — the integrated OR-01..OR-14 audit: seven interaction regressions for the remaining OR-04/OR-05 combinations (bare forall a. a -> a transport, constructor-nested patterns, two pattern columns, wildcard labels, pattern-extracted callables, guarded patterns, one erased-recovered record at two use types), every row re-executed, checklist/D-04/scoreboard updated.

Measured results

  • Runtime board re-measured with the established worker pattern: 287/340, identical 52-case failure list, 25 excluded FFI groups, BigFunction at the 2 GiB RSS guard as before (/tmp/psrs-or0405-runtime/summary.json).
  • Debug workspace 2,107 passed / 0 failed / 5 ignored with required Wasmtime and the locked package; formatting and strict Clippy pass.
  • Frontend boards unchanged: L1 904/908, L2 72/72, L3 39/48, L4 39/50, L5 81/97.
  • Library Node conformance 13/13 on the current tree.

Evidence and per-row status: the open-record checklist.

biuld added 11 commits October 17, 2026 15:39
Normalize an ordinary configured executable by checked polymorphic
instantiation through Core's common module relation: the library-owned
PSRS.Command.run :: forall a. Effect a -> Int runs the action exactly
once and discards its result. Unchanged official Sequence.purs executes
with exact Done output and exit zero.

The runtime scoreboard measures program units instead of single files,
following the reference purs: a category-root source with its same-stem
support directory is one program; support sources stay inputs and are
never separately compiled as commands. FFI declarations or sibling
JavaScript in any source exclude the whole program. Filters and limits
apply to program roots; separator coverage and the first blocking stage
are recorded per program.

Evidence: the released board measures 273/340 program groups with
PSRS_REQUIRE_WASMTIME=1 (Wasmtime 49.0.3, package
50c26d67a78a6b25a9915b28fef981bc178cd767, release suite
34e755d1b36825cb5fe9b724afbb4c33ba5428bcec1c9114ecd78ca00efa7263);
corpus classification tests cover grouping, FFI exclusion, support
command exclusion, and filter-before-limit. Checked command
instantiation and board units are recorded in
docs/implementation/backend/polymorphic-command-runner.md and
docs/implementation/runtime-program-scoreboard.md (the accounting
record lands with the integrated checkpoints).
When checking an application against a monomorphic expected result,
constrain the callable result before checking the argument, so a known
result such as Int stays concrete while a rank-N callback opens its own
skolem scope: a rigid mismatch reports TypesDoNotUnify instead of a
premature EscapedSkolem. Polymorphic and constrained contexts retain
synthesis followed by subsumption, and the common unknown-binding escape
check stays authoritative. Result dictionaries survive the ordinary
instantiate_use and apply_constraints scheme operations and are
recovered with the eventual application.

Also pin the standard-library package to the Symbol reification and
command-runner revision 6fcef6ccbab1f3459af2573bbef4ae25b86852d4
(fingerprint fnv1a64-v1:5fcbb57525c63eb1) with the vendored
upstream-prelude Symbol fixture and its differential reflection test.

Evidence: driver rank-N suites including the new contextual rejection
and inferred-result cases, upstream differential tests, and the
integrated workspace run recorded in
docs/implementation/frontend/contextual-application-results.md.
Closed typed records keep their specialized products, while open rows
and all bare erased record values now share one immutable labelled
store: a product header with parallel sorted unique String keys and
non-null erased payloads (DEC-22). Producers establish runtime
contents; a schema check proves the physical schema, and complete
closed recovery validates lengths and every expected key before
recovering fields. No source type ID or module-name test becomes a
runtime record identity.

The machine control pair publishes its result through the common
erased-record protocol instead of a private two-field product: one
conversion each way is planned by the common payload planner, and the
boundary checker compares the complete expected plan at its exact
ordered location. A fixed RecordPack whose fields are all Identity
emits straight-line projections instead of a conversion helper, so
machine terminals keep their exact checked targets.

The ABI retains both the logical record and the physical store as one
view and recurses through complete Field descriptors, so parameterized
ADT fields, erased record lists and filesystem programs share the same
storage policy. CC and MIR reject malformed schemas, conversion plans,
mismatched endpoints and unregistered record owners.

Evidence: 518 backend tests including eight schema, six
conversion-plan and five MIR owner/physical mutations reject
malformed IR; nine required-Wasmtime open-row source runs exit 42
across row indices, recursive access, complete closed recovery, erased
ADT and Array slots, independent nested rows, and callable fields and
results; direct IR round trips and wrong-key/short-payload traps run
in actual Wasmtime. The design is docs/design/backend/fp/open-records.md
with the DEC-22 decision.
Open-row record patterns read the labelled store through one shared
kernel with the accessor path instead of guessing a product index: a
literal label, a Find, a Read, then the common payload recovery to the
checked use type. Closed records still specialize into their checked
products; only labelled stores project by label, and a pattern whose
claimed representation is not its labelled store is rejected rather
than reinterpreted.

Evidence: a realize-level unit test proves Find/Read assignments with
no ProductGet while the case verifies as CC; two required-Wasmtime
source runs across differing prefixes and nested open-row values exit
42; the official FieldPuns, FieldConsPuns and ReservedWords roots
finish with Done and exit zero. The runtime board lifts to 279/340
programs (25 FFI groups excluded) on release suite
7c9f8839dbd7cf73d63322e90ca2eefd5a904551c63cf73b76bb77b64673e2eb with
no other reason changed; the full debug workspace passes 2,056 tests,
formatting, source layout and Clippy stay clean, and the L1-L5 boards
keep their counts. D-04, README and the runtime scoreboard record
carry the 279/340 row; the integrated-session evidence is recorded in
the open-records execution checklist and handoff.
Open rows rejected every record update with "record representation has
no canonical field labels" because the closed path names canonical
product indices. The record owner gains an Update operation: CC lowering
emits the base record and every update expression exactly once in source
order, erases each replacement payload through the common planner into a
private slot keyed by its literal label, and rejects duplicate labels
inside one update at the source position. MIR lowering scans each
replacement label in the base's runtime sequence, traps when a label is
absent, clones the value array once, patches the found slots, and reuses
the unchanged label sequence in a fresh header. The input store is never
written, the complete label/value sequence including the unknown tail is
retained, closed records keep their specialized products, and record
helper interning generalizes to ordered operands per arity.

Evidence: direct CC/MIR/GC runs replace a label and recover the rest,
trap on a missing label, and reject forged operands at the CC verifier;
three required-Wasmtime source runs cover source-order multi-label
updates, a type-changing field over a retained tail, and a case-branch
update. The official ObjectUpdate, ObjectUpdate2, ObjectUpdater,
NestedRecordUpdate, NestedRecordUpdateWildcards and derived-Functor 2616
roots execute. The runtime board lifts to 282/340 (25 FFI groups
excluded) on release suite 8585a60b24a8a02eb8b5c132c596359422492e224f619
9a133fefd2364476337; the full debug workspace passes 2,062 tests with
required Wasmtime, and formatting, source layout and Clippy stay clean.
D-04, README and the runtime scoreboard record carry the 282/340 row;
the open-records checklist gains the OR-06 row and slice section.
Everything the 2026-10-17 handoff describes is committed now, so its
state header and checkout section record the five topical commits
through b777865 instead of a dirty tree, and a 'Follow-up agent start
point' section states the accepted evidence, the validation and board
re-measure routines, the remaining slices ranked by unblocking value,
and the guardrails that bound them.
The four psrs:record-storage bindings (length, key_at, payload_at, build)
become source-typed runtime primitives instead of raw imports. P8 resolves
each slot type through its checked type applications to positive ordinary
constructorless declaration evidence and rejects newtypes, opaque types,
constructor-bearing data and absent metadata; P9 keeps the provider export
identity, verifies its exact CC operation and physical canonical signature,
and rejects direct calls that bypass the projected operation. The one
RecordOperation owner grows a Build operation for dynamic label/value arrays:
MIR snapshots both inputs, checks equal nonnegative lengths, recovers labels
from erased element storage, traps on null labels or slots, enforces strictly
increasing Unicode-scalar label order, and publishes a fresh store without
mutating either source.

The library package e556bf2f then owns the official Record.Unsafe wrappers
and the PSRS.Record search and mutation algorithms on top of the checked
primitives, keeping each official signature verbatim; the lock pins that
revision, vendoring audits 50 packages and 309 modules with nothing missing,
and its Node conformance suite passes 13/13 with an independent target oracle
report for the empty, missing and inherited-key traps.

Official Deriving.purs and TCOFloated.purs now execute through the configured
library runner. The full debug workspace passes 2,084 tests, failing zero,
ignoring five, with required Wasmtime; formatting, source layout and Clippy
pass, and the release suite rebuilds at
37bcdd007466f2ed91f2cbd06962c584bcdd00caef10f73465a5070f36d1f4ee. The
remeasured runtime board is 284/340 with 25 FFI groups excluded: exactly
Deriving.purs and TCOFloated.purs leave the failing set and no other failure
changed state. TCOMutRec.purs still awaits a real Test.Assert.checkThrows
contract, so the topic stays open and #124 remains In Progress.
Audit every OR-01..OR-14 row against its producer, verifier, direct-IR test
and executed runtime evidence on the current tree, resolving the remaining
combination-coverage, malformed-IR, ABI and final-review clauses. Add seven
passing interaction regressions for OR-04/OR-05 under
tests::records::open_rows::interactions: bare forall a. a -> a transport,
constructor-nested record patterns, two pattern columns, wildcard labels,
pattern-extracted callables, guarded patterns, and one erased-recovered
record serving two use types.

Re-measure the board with the e331f9b suite binary (cfg(test)-only library
changes do not rebuild it): 287/340 with an identical 52-case failure list,
BigFunction at the RSS guard as before. Workspace passes 2,107/0/5 with
required Wasmtime; formatting and strict Clippy pass. Update the checklist
rows and final section, D-04 FE-13/FE-14/L6-M7, the scoreboard recheck and
the handoff outcome addendum.
@biuld
biuld merged commit 30d146a into master Oct 17, 2026
1 check failed
@biuld
biuld deleted the open-records-acceptance branch October 17, 2026 17:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Land the Data library modules that no Phase 3 issue owns

1 participant