web lint hook: run a check when a file it reads changes (Swift-only pushes skipped check:text-focus)
Summary
The pre-push web lint did not run a check when a push changed a file that the check reads but that is outside the check's package triggers. webviews' check:text-focus (scripts/cmux-next/check-text-focus-rings.py) walks Packages/macOS/CmuxNext/Sources/**/*.swift. The hook planned the webviews check only from triggers (webviews/, config/vite-plus/, scripts/cmux-next/, the acpmux spec), so a Swift-only push linted nothing. That is how 385cb09a747 (McpConnectCardParts.swift, Swift only) passed the hook and then turned feat-cmux-next's web lint (fast) red (fixed by #33979).
Correction (from review): c0230efd501 (AllThemesPlaygroundView.swift, fixed by #34025) is not covered. That push also changed scripts/cmux-next/media/states/*.json. This folder is a webviews trigger and an executed path, so the hook refused to lint the push ("not linted here") for that reason, before and after this PR. The module docstring also names c0230efd501; a follow-up will correct it.
The rule now: a check runs when any input it reads changes.
- Each source-check script declares what it reads next to its own path constants, as a module-level
INPUTStuple. Example:INPUTS = (TREE, f"{SWIFT_TREE}/**/*.swift"). The declaration is part of the check, so there is one source of truth. scripts/web_lint_prepush.pyreadsINPUTSwithastand never runs it (declared_inputs(),input_pieces()). Onlypython3pieces that the hook already accepts as guarded source checks (light_script) qualify.- A change that misses the package triggers but touches a piece's
INPUTSruns only those pieces, as argument lists with no shell and no install. This is the same on a build host and on a host withCMUX_LOCAL_HEAVY_CHECKS=0. A Swift-only push costs about 3 s, not the whole webviews check. - These pieces never run code that the push changed. A change to a piece's own script is under
scripts/cmux-next/, which is a trigger and an executed path. The hook therefore refuses to lint that push, as before.
Other webviews pieces that read files outside webviews/ are now declared in the same way:
| Piece | Reads outside webviews/ |
|---|---|
| check:text-focus, check:toast-targets, check:dialog-keys | Packages/macOS/CmuxNext/Sources/**/*.swift |
| check:system-blue | Packages/macOS/CmuxNext/Sources, Packages/Shared |
| check:session-info-names | two CmuxNext Swift files (one under Tests/) |
| check:catalog-keys | every *.xcstrings |
| check:type-scale, check:motion-scale, check:layout-grid, check:status-glyphs, check:surface-roles | their schemas/ source and generated Swift file |
Not covered (these are not source-check pieces):
vp check(the type check) imports JSON and JS from outside webviews/:schemas/{settings,layout-grid,agent-pane,sync-motion},web/data/model-catalog,Packages/Shared/CmuxAgentQuestion/.../Fixtures,Resources/markdown-viewer,cmux-tui/spec/page-router.json, a CmuxNext font. Running the type check for those changes would need the full install, so this PR leaves them to CI.check:attachment-capsruns with--warnand cannot fail.
The web lint (fast) job on feat-cmux-next runs the same script, so a Swift-only push with a known base now runs these pieces there too. No CI job, step or gate is added. The PR fast gates' web_needed is unchanged.
Testing
Red on the base, green on the head (the test is in its own commit, 4fe06333544):
(cd tests && python3 -m unittest -k swift test_web_lint_prepush)
- Base ba1cf8e38ee: 2 of 3 fail. The Swift-only push with a ringed
TextFieldreaches origin. The dry run printsnothing to lint. - Head: 3 of 3 pass. The push is refused and names
Field.swift:3, on a build host and on a host withCMUX_LOCAL_HEAVY_CHECKS=0. No other piece runs. A clean Swift push runs onlycheck-text-focus-rings.pyand passes. A Swift file that no piece reads lints nothing.
Observed / Not run
Observed:
python3 tests/test_web_lint_prepush.py: 62 tests OK. This includes two new unit tests:declared_inputsandinput_matchesforms, and the realwebviews/package.jsonthat selects the four Swift-reading pieces for a CmuxNext Swift path and none forREADME.mdorios/App.swift.python3 -m unittest test_cmux_next_fast_gates: 77 OK.python3 scripts/cmux-next/prepush-gate.py: no new violations.- Every declared piece run by hand on the tip: all pass in 3.3 s or less, except check:text-focus. Its red is the base red from c0230efd501, which #34025 fixes.
scripts/web-lint.sh: only that same base red.
Not run:
- A real push to feat-cmux-next with a Swift-only change through the installed hook. The tests drive the real
git pushand the installed hook copy in a throwaway repository.
Changelog
none
Proof
No capture: hook and CI tooling only.