@alexgorbatchev/typescript-ai-policy

中文文档
15.0.0发布于 2026/11/07TypeScriptES Module构建来源已验证近 30 天下载 2565

Shared TypeScript AI policy configs and Oxlint rules

原始使用文档
文档目录11 节
  1. Who this is for
  2. What you get
  3. Install
  4. Quick start
  5. What it enforces
  6. Lint-disable comments are not a valid repair strategy
  7. Storybook is the React component contract
  8. Expected layout shape
  9. CLI tooling
  10. Learn more
  11. Local package setup

@alexgorbatchev/typescript-ai-policy

Shared Oxfmt and Oxlint config for teams that want AI-assisted TypeScript to stay strict, predictable, and reviewable.

This package is opinionated on purpose. It does not try to be a flexible style preset. It encodes repository contracts as lint rules so generated and modified code lands in a shape you can actually trust.

Who this is for

Use this package if you want to:

  • enforce stricter structure on AI-generated or AI-modified TypeScript
  • replace hand-wavy coding guidance with machine-checkable rules
  • keep React, tests, fixtures, and type boundaries deterministic
  • ship one shared policy pack across repositories

If you want a loose collection of optional style rules, this package is the wrong tool.

What you get

  • shared Oxfmt config
  • shared Oxlint config
  • custom @alexgorbatchev/* rules aimed at common LLM failure modes
  • diagnostics written as direct repair instructions
  • the typescript-ai-policy CLI with fix-semantic and guidance commands

Upstream Oxlint, TypeScript, and Jest rules stay enabled as baseline correctness guardrails.

Install

bun add -d @alexgorbatchev/typescript-ai-policy oxfmt oxlint

If you want to use the typescript-ai-policy fix-semantic command, install its optional peer dependencies:

bun add -d typescript@npm:@typescript/typescript6@latest @typescript/native@npm:typescript@latest

The typescript alias provides the TypeScript 6 compiler API used by semantic fixes. The @typescript/native alias provides the TypeScript 7 compiler and LSP backend. Help, check, and guidance work without either compiler.

The published package ships compiled .js runtime files plus .d.ts declarations. The installed typescript-ai-policy CLI runs through Bun, so Bun is required to execute the package-installed bin. The fix-semantic command still expects its optional peer dependencies to be installed in the consuming project, while guidance only reads the published policy metadata.

Quick start

oxfmt.config.ts

import createOxfmtConfig from "@alexgorbatchev/typescript-ai-policy/oxfmt-config";

export default createOxfmtConfig(() => ({
  ignorePatterns: ["vendor/**"],
}));

oxlint.config.ts

import createOxlintConfig from "@alexgorbatchev/typescript-ai-policy/oxlint-config";

export default createOxlintConfig({
  ignorePatterns: ["coverage"],
  rules: {
    "no-var": "error",
  },
});

Both config entrypoints export factory functions. createOxlintConfig(...) accepts either a config object or a callback that returns one. The returned user config is deep-merged before the shared defaults, so the shared policy still wins on conflicting keys.

For Oxlint specifically, consumer configs are extension-only. If the provided config tries to redefine a shared rule, the factory throws instead of letting repositories silently weaken the policy downstream.

createOxlintConfig also exports FilenameStyle as a named export from @alexgorbatchev/typescript-ai-policy/oxlint-config. createOxlintConfig reserves the filenameStyle key for this package's shared filename policy. It defaults to FilenameStyle.PascalCase, which enforces ComponentName.tsx and useThing.ts{,x} ownership files. Set filenameStyle: FilenameStyle.DashCase to enforce component-name.tsx and use-thing.ts{,x} instead:

import createOxlintConfig, { FilenameStyle } from "@alexgorbatchev/typescript-ai-policy/oxlint-config";

export default createOxlintConfig({
  filenameStyle: FilenameStyle.DashCase,
  ignorePatterns: ["coverage"],
});

When you run Oxlint manually, use Bun to launch the CLI:

bun --bun oxlint .

Treat bun --bun oxlint ... as the canonical invocation form for this package and for consumer repositories using these TypeScript config entrypoints.

What it enforces

At a glance, the shared policy enforces:

  • baseline guardrails such as strict equality, no any, and complete React Hook dependency lists (react/exhaustive-deps as an error)
  • component ownership files that export exactly one main component or one multipart component family, plus type-only secondary API, and live under canonical components/, templates/, or layouts/ directories using ComponentName.tsx by default or component-name.tsx when filenameStyle: FilenameStyle.DashCase is configured
  • hook ownership files that export exactly one main use* hook, plus type-only secondary API, and live as direct-child hooks/useThing.ts[x] files by default or hooks/use-thing.ts[x] when filenameStyle: FilenameStyle.DashCase is configured
  • hook-owned .tsx files use hook contracts and matching tests instead of component naming, test-id, or Storybook ownership requirements; shared raw-JSX and direct-styling boundaries still apply
  • JSX-only React component code instead of React.createElement(...)
  • matching Storybook files for component ownership files under sibling stories/ directories, with story support files limited to helpers.ts[x], fixtures.ts[x], or fixtures/
  • Storybook project support .tsx files under direct or nested .storybook/ paths without treating them as component ownership files
  • matching test files for hook ownership files under sibling __tests__/ directories, preserving the source basename and extension (.ts hooks require .test.ts; .tsx hooks require .test.tsx), with test support files limited to helpers.ts[x], fixtures.ts[x], or fixtures/
  • typed Storybook meta with package-relative titles, typed story exports, and required play functions
  • deterministic component test ids such as ComponentName and ComponentName--child, plus required root test ids for exported ownership components
  • canonical component ownership directories (components/, templates/, layouts/) as the only product .tsx surface allowed to render raw intrinsic JSX or pass direct className / style props, with file-role carve-outs for story/test support and Storybook .storybook/ support files
  • strict boundaries between runtime code, test code, story code, and fixture code, including no imports from __tests__/ into runtime code and no imports of declared types from constants.ts; erased named imports used exclusively in typeof value queries are allowed
  • test-file discipline: no skipped or focused tests, no conditional logic, no throw, no module mocking, no test-file exports, and no inline fixture bindings
  • fixture discipline: canonical location, single entrypoint, constrained export naming and export types, no local type declarations, and canonical fixture import paths
  • explicit type/value ownership rules for files such as index.ts, constants.ts, and types.ts
  • strict type and function-contract rules: I* interfaces only, no I* type aliases, no direct interface-to-type passthrough aliases, no trivial property-selector forwarding wrappers whose names merely restate the selected property, no inline type imports or inline structural type expressions, and indented multiline template literals
  • a policy stance that inline lint-disable comments are not an acceptable escape hatch for fixing violations

Lint-disable comments are not a valid repair strategy

Agents and developers are expected to satisfy the shared policy directly, not suppress it locally with comments such as // oxlint-disable-next-line or /* oxlint-disable */.

