Skip to content

feat(lint): add the stx conformance checks to buddy lint - #2208

Merged
glennmichael123 merged 1 commit into
mainfrom
feat/lint-stx
Aug 4, 2026
Merged

feat(lint): add the stx conformance checks to buddy lint#2208
glennmichael123 merged 1 commit into
mainfrom
feat/lint-stx

Conversation

@glennmichael123

Copy link
Copy Markdown
Member

Redo of the closed #2206, in the shape you asked for:

./buddy lint:stx i dont think should be command either / buddy lint is fine / buddy lint --stx reads better, because there will be more options then just stx

./buddy lint --stx

What #2206 got wrong

then now
.stx-gate.json dotfile in the repo root config/lint.ts, typed LintConfig, alongside the other 45 configs
a stx-gate-types.ts nothing imported types declared where they are used
--update rewrote the baseline file the linter never writes to source; a stale baseline prints the counts ready to paste
its own top-level command a flag on the existing one

The dotfile was the worst of it — config/ui.ts documents the convention in its own comment ("Stacks keeps every runtime-owned directory under storage/ rather than a .stx in the project root") and I put a JSON dotfile in the root anyway.

What it checks

Chapter 12 of the stx standards, plus three that read the build output. Those three exist because a real bug shipped past every source-level check: a mis-resolved component put an error string where the sidebar should have been on every built page, so the app shipped with no navigation and the developer's home directory in the HTML — and the build still exited 0.

A ratchet, not a cliff

Counts are compared against config/lint.ts baselines, and the check fails both above a baseline and below one. Clearing a violation has to be recorded rather than quietly banked. A check with no entry is held at zero, so one added by a framework upgrade starts strict rather than inheriting whatever the project happens to have.

Stacks' own baselines

Shipped with it, each non-zero entry naming what clears it:

check count clears when
stx-config-keys 3 config/ui.ts sets strict/root/pagesDir
doctype-no-nolayout 5 stacksjs/stx#1798 lands generateDocumentShell htmlAttrs
style-block 2 the two remaining <style> blocks move to crosswind preflights
dom-guard 3 coming-soon.stx / index.stx move to signals
inline-style-attr 49 desktop demo components + pre-hydration display:none
plain-internal-anchor 1 index.stx's brand link becomes StxLink

stx-config-keys is recorded as debt rather than fixed in passing: pinning root+pagesDir changes how stx resolves topology and wants its own dev+build pass, which is not a change a linter should make on a project's behalf.

Not wired into CI. The framework does not pass its own checks yet, and turning a red gate on is a separate decision from making the tool exist.

Verification

Ratchet exercised both directions (regression → exit 1, stale baseline → exit 1 with the paste block), plain buddy lint unaffected, 241 buddy tests pass, pickier clean, framework + app typechecks clean, command reference regenerated and passing.

Once this lands, postline's scripts/stx-gate.ts gets deleted rather than annotated — my note-adding commit there was the wrong call.

🤖 Generated with Claude Code

Redo of the closed #2206, in the shape Chris asked for: a flag on the existing
command rather than a command of its own, since more lint modes than stx are
likely.

  ./buddy lint --stx

Chapter 12 of the stx standards, plus three that read the build output. Those
three exist because a real bug shipped past every source-level check: a
mis-resolved component put an error string where the sidebar should have been
on every built page, so the app shipped with no navigation and the developer's
home directory in the HTML, and the build still exited 0.

A ratchet, not a cliff. Counts are compared against baselines and the check
fails BOTH above one and below one, because clearing a violation has to be
recorded rather than quietly banked. A check with no entry is held at zero, so
one added by a framework upgrade starts strict.

What #2206 got wrong, and what changed:

  - Baselines were a `.stx-gate.json` dotfile in the repo root, against the
    convention `config/ui.ts` documents in its own comment. They now live in
    `config/lint.ts`, typed as `LintConfig`, alongside the other 45 configs.
  - There was a separate `stx-gate-types.ts` that nothing imported. The types
    are declared where they are used.
  - `--update` rewrote the baseline file. The linter no longer writes to
    source; a stale baseline prints the current counts ready to paste, which is
    the ergonomics the app-local original already had.

Stacks' own baselines ship with it, each non-zero entry naming what clears it.
Not wired into CI: the framework does not pass its own checks yet, and turning
a red gate on is a separate decision from making the tool exist.

Verified the ratchet both directions (regression fails, stale baseline fails),
plain `buddy lint` unaffected, 241 buddy tests pass, pickier and both
typechecks clean, command reference regenerated.
@github-actions github-actions Bot added actions @stacksjs/actions config @stacksjs/config docs @stacksjs/docs storage @stacksjs/storage types @stacksjs/types buddy Buddy core labels Aug 4, 2026
@glennmichael123
glennmichael123 merged commit 45655dc into main Aug 4, 2026
7 of 10 checks passed
@glennmichael123
glennmichael123 deleted the feat/lint-stx branch August 4, 2026 14:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

actions @stacksjs/actions buddy Buddy config @stacksjs/config core docs @stacksjs/docs storage @stacksjs/storage types @stacksjs/types

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant