Skip to content

ROFL as a linter over its own rule files, and 21 rule packs cut to their decisions - #5

Open
Disentinel wants to merge 18 commits into
nextverfrom
lint-rules
Open

ROFL as a linter over its own rule files, and 21 rule packs cut to their decisions#5
Disentinel wants to merge 18 commits into
nextverfrom
lint-rules

Conversation

@Disentinel

Copy link
Copy Markdown
Owner

What this is

The question was whether two model-written rule files (rules/js-effects.rofl, rules/js-callgraph.rofl) could be shorter, and whether the answer would be visible structurally if ROFL itself were the linter. It was, so the instrument was built and then run over the tree.

The instrument

  • scanners/rofl_lint.ts turns every rule and fact pack into facts about its clauses (what it concludes, what it reads, an alpha-normalised body, which premises are implied through every arm of another premise) and its comment blocks (what follows each, banners, dates, backticked names).
  • rules/rofl-lint.rofl holds the criteria as rule bodies: orphan_block, dangling_mention/dangling_bare, section_twice/title_twice/list_repeats, twin, paired_arm, shape_twin, alias, implied, unread/unasserted_audit. Every one is a candidate list, none an [audit]: they are non-empty on an honest tree by design.
  • npm run rofllint renders the report; facts/rofl-lint.rofl is the committed census and rules_rofl-lint is a golden world, so a repair shows up as a count moving on bless.

What it found and what was repaired

  • Twelve orphan paragraphs in js-callgraph whose rules had moved to js-dataflow a week earlier; fn_binding cited and defined nowhere; section 6 twice and a list restarting in js-effects. All repaired.
  • top_call = top_site: one rule, one name now.
  • caught_here said a try with only a finally catches; repaired at the source with catches_via(try_statement, handler) and try_catches, and eff_catch_here collapsed onto it. The old finding's witness_absent became witness_in_atleast.

The comment cut

21 rule packs, every rules/js-*.rofl plus nullary, worklist, ingest, rule-shape and depends, cut to a header and one note per decision anchored to its clause. No rule text moved by a character: every golden held on every step and only the lint world moved on each bless. rules/js-* went from 6174 comment lines to 1605 against 3287 lines of rules. The instrument caught its own author six times on the way (do_while, may_be_*, resolve_*, replaced_by, rule_shape, peak_rows), which is the argument for running it on every file.

The ledger

  • Five findings recorded; facts/refactoring.rofl is a new queue volume (w_queue, refactoring_queue world) holding what the lint still reports on the clause side and was deliberately left for a decision: the may_be_node/may_be_lit template, the unread relations, the implied premises, the twins in worklist (needs_reach = waits_on), depends (code_needs = generated) and ingest, and ingest's undeclared host relations.
  • The service-graph design (url pack, fetch and express semantics, parts/joined abstraction, library meaning as an authored table) is recorded as five dependent items in facts/worklist.rofl and one design-principle finding.

Merge with nextver

nextver removed test/ and docs/dogfood/. The branch's edits to three test files, its mutant file for the lint (test/rofl-lint.test.ts, eight mutants) and its dogfood note went with them; the instrument's liveness now rests on the golden census alone, which is the same disposition the other 191 files got. Three settlements that cited those paths now cite the rule and the queue.

npm test: 87/87 worlds on both engines. The two DANGLING grave lines (test/version-plan.test.ts, test/publishes.test.ts) are nextver's own removed_in rows pointing at shas outside this shallow clone.

Next, per the owner: put npm run rofllint into CI.

🤖 Generated with Claude Code

https://claude.ai/code/session_011pE9mh2aKYpNhpEzgsJ6ps


Generated by Claude Code

scanners/rofl_lint.ts turns every rule file into facts about its clauses
and comment blocks; rules/rofl-lint.rofl holds the criteria as rule
bodies (orphan blocks, dangling names, twins, aliases, implied premises,
unread relations); npm run rofllint renders them. test/rofl-lint.test.ts
pins the rows found in js-callgraph and js-effects and measures the
instrument with a mutant set. Nothing here is a gate: every relation is
a candidate list, non-empty on an honest checkout by design.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011pE9mh2aKYpNhpEzgsJ6ps
catches_via(try_statement, handler) in rules/js-controlflow.rofl is the fact
about the language as a row; caught_here reads it through try_catches, so
may_throw, thrown_by and the effect layer stand on one guard instead of the
effect layer carrying its own. leaky/useLeaky in alpha.mjs is the corpus
site the defect never had; the tripwire the finding asked for fired on it
before the repair went in. The witness moves from an absence to a floor.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011pE9mh2aKYpNhpEzgsJ6ps
…by the try_catches repair

