Skip to content

[DEV-1822] Document the four non-routing boot-lint rules and rule severity - #293

Open
galisufyan-327 wants to merge 4 commits into
masterfrom
fix/DEV-1822-boot-lint-ruleid-docs
Open

[DEV-1822] Document the four non-routing boot-lint rules and rule severity#293
galisufyan-327 wants to merge 4 commits into
masterfrom
fix/DEV-1822-boot-lint-ruleid-docs

Conversation

@galisufyan-327

@galisufyan-327 galisufyan-327 commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Product areas affected

Developer docs only (docs/API/v3/) — app-bootstrap.md, routing.md, frameworks/react.md, plus the regenerated .well-known/ search-index artifacts. No CLI code, no runtime behaviour.

What does this PR do?

The Studio V3 AI builder lints generated boot HTML, and on rejection tells the model: each violation carries a ruleId that maps to a row in the routing.md "Forbidden patterns" table — use the table to find the canonical replacement.

That table documented only the 8 routing rules. Four rules had no row anywhere in the docs — and per 90 days of production data those four are 96% of all real violations:

Undocumented ruleId Violations / 90d
duplicate-fliplet-require 150 (76% of all violations)
get-contents-as-module-default-access 30
undeclared-lazy-name 10
font-awesome-not-available 0

So the docs pointer was a dead end for almost every rejection a real user hits. This PR gives all four a row in app-bootstrap.md, cross-linked both ways with the routing table.

It also adds a Severity column to both tables, because the paired Studio PR splits the lint into two tiers: blocking rules refuse the save, warn rules deploy and return warnings alongside a successful save. The docs previously couldn't express that distinction at all — notably that createBrowserRouter blocks while <HashRouter> only warns.

