Repository navigation
Formal: converge the Quint specification on one kernel model with profile instances #165
Description
Summary
The Quint specification should converge on one kernel library that states every portable DialCache rule exactly once, with every conformance profile written as a composition of that library over the profile's own bounded state. The goal is a formal base that covers all behavior and features of the TypeScript implementation, is easy to update when behavior changes, and keeps validating ports through the same replay corpus, drivers and mutation evidence as today. This is the third version of this issue. The first two described the kernel as a single state machine that every profile instantiates and that generates the corpus; the two-profile pilot (#171, #172) showed that shape is achievable for behavior but not for generation cost, and the review recorded in the comments below produced this version. The evidence guarantees are unchanged.
Where the specification is today
The boundary between the specification and the implementations works. Quint generates histories; the shared coordinator hands drivers fixtures and external commands and never its predictions; drivers report observations; the coordinator asserts them. Witness classification, observation validation and the mutation catalog are shared and language neutral. A port supplies a native implementation, a controlled test environment, a driver and a transport.
The boundary inside the specification does not. Behavior is defined more than once:
| Model kind | Files | Lines | Role |
|---|---|---|---|
| Conformance profiles | 15 | 6,492 | Generate histories; each is a bounded re-implementation of the cache with integer encodings |
| Verification models | 7 | 2,760 | Readable sum-typed slices with the semantic invariants |
| Rule checks | 1 | 61 | Finite symbolic checks over cache-rules; the only Apalache target |
| Connection monitors | 5 | 294 | Check that a profile's captured records agree with cache-contract |
| Wire vector models | 4 | 1,033 | Deterministic transforms (keys, frames, envelopes, invalidation) |
| Shared libraries | 5 | 256 | cache-rules, cache-contract, observation encodings, wire text, cohort boundaries |
| Kernel pilot | 5 | 1,374 | One kernel of pure transitions with layers and effects views (#171, #172) |
cache-rules.qnt fixed the worst duplication: 18 files import the age, expiry, deadline and fence judgments instead of restating them. But a profile still restates ownership, publication authority, request memo lifetime, flight registration and diagnostics in its own transitions; a verification model states the same rule a third time; the connection monitors reconstruct ownership and timing facts independently and check the profile against them; and witness classification lives in 25 JavaScript modules (2,276 lines) that read private trace fields to decide whether a history reached a boundary. A behavior change touches a verification model, one or more profiles, their receipt invariants, a connection monitor and a witness classifier.
What the pilot established
The pilot wrote one kernel of pure transitions and expressed the layers and effects profiles as instances of it. It settled the design risk the previous version named as the one that should stop the migration: one kernel with one settlement constant reproduces both the layers boundary (adapter completions inside the call) and the effects boundary (held gates) step for step on twelve fixed histories, both ports replay the result unchanged, and a dependency-following lint proves the views assign no kernel state and that witness state feeds no transition.
It also measured what instantiation costs, and the cost is structural. Quint records every state variable in every ITF state and has no projection flag, so a view exports the whole kernel record: 2.7 to 2.8 times the original's bytes per state, 61 to 83 percent of them the kernel state the view mostly never touches. Under the generation lane's own command (512 traces per profile) both views exhaust Node's default heap before writing a trace; with a 12 GB heap the effects view completes at 2.3 times the original's wall time, 2.75 times its bytes and 7 GB of memory. Sampling cost after the witness monitor was made incremental is 1.0 to 1.2 times the original for layers and 1.6 to 1.8 for effects with each model's own invariants, but that pairing compares nine original invariants against five kernel ones; without invariants the views cost 1.9 and 3.5 times, and the effects view's transitions alone cost about double a 200-line profile because they carry request, local and diagnostic state that profile never had. Every further feature the kernel absorbs (recovery, shadow, admission, policy) would grow the record every view exports. The pilot's own report records generation parity as unmet.
Two other results shape this version. The witness monitor written in Quint computed eleven labels at 13 to 15 microseconds per step and about 23 lines of Quint plus controls per label, against about 5 lines per label in today's JavaScript classifiers, and none of its labels were among the 410 required ones; moving 410 labels into a per-step monitor would tax every sampled step of every profile. And a review of the goal found that what a porter consumes is the coordinator protocol, the contract table, SPEC.md and the corpus, not Quint module structure: the kernel's value is single authority for maintainers and for resolving ambiguity, not a porter reading path.
What the contract is
Kernel initialization and transitions, together with explicit environment assumptions, define allowed behavior. Independent properties, exported regressions and witnesses check that behavior; they do not by themselves define every permitted execution. Progress is stated as bounded-progress obligations checked on every explored state, never as eventual completion: a completion witness establishes one successful execution, and a bounded-progress invariant establishes completion within a declared budget for every eligible call the simulation reached. Each such obligation says what makes a call eligible, when its step budget starts, which scheduling steps count, and which environment assumptions hold. A disabled caller deadline alone does not exclude a call whose source work has settled. Fixtures with intentionally unbounded source work are excluded by name. A call that becomes eligible near the end of a sampled trace may have too few remaining steps to test its budget; a passing invariant then establishes only that no eligible call exceeded its budget while incomplete. Such an obligation is reported as inconclusive because the trace ended, the inconclusive count is part of the diversity report, and it is distinct from a discharged obligation.
Target architecture: one library, composed profiles
1. A kernel library states every portable rule once. The library is a set of concern modules, each with its types and pure transitions: flights and ownership (registration, coalescing, joining, completion of owned callers), request memo and scope lifetime, local storage (insert, LRU order, capacity eviction, expiry), remote frames and watermarks (fences, tracked invalidation), deadlines and budgets (read and source), publication and refill authority, stale recovery, shadow jobs, runtime policy capture, admission, and diagnostics. cache-rules stays the judgment layer under them. Each module owns a record type for its part of the state and transitions of the form pure def f(state: T, inputs...): T or a record of results. Success is measured by whether a behavior change has one authoritative implementation, not by a line count; the exact module boundaries are fixed by the first migration slice from a concern map of the fifteen profiles.
2. Profiles compose the library over their own bounded state. A profile declares only the state its fixtures exercise (a profile without a local layer has no local storage variable), owns the nondet choice of inputs, restricts the environment, and projects its observations. Every assignment in a profile is the result of a library transition; a profile contains no rule logic of its own. The public action vocabulary the drivers are keyed on (mbt::actionTaken, mbt::nondetPicks with { choice }) is unchanged: the profile's actions remain the wrappers. Traces keep their current shape and size because the profile exports only its own state.
3. The settlement boundary is an explicit environment restriction, as before. The pilot's design stands: fine-grained effect steps in the library, and each profile states which external responses are immediately available and which remain held. Ownership, publication authority, timeout decisions and accepted values are governed by the library's transitions. Draining ready work must not silently advance deadline time, release unresolved gates, or discard observable effects. Effect ordering and clock capture happen at the internal step where the event occurs. The projection collapses auto-settled internal steps into one observation per public input and never manufactures an outcome.
4. Witnesses are labels computed from public inputs and projected observations, in the shared JavaScript evaluator. The rule is unchanged: a label may depend only on the input history and the observations the drivers assert, so credit can never depend on state no driver checks. The mechanism changes: the evaluator already classifies once per corpus, carries per-label provenance and is consumed by the Go port by hash, and it costs no sampled step and no trace bytes. Classifiers that read private trace fields today are rewritten to read inputs and public observations only, and a test enforces that they read nothing else; labels that depended on private storage state (LRU order, memo contents) are redefined around a later public probe read as their checkpoint. Each label keeps a positive regression and a distinguishing negative. The Quint witness monitor from the pilot is deleted.
5. Independent checks survive; duplicate transition logic does not. The connection monitors reconstruct source starts, settlement receipts, fence acquisition and clock capture from external inputs independently of the library's records and check the composed profiles against them, one monitor per concern. Verification models fold into module lemmas where they restate a rule the library now owns, are kept where they state a property nothing else states, and are deleted when they do neither. The rule-checks model stays as the symbolic boundary check over cache-rules.
6. Wire vector models stay separate. Key encoding, frames, envelopes and invalidation transitions are deterministic transforms and are correctly specified as vectors.
7. The implementation is the only second implementation. Drivers, the transport, the driver-facing coordinator contract, the completion gates and the trace shape are unchanged. A port is validated exactly as today: it replays the corpus, passes the witness gates, and its mutation lane shows the corpus would catch its mistakes.
8. Coverage is complete and stated. Every behavioral feature and option of the TypeScript implementation that a port must reproduce maps to contract IDs and to the profiles that exercise it, or is recorded as a wire vector or as intentionally out of scope (non-portable, such as metrics adapters). The map is produced by the first slice and maintained as a validated table; a feature without a profile is a coverage gap to close, not a footnote.
Why composition rather than instantiation
Instantiation removes every duplicated line, including the profile's state declaration and action wiring, at the price the pilot measured: every profile exports and updates every feature's state. Composition leaves that wiring in each profile (a few dozen lines of declarations and wrapper actions that call library transitions) and removes only the rules, which is where the duplication that costs maintainers lives. It keeps trace sizes, generation cost, replay cost and the trace readers unchanged, and it lets each profile migrate in place: the rewritten profile replays its own preserved corpus against the old text before the old text is deleted in the same change. That is the "not fully DRY" the owner accepted in exchange for a base that fits the lane and can be updated one module at a time.
What this is not
It is not one model whose step enables every action over every domain. The bounded profiles exist for a good reason and remain. It is not a porter reading path: porters consume the contracts, the specification prose, the coordinator and the corpus; the library is the maintainers' single authority and the place ambiguity in the prose is resolved. It is not a change to how ports are validated.
Evidence guarantees
These are unchanged from the previous version and none depends on the library.
1. Per-label witness provenance. Done (#170): every credited label records its trace identity, whether the trace is sampled or a named regression, and the public checkpoint steps; sampled and regression counts are reported separately.
2. A deterministic reproducer for each new challenge. Done for new challenges (#170); 60 existing challenges remain in a reported backlog and are backfilled as their models are touched.
3. Fault mapping by meaning. Not started. Every model challenge maps to relevant native mutation evidence in both ports, or carries a precise model-only or not-applicable explanation, in a validated many-to-many table; today 67 model challenges stand against 13 native mutants per port, a mapping backlog rather than a measure of strength.
4. Witness-to-failure linkage at the distinguishing checkpoint. Not started. The chain is contract, relevant fault, distinguishing history, failure at the observable checkpoint that establishes the consequence, joined over the provenance from guarantee 1.
5. Fault coupling as a report. Not started. Each catalog fault is injected once in the library module that owns the rule and the detecting profiles are listed; a profile that reaches the rule but does not detect the fault is a gap to investigate, not a gate.
6. Structural enforcement of the thin-profile rule and witness isolation. Done for today's shape (#170); the thin-profile rule changes with this version: a profile may assign its own state, but the assigned values must come from library transitions, and no profile definition may contain rule logic (see tooling). Witness isolation moves to the evaluator: a test that classifiers read only inputs and public observations.
7. Single-authority citations. Not started. Every contract ID cites exactly one authoritative definition in semantic-cases.json: a library module definition for behavioral contracts, or a definition in an explicitly scoped wire module for the wire contracts. Monitors and lemmas are cited as independent checks and tagged as such.
8. Corpus diversity signal. Done (#170): distinct action and observation sequences and per-label hit counts, gated against a recorded baseline.
9. Fresh-seed exploration stays in the aggregate. Done (#164).
Tooling changes
- Corpus differential. The pilot runner's history comparison becomes the migration tool: a generated scheduler replays a profile's preserved sampled histories and exported regressions through the rewritten profile in a few Quint processes and compares the driver-asserted observation at every step with the original's trace. It runs in the pull request that rewrites the profile and on later pull requests that touch the library, path filtered.
- Lint. The dependency-following lint keeps its resolved-reference walk and gains the composition rule: within a profile module, every state assignment's value must resolve to a library transition or a field of one, and no profile definition may branch on cache semantics (the walk reports any comparison or arithmetic over library record fields outside a wrapper's input choice). Its baseline over today's profiles is the migration work list.
- Deletions from the pilot. The layers and effects views, the Quint witness monitor and its controls, the frozen-monitor and generation-parity measurements, and the kernel-pilot workflow job are deleted as the first slice lands; the pilot kernel's pure transitions seed the library modules and the pilot README's measurements move into this issue's record.
- Trace readers and fixtures are unchanged. Profiles keep plain
sandinputvariables and today's integer encodings until a profile's own change replaces them; variant encodings ({ tag, value }) are introduced only where a profile's observation schema changes with them. - Docs.
SPEC.mdandPORTING.mdcite library definitions as the authority behind each contract; the reading path for porters stays the contracts, the specification prose and the coordinator. Docs: language-neutral behavior pages, generated per-language references, and executed examples #166 generates behavior pages from the semantic cases and library definitions.
Sequence
- Update this issue (this version).
- Concern map and coverage audit: map every profile's state fields, public actions, rule logic and witness private reads onto concerns; audit the TypeScript feature surface against contracts and profiles; record the module boundaries, the profile migration order grouped by the modules they compose, and the coverage gaps. No code changes.
- Library extraction and the first in-place rewrite: turn the pilot kernel's transitions into concern modules; rewrite the layers profile in place as a composition; replay its preserved corpus and regressions through the rewrite against the old text; delete the pilot views, the Quint monitor and the parity measurement; land the corpus differential and the composition lint. This slice fixes the module boundaries.
- Evidence guarantees 3 and 4 in parallel with step 3, and the reproducer backlog for the profiles being rewritten.
- Rewrite the remaining profiles in place, grouped by the modules they compose (lifecycle: effects, core, scope, independent, source-budgets, local-clock; then recovery and recovery-read; then policy, runtime-boundaries, admission, local-failure; then shadow and shadow-layers), each with the corpus differential, the composition lint clean, its verification model folded or kept by the rule above, its connection monitor retargeted, and its witness classifiers made public-only. Close coverage gaps found in step 2 as the module that owns the feature lands.
- Guarantees 5 and 7 as the modules stabilize;
SPEC.md,PORTING.mdandREADME.mdupdated to cite the library; Docs: language-neutral behavior pages, generated per-language references, and executed examples #166.
Per-profile migration criteria
A profile rewrite lands only when:
- Every sampled history and every exported regression of the profile's current corpus replays through the rewritten profile with step-by-step agreement on the driver-asserted observation, in the same job. Any disagreement is resolved in the library, never by adjusting a projection or patching the rewrite to match the old text.
- The composition lint reports no rule logic in the profile.
- The profile carries every invariant it had, or a written equivalence argument per dropped one, and its fault challenges still fail at their declared steps.
- Both ports replay the regenerated corpus and the witness gates pass with the profile's baseline within tolerance.
- The profile's generation time in the same job is within 1.5 times the old text's, and its trace bytes per state within 1.2 times.
- The old text is deleted in the same change.
Risks and how to see them early
- Wiring drifts into rule logic. The composition lint is the guard; its report is reviewed on every profile pull request.
- Module boundaries are wrong. The first slice is the test: if the layers rewrite needs a transition that crosses two modules' records repeatedly, the boundary moves before a second profile is written.
- Public-only witnesses lose sampled hits. Labels redefined around a probe read may be reached less often by random sampling; the diversity baseline shows it, and a named regression pins the label until the profile's schedule is adjusted.
- A library change breaks a profile it does not exercise. The corpus differential runs on library-touching pull requests for every migrated profile.
- Stop rule. If two consecutive profile rewrites exceed 1.5 times the old text's generation time or need library changes that grow other profiles' state, the approach is re-examined here before a third.
Acceptance criteria
- A kernel library under
formal/of concern modules with sum-typed state and every portable rule stated once;cache-rulesimported, not restated. Every behavioral contract ID cites one authoritative library definition insemantic-cases.json; wire contracts cite an explicitly scoped wire module. - Every conformance profile declares only its own bounded state, owns its input choice and environment restriction, and assigns state only through library transitions; the composition lint reports no rule logic and no witness feedback in any profile.
- Every required witness label is computed by the shared evaluator from inputs and projected observations only, with a positive regression and a distinguishing negative; a test proves the classifiers read nothing else.
- Witness evidence carries per-label provenance, diversity counts and a baseline gate (done).
- Every model challenge carries a checked mapping and a deterministic reproducer or is in the reported backlog; every challenge maps to native evidence in both ports or carries a precise explanation.
- The connection monitors are library-facing, one per concern, with their challenges intact. Rule checks and the wire vector models remain.
- A validated coverage table maps every TypeScript behavioral feature and option to contract IDs and profiles, or records it as a wire vector or out of scope; no feature is unmapped.
- Bounded-progress obligations are stated with eligibility, budget start, counted steps and assumptions, hold on every explored state, and report inconclusive obligations separately.
- Full validation passes: models and regressions, both ports' replay of the complete corpus, all witness gates, both mutation catalogs, exploration on a fresh seed, at today's generation and replay budgets.
Reference points
- feat: add Quint-driven Go port with shared behavior contracts #161 introduced the profiles and the shared behavior contracts.
- test: unify Quint contracts and cross-language conformance replay #163 introduced
cache-rules,cache-contract, the connection monitors and the shared replay coordinator. - test: close the formalization review gaps, pin fragile witnesses, and parallelize the formal lanes #164 moved witness classification into the shared evaluator, typed the observation contract, made the mutation catalog per model, split model checking from generation, ran Quint concurrently, pinned ten seed-fragile witnesses and sharded the mutation lanes.
- test: add witness provenance, challenge reproducers, and a profile lint baseline (#165 step 2) #170 delivered guarantees 1, 2, 6 and 8: provenance, reproducers, the dependency-following lint with its baseline, the diversity baseline.
- test(formal): add shared lifecycle kernel pilot #171 and test(formal): advance the kernel witness monitor per step and bound the pilot's generation ratio #172 are the pilot: one kernel of pure transitions with layers and effects views, the settlement design, the incremental witness monitor, and the generation-cost measurements recorded in
formal/kernel/README.mdat the time. - Docs: language-neutral behavior pages, generated per-language references, and executed examples #166 records the documentation target.
- The comments on this issue record the reviews that produced each version.
Activity
lan17 commentedon Sep 12, 2026
Thanks. Four of the five points are right and expose real gaps in the issue as written; the fifth is right but needs a measurable form. The most important correction is point 2, where the issue conflated two different failure modes. Point by point, with the amendments we intend to make.
Where the feedback is right and the issue is wrong
Point 2, independent properties. The issue says "delete the five connection monitors once no profile can drift, because instances cannot." That confuses profile drift, which instantiation removes, with kernel error, which it does not. The effects monitor reconstructs source start times and settlement receipts from the external inputs and the clock, independently of the profile's
deadlineandacceptedAtfields, and checks publication against that reconstruction. An instance trusts the kernel's fields, so if the kernel stamps the wrong owner or clock, no instance can notice. The monitors' obligations and their mutation challenges have to survive as independent reconstructions aimed at the kernel, one monitor per concern rather than per profile. That is a deliberate second implementation of a few timing and ownership rules and should be named as the only sanctioned duplication, kept small and input-driven.The second half of the point is also right: bounded simulation cannot check progress. Today progress is carried by witnesses (something completed) and by the settlement contract. The issue should say the contract is invariants plus exported regressions plus reachability labels, and should state the progress obligations explicitly, for example that every begun call completes once its held gates are released.
Point 3, witness attribution. The issue says each label needs "a mutation-catalog entry or a named run that must fail to reach it." An arbitrary non-reaching run proves nothing. The current publication-authority classifier credits the label only when the history contains the subsequent public read that shows reuse, and it reads only observations every driver asserts, never model phase or private timestamps. If kernel-recorded labels are computed from private kernel state, attribution rigor goes backwards even as maintenance gets easier. Proposed rule, one step further than the feedback: labels are pure functions of the input history and the projected observation, defined in a module with no access to kernel state variables. The kernel recording is then a convenience, the label could be recomputed outside Quint, and credit can never depend on state no driver sees. Each label gets a positive regression and a distinguishing negative: a history that does everything except the consequence must not earn it. "Labels cannot influence enabled actions" becomes a structural rule: the label variable appears only on the left of assignments and in invariants.
Point 4, equivalence by preserved histories. Right, and migration step 2 was wrong as written. After the model structure changes, the same seed produces different random choices, so seed equality proves nothing. The inputs are explicit
{name, choice}records, so the existing corpus can be turned into deterministic Quint runs against the new instance and observations compared per step. The boundaries named are the real design problem: the layers profile completes read and decode inside one call, the effects profile exposes reads as held gates. The kernel therefore needs fine-grained effect steps plus a per-profile settlement policy, a constant that says which effects auto-settle inside a public action and which are held for external release, with the projection collapsing auto-settled internal steps into one observation per public input. The issue mentions none of this and it is the hardest part of the kernel.Point 5, exploration strength. Agreed. Reaching every label says nothing about combinations or depth. Keep the current trace and step budgets, measure throughput and per-label hit distributions (the diversity signal in the evidence section), and keep the cross-feature profiles. The rule that projections encode and never decide is in the issue but should be stated as a rule.
Where we would sharpen rather than accept
Point 1, success metric. Dropping the line-count target is correct; it was a proxy and it invites the wrong optimization. But "one authoritative implementation" needs something checkable or it becomes a matter of opinion in review. Two proposals: every contract ID in
semantic-cases.jsoncites exactly one kernel definition as its authority, with monitors and lemmas tagged as independent checks rather than authorities; and a fault-coupling measurement, where each catalog fault is injected once in the kernel and every instance whose schedule reaches the behavior must detect it. If an instance does not, either its schedule never reaches the rule or it carries a private copy. Both are mechanical. Readable modules are fine and Quint supports them; "this is the file a porter reads" becomes "one entry module with focused submodules".The pilot. Two profiles, layers plus effects, is the right first step and better than "generalize the layers profile, then re-express one profile". Layers exercises multi-instance ownership, effects exercises held asynchronous effects, and together they force the settlement-policy design early. We would add runtime to the exit criteria: generation time per profile within a stated multiple of today's, and per-label hit counts not collapsing.
Amendments we intend to make
Holding the edits until you have had a chance to respond.
lan17 commentedon Sep 12, 2026
Following up on the reply above: these amendments address my main architectural concerns. I support proceeding with the layers + effects pilot. I would tighten the evidence criteria below before adopting them as gates.
The strongest improvement is the proposed witness boundary: labels derived from explicit inputs and projected observations, in a module that cannot inspect private kernel state. Preserving independent ownership/timing reconstructions, replaying preserved histories, retaining exploration budgets, and using focused modules behind one entry point also make sense.
1. Make fault coupling depend on a distinguishing history.
Injecting a shared fault once and checking its effect across applicable profiles is a useful measurement. However, reaching a rule does not imply that every mutation of that rule must be detected.
For example, changing
age < ttltoage <= ttldoes not change a read at age zero with a positive TTL. A profile can execute the canonical freshness rule repeatedly without exercising its exclusive boundary. A fault can also change intermediate state without affecting the observed result, or be equivalent under a particular fixture. None of those outcomes establishes that the profile contains a private implementation.I suggest a checked mapping with these elements:
Missing a required distinguishing history is a coverage gap. Surviving one is an assurance gap to investigate. Detecting it is evidence for that specific obligation. This makes the coupling check useful without interpreting every survivor as proof of duplicated behavior.
Single-authority citations are also valuable: each contract should identify its authoritative definition, with independent checks classified separately. They need structural enforcement of the thin-profile rule; citations and mutation scores alone cannot establish that no private transition logic exists.
2. Map model and implementation faults by meaning, rather than matching their counts.
I agree with expanding implementation mutation coverage. The revised issue's challenge-parity requirement should support an explicit many-to-many mapping between contract/fault families, Quint challenges, and native mutations.
Several model challenges may exercise the same shared defect through different profiles. A fault in model-only receipt instrumentation may have no direct production counterpart. Conversely, a language binding may need several native mutations to challenge one portable obligation.
Each model challenge should therefore map to relevant native evidence in both ports, or carry a precise explanation of its model-only scope or non-applicability. Preserve the clean baselines and the requirement that detection comes from a relevant property/assertion failure. Compilation failures, malformed transport, and runner failures still receive no detection credit. Comparing the raw number of model challenges with native mutants is useful for finding mapping work, but is not itself a comparison of assurance strength.
3. Link witnesses to relevant failures at their distinguishing checkpoints.
The updated issue's witness-to-mutant linkage is a good direction, but a label and an arbitrary mutant failure occurring in the same trace is too weak.
A trace could demonstrate recovery at step 30 while an unrelated invalidation mutant fails at step 3. That does not establish that the recovery consequence is tested. The desired chain is:
Contract → relevant fault → distinguishing history → failure at the relevant observable checkpoint.
For each credited witness, retain the trace identity, the public checkpoints establishing its consequence, the relevant fault/contract mapping, and the assertion that detects the altered consequence. A later public read may be the checkpoint that establishes an earlier publication; attribution should preserve that causal chain rather than insist on failure at the instant a label is first emitted.
There is some new evidence plumbing here. At the currently examined #164 revision, the witness writer stores aggregate labels and corpus hashes. Per-label trace/checkpoint provenance needs to be added before this can become a join over saved artifacts.
Keep the positive and distinguishing negative controls when moving classification into Quint. A history that preserves the setup but removes the required consequence must lose the label. Generic malformed-trace, provenance, and completion-gate controls remain useful outside Quint.
One implementation clarification: an accumulating witness monitor must be allowed to read its own prior state. The structural restriction should be that witness state cannot influence cache transitions, enabled actions, scheduling, or results; requiring it to appear only on assignment left-hand sides would prohibit accumulation itself.
4. Define the contract through allowed executions, and state progress assumptions explicitly.
I would replace the proposed formulation with:
Invariants, regressions, and labels do not by themselves define all permitted executions.
Also, bounded simulation can check bounded progress on the executions it explores, such as completion within a declared number of steps or elapsed-time bound under specified inputs. It cannot prove eventual completion across all possible fair executions. Reaching a completion witness establishes one successful execution, not completion of every eligible call.
A completion obligation should say which source/adapter work must settle, which clocks must advance, and what scheduling assumptions apply. This matters for fixtures with intentionally unbounded source work or disabled caller deadlines.
5. Make the settlement policy an explicit environment restriction.
The proposed fine-grained kernel and per-profile settlement policy address the right problem. The policy may determine which external responses are immediately available and which remain held. Ownership, publication authority, timeout decisions, and accepted values remain governed by the shared kernel.
Draining ready work must not silently advance deadline time, release unresolved gates, or discard observable effects. Preserve effect ordering and clock capture at the internal step where the event actually occurs. The projection should expose the agreed public boundary and encode its observations; it must not manufacture an outcome to reproduce an old profile.
For the layers + effects pilot, I would require:
That is enough to begin. The pilot should establish whether the settlement design preserves behavior and whether the modular kernel improves readability at an acceptable cost. The remaining profiles can then migrate against demonstrated criteria rather than a speculative line-count target.
test: close the formalization review gaps, pin fragile witnesses, and…
lan17 commentedon Sep 12, 2026
Agreed on the direction and on most of the tightening. Point by point, with what we would adopt and where we would add to it. Nothing is applied to the issue body yet; this is to check agreement first.
1. Fault coupling needs a distinguishing history. Accepted. "Inject once, every reaching profile must detect" was too blunt: reaching a rule is not exercising its boundary, and a survivor can be an equivalent mutant under that fixture rather than a private copy. We would adopt the checked mapping as written (contract and fault family, applicable profiles, distinguishing public-input history, expected failure, explicit exclusions).
One corollary worth drawing out: challenge detection today relies on bounded random simulation reaching the boundary, which is the same seed fragility #168 just fixed for witnesses (ten required labels reached by three or fewer of about 550 sampled histories, one by a single history). A distinguishing history per challenge is a named public regression that must fail on the mutant, so detection becomes deterministic and seed-independent, using an artifact type that is already exported and replayed. We would phase it: required for new challenges, added to existing ones when they are touched, with the count of challenges lacking one reported.
On structural enforcement of the thin-profile rule: agreed that citations and mutation scores cannot establish it.
quint parseexposes the module IR, so a lint can require that a profile module declares no state variable of its own and that every action is a wrapper that chooses an input and calls one kernel action. That lint is the gate; the coupling measurement becomes a report of things to investigate, not proof of duplication.2. Map faults by meaning. Accepted. "67 model challenges against 13 native mutants" is a mapping backlog, not a comparison of assurance strength, and the issue should say so. The criterion becomes a validated many-to-many mapping: every model challenge maps to native evidence in both ports, or carries a precise model-only or not-applicable explanation. Clean baselines and the rule that only a relevant property or assertion failure earns credit are unchanged.
3. Linkage at distinguishing checkpoints. Accepted, including the gap you located: the evidence writer stores aggregate labels and corpus hashes, with no per-label trace or checkpoint provenance, so the join is not possible today and a naive one would link unrelated failures. The chain is contract, relevant fault, distinguishing history, failure at the observable checkpoint that establishes the consequence, which may be a later public read. Per-label provenance (trace identity and the public checkpoint steps) is cheap plumbing that needs no kernel, and it also yields the per-label hit counts #168 computed by hand. We would make it the first deliverable of the evidence section.
Correction accepted on witness state: an accumulating monitor must read its own prior state. The restriction is that witness state is never read by a cache transition, guard, schedule or result, and that is lintable the same way as the thin-profile rule. Positive and distinguishing-negative controls stay when classification moves into Quint; malformed-trace, provenance and completion-gate controls stay outside it.
4. Contract through allowed executions. We would adopt your formulation verbatim: kernel initialization and transitions, together with explicit environment assumptions, define allowed behavior; independent properties, exported regressions and witnesses check it. On progress, agreed that a completion witness establishes one execution. One addition: bounded simulation can still check a universally quantified bounded-progress invariant on every explored state, such as "every begun call whose gates are all released completes within K internal steps", which is stronger than a witness while remaining honest about being bounded. Fixtures with unbounded source work or disabled caller deadlines are excluded by name.
5. Settlement as an explicit environment restriction. Accepted in full, including the three prohibitions for draining (no silent deadline advance, no releasing unresolved gates, no discarding observable effects), clock capture at the internal step where the event occurs, and a projection that encodes rather than manufactures. The pilot criteria are right. One addition from this week's runs: the generation-runtime budget should be relative, measured by generating the old profile and the kernel instance in the same job and bounding the ratio, because hosted runners varied 1.8x day to day on identical work.
Sequencing. We would put per-label provenance and the distinguishing-history requirement for new challenges ahead of the pilot, so the pilot is measured against the tightened evidence rather than the current one. Neither depends on the kernel.
If this matches your reading, the issue body gets these amendments plus the earlier six (monitors survive as kernel-facing reconstructions, preserved-history replay, settlement policy as a constant, pilot as step 1, budgets fixed during migration, contract restated as above), and the pilot can start.
lan17 commentedon Sep 12, 2026
Following up on your latest reply: I think we have converged on the architecture and evidence criteria. I support updating the issue and proceeding with the agreed sequence. The remaining details fit within that design and can be resolved during implementation.
The most valuable addition is a deterministic reproducer for each new challenge. Random exploration discovers distinguishing histories; preserving those histories ensures that a known fault continues to be detected. PR #168 demonstrates why this matters: some required witnesses depended on very rare sampled histories. Requiring reproducers for new challenges, backfilling existing challenges as their models are touched, and reporting the remaining backlog is a practical approach. Each reproducer should pass against the clean baseline and fail for the intended semantic or property reason under the challenge.
I also agree with making witness provenance the first deliverable. Per-label trace and checkpoint references will let us inspect which histories establish which consequences, identify labels supported by very few cases, and assess what the pilot preserves. The same-job comparison of old and new generation is also the right way to evaluate runtime without confusing runner variation with architectural cost.
Three clarifications should carry into implementation:
Keep portable and model-only fault obligations explicit. A portable behavior fault should have an exported regression expressed through public inputs. A fault in model-only instrumentation can have a deterministic model-level test with its scope and the reason it has no native counterpart documented. The new reproducer requirement should preserve those agreed exceptions. Likewise, model/native fault mappings should remain many-to-many where appropriate; raw challenge counts are not a parity measure.
Make the structural lint follow dependencies. Inspect resolved helper calls and operator arguments so that private transitions or feedback from witness state cannot hide behind another function. Direct textual checks would not enforce the intended boundary. Witness state may maintain its own history, but it must not influence cache transitions, guards, scheduling, or results.
Define bounded progress precisely. Specify when a call becomes eligible, when its step budget starts, and which scheduling steps count, together with the required environment assumptions. A disabled caller deadline alone should not exclude a call whose source work has settled. The property can quantify over every eligible call in every explored state, while the evidence claim remains explicitly limited to the executions explored.
My recommended sequence is:
I would not make completion of the entire historical challenge backlog a prerequisite for the pilot. Keep that backlog visible, preserve the agreed exceptions, and let the pilot provide concrete evidence for the remaining implementation choices.
lan17 commentedon Sep 12, 2026
The body is updated to the agreed version: the contract stated through allowed executions with bounded-progress obligations defined precisely; the settlement policy as an explicit environment restriction with the three draining prohibitions; witnesses computed from inputs and projected observations with positive and distinguishing-negative controls, and monitor state that may accumulate but never feeds transitions; independent monitors retargeted at the kernel as the only sanctioned duplication; the nine evidence guarantees including per-label provenance, deterministic reproducers with the portable versus model-only distinction, mapping by meaning, checkpoint-anchored linkage, fault coupling as a report, and the dependency-following lint run on today's profiles as a baseline; preserved-history replay instead of seed equality; the two-profile pilot with its exit criteria and a relative runtime budget; and the four-step sequence with the reproducer backlog kept visible rather than gating the pilot. The previous body is preserved in the edit history.
lan17 commentedon Sep 12, 2026
I re-reviewed the updated body against our discussion. It is ready to guide the layers + effects pilot. It incorporates the substantive agreements: independent monitors survive, witnesses use public observations, challenges get deterministic reproducers, settlement assumptions are explicit, and migration starts with two profiles.
Four small clarifications remain. None requires reopening the architecture discussion.
Allow wire models to be authoritative. The target architecture and acceptance criteria retain wire models separately, but evidence guarantee 7 and the first acceptance criterion require every contract to cite a kernel definition. Those requirements conflict for wire contracts. Use “one authoritative Quint definition, in the kernel or an explicitly scoped wire module.” Shared rules should still be imported rather than duplicated; monitors and lemmas remain separately identified independent checks.
Make the lint cover the full witness-isolation boundary. The design prohibits witness state from influencing scheduling and results, but guarantee 6 specifically describes dependency roots at cache guards and assignments. Explicitly include profile
init/step, input-choice domains, observation projections, and operator-constant bindings, following resolved dependencies through helpers and operator arguments. Otherwise, witness feedback could affect the explored inputs or reported results without appearing in a cache assignment.Separate sampled coverage from regression coverage. Deterministic regressions now preserve rare witnesses. An aggregate witness gate can therefore remain green even when random exploration stops finding those cases. The risk section's claim that witness gates immediately expose lost corners is too strong. Record sampled versus named-regression provenance and counts in the planned evidence, and distinguish them in the diversity report. This makes reliable regression protection and exploration quality separately visible; it fits the existing provenance work rather than requiring another workstream.
Account for unfinished progress obligations at trace boundaries. A call can become eligible near the end of a sampled trace, leaving insufficient steps to test its completion budget. A passing invariant establishes that no observed eligible call exceeded its budget while incomplete; it does not establish completion for every eligible call reached. Either extend the execution until the obligation is discharged or its budget is exhausted, under the declared environment assumptions, or report that obligation as inconclusive because the trace ended. The extension must still respect the settlement restrictions, including no silent clock advance or release of unresolved gates.
I recommend incorporating these clarifications and proceeding with the provenance/reproducer work, followed by the pilot. The architecture now has enough concrete constraints and exit criteria for implementation to answer the remaining questions.
lan17 commentedon Sep 12, 2026
Applied all four clarifications to the body. (1) Guarantee 7 and the first acceptance criterion now read one authoritative Quint definition, in the kernel or an explicitly scoped wire module, with shared rules imported and monitors and lemmas tagged as independent checks. (2) Guarantee 6 roots the witness-isolation lint at cache guards and assignments, profile init and step, input-choice domains, observation projections and the bodies of operator constants bound at instantiation, following resolved references through helpers and operator arguments. (3) Guarantee 1 records whether each credited trace is a sampled history or a named regression and reports the two counts separately; guarantee 8 gates the sampled counts; the risk section no longer claims the aggregate gate exposes a lost corner. (4) The contract section reports an obligation left unfinished at a trace boundary as inconclusive, counts it in the diversity report, requires a minimum number of discharged obligations per profile through the same baseline, and keeps extension under the settlement restrictions as the alternative if discharged counts are too low. Next is step 2 of the sequence: per-label provenance with sampled versus regression counts, the reproducer requirement for new challenges, and the lint baseline over today's profiles.
test: add witness provenance, challenge reproducers, and a profile li…
test(formal): add shared lifecycle kernel pilot (#171)
test(formal): restore the scheduled model where it is rewritten and r…
test(formal): advance the kernel witness monitor per step and bound t…
lan17 commentedon Sep 16, 2026
The body is now the third version. What changed and why, in short:
The evidence guarantees are unchanged; 1, 2, 6, 8 and 9 are done, 3, 4, 5 and 7 are not. The previous body is preserved in this issue's edit history.
feat(formal): extract the kernel library and compose the layers profi…
lan17 commentedon Sep 16, 2026
Step 3 landed: the kernel library and the first composed profile (#178)
What exists now
formal/kernel/: eight concern modules (encodings,layer_policy,request_memo,local_storage,remote_frames,flights,clock,serving), each a set of pure transitions over a row-polymorphic record type (type Scoped[r] = { memo: List[int], closed: List[bool] | r }), so a profile composes them over its own flat state with no change to its trace shape. Quint 0.32 supports row variables in aliases and across modules on the Rust backend; that settled the composition mechanism.formal/dialcache-layers-conformance.qntis composed from the library (549 to 386 lines): same constants, flat state, input contract, nondet choices, guards, nine invariants and fifteen regressions; everys'is a library transition, a record literal or input decoding. The two layers fault challenges anchor onflightsandrequest_memoand still fail at their steps.formal/differential.mjs(make differential, a pull-request job): both revisions' texts and manifests are read as recorded, the reference corpus replays through the candidate and the candidate corpus through the reference, every driver-asserted channel is compared per step, bytes per state may not grow beyond 1.2x, an intended change is declared by bumpingdifferential.behaviorVersion(or the profile's schema version), an unchanged import closure is skipped, and refused inputs are named with the evaluator's diagnostic. Result for layers: 527 of 527 histories agree in both directions, wall x1.00, bytes per state x1.000.Decisions made in review (four rounds, 50 files)
flights) and scope closure goes throughserving.closeScope(state, layout, context).formal/kernel/README.md.Preconditions for the next profiles
formal/replay/features.mjs.core,effectsandlocal-clockhave none today and need one before they compose;local-failure,source-budgets,scope,runtime-boundariesand the rest are ready.servingadopts the layers encoding of every field it names. A profile with a different private layout re-encodes when it composes, and the witness classifiers that read its private fields (step 4 of this issue) move with it; the next slice measures bytes per state for that profile against the 1.2 bound before committing to the monolithicserving.beginor splitting it per concern.--composedruns profiles sequentially (fine for one profile, to revisit as more compose); the committedwitness-baseline.jsonlayers fingerprint differs from whatmain's own text generates locally (pre-existing; refresh separately).7 remaining items
feat(formal): compose the source-budgets profile over a budgeted loca…
lan17 commentedon Sep 16, 2026
Progress since the slices 6 to 8 note.
Landed
requestReleasejudgment both consume. The layered, request-only and diagnosed shapes are now aliases over oneTraversedrecord.varslist differently from the pinned Linux build, and their corpus fingerprints had been recorded from raw local traces. The fingerprints are now taken from normalized corpora and the gate reports a matching corpus for all fourteen profiles.In flight
Call.keyFailedreplacesoutside, pinned for every call shape by a kernel fixture; the local projection's source record now carries the identity it serves; local insertion expiry is pinned by an exported regression.now + skew, remote frames stamped on the wall clock and retained on the monotonic one withretained/fresh/readableFrame(freshMs),Ttlspassed beside the resolution to every shape with a layer turned off by a zero TTL (stated once in the traversal), each source capturing the TTLs of the reply that started it sosettlepublishes with the source's own,Servedfault switches read at the remote read, the dump and the write, a monotone watermark, and 47 kernel fixture runs pinning boundaries and faults with the two clocks apart. Three review rounds so far (watermark could lower after a rollback; write-side clock choices unpinned; the wall clock as independent state; TTLs in the layout; the settlement-TTL design record measured against the wrong variant); a fourth runs on the rebased head with the full run.policy_overlay(26 codes to a resolution and TTLs),config_errors, a one-recordreceiptsvariant for the two read invariants (the receipt-free restatement cannot tell a local hit from a remote hit that warmed local), the profile at 612 lines with its 29 regressions verbatim, nine invariants (one dropped with named carriers), both policy challenges re-anchored on kernel text, the witness fidelity check re-encoded to the composed layout. The policy corpus replays 541 of 541 histories both ways at x0.74 bytes per state; composition lint 47 to 0.Decisions taken (revisable)
Ttlstravel as an argument besideResolutionrather than inside it (the scope and source-budgets profiles build and storeResolutionliterals; Quint records have no width subtyping).Layoutcarries no TTLs; every shape takes the reply's TTLs the same way at release, and each source record captures the two it publishes with (measured x1.13 bytes per state on layers, inside the bound), which deletes the parallel-list variant the design pass had planned.now + skewso a profile cannot advance one clock without the other;shiftWalladjusts the skew.finishRedisChainwarms local on a read error only for untracked keys); pinned by a fixture.openScopeneed not live inrequest_memo); an absolute bytes-per-state budget per profile; hashing witness corpus fingerprints over states only so local reports stop saying "corpus differs".Next: land #184 after its round and run, then the 9B pull request; then local-failure folded into layers per the synthesis, with the open owner questions above still open.
feat(formal): stamp remote frames on the wall clock and carry TTLs an…
feat(formal): compose the policy profile from the kernel library (#185)
lan17 commentedon Sep 17, 2026
Slice 9 is on main.
Landed since the last note
now + skewso a profile cannot advance one clock without the other; remote frames stamped on the wall clock and retained on the monotonic one, served only while retained, fresh for the reply's TTL and fence-cleared; a watermark that never lowers (the implementation's invalidation takes the maximum);Ttlspassed beside the resolution to every shape with a zero TTL turning a layer off, stated once in the traversal; each source capturing the TTLs of the reply that started it, so settlement publishes with the source's own; fault switches read at the remote read, the dump and the write; 47 kernel fixture runs pinning the boundaries and faults with the two clocks apart. Four review rounds.policy_overlay(the 26 codes to TTLs and coalescing),config_errors, a one-recordreceiptsvariant judged from the same release judgment the traversal consumes (the receipt-free restatement cannot tell a local hit from a remote hit that warmed local), eleven invariants including the join direction and the remote-hit warming TTL, two new challenges on the traversal order indecideeach carried by exported regressions in every profile that observes the fault, the witness fidelity check re-encoded to the composed layout (receipt and owners bound). The policy corpus replays 541 of 541 and 542 of 542 histories both ways at x0.74 bytes per state; composition lint 47 to 0. Three review rounds.Coverage. An independent three-lens audit over the whole range (before slice 6 to the current main) found no loss of coverage against the TypeScript and Go implementations: driver descriptors,
src/andgo/byte-identical; regressions 406 to 417 scheduled and 239 to 250 exported with none removed or renamed and every public expectation verbatim; 262 semantic cases and 435 required witness labels unchanged; challenges 67 to 72. The model-check lane traded two hand-written invariants for regression carriers (a traversal-order property in runtime-boundaries, the failed-reply diagnostic count in policy) and had three restated invariants strengthened back after review.Housekeeping. The composed profiles' witness corpus fingerprints are now recorded from normalized traces (the local Rust evaluator emits the ITF
varslist differently from the pinned Linux build; the hosted gate had been running in tolerance mode for three profiles and now reports a matching corpus for all fourteen). Two ledgered guides still quote the old challenge count; a docs pass follows.Next per the synthesis above: local-failure folded into layers as a fault fixture (deletes that profile; needs the "deleted profile" outcome ratified), then local-clock (descriptor plumbing first), then the held-I/O design pass before independent. The open owner questions (bytes exceptions for recovery, admission and shadow; the deleted-profile outcome) still stand.
lan17 commentedon Sep 18, 2026
Fault mapping by meaning (evidence guarantee 3) is implemented in #188, ready for review and not merged.
What it adds
execution.jsoncarries anativeMutantsentry:mappedto a native mutant that injects the same wrong behavior into both ports, or an explanation (unobservable: a port line exists but the port re-checks the condition later, so no public history distinguishes the fault;model-only: the fault rewrites model bookkeeping no port line carries). The result over 72 challenges: 62 mapped, 2 unobservable, 6 model-only, 2 in a frozen backlog (the Lua watermark cutoff, which no in-process cohort executes; the buffer limit, whose client-side lines exist in both ports but which no generated history reaches). Before this, 9 of the 34 challenged contracts had any native mutant.formal/mutations.json, replaces the two paired files: 54 faults (13 before), each described once with a rationale naming the port lines it changes and a TypeScript and a Go section of exact-anchor edits.node formal/execution.mjs,make audit, the test suite and both mutation runners check that every anchor still matches the port text exactly once, so asrc/orgo/refactor that moves an anchored line fails the pull request rather than the weekly lane; the Quint generation lanes never read port text.independentFailureKeepsSettledLocalValueTest, local-failurerejectedSourceDoesNotSeedLocalTest); both replay in both ports.crashedcohort and the shard continues, as is a mutant that does not compile; the Go runner credits the core replay's two pair assertions;MUTATION_ONLY=Mnn make mutations-ts|gomeasures named mutants while authoring.Review. Three report rounds of seven lanes plus a holistic pass. Round one moved the anchor check onto the pull-request path, corrected a backlog rationale, and simplified the schema; round two folded the two catalogs into one file with the port-side account beside the anchors and cut the challenge texts to the model-side identity under a length ceiling, split anchor checking out of manifest validation, and added per-mutant crash records; round three was low-only. The hosted run on the round-two head exposed one nondeterministic mutant (a shared Go flight map without a common lock), fixed in the final commit.
Decisions taken (revisable)
generatedandportabledetection only; the thirteen original mutants keep theirordinaryrequirement. Requiring the unit suite's incidental detections would turn every unit-test refactor into a weekly-lane failure.portablestays in every required list (it is implied bygenerated); dropping it catalog-wide is a separate cleanup.Follow-ups this opened
integrationcohort against real Redis for the Lua cutoff challenge, and a profile input for the future buffer so the buffer-limit challenge can be mapped.go/test-file change).Next in the strengthening order: required witnesses for the fifteen semantic cases that have exported regressions but no sampled witness, then a machine-checkable settlement contract. The owner questions above (deleted-profile outcome, bytes exceptions) still stand.
lan17 commentedon Sep 19, 2026
The two remaining coverage holes are closed on #188 (same branch as the fault map; two more commits, 2ec10a4 and 4952b77), ready for review and not merged.
A required generated witness for every semantic case
semantic-cases.jsonhad exported regressions but no required sampled witness, so nothing checked that generated histories reach them;check-go-paritylisted them underwithoutRequiredGeneratedWitnesses. Each now names at least one generated witness: the runtime-boundaries exact-serving and bypass clauses are narrowed to what the public observation proves, a layers tracked-local-only rule and an independent source-budget rule are new classifiers that read inputs and public observations only, and two policy labels the classifier already credited are registered. The registry grows to 440 labels; the inventory reports 240 cases with required generated witnesses and none without.The settlement contract, checked
causally-ready-v1was prose with one no-settle control per port. Every behaviorobservenow carries a settlement receipt (elapsedMs,runnable,held), and the coordinator keeps a ledger of the commands it issued per session and checks the receipt before comparing the observation: nothing runnable after one zero-time verification drain (R2); the monotonic clock at the sum of the advances plus the fixture's callback work (R3); the wall clock at the epoch plus the clock commands plus the same work (R4); exactly the loader, adapter and scope gates the schedule leaves open (R5). Core sessions carry no receipt and are held to R4 alone; the local-clock driver's process clock is unconstrained.synctest.Waitand the deferred queue), both transports send it exactly whenpreparenames it after validating it locally, and both no-settle controls must fail every behavior-driver profile with a settlement violation, never an observation mismatch. Receipts held at every observe of every history in both ports over the CI corpus.runnableis the driver's attestation from one drain, timer delivery is checked by the next observation, core is held to the wall-clock rule alone. A third port must carry a no-settle control of its own.Review and ground truth. Four review rounds of seven lanes plus a holistic pass on the new commits. Round four found the snapshot-encoding defect the hosted run had already exposed and had a settlement violation under a mutant recorded against that mutant instead of stopping the lane, the ledger's per-interval attribution of held gates stated and enforced, the TypeScript transport's duplicate checks removed and a Go test shim deleted; round five had portable evidence left unmeasured with its component, the two binding fields folded into one, the independent classifier reading its budget from the profile, a driver-side diagnostic of what the verification drain found, and new controls for the independence clauses, the fixture work terms and the timer term; round six moved the violation matcher both runners use next to the texts it matches and gave the Go driver the same diagnostic; round seven was clean apart from two low items, one applied. The first hosted full run on the receipt commit failed one TypeScript mutation shard and thereby found a driver defect: under M37, which publishes a rejected source's error object into local storage, the driver's quiescence check compared a structured clone of the observation with the live one and read an unchanged Error object as runnable work. The snapshot is now the JSON text that crosses the wire; the hosted runs on that fix and on each review-round head (35402562963, 35404844418, 35407448531, 35409976443) are green on all sixteen mutation shards, both merges and both parity jobs; run 35411849865 covers the final head.
Decisions taken (revisable)
Where the #165 guarantees stand. Fault mapping by meaning (3) and witness coverage for every case are in place; the settlement contract is machine-checked. Still open from the plan: finishing composition (10 of 15 profiles remain hand-written; held-I/O design first), single-authority kernel citations for semantic cases (7), witness-to-failure linkage (4), fault coupling (5), and connection monitors.
lan17 commentedon Sep 19, 2026
Composition resumes on #188 (same branch): the kernel seam for held remote I/O and the
independentprofile composed over it, ready for review and not merged.The seam (036c6d9, fixed up in a19e1c5). Designed once for every remaining remote profile by a four-reader, three-design, three-judge pass with a completeness critic:
remote_iois a variant family over the layered shape. Held reads and decodes are pending-only records; every held read registers its flight at dispatch so followers join a pending read; loader ordinals map to flights through one helper on every held start; the drivers' io channel is written by the transitions that hold each fact.recoveryis a consulted record: a snapshot retained at read settlement from the classifier passed there, consulted at loader failure and at the recovery decode. No profile composes a recovery transition, so recovery-read and recovery need no wrapper order.deadlinesis one pending-only list of due instants delivered by an instant-ordered fold instantiated inside the kernel, late arrival as one judgment, no drain at expiry; the local variants keep their history and source-budgets gains a field with no wiring change.servingexposes the release judged with the remote layer unobserved, the shared prologue, completion split from the result record, warming and publication as named steps, and source authority with an explicit fence;remote_framesstates the C58 rule (a visible but declined frame yields no fence), pinned by fixture runs and the TypeScript reading because no composed corpus can observe it.independent composed (37d166e). Seven library transitions and nothing else; lint zero. Three invariants verbatim, four restated one step over library records, one replaced by an equivalence carried by the connection monitor, two regressions and a fixture run. Ten regressions verbatim (three private-state patches became input schedules) plus three new exported ones. Six challenges re-anchored on kernel text with every mutant caught by its named invariant or regression; nine reproducer exclusions rewritten to state why each other profile cannot reach the fault; two challenges left the reproducer backlog. All 512 sampled histories and the regressions replay step-identically in both directions at 0.76 of the old bytes per state and 0.65 of its generation time; the witness labels credit the same histories (the classifier had been made public-only first, in 7d0cada).
Review. Three rounds of seven lanes plus a holistic pass. The seam's round found one high item before any profile used it: a held reply that left the remote layer off started a source without a loader ordinal, so its deadline landed on index -1; fixed with one mapping helper on every held start and a fixture invariant, alongside the lint's operator rule, a challenge anchor that had drifted onto property history, dead definitions after the split and fixture pins for the C58 rule. The second round, on the composition and those fixes, was clean on correctness and reliability and had the lint judge operator arguments from the kernel's declared parameter types, the fixture checker run under Quint's own selection, and the timeout classifier pinned. The third round was clean on correctness, architecture and performance; its low items (an alias-typed or alias-applied kernel operator the lint did not see, one redundant recovery helper, and an exported regression for the unfenced refill after a failed decode) are applied as the final commit of the slice.
Ground truth. Hosted full runs are green on the fix heads a19e1c5 (35442599999) and ff5c1dd (35446071419), the composed independent corpus included; run 35448859364 covers the final commit 0135f49. Locally at the head: every kernel module and composed profile typechecks, all six composed profiles replay their reference corpora step-identically in both directions (independent at 0.76 of the old bytes per state and 0.6 of its generation time), 7 fixture files with 78 runs, lint baseline, manifest, ledgers and locks consistent, full test suites of both ports green.
Lane budget. With six composed profiles a kernel change replays every one in both directions, about 35 minutes on the hosted runner; the differential lane's budget is now an hour, and it needs sharding before many more profiles compose.
Decisions taken (revisable), and questions
sourceSettlementsRespectOwnDeadlineis dropped as a scheduled invariant in favor of the written equivalence; a new exported regression pins the loader a read expiry starts at the read's due instant.independent, recovery-read and shadow-layers need neither.Next. recovery-read (markers, payload classes, the retention cap in authority) over the same seam; then shadow-layers (held dumps and writes, detached sources, shadow jobs).
lan17 commentedon Sep 20, 2026
Progress 7 (PR 188, head 9d64a88): the recovery-read profile is composed, the seventh of fifteen.
payloads(enveloped payload classes judged once inremote_frames::observefor both remote paths), the tracked one-hour cap inremote_framesapplied byserving::authority,remote_io::beginand the latest-effect judgments,Serving::maintainsand themutation_errorinvalidation outcome, and with the composer,markers(marker lifetime; expiry zeroes the watermark) andcompression(settlement variants reporting the decode outcome). 21 modules, 9 fixtures, 105 runs.NO_VALUE(=CALL_PENDING); fixed inrecovery::retainbefore landing. Main's Go API reshape (PR 190) invalidated 23 catalog anchors; all retargeted and compile/detection-verified in the merge commit.anyfor input decoding that selects between two library transitions (replay-safe becausenormalizeReplayInputsoverwritesmbt::actionTaken).Next: shadow-layers (designed: one
shadowmodule overServing::releaseJudged; bytes x0.93; two commits), then recovery, shadow (needs afutureBufferMsdimension onServing::invalidateor a profile-side raise), admission, effects; the local-failure fold and the per-profile bytes knob await the owner decisions listed in progress 6.lan17 commentedon Sep 20, 2026
Progress 8 (PR 188, head 5b4da7b): the shadow-layers profile is composed, the eighth of fifteen.
serving::releaseJudged(a variant that records beside the release judges once),startDetachedSource/flights::registerDetached,deadlinesoverScheduled,recovery::failure; with the composer,remote_writes(atomic release with held dump/write refills) andshadow(job registry, capacity, budgets, cohorts, captured fill authority). 23 modules, 10 fixtures, 129 runs.shadow, one shared refill-authority judgment, two connection clauses to restate over the drivers' literal code tables) are recorded in the PR for the shadow slice, which reworks the same module.Next: slimming wave 1, then recovery and the small profiles.
lan17 commentedon Sep 20, 2026
Progress 9 (PR 188, head 7db25ec): recovery, local-failure and local-clock are composed, the ninth, tenth and eleventh of fifteen; core stays uncomposed by decision (its drivers read private state), so three remain: shadow, admission, effects.
Kernel:
remote_io::settleDispatched/releaseJudged/beginReadand theirdeadlinesmirrors;diagnosticsgains the held lifecycle's channel; a fractional clock, an inline local call,flights::latest,instances::construct, the policy-provider layout fact,local_faults. Kernel fixtures 12 files.recovery: 9 library transitions, lint 0 (was 80); 30 regressions verbatim; 10 + 5 invariants (the monitor carries the candidate-window clause from the recovery-read follow-ups); differential 542/542 both ways; bytes x1.79 under a declared 1.85. local-failure x1.40 under 1.45, local-clock x0.63; both 100% agreement both ways.
Apparatus: the slimming wave landed (compact fixture encoding, minus 186k lines; derived schedules; narrower lock; per-model bytes bound; computed pins). A slice now touches the profile, the manifest's invariants and bound, mutations/semantic-cases citations, and tool-written files.
Decisions taken by default: per-model bytes bounds for recovery and local-failure (the shared kernel shapes have a structural floor above x1.2 on thin profiles); core stays uncomposed (its drivers read private state).
Parallel lanes: lane A (this branch) and lane B (a sibling branch merged in with a ledger reconciliation) ran the two slices concurrently.
Reviews (one round each plus the merge): recovery clean on correctness and contracts with hygiene items landed (dead kernel definitions deleted, a test budget, a citation); the small profiles had two medium items fixed before the merge (the local read fault is now a judgment argument, so it no longer switches off layer participation or sharing; a dead recipe binding deleted). Eight cross-lane exclusion cells were re-measured at the merge.
Next: shadow, admission, effects; the second slimming wave (derive go-parity.json, fold quint-case-audit into semantic-cases).
lan17 commentedon Sep 20, 2026
Progress 10 (PR 188, head d9e6d5a): admission is composed, the twelfth of fifteen; core stays uncomposed by decision, so two remain: shadow (in progress on a lane branch) and effects.
shadowgains the held lifecycle (job registry, capacity and budget limits, held settlements,busy,confirmation);remote_io::holdRead. Kernel fixtures 14 files, 166 runs.Next: shadow (lane branch, kernel commit then composition), effects (reusing shadow's future-buffer invalidation signature), then the audit follow-ups (pins manifest, the last go-parity mirrors, connection-model merges).
lan17 commentedon Sep 20, 2026
Progress 11 (PR 188, head f6ced95): shadow is composed, the thirteenth of fifteen; effects is in flight (its kernel commit runs on a third lane), and core stays uncomposed by decision.
invalidate(state, entity, bufferMs); pending-only job registry (shadow-layers bytes x0.90, admission x0.96). The kernel verify found and fixed a gap no old text reached: a caller's source deadline now ends a waiting dark job. Fixtures 15 files, 170 runs.Next: effects (kernel commit in progress; its composition merges this head first), then the interactions PR whose design is being written.
lan17 commentedon Sep 20, 2026
Progress 12 (PR 188, head 070e42f): effects is composed, the fourteenth of fifteen and the last planned one; core stays uncomposed by decision (both ports' core drivers read private state; a later slice may rewrite them to the public record). The composition series is complete.
remote_io::settleObserved/startLoaderFenced,deadlines::settleObserved, the held refill over the held read path (remote_writes::HeldWriting/settleLoader,HeldDump.sampled),diagnostics::begin; new modulesadapter_repliesandmetrics. 29 modules; fixtures 16 files, 189 runs.Next: the interactions PR (design written: a dark-shadow-over-layers profile first, executable refusals of unmodeled combinations, and a boundary-specific mutation gate), then the audit leftovers and the transitional bytes bounds.
feat(formal): map challenges to native mutants, require witnesses for…