Skip to content

fix(lint)!: prefix option constructors to avoid Base collisions - #1565

Merged
Lorenzobattistela merged 2 commits into
bendlang:mainfrom
vicmcorrea:fix/lint-option-text
Oct 15, 2026
Merged

Lorenzobattistela merged 2 commits into
bendlang:mainfrom
vicmcorrea:fix/lint-option-text

Conversation

@vicmcorrea

@vicmcorrea vicmcorrea commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Problem and fix

Base's Text constructor for Event, added in #1441, collides with bend-lint's text option constructor. Bend-written rules, including the bundled file-length rule, fail to load with duplicate declaration: Text.

Use consistent OptionNum, OptionFlag, and OptionText names for the three option constructors, their helper match arms, and their JavaScript bridge tags. Document the constructor migration in the README's rule-authoring section.

Blast radius

  • tools/bend-lint/src/bend/lint.bend: three option constructors and nine helper match arms.
  • tools/bend-lint/src/bend/effects.js: the tags used to send number, boolean, and string options to Bend rules.
  • tools/bend-lint/README.md: migration guidance for rule authors.

Compatibility impact: direct construction or matching of Lint.Num, Lint.Flag, and Lint.Text must use Lint.OptionNum, Lint.OptionFlag, and Lint.OptionText. Bare constructor names and handwritten foreign CID(...) references also need updating. Documented option helpers, JSON configuration, and TypeScript option APIs retain their behavior; bundled rules use the helpers.

The compiler, Base, formatter, and gates are unchanged. Existing tests stay in bend-lint's suite, following the maintainer guidance in #1389.

Regression evidence

The existing a Bend rule reads its options with defaults test compiles the actual contract and executes the JS bridge with number, boolean, and string options. It fails on base dbb3157 at the duplicate declaration and passes with this fix. Restoring only the old CID(Text) bridge tag in the final source makes that same test lose the configured string (none instead of x), so it also detects an incomplete rename. No additional test is needed.

Clean base's tool suite reports 109 pass / 9 fail / 1 error; the fixed suite reports 122 pass / 0 fail. The file-length test module now loads and its tests register.

Checks

  • bun test in tools/bend-lint: 122 passed, 0 failed; 700 assertions.
  • bun gates/repo.ts: 54/54, with CI-pinned ttok 0.3.
  • Actual CLI with the Bend file-length rule: loads, reports the expected warning for three lines with maxLines: 1, and exits 0.
  • git diff --check: passed.

Validation limits

Local checks ran on macOS arm64 with Bun 1.3.11. Windows, the cluster gates, and typecheck were not run. External third-party rules and alternative Bend releases were not tested; direct constructor consumers require the migration described above. Other bare tool constructor names remain subject to collisions with future Base additions; this change only updates the option constructors.

Use OptionText in the Bend option contract and its JS bridge so Bend-written rules load with Base's Text event constructor.

BREAKING CHANGE: direct Lint.Text constructor users must use Lint.OptionText. Option helpers and configuration are unchanged.

@nicolas-abril nicolas-abril left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI review (Claude Code), posted by @nicolas-abril.

No bugs in the diff itself: at 645d9e29 no Text constructor reference is left in tools/bend-lint, and Base and bend-lint now share no constructor names except Base's own Some and None. The rest is about how this can happen again, and what fails silently.

In this PR

  1. The rename needs a migration note in the README (lint.bend:34). It breaks user rules: one matching case Some{Lint.Text{t}} now fails with an unknown-constructor error, and one matching a bare Text{t} now binds to Base's Event.Text and fails with a type error. Neither error points at the rename, and the compatibility note is only in the PR body, not in tools/bend-lint/README.md's rule-authoring section.
  2. The Value constructors are named inconsistently (lint.bend:32): Num, Flag, OptionText. Num and Flag are generic enough that Base could add them too, which would repeat this outage. Renaming all three the same way (OptionNum, OptionFlag, OptionText) in this breaking change costs no extra compatibility.

Outside this PR (follow-ups)

  1. No gate runs bend-lint's tests (repo-gate.yml:37). Only gates/repo.ts runs on PRs, which is how #1441 merged while breaking bend-lint. Main at dbb3157 already shows 109 pass / 9 fail / 1 error under bun test in tools/bend-lint.
  2. The root cause is still there (bend.ts:2425). parse_fresh rejects a module-local name whose bare form is already declared, so a module can't reuse a name Base defines. lint.bend still declares about 30 bare constructors (Num, Flag, Span, Edit, Fix, Error, Warning, Hint, Node, Term, Option, Use, View, Shape, …). Base adding any of them gives duplicate declaration and stops bend-lint and every Bend rule from loading. Letting a namespaced declaration shadow Base's bare name, or namespacing Base, would fix the whole class. (bend.ts is human-written per AGENTS.md.)
  3. A stale bridge tag binds silently (comp.ts:2789). c_ids resolves CID(k) in the source's namespace first, then falls back to the bare k. Foreign JS still using CID(Text) after this rename resolves to Event.Text instead of failing to compile. The rule gets a tag no option_*_or arm expects, so string options quietly come back as their default (the none instead of x this PR ran into).

Suggest fixing 1 and 2 here, and opening issues for 3 to 5.

Use OptionNum and OptionFlag alongside OptionText, and document direct constructor and foreign CID migration for rule authors.

BREAKING CHANGE: direct Lint.Num and Lint.Flag users must use Lint.OptionNum and Lint.OptionFlag. Option helpers and configuration are unchanged.
@vicmcorrea vicmcorrea changed the title fix(lint)!: rename the colliding text option constructor fix(lint)!: prefix option constructors to avoid Base collisions Oct 14, 2026
@Lorenzobattistela
Lorenzobattistela merged commit 7e08d6d into bendlang:main Oct 15, 2026
1 check passed
@Lorenzobattistela Lorenzobattistela mentioned this pull request Oct 20, 2026
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.

3 participants