This package explicitly bans inline lint-disable comments for both ESLint and Oxlint. Treat this as a hard policy signal, not as an obstacle to bypass. The enforcement strategy assumes you will fix the underlying contract violation rather than suppressing the warning.

The important contract is simple:

  • do not use inline lint-disable comments to get around the shared policy
  • fix the code so it satisfies the rule set instead
  • if the policy itself is wrong, change the shared package deliberately rather than bypassing it locally

Storybook is the React component contract

For React components, this policy is intentionally story-first.

Every component ownership file must have a matching Storybook file, every story meta must be typed and use a package-relative title, and every exported story must be typed and include a play function unless !test removes the built-in Storybook test tag for that story. In practice, that makes Storybook the canonical artifact for component behavior:

  • the same story layer can back CI interaction coverage
  • the same stories also act as the human visual reference for the component
  • component structure and component verification stay in one place instead of drifting across separate ad-hoc test files

A main.tsx outside component ownership directories is a React client entrypoint when it has no exports or local component declarations and directly renders JSX through an imported react-dom/client createRoot call (chained or assigned to a local root). Such bootstraps do not require a component export, ownership directory, or story. All other policy checks still apply; the filename alone does not qualify a file as an entrypoint.

This package does not wire your CI for you, but it does enforce the repository shape required for Storybook-driven component verification.

