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.8"
"ref": "v0.14.9"
},
"policy": {
"installation": "AVAILABLE",
"authentication": "ON_USE"
},
"category": "Developer Tools",
"version": "0.14.8",
"version": "0.14.9",
"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.8/assets/official-logo.png",
"icon": "https://cdn.jsdelivr.net/gh/full-stack-plugins/codeguard-plugin@v0.14.9/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.8/assets/official-logo.png"
"logo": "https://cdn.jsdelivr.net/gh/full-stack-plugins/codeguard-plugin@v0.14.9/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.8+codex.20260923",
"version": "0.14.9+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.8",
"version": "0.14.9",
"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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ python3 scripts/run_check.py --mcp /path/to/project
| list_languages | Registry ids and display names |
| analyze_java_impact | Read-only plan; accepts path and optional changed array |

Output logs default to <project>/out/.codeguard-last.log; CLI --quiet disables log writing. A failed multi-command check logs output from every executed check. Diagnostic logs are replaced atomically with owner-only file permissions on POSIX; a symlinked output directory disables log writing without changing the check verdict. The MCP execution trace reports phase, sequence, program, exit/failure and output lengths; it does not echo argv, environment overrides or captured output. Local logs can contain sensitive checker output: keep them out of version control. MCP auto_fix does not write when a Git scope cannot be established.
Output logs default to <project>/out/.codeguard-last.log; CLI --quiet disables log writing. A failed multi-command check logs output from every executed check. Diagnostic logs are replaced atomically with owner-only file permissions on POSIX; a symlinked output directory disables log writing without changing the check verdict. The MCP execution trace reports phase, sequence, program, exit/failure and output lengths; it does not echo argv, environment overrides or captured output. MCP auto_fix also keeps formatter argv/stderr out of its JSON result; available formatter diagnostics are written to a private <project>/out/.codeguard-fix.log and returned by path. Local logs can contain sensitive checker output: keep them out of version control. MCP auto_fix does not write when a Git scope cannot be established.

## Configuration and coverage

Expand Down
2 changes: 1 addition & 1 deletion README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ python3 scripts/run_check.py --mcp /path/to/project
| list_languages | 注册表语言标识和名称 |
| analyze_java_impact | 只读计划,接受 path 和可选 changed 数组 |

日志默认在 <project>/out/.codeguard-last.log;CLI --quiet 关闭写日志。多命令检查失败时,日志保存每条已执行检查的完整输出。诊断日志以原子替换写入,POSIX 上仅当前用户可读写;输出目录是符号链接时不写日志,但检查结论不变。MCP 执行轨迹只返回阶段、序号、程序名、退出/故障及输出长度,不回显 argv、环境覆盖或检查器输出。本地日志可能含敏感文本,应排除出版本控制。MCP auto_fix 无法确定 Git 范围时不会写入。
日志默认在 <project>/out/.codeguard-last.log;CLI --quiet 关闭写日志。多命令检查失败时,日志保存每条已执行检查的完整输出。诊断日志以原子替换写入,POSIX 上仅当前用户可读写;输出目录是符号链接时不写日志,但检查结论不变。MCP 执行轨迹只返回阶段、序号、程序名、退出/故障及输出长度,不回显 argv、环境覆盖或检查器输出。MCP auto_fix 的 JSON 结果也不回显 formatter 原始参数或 stderr;可用的修复诊断写到私有 <project>/out/.codeguard-fix.log 并返回路径。本地日志可能含敏感文本,应排除出版本控制。MCP auto_fix 无法确定 Git 范围时不会写入。

## 配置与覆盖

