@wwkit/harness 1.0.9 → 1.0.10

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.
Files changed (110) hide show
  1. package/agents/extract.md +2 -14
  2. package/agents/lint.md +367 -0
  3. package/agents/pyit.md +361 -0
  4. package/agents/pyut.md +347 -0
  5. package/agents/query.md +2 -14
  6. package/agents/revise.md +2 -14
  7. package/agents/work.md +151 -0
  8. package/commands/git-sync.md +218 -0
  9. package/commands/net-port.md +364 -0
  10. package/commands/pyit.md +6 -0
  11. package/commands/pyut.md +6 -0
  12. package/commands/resume.md +104 -0
  13. package/package.json +2 -2
  14. package/skills/better-skill/SKILL.md +124 -0
  15. package/skills/blame-skill/SKILL.md +201 -0
  16. package/skills/lint-ai-fix/SKILL.md +141 -0
  17. package/skills/lint-config-setup/SKILL.md +106 -0
  18. package/skills/lint-config-setup/references/languages/js.md +110 -0
  19. package/skills/lint-config-setup/references/languages/py.md +89 -0
  20. package/skills/lint-env-ensure/SKILL.md +92 -0
  21. package/skills/lint-env-ensure/references/config.md +65 -0
  22. package/skills/lint-language-detect/SKILL.md +79 -0
  23. package/skills/lint-language-detect/references/detect-language.js +65 -0
  24. package/skills/lint-rules-analyze/SKILL.md +129 -0
  25. package/skills/lint-suitability-check/SKILL.md +84 -0
  26. package/skills/lint-tool-fix/SKILL.md +94 -0
  27. package/skills/new-skill/SKILL.md +227 -0
  28. package/skills/new-skill/references/template.md +53 -0
  29. package/skills/new-skill/references/workflow-patterns.md +104 -0
  30. package/skills/pytest-case-create/SKILL.md +327 -0
  31. package/skills/pytest-case-create/references/test-standards.md +244 -0
  32. package/skills/pytest-case-fix/SKILL.md +274 -0
  33. package/skills/pytest-coverage-analyze/SKILL.md +226 -0
  34. package/skills/pytest-coverage-analyze/references/scoring-rules.md +57 -0
  35. package/skills/pytest-env-ensure/SKILL.md +198 -0
  36. package/skills/pytest-env-ensure/references/config.md +145 -0
  37. package/skills/pytest-execute/SKILL.md +155 -0
  38. package/skills/pytest-sample/SKILL.md +164 -0
  39. package/skills/pytest-sample/references/src/pytest-sample/Calculator.py +67 -0
  40. package/skills/pytest-sample/references/src/pytest-sample/ConfigManager.py +68 -0
  41. package/skills/pytest-sample/references/src/pytest-sample/FileProcessor.py +53 -0
  42. package/skills/pytest-sample/references/src/pytest-sample/OrderService.py +82 -0
  43. package/skills/pytest-sample/references/src/pytest-sample/TokenGenerator.py +50 -0
  44. package/skills/pytest-sample/references/src/pytest-sample/UserService.py +45 -0
  45. package/skills/pytest-sample/references/src/pytest-sample/__init__.py +0 -0
  46. package/skills/pytest-suitability-check/SKILL.md +224 -0
  47. package/skills/read-docs/SKILL.md +134 -0
  48. package/skills/read-docs/references/opencode/agents/cases.md +206 -0
  49. package/skills/read-docs/references/opencode/agents/design-pattern.md +47 -0
  50. package/skills/read-docs/references/opencode/agents/detail.md +191 -0
  51. package/skills/read-docs/references/opencode/agents/examples.md +100 -0
  52. package/skills/read-docs/references/opencode/agents/index.md +307 -0
  53. package/skills/read-docs/references/opencode/agents/workflow.md +161 -0
  54. package/skills/read-docs/references/opencode/cli/commands/acp.md +32 -0
  55. package/skills/read-docs/references/opencode/cli/commands/agent.md +16 -0
  56. package/skills/read-docs/references/opencode/cli/commands/attach.md +20 -0
  57. package/skills/read-docs/references/opencode/cli/commands/mcp.md +37 -0
  58. package/skills/read-docs/references/opencode/cli/commands/others.md +49 -0
  59. package/skills/read-docs/references/opencode/cli/commands/plugin.md +13 -0
  60. package/skills/read-docs/references/opencode/cli/commands/provider.md +44 -0
  61. package/skills/read-docs/references/opencode/cli/commands/run.md +81 -0
  62. package/skills/read-docs/references/opencode/cli/commands/serve.md +84 -0
  63. package/skills/read-docs/references/opencode/cli/commands/session.md +38 -0
  64. package/skills/read-docs/references/opencode/cli/commands/web.md +15 -0
  65. package/skills/read-docs/references/opencode/cli/env.md +39 -0
  66. package/skills/read-docs/references/opencode/cli/index.md +19 -0
  67. package/skills/read-docs/references/opencode/cli/tui.md +35 -0
  68. package/skills/read-docs/references/opencode/commands/examples.md +42 -0
  69. package/skills/read-docs/references/opencode/commands/index.md +185 -0
  70. package/skills/read-docs/references/opencode/config/provider.md +152 -0
  71. package/skills/read-docs/references/opencode/formatter/index.md +71 -0
  72. package/skills/read-docs/references/opencode/guide/config.md +419 -0
  73. package/skills/read-docs/references/opencode/guide/formatters.md +70 -0
  74. package/skills/read-docs/references/opencode/guide/index.md +37 -0
  75. package/skills/read-docs/references/opencode/guide/providers.md +31 -0
  76. package/skills/read-docs/references/opencode/guide/rules.md +63 -0
  77. package/skills/read-docs/references/opencode/plugins/examples.md +75 -0
  78. package/skills/read-docs/references/opencode/plugins/index.md +188 -0
  79. package/skills/read-docs/references/opencode/reference/index.md +119 -0
  80. package/skills/read-docs/references/opencode/rule/index.md +78 -0
  81. package/skills/read-docs/references/opencode/skills/detail.md +113 -0
  82. package/skills/read-docs/references/opencode/skills/examples.md +141 -0
  83. package/skills/read-docs/references/opencode/skills/index.md +126 -0
  84. package/skills/read-docs/references/opencode/skills/workflow.md +146 -0
  85. package/skills/read-docs/references/opencode/tests/agent.md +10 -0
  86. package/skills/read-docs/references/opencode/tests/config.md +60 -0
  87. package/skills/read-docs/references/opencode/tests/file.md +12 -0
  88. package/skills/read-docs/references/opencode/tests/serve.md +18 -0
  89. package/skills/read-docs/references/opencode/tests/session.md +31 -0
  90. package/skills/read-docs/references/opencode/tests/web.md +17 -0
  91. package/skills/read-docs/references/opencode/tools/arguments.md +305 -0
  92. package/skills/read-docs/references/opencode/tools/context.md +18 -0
  93. package/skills/read-docs/references/opencode/tools/custom.md +111 -0
  94. package/skills/read-docs/references/opencode/tools/detail.md +104 -0
  95. package/skills/read-docs/references/opencode/tools/examples.md +71 -0
  96. package/skills/read-docs/references/opencode/tools/index.md +56 -0
  97. package/skills/read-docs/references/opencode/tools/lsp.md +26 -0
  98. package/skills/read-docs/references/opencode/tools/mcp.md +132 -0
  99. package/skills/read-docs/references/opencode/train/README.md +135 -0
  100. package/skills/read-docs/references/opencode/train/agent-basic.md +772 -0
  101. package/skills/read-docs/references/opencode/train/command-basic.md +668 -0
  102. package/skills/read-docs/references/opencode/train/config-basic.md +509 -0
  103. package/skills/read-docs/references/opencode/train/index.md +164 -0
  104. package/skills/read-docs/references/opencode/train/practice.md +873 -0
  105. package/skills/read-docs/references/opencode/train/skill-basic.md +608 -0
  106. package/skills/read-docs/references/opencode/tui/commands/config.md +32 -0
  107. package/skills/read-docs/references/opencode/tui/commands/editor.md +47 -0
  108. package/skills/read-docs/references/opencode/tui/commands/index.md +125 -0
  109. package/skills/read-docs/references/opencode/tui/commands/init.md +5 -0
  110. package/skills/read-docs/references/opencode/tui/index.md +26 -0
