Skip to content

Commit ee2e29a

Browse files
authored
Merge pull request #64 from full-stack-plugins/release/codeguard-v0.14.15
fix: 收敛 Git 快照资源边界与覆盖层一致性 (v0.14.15)
2 parents 95b793f + 00ad1e9 commit ee2e29a

15 files changed

Lines changed: 296 additions & 64 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.14.14"
12+
"ref": "v0.14.15"
1313
},
1414
"policy": {
1515
"installation": "AVAILABLE",
1616
"authentication": "ON_USE"
1717
},
1818
"category": "Developer Tools",
19-
"version": "0.14.14",
19+
"version": "0.14.15",
2020
"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.",
21-
"icon": "https://cdn.jsdelivr.net/gh/full-stack-plugins/codeguard-plugin@v0.14.14/assets/official-logo.png",
21+
"icon": "https://cdn.jsdelivr.net/gh/full-stack-plugins/codeguard-plugin@v0.14.15/assets/official-logo.png",
2222
"interface": {
2323
"displayName": "代码规范守卫",
2424
"shortDescription": "Trustworthy code checks and Java impact analysis",
25-
"logo": "https://cdn.jsdelivr.net/gh/full-stack-plugins/codeguard-plugin@v0.14.14/assets/official-logo.png"
25+
"logo": "https://cdn.jsdelivr.net/gh/full-stack-plugins/codeguard-plugin@v0.14.15/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.14.14+codex.20260923",
3+
"version": "0.14.15+codex.20260923",
44
"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.",
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.14.14",
8+
"version": "0.14.15",
99
"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.",
1010
"description_i18n": {
1111
"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.",

‎docs/current-architecture.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ flowchart TD
2727
```
2828

2929
`execution` 只记录进程证据,不把非零退出自动认定为代码违规;stdout/stderr 合计按默认 16 MiB 捕获预算并发读取,超限终止执行、保留预算内诊断且返回 `output_limit`/UNVERIFIED,不把片段当成完整日志。`verdict`、CVE 与 Dockerfile 报告解析决定 PASS、FAIL 或 UNVERIFIED;入口仅按各自协议呈现和聚合退出码。Git 提交检查使用 index 或预测暂存快照,推送检查使用 HEAD;保存钩子只给反馈。计划、未执行和未验证不能宣传为通过。
30-
Git 准确快照的二进制读取独立于文本检查执行器:先严格解析 index/HEAD 对象列表的 NUL 帧、模式、ID、类型/阶段和唯一文件名,并与独立路径列举核对;`cat-file` 两阶段响应再逐项核对 ID、blob 类型、大小与边界,按 SHA-1/SHA-256 blob 对象格式复算内容哈希。缺项、截断、尾部脏数据或同长度内容替换均不交付临时树,而是明确标记 Git UNVERIFIED。原始 index 不在观察过程中改写。该校验不是恶意 Git 进程沙箱或完整 Git/Shell 模拟。
30+
Git 准确快照复用统一执行器的原始字节模式:路径列表默认最多捕获 16 MiB,`cat-file --batch-check` 按对象数分配响应预算;通过大小响应确认对象总量不超过 256 MiB 后,`--batch` 才按总 blob 大小和逐项头部预算读取。stdout/stderr 合计超限时及时终止 Git,抛出 `SnapshotError`,不交付截断内容。预测暂存的工作树覆盖层只列举一次,并以同一集合决定 `changed` 和物化内容;最多 20,000 项、单文件 32 MiB、实际复制总量 256 MiB,以 64 KiB 块流式读取。打开时使用非阻塞与不跟随末级链接的可用平台标志,避免类型检查后变成 FIFO 时卡住。特殊文件、读取期间变化和超限不交付临时树,文件↔目录转换按父路径先处理。随后严格解析 index/HEAD 对象列表的 NUL 帧、模式、ID、类型/阶段和唯一文件名,并与独立路径列举核对;`cat-file` 两阶段响应再逐项核对 ID、blob 类型、大小与边界,按 SHA-1/SHA-256 blob 对象格式复算内容哈希。缺项、截断、尾部脏数据或同长度内容替换均不交付临时树,而是明确标记 Git UNVERIFIED。原始 index 不在观察过程中改写。该校验不是恶意 Git 进程沙箱或完整 Git/Shell 模拟。
3131
`language_check` 将 `PlanExecution` 的实际命令依序映射为应用层有界 `execution_trace`(检查、修复、复检阶段);`check_application` 将其进一步压成 MCP 安全元数据,不回显原始 argv、环境覆盖或捕获输出。MCP `auto_fix` 以 `fingerprint.file_content` 对仓内改动文件在修复前、formatter 后、复检后分别采集有总量预算的流式身份,仓外路径、符号链接或读取故障不启动 formatter;顶层 `fixed` 只归因于 formatter 且复检后仍保留的变化。公开 `fix_results` 将命令成功 `formatter_succeeded` 与逐项修复确认 `fixed` 分离;只有唯一成功执行的 formatter 且内容变化可验证时才把全局变化归给该项,多 formatter 执行不猜测归属。后续身份不可采集、formatter 失败后仍有内容变化或检查器改写目标文件时,保留实际执行证据、整体标为 UNVERIFIED,不把未知副作用声称为已确认修复。`fix_results` 只公开状态与安全元数据;formatter stderr 尾部写入私有 `.codeguard-fix.log` 后只公开路径,日志不可用时不退回公开原文。失败日志保留各已执行检查在捕获预算内的输出;输出超限时日志只含片段,不能称为完整诊断,且可能含敏感文本,应排除出版本控制。项目日志和门禁截断日志共用 `storage.write_private_text` 的私有原子落盘;预置日志文件链接不被跟随,默认 `out` 目录为链接或不可写时不返回虚假日志路径,也不覆盖检查结论。终止命令仍决定既有状态、退出码和旧字段;未运行的计划命令不进入证据。
3232
`run_fix` 的历史 `fixed` 字段仍表示 formatter 命令以 0 退出,供旧调用方决定是否复检;它本身不是内容变化证明。CLI `fix` 因而只报告 formatter 执行成功与文件变化未验证,不再把退出码 0 呈现为已确认修复。
3333
Git 命令的仓库定位与拟暂存解析共用入口传入的 cwd;显式 `cd`/`git -C` 无法绑定 Git 工作树时,硬门禁给出目标未验证并阻断,不退回到调用者仓或无关子仓。未给出显式目标且调用目录非仓时仍保留 workspace 子仓兜底。静态命令解析不等于完整 Shell 执行模拟。
@@ -49,7 +49,7 @@ workspace 兜底产生的每个子仓是合成目标,暂存观察也绑定该
4949
| `java_build.py`、`java_impact.py`、`java_planning.py` 等 | 构建读取、纯影响闭包、命令选择与环境观察 | 默认保留跳过测试的行为;复杂构建保守扩大检查范围 |
5050
| `cve_reports.py`、`cve_policy.py`、`cve_scanners.py`、`cve.py` | 漏洞报告、阈值、进程适配与复扫编排 | 无有效结构化报告就没有安全通过结论 |
5151
| `dockerfile_reports.py`、`dockerfile.py` | hadolint/Trivy 结构化证据与逐文件扫描 | `dockerfile_security.py` 只解析参数和呈现报告 |
52-
| `execution.py`、`git_staging.py`、`git_snapshot.py`、`storage.py` | 外部进程、Git 内容面、原子状态读改写 | Git blob 保持字节,不经过文本检查执行器;准确快照必须核对批量对象协议与内容身份 |
52+
| `execution.py`、`git_staging.py`、`git_snapshot.py`、`storage.py` | 外部进程、Git 内容面、原子状态读改写 | Git blob 走有界原始字节通道、不经文本解码;准确快照必须核对批量对象协议与内容身份 |
5353
| `registry.py`、`registry_schema.py`、`discovery.py`、`config.py` | 已校验的语言表、发现与配置 | `languages.json` 是语言清单的事实源 |
5454

5555
这些是源代码层的边界。`scripts/check_architecture.py` 对第一方静态导入和环做门禁;动态加载、进程副作用和宿主行为仍需测试。

‎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.14.14",
3+
"version": "0.14.15",
44
"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.",
55
"author": {
66
"name": "Full Stack Skills / PartMe.AI"

‎openspec/changes/refactor-codeguard-architecture/design.md‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ flowchart TD
5252

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

55-
第二十八批审计确认 `subprocess.run(capture_output=True)` 会先无界收集检查器输出,应用层截断不能保护进程内存。统一执行器改为两流并发读取,默认合计最多保留 16 MiB;输出超限时停止进程,返回独立 `output_limit` 故障与退出码 125,保留预算内的诊断前缀,不声称存在完整日志。POSIX 上使用独立进程组终止子进程;Windows 仍只终止直接进程,子孙生命周期需实机验证。调用方可以为确定性测试传入更小预算,但正常预算内的 argv、cwd、输出和退出契约不变。这是外部工具资源护栏,不是执行沙箱;Git 二进制快照入口另有自身预算,不经过文本执行器。
55+
第二十八批审计确认 `subprocess.run(capture_output=True)` 会先无界收集检查器输出,应用层截断不能保护进程内存。统一执行器改为两流并发读取,默认合计最多保留 16 MiB;输出超限时停止进程,返回独立 `output_limit` 故障与退出码 125,保留预算内的诊断前缀,不声称存在完整日志。POSIX 上使用独立进程组终止子进程;Windows 仍只终止直接进程,子孙生命周期需实机验证。调用方可以为确定性测试传入更小预算,但正常预算内的 argv、cwd、输出和退出契约不变。这是外部工具资源护栏,不是执行沙箱。后续快照审计将同一有界捕获分成文本与原始字节两种结果:Git `cat-file` 保留完整二进制协议,先按数量限制大小响应,再用经验证的 blob 大小分配内容预算,任何超限都抛出快照未验证,不交付部分内容。
5656

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

@@ -81,7 +81,7 @@ MCP 的 `auto_fix` 还必须在应用层单独投影公开结果:`run_fix` 保
8181

8282
`path_policy` 是扫描排除表、产物识别与拟入库路径规则的单一来源;`scope` 和 `gate_lib` 只兼容导出/调用。策略接收已经确定的路径,不读取 Git,更不会执行建议中的移除操作。Git 快照采集仍在 git_snapshot,反馈格式仍在 reporting。
8383

84-
`git_snapshot` 保持二进制 Git 基础设施边界,不经文本检查执行器转换 blob。对象列举之后,
84+
`git_snapshot` 保持二进制 Git 基础设施边界,复用统一执行器的原始字节模式而不解码 blob。对象列举之后,
8585
同一个 Git 字节执行入口读取 `cat-file --batch-check` 和 `--batch`;逐项确认对象 ID、类型、
8686
大小、数量、顺序、终止分隔符与尾部边界,并以 SHA-1/SHA-256 Git blob 对象格式重新计算
8787
payload 哈希。任一不一致转为 `SnapshotError`,准确门禁沿既有策略显示 UNVERIFIED;不把
@@ -92,6 +92,7 @@ payload 哈希。任一不一致转为 `SnapshotError`,准确门禁沿既有
9292
或 `ls-tree --name-only` 路径面交叉核对,防止单个响应在完整记录边界被截断后仍交付
9393
部分树。通用 `-z` 路径列举同样拒绝未终止或空记录;并发 index/HEAD 变化宁可转
9494
UNVERIFIED,不把两个时点拼成一次确定快照。这不是对恶意 Git 进程的完整双源证明。
95+
工作树预测暂存覆盖层与 Git blob 是两种不同来源:前者不是 `cat-file` 的预算一部分,故另限 20,000 路径、单文件 32 MiB、实际复制总量 256 MiB,并通过有界块读取避免 `read_bytes()` 的整文件内存副本。覆盖路径仅列举一次,原样传给 changed 路径计算与临时树物化,避免两次 Git 查询之间集合变化造成“报告 A、检查 B”。源文件打开在支持的平台上使用 `O_NOFOLLOW | O_NONBLOCK`,类型检查与打开之间即使变成 FIFO 也不阻塞;源描述符在复制前后核对类型、大小与时间戳。超限、特殊文件和读取故障均拒绝交付。临时树按路径深度处理覆盖项,允许文件转目录;目录转文件时只清理一次性临时树中的旧子项,不改原仓。这个机制仍不承诺对抗父目录并发替换或同内容同元数据伪装的完整文件系统快照隔离。
9596

9697
直接命令链的拟暂存分析分成静态事件观察与按提交时间投影:先把同仓 `add`/`commit` 及其调用目录记录为不可变事件,再只将最后一个 commit 及以前的 add 送往 Git pathspec 查询和内容快照。这样后续 add 不会回溯污染已完成提交,也不跳过两个 commit 之间的 add。旧的独立 `staging_intent` 调用默认仍返回整条链的暂存意图;硬门禁只在没有一层间接脚本或 Shell 命令替换时启用按提交投影。`$(...)`/反引号的内层实际先执行,而旧静态展开把它附在文本尾部;间接脚本与外层 add 的跨层顺序也尚无统一事件时钟。这两类命令继续采用保守并集,不能以局部排序缩小检查面。
9798

‎openspec/changes/refactor-codeguard-architecture/specs/execution-kernel/spec.md‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
### Requirement: Tool execution SHALL preserve process evidence
1010

1111
执行结果 MUST 保留实际 argv、工作目录、原始退出码、标准输出和标准错误;若外部工具输出超过明确的捕获预算,则 MUST 终止该执行并保留预算内已捕获的诊断,以独立故障标识报告 UNVERIFIED,不得伪造完整输出或 PASS。参数 MUST 以 argv 传递,不隐式增加 shell;工具是否发现代码违规由工具判定策略解释,不能由进程执行器推断。
12+
Git 快照使用同一有界进程边界的原始字节模式,MUST 保留 NUL 与 blob 字节且不在协议校验前解码;路径列举、大小响应及对象内容 MUST 各有明确捕获预算。任何超限或执行故障 MUST 阻止交付快照并成为 SnapshotError,不能以截断数据继续门禁。对象总量预算必须在读取 batch 内容之前由大小响应确定。
13+
工作树预测暂存覆盖层 MUST 以有界缓冲复制普通文件,并同时限制文件数量、单文件与累计字节数;检查期间文件超出预算、变成特殊文件或读取失败 MUST 拒绝交付临时树,不能把不完整覆盖层当准确 Git 快照。删除及文件与目录之间双向转换的预测语义必须保留,不能因覆盖路径迭代顺序不同而改变快照。
14+
同一次准确快照中,拟提交路径与实际物化的覆盖层 MUST 使用同一份已列举的路径集合;不得分别查询两次 Git 工作树后把不同时点的路径清单拼成一个已验证结论。
1215

1316
#### Scenario: A checker exits nonzero
1417
- **WHEN** 同一检查器经 CLI、保存 hook、Git 门禁或 CVE 执行并以非零退出
@@ -22,6 +25,22 @@
2225
- **WHEN** 外部检查器向 stdout/stderr 持续写入超过进程执行预算的内容
2326
- **THEN** 执行器有界地保留两个流的已有诊断,终止该检查,返回明确的输出超限故障与非成功退出;下游不得把截断的成功前缀判为 PASS 或宣称已有完整诊断日志
2427

28+
#### Scenario: Git emits more data than the snapshot budget
29+
- **WHEN** Git 路径列举、batch-check 或 batch 内容超过相应捕获预算,即使进程继续输出
30+
- **THEN** 执行器及时终止进程;快照入口报告未验证且不交付部分内容、不得据此前的成功前缀放行
31+
32+
#### Scenario: Many predicted worktree files exceed the aggregate overlay budget
33+
- **WHEN** 每个文件均小于单文件上限,但所有拟暂存工作树文件的实际读取字节总数超过覆盖层预算
34+
- **THEN** 快照不交付部分临时树,门禁报告未验证,原工作树与 Git index 保持不变
35+
36+
#### Scenario: Overlay listing changes between observations
37+
- **WHEN** Git 工作树路径列举在两次调用之间返回不同集合
38+
- **THEN** 单次快照只使用一次列举结果来计算 changed 与构建临时树;不能把第一份 changed 与第二份物化内容配对
39+
40+
#### Scenario: A predicted path is a special file
41+
- **WHEN** 拟暂存路径在快照复制时变成 FIFO、socket 或其它非普通文件
42+
- **THEN** 快照拒绝该内容,即使类型检查与打开之间发生替换也不阻塞读取特殊文件,且不把它当作成功删除
43+
2544
### Requirement: Execution failures SHALL remain observable
2645

2746
超时 MUST 保留已捕获输出并记录超时故障;缺失命令与权限/工作目录故障 MUST 返回明确不可验证的执行结果。非 UTF-8 输出 MUST 保留可解码文本并替换非法字节,不能让编码异常吞掉整次检查。不得捕获用户取消或任意编程异常作为成功结果。

‎openspec/changes/refactor-codeguard-architecture/tasks.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,6 @@
3333
- [x] 5.1 增加自动架构依赖/循环检查并接入 CI,临时源码树注入反向依赖/函数内导入/相对导入环后确实拒绝;本地已验证,远端 CI 待发布阶段。不以文件行数当合格标准。
3434
- [x] 5.2 四个历史 skipped 已全部恢复;Dockerfile CLI 接入统一报告解析与扫描应用,14 项真实进程边界测试通过;基线比较按诊断内容和次数核验并要求基线实际 FAIL,三项误豁免用例先红后绿。完整 433 项单测零跳过、142 项回归零失败。
3535
- [x] 5.3 新增当前架构 Mermaid 与扩展指南;报告版本读取插件 manifest,双语 README 指向当前证据,旧设计标明历史范围;双语标题/链接/版本及本地链接存在性测试通过。发布版本仍需在 5.5 检查。
36-
- [x] 5.4 全量单测/真实 hook 回归/ruff/语言 schema/vendor 离线与在线/本 change strict 和逐条规格追溯通过;第二十八批本地 549 项单测、143 项真实 Hook 回归、57 项/11 规则,证据见 verification.md。仅证明本地契约,不等同三宿主现场验收。
36+
- [x] 5.4 全量单测/真实 hook 回归/ruff/语言 schema/vendor 离线与在线/本 change strict 和逐条规格追溯通过;第二十九批本地 559 项单测、143 项真实 Hook 回归、57 项/11 规则,证据见 verification.md。仅证明本地契约,不等同三宿主现场验收。
3737
- [x] 5.5 按仓规升级版本、生成市场元数据、授权的 PR/CI/不可变 tag/Release 闭环;第二十八批已发布 v0.14.14(插件 PR #62、市场 PR #18、源码 PR/main CI、注释 tag/正式 Release 均核对;市场 PR 无 CI 检查)。宿主安装运行另行记录,未授权不得改宿主;发布证据见 verification.md。
3838
- [ ] 5.6 完成全目标审计,代码/规格/证据一致后同步并归档 change,才可将整体优化标记完成。

0 commit comments

Comments
 (0)