Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .agents/plugins/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,20 @@
"source": {
"source": "url",
"url": "https://github.com/partme-ai/partme-codeguard-plugin.git",
"ref": "v0.14.0"
"ref": "v0.14.1"
},
"policy": {
"installation": "AVAILABLE",
"authentication": "ON_USE"
},
"category": "Developer Tools",
"version": "0.14.0",
"version": "0.14.1",
"description": "Evidence-backed code checks and Git content gates for AI assistants, with Maven/Gradle module impact analysis. Save hooks provide feedback; unverified checks are explicit.",
"icon": "https://cdn.jsdelivr.net/gh/full-stack-plugins/codeguard-plugin@v0.14.0/assets/official-logo.png",
"icon": "https://cdn.jsdelivr.net/gh/full-stack-plugins/codeguard-plugin@v0.14.1/assets/official-logo.png",
"interface": {
"displayName": "代码规范守卫",
"shortDescription": "Trustworthy code checks and Java impact analysis",
"logo": "https://cdn.jsdelivr.net/gh/full-stack-plugins/codeguard-plugin@v0.14.0/assets/official-logo.png"
"logo": "https://cdn.jsdelivr.net/gh/full-stack-plugins/codeguard-plugin@v0.14.1/assets/official-logo.png"
}
}
]
Expand Down
2 changes: 1 addition & 1 deletion .codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "codeguard",
"version": "0.14.0+codex.20260923",
"version": "0.14.1+codex.20260923",
"description": "Evidence-backed code checks and Git content gates for AI assistants, with Maven/Gradle module impact analysis. Save hooks provide feedback; unverified checks are explicit.",
"author": {
"name": "Full Stack Skills / PartMe.AI",
Expand Down
2 changes: 1 addition & 1 deletion .zcode-plugin/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"en": "CodeGuard",
"zh-CN": "代码规范检查"
},
"version": "0.14.0",
"version": "0.14.1",
"description": "Evidence-backed code checks and Git content gates for AI assistants, with Maven/Gradle module impact analysis. Save hooks provide feedback; unverified checks are explicit.",
"description_i18n": {
"en": "Evidence-backed code checks and Git content gates for AI assistants, with Maven/Gradle module impact analysis. Save hooks provide feedback; unverified checks are explicit.",
Expand Down
4 changes: 2 additions & 2 deletions docs/current-architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ flowchart TD
| `bin/codeguard`、`scripts/run_check.py`、`scripts/fix.py` | CLI 参数、输出与 MCP stdio 注册 | 不复制扫描器或判定逻辑 |
| `hooks/` | 宿主 JSON、会话事件、通知与退出协议 | 五类 Hook 将检查编排委托应用服务;入口保留旧导入兼容面及 fail-open 协议 |
| `scripts/codeguard/check_application.py`、`language_check.py` | 语言选择、检查与修复请求、MCP 工具分发 | 不导入 MCP SDK;旧 `run_per_language.py` 仅再导出 |
| `startup_application.py`、`session_application.py`、`prompt_application.py`、`git_guard_application.py`、`save_application.py` | 五类 Hook 的盘点、状态消费、软提示、Git 守卫及保存反馈编排 | 返回结构化结果,不打印或调用宿主通知;Hook 控制输出、通知与 fail-open。软/硬提示与保存统计在成功输出后确认;Stop 的状态消费仍先于 stdout,输出故障时可能丢失总结 |
| `gate.py`、`gate_checks.py`、`repository_policy.py`、`baseline.py` | Git 门禁、单语言结果、安全规则及有证据的存量比较 | 只有准确基线失败且每条诊断及次数覆盖当前结果才可豁免 |
| `startup_application.py`、`session_application.py`、`prompt_application.py`、`git_guard_application.py`、`save_application.py` | 五类 Hook 的盘点、状态消费、软提示、Git 守卫及保存反馈编排 | 返回结构化结果,不打印或调用宿主通知;Hook 控制输出、通知与 fail-open。Stop 在 stdout 刷新后才确认消费;若同时有新统计,为避免丢记录,后续 Stop 可能重复展示旧统计 |
| `gate.py`、`gate_checks.py`、`repository_policy.py`、`baseline.py` | Git 门禁、单语言结果、安全规则及有证据的存量比较 | 只有准确基线失败且逐条诊断的文件归属、内容及次数覆盖当前结果才可豁免;基线临时路径映射回被检查文件 |
| `java_build.py`、`java_impact.py`、`java_planning.py` 等 | 构建读取、纯影响闭包、命令选择与环境观察 | 默认保留跳过测试的行为;复杂构建保守扩大检查范围 |
| `cve_reports.py`、`cve_policy.py`、`cve_scanners.py`、`cve.py` | 漏洞报告、阈值、进程适配与复扫编排 | 无有效结构化报告就没有安全通过结论 |
| `dockerfile_reports.py`、`dockerfile.py` | hadolint/Trivy 结构化证据与逐文件扫描 | `dockerfile_security.py` 只解析参数和呈现报告 |
Expand Down
5 changes: 4 additions & 1 deletion hooks/stop_summary.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,11 @@ def main(payload: dict | None = None) -> int:


def _main(payload: dict | None = None) -> int:
for line in session_application.consume_summary(LEGACY_STATE_FILE, Path.cwd()):
prepared = session_application.prepare_summary(LEGACY_STATE_FILE, Path.cwd())
for line in prepared.lines:
print(line)
sys.stdout.flush()
prepared.acknowledge()
return 0


Expand Down
2 changes: 1 addition & 1 deletion kimi.plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "codeguard",
"version": "0.14.0",
"version": "0.14.1",
"description": "Evidence-backed code checks and Git content gates for AI assistants, with Maven/Gradle module impact analysis. Save hooks provide feedback; unverified checks are explicit.",
"author": {
"name": "Full Stack Skills / PartMe.AI"
Expand Down
13 changes: 10 additions & 3 deletions openspec/changes/refactor-codeguard-architecture/design.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,13 @@ flowchart TD

`storage` 只提供带进程锁的原子读改写、消费和有界 JSONL;`hook_state` 保存归属与业务字段,
hooks 只负责取得 payload、进入会话作用域和输出。使用稳定旁路锁文件,避免替换数据 inode 后
两个进程各锁不同文件。统计、冷却和绕过明细使用同一事务边界;Stop 原子取出当前作用域,
不会再在输出后删除另一进程刚写入的计数。无 session_id 继续旧共享状态,明确不保证会话隔离。
两个进程各锁不同文件。统计、冷却和绕过明细使用同一事务边界;Stop 只处理当前作用域,
不会在确认输出后删除另一进程刚写入的计数。无 session_id 继续旧共享状态,明确不保证会话隔离。

Stop 的宿主入口先准备原子可读的状态快照,成功写入并刷新 stdout 后,在同一旁路锁内仅当状态
仍等于该快照时删除。输出失败保留统计供重试;并发新写入时保留整份状态而不冒险相减,
后续 Stop 可能重复展示旧统计,但不会丢掉未展示的新统计。旧直接消费接口继续兼容,
不用于宿主 Stop 交付路径。

事件去重不等于权限缓存。观察 Hook 成功返回后才登记完成,异常允许重试;UPS 有 skipped 时
保守地不登记。硬门禁只重放已完成拒绝,放行、未验证和执行中一律不复用;并发副本允许
Expand Down Expand Up @@ -129,7 +134,9 @@ flowchart TD

这不仅改变文件位置:并发 worker 不再共享备注列表,也不依赖 ContextVar 隐式跨线程传播;审计在
调用线程记录原 worktree、实际 execution_root 与 argv。基线工具或当前结果为未知时不进入豁免,
避免文本相似覆盖执行失败。Java 原有项目感知计划继续复用,详细解析/规划分离留到 task 3.4。
避免文本相似覆盖执行失败。逐条基线诊断比较保留文件归属、描述与出现次数,只忽略同文件的
行列号漂移;基线临时文件路径映射回原仓相对路径,不得用另一文件的同文本违规抵扣当前文件。
Java 原有项目感知计划继续复用,详细解析/规划分离留到 task 3.4。

迁移测试时发现旧 fixture 修改模块全局函数且不恢复,造成后续语言检测污染;改为显式语言参数和
有作用域的注册表覆盖。低层 timeout 故障仍在实际进程边界注入。真实替换测试还暴露了 scope 对
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
### Requirement: Hook state SHALL preserve concurrent and session ownership

统计、绕过明细、冷却与审计的读改写 MUST 在进程锁内完成并原子替换文件。宿主提供 session_id 时,统计 MUST 绑定会话与当前 worktree;Stop MUST 只消费该作用域的记录,并与并发写入互斥。无 session_id 时保留旧共享状态兼容,MUST 明示不能证明跨会话隔离。去重 MUST NOT 把未完成或 UNVERIFIED 的检查当成已完成检查。
Stop MUST 在宿主输出成功刷新后才确认消费;输出失败时记录必须保留供重试。若确认前有并发新写入,允许后续 Stop 重复展示旧统计,但不得删除未展示的新记录。

#### Scenario: Concurrent writers preserve all increments
- **WHEN** 多个 Hook 进程同时更新同一统计、绕过记录或审计日志
Expand All @@ -70,6 +71,10 @@
- **WHEN** 两个会话或两个 worktree 同时有检查记录,其中一个收到 Stop
- **THEN** 只汇总并清理当前作用域,其余记录保持可供各自 Stop 消费

#### Scenario: Stop output fails or state changes during delivery
- **WHEN** Stop 已准备总结但宿主 stdout 写入或刷新失败,或在输出期间有新统计写入
- **THEN** 输出失败时旧统计可在重试中再次展示;并发新统计不得被确认消费误删,允许为了不丢记录而在后续 Stop 重复展示旧统计

#### Scenario: Retry follows an unverified save check
- **WHEN** 相同文件未变化,上次保存检查未能获得结论,紧接着再次触发
- **THEN** 再次执行检查,不因此前写入的去重标记而静默跳过
Expand All @@ -93,7 +98,7 @@
### Requirement: Gate application SHALL separate checks from host presentation

门禁应用 MUST 不依赖 hooks 导入或宿主 SDK。单个语言检查 MUST 返回独立结果,汇总 MUST 保持输入顺序,不用共享可变备注列表连接并发检查。准确快照的审计 MUST 保留原 worktree 和会话归属,实际执行目录只作为执行上下文,不冒充项目身份。基线比较遇到未验证工具结果 MUST NOT 产生存量豁免。
基线豁免 MUST 比较逐条诊断内容及出现次数,且基线检查器本身 MUST 确认失败;规则码集合或仅有文本输出不足以证明当前发现已存在。
基线豁免 MUST 比较逐条诊断内容、出现次数及可识别的文件归属,且基线检查器本身 MUST 确认失败;规则码集合或仅有文本输出不足以证明当前发现已存在。基线临时文件路径可以映射回被检查的仓库相对路径,行列号移动不应单独取消同文件的存量豁免;不同文件的同文本诊断不得互相抵扣。

#### Scenario: Exact snapshot audit retains ownership
- **WHEN** 带会话 ID 的提交门禁从临时 Git 快照执行检查
Expand All @@ -107,6 +112,10 @@
- **WHEN** 基线检查器返回成功码却打印诊断、同一规则新增第二处违规,或规则码相同但诊断内容变化
- **THEN** 当前违规不得获得存量豁免;只有基线自身确认失败且逐条诊断及出现次数覆盖当前结果时才能豁免

#### Scenario: Identical diagnostics belong to different files
- **WHEN** 当前输出将同一规则和描述归于另一文件,而基线输出归于被检查文件;或者 ShellCheck 的 `In <file> line N` 段属于另一文件
- **THEN** 不得以文本相同授予存量豁免;被检查文件自身仅行列号变化时仍可保留有证据的旧发现豁免

### Requirement: Language services SHALL have explicit input and lifetime

语言注册表 MUST 由同一校验逻辑验证后派生识别与命令表,非法形状和重复 ID 不得静默覆盖。
Expand Down
2 changes: 1 addition & 1 deletion openspec/changes/refactor-codeguard-architecture/tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,5 @@
- [x] 5.2 四个历史 skipped 已全部恢复;Dockerfile CLI 接入统一报告解析与扫描应用,14 项真实进程边界测试通过;基线比较按诊断内容和次数核验并要求基线实际 FAIL,三项误豁免用例先红后绿。完整 433 项单测零跳过、142 项回归零失败。
- [x] 5.3 新增当前架构 Mermaid 与扩展指南;报告版本读取插件 manifest,双语 README 指向当前证据,旧设计标明历史范围;双语标题/链接/版本及本地链接存在性测试通过。发布版本仍需在 5.5 检查。
- [ ] 5.4 全量单测/真实 hook 回归/ruff/语言 schema/vendor 离线与在线/本 change strict 和逐条规格追溯通过。
- [ ] 5.5 按仓规升级版本、生成市场元数据、授权的 PR/CI/不可变 tag/Release 闭环;v0.13.0 阶段版本已完成插件/市场双仓合并、PR/main CI、tag/Release,但后续工作树改动仍未发布。宿主安装运行独立记录,未授权不得改宿主。
- [ ] 5.5 按仓规升级版本、生成市场元数据、授权的 PR/CI/不可变 tag/Release 闭环;v0.14.0 阶段版本已完成插件/市场双仓合并、PR/main CI、tag/Release,但后续工作树改动仍未发布。宿主安装运行独立记录,未授权不得改宿主。
- [ ] 5.6 完成全目标审计,代码/规格/证据一致后同步并归档 change,才可将整体优化标记完成。
Original file line number Diff line number Diff line change
Expand Up @@ -162,3 +162,11 @@
- 临时 CodeGraph 快照重新同步了本批改动并追踪三个新应用服务的 Hook 调用点;源仓未初始化索引。`scripts/check_architecture.py` 声明并约束新内核模块,隔离导入测试阻止其反向加载宿主 Hook/MCP。
- 使用本机已有、带 MCP SDK 的 `/opt/anaconda3/bin/python3` 3.13.5 完整执行 **454 unittest,全部通过、0 skipped**;`tests/run_all.py` **142/0/0**。Homebrew Python 3.14 缺 MCP SDK 时同一套测试仅执行 451 项、跳过 3 项,故不将该运行作为完整证明。ruff、架构门禁、语言 schema 57 项/11 规则、vendor 离线与在线、本 change strict、diff whitespace 通过;技能 lock 和受管技能未改。
- 本地入口边界已满足 task 4.3。Stop 会先消费会话状态再输出,若 stdout 故障可能丢失该次总结;三宿主安装现场、Windows、联网漏洞库及所有语言真实工具链仍待独立验收。本批源码在本记录时仍未 bump/提交/推送/发布,不把 v0.13.0 的远端证据套用到新改动。

## 第十五批实际验证:诊断归属与 Stop 交付确认

- v0.14.0 已经插件 PR #46、市场 PR #2/#3 合并到两个 `main`;插件 PR 和合并后 `main` 的 `skills-check` 通过,不可变 tag/Release 指向插件合并提交 `0e699b85b0cb3abaf6a248e04121ecae152ba508`,市场三宿主清单及中英文导航均为 0.14.0。该发布证据只覆盖上一批代码,本批源码尚未发布。
- 临时 CodeGraph 索引同步后追出 `check_language → baseline_stale_finding → finding_instances`;原提取器剥掉文件位置。两项真实 Git/检查器测试先 RED:其它文件的同文本 `F401` 与 ShellCheck `In <file> line N` 诊断均被误豁免。现在比较文件归属、描述、出现次数,把基线临时路径映射回原仓相对路径;同文件只移动行号仍允许有证据的豁免。CodeGraph 的受影响测试映射返回空,故以实际源码调用和目标测试作为覆盖证据,不将空映射当无测试。
- Stop 原逻辑在输出前 `take_json`,故故障注入先 RED:stdout 写入失败时会话记录已被删除。现新增准备结果和输出后确认;写入或刷新失败时记录保留可重试。若准备后有并发新写入,锁内快照不一致就不消费,允许下一次重复展示旧统计而不删除新记录。旧 `consume_summary` 兼容接口保留,Hook 改用 `prepare_summary`。两种输出故障和并发写入均有目标测试。
- 本机现有 `/opt/anaconda3/bin/python3` 3.13.5 完整执行 **460 unittest,全部通过、0 skipped**;`tests/run_all.py` **142/0/0**。ruff、架构门禁、语言 schema 57 项/11 规则、vendor 离线与在线、本 change strict、diff whitespace 均通过;受管技能及 lock 未改。上述为本地证据,远端 CI/版本/市场需在本批发布后另验。
- 这两处消除了已复现的假豁免与输出前丢总结;仍不声称完整 Shell 解释、三宿主现场、Windows、在线漏洞库、全部工具链或 OpenSpec 5.4/5.6 的全目标审计完成。stdout 刷新成功不等于宿主最终消费确认,因此异常重试可出现重复总结;该取舍优先保证不丢统计。
6 changes: 4 additions & 2 deletions scripts/check_architecture.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
"codeguard.execution"},
"codeguard": {"__future__"},
"codeguard.models": {"__future__", "dataclasses", "pathlib", "typing"},
"codeguard.verdict": {"__future__", "re", "collections", "pathlib", "codeguard.models"},
"codeguard.verdict": {"__future__", "re", "posixpath", "collections", "collections.abc",
"pathlib", "codeguard.models"},
"codeguard.execution": {"__future__", "os", "subprocess", "collections", "pathlib", "codeguard.models"},
# 报告当前仍拥有诊断日志落盘;不将其误称为无 IO 的纯模型。
"codeguard.reporting": {"__future__", "re", "json", "pathlib", "hashlib", "tempfile",
Expand Down Expand Up @@ -57,7 +58,8 @@
"codeguard.check_application": {"__future__", "pathlib", "scope", "codeguard.config",
"codeguard.discovery", "codeguard.java_analysis",
"codeguard.language_check", "codeguard.registry"},
"codeguard.session_application": {"__future__", "pathlib", "codeguard.execution",
"codeguard.session_application": {"__future__", "collections.abc", "dataclasses", "pathlib",
"codeguard.execution",
"codeguard.hook_state", "codeguard.repository_policy",
"codeguard.storage"},
"codeguard.startup_application": {"__future__", "re", "dataclasses", "pathlib",
Expand Down
8 changes: 6 additions & 2 deletions scripts/codeguard/baseline.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,9 @@ def baseline_stale_finding(
pre = _git(project_root, "show", f"{baseline_ref}:{rel_path}")
if pre is None:
return None
new_sigs = finding_instances(output)
canonical = Path(rel_path).as_posix()
current_aliases = {canonical: canonical, str(project_root / rel_path): canonical}
new_sigs = finding_instances(output, path_aliases=current_aliases)
if not new_sigs:
return None
import tempfile as _tf
Expand All @@ -99,7 +101,9 @@ def baseline_stale_finding(
proc = execute(cmd, project_root, timeout)
if lint_verdict(proc.returncode, cmd, proc.stdout + proc.stderr)[0] != FAIL:
return None
base_sigs = finding_instances((proc.stdout or "") + (proc.stderr or ""))
baseline_aliases = {str(tmp): canonical, tmp.name: canonical}
base_sigs = finding_instances((proc.stdout or "") + (proc.stderr or ""),
path_aliases=baseline_aliases)
if not base_sigs:
return None
return ("存量问题(基线同命令同工具已存在)" if
Expand Down
Loading
Loading