Expand Down
6 changes: 3 additions & 3 deletions docs/current-architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ flowchart TD
```

`execution` 只记录进程证据,不把非零退出自动认定为代码违规。`verdict`、CVE 与 Dockerfile 报告解析决定 PASS、FAIL 或 UNVERIFIED;入口仅按各自协议呈现和聚合退出码。Git 提交检查使用 index 或预测暂存快照,推送检查使用 HEAD;保存钩子只给反馈。计划、未执行和未验证不能宣传为通过。
`language_check` 将 `PlanExecution` 的实际命令依序映射为应用层有界 `execution_trace`(检查、修复、复检阶段);`check_application` 将其进一步压成 MCP 安全元数据,不回显原始 argv、环境覆盖或捕获输出。失败日志保留各已执行检查的完整输出,可能含敏感文本,应排除出版本控制。项目日志和门禁截断日志共用 `storage.write_private_text` 的私有原子落盘;预置日志文件链接不被跟随,默认 `out` 目录为链接或不可写时不返回虚假日志路径,也不覆盖检查结论。终止命令仍决定既有状态、退出码和旧字段;未运行的计划命令不进入证据。
`language_check` 将 `PlanExecution` 的实际命令依序映射为应用层有界 `execution_trace`(检查、修复、复检阶段);`check_application` 将其进一步压成 MCP 安全元数据,不回显原始 argv、环境覆盖或捕获输出。`auto_fix` 的 `fix_results` 也只公开状态与安全元数据;formatter stderr 尾部写入私有 `.codeguard-fix.log` 后只公开路径,日志不可用时不退回公开原文。失败日志保留各已执行检查的完整输出,可能含敏感文本,应排除出版本控制。项目日志和门禁截断日志共用 `storage.write_private_text` 的私有原子落盘;预置日志文件链接不被跟随,默认 `out` 目录为链接或不可写时不返回虚假日志路径,也不覆盖检查结论。终止命令仍决定既有状态、退出码和旧字段;未运行的计划命令不进入证据。
Git 命令的仓库定位与拟暂存解析共用入口传入的 cwd;显式 `cd`/`git -C` 无法绑定 Git 工作树时,硬门禁给出目标未验证并阻断,不退回到调用者仓或无关子仓。未给出显式目标且调用目录非仓时仍保留 workspace 子仓兜底。静态命令解析不等于完整 Shell 执行模拟。
一条命令链中的 Git 副作用先绑定为仓库与操作的有序对,再按仓库聚合检查面:纯 push 不读取该仓未提交的 index,同仓 commit→push 则保留已有 HEAD 与拟提交内容的并集。仓库级、内联及链式 `skipGate` 均按目标仓与操作顺序生效;已存在的仓库配置也可被同链先行 `git config --unset` 取消。链式设置跨 `||`、`;` 或换行时无法证明生效,门禁要求拆分命令;写入其它文件的 config 设置也不构成本仓豁免。语法、仓库归属、间接脚本与拟暂存分析共用引号/转义感知切分;参数文本中的控制符不能合成豁免。解析能力仍限于受支持的静态 Shell 形态。
一层 `bash`/`sh`/`zsh` 的 `-c`(含组合短选项)及可读脚本现在携带调用目录与正文进入同一 Git 操作计划;脚本内的 `git add` 可进入拟暂存范围,外层和内层 Git 操作按仓分别检查。识别到无法建模的间接 Git 操作、脚本内 `skipGate` 配置变更或跨解释器的暂存/提交关系时,明确以 Git 意图 UNVERIFIED 阻断,不借用调用者仓的检查结果。动态脚本、任意控制流及 Python/Node 中构造的 subprocess 仍未建模。
Expand All @@ -39,9 +39,9 @@ Git 命令的仓库定位与拟暂存解析共用入口传入的 cwd;显式 `c
|---|---|---|
| `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` 仅再导出 |
| `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 刷新后确认状态;Git 已知拦截在输出故障时仍拦截但不缓存。并发或交付重试可能重复反馈,不得丢掉未交付记录 |
| `gate.py`、`gate_checks.py`、`repository_policy.py`、`baseline.py` | Git 门禁、单语言结果、安全规则及有证据的存量比较 | 只有准确基线失败且逐条诊断的文件归属、内容及次数覆盖当前结果才可豁免;基线临时路径映射回被检查文件 |
| `gate.py`、`gate_checks.py`、`repository_policy.py`、`baseline.py` | Git 门禁、单语言结果、安全规则及有证据的存量比较 | 单个语言 worker 异常只标该语言 UNVERIFIED,保留其它结论;安全路径快照失败明确报告未验证,不能抹掉已确认拦截。只有准确基线失败且逐条诊断的文件归属、内容及次数覆盖当前结果才可豁免 |
| `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
3 changes: 3 additions & 0 deletions hooks/__protocol__.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@ if __name__ == "__main__":

**禁止**因工具未装、项目未接入、检查超时等 UNVERIFIED 状态 exit 2;保留 fail-open,
但 MUST 明确未验证,不能输出“全部通过”。没有适用改动是 SKIPPED,不等于工具故障。
单个并行语言检查出现内部异常时,只将该语言标为 UNVERIFIED,其余语言的已知失败仍拦截。
Git 安全路径观察无法读取拟入库路径时,以 JSON additionalContext 说明未验证;若已有已知失败,
该失败仍 exit 2,不能因后续安全观察故障被顶层 fail-open 清空。
退出码按工具解释,不能全局把 2 当崩溃(例如 pylint 的 2 是违规)。
**取消无基线存量归因**:报错在未修改文件上也可能是本次 API 变化造成的,不能凭路径放行。

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.8",
"version": "0.14.9",
"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
15 changes: 10 additions & 5 deletions openspec/changes/refactor-codeguard-architecture/design.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ flowchart TD