@@ -0,0 +1,89 @@
1
+ # Python Ruff 规则清单
2
+
3
+ ## 工具信息
4
+
5
+ | 项 | 值 |
6
+ |---|---|
7
+ | 工具 | Ruff |
8
+ | 安装 | `pip install ruff` 或 `uv add --dev ruff` |
9
+ | 配置文件 | `ruff.toml` |
10
+ | 检查命令 | `ruff check {target_dir} --output-format json` |
11
+ | 修复命令 | `ruff check {target_dir} --fix` |
12
+ | 输出格式 | JSON 数组,每元素含 code/message/filename/location |
13
+
14
+ ## Ruff JSON 输出解析
15
+
16
+ ```json
17
+ [
18
+ {
19
+ "code": "F401",
20
+ "message": "'os' imported but unused",
21
+ "filename": "/abs/path/to/file.py",
22
+ "location": [10, 1],
23
+ "end_location": [10, 10],
24
+ "fix": null
25
+ }
26
+ ]
27
+ ```
28
+
29
+ - `fix` 非 null = 可自动修复(`fixable = true`)
30
+ - severity 映射:F 前缀 = error,E 前缀 = error,W 前缀 = warning,UP 前缀 = warning
31
+
32
+ ## 规则清单
33
+
34
+ > 初始启用标记 ✓ 的规则在配置生成时写入 config 文件;✗ 的规则仅记录在清单中,后续可逐步放开。
35
+
36
+ ### Pyflakes (F)
37
+
38
+ | 规则 | 描述 | 默认级别 | 初始启用 | 可 fix |
39
+ |------|------|---------|---------|--------|
40
+ | F401 | 未使用的 import | error | ✓ | ✓ |
41
+ | F811 | 重定义未使用的名称 | error | ✓ | ✓ |
42
+ | F841 | 未使用的局部变量 | error | ✓ | ✓ |
43
+ | F501 | f-string 无占位符 | error | ✗ | ✓ |
44
+ | F541 | f-string 无占位符 | error | ✗ | ✓ |
45
+ | F601 | 字典字面量重复键 | error | ✗ | ✓ |
46
+ | F621 | 参数列表解包重复 | error | ✗ | ✗ |
47
+ | F622 | 星号后重复参数 | error | ✗ | ✗ |
48
+ | F633 | 非法 __future__ import | error | ✗ | ✗ |
49
+ | F701 | break 在循环外 | error | ✗ | ✗ |
50
+ | F821 | 未定义名称 | error | ✗ | ✗ |
51
+ | F822 | __all__ 中未定义名称 | error | ✗ | ✗ |
52
+
53
+ ### Pycodestyle (E/W)
54
+
55
+ | 规则 | 描述 | 默认级别 | 初始启用 | 可 fix |
56
+ |------|------|---------|---------|--------|
57
+ | E711 | 比较使用 None 应为 is None | error | ✓ | ✓ |
58
+ | E712 | 比较使用 True/False 应为 is | error | ✗ | ✓ |
59
+ | E713 | not in 应替代 not ... in | error | ✗ | ✓ |
60
+ | E714 | is not 应替代 not ... is | error | ✗ | ✓ |
61
+ | E501 | 行过长(默认 88 字符) | warn | ✗ | ✗ |
62
+ | E302 | 预期 2 个空行 | warn | ✗ | ✓ |
63
+ | E303 | 函数间空行过多 | warn | ✗ | ✓ |
64
+ | E305 | 函数/类后 2 个空行 | warn | ✗ | ✓ |
65
+ | W291 | 行尾空格 | warn | ✗ | ✓ |
66
+ | W292 | 文件末尾无换行 | warn | ✗ | ✓ |
67
+ | W293 | 空行有空白字符 | warn | ✗ | ✓ |
68
+
69
+ ### Pyupgrade (UP)
70
+
71
+ | 规则 | 描述 | 默认级别 | 初始启用 | 可 fix |
72
+ |------|------|---------|---------|--------|
73
+ | UP001 | 过时的 __future__ import | warn | ✗ | ✓ |
74
+ | UP010 | 过时的 __future__ union types | warn | ✗ | ✓ |
75
+ | UP011 | 不必要的 lru_cache 括号 | warn | ✗ | ✓ |
76
+ | UP015 | 不必要的 open 模式 | warn | ✗ | ✓ |
77
+
78
+ ## 配置文件模板(ruff.toml)
79
+
80
+ ```toml
81
+ [lint]
82
+ # 初始启用规则
83
+ select = ["F401", "F811", "F841", "E711"]
84
+
85
+ [lint.fix]
86
+ unsafe-fixes = false
87
+ ```
88
+
89
+ > 仅写入初始启用 ✓ 的规则。用户已有配置文件时只追加缺失规则,不覆盖。
@@ -0,0 +1,92 @@
1
+ ---
2
+ name: lint-env-ensure
3
+ description: |
4
+ 检查 lint 工具可用性,缺失时在项目内自动安装。按主语言检查对应 linter(jsts→eslint,python→ruff),
5
+ 安装失败重试 3 次。加载配置清单供后续 skill 共享。
6
+ 适用:lint agent 的环境检查阶段,在配置生成和规则分析前确保工具可用。
7
+ 不适用:非 lint 场景的环境检查、系统级工具安装。
8
+ ---
9
+
10
+ # Lint 环境检查
11
+
12
+ ## 工作流模式
13
+
14
+ 顺序执行,4 个阶段。
15
+
16
+ ## 输入
17
+
18
+ | 参数 | 必填 | 类型 | 说明 |
19
+ |------|------|------|------|
20
+ | root_dir | 是 | string | 工程根目录路径 |
21
+ | primary_language | 是 | string | 主语言(`jsts` 或 `python`) |
22
+
23
+ ## 输出
24
+
25
+ - `linter_name`:linter 名称(`eslint` 或 `ruff`)
26
+ - `linter_version`:linter 版本号
27
+ - `linter_installed`:是否已安装且可用(bool)
28
+ - `config`:从 references/config.md 加载的配置对象
29
+
30
+ ## 阶段一:检查工具可用性
31
+
32
+ 按 `primary_language` 检查对应 linter:
33
+
34
+ | 主语言 | linter | 检查命令 |
35
+ |--------|--------|---------|
36
+ | jsts | eslint | `npx eslint --version` |
37
+ | python | ruff | `ruff --version` |
38
+
39
+ ## 阶段二:自动安装(工具缺失时)
40
+
41
+ 工具不可用时,在项目内安装:
42
+
43
+ | 主语言 | 安装命令 | 备注 |
44
+ |--------|---------|------|
45
+ | jsts | `cd {root_dir} && npm install -D eslint` | TS 项目额外安装 `@typescript-eslint/parser @typescript-eslint/eslint-plugin` |
46
+ | python | `cd {root_dir} && pip install ruff` 或 `cd {root_dir} && uv add --dev ruff` | 优先用 uv,回退到 pip |
47
+
48
+ 安装失败时重试,最多 3 次(`install_retry` 来自 config)。
49
+
50
+ ## 阶段三:安装验证
51
+
52
+ 重新执行阶段一的检查命令,确认安装成功。
53
+
54
+ | 条件 | 动作 |
55
+ |------|------|
56
+ | 工具可用 | 输出 linter_name/version/installed=true,继续 |
57
+ | 工具仍不可用 | 输出 installed=false,agent 退出 |
58
+
59
+ ## 阶段四:加载配置
60
+
61
+ 读取 `references/config.md`,输出配置对象供后续 skill 使用。
62
+
63
+ ## 决策
64
+
65
+ | 条件 | 动作 |
66
+ |------|------|
67
+ | 工具已安装 | 输出结果,流程结束 |
68
+ | 工具缺失,安装成功 | 输出结果,流程结束 |
69
+ | 工具缺失,安装失败 | 输出 installed=false,agent 退出 |
70
+
71
+ ## 失败处理
72
+
73
+ | 场景 | 处理方式 |
74
+ |------|---------|
75
+ | 检查命令执行失败 | 认为工具未安装,进入安装流程 |
76
+ | npm install 失败 | 重试最多 3 次 |
77
+ | pip install 失败 | 尝试 uv add,再失败则重试 |
78
+ | 重试 3 次仍失败 | 输出 installed=false |
79
+
80
+ ## 一定要做
81
+
82
+ 1. 在项目内安装(`npm install -D`),不安装全局
83
+ 2. 安装后必须重新验证工具可用性
84
+ 3. 加载 config.md 配置供后续 skill 共享
85
+ 4. TS 项目检查是否需要 @typescript-eslint 插件
86
+
87
+ ## 一定不要做
88
+
89
+ 1. 不要全局安装工具(`npm install -g`)
90
+ 2. 不要跳过安装验证步骤
91
+ 3. 不要修改项目配置文件(package.json 等)
92
+ 4. 不要使用 webfetch 下载工具,仅通过包管理器(npm/pip/uv)安装
@@ -0,0 +1,65 @@
1
+ # lint 检查代理配置清单
2
+
3
+ > 本文件是 lint 代理的全局配置,agent 启动时首先读取,后续所有 skill 共享。
4
+
5
+ ## 依赖工具
6
+
7
+ ### JS/TS
8
+
9
+ | name | check | required | install |
10
+ |------|-------|----------|---------|
11
+ | eslint | `npx eslint --version` | true | `npm install -D eslint` |
12
+ | @typescript-eslint/parser | `npx tsc --version` 时需要 | false | `npm install -D @typescript-eslint/parser @typescript-eslint/eslint-plugin` |
13
+
14
+ ### Python
15
+
16
+ | name | check | required | install |
17
+ |------|-------|----------|---------|
18
+ | ruff | `ruff --version` | true | `pip install ruff` 或 `uv add --dev ruff` |
19
+
20
+ ## 环境检查
21
+
22
+ | 参数 | 值 | 说明 |
23
+ |------|-----|------|
24
+ | install_retry | 3 | 工具安装失败重试次数 |
25
+
26
+ ## Loop 控制
27
+
28
+ | 参数 | 值 | 说明 |
29
+ |------|-----|------|
30
+ | outer_max | 3 | 外层 loop(check→fix→recheck)最大轮次 |
31
+ | inner_max | 3 | lint-ai-fix 内部 loop 最大轮次 |
32
+
33
+ ## 评分模型
34
+
35
+ | 参数 | 值 | 说明 |
36
+ |------|-----|------|
37
+ | target_score | 100 | 二元制:0 违规=100,1+ 违规=0 |
38
+ | pass_threshold | 0 | 违规数达标线(0 = 全部通过) |
39
+
40
+ ## 命名规则
41
+
42
+ | 参数 | 值 | 说明 |
43
+ |------|-----|------|
44
+ | report_dir_pattern | `{root_dir}/.webwork/lint/reports/{YYYYMMDD_HHMMSS}/` | 报告输出目录 |
45
+ | report.lint_report | `lint_report.md` | 最终报告文件名 |
46
+
47
+ ## 语言映射
48
+
49
+ | 语言 | 标识 | 扩展名 | manifest | linter | config_file |
50
+ |------|------|--------|----------|--------|-------------|
51
+ | JS/TS/Vue | jsts | .js .jsx .ts .tsx .vue .mjs .cjs | package.json | eslint | eslint.config.js |
52
+ | Python | python | .py | pyproject.toml / setup.py | ruff | ruff.toml |
53
+
54
+ ## 排除目录
55
+
56
+ ```
57
+ node_modules/ dist/ build/ .git/ __pycache__/ .venv/ venv/ .webwork/ reports/ coverage/ .next/ .nuxt/ .output/ .eggs/ eggs/
58
+ ```
59
+
60
+ ## 语法验证命令
61
+
62
+ | 语言 | 命令 | 说明 |
63
+ |------|------|------|
64
+ | jsts | `node --check {file}` | Node.js 语法检查 |
65
+ | python | `python3 -m py_compile {file}` | Python 字节码编译检查 |
@@ -0,0 +1,79 @@
1
+ ---
2
+ name: lint-language-detect
3
+ description: |
4
+ 探测工程主语言。优先检查 manifest 文件(package.json → jsts,pyproject.toml/setup.py → python),
5
+ 无 manifest 时按源码文件扩展名计数,多者为主语言。JS/TS 视为一种语言。
6
+ 适用:lint agent 的语言探测阶段,在环境检查和配置生成前确定主语言。
7
+ 不适用:非 lint 场景的语言检测、混合语言项目(v1 按主语言处理,不支持混合)。
8
+ ---
9
+
10
+ # 主语言探测
11
+
12
+ ## 工作流模式
13
+
14
+ 顺序执行,2 个阶段。
15
+
16
+ ## 输入
17
+
18
+ | 参数 | 必填 | 类型 | 说明 |
19
+ |------|------|------|------|
20
+ | root_dir | 是 | string | 工程根目录路径 |
21
+
22
+ ## 输出
23
+
24
+ - `primary_language`:主语言标识(`jsts` 或 `python`)
25
+ - `detection_method`:检测方式(`manifest` 或 `file_count`)
26
+ - `file_counts`:各语言源码文件计数(仅 `file_count` 方式时有值)
27
+
28
+ ## 阶段一:Manifest 检测
29
+
30
+ 检查 `root_dir` 下的 manifest 文件:
31
+
32
+ | 检查项 | 命中结果 |
33
+ |--------|---------|
34
+ | `package.json` 存在 | `primary_language = jsts`,`detection_method = manifest` |
35
+ | `pyproject.toml` 存在 | `primary_language = python`,`detection_method = manifest` |
36
+ | `setup.py` 存在 | `primary_language = python`,`detection_method = manifest` |
37
+
38
+ 若 manifest 命中,直接输出结果,跳过阶段二。
39
+
40
+ ## 阶段二:文件计数检测
41
+
42
+ 无 manifest 时,调用 `references/detect-language.js` 的 `detectLanguage(rootDir)` 函数扫描源码文件:
43
+
44
+ 1. 递归扫描 `root_dir`(最大深度 10 层)
45
+ 2. 排除目录:`node_modules/`、`dist/`、`build/`、`.git/`、`__pycache__/`、`.venv/`、`venv/`、`.webwork/`、`reports/`、`coverage/`
46
+ 3. 按扩展名分类计数:
47
+ - jsts:`.js`、`.jsx`、`.ts`、`.tsx`、`.vue`、`.mjs`、`.cjs`
48
+ - python:`.py`
49
+ 4. 文件数多者为主语言;两者都为 0 → 报错
50
+
51
+ ## 决策
52
+
53
+ | 条件 | 动作 |
54
+ |------|------|
55
+ | manifest 命中 | 输出主语言,流程结束 |
56
+ | 无 manifest,源码文件 > 0 | 输出计数多者为主语言 |
57
+ | 无 manifest,源码文件 = 0 | 报错退出 |
58
+
59
+ ## 失败处理
60
+
61
+ | 场景 | 处理方式 |
62
+ |------|---------|
63
+ | root_dir 不存在 | 报错"工程根目录不存在" |
64
+ | 无 manifest 且无源码文件 | 报错"无法检测项目主语言" |
65
+ | 扫描权限不足 | 跳过不可读目录,继续扫描 |
66
+
67
+ ## 一定要做
68
+
69
+ 1. 优先检查 manifest 文件,避免全量扫描
70
+ 2. JS/TS 统一视为 `jsts` 一种语言
71
+ 3. 排除常见的非源码目录
72
+ 4. 无 manifest 时必须扫描文件计数
73
+
74
+ ## 一定不要做
75
+
76
+ 1. 不要返回多个语言(v1 只返回主语言)
77
+ 2. 不要扫描 `node_modules/` 等依赖目录
78
+ 3. 不要修改任何文件
79
+ 4. 不要执行网络请求
@@ -0,0 +1,65 @@
1
+ import { existsSync, readdirSync, statSync } from 'fs';
2
+ import { join, extname } from 'path';
3
+
4
+ const JSTS_EXTENSIONS = new Set(['.js', '.jsx', '.ts', '.tsx', '.vue', '.mjs', '.cjs']);
5
+ const PY_EXTENSIONS = new Set(['.py']);
6
+ const MAX_SCAN_DEPTH = 10;
7
+ const EXCLUDE_DIRS = new Set([
8
+ 'node_modules', 'dist', 'build', '.git', '__pycache__',
9
+ '.venv', 'venv', '.webwork', 'reports', 'coverage',
10
+ '.next', '.nuxt', '.output', 'eggs', '.eggs',
11
+ ]);
12
+
13
+ export function detectLanguage(rootDir) {
14
+ if (existsSync(join(rootDir, 'package.json'))) {
15
+ return 'jsts';
16
+ }
17
+ if (existsSync(join(rootDir, 'pyproject.toml')) || existsSync(join(rootDir, 'setup.py'))) {
18
+ return 'python';
19
+ }
20
+
21
+ const counts = { jsts: 0, python: 0 };
22
+ _countFiles(rootDir, counts, 0);
23
+
24
+ if (counts.jsts === 0 && counts.python === 0) {
25
+ throw new Error(
26
+ 'No lintable source files found: no package.json, pyproject.toml, or .js/.ts/.py files detected'
27
+ );
28
+ }
29
+
30
+ return counts.jsts >= counts.python ? 'jsts' : 'python';
31
+ }
32
+
33
+ function _countFiles(dir, counts, depth) {
34
+ if (depth > MAX_SCAN_DEPTH) return;
35
+
36
+ let entries;
37
+ try {
38
+ entries = readdirSync(dir);
39
+ } catch {
40
+ return;
41
+ }
42
+
43
+ for (const entry of entries) {
44
+ const fullPath = join(dir, entry);
45
+ let stat;
46
+ try {
47
+ stat = statSync(fullPath);
48
+ } catch {
49
+ continue;
50
+ }
51
+
52
+ if (stat.isDirectory()) {
53
+ if (!EXCLUDE_DIRS.has(entry)) {
54
+ _countFiles(fullPath, counts, depth + 1);
55
+ }
56
+ } else {
57
+ const ext = extname(entry).toLowerCase();
58
+ if (JSTS_EXTENSIONS.has(ext)) {
59
+ counts.jsts++;
60
+ } else if (PY_EXTENSIONS.has(ext)) {
61
+ counts.python++;
62
+ }
63
+ }
64
+ }
65
+ }
@@ -0,0 +1,129 @@
1
+ ---
2
+ name: lint-rules-analyze
3
+ description: |
4
+ 执行 linter 检查并解析 JSON 输出,产出违规清单。按主语言调用对应 linter(eslint/ruff),
5
+ 解析输出为统一的 violations 结构。二元制评分:0 违规=100,1+违规=0。
6
+ 适用:lint agent 的规则分析阶段,用于基线检查和轮尾独立验证。
7
+ 不适用:修复违规(使用 lint-tool-fix / lint-ai-fix)、非 lint 场景的代码分析。
8
+ ---
9
+
10
+ # Lint 规则分析
11
+
12
+ ## 工作流模式
13
+
14
+ 顺序执行,4 个阶段。
15
+
16
+ ## 输入
17
+
18
+ | 参数 | 必填 | 类型 | 说明 |
19
+ |------|------|------|------|
20
+ | target_dir | 是 | string | 检查目标目录路径 |
21
+ | root_dir | 是 | string | 工程根目录路径 |
22
+ | primary_language | 是 | string | 主语言(`jsts` 或 `python`) |
23
+ | config_file_path | 是 | string | lint 配置文件路径 |
24
+
25
+ ## 输出
26
+
27
+ - `violation_count`:违规总数
28
+ - `violations`:违规列表,每条含 `{ file, line, column, rule, severity, message, fixable }`
29
+ - `score`:评分(100 或 0)
30
+
31
+ ## 阶段一:执行 linter
32
+
33
+ 按主语言执行 linter,输出 JSON 格式:
34
+
35
+ | 主语言 | 命令 |
36
+ |--------|------|
37
+ | jsts | `cd {root_dir} && npx eslint {target_dir} --format json` |
38
+ | python | `cd {root_dir} && ruff check {target_dir} --output-format json` |
39
+
40
+ ## 阶段二:解析 JSON 输出
41
+
42
+ ### ESLint JSON 解析
43
+
44
+ ESLint 输出 JSON 数组,每元素含 `filePath` 和 `messages[]`:
45
+
46
+ ```
47
+ 对每条 message 提取:
48
+ - file: filePath(转为相对 root_dir 的相对路径)
49
+ - line: message.line
50
+ - column: message.column
51
+ - rule: message.ruleId
52
+ - severity: message.severity === 2 ? 'error' : 'warning'
53
+ - message: message.message
54
+ - fixable: message.fix != null
55
+ ```
56
+
57
+ ### Ruff JSON 解析
58
+
59
+ Ruff 输出 JSON 数组,每元素含 `code`、`filename`、`location`:
60
+
61
+ ```
62
+ 对每条 violation 提取:
63
+ - file: filename(转为相对 root_dir 的相对路径)
64
+ - line: location[0]
65
+ - column: location[1]
66
+ - rule: code
67
+ - severity: code.startsWith('F') || code.startsWith('E') ? 'error' : 'warning'
68
+ - message: message
69
+ - fixable: fix != null
70
+ ```
71
+
72
+ ## 阶段三:评分计算
73
+
74
+ | 条件 | score |
75
+ |------|-------|
76
+ | violation_count = 0 | 100 |
77
+ | violation_count > 0 | 0 |
78
+
79
+ ## 阶段四:输出报告
80
+
81
+ 输出违规清单和评分。
82
+
83
+ ```
84
+ ## Lint 检查结果
85
+
86
+ - 违规总数: X
87
+ - 评分: 100|0
88
+ - error 数: X
89
+ - warning 数: X
90
+ - 可修复数: X
91
+
92
+ ### 违规明细
93
+ | # | 文件 | 行号 | 规则 | 严重级别 | 描述 | 可修复 |
94
+ |---|------|------|------|---------|------|--------|
95
+ | 1 | src/foo.js | 10 | no-unused-vars | error | 'x' is defined but never used | ✗ |
96
+ ```
97
+
98
+ ## 决策
99
+
100
+ | 条件 | 动作 |
101
+ |------|------|
102
+ | violation_count = 0 | score=100,agent 判断达标 |
103
+ | violation_count > 0 | score=0,agent 判断需修复 |
104
+
105
+ ## 失败处理
106
+
107
+ | 场景 | 处理方式 |
108
+ |------|---------|
109
+ | linter 未安装 | 报错"linter 不可用,请先运行环境检查" |
110
+ | linter exit code 1(有违规) | 正常行为,解析 JSON 输出违规清单 |
111
+ | linter exit code 2(配置错误) | 报错"linter 配置错误" |
112
+ | linter 执行超时 | 报错"检查超时" |
113
+ | JSON 解析失败 | 报错"linter 输出解析失败" |
114
+ | target_dir 不存在 | 报错"检查目录不存在" |
115
+ | 无违规(exit code 0) | 输出 violation_count=0, score=100 |
116
+
117
+ ## 一定要做
118
+
119
+ 1. 使用 JSON 格式输出,便于解析
120
+ 2. 将文件路径转为相对 root_dir 的相对路径
121
+ 3. 统一 violations 数据结构(file/line/column/rule/severity/message/fixable)
122
+ 4. 二元制评分:0 违规=100,1+违规=0
123
+
124
+ ## 一定不要做
125
+
126
+ 1. 不要修复任何违规(只检查)
127
+ 2. 不要修改源码文件
128
+ 3. 不要省略 warning 级别的违规
129
+ 4. 不要执行网络请求
@@ -0,0 +1,84 @@
1
+ ---
2
+ name: lint-suitability-check
3
+ description: |
4
+ 扫描目标目录,筛选出可 lint 的源码文件列表。按主语言扩展名过滤,排除依赖/构建/缓存目录。
5
+ 适用:lint agent 的适用性检查阶段,在环境检查前确定可检查的文件范围。
6
+ 不适用:非 lint 场景的文件筛选、语言检测(使用 lint-language-detect)。
7
+ ---
8
+
9
+ # 可 Lint 文件筛选
10
+
11
+ ## 工作流模式
12
+
13
+ 顺序执行,3 个阶段。
14
+
15
+ ## 输入
16
+
17
+ | 参数 | 必填 | 类型 | 说明 |
18
+ |------|------|------|------|
19
+ | root_dir | 是 | string | 工程根目录路径 |
20
+ | target_dir | 是 | string | 检查目标目录路径 |
21
+ | primary_language | 是 | string | 主语言(`jsts` 或 `python`) |
22
+
23
+ ## 输出
24
+
25
+ - `lintable_files`:可 lint 文件路径列表(相对 root_dir 的相对路径)
26
+ - `file_count`:文件数量
27
+ - `excluded_count`:被排除的文件数量
28
+
29
+ ## 阶段一:确定扩展名过滤集
30
+
31
+ | 主语言 | 匹配扩展名 |
32
+ |--------|-----------|
33
+ | jsts | `.js`、`.jsx`、`.ts`、`.tsx`、`.vue`、`.mjs`、`.cjs` |
34
+ | python | `.py` |
35
+
36
+ ## 阶段二:递归扫描
37
+
38
+ 递归扫描 `target_dir`,排除以下目录:
39
+
40
+ | 排除目录 | 原因 |
41
+ |---------|------|
42
+ | `node_modules/` | 依赖目录 |
43
+ | `dist/`、`build/`、`.output/` | 构建产物 |
44
+ | `.git/` | 版本控制 |
45
+ | `__pycache__/`、`.eggs/` | Python 缓存 |
46
+ | `.venv/`、`venv/` | 虚拟环境 |
47
+ | `.webwork/` | 工具输出目录 |
48
+ | `reports/`、`coverage/` | 报告目录 |
49
+ | `.next/`、`.nuxt/` | 框架缓存 |
50
+
51
+ 最大扫描深度 10 层。
52
+
53
+ ## 阶段三:输出文件清单
54
+
55
+ 将匹配的文件路径转为相对 `root_dir` 的相对路径,输出列表。
56
+
57
+ ## 决策
58
+
59
+ | 条件 | 动作 |
60
+ |------|------|
61
+ | file_count > 0 | 输出文件清单,agent 继续 |
62
+ | file_count = 0 | 输出空列表,agent 退出 |
63
+
64
+ ## 失败处理
65
+
66
+ | 场景 | 处理方式 |
67
+ |------|---------|
68
+ | target_dir 不存在 | 报错"检查目录不存在" |
69
+ | target_dir 是文件 | 对该单文件检查 |
70
+ | 扫描权限不足 | 跳过不可读目录 |
71
+
72
+ ## 一定要做
73
+
74
+ 1. 按主语言扩展名精确过滤
75
+ 2. 排除所有依赖/构建/缓存目录
76
+ 3. 输出相对路径而非绝对路径
77
+ 4. 统计 file_count 供 agent 判断
78
+
79
+ ## 一定不要做
80
+
81
+ 1. 不要扫描 node_modules 等排除目录
82
+ 2. 不要返回非目标语言的文件
83
+ 3. 不要修改任何文件
84
+ 4. 不要执行网络请求
@@ -0,0 +1,94 @@
1
+ ---
2
+ name: lint-tool-fix
3
+ description: |
4
+ 执行 linter 的 --fix 自动修复,然后内部复跑 linter 获取剩余违规清单。
5
+ 只处理 linter 可自动修复的规则,不可修复的规则交由 lint-ai-fix 处理。
6
+ 适用:lint agent 的工具修复阶段,在 AI 修复前先自动修复可修复项。
7
+ 不适用:AI 语义修复(使用 lint-ai-fix)、规则检查(使用 lint-rules-analyze)。
8
+ ---
9
+
10
+ # Lint 工具自动修复
11
+
12
+ ## 工作流模式
13
+
14
+ 顺序执行,3 个阶段。
15
+
16
+ ## 输入
17
+
18
+ | 参数 | 必填 | 类型 | 说明 |
19
+ |------|------|------|------|
20
+ | target_dir | 是 | string | 检查目标目录路径 |
21
+ | root_dir | 是 | string | 工程根目录路径 |
22
+ | primary_language | 是 | string | 主语言(`jsts` 或 `python`) |
23
+ | config_file_path | 是 | string | lint 配置文件路径 |
24
+
25
+ ## 输出
26
+
27
+ - `tool_fixed_count`:自动修复的违规数
28
+ - `remaining_violations`:修复后剩余的违规列表(结构同 lint-rules-analyze 的 violations)
29
+
30
+ ## 阶段一:执行 --fix
31
+
32
+ 按主语言执行 linter 的自动修复命令:
33
+
34
+ | 主语言 | 命令 |
35
+ |--------|------|
36
+ | jsts | `cd {root_dir} && npx eslint {target_dir} --fix` |
37
+ | python | `cd {root_dir} && ruff check {target_dir} --fix` |
38
+
39
+ `--fix` 会自动修复所有可自动修复的违规。不可自动修复的规则不受影响。
40
+
41
+ ## 阶段二:复跑 linter 获取剩余违规
42
+
43
+ 修复后重新执行 linter 检查(同 lint-rules-analyze 的命令),获取剩余违规:
44
+
45
+ | 主语言 | 命令 |
46
+ |--------|------|
47
+ | jsts | `cd {root_dir} && npx eslint {target_dir} --format json` |
48
+ | python | `cd {root_dir} && ruff check {target_dir} --output-format json` |
49
+
50
+ 解析 JSON 输出为 `remaining_violations`(结构与 lint-rules-analyze 一致)。
51
+
52
+ ## 阶段三:输出
53
+
54
+ ```
55
+ ## 工具修复结果
56
+
57
+ - 自动修复数: X
58
+ - 剩余违规数: X
59
+ - 剩余可修复数: X(理论上应为 0,--fix 已尽力修复)
60
+ - 剩余不可修复数: X(需 AI 修复)
61
+
62
+ ### 剩余违规明细
63
+ | # | 文件 | 行号 | 规则 | 严重级别 | 描述 | 可修复 |
64
+ |---|------|------|------|---------|------|--------|
65
+ | 1 | src/foo.js | 10 | no-unused-vars | error | ... | ✗ |
66
+ ```
67
+
68
+ ## 决策
69
+
70
+ | 条件 | 动作 |
71
+ |------|------|
72
+ | remaining_violations 为空 | agent 回到轮尾评分(final_count 应为 0 → 达标) |
73
+ | remaining_violations 非空 | agent 进入 AI 修复(Step 8) |
74
+
75
+ ## 失败处理
76
+
77
+ | 场景 | 处理方式 |
78
+ |------|---------|
79
+ | --fix 执行失败 | 报错,agent 跳过工具修复直接进入 AI 修复 |
80
+ | 复跑 linter 失败 | 报错,remaining_violations 设为空列表,agent 将在轮尾独立验证中获取真实违规数 |
81
+ | linter 未安装 | 报错退出 |
82
+
83
+ ## 一定要做
84
+
85
+ 1. --fix 后必须复跑 linter 获取剩余违规
86
+ 2. 输出 remaining_violations 的数据结构与 lint-rules-analyze 一致
87
+ 3. 统计 tool_fixed_count(修复前违规数 - 修复后违规数)
88
+
89
+ ## 一定不要做
90
+
91
+ 1. 不要执行 AI 语义修复(那是 lint-ai-fix 的职责)
92
+ 2. 不要修改 linter 配置文件
93
+ 3. 不要跳过复跑 linter 步骤
94
+ 4. 不要执行网络请求