Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0920a4e91b | |||
| 627458fb5f | |||
| 50df193a8c | |||
| 5b568f9ea6 |
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
description: bot-agents migration decisions: live @main action for six repos, JSON profiles, Node 24.2+, Deno kept only for agents, no @cunarist plugins needed
|
description: bot-agents migration decisions: live @main action for six repos, JSON profiles, Node 24.2+, Deno kept only for agents, no eslint-plugin-* packages needed
|
||||||
---
|
---
|
||||||
|
|
||||||
Decisions for `commons/bot-agents` (Capsulizers Gitea), from the Deno to
|
Decisions for `commons/bot-agents` (Capsulizers Gitea), from the Deno to
|
||||||
@@ -22,10 +22,13 @@ Node + Vite+ migration (PR #20, `node-migration`, 2026-10-15/16):
|
|||||||
because the agents still check Deno-based consumer repos (memona,
|
because the agents still check Deno-based consumer repos (memona,
|
||||||
memona-home). Remove it once those repos have moved; it is not a
|
memona-home). Remove it once those repos have moved; it is not a
|
||||||
dependency of this repo's TypeScript.
|
dependency of this repo's TypeScript.
|
||||||
- **No `@cunarist/eslint-plugin-*`.** The Deno setup enabled no plugin, so
|
- **No `eslint-plugin-*` packages** (`eslint-plugin-explicit-types`,
|
||||||
this repo depends on none and CI passes without them being published.
|
`eslint-plugin-import-structure`, `eslint-plugin-lit-robust`; unscoped
|
||||||
Planned (2026-10-17): once the plugins are on npm, add
|
since 2026-10-18, formerly `@cunarist/...`). The Deno setup enabled no
|
||||||
`@cunarist/eslint-plugin-modules` here for its import checks.
|
plugin, so this repo depends on none and CI passes without them being
|
||||||
|
published. Planned (2026-10-17): once the plugins are on npm, add
|
||||||
|
`eslint-plugin-import-structure` (rule prefix `import-structure/`) here for
|
||||||
|
its import checks.
|
||||||
- **Stricter input checks were accepted** in the migration: Gitea `/user` and
|
- **Stricter input checks were accepted** in the migration: Gitea `/user` and
|
||||||
comment responses, the runtime manifest, and the outcome's profile type are
|
comment responses, the runtime manifest, and the outcome's profile type are
|
||||||
validated; some type errors became `TypeError` with the same messages.
|
validated; some type errors became `TypeError` with the same messages.
|
||||||
|
|||||||
@@ -11,23 +11,25 @@ unbuilt. `vp pack` inlines them, so they never reach package consumers.
|
|||||||
|
|
||||||
One rule for every file, never tied to folder or file names (user rule
|
One rule for every file, never tied to folder or file names (user rule
|
||||||
2026-10-17; it replaces the earlier "aliases only point at direct `src/`
|
2026-10-17; it replaces the earlier "aliases only point at direct `src/`
|
||||||
subfolders" rule as the general rule, and the "modules plugin checks only
|
subfolders" rule as the general rule, and the "import-structure plugin
|
||||||
aliased folders" scope; this repo keeps the stricter rule as a local
|
checks only aliased folders" scope; this repo keeps the stricter rule as a
|
||||||
convention, see the last section):
|
local convention, see the last section):
|
||||||
|
|
||||||
- **An alias may point anywhere** and owns its target. An alias to a
|
- **An alias may point anywhere** and owns its target. An alias to a
|
||||||
folder's `index.ts` owns that folder and everything below it; an alias to
|
folder's `index.ts` owns that folder and everything below it; an alias to
|
||||||
any other file owns only that file.
|
any other file owns only that file.
|
||||||
- **No overlap.** No file may be owned by 2 aliases: no alias inside another
|
- **No overlap.** No file may be owned by 2 aliases: no alias inside another
|
||||||
alias's area, and no 2 aliases with the same target. The modules plugin's
|
alias's area, and no 2 aliases with the same target. The import-structure
|
||||||
`enforce-layer-order` reports it once at the top of every file 2 aliases
|
plugin's `enforce-layer-order` reports it once at the top of every file 2
|
||||||
claim. Fix by merging the aliases or moving files apart.
|
aliases claim. Fix by merging the aliases or moving files apart.
|
||||||
- **Outside an area, only the exact alias reaches it.** A deeper alias
|
- **Outside an area, only the exact alias reaches it.** A deeper alias
|
||||||
specifier (`#a/one.ts`, `no-barrel-bypass`) and a relative path into the
|
specifier (`#a/one.ts`, `no-barrel-bypass`) and a relative path into the
|
||||||
area (`./a/one.ts`, `no-relative-bypass`; `./b/f.ts` to a file alias,
|
area (`./a/one.ts`, `no-relative-bypass`; `./b/f.ts` to a file alias,
|
||||||
`prefer-alias-import`, fixed to the alias) are bypasses.
|
`prefer-alias-import`, fixed to the alias) are bypasses.
|
||||||
- **Inside an area, relative imports of siblings and subfolders are free.**
|
- **Inside an area, relative imports of siblings and subfolders are free.**
|
||||||
- **`../` is banned in every file**, owned or not (`no-parent-import`).
|
- **A `../` import is banned in every file**, owned or not (`no-parent-import`).
|
||||||
|
Runtime file URLs (`new URL("../prompt.md", import.meta.url)`) are not
|
||||||
|
imports and are allowed.
|
||||||
Anything above a file needs an alias.
|
Anything above a file needs an alias.
|
||||||
- **Files no alias owns** need no `index.ts` and no alias, and import `./`
|
- **Files no alias owns** need no `index.ts` and no alias, and import `./`
|
||||||
siblings and subfolders freely.
|
siblings and subfolders freely.
|
||||||
@@ -89,8 +91,8 @@ Relative imports are written with the `.ts` extension.
|
|||||||
## Local convention: aliases target direct `src/` subfolders
|
## Local convention: aliases target direct `src/` subfolders
|
||||||
|
|
||||||
This is a convention of this repo only, stricter than the general rule above
|
This is a convention of this repo only, stricter than the general rule above
|
||||||
(which the published modules plugin checks and which allows more). It is not
|
(which the published import-structure plugin checks and which allows more).
|
||||||
a plugin rule.
|
It is not a plugin rule.
|
||||||
|
|
||||||
- Every `package.json` `imports` alias points only at the `index.ts` of a
|
- Every `package.json` `imports` alias points only at the `index.ts` of a
|
||||||
direct subfolder of `src/`, e.g. `"#helpers": "./src/helpers/index.ts"`.
|
direct subfolder of `src/`, e.g. `"#helpers": "./src/helpers/index.ts"`.
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ turn on whole categories, then list only what parity or a real need adds.
|
|||||||
```ts
|
```ts
|
||||||
lint: {
|
lint: {
|
||||||
plugins: ["typescript", "unicorn", "oxc", "import"],
|
plugins: ["typescript", "unicorn", "oxc", "import"],
|
||||||
jsPlugins: ["@cunarist/eslint-plugin-explicit-types", "./scripts/project-lint.ts"],
|
jsPlugins: ["eslint-plugin-explicit-types", "./scripts/project-lint.ts"],
|
||||||
categories: { correctness: "error", suspicious: "error", pedantic: "error", perf: "error" },
|
categories: { correctness: "error", suspicious: "error", pedantic: "error", perf: "error" },
|
||||||
rules: { ...explicitTypes.configs.concrete.rules, ...projectLint.configs.project.rules },
|
rules: { ...explicitTypes.configs.concrete.rules, ...projectLint.configs.project.rules },
|
||||||
ignorePatterns: ["src/generated/**"], // generated files only, see below
|
ignorePatterns: ["src/generated/**"], // generated files only, see below
|
||||||
@@ -40,8 +40,8 @@ lint: {
|
|||||||
Hand-written code is never ignored.
|
Hand-written code is never ignored.
|
||||||
- **No lint disable comments**: [[lint-no-disable-comments]].
|
- **No lint disable comments**: [[lint-no-disable-comments]].
|
||||||
- **Parity:** [[lint-parity-never-shrinks]]. **Naming:** [[naming-id-match]].
|
- **Parity:** [[lint-parity-never-shrinks]]. **Naming:** [[naming-id-match]].
|
||||||
- Don't add a second import sorter; the modules plugin's `enforce-import-order` is
|
- Don't add a second import sorter; the import-structure plugin's
|
||||||
the only one, and Oxfmt's `sortImports` stays off.
|
`enforce-import-order` is the only one, and Oxfmt's `sortImports` stays off.
|
||||||
|
|
||||||
`perf` came last: in the template it flagged nine `.includes` on constant
|
`perf` came last: in the template it flagged nine `.includes` on constant
|
||||||
arrays, fixed as `ReadonlySet` + `.has()` rather than by turning a rule off.
|
arrays, fixed as `ReadonlySet` + `.has()` rather than by turning a rule off.
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ Oxfmt's standard `package.json` sorting is accepted: there is no
|
|||||||
replaces the earlier hand-written order (metadata, `scripts`, `exports`,
|
replaces the earlier hand-written order (metadata, `scripts`, `exports`,
|
||||||
`imports`, `devDependencies`, `dependencies`).
|
`imports`, `devDependencies`, `dependencies`).
|
||||||
|
|
||||||
The `imports` key order can carry meaning: the modules plugin's
|
The `imports` key order can carry meaning: the import-structure plugin's
|
||||||
`enforce-layer-order` reads it as the layer order. Never reorder it casually.
|
`enforce-layer-order` reads it as the layer order. Never reorder it casually.
|
||||||
|
|
||||||
## Fields
|
## Fields
|
||||||
@@ -23,7 +23,7 @@ The `imports` key order can carry meaning: the modules plugin's
|
|||||||
- **No `peerDependencies`, ever** (user preference, 2026-10-14). If something
|
- **No `peerDependencies`, ever** (user preference, 2026-10-14). If something
|
||||||
is needed at runtime, it goes in `dependencies`.
|
is needed at runtime, it goes in `dependencies`.
|
||||||
- **`dependencies`** = what runs or is type-referenced at runtime by consumers
|
- **`dependencies`** = what runs or is type-referenced at runtime by consumers
|
||||||
(the lit plugin ships `parse5`, `oxc-parser`, `oxc-resolver`, and
|
(the lit-robust plugin ships `parse5`, `oxc-parser`, `oxc-resolver`, and
|
||||||
`@eslint/core` for its public types; they stay external, never bundled).
|
`@eslint/core` for its public types; they stay external, never bundled).
|
||||||
- **`devDependencies`** = everything else: `vite-plus`, `eslint`,
|
- **`devDependencies`** = everything else: `vite-plus`, `eslint`,
|
||||||
`@typescript-eslint/parser`, `eslint-doc-generator`, `esbuild`,
|
`@typescript-eslint/parser`, `eslint-doc-generator`, `esbuild`,
|
||||||
|
|||||||
@@ -6,16 +6,17 @@ The user's rule, from the Deno days and restated for Node (2026-10-12): "No
|
|||||||
JS, not even JSX/TSX, only TS." Source, scripts, tests, and configs are all
|
JS, not even JSX/TSX, only TS." Source, scripts, tests, and configs are all
|
||||||
plain `.ts`. Build output in a gitignored folder is the only JS.
|
plain `.ts`. Build output in a gitignored folder is the only JS.
|
||||||
|
|
||||||
`tsconfig.json`: no `allowJs`, no `jsx`, and exactly this strictness set
|
`tsconfig.json`: no `allowJs`, no `jsx`, and exactly this strictness set (user
|
||||||
(user decision, 2026-10-18): `strict` (written out), `noUncheckedIndexedAccess`,
|
decision, 2026-10-18): `strict` (written out), `noUncheckedIndexedAccess`,
|
||||||
`noPropertyAccessFromIndexSignature`, `noImplicitReturns`, `noUnusedLocals`,
|
`noPropertyAccessFromIndexSignature`, `noImplicitReturns`, `noUnusedLocals`,
|
||||||
`noUnusedParameters`, `noImplicitOverride`, `noFallthroughCasesInSwitch`,
|
`noUnusedParameters`, `noImplicitOverride`, `noFallthroughCasesInSwitch`,
|
||||||
`erasableSyntaxOnly`, plus the mechanical `verbatimModuleSyntax`,
|
`erasableSyntaxOnly`, and `allowUnreachableCode: false` plus
|
||||||
`allowImportingTsExtensions`, and `noEmit` (packages also keep `declaration`
|
`allowUnusedLabels: false` (user decision, 2026-10-18; on in the Deno setup),
|
||||||
and `isolatedDeclarations`). `exactOptionalPropertyTypes` is off everywhere:
|
plus the mechanical `verbatimModuleSyntax`, `allowImportingTsExtensions`, and
|
||||||
write `{ key: maybeUndefined }` rather than leaving the key out to please it.
|
`noEmit` (packages also keep `declaration` and `isolatedDeclarations`).
|
||||||
If a tool or framework seems to need a JS or TSX file, stop and flag it
|
`exactOptionalPropertyTypes` is off everywhere: write `{ key: maybeUndefined }`
|
||||||
instead of adding one.
|
rather than leaving the key out to please it. If a tool or framework seems to
|
||||||
|
need a JS or TSX file, stop and flag it instead of adding one.
|
||||||
|
|
||||||
## No asset imports (2026-10-14, widened 2026-10-16 and 2026-10-17)
|
## No asset imports (2026-10-14, widened 2026-10-16 and 2026-10-17)
|
||||||
|
|
||||||
|
|||||||
@@ -29,16 +29,17 @@ below it; an alias to any other file owns only that file. No overlap: no file
|
|||||||
may be owned by 2 aliases, so no alias inside another alias's area and no 2
|
may be owned by 2 aliases, so no alias inside another alias's area and no 2
|
||||||
aliases with the same target. Outside an area, only the exact alias reaches
|
aliases with the same target. Outside an area, only the exact alias reaches
|
||||||
it; a deeper alias specifier or a relative path into the area is a bypass.
|
it; a deeper alias specifier or a relative path into the area is a bypass.
|
||||||
Inside an area, relative imports of siblings and subfolders are free. `../`
|
Inside an area, relative imports of siblings and subfolders are free. A `../`
|
||||||
is banned in every file, owned or not
|
import is banned in every file, owned or not
|
||||||
(`import/no-relative-parent-imports`). Files no alias owns need no `index.ts`
|
(`import/no-relative-parent-imports`); runtime file URLs such as
|
||||||
and no alias, and import `./` siblings and subfolders freely. The one alias
|
`new URL("../prompt.md", import.meta.url)` are paths, not imports, and stay.
|
||||||
is `#testing` (`./src/testing/index.ts`): every test imports it by alias, and
|
Files no alias owns need no `index.ts` and no alias, and import `./` siblings
|
||||||
`tests/` reaches `src/` only through it. Local convention, stricter than the
|
and subfolders freely. The one alias is `#testing` (`./src/testing/index.ts`):
|
||||||
general rule above: in this repo, aliases point only at a direct subfolder of
|
tests that use its helpers import it by alias, and `tests/` imports `src/`
|
||||||
`src/` (`"#helpers": "./src/helpers/index.ts"`), and code outside `src/` uses
|
only through it. Local convention, stricter than the general rule above: in
|
||||||
`./` relative imports. `scripts/` is flat: one file per
|
this repo, aliases point only at a direct subfolder of `src/`
|
||||||
tool, no subfolders and no `index.ts`, imported directly by file path
|
(`"#helpers": "./src/helpers/index.ts"`), and code outside `src/` uses `./`
|
||||||
|
relative imports. `scripts/` is flat: one file per tool, no subfolders and no `index.ts`, imported directly by file path
|
||||||
([.agents/memory/imports-aliases-barrels.md](.agents/memory/imports-aliases-barrels.md)).
|
([.agents/memory/imports-aliases-barrels.md](.agents/memory/imports-aliases-barrels.md)).
|
||||||
|
|
||||||
The only config files are `package.json`, `tsconfig.json`, and
|
The only config files are `package.json`, `tsconfig.json`, and
|
||||||
|
|||||||
+3
-1
@@ -15,6 +15,8 @@
|
|||||||
"noImplicitReturns": true,
|
"noImplicitReturns": true,
|
||||||
"noFallthroughCasesInSwitch": true,
|
"noFallthroughCasesInSwitch": true,
|
||||||
"noUnusedLocals": true,
|
"noUnusedLocals": true,
|
||||||
"noUnusedParameters": true
|
"noUnusedParameters": true,
|
||||||
|
"allowUnreachableCode": false,
|
||||||
|
"allowUnusedLabels": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user