Three inaccuracies were corrected along the way, each verified against lintV3Boot.js:

  • undeclared-lazy-name remedy was wrong. It said registered Fliplet packages "are declared by plain name and loaded with Fliplet.require.lazy.chain('name')". A plain-name declaration is eager (addDependencies.js:17-18), so the name never lands in window.ENV.dependencies.lazy and lazy.chain rejects at runtime. Worse, the lint can't catch it — declaredLazy is built from every page dependency regardless of its lazy flag — so following that advice produced boot HTML that passed the lint and failed in the app. Now states the real { latest: '', lazy: true } shape, and the tool's true { dependencies: [ … ] } wire shape rather than the flat house shorthand.
  • A lint rule that does not exist. app-bootstrap.md cited viewport-not-locked; no such rule is in lintV3Boot.js or anywhere in Studio's src/v3/ai/. The viewport requirement is real and stays — the claim that the lint enforces it is gone.
  • get-contents-as-module-default-access row described the failure as ".default is undefined" (it's a hard TypeError: <id>.default is not a function) and narrowed the forbidden pattern to <id>.default(...) when the rule fires on any .default access.

Finally, three statements elsewhere in the doc set that the new severity column contradicted: frameworks/react.md ("both are rejected by lint"), routing.md's frontmatter description ("the full list of forbidden patterns"), and app-bootstrap.md's intro (blanket lint-rejection across all four constraints, when only constraints 1 and 2 have rules).

JIRA ticket

DEV-1822

Result

Every ruleId the lint can emit now has a documented row with a severity and an actionable remedy — 12 rules across two tables, 8 routing + 4 non-routing, cross-linked in both directions.

Both severity tables were audited row by row against lintV3Boot.js, including the two rules emitted outside the RULES array (undeclared-lazy-name, get-contents-as-module-default-access — both block) and the two RULES entries that share ruleId: 'path-dispatcher' (both warn, correctly collapsed to one row).

Checklist

  • Added automated test coverage as appropriate for this change.

Docs-only, so the applicable coverage is this repo's own CI gates, both re-run on the final commit: npm run check:docs (strict — frontmatter, capabilities, and cross-link validation; 203 docs, exit 0) and npm run test:unit (163/163 pass). Both new anchors resolve and no inbound cross-reference breaks.

Deployment instructions

None — docs publish on merge.

Should land with the paired Studio PR Fliplet/fliplet-studio#8872, which is where the severity split these tables document actually lives. Merging this first would describe behaviour that isn't shipped yet; merging Studio first leaves the tool error pointing at a table that still has no row for 96% of violations.

Author concerns

  • The .well-known/ artifacts are regenerated build output, committed in the same commits per this repo's convention (094ad63, 0064828, cb6d473). Every changed artifact line was traced to a source edit: llms.txt and agent-skills/fliplet-js-api/SKILL.md carry the routing.md description change, index.json the resulting sha256, llms-full.txt the three body edits, and llms-v3-libraries.json only its generatedAt bump. Re-running the generator reproduces them byte-identically apart from that timestamp.
  • app-bootstrap.md:82 renders `Fliplet.require(...)` verbatim — in the very doc the block error tells the model to fetch while it is retrying that rule. The paired Studio PR removes that exact string from the always-present builder prompt on the hypothesis that verbatim rendering drives the 76% copy rate. A "what's forbidden" column can't name the pattern without showing it, and the lint's own guidance string already puts the same text in the model's context on every block — so this is defensible, but it means the prompt rewrite alone doesn't close the mechanism hypothesis.
  • "Constraints 1 and 2 are also enforced by the boot-HTML lint" is true per-rule but broader than the rules are: the lint checks aspects of those constraints (no bare require(, declared lazy names, no .default), and nothing detects a <script src="cdn…"> tag, an import, or a missing getContents fetch. A reader could infer "lint clean ⇒ constraints satisfied". Same class as the claims this PR swept, much smaller magnitude.
  • app-bootstrap.md's frontmatter description doesn't mention the new rule table, so none of the four ruleIds is findable via search_fliplet_docs. Low impact: the load-bearing path doesn't go through search — the block error names fetch_fliplet_doc({ path: 'API/v3/app-bootstrap.md' }) directly, and that path is a hardcoded entry point in the builder's docs-lookup.md. Only the fuzzy-search route is degraded.
  • routing.md's description is 170 chars against the ≤160 budget in docs/CLAUDE.md. Improved from master's 175 but still over; check:docs --strict does not enforce length. Left as-is rather than triggering another review round on a cosmetic overrun that predates this change.

galisufyan-327 and others added 4 commits August 24, 2026 18:55
…rity

The boot-HTML lint tells the AI builder that each violation's ruleId maps to
a row in routing.md's forbidden-patterns table, but that table only ever
covered the eight routing rules. duplicate-fliplet-require,
undeclared-lazy-name, get-contents-as-module-default-access and
font-awesome-not-available had no row anywhere, so the pointer was a dead end
for the large majority of violations users actually hit.

Give the four non-routing rules their own forbidden-patterns table on the app
bootstrap page, cross-linked both ways with the routing one, and add the
severity column now that the lint grades rules into block (refuses the save)
and warn (deploys, reports alongside).

Also make the declaration prerequisite explicit where the doc introduces
Fliplet.require.lazy: the engine resolves only names the page declared, which
is what undeclared-lazy-name fires on.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
State the real registered-lazy declaration shape (latest: '', lazy: true) and
the add_dependencies wire shape, name the TypeError the .default access
actually throws, widen that rule to any .default read, and drop the citation
of a lint rule that does not exist.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Nothing lints the viewport meta, so the warning promised enforcement that
does not exist. The constraint itself is unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
createBrowserRouter blocks but the HashRouter component only warns; the
routing page covers routing rules only, not every forbidden pattern; and the
boot-HTML lint enforces the first two bootstrap constraints, not all four.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying fliplet-cli with  Cloudflare Pages  Cloudflare Pages

Latest commit: e0bfa86
Status: ✅  Deploy successful!
Preview URL: https://57e2409b.fliplet-cli.pages.dev
Branch Preview URL: https://fix-dev-1822-boot-lint-rulei.fliplet-cli.pages.dev

View logs

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