不可变执行结果记录 argv、cwd、退出码、stdout、stderr、启动/超时故障。执行器不把 rc=1 判断成代码违规、不跑安装、不隐式 shell。`lint_verdict` 和 CVE 报告解析负责各工具语义。保留旧 tuple 包装以兼容已有消费者,但真实执行逻辑仅一份。

超时保留部分输出;使用 UTF-8 替换无法解码的字节,防止 decode error 把整个门禁变成未知异常。缺命令=127、超时=124、其他启动 OS 错误=126;与已有 UNVERIFIED 语义一致。非预期程序错误仍向上暴露,不能用 except Exception 将开发缺陷吞成正常结果。
超时保留部分输出;使用 UTF-8 替换无法解码的字节,防止 decode error 把整个门禁变成未知异常。缺命令=127、超时=124、其他启动 OS 错误=126;与已有 UNVERIFIED 语义一致。执行器不将非预期程序错误吞成正常进程结果;并行门禁在每个语言任务的应用边界把未预期异常显式标为 UNVERIFIED,继续保留其它语言已确认的结论,且不把异常原文注入宿主。

### 3. 策略差异必须显式,不能强行拉平

Expand All @@ -68,6 +68,8 @@ flowchart TD

本轮审计发现 CLI/MCP 与 Git 门禁均直接写原始诊断日志:前者位于项目 `out`,后者使用可预测的临时文件名。保留各自的日志路径和呈现职责,但由 `storage` 的统一私有原子文本写入负责落盘;应用不得再用普通 `write_text` 跟随预置链接或留下默认可读权限。日志故障只影响日志证据的可用性,不得覆盖检查结论;这不是完整的对抗性文件系统沙箱。

MCP 的 `auto_fix` 还必须在应用层单独投影公开结果:`run_fix` 保留执行所需的原始命令与 stderr,但 JSON 只允许修复状态、退出码及收敛后的执行元数据。formatter 的 stderr 尾部写入项目 `out/.codeguard-fix.log`,成功落盘才公开私有日志路径;日志不可写时不回退输出原文。此边界不修改 CLI 的本地诊断契约,也不把私有日志路径当成宿主已读取的证明。

### 5. 命令语法、仓库观察与路径政策分离

`git_syntax` 只解释已支持的静态命令形态,不查文件、不起进程;`git_context` 负责仓库探测、读取一层解释器脚本和映射提交面,仓库探测复用执行内核。`PreToolUse` 入口保留宿主 JSON、绕过审计、门禁调用及报告输出,旧 Python helper 导入继续可用。间接脚本读取只保留一个实现,主入口不再重复读取脚本来判定模式。
Expand Down Expand Up @@ -140,19 +142,22 @@ PostToolUse 在修复后重新捕获输入、复检后再决定是否可去重

```mermaid
flowchart TD
Hook[Hook 协议入口] --> Compat[gate_lib 兼容导出]
Compat --> Gate[gate 应用服务]
Hook[PreToolUse 协议入口] --> GitApp[git_guard_application]
Hook -. 旧 Python 导入 .-> Compat[gate_lib 兼容导出]
GitApp --> Gate[gate 应用服务]
GitApp --> Safety[repository_policy 路径安全]
Gate --> Snapshot[准确 Git 快照 / 观察内容面]
Gate --> Checks[gate_checks 独立语言检查]
Checks --> Plan[共享计划与执行]
Checks --> Baseline[baseline 基线证据]
Checks --> Outcome[不可变 GateOutcome 与 GateDecision]
Outcome --> Merge[调用线程保序汇总]
Merge --> Audit[原 worktree + 会话归属审计]
Merge --> Report[reporting 反馈适配]
Compat --> Safety[repository_policy 路径安全与豁免]
GitApp --> Report[reporting 反馈适配]
```

语言 worker 的故障隔离只在 `gate` 的任务边界:每个输入语言仍恰好产生一条独立结果;异常产生 UNVERIFIED 备注,不授予 PASS、豁免或软缓存,并且其余 worker 的失败及审计不丢失。Git 安全路径扫描的 `SnapshotError` 属可预期的观察失败,由 `git_guard_application` 转为宿主可见的未验证上下文;若此前已有真实 lint 违规,仍保持 exit 2。没有已确认拦截时沿用 Hook 既有的未验证放行,不把这项隔离误称为 fail-closed。

这不仅改变文件位置:并发 worker 不再共享备注列表,也不依赖 ContextVar 隐式跨线程传播;审计在
调用线程记录原 worktree、实际 execution_root 与 argv。基线工具或当前结果为未知时不进入豁免,
避免文本相似覆盖执行失败。逐条基线诊断比较保留文件归属、描述与出现次数,只忽略同文件的
Expand Down
Loading
Loading