@billwgong/contextlint 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 BillW Gong
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,160 @@
1
+ <p align="center"><img src="https://raw.githubusercontent.com/BillWGong/contextlint/main/assets/banner.svg" alt="ContextLint — lint the instructions behind your coding agent" width="100%" /></p>
2
+
3
+ <p align="center">
4
+ <a href="https://github.com/BillWGong/contextlint/actions/workflows/ci.yml"><img src="https://github.com/BillWGong/contextlint/actions/workflows/ci.yml/badge.svg" alt="CI" /></a>
5
+ <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-167d73" alt="MIT license" /></a>
6
+ <img src="https://img.shields.io/badge/Node.js-22%2B-334655" alt="Node.js 22 or newer" />
7
+ <img src="https://img.shields.io/badge/interface-English%20%2F%20中文-167d73" alt="English and Chinese interfaces" />
8
+ </p>
9
+
10
+ <p align="center"><strong>English</strong> · <a href="README.zh-CN.md">简体中文</a></p>
11
+
12
+ # ContextLint
13
+
14
+ **Lint the instructions behind your coding agent.**
15
+
16
+ A local CLI that finds repeated rules, explicit potential conflicts, and broken references in `AGENTS.md`, `CLAUDE.md`, and other coding-agent instruction files. Open an offline report with the original text, file locations, and suggested next steps.
17
+
18
+ No API key. No model calls. No file uploads during scanning.
19
+
20
+ <p align="center"><img src="https://raw.githubusercontent.com/BillWGong/contextlint/main/assets/finding.svg" alt="Illustrated example: competing pnpm and npm instructions, with source lines and a suggested next step" width="100%" /></p>
21
+
22
+ ## Try it
23
+
24
+ Requires **Node.js 22+**. Run it directly in your project:
25
+
26
+ ```bash
27
+ npx @billwgong/contextlint@latest . --html
28
+ ```
29
+
30
+ For a Chinese report, add `--lang zh`. Open the saved HTML path printed by the CLI.
31
+
32
+ Or install the command globally:
33
+
34
+ ```bash
35
+ npm install -g @billwgong/contextlint
36
+ contextlint . --html
37
+ ```
38
+
39
+ To build from source, use pnpm:
40
+
41
+ ```bash
42
+ git clone https://github.com/BillWGong/contextlint.git
43
+ cd contextlint
44
+ pnpm install --frozen-lockfile
45
+ pnpm build
46
+
47
+ # Start with the included example
48
+ node dist/cli.js examples/demo --agent codex --html report.html
49
+ ```
50
+
51
+ Open `report.html` in your browser. Switch between **English** and **简体中文** in the top-right corner, filter findings, or search the original instructions. The file works offline; JavaScript enables filters and language switching.
52
+
53
+ Then point the CLI at your own repository:
54
+
55
+ ```bash
56
+ node dist/cli.js /path/to/your/repo --agent codex --html report.html
57
+ ```
58
+
59
+ Every HTML scan saves a unique file in `<scanned-project>/.contextlint/reports/`. Reports remain after the command exits and are never automatically deleted. The CLI prints an absolute path and a `file://` link. `--html report.html` also writes a convenient copy, creating parent directories when needed; previous scans remain in the history folder. The scanned project must be writable. Output copies replace existing regular files atomically; symbolic-link outputs and history directories are refused. If copying fails, the error includes the retained history path. New histories and copies use owner-only permissions on POSIX. Add `.contextlint/` to your project’s `.gitignore`: reports contain instruction excerpts, not encrypted data. The report title uses the scanned project’s `package.json` name when available, otherwise its directory name.
60
+
61
+ For a terminal report, omit `--html`. Use `--lang en` or `--lang zh` to choose the interface language. The CLI defaults to your locale, then English. Instruction text is always preserved in its original language.
62
+
63
+ ## What you get
64
+
65
+ | Check | Evidence | Suggested next step |
66
+ | --- | --- | --- |
67
+ | Package-manager conflicts | Explicit competing `Use pnpm` / `Use npm` choices | Check the lockfile and clarify the intended tool |
68
+ | Opposite directives | Matching actions with `Always` / `Never`, or supported Chinese equivalents | Keep the intended rule or add missing conditions |
69
+ | Repeated rules | Matching text after limited normalization | Review whether both copies are needed |
70
+ | Broken references | Relative Markdown links with missing local targets | Update, restore, or remove the reference |
71
+
72
+ Every finding includes its original file and line range. The HTML report explains what was matched and offers guidance. It does not edit your files.
73
+
74
+ **Scope matters.** Files for different agents are separated. Package-manager choices can conflict across headings within one file. Other checks keep heading isolation; cross-file headings, parent/child directory rules, and unresolved activation conditions are handled conservatively. A Cursor rule and a Codex rule choosing different tools are not automatically a conflict.
75
+
76
+ ## CLI
77
+
78
+ ```bash
79
+ # Human-readable terminal output
80
+ node dist/cli.js . --agent codex --lang en
81
+
82
+ # Chinese interface and a Chinese-language sample
83
+ node dist/cli.js examples/zh-demo --lang zh --html report-zh.html
84
+
85
+ # Stable machine-readable output
86
+ node dist/cli.js . --json > findings.json
87
+
88
+ # CI: exit 1 if warning findings exist
89
+ node dist/cli.js . --agent codex --strict --json > findings.json
90
+
91
+ # Exclude a literal relative file or directory; repeat as needed
92
+ node dist/cli.js . --exclude fixtures --exclude legacy
93
+ ```
94
+
95
+ | Option | Behavior |
96
+ | --- | --- |
97
+ | `--agent claude\|codex\|cursor\|copilot` | Select instruction sources for one agent |
98
+ | `--html [file.html]` | Save a permanent visual report; optionally write an additional copy |
99
+ | `--lang en\|zh` | Choose CLI and initial report language |
100
+ | `--json` | Emit language-independent JSON with `schemaVersion: "1.0"` |
101
+ | `--strict` | Exit 1 for warnings; otherwise exit 2 if no sources or analysis is limited |
102
+ | `--exclude <path>` | Exclude a literal relative path; no globs |
103
+
104
+ HTML and JSON are separate output modes. Exit codes: **0** completed, **1** strict threshold reached, **2** usage/execution error, or a strict scan with no findings that is incomplete or checked no files. `status` is `complete`, `limited`, or `no-sources`; `complete` refers only to the supported static checks and selected scope. JSON report data goes to stdout; errors go to stderr. JSON field names and diagnostics remain stable English strings regardless of interface language.
105
+
106
+ ## Supported files
107
+
108
+ | Source | Agent classification | Comparison policy |
109
+ | --- | --- | --- |
110
+ | `AGENTS.md` | Codex / Copilot | Directory scope; nested directories stay separate |
111
+ | `CLAUDE.md` | Claude | Directory scope |
112
+ | `.claude/rules/**/*.md` | Claude | File-local comparisons; activation unresolved |
113
+ | `.cursor/rules/**/*.mdc` / `.md` | Cursor | Cross-file only with simple `alwaysApply: true` and no nonempty `globs` |
114
+ | `.github/copilot-instructions.md` | Copilot | Project directory scope |
115
+ | `.github/instructions/**/*.instructions.md` | Copilot | File-local comparisons; activation unresolved |
116
+
117
+ `--agent` selects a static source set. It does not simulate an agent's instruction-loading system. Global instructions, imports, skills, `AGENTS.override.md`, and custom fallback filenames are not scanned in this release.
118
+
119
+ ## Deliberate limits
120
+
121
+ - This is a **static linter**, not a runtime debugger. It cannot prove which instructions an agent loaded or followed.
122
+ - Conflict detection uses a small set of explicit English and Chinese patterns. It does not understand arbitrary natural-language contradictions.
123
+ - Code fences, quoted examples, comments, and recognized conditions are excluded from conflict checks. Markdown and frontmatter parsing are intentionally limited.
124
+ - Different heading paths are not compared across files; within a file, only package-manager choices cross headings. Nested directories remain separate. That avoids some misleading findings and can miss real problems.
125
+ - Local Markdown links are resolved from the instruction file directory, within the scan root. URLs, absolute paths, images, templates, and bare backtick paths are skipped.
126
+ - Token counts are heuristic estimates, not session usage or cost savings. A clean report is not a correctness guarantee.
127
+ - The scanner skips common dependency/build directories and symlinks. It does not apply `.gitignore`; use `--exclude` for additional paths. Files over 1 MiB are skipped. Safety limits: 100,000 visited entries, depth 64, 1,000 instruction files, 8 MiB instruction text, 10,000 candidate rules, 8,192 characters per paragraph, 200,000 candidate conflict comparisons, and 1,000 findings per analyzer. Reaching a limit marks the report `limited`. Explicit exclusions and unsupported symlinks are intentional scope choices. Supported instruction-file symlinks remain visible as limited analysis.
128
+
129
+ See [detection rules](docs/rules.md), [JSON Schema](docs/report.schema.json), and [validation notes](docs/validation.md) for details.
130
+
131
+ ## Development
132
+
133
+ ```bash
134
+ pnpm install --frozen-lockfile
135
+ pnpm test
136
+ pnpm build
137
+ pnpm pack
138
+ ```
139
+
140
+ TypeScript + Node.js, with **zero production dependencies**. The public API exports `lint(root, options)` from `dist/index.js`.
141
+
142
+ ```js
143
+ import { lint } from './dist/index.js';
144
+ const report = await lint('/path/to/repo', { agent: 'codex' });
145
+ console.log(report.findings);
146
+ ```
147
+
148
+ Contributions are welcome, especially real examples that expose a false positive or a missed finding. See [CONTRIBUTING.md](CONTRIBUTING.md). Please remove private instructions and paths before sharing a report.
149
+
150
+ ## Next
151
+
152
+ - More annotated examples from real repositories.
153
+ - Better condition and activation parsing.
154
+ - Codex override/fallback discovery and source queries.
155
+
156
+ [Related projects](docs/market-check.md) explore this space too. ContextLint focuses on a conservative, evidence-first review workflow and bilingual visual reports.
157
+
158
+ ## License
159
+
160
+ [MIT](LICENSE).
@@ -0,0 +1,138 @@
1
+ <p align="center"><img src="https://raw.githubusercontent.com/BillWGong/contextlint/main/assets/banner.svg" alt="ContextLint:检查编程助手的指令" width="100%" /></p>
2
+
3
+ <p align="center"><a href="README.md">English</a> · <strong>简体中文</strong></p>
4
+
5
+ # ContextLint
6
+
7
+ **检查编程助手背后的指令,把问题和依据一起展示出来。**
8
+
9
+ 一个本地 CLI:扫描 `AGENTS.md`、`CLAUDE.md` 等指令文件,寻找重复规则、明确的潜在冲突和失效链接。生成的可视化报告保留原文、文件行号、检测依据和修改建议。
10
+
11
+ 扫描时无需 API key、不调用模型、不上传文件。
12
+
13
+ ![原文对比示意](https://raw.githubusercontent.com/BillWGong/contextlint/main/assets/finding.svg)
14
+
15
+ ## 开始使用
16
+
17
+ 需要 **Node.js 22+**。在自己的项目目录直接运行:
18
+
19
+ ```bash
20
+ npx @billwgong/contextlint@latest . --html --lang zh
21
+ ```
22
+
23
+ 按终端显示的路径打开 HTML 报告。也可以全局安装:
24
+
25
+ ```bash
26
+ npm install -g @billwgong/contextlint
27
+ contextlint . --html --lang zh
28
+ ```
29
+
30
+ 如需从源码构建,使用 pnpm:
31
+
32
+ ```bash
33
+ git clone https://github.com/BillWGong/contextlint.git
34
+ cd contextlint
35
+ pnpm install --frozen-lockfile
36
+ pnpm build
37
+
38
+ # 先运行中文示例
39
+ node dist/cli.js examples/zh-demo --agent codex --lang zh --html report.html
40
+ ```
41
+
42
+ 在浏览器打开 `report.html`。右上角可以切换 **English / 简体中文**,也可以按类型筛选、搜索指令原文。报告离线可查看,筛选和语言切换需要 JavaScript。
43
+
44
+ 然后换成自己的项目路径:
45
+
46
+ ```bash
47
+ node dist/cli.js /你的项目路径 --agent codex --lang zh --html report.html
48
+ ```
49
+
50
+ 每次生成 HTML 都会在 `<扫描项目>/.contextlint/reports/` 保存一份独立历史报告,命令退出后仍可打开,不会自动删除。终端会显示绝对路径和 `file://` 链接。使用 `--html report.html` 还会额外保存一份便于查找的副本,并自动创建父目录;再次扫描不会覆盖历史记录。扫描项目需要可写。 报告标题优先显示扫描项目 `package.json` 中的名称,没有有效名称时显示扫描目录名。
51
+
52
+ 去掉 `--html` 就会直接显示终端报告。CLI 默认按系统语言选择中文或英文,也可以用 `--lang en|zh` 指定。指令原文始终保持原样,不进行机器翻译。
53
+
54
+ ## 能发现什么
55
+
56
+ | 检查 | 展示的依据 | 修改方向 |
57
+ | --- | --- | --- |
58
+ | 包管理器选择冲突 | 明确的 pnpm / npm 等选择 | 检查 lockfile,统一工具或说明范围 |
59
+ | 相反的动作要求 | 相同动作被要求和禁止 | 保留预期规则,或补充适用条件 |
60
+ | 重复规则 | 有限归一化后相同的原文 | 判断是否需要多处保留 |
61
+ | 失效链接 | 指向不存在文件的 Markdown 相对链接 | 修正路径、恢复文件或清理旧引用 |
62
+
63
+ 每项发现都有文件和原始行号。可视化报告进一步说明判断依据和修改建议,不会自动修改文件。
64
+
65
+ 检测支持少量明确的中英文句式。例如 `Use pnpm`、`请使用 pnpm 管理依赖`,以及同动作的 `Always / Never`、`必须 / 禁止`。复杂自然语言语义暂不支持。
66
+
67
+ **范围会影响判断。** 包管理器选择可在同一文件内跨标题比较;重复规则和正反指令仍按标题隔离。不同助手、跨文件的不同标题、父子目录规则,以及激活条件不明的跨文件规则,不会直接视为同一范围的冲突。这种保守策略也可能漏报。
68
+
69
+ ## 常用命令
70
+
71
+ ```bash
72
+ # 终端中文报告
73
+ node dist/cli.js . --agent codex --lang zh
74
+
75
+ # 英文示例和可视化报告
76
+ node dist/cli.js examples/demo --lang en --html report-en.html
77
+
78
+ # 程序接口:JSON 不随界面语言变化
79
+ node dist/cli.js . --json > findings.json
80
+
81
+ # CI:存在 warning 时返回退出码 1
82
+ node dist/cli.js . --agent codex --strict --json > findings.json
83
+
84
+ # 排除相对路径,可重复使用
85
+ node dist/cli.js . --exclude fixtures --exclude legacy
86
+ ```
87
+
88
+ | 参数 | 用途 |
89
+ | --- | --- |
90
+ | `--agent claude\|codex\|cursor\|copilot` | 选择对应助手的静态来源集合 |
91
+ | `--html [file.html]` | 持久保存可视化报告,可另指定一份副本 |
92
+ | `--lang en\|zh` | 指定 CLI 和报告初始语言 |
93
+ | `--json` | 输出 `schemaVersion: "1.0"` 的稳定 JSON |
94
+ | `--strict` | 存在 warning 时返回 1 |
95
+ | `--exclude <path>` | 排除相对字面路径,不支持 glob |
96
+
97
+ HTML 与 JSON 为互斥输出模式。退出码:**0** 完成、**1** 严格检查未通过、**2** 执行或参数错误。JSON 字段名和诊断字符串保持英文,便于集成;终端和可视化界面支持中文。
98
+
99
+ ## 文件支持与限制
100
+
101
+ 支持 `AGENTS.md`、`CLAUDE.md`、`.claude/rules/**/*.md`、`.cursor/rules/**/*.mdc` / `.md`、`.github/copilot-instructions.md` 和 `.github/instructions/**/*.instructions.md`。具体分类和比较策略见 [英文表格](README.md#supported-files)。
102
+
103
+ - 这是静态检查,无法证明 Codex 实际加载或遵守了哪些规则。
104
+ - 首版不扫描全局指令、导入、skills、`AGENTS.override.md` 或自定义 fallback 文件名。
105
+ - Markdown / frontmatter 是有限解析;代码示例、注释和已识别条件不会参与冲突判断。
106
+ - 同动作冲突需要动作文本匹配,不支持任意改写或翻译之间的语义匹配。
107
+ - 链接以指令文件目录为基准,只检查扫描根目录内目标;跳过 URL、绝对路径、图片和模板。
108
+ - Token 是启发式估算,不代表真实会话消耗或节省费用;无诊断不代表没有问题。
109
+ - 跳过常见依赖/构建目录和符号链接,不自动使用 `.gitignore`;额外路径用 `--exclude`。超过 1 MiB 的指令文件会跳过。
110
+
111
+ 详情见 [规则说明](docs/rules.md)、[JSON Schema](docs/report.schema.json) 和 [验证记录](docs/validation.md)。
112
+
113
+ ## 开发与贡献
114
+
115
+ ```bash
116
+ pnpm install --frozen-lockfile
117
+ pnpm test
118
+ pnpm build
119
+ pnpm pack
120
+ ```
121
+
122
+ TypeScript + Node.js,无生产依赖。`dist/index.js` 导出 `lint(root, options)`。
123
+
124
+ 欢迎提交误报、漏报和真实指令样例。提交前请清理私人路径与内容。贡献说明见 [CONTRIBUTING.md](CONTRIBUTING.md),Issues 可以使用中文或英文。
125
+
126
+ 下一步优先补充真实样例、改进条件解析,以及支持 Codex 的 override/fallback 来源查询。[其他相关工具](docs/market-check.md) 也在探索这一领域。
127
+
128
+ ## 许可证
129
+
130
+ [MIT](LICENSE)。
131
+
132
+ ### 报告状态与保存安全
133
+
134
+ JSON 的 `status` 区分 `complete`(在所选范围内完成已支持的静态检查)、`limited`(部分检查受限)和 `no-sources`(没有检查到文件)。`complete` 不代表理解了全部自然语言,也不代表助手运行时一定加载了这些规则。严格模式先对警告返回 1;没有警告但结果受限或没有文件时返回 2。
135
+
136
+ 输出副本会原子替换已有普通文件,拒绝符号链接。副本保存失败时,错误会给出已保留的历史路径。POSIX 下新报告权限为仅文件所有者可读写。请将 `.contextlint/` 加入所扫描项目的 `.gitignore`;报告含指令原文片段,并非加密文件。
137
+
138
+ 为防止异常仓库卡死,上限为:100,000 个目录条目、64 层目录、1,000 个指令文件、8 MiB 指令内容、10,000 条候选规则、单段 8,192 字符、200,000 次候选冲突比较、每类分析器 1,000 项发现。达到上限会明确标记结果不完整。显式排除和不支持的符号链接属于扫描范围选择;指令文件本身为符号链接时会提示分析受限。
package/SECURITY.md ADDED
@@ -0,0 +1,11 @@
1
+ # Security and trust boundaries
2
+
3
+ ContextLint treats repository instructions as data. It does not execute commands in them, load repository JavaScript, or call an LLM. Production code uses Node built-ins only.
4
+
5
+ The scanner reads supported regular files within a canonical scan root, skips symlinks and applies documented resource limits. Root symlinks explicitly supplied by the user are resolved. Report output uses independent local archives, private permissions where supported, and atomic replacement of regular output copies. Output-file symlinks and linked history directories are refused. HTML escapes repository text and restricts executable scripts with a hash-based Content Security Policy. Terminal controls and directional overrides are displayed visibly; JSON preserves the original evidence.
6
+
7
+ A report is a snapshot, not proof of runtime instruction loading. Unresolved conditions, unreadable files and resource limits are reported. Reports contain source excerpts and paths: exclude `.contextlint/` from version control and review content before sharing. Owner-only file permissions do not provide encryption or defend against another process running as the same user.
8
+
9
+ The filesystem must not be concurrently modified by a hostile process. Portable Node filesystem APIs do not provide a complete sandbox against all ancestor-directory replacement races. Markdown and frontmatter parsing and natural-language checks are deliberately limited. No security review can guarantee an absence of undiscovered bugs.
10
+
11
+ When reporting an issue, provide a minimal sanitized reproduction, Node/OS versions and the CLI command. Do not include secrets or private instruction files.
@@ -0,0 +1,3 @@
1
+ import type { Agent, Finding, Rule, Report } from './types.js';
2
+ export declare function analyzeRules(rules: Rule[], filter?: Agent, skipped?: Report['skipped']): Finding[];
3
+ export declare function analyzeReferences(root: string, rules: Rule[], filter?: Agent, skipped?: Report['skipped']): Promise<Finding[]>;
@@ -0,0 +1,194 @@
1
+ import path from 'node:path';
2
+ import { lstat, realpath } from 'node:fs/promises';
3
+ import { isWithin } from './safe-io.js';
4
+ const location = (r) => ({ path: r.source.path, line: r.line, endLine: r.endLine, text: r.text });
5
+ function overlap(a, b, projectPackageManager = false) {
6
+ if (a.conditional || b.conditional)
7
+ return [];
8
+ // Only package-manager choices within one file may cross heading boundaries.
9
+ if (a.context !== b.context && !(projectPackageManager && a.source.path === b.source.path))
10
+ return [];
11
+ const agents = a.source.agents.filter(agent => b.source.agents.includes(agent));
12
+ if (!agents.length)
13
+ return [];
14
+ if (a.source.path === b.source.path)
15
+ return agents;
16
+ // Descendant instruction files may override parent rules. Do not treat those as conflicts.
17
+ if (a.source.activation !== 'directory' || b.source.activation !== 'directory' || a.source.scope !== b.source.scope)
18
+ return [];
19
+ return agents;
20
+ }
21
+ function packageManager(r) {
22
+ if (r.conditional)
23
+ return null;
24
+ const text = r.normalized.replace(/`([^`]+)`/g, '$1');
25
+ const match = text.match(/^(?:always\s+)?use\s+(npm|pnpm|yarn|bun)(?:\s+(?:for (?:this |the )?project|as (?:the |your )?package manager|for (?:package|dependency) management))?$|^(?:请|必须|始终|总是|务必)?(?:使用|用)\s*(npm|pnpm|yarn|bun)(?:\s*(?:管理依赖|作为包管理器))?$/i);
26
+ if (match)
27
+ return (match[1] || match[2]).toLowerCase();
28
+ // A small closed grammar: reject unknown prose rather than infer intent from mentions.
29
+ if (text.length > 160)
30
+ return null;
31
+ const clauses = text.toLowerCase().split(/[.!;,。!;,]+/).map(c => c.trim()).filter(Boolean);
32
+ let selected = null;
33
+ const excluded = new Set();
34
+ for (const clause of clauses) {
35
+ const negative = clause.match(/^(?:not\s+|(?:不用|不要用|禁止使用|禁用)\s*)(npm|pnpm|yarn|bun)$|^(npm|pnpm|yarn|bun)\s+(?:is\s+(?:legacy|a workaround)|禁用)$/);
36
+ if (negative) {
37
+ excluded.add((negative[1] || negative[2]));
38
+ continue;
39
+ }
40
+ const affirmative = clause.match(/^(npm|pnpm|yarn|bun)(?:\s+install\s+or\s+go\s+home)?$|^(?:always\s+)?use\s+(npm|pnpm|yarn|bun)(?:\s+(?:for (?:this |the )?project|as (?:the |your )?package manager|for (?:package|dependency) management))?$|^(?:请|必须|始终|总是|务必)?(?:使用|用)\s*(npm|pnpm|yarn|bun)(?:\s*(?:管理依赖|作为包管理器))?$/);
41
+ if (affirmative) {
42
+ const manager = (affirmative[1] || affirmative[2] || affirmative[3]);
43
+ if (selected && selected !== manager)
44
+ return null;
45
+ selected = manager;
46
+ continue;
47
+ }
48
+ // Rhetoric only reinforces an already explicit choice; it cannot select a tool.
49
+ if (selected && clause === `${selected} is the future`)
50
+ continue;
51
+ return null;
52
+ }
53
+ return selected && !excluded.has(selected) ? selected : null;
54
+ }
55
+ function polarity(r) {
56
+ if (r.conditional)
57
+ return null;
58
+ const match = r.normalized.match(/^(always|never)\s+(.+)$/i);
59
+ if (match)
60
+ return { negative: match[1].toLowerCase() === 'never', action: match[2] };
61
+ const chinese = r.normalized.match(/^(始终|总是|必须|务必|禁止|绝不|不要)\s*(.+)$/);
62
+ if (!chinese)
63
+ return null;
64
+ return { negative: ['禁止', '绝不', '不要'].includes(chinese[1]), action: chinese[2] };
65
+ }
66
+ export function analyzeRules(rules, filter, skipped) {
67
+ const limit = () => skipped?.push({ path: '.', reason: 'Conflict comparison or finding limit reached' });
68
+ const findings = [];
69
+ const duplicateGroups = new Map();
70
+ for (const rule of rules) {
71
+ if (rule.normalized.length < 12 || rule.conditional)
72
+ continue;
73
+ const group = duplicateGroups.get(rule.normalized) ?? [];
74
+ group.push(rule);
75
+ duplicateGroups.set(rule.normalized, group);
76
+ }
77
+ for (const group of duplicateGroups.values()) {
78
+ // Connected components could imply overlap transitively; instead group by identical scope/activation.
79
+ const buckets = new Map();
80
+ for (const r of group) {
81
+ const key = JSON.stringify([r.context, r.source.activation === 'directory' ? `scope:${r.source.scope}` : `file:${r.source.path}`]);
82
+ const bucket = buckets.get(key) ?? [];
83
+ bucket.push(r);
84
+ buckets.set(key, bucket);
85
+ }
86
+ for (const bucket of buckets.values()) {
87
+ for (const agent of filter ? [filter] : ['claude', 'codex', 'cursor', 'copilot']) {
88
+ const relevant = bucket.filter(r => r.source.agents.includes(agent));
89
+ if (relevant.length < 2)
90
+ continue;
91
+ findings.push({ id: 'DUPLICATE_RULE', severity: 'warning', confidence: 'high', message: 'Repeated rule in the same static scope',
92
+ reason: 'Rule text matches after removing list markers, whitespace differences and trailing sentence punctuation.',
93
+ agents: [agent], locations: relevant.map(location) });
94
+ }
95
+ }
96
+ }
97
+ // Merge duplicate findings that describe the same locations for several agents.
98
+ const merged = new Map();
99
+ for (const f of findings) {
100
+ const key = JSON.stringify(f.locations);
101
+ const previous = merged.get(key);
102
+ if (previous)
103
+ previous.agents.push(...f.agents);
104
+ else
105
+ merged.set(key, f);
106
+ }
107
+ const result = [...merged.values()];
108
+ if (result.length >= 1000) {
109
+ limit();
110
+ return result.slice(0, 1000);
111
+ }
112
+ const recognized = rules.map(rule => ({ rule, manager: packageManager(rule), polarity: polarity(rule) }));
113
+ const managerKinds = new Set(recognized.map(c => c.manager).filter(Boolean));
114
+ const directions = new Map();
115
+ for (const candidate of recognized)
116
+ if (candidate.polarity) {
117
+ const values = directions.get(candidate.polarity.action) ?? new Set();
118
+ values.add(candidate.polarity.negative);
119
+ directions.set(candidate.polarity.action, values);
120
+ }
121
+ const candidates = recognized.filter(c => (c.manager && managerKinds.size > 1)
122
+ || (c.polarity && directions.get(c.polarity.action).size > 1));
123
+ let comparisons = 0;
124
+ for (let i = 0; i < candidates.length; i++)
125
+ for (let j = i + 1; j < candidates.length; j++) {
126
+ if (++comparisons > 200000 || result.length >= 1000) {
127
+ limit();
128
+ return result;
129
+ }
130
+ const ca = candidates[i], cb = candidates[j];
131
+ const a = ca.rule, b = cb.rule;
132
+ const shared = overlap(a, b).filter(agent => !filter || agent === filter);
133
+ const managerShared = overlap(a, b, true).filter(agent => !filter || agent === filter);
134
+ if (!shared.length && !managerShared.length)
135
+ continue;
136
+ const managerA = ca.manager, managerB = cb.manager;
137
+ const pa = ca.polarity, pb = cb.polarity;
138
+ const pm = managerShared.length && managerA && managerB && managerA !== managerB;
139
+ const opposite = shared.length && pa && pb && pa.negative !== pb.negative && pa.action === pb.action;
140
+ if (!pm && !opposite)
141
+ continue;
142
+ result.push({ id: pm ? 'PACKAGE_MANAGER_CONFLICT' : 'POLARITY_CONFLICT', severity: 'warning', confidence: 'medium',
143
+ message: pm ? `Potential package-manager conflict: ${managerA} / ${managerB}` : 'Potential opposite-directive conflict',
144
+ reason: 'Explicit incompatible statements share an agent and static scope. Runtime loading and precedence are not inferred.',
145
+ agents: pm ? managerShared : shared, locations: [location(a), location(b)] });
146
+ }
147
+ return result;
148
+ }
149
+ export async function analyzeReferences(root, rules, filter, skipped) {
150
+ const findings = [];
151
+ for (const rule of rules) {
152
+ const prose = rule.text.replace(/`+[^`]*`+/g, '');
153
+ for (const match of prose.matchAll(/(?<!!)\[[^\[\]\n]+\]\(([^\s()]+)(?:[ \t]+"[^"\n]*")?\)/g)) {
154
+ let target = match[1].replace(/^<|>$/g, '').split(/[?#]/)[0];
155
+ if (!target || /^(?:[a-z][a-z0-9+.-]*:|\/|~)/i.test(target) || /[*{}$<>\\]/.test(target))
156
+ continue;
157
+ try {
158
+ target = decodeURIComponent(target);
159
+ }
160
+ catch {
161
+ continue;
162
+ }
163
+ const absolute = path.resolve(root, path.dirname(rule.source.path), target);
164
+ if (!isWithin(root, absolute))
165
+ continue;
166
+ try {
167
+ const parent = await realpath(path.dirname(absolute));
168
+ if (!isWithin(root, parent))
169
+ continue;
170
+ if ((await lstat(absolute)).isSymbolicLink())
171
+ continue;
172
+ const resolved = await realpath(absolute);
173
+ if (!isWithin(root, resolved))
174
+ continue;
175
+ }
176
+ catch (error) {
177
+ if (findings.length >= 1000) {
178
+ skipped?.push({ path: '.', reason: 'Reference finding limit reached' });
179
+ return findings;
180
+ }
181
+ if (!['ENOENT', 'ENOTDIR'].includes(error.code ?? '')) {
182
+ skipped?.push({ path: rule.source.path, reason: `Reference could not be checked (${error.code ?? 'unknown'})` });
183
+ continue;
184
+ }
185
+ findings.push({ id: 'BROKEN_REFERENCE', severity: 'warning', confidence: 'high',
186
+ message: `Local Markdown link does not exist: ${target}`,
187
+ reason: 'Relative Markdown link resolved from the instruction file directory, within the scan root.',
188
+ agents: rule.source.agents.filter(agent => !filter || agent === filter), locations: [location(rule)] });
189
+ }
190
+ }
191
+ }
192
+ return findings;
193
+ }
194
+ //# sourceMappingURL=analyzers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyzers.js","sourceRoot":"","sources":["../src/analyzers.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};