Skip to content

v1.13.0 — actions that happen once, and ledgers that tell the truth about what they dropped

Choose a tag to compare

@sanjay1909 sanjay1909 released this 20 Aug 21:51
· 17 commits to main since this release

[1.13.0] - 2026-08-20

Added

  • concurrency: { mode: 'once' } — the receipt survives settlement
    (Context Integrity, the choice seam). single-flight suppresses a repeat
    while the first occurrence is unresolved; the measured duplicate-execution
    failure happened after it settled. 'once' is a third mode at the same
    declaration door: one EXECUTED occurrence per scope for the session, refused
    DUPLICATE_EXECUTION with the receipt (priorTransitionId) and the authored
    howToRepeat sentence. Two field lessons are the law's shape: only a person
    acting on the screen (a user-attributed transition after the receipt) reopens
    the action, and the reopened repeat FIRES carrying repeated on the result
    AND the transition record — report, don't refuse. A refused first occurrence
    minted no receipt; an 'unobservable' one counts (unprovable non-execution
    is not non-execution). While the first is unsettled, 'once' answers exactly
    as single-flight (PRIOR_FIRE_PENDING). The served row carries the verdict
    (alreadyPerformed, action scope only) and Mode B greys the control out —
    never send a person to approve a fire about to be turned away. Scopes,
    payload identity and the matcher are single-flight's own (sameFire, one
    owner of "what counts as the same fire again").

  • TransitionRecord.instance — the repeats-container card a fire named now
    rides its receipt. A record that says what was pressed but not which row
    cannot answer "did we already cancel order #57?".

  • Bounded ledgers state their retention window, and every silent cut now
    speaks
    (Context Integrity, phase 0). session.offersRetention() /
    session.acknowledgementsRetention() answer { minted, dropped, firstRetained, lastRetained } — the window that is still answerable, not
    only the loss — and session.offerStanding(id) asks the three-way
    retained/evicted/unknown question without firing anything. Oversized
    sensing trails join the house standard: evictions are counted
    (sensedTrailsDropped()), and sensedTrail() on an evicted trail says
    EVICTED with the surviving count instead of an answer indistinguishable
    from "never sensed". The data channel's silent caps now announce
    themselves the way its string cap always has: an array cut at 30 appends
    … N more omitted, an object cut at 40 keys carries "…": "N more key(s) omitted". And a repeats row's render cap states its size:
    instancesTotal rides the served row and both instance refusals, so 50
    keys of 200 can never read as 50 of 50 (fireability was always uncapped;
    now the served row says so).

  • The unknown-instance refusal says which kind of wrong it is (Context
    Integrity). INSTANCE_UNKNOWN now carries
    verdict: 'never-existed' | 'unsupported', decided by the coverage of the
    set the id was compared against — the same source the served row's
    enumeration states. Absent from the app's declared existence source (a
    selector set enumerates everything that exists) → 'never-existed', and
    the refusal may finally say so. Absent from the mounted window →
    'unsupported': not backed by anything served, and that is ALL the refusal
    knows — a window has an edge, the world continues past it, and under a
    capped window an id past the render cap is exactly the case
    'unsupported' protects. A selector that throws or answers a non-array
    falls back to the mounted window, and the verdict falls back WITH it: a
    nonexistence claim never outlives its evidence.