Skip to content

Adds Statifier.check_accepts for a chart's declared events - #24

Merged
johnnyt merged 1 commit into
mainfrom
srb-7is-check-accepts
Oct 24, 2026
Merged

johnnyt merged 1 commit into
mainfrom
srb-7is-check-accepts

Conversation

@johnnyt

@johnnyt johnnyt commented Oct 24, 2026

Copy link
Copy Markdown
Member

Refs: srb-7is

What this adds

Statifier.check_accepts(machine, declared_events): a host that declares the event names a chart accepts asks which of them the chart can never select on, and which event descriptors the chart listens for that the declaration leaves out. It answers a frozen Statifier::AcceptsCheck with two lists:

  • unreachable: each declared name no descriptor in the chart's vocabulary matches, in the declaration's order, without duplicates.
  • undeclared: each descriptor in the vocabulary that matches no declared name, in transition index order (a state's own transitions before its children's), each descriptor once.

nil (no declaration) answers two empty lists; [] answers the whole vocabulary as undeclared. A machine of the wrong kind, a declaration that is neither an Array nor nil, or a declared name that is not a String raises TypeError, as the other public calls raise for arguments of the wrong kind.

The semantics, and where they come from

The reference is statifier-ex at v2.16.0, the tag the vendored corpus names:

  • The two lists: Statifier.Chart.check_accepts/2 in lib/statifier/chart.ex. A declared entry is a name, not a descriptor, so a * in it is an ordinary token.
  • The vocabulary: Statifier.Chart.events/1 and its private entry walk entered_states/1 in the same file. "Can be active" is a static rule over the chart's structure that reads no cond: the root by its default, then every state a transition, an initial, a parallel's regions or a history's default enters, with its ancestors and a parallel ancestor's untargeted regions. History pseudo-states contribute no descriptor. Descriptors are sorted by transition index and deduplicated as strings.
  • The matching: Statifier.Interpreter.NameMatch.name_match?/2 and tokenize/1. This package already has that matcher (Statifier::Interpreter::NameMatch, which transition selection uses), and the check reuses it; there is no second matcher.
  • The runner comparison: accepts/2 in lib/mix/statifier/corpus/host_case.ex. Both keys or neither; either alone is a disagreement naming the one present; the check's two lists must equal expect_accepts exactly, order included, before the session starts.

statifier-ts's checkAccepts (src/accepts.ts) has the same shape: a plain value with the same two members.

Return shape

check_accepts returns its AcceptsCheck directly, not a Statifier::Result. The reference and statifier-ts both return a plain value, and the check refuses nothing, so a Result would always have a nil error. The Statifier module doc and the README say that the other nine calls answer a Result and this one does not. The method name is statifier-ts's checkAccepts in snake case, decided by the conductor under a standing consent, 2026-10-23.

The runner and the registry

test/conformance/runner.rb now reads declared_events and expect_accepts (Drive::HONOURED_HOST_KEYS). The comparison lives in Conformance::Accepts (test/conformance/accepts.rb): it compiles the case and compares the check before the drive starts the chart. The statifier suite's accepts case, statifier/accepts/loan_declares_an_unreachable_event, now passes, and rake "ratchet[statifier]" added it to conformance/registry.json. The registry's claims are unchanged (scion, statifier, w3c-mandatory, w3c-optional). The README's conformance table now reads statifier 22 of 36 and 295 entries in all (119 + 22 + 152 + 2). The gate's registry stage prints 295 entries pass today, and its gap list names 14 unclaimed statifier cases: the ten diff cases and the four that state an exported position.

Tests

  • test/accepts/check_accepts_test.rb covers the public method: transition order with a chart whose walk enters a later state first; the matcher on token boundaries with prefixes, a trailing dot and wildcards; a * in a declared name; each entry rule (an ancestor's transition, a parallel's untargeted region, a history's default target, and a state no path enters); duplicates; nil and []; a deeply frozen answer with the host's strings left unfrozen; and the TypeErrors.
  • test/conformance/accepts_test.rb covers the runner: an exact comparison including order; the check compared before the chart is driven; either key without the other failing the case and naming the key that is present.
  • test/conformance/statifier_suite_test.rb now expects the suite's accepts group to pass. test/conformance/drive_test.rb tests the not-honoured refusal with a key the runner still does not read.

Every new test that asserts behaviour has a sabotage note: the code was broken, the named test failed on an assertion, and the file was restored byte for byte.

Gate

mise exec -- bundle exec rake is green on this head: rubocop clean on 197 files, corpus:check agrees, registry: 295 entries pass today, 614 runs with 0 failures, line coverage 99.81% (3164 / 3170), branch coverage 96.46% (1008 / 1045). The commit's tree is byte-identical to the tree that run checked.

Provenance

  • The brief's file map named the runner, the README, CLAUDE.md and the changelog fragment. The bead also forced two more files. test/conformance/accepts.rb holds the runner's comparison because adding it to Conformance::Drive pushed that module over the lint's module-length limit. test/conformance/drive_test.rb changed because its not-honoured test used declared_events as its example of a key the runner does not read.
  • The changelog fragment is changelog.d/srb-7is.md (Added).

A host that declares the events it will send can now ask which
declared names the chart can never select on (unreachable) and which
descriptors the chart listens for that the declaration leaves out
(undeclared). The lists and their order follow the reference's
Statifier.Chart.check_accepts/2 at v2.16.0: the vocabulary is every
descriptor on a transition of a state some path can enter, in
transition index order, matched with the selection's own event-name
matcher, and a declared name is never read as a pattern.

The conformance runner now reads declared_events and expect_accepts
as the reference's harness reads them: both or neither, the two lists
compared exactly before the chart starts. The statifier suite's
accepts case passes and joins the registry.

Refs: srb-7is
@johnnyt
johnnyt merged commit 5a0146b into main Oct 24, 2026
4 checks passed
@johnnyt
johnnyt deleted the srb-7is-check-accepts branch October 24, 2026 21:57
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.

1 participant