Skip to content

feat(rules): add Octane correctness diagnostics - #1659

Draft
aidenybai wants to merge 2 commits into
mainfrom
aiden/octane-rules-993d
Draft

feat(rules): add Octane correctness diagnostics#1659
aidenybai wants to merge 2 commits into
mainfrom
aiden/octane-rules-993d

Conversation

@aidenybai

@aidenybai aidenybai commented Aug 18, 2026

Copy link
Copy Markdown
Member

Catches Octane hook-slot collisions in plain JavaScript loops and React-style text onChange handlers that only fire on native commit.

Why

Octane tracks slot-keyed hooks by compiler-assigned call site. Repeating one call site in a plain JavaScript loop makes iterations share state, memo, or effect storage, so Octane rejects the pattern. Octane also uses native DOM events: text onChange runs on commit or blur, while onInput runs for each edit.

import { useState } from "octane";

for (const item of items) {
  useState(item);
}

<input value={query} onChange={(event) => setQuery(event.currentTarget.value)} />

Use keyed TSRX iteration or a child component for repeated hooks, and use onInput for per-edit text updates:

@for (const item of items; key item.id) {
  const [value] = useState(item);
  <Row value={value} />
}

<input value={query} onInput={(event) => setQuery(event.currentTarget.value)} />

Intentional native commit behavior remains supported with suppressNativeChangeWarning.

What changed

  • Added octane-no-hook-in-loop, including aliases, namespace calls, custom hooks, IIFEs, .call()/.apply() IIFEs, and synchronous iterator callbacks.
  • Exempted use(), useContext, deferred nested functions, conditions, early returns, and loop-free callbacks.
  • Added octane-no-native-text-onchange using Octane's compiler decision boundaries for text input types, callable input handlers, readonly/disabled controls, dynamic props, spreads, capture handlers, explicit suppression, and non-DOM renderers.
  • Gated both rules to modules proven to use Octane and tagged them octane.
  • Added generated registry entries, liveness fixtures, adversarial tests, and a patch changeset.

Evidence

The contracts follow Octane's current compile-errors.test.ts, native-change-compiler.test.ts, compile.js, native-change-diagnostics.js, and public differences-from-React documentation. The implementation intentionally stays within those compiler-proven boundaries.

Validation

  • Plugin tests: 1,114 files passed; 27,521 tests passed and 187 skipped.
  • Plugin typecheck: passed.
  • Strict fuzzing: 500 iterations per new rule, both passed and both reached their liveness fixture.
  • Full repository test, lint, typecheck, format:check, and smoke:json-report: passed.
  • Local RDE inspection was unavailable because no React Doctor Evals checkout exists in this environment.
  • PR parity was blocked because DAYTONA_API_KEY is not available in this environment.

Test plan

  • nr --filter oxlint-plugin-react-doctor test
  • nr --filter oxlint-plugin-react-doctor typecheck
  • FUZZ_RULE=octane-no-hook-in-loop FUZZ_STRICT=1 FUZZ_ITERATIONS=500 nr fuzz
  • FUZZ_RULE=octane-no-native-text-onchange FUZZ_STRICT=1 FUZZ_ITERATIONS=500 nr fuzz
  • nr test
  • nr lint
  • nr typecheck
  • nr format:check
  • nr smoke:json-report
Open in Web Open in Cursor 

Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com>
@pkg-pr-new

pkg-pr-new Bot commented Aug 18, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/eslint-plugin-react-doctor@1659
npm i https://pkg.pr.new/oxlint-plugin-react-doctor@1659
npm i https://pkg.pr.new/react-doctor@1659

commit: 638ae6c

Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

Interactive terminal E2E

Terminal Control verified the built CLI at 638ae6c in a real PTY:

  • selected a project interactively and observed Scanning... before the three-second Git delay completed
  • waited for the clean result and exercised the compact report
  • opened copy context and the GitHub Actions confirmation, then cancelled safely

Download the edited MP4 and PNG evidence

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.

2 participants