Expected layout shape

The policy enforces canonical role directories inside your feature tree.

That means repositories can choose their feature boundaries, but component, story, hook, and test files still have fixed ownership locations:

  • component ownership .tsx files live under components/, templates/, or layouts/
  • nested subdirectories inside those component ownership areas are allowed but not required
  • non-story, non-test .tsx files must not render raw intrinsic JSX such as <div>, <span>, or <p> unless the file lives inside one of those canonical component ownership areas
  • direct className and style props are only allowed on raw HTML elements in files inside those canonical component ownership areas. Custom/capitalized components must not accept className or style props in any file.
  • Storybook project support .tsx files under .storybook/*.tsx and .storybook/**/*.tsx are not component ownership files and may use local Storybook wrapper markup
  • story files live under sibling stories/ directories, and that area is reserved for *.stories.tsx, helpers.ts[x], fixtures.ts[x], and fixtures/
  • exported runtime hooks whose names start with use live under direct-child hooks/ ownership files
  • test files live under sibling __tests__/ directories, and that area is reserved for *.test.ts[x], helpers.ts[x], fixtures.ts[x], and fixtures/
  • fixture declarations live in fixtures.ts[x] under stories/ or __tests__/; a directory entrypoint uses a pure fixtures/index.ts barrel with unaliased named exports or bare wildcards from its own nested fixtures.ts[x] declaration files
  • extensionless fixture barrel sources require a matching .ts or .tsx declaration file; directory barrel hops are not declaration ownership
  • direct relative fixture re-exports from runtime barrels, helpers, or another fixture area are rejected for both named and wildcard syntax; the check does not resolve package aliases or transitive module graphs
  • component filenames match the exported PascalCase component name in ComponentName.tsx form by default, or component-name.tsx when filenameStyle: FilenameStyle.DashCase is configured
  • hook filenames match the exported use* hook name in useThing.ts[x] form by default, or use-thing.ts[x] when filenameStyle: FilenameStyle.DashCase is configured
  • index.ts is reserved for pure barrel re-exports only
  • constants.ts is for runtime values only
  • types.ts is for type-only exports only

Example:

feature/
├── components/
│   ├── AccountPanel.tsx
│   └── stories/
│       └── AccountPanel.stories.tsx
└── hooks/
    ├── useAccount.ts
    └── __tests__/
        └── useAccount.test.ts

Minimal config:

import createOxlintConfig from "@alexgorbatchev/typescript-ai-policy/oxlint-config";

export default createOxlintConfig();

With that config in place, routes, pages, feature views, and other product .tsx files must render imported components instead of raw DOM tags, and they must not pass direct className or style props. Raw intrinsic JSX and direct styling props stay on raw HTML elements inside canonical component ownership areas, story/test support files, or Storybook .storybook/ support files. Passing className or style props to custom components is banned everywhere.

In a consuming repository, use typescript-ai-policy check through your package manager's local binary runner to execute the shared formatter and linter checks against that repo.

When a consuming harness supports environment injection, configure that harness to run shell commands with AGENT=1 so typescript-ai-policy check emits agent-formatted oxlint output automatically for agent workflows and more token-efficient lint output.

CLI tooling

