Skip to content

Commit 9df5c43

Browse files
authored
Merge pull request #5 from full-stack-plugins/feat/detect-lang-splits-v0.6.1
feat: 拆分 detect_lang.py 职责边界 + manifest bundle 测试动态化 (v0.6.1)
2 parents 5591125 + be094ba commit 9df5c43

20 files changed

Lines changed: 502 additions & 149 deletions

File tree

‎.agents/plugins/marketplace.json‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,20 @@
99
"source": {
1010
"source": "url",
1111
"url": "https://github.com/partme-ai/partme-codeguard-plugin.git",
12-
"ref": "v0.6.0"
12+
"ref": "v0.6.1"
1313
},
1414
"policy": {
1515
"installation": "AVAILABLE",
1616
"authentication": "ON_USE"
1717
},
1818
"category": "Developer Tools",
19-
"version": "0.6.0",
19+
"version": "0.6.1",
2020
"description": "Cross-language code lint enforcement for AI coding assistants (ZCode, Claude Code, Codex CLI, Kimi Code): Java, Rust, TypeScript, Python. PostToolUse hook auto-runs the native linter on every AI-written file and blocks on failure in strict mode.",
21-
"icon": "https://cdn.jsdelivr.net/gh/full-stack-plugins/codeguard-plugin@v0.6.0/assets/official-logo.png",
21+
"icon": "https://cdn.jsdelivr.net/gh/full-stack-plugins/codeguard-plugin@v0.6.1/assets/official-logo.png",
2222
"interface": {
2323
"displayName": "代码规范守卫",
2424
"shortDescription": "Make AI-written code pass lint on first try",
25-
"logo": "https://cdn.jsdelivr.net/gh/full-stack-plugins/codeguard-plugin@v0.6.0/assets/official-logo.png"
25+
"logo": "https://cdn.jsdelivr.net/gh/full-stack-plugins/codeguard-plugin@v0.6.1/assets/official-logo.png"
2626
}
2727
}
2828
]

‎.codex-plugin/plugin.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "codeguard",
3-
"version": "0.6.0+codex.20260921",
3+
"version": "0.6.1+codex.20260922",
44
"description": "Cross-language code lint enforcement for AI coding assistants (ZCode, Claude Code, Codex CLI, Kimi Code): Java, Rust, TypeScript, Python. PostToolUse hook auto-runs the native linter on every AI-written file and blocks on failure in strict mode.",
55
"author": {
66
"name": "Full Stack Skills / PartMe.AI",

‎.zcode-plugin/plugin.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"en": "CodeGuard",
66
"zh-CN": "代码规范检查"
77
},
8-
"version": "0.6.0",
8+
"version": "0.6.1",
99
"description": "Cross-language code lint enforcement for AI coding assistants (ZCode, Claude Code, Codex CLI, Kimi Code): Java, Rust, TypeScript, Python. PostToolUse hook auto-runs the native linter on every AI-written file and blocks on failure in strict mode.",
1010
"description_i18n": {
1111
"en": "Cross-language code lint enforcement. PostToolUse hook auto-runs the language-specific linter on every AI-written file; failed lint blocks further writes when strict_mode is on. Ships ready-to-go .pre-commit-config.yaml templates for Java/Rust/TypeScript/Python.",

‎kimi.plugin.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "codeguard",
3-
"version": "0.6.0",
3+
"version": "0.6.1",
44
"description": "Cross-language code lint enforcement for AI coding assistants (ZCode, Claude Code, Codex CLI, Kimi Code): Java, Rust, TypeScript, Python. PostToolUse hook auto-runs the native linter on every AI-written file and blocks on failure in strict mode.",
55
"author": {
66
"name": "Full Stack Skills / PartMe.AI"
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
schema: spec-driven
2+
created: 2026-09-22
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
## Context
2+
3+
实测证据(code-review-graph 2026-09-22 build,HEAD `5591125`):
4+
- 社区数 3:scripts-scan(42 节点) / hooks-gate(39 节点) / tests-skill(36 节点)。
5+
- 跨社区边 25,其中 19 条 CALLS 全部指向 `scripts/detect_lang.py` 的同一组函数:
6+
- `ensure_user_path`(4 处,env_check / post_tool_lint / pre_tool_git_guard / user_prompt_validator)
7+
- `detect_languages` / `detect_language`(5 处)
8+
- `find_project_root`(3 处)
9+
- `probe_toolchain`(5 处)
10+
- `project_uses_linter`(5 处)
11+
- `load_user_config`(4 处,含 user_prompt_validator / pre_tool_git_guard / post_tool_lint / env_check)
12+
13+
耦合来源是三职责合一:所有 hook 既要 PATH 补齐(属于进程环境),又要项目配置(属于用户态),又要语言识别(属于注册表)。后续若新增 hook / 修改 PATH 策略 / 改配置 schema 都会让 hooks 全军覆没。
14+
15+
## Decisions
16+
17+
### 三个文件按职责一刀切
18+
19+
- `scripts/paths.py`:仅 `ensure_user_path` + 内部静态目录与 fallback。依赖:std + `Path`。无项目根、无 JSON 解析。
20+
- `scripts/user_config.py`:`load_user_config` / `load_project_overrides` / `get_overrides`。依赖:std + JSON + `Path`。无 subprocess。
21+
- `scripts/detect_lang.py`:保留 `detect_languages` / `detect_language` / `find_project_root` / `probe_toolchain` / `project_uses_linter` / `extract_tool_binaries` / `LANG_COMMANDS` / `_load_registry`。依赖注册表 + subprocess。
22+
23+
### 外部 API 不变
24+
25+
`detect_lang.py` 顶部 `from paths import ensure_user_path` 与 `from user_config import load_user_config, load_project_overrides, get_overrides`,并 `__all__` 暴露全部历史符号。已有 6 处 hooks + 1 处 `fix.py` + 1 处 `run_check.py` + `tests/run_all.py` 全部无需改动。
26+
27+
### 调用方注释化
28+
29+
每个 hook 的 `from detect_lang import ...` 行末尾加注释 `# 实际定义见 scripts/paths.py / user_config.py`,便于未来定位到正确文件。
30+
31+
### 不动锁与注册表
32+
33+
`scripts/languages.json` 与 `skills.lock.json` 不变;拆分是纯结构调整,不影响任何语言识别结果。
34+
35+
### 不下沉到插件本地技能
36+
37+
PATH / 用户配置是 Hook 必需的运行时环境,与「面向用户的技能」无关——下沉到 `skills/` 会让 import 路径变得奇怪且增加发现成本。
38+
39+
## Risks / Trade-offs
40+
41+
- **首次 import 多一层**:`ensure_user_path` 调用点不变,但 Python 解释器多解析一个小文件(<10ms),可忽略。
42+
- **`detect_lang.py` 顶端 re-export 列表易过期**:新增函数时若忘记在 `detect_lang.py` 加 re-export,hook 会立刻 ImportError——这是设计意图(fail-fast),但需在 PR review 时人工检查。
43+
- **测试夹具路径**:`tests/run_all.py` 用 `sys.path.insert(0, str(PLUGIN / "scripts"))`,新文件位置在同一目录,零改动。
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
## Why
2+
3+
`scripts/detect_lang.py`(401 行)当前承担三职责合一:① 进程 PATH 补齐(`ensure_user_path` + 内部 helper)、② 用户/项目级配置加载(`load_user_config` / `load_project_overrides` / `get_overrides`)、③ 语言注册表与命令表(其余)。code-review-graph 已记录 hooks↔scripts 高耦合告警(19 条 CALLS 边集中指向 `detect_lang.py`),三职责合一让新增/修改任意一条职责都会触发全部 hooks 的回归面。
4+
5+
## What Changes
6+
7+
- 新增 `scripts/paths.py`:仅含 `ensure_user_path(from_login_shell=False) -> None` 及其内部 helper;零业务依赖。
8+
- 新增 `scripts/user_config.py`:仅含 `load_user_config` / `load_project_overrides` / `get_overrides`;与 hooks/commands 共享。
9+
- `scripts/detect_lang.py` 改为 re-export 上述符号以保持外部 API 不变(`from detect_lang import ensure_user_path, load_user_config` 仍工作),同时删除实现正文。
10+
- 所有 hooks(`env_check.py` / `pre_tool_git_guard.py` / `post_tool_lint.py` / `user_prompt_validator.py` / `stop_summary.py`)继续走 `detect_lang` re-export;显式注释每个 import 来自哪个新文件,便于后续单独演进。
11+
12+
## Capabilities
13+
14+
### New Capabilities
15+
16+
- `language-gate-commands`: Defines the responsibility split between PATH handling, user configuration loading, and language detection command tables.
17+
18+
### Modified Capabilities
19+
20+
None.
21+
22+
## Impact
23+
24+
新增 2 个脚本文件(`scripts/paths.py` / `scripts/user_config.py`,预计合计 ~150 行);修改 `scripts/detect_lang.py`(约 400 行缩到 ~250 行,但保持 API);hooks 无外部行为变化,仅加注释。`scripts/languages.json` 与 OpenSpec 现有 `language-gate-commands` / `language-registry-doc-sync` 两个 spec 不变。code-review-graph 的 hooks↔scripts 跨社区边应从 19 降至 ≤4。
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
## ADDED Requirements
2+
3+
### Requirement: Process PATH enrichment SHALL live in scripts/paths.py
4+
5+
The function `ensure_user_path(from_login_shell: bool = False) -> None` SHALL be defined in `scripts/paths.py` and re-exported from `scripts/detect_lang.py` so existing call sites continue to work without modification.
6+
7+
#### Scenario: Hooks import ensure_user_path from detect_lang
8+
9+
- **WHEN** any hook script imports `ensure_user_path` from `scripts/detect_lang`
10+
- **THEN** the import resolves to the symbol defined in `scripts/paths.py` without behavioral change
11+
12+
#### Scenario: Direct import from scripts/paths
13+
14+
- **WHEN** a new script needs to enrich PATH without depending on language detection
15+
- **THEN** it can `from paths import ensure_user_path` with no other dependencies required
16+
17+
### Requirement: User configuration loading SHALL live in scripts/user_config.py
18+
19+
The functions `load_user_config`, `load_project_overrides`, and `get_overrides` SHALL be defined in `scripts/user_config.py` and re-exported from `scripts/detect_lang.py`.
20+
21+
#### Scenario: Hooks import load_user_config from detect_lang
22+
23+
- **WHEN** any hook script imports configuration helpers from `scripts/detect_lang`
24+
- **THEN** the import resolves to the symbol defined in `scripts/user_config.py`
25+
26+
### Requirement: scripts/detect_lang.py SHALL retain language-detection surface only
27+
28+
`scripts/detect_lang.py` SHALL expose only the language-detection and command-table API: `LANG_COMMANDS`, `detect_languages`, `detect_language`, `find_project_root`, `probe_toolchain`, `project_uses_linter`, `extract_tool_binaries`, and the internal `_load_registry`. It SHALL NOT define PATH enrichment or configuration helpers in its own body.
29+
30+
#### Scenario: Refactor introduces a third responsibility
31+
32+
- **WHEN** a new function in `scripts/detect_lang.py` mixes PATH handling, config loading, or other unrelated concerns with language detection
33+
- **THEN** the change SHALL be rejected because it violates the single-responsibility boundary
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
## 1. New files
2+
3+
- [ ] 1.1 Create `scripts/paths.py` with `ensure_user_path(from_login_shell=False)` plus its internal static-dir and node-availability helpers, copied verbatim from `scripts/detect_lang.py`.
4+
- [ ] 1.2 Create `scripts/user_config.py` with `load_user_config`, `load_project_overrides`, `get_overrides`, copied verbatim from `scripts/detect_lang.py`.
5+
6+
## 2. detect_lang.py refactor
7+
8+
- [ ] 2.1 Delete the implementation bodies of `ensure_user_path` and configuration helpers from `scripts/detect_lang.py`.
9+
- [ ] 2.2 Replace them with re-exports (`from paths import ensure_user_path`, `from user_config import load_user_config, load_project_overrides, get_overrides`) and add `__all__` enumerating all externally imported symbols (existing + new re-exports).
10+
11+
## 3. Hooks annotation
12+
13+
- [ ] 3.1 In each of `hooks/env_check.py`, `hooks/pre_tool_git_guard.py`, `hooks/post_tool_lint.py`, `hooks/user_prompt_validator.py`, append an inline comment to the existing `from detect_lang import ...` line noting the source file (`paths.py` or `user_config.py`).
14+
15+
## 4. Validation
16+
17+
- [ ] 4.1 Run `python3 tests/run_all.py` — all hook simulation, language-registry, unit, CVE, edges, and field-regression subsets must pass.
18+
- [ ] 4.2 Run `python3 -m unittest discover -s tests -p 'test_*.py' -v` — `test_plugin_manifests.py` and `test_skill_vendor.py` must pass (pre-existing baseline).
19+
- [ ] 4.3 Run `git diff --check` — must be clean.
20+
- [ ] 4.4 Run `openspec validate --all --strict` — must pass (3 pre-existing specs + new `language-gate-commands`).
21+
- [ ] 4.5 Run `ruff check scripts/paths.py scripts/user_config.py scripts/detect_lang.py hooks/` — zero lint issues.
22+
23+
## 5. Graph evidence
24+
25+
- [ ] 5.1 Rebuild `code-review-graph` and verify the cross-community edge count between `hooks-gate` and `scripts-scan` drops to ≤4 (was 19).
26+
27+
## 6. Release
28+
29+
- [ ] 6.1 `node scripts/bump-plugin.mjs codeguard patch` — bump 0.6.0 → 0.6.1.
30+
- [ ] 6.2 Commit plugin repo change, push `main` + tag `v0.6.1`.
31+
- [ ] 6.3 In `full-stack-plugins` market repo, sync catalog `codeguard` to `0.6.1` and regenerate three marketplace manifests; commit and push.
32+
- [ ] 6.4 `openspec archive add-detect-lang-splits` after all tasks above are checked.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
schema: spec-driven
2+
created: 2026-09-22

0 commit comments

Comments
 (0)