Skip to content

Check no-conditional-none-branch only on event handlers - #257

Merged
SandroMaglione merged 1 commit into
mainfrom
oxlint-plugin-consumer-rules
Nov 1, 2026
Merged

SandroMaglione merged 1 commit into
mainfrom
oxlint-plugin-consumer-rules

Conversation

@SandroMaglione

@SandroMaglione SandroMaglione commented Nov 1, 2026 •

Copy link
Copy Markdown
Member

Summary

effect-machine/no-conditional-none-branch now checks only event handlers in a state's on record. Machine.can queries events, not invocation outcomes (onSnapshot, onDone, …) or eventless always transitions, so a resolver there may select a none branch conditionally. Dogfooding in #260 hit this false positive on the devtools invoke-outcomes-example.ts, whose onSnapshot resolver selects a titled none branch while the worker starts. This PR removes that suppression comment, and new valid tests cover onSnapshot and always.

The README's no-conflicting-invocation-identity example, which the formatter had collapsed into invoke: ;, is restored as two object literals.

Rules evaluated and not added

This PR originally ported seven rules from a production consumer. After review, none were kept:

  • no-runsync-machine-can: an application/React convention rather than a machine-model check.
  • no-guarded-none: a guarded none falls through to an ancestor handler when the guard fails, which is the same behavior as the suggested declinable resolver. The rule only forced a longer spelling.
  • no-duplicate-sibling-transitions: its fix can change behavior. A transition's callbacks read state relative to the declaring state, so the same guard gives a different result when moved to the parent. It also treated an unresolved root as non-parallel.
  • no-public-event-self-raise: a convention whose detection misses the common layout of events declared in another module.
  • no-shadowing-none: reports the documented pattern of deliberately ignoring an ancestor's event, and its fix duplicates handlers.
  • no-raise-only-resolve: reports the only way to transition and raise in one handler whenever the machine has any parallel state, even if the raised event never crosses regions.
  • no-large-machine-in-component: a file-organization policy with an arbitrary threshold.

Changeset

  • Added or updated for a library or package-metadata change (patch for @typeonce/oxlint-plugin-effect-machine)
  • Not required because this PR does not change a publishable package

Validation

  • pnpm check (includes pnpm lint, which now reports no finding on the devtools example without the suppression)
  • Plugin tests: 7 files, 97 tests
  • Automated type-performance measurement passed or was not required (no core change)
  • Automated runtime- and memory-performance measurement passed or was not required (no core change)

🤖 Generated with Claude Code

Machine.can queries events, not invocation outcomes or eventless
transitions, so no-conditional-none-branch now checks only resolvers of
handlers in a state's `on` record. This removes the false positive on the
devtools invoke-outcomes example, whose onSnapshot resolver selects a titled
`none` branch while the worker starts, and its suppression comment.

Also restore the no-conflicting-invocation-identity README example that the
formatter had collapsed into `invoke: ;`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@SandroMaglione
SandroMaglione force-pushed the oxlint-plugin-consumer-rules branch from d68e45b to cb011ff Compare November 1, 2026 22:56
@SandroMaglione SandroMaglione changed the title Add consumer-proven machine rules to the Oxlint plugin Check no-conditional-none-branch only on event handlers Nov 1, 2026
@SandroMaglione
SandroMaglione merged commit 8ae71a8 into main Nov 1, 2026
9 checks passed
@SandroMaglione
SandroMaglione deleted the oxlint-plugin-consumer-rules branch November 1, 2026 23:25
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