The package includes the typescript-ai-policy CLI. Its fix-semantic command is backed by tsc --lsp --stdio, and its guidance command prints authoritative repair guidance for the local @alexgorbatchev/* rules as a wrapped Markdown bullet list with bold rule names or as JSON.

Package-installed usage:

  • bun run typescript-ai-policy -- check — run the package formatter and linter checks in the consuming repository. When the consuming harness is configured to inject AGENT=1, the oxlint step uses agent formatting automatically for agent workflows and more token-efficient output.
  • bun run typescript-ai-policy -- guidance — print the published rule guidance that the package exposes for AI agents as a wrapped Markdown bullet list with bold rule names.
  • bun run typescript-ai-policy -- guidance --json — print the same published rule guidance as JSON objects with ruleName and resolved guidance fields.
  • bun run typescript-ai-policy -- fix-semantic <target-directory> — run Oxlint with this package's policy config, collect supported diagnostics, and apply semantic fixes to the target directory.
  • bun run typescript-ai-policy -- fix-semantic <target-directory> --dry-run — print the planned semantic-fix scope without mutating files.

The published guidance output is package-level repair guidance, not a repository-specific config dump. Agents should still inspect the consuming repository's actual oxlint.config.ts before applying file-specific guidance in another codebase.

Repository development commands are documented in AGENTS.md.

Today the framework applies three conservative semantic fixes:

  • @alexgorbatchev/interface-naming-convention — rename repository-owned interfaces to their required I* form when the existing name can be normalized safely.
  • @alexgorbatchev/no-i-prefixed-type-aliases — rename repository-owned type aliases to drop the interface-style I* prefix when the diagnostic resolves to a concrete type alias name safely.
  • @alexgorbatchev/test-file-location-convention — move misplaced .test.ts / .test.tsx files into a sibling __tests__/ directory as __tests__/basename.test.ts[x] and rewrite the moved file's relative imports.

The command and backend shape remain intentionally generic so more rule-backed semantic operations can be added later.

Learn more

  • src/oxlint/README.md — full rule catalog, rationale, and examples
  • AGENTS.md — repository guidance for coding agents working on this package

Local package setup

This repository also consumes its own shared configs at the root:

  • oxfmt.config.ts
  • oxlint.config.ts

版本与发布记录

@alexgorbatchev/typescript-ai-policy 共发布 39 个版本,首次发布于 2026/04/04;过去 12 个月发布了 39 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
15.0.0latest2026/11/071 天前
14.0.42026/11/071 天前
14.0.32026/10/308 天前
14.0.22026/10/309 天前
14.0.12026/10/2514 天前
14.0.02026/10/2018 天前

关于 @alexgorbatchev/typescript-ai-policy 的常见问题

@alexgorbatchev/typescript-ai-policy 是什么?

Shared TypeScript AI policy configs and Oxlint rules

如何安装 @alexgorbatchev/typescript-ai-policy?

在项目目录运行 npm install @alexgorbatchev/typescript-ai-policy,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:oxfmt(>=0.49.0 <1.0.0)、oxlint(^1.64.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。它还提供命令行工具 typescript-ai-policy,可以用 npx typescript-ai-policy 直接运行。

@alexgorbatchev/typescript-ai-policy 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@alexgorbatchev/typescript-ai-policy 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@alexgorbatchev/typescript-ai-policy 可以商用吗?

@alexgorbatchev/typescript-ai-policy 使用 未声明 许可。package.json 没有声明许可证。没有许可证的代码默认保留全部权利,商用前请联系作者或查看仓库中的 LICENSE 文件。以上为概括,不构成法律意见,请以许可原文为准。

@alexgorbatchev/typescript-ai-policy 的下载量有多少?

根据 npm 官方下载统计,@alexgorbatchev/typescript-ai-policy 在 2026/10/06 – 2026/11/04 这 30 天内被下载 2,565 次,日均约 86 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@alexgorbatchev/typescript-ai-policy 还在维护吗?

最新版本 15.0.0 发布于 2026/11/07(1 天前);至今共发布 39 个版本,其中过去 12 个月发布了 39 个;首次发布于 2026/04/04。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。