Golden set 85/85 worlds; the DANGLING lines are nextver's own and predate
this branch.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011pE9mh2aKYpNhpEzgsJ6ps
No rule text moves — every mutant anchor and every golden holds. What stays
beside a rule is the reason it is not the obvious rule; what went was
history, measurements, the ghost of section 4 whose rules moved to
js-dataflow on 2026-09-04, and a section header that had been renumbered by
hand. js-effects 791 -> 222 comment lines, js-callgraph 570 -> 135. The
limitations list is kept whole and renumbered. rofl-lint's comment-side
controls flip from present to absent with the repair.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011pE9mh2aKYpNhpEzgsJ6ps
Twins since the 2026-09-08 repair moved top_call from call_site to site;
frontier_at's transfer arm now reads top_call and top_site is gone. Goldens
85/85; the callgraph world moves by exactly one rule.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011pE9mh2aKYpNhpEzgsJ6ps
…on twins

Three items rofl-lint priced: the value layer written twice (fourteen
may_be_node/may_be_lit pairs), four relations nothing reads, eighteen implied
premises. Declared as the refactoring_queue world in facts/checks.rofl and as
a pack of w_queue. The decision on the other thirty-three pairs — a name
beats a mode column until the boilerplate is tenfold; templates as sugar
deferred past ten real templates — is in the ledger.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011pE9mh2aKYpNhpEzgsJ6ps
…irst

w_concat_value -> w_url_pack -> w_fetch_semantics / w_express_semantics ->
w_service_graph, ordered by work_needs; the queue hands out the value
abstraction first because four items stand on it. The principle is in the
ledger: one abstract value per question, entry points per syntax, library
meaning as an authored table with provenance, and what libraries disagree on
as a column a reader can refuse by name.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011pE9mh2aKYpNhpEzgsJ6ps
No rule text moves. 1249 comment lines to 235; sixteen numbered sections,
each note the reason a rule is not the obvious rule.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011pE9mh2aKYpNhpEzgsJ6ps
No rule text moves. 933 comment lines to 179; eight numbered sections, the
mechanism table and the three-state gate kept with their reasons.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011pE9mh2aKYpNhpEzgsJ6ps
No rule text moves. js-modules 463 comment lines to 119 (sections renumbered:
7 was used twice), js-model 397 to 82.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011pE9mh2aKYpNhpEzgsJ6ps
…sions

No rule text moves. Comment lines: js-ambient 384 to 134, js-host 300 to
109, js-env 232 to 77, js-globals 211 to 73. The lint reports no orphan
block, dangling name or renumbered section in any of the four.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011pE9mh2aKYpNhpEzgsJ6ps
…bulary: cut the comments to the decisions

No rule text moves. Comment lines: js-resolve 152 to 70, js-attrs 140 to
55, js-pack-home 136 to 41, js-structure 96 to 27, js-env-api 60 to 23,
js-vocabulary 60 to 22. The lint reports no orphan block, dangling name or
renumbered section in any of the six.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011pE9mh2aKYpNhpEzgsJ6ps
…e dogfood note

6174 comment lines to 1605 with no rule text moved; the settled count is 674.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011pE9mh2aKYpNhpEzgsJ6ps
No rule text moves. Comment lines: nullary 204 to 87, worklist 186 to 75.
The lint reports no orphan block, dangling name or renumbered section in
either; the clause-side rows it still reports (needs_reach = waits_on,
held_by :- held, unread held_by) are left for the refactoring queue.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011pE9mh2aKYpNhpEzgsJ6ps
No rule text moves. Comment lines: ingest 123 to 54, rule-shape 112 to 62,
depends 106 to 55. The one dangling name left, needed_hot in ingest, is the
file's own: a relation it reads that nothing declares, queued as
w_ingest_declares_half_its_host_relations.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011pE9mh2aKYpNhpEzgsJ6ps
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011pE9mh2aKYpNhpEzgsJ6ps
nextver removed test/ and docs/dogfood/; the branch's three test edits, its
new mutant file for the lint and its dogfood note go with them. The three
settlements that cited those paths now cite the rule and the queue. Goldens
re-blessed: the lint and refactoring worlds are new, and the callgraph,
controlflow, effects, worklist, worlds and findings worlds carry this
branch's rows over nextver's base.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011pE9mh2aKYpNhpEzgsJ6ps
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