Skip to content

Commit aa8142c

Browse files
author
loong10k
committed
chore(openspec): 归档 fix-gate-trigger-and-mcp——任务全勾 + delta specs 并入主 specs
- tasks.md 组 7 全部勾选(7.1 手工补完四端+钉版;7.2 hub 链由 release: codeguard 0.7.0 落账;7.3 PR #21/#24 + tag dbc133a + Release; 7.4 archive 执行) - proposal 依赖声明更正为 mcp>=1.0,<2 - archive 移动 + openspec/specs 新增 gate-trigger-policy(+3)、mcp-tool-server(+4) - 校验:openspec strict 12/12、ruff clean、44/44 unittest、diff-check clean
1 parent 0e84186 commit aa8142c

9 files changed

Lines changed: 96 additions & 5 deletions

File tree

openspec/changes/2026-09-22-fix-gate-trigger-and-mcp/.openspec.yaml renamed to openspec/changes/archive/2026-09-22-fix-gate-trigger-and-mcp/.openspec.yaml

File renamed without changes.

openspec/changes/2026-09-22-fix-gate-trigger-and-mcp/README.md renamed to openspec/changes/archive/2026-09-22-fix-gate-trigger-and-mcp/README.md

File renamed without changes.

openspec/changes/2026-09-22-fix-gate-trigger-and-mcp/design.md renamed to openspec/changes/archive/2026-09-22-fix-gate-trigger-and-mcp/design.md

File renamed without changes.

openspec/changes/2026-09-22-fix-gate-trigger-and-mcp/proposal.md renamed to openspec/changes/archive/2026-09-22-fix-gate-trigger-and-mcp/proposal.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,5 @@ None.
2727

2828
- `hooks/user_prompt_validator.py`:触发判定与语言选择逻辑改动;外部行为变化仅在误触发场景(更少误触发为正向变化)。
2929
- `scripts/run_check.py`:新增官方 SDK 依赖(`mcp` 包需写入 `requirements.txt` 或类似清单),新增 `out/.codeguard-last.log` 落盘逻辑,删除占位 `mcp_main` 分支。
30-
- 新建根 `requirements.txt` 声明 `mcp>=1.0`(本仓当前没有任何 requirements 文件;`mcp` 1.26.0 已在开发环境安装,CI 需显式安装)。
30+
- 新建根 `requirements.txt` 声明 `mcp>=1.0,<2`(2.x 更改了装饰器 API;本仓此前无 requirements 文件,CI 显式安装)。
3131
- 不修改 vendored 技能(codeguard-* 走 vendor 流程);不修改 marketplace 清单。

openspec/changes/2026-09-22-fix-gate-trigger-and-mcp/specs/gate-trigger-policy/spec.md renamed to openspec/changes/archive/2026-09-22-fix-gate-trigger-and-mcp/specs/gate-trigger-policy/spec.md

File renamed without changes.

openspec/changes/2026-09-22-fix-gate-trigger-and-mcp/specs/mcp-tool-server/spec.md renamed to openspec/changes/archive/2026-09-22-fix-gate-trigger-and-mcp/specs/mcp-tool-server/spec.md

File renamed without changes.

openspec/changes/2026-09-22-fix-gate-trigger-and-mcp/tasks.md renamed to openspec/changes/archive/2026-09-22-fix-gate-trigger-and-mcp/tasks.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242

4343
## 7. Release
4444

45-
- [ ] 7.1 `node scripts/bump-plugin.mjs codeguard minor` (0.6.6 → 0.7.0; MCP server is a new feature).
46-
- [ ] 7.2 Sync marketplace manifest + hub catalog.
47-
- [ ] 7.3 Push, confirm CI green, tag v0.7.0, GitHub Release.
48-
- [ ] 7.4 `openspec archive 2026-09-22-fix-gate-trigger-and-mcp`.
45+
- [x] 7.1 Bump minor 0.6.8 → 0.7.0 (MCP server is a new feature; worktree depth broke the hub resolver so manifests were completed manually: 4 manifests + marketplace ref/icon/logo pins + README rows).
46+
- [x] 7.2 Sync marketplace manifest + hub catalog (repo pins v0.7.0; hub chain landed as `release: codeguard 0.7.0` + README row alignment).
47+
- [x] 7.3 Push, confirm CI green (PR #21 feature, PR #24 release), tag v0.7.0 at dbc133a, GitHub Release published (README row follow-up at main 0e84186).
48+
- [x] 7.4 `openspec archive 2026-09-22-fix-gate-trigger-and-mcp`(delta specs 已并入 openspec/specs:gate-trigger-policy +3、mcp-tool-server +4)。
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# gate-trigger-policy Specification
2+
3+
## Purpose
4+
TBD - created by archiving change 2026-09-22-fix-gate-trigger-and-mcp. Update Purpose after archive.
5+
## Requirements
6+
### Requirement: The UserPromptSubmit hook SHALL run the lint gate only when intent is commit-like
7+
The `UserPromptSubmit` hook MUST evaluate the user's prompt for commit intent using word-boundary matching of trigger words (`commit|push|deploy|发布|部署`) and a separate action-verb check. The hook SHALL exit silently when either (a) no trigger word is present, (b) the only trigger occurrence is followed by `?`, or (c) a trigger word appears in an interrogative sentence identified by `QUESTION_MARKERS` (`?`, `?`, `么`, `吗`, `如何`, `怎么`, `有没有`, `是不是`, `什么是`, `哪些`).
8+
9+
#### Scenario: User asks a question containing a trigger word
10+
11+
- **WHEN** the user prompt is `使用过程中的情况` or `Should I commit this?` or `先读项目结构`
12+
- **THEN** the hook exits 0 with empty stdout; no linter runs
13+
14+
#### Scenario: User issues a commit-like imperative
15+
16+
- **WHEN** the user prompt is `请帮我 commit` or `commit this now` or `请帮我 push`
17+
- **THEN** the hook enters the gate path and invokes `run_gate()`
18+
19+
#### Scenario: Trigger word followed by question mark is exempt
20+
21+
- **WHEN** the user prompt is `commit?` or `要不要 push?` or `should I deploy?`
22+
- **THEN** the hook exits silently regardless of other QUESTION_MARKERS content
23+
24+
### Requirement: The gate SHALL run only languages named in the user message when they can be identified
25+
When the trigger fires, the hook MUST extract candidate language ids from the user prompt using case-insensitive token matching against `scripts/languages.json` ids. When the intersection is non-empty, the gate SHALL run only that subset. When the intersection is empty, the gate SHALL fall back to the existing `detect_languages()` behavior.
26+
27+
#### Scenario: User mentions one language explicitly
28+
29+
- **WHEN** the user prompt is `请帮我 commit 这次 ruff 改动`
30+
- **THEN** the gate runs only Python; other detected languages are skipped for this invocation
31+
32+
#### Scenario: User mentions no language
33+
34+
- **WHEN** the user prompt is `请帮我 commit` with no language token
35+
- **THEN** the gate runs every language detected by `detect_languages()` (current behavior preserved)
36+
37+
### Requirement: Question markers SHALL cover both Chinese and English
38+
`QUESTION_MARKERS` MUST include the ASCII `?` in addition to the existing Chinese markers, so that an English prompt ending with `?` is recognized as a question even without other markers.
39+
40+
#### Scenario: ASCII question mark without any other marker
41+
42+
- **WHEN** the user prompt is `Should I push this?`
43+
- **THEN** the hook exits silently because `?` is a recognized question marker
44+
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# mcp-tool-server Specification
2+
3+
## Purpose
4+
TBD - created by archiving change 2026-09-22-fix-gate-trigger-and-mcp. Update Purpose after archive.
5+
## Requirements
6+
### Requirement: The MCP server SHALL expose three tools over stdio JSON-RPC
7+
`scripts/run_check.py --mcp` MUST start an stdio JSON-RPC server using the official `mcp` Python SDK and register exactly three tools: `check_code_style`, `auto_fix`, and `list_languages`. The server MUST NOT take any other CLI flag in MCP mode.
8+
9+
#### Scenario: Listing tools at startup
10+
11+
- **WHEN** a client sends `tools/list`
12+
- **THEN** the response enumerates `check_code_style`, `auto_fix`, `list_languages` with their input schemas
13+
14+
### Requirement: `check_code_style` SHALL return a structured envelope with full stderr on disk
15+
`check_code_style(path, languages?)` MUST run the configured linters, write the full stderr of any failing invocation to `<log_dir>/.codeguard-last.log` (default `<project>/out/.codeguard-last.log`), and return a JSON envelope with one entry per language: `{language, passed: bool, exit_code: int, stderr_path: str, log_path: str}`.
16+
17+
#### Scenario: One language fails
18+
19+
- **WHEN** the path contains a single Python project whose ruff lint fails
20+
- **THEN** the envelope contains one entry with `passed=false`, `exit_code` from ruff, `stderr_path` pointing at the on-disk log, and `log_path` echoing the same path
21+
22+
#### Scenario: All languages pass
23+
24+
- **WHEN** every linter exits 0
25+
- **THEN** every entry has `passed=true`, `exit_code=0`, and the log file is either empty or absent (no stderr written)
26+
27+
### Requirement: `auto_fix` SHALL run formatters and re-verify
28+
`auto_fix(path, languages?)` MUST invoke the per-language formatter chain (`format` from `scripts/languages.json`) and then re-run `check_code_style` on the same scope before returning. The response envelope MUST contain both `fixed: bool` (whether any file was modified) and the `check_code_style` envelope for the post-fix re-check.
29+
30+
#### Scenario: Formatter succeeds and lint passes
31+
32+
- **WHEN** ruff `--fix` removes unused imports and the re-check passes
33+
- **THEN** `fixed=true` and the embedded `check_code_style` envelope is all-pass
34+
35+
#### Scenario: Formatter succeeds but lint still fails
36+
37+
- **WHEN** ruff `--fix` ran but a remaining error is non-fixable
38+
- **THEN** `fixed=true` and the embedded `check_code_style` envelope contains at least one failing entry
39+
40+
### Requirement: `list_languages` SHALL return id + name only
41+
`list_languages()` MUST return a JSON array of `{id, name}` objects from `scripts/languages.json`, omitting the rest of each language record (lint command, format command, install hint, etc.) so internal commands are not exposed as part of the MCP surface.
42+
43+
#### Scenario: Listing all supported languages
44+
45+
- **WHEN** the client calls `list_languages`
46+
- **THEN** the response enumerates every entry in `scripts/languages.json` with exactly two fields (`id`, `name`) per record
47+

0 commit comments

Comments
 (0)