ccfb08f4d5
Follow-up to #20, which was merged before this landed. bot-agents has no `package.json` `imports` aliases (`src/` is flat and everything imports relatively), so no code changes. This records the new rule in the docs: - `.agents/memory/imports-aliases-barrels.md`: aliases may target only a direct subfolder of `src/` (its `index.ts` or a `#x/*` pattern); nothing outside `src/`, not `src/` itself, not deeper folders; such code imports relatively. - `.agents/memory/tests-layout-vitest.md`: `tests/` reach the public entry through a relative import, not a `#plugin` alias. - `.agents/skills/migrate-deno-repo/SKILL.md` and `AGENTS.md`: same rule. `vp check`, `vp test`, and `damem doctor` pass. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Reviewed-on: #21 Reviewed-by: bot <noreply@capsulizers.com> Co-authored-by: Danny Kim <temeddix@gmail.com> Co-committed-by: Danny Kim <temeddix@gmail.com>
2.5 KiB
2.5 KiB
description
| description |
|---|
| scripts/project-lint.ts is the repo-local plugin "project" holding the repo's rule list (typed DummyRuleMap) and repo-only rules; never published, no tests |
Every repo has scripts/project-lint.ts, copied from
cunarist/eslint-plugin-explicit-types and extended. It is a repo-local
Oxlint plugin with meta.name "project", loaded through jsPlugins in
vite.config.ts. It holds:
configs.project.rules: the repo's whole rule list beyond the published plugin configs: Deno parity rules, extras, per-rule options, and opt-outs, built-in Oxlint ids included (curly,id-match,import/no-cycle, ...).- Custom rules, enabled as
project/<rule>. Every repo hasno-disable-commentsandno-asset-imports; bot-agents has no others.
scripts/ stays flat; don't add scripts/rules/. If the plugin ever needs
more files, they sit flat beside it and share the prefix
(project-lint-modules.ts, ...); scripts/project-lint.ts keeps the plugin
object and the rule list.
import type { DummyRuleMap } from "vite-plus/lint";
const rules: DummyRuleMap = {
"id-match": ["error", "^_*[^_]*_*$|^[^a-z]*$", {/* ... */}],
curly: "error",
"project/no-disable-comments": "error",
};
const plugin = {
meta: { name: "project" },
rules: { "no-disable-comments": noDisableCommentsRule /* ... */ },
configs: { project: { rules } },
};
export default plugin;
Why DummyRuleMap and an unannotated plugin (decided 2026-10-15)
DummyRuleMap(re-exported byvite-plus/lint) is Oxlint's type forOxlintConfig.rules. Despite the name it lists every built-in rule with its options, so a typo in a rule id or option is a type error, not just a CI failure. Without it, TypeScript widens"error"tostring;as constdoesn't help because Oxlint wants mutable tuples.@eslint/core'sPluginis too loose to read back:configsis optional, any key may be missing, and a config may be an array, soprojectLint.configs.project.rulesfails invite.config.ts(and!is banned). Optional chaining still leaves the array case.- Oxlint's own
Plugintype (vite-plus/lint/plugins) has noconfigs. - Two hand-written interfaces worked but were dropped as noise; a plain config object was rejected because custom rules need the plugin form anyway and every repo should look the same.
scripts/ is tooling, not production code: never packed or published, and
no tests. Narrow overrides for scripts/** are allowed when a script truly
needs one (e.g. no-console); see lint-overrides-policy.