ci(lint): add oxlint and fail CI on any warning (#828) - #839
Merged
Merged
Conversation
…and roles set (Tencent#836) The three commands saved the local config and reset lastPullRev even under the global --dry-run, which is documented as "Preview mode, no changes made". Their siblings (tags add/remove, roles init/add/remove/ update) already return early with a [dry-run] message. The roles set preview names the additional roles it would save, including none, because a real run replaces the existing list. oxlint reported the unused options parameter in tagsSubscribe and tagsUnsubscribe; rolesSet has the same bug but reads options.add.
Pinned to an exact version so a new default rule arrives in its own PR, not as a CI failure on an unrelated one. The no-unused-vars options keep oxlint's _ ignore patterns and add ignoreRestSiblings, which the rest-omit in dashboard.ts relies on to keep config and roots out of /api/workspaces.
Drop redundant escapes in regex character classes and template literals, empty-object fallbacks in object spreads (spreading undefined adds nothing), and anchored regexes that are plain startsWith/endsWith checks. No behavior change.
Applied with oxlint --fix-suggestions and reviewed by hand. Every removed whole import is a library module with no import-time side effects.
Each hit was checked against its callers and git history; none is missing wiring (the two that were, tags subscribe/unsubscribe, are fixed in the preceding commit). Removed: unused locals and functions, the options parameter of tagsList, rolesList and generateDigest (read-only commands), the never-read interactive option of importFromRepo, the empty test/e2e.mjs left over from the E2E migration, and a try/catch that only rethrew. new Array(n) becomes Array.from. No behavior change.
- contribute dry-run test asserted nothing; it now checks that the run leaves the repo/HOME tree unchanged (verified to fail when the dry-run early return is removed). - Drop a no-op expect(result).not.toThrow on a string. - Keep undefined in two optional-chain casts so a regression fails the assertion instead of throwing a TypeError. - Remove unused locals, helpers and imports; new Array(n) becomes Array.from.
no-control-regex flags literal control ranges. \p{Cc} names the same
set (C0, DEL, C1) and reads as what it means. Checked against the old
classes on every code point from U+0000 to U+10FFFF: manifest-schema and
agent-format match exactly, and contribute-check's normalization
pipeline produces the same output. The test assertion is now stricter
and checks every control character the sanitizer removes.
Four eslint-disable comments named rules this repo never ran (no-await-in-loop, @typescript-eslint/no-explicit-any), so they suppressed nothing.
npm run lint runs oxlint --deny-warnings and runs before the type check in both GitHub Actions and Coding CI. The repo is at zero warnings, so new code must stay clean. --report-unused-disable-directives also fails on a disable comment that suppresses nothing, so a suppression cannot outlive the code it was written for. CLAUDE.md, AGENTS.md, CONTRIBUTING.md and the PR template list the command so contributors and agents run it before opening a PR. Closes Tencent#828
|
…20.0 oxlint 1.17.0 and later declare engines.node ^20.19.0 || >=22.12.0, while the repo supports Node >=20. 1.16.0 declares >=8, supports --deny-warnings and --report-unused-disable-directives, and reports 0 warnings on this branch.
…bscribe and roles set (Tencent#836)" This reverts commit 224d459.
…nd unsubscribe With the Tencent#837 dry-run fix reverted out of this PR, both functions no longer read options. The underscore prefix keeps the signature and call sites unchanged, so Tencent#837 can rebase onto it by renaming the parameter back.
This reverts commit e2347ef. oxlint is a devDependency, so its Node requirement (^20.19.0 || >=22.12.0) never reaches users installing teamai-cli, and CI's node-version 20 resolves to the latest 20.x. Staying on 1.85.0 keeps the Tencent#836 warning counts and the planned type-aware follow-up on the same version.
The earlier |
|
No new findings.
|
Resolve src/recall.ts and src/tags.ts; drop the unused imports, variable and tagsList parameter the merged code brought in.
jeff-r2026
requested changes
Sep 26, 2026
jeff-r2026
left a comment
Collaborator
There was a problem hiding this comment.
Please resolve the conflicts.
Resolve src/import-local.ts: keep Tencent#840's English prompt and drop the no-await-in-loop disable comment, as this PR does for the others.
|
No new findings.
|
jeff-r2026
approved these changes
Sep 26, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds oxlint with its default rules and fails CI on any warning, as agreed in #828.
mainhad 145 warnings. This PR fixes all of them without suppression comments and changes no runtime behavior.--dry-runfortags subscribe,tags unsubscribeandroles setis delivered by #837, now merged intomain. This branch first carried #837's commit (224d459), then reverted it (a288564) and renamed the unused parameter to_options(6fbf636). Since #837 merged, those functions readoptionsagain, so the rename is gone andgit diff origin/main...HEADhas no dry-run change. Please squash-merge.mainis merged in througha47bb7ea(#833, #834, #835, #837, #840). The code it brought had 5 new warnings and 1 new disable comment, fixed in the merge commits (row below).CI job lint-and-test (ci.yml and .coding-ci.yaml) npm ci + npm run lint # oxlint --deny-warnings npx tsc --noEmit npx vitest run --coverageWarnings after each commit, counted with
npx oxlintat that commit, on the stack that still carried #837's commit:fix(tags,roles)(#837)mainhas 145; this commit fixes 2chore(lint)oxlintdevDependency,lintscript,.oxlintrc.json(defaults plusignoreRestSiblings, so the rest-omit indashboard.tskeepsconfigandrootsout of/api/workspaces)style(lint)oxlint --fix: redundant regex escapes,...(x ?? {})→...x, anchored regex →startsWith/endsWithrefactor(lint)--fix-suggestions, reviewed by hand; every removed whole import has no side effects)refactor(lint)optionson read-onlytagsList/rolesList/generateDigest, the never-readinteractiveoption ofimportFromRepo, the emptytest/e2e.mjs, a try/catch that only rethrewtest(lint)refactor(lint)\p{Cc}refactor(lint)eslint-disablecomments for rules this repo never ran (no-await-in-loop,@typescript-eslint/no-explicit-any), found by the flag belowci(lint)--deny-warnings --report-unused-disable-directives, both CI files, andnpm run lintinCLAUDE.md,AGENTS.md,CONTRIBUTING.mdand the PR templateRevert+refactor(lint)_optionsdocs(contributing),docs(agents)npm run lintneeds, inCONTRIBUTING.md,AGENTS.mdandCLAUDE.md(see Review notes)origin/main(8eb4c8b, 3f76815)recall.ts,tags.ts,import-local.ts. New hits intags.ts: unusedpath,YAML,readFileSafeimports, unusedtotalRules, andoptionson read-onlytagsList(its 4 test calls drop{}); ano-await-in-loopdisable comment inimport-local.tsThe repo ends with zero disable comments.
--report-unused-disable-directivesmakes a suppression fail CI once it no longer suppresses anything, so none can outlive the code it was written for.Each
no-unused-varshit was checked against its callers and git history before deletion, to tell dead code from missing wiring. Only the--dry-runbug turned up (#837). The other issues found along the way are tracked in #836, together with the next rule sets to evaluate, starting with anti-slop.Test fixes worth a look:
contribute"handles dry-run mode" asserted nothing. It now checks that the run leaves the repo/HOME tree unchanged.expect(result).not.toThrow;on a string was a no-op, and is removed.(x?.y as T).zcasts would throw aTypeErrorinstead of failing the assertion. They now keepundefinedin the type.Evidence
npx oxlintonmainat7c834ce4gives 145 warnings and exit 0, so nothing enforces them.After:
npm run lint→oxlint --deny-warnings --report-unused-disable-directivesgives 0 warnings and exit 0. Each throwaway probe file gives exit 1:npx tsc --noEmitis clean,npm run buildsucceeds, andnpx vitest rungives 5122 passed, 1 skipped (329 files) after mergingmain....(x ?? {})→...x(spreadingundefinedis a no-op), redundant regex escapes, anchored regex →startsWith/endsWith,new Array(n)→Array.from, a rethrow-only try/catch,resolveBaseDir(localConfig)→ thebaseDirconst computed from it at the top ofbuildRemovalPlan, and the\p{Cc}rewrites below. None changes output.\p{Cc}rewrites were compared with the old classes on every code point from U+0000 to U+10FFFF.manifest-schemaandagent-formatmatch exactly, and thecontribute-checknormalization pipeline gives identical output. Only the test assertion is stricter.contributedry-run assertion fails when the dry-run early return is removed:npm run build, isolatedHOME, local team repo). These are the commands whose code or signatures changed:main's code) and the_optionsrename;teamai tags subscribe haion the rebuiltdist/reachestagsSubscribe(it stops at the uninitialized-HOME check, as onmain).After merging
main,teamai tags listandteamai tags subscribe hai --dry-runon the rebuiltdist/reachrequireInitand stop atteamai is not initialized, as onmain.I did not run
digestagainst a real team repo: the sandbox here doesn't allow creating a git repo outside the worktree. Its only change is dropping an unused parameter, andtscchecks the call site.Review notes
^20.19.0 || >=22.12.0(P2): kept on purpose. oxlint is a devDependency only, so it never reaches users who installteamai-cli, and the runtime minimum stays Node ≥ 20. CI'snode-version: 20resolves to the latest 20.x, which satisfies it..github/CONTRIBUTING.mdsaysnpm run lintneeds Node ^20.19 or >=22.12 while the CLI still supports Node 20, and the toolchain line inAGENTS.mdandCLAUDE.mdnow says the same. The Node 20+ mentions inskill-data/setup/are for end users installing the CLI and stay as they are.Merge Danger
Door: two-way
Blast Radius: contributors
Runtime behavior is unchanged. Every PR opened after this one must pass
npm run lint. The warning text says what to change, andnpm run lint -- --fixhandles most mechanical cases. oxlint is pinned exactly, so a new default rule arrives only through a deliberate version bump. Reverting is a single revert.