Skip to content

Commit 508a603

Browse files
committed
fix: 收敛显式 Git 目标判定并发布 v0.14.3
1 parent 2cdf816 commit 508a603

14 files changed

Lines changed: 154 additions & 26 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.2"
12+
"ref": "v0.14.3"
1313
},
1414
"policy": {
1515
"installation": "AVAILABLE",
1616
"authentication": "ON_USE"
1717
},
1818
"category": "Developer Tools",
19-
"version": "0.14.2",
19+
"version": "0.14.3",
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.2/assets/official-logo.png",
21+
"icon": "https://cdn.jsdelivr.net/gh/full-stack-plugins/codeguard-plugin@v0.14.3/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.2/assets/official-logo.png"
25+
"logo": "https://cdn.jsdelivr.net/gh/full-stack-plugins/codeguard-plugin@v0.14.3/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.2+codex.20260923",
3+
"version": "0.14.3+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.2",
8+
"version": "0.14.3",
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 & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ flowchart TD
2727
```
2828

2929
`execution` 只记录进程证据,不把非零退出自动认定为代码违规。`verdict`、CVE 与 Dockerfile 报告解析决定 PASS、FAIL 或 UNVERIFIED;入口仅按各自协议呈现和聚合退出码。Git 提交检查使用 index 或预测暂存快照,推送检查使用 HEAD;保存钩子只给反馈。计划、未执行和未验证不能宣传为通过。
30+
Git 命令的仓库定位与拟暂存解析共用入口传入的 cwd;显式 `cd`/`git -C` 无法绑定 Git 工作树时,硬门禁给出目标未验证并阻断,不退回到调用者仓或无关子仓。未给出显式目标且调用目录非仓时仍保留 workspace 子仓兜底。静态命令解析不等于完整 Shell 执行模拟。
3031

3132
## 模块所有权
3233

@@ -66,4 +67,4 @@ python3 scripts/vendor/skill_vendor.py check
6667
openspec validate refactor-codeguard-architecture --strict
6768
```
6869

69-
真实 Maven/Gradle 大型项目、联网漏洞数据库、57 种工具链、Windows 与三宿主已安装运行均需要独立证据。临时 Git 快照不是执行沙箱;构建和扫描命令以当前用户权限运行。当前重构的任务进度和本地证据见 `openspec/changes/refactor-codeguard-architecture/verification.md`。v0.14.1 的源码、CI、tag、Release 和市场已核对;其后工作树变更仍需独立发布,宿主安装运行尚未验收。
70+
真实 Maven/Gradle 大型项目、联网漏洞数据库、57 种工具链、Windows 与三宿主已安装运行均需要独立证据。临时 Git 快照不是执行沙箱;构建和扫描命令以当前用户权限运行。当前重构的任务进度和各阶段发布证据见 `openspec/changes/refactor-codeguard-architecture/verification.md`;不能以某一阶段的源码、CI、tag、Release 或市场记录替代后续改动的发布与宿主验收。

‎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.2",
3+
"version": "0.14.3",
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: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,11 @@ flowchart TD
7272

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

75-
这不是完整 Shell 解释器:分隔符/引用/动态拼接和复杂相对 cd 仍有既有边界。本批保留非 Git cd 后回退调用方 cwd 的历史策略,但删去“等价于 Shell 语义”的错误说明;不凭模块拆分宣称修好了这些定位边界。后续门禁应用拆分与命令上下文完善须分别用真实 Git 场景验证。
75+
这不是完整 Shell 解释器:分隔符/引用/动态拼接和复杂相对 cd 仍有既有边界。显式 `cd` 或
76+
`git -C` 指向非 Git 目标时,解析器现在返回独立的目标故障,硬门禁阻断而不回退调用者仓;
77+
无显式目标且 cwd 非仓时继续保留 workspace 一层子仓兜底。仓库定位和拟暂存解析共用入口
78+
传入的 cwd,不再分别读取进程全局工作目录。Git 根查询故障也保留阻断结论;这些只覆盖
79+
支持的静态命令形态,不能宣称模拟完整 Shell 控制流。
7680

7781
参考:pre-commit 的 [Language Protocol 与通用执行](https://github.com/pre-commit/pre-commit/blob/main/pre_commit/lang_base.py)、[Python 适配器](https://github.com/pre-commit/pre-commit/blob/main/pre_commit/languages/python.py)。只借鉴边界设计,不复制安装环境逻辑或新增插件生态协议。
7882

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,11 +194,24 @@ CLI 呈现 MUST 各有单一所有者。只有有效报告且执行状态可解
194194
路径并集。显式 pathspec MUST 交由只读 Git 查询成组解析,保留目录、glob、literal、exclude、
195195
引号路径及 -u/-f 的选择差异;展开后的文件名不得再作为 glob 解释。观察 MUST 不改写实际
196196
index 或工作树;不支持的动态/交互式形态必须明确未验证,不得冒充准确暂存面。
197+
仓库定位与拟暂存解析 MUST 使用同一个显式调用目录,不能一处用传入的 cwd、另一处读取
198+
门禁进程的全局工作目录。
199+
显式 `cd` 或 `git -C` 已给出目标时,若该目标不是可解析的 Git 工作树,MUST 阻断
200+
该 Git 副作用命令并报告目标不可确定;不得回退调用者仓或扫调用者一层子仓。
201+
只有命令未给出显式目标且调用目录不是 Git 仓时,才保留既有 workspace 子仓兜底策略。
197202

198203
#### Scenario: Two repositories have different staging commands
199204
- **WHEN** 一条命令链对 A 执行 add -A、对 B 只提交已暂存内容
200205
- **THEN** B 的未暂存及未跟踪文件不进入拟提交检查面
201206

207+
#### Scenario: An explicit Git target is not a repository
208+
- **WHEN** 命令从 Git 仓调用,但在 `cd` 到非 Git 目录后运行 `git push`,或使用无效的 `git -C` 目标
209+
- **THEN** 门禁以明确诊断阻断,而不是检查调用者仓或用 workspace 兜底;后续显式 `git -C` 指向有效仓时仍能正确绑定该仓
210+
211+
#### Scenario: Explicit invocation directory binds staging intent
212+
- **WHEN** 应用服务收到的调用目录与门禁进程当前目录不同,命令在调用目录中 `git add` 并提交
213+
- **THEN** 拟暂存路径按传入调用目录的仓与文件解析,不遗漏额外路径,也不纳入进程目录的仓
214+
202215
#### Scenario: Exclusion and literal pathspecs remain exact
203216
- **WHEN** git add 指定包含与排除 pathspec,或字面文件名包含星号
204217
- **THEN** 快照只覆盖 Git 实际匹配的文件,排除项及同名 glob 邻居不会被额外暂存

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,5 @@
3434
- [x] 5.2 四个历史 skipped 已全部恢复;Dockerfile CLI 接入统一报告解析与扫描应用,14 项真实进程边界测试通过;基线比较按诊断内容和次数核验并要求基线实际 FAIL,三项误豁免用例先红后绿。完整 433 项单测零跳过、142 项回归零失败。
3535
- [x] 5.3 新增当前架构 Mermaid 与扩展指南;报告版本读取插件 manifest,双语 README 指向当前证据,旧设计标明历史范围;双语标题/链接/版本及本地链接存在性测试通过。发布版本仍需在 5.5 检查。
3636
- [ ] 5.4 全量单测/真实 hook 回归/ruff/语言 schema/vendor 离线与在线/本 change strict 和逐条规格追溯通过。
37-
- [ ] 5.5 按仓规升级版本、生成市场元数据、授权的 PR/CI/不可变 tag/Release 闭环;v0.14.1 阶段版本已完成插件/市场双仓合并、PR/main CI、tag/Release,但本 change 后续改动仍需独立发布。宿主安装运行独立记录,未授权不得改宿主。
37+
- [ ] 5.5 按仓规升级版本、生成市场元数据、授权的 PR/CI/不可变 tag/Release 闭环;v0.14.2 阶段版本已完成插件/市场双仓合并、PR/main CI、tag/Release,但本 change 后续改动仍需独立发布。宿主安装运行独立记录,未授权不得改宿主。
3838
- [ ] 5.6 完成全目标审计,代码/规格/证据一致后同步并归档 change,才可将整体优化标记完成。

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,3 +178,11 @@
178178
- 新增 RED:UserPromptSubmit 与 PostToolUse 在 stdout 刷新失败时,旧入口仍登记完成;Git 已知拦截的输出写入失败向外抛异常,若由入口顶层 fail-open 捕获则可能放行;刷新失败还会缓存未交付拦截。现在所有确认都在刷新后;已知拦截输出故障保留 exit 2、不缓存,含无 tool_use_id 路径和缓存重放。对普通软反馈仍保持原 fail-open 协议。
179179
- 定向测试 **26/26**,完整单测 **465/465、0 skipped**,真实 Hook 回归 **142/0/0**;ruff、架构依赖/循环、本 change strict、语言 schema **57 项/11 规则**、vendor 离线和在线以及 diff whitespace 通过。vendor lock 仍为 v0.1.2 → `2c0c8071f96de48dc53e11de2499c083c100e44c`,受管技能与 lock 未修改。
180180
- 本批只证明本地输出时序与故障注入;stdout 刷新不等于宿主最终消费,可能在重试时重复反馈。三宿主已安装运行、Windows、联网漏洞库和全部语言工具链仍需独立验收;本批在此记录时尚未 bump/提交/发布。
181+
182+
## 第十七批实际验证:显式 Git 目标与调用目录
183+
184+
- v0.14.2 已经插件 PR #48、市场 PR #5 合并到双仓 `main`;插件 PR/main 的 `skills-check` 通过,不可变 tag/Release 指向合并提交 `2cdf816d3a5924155480dd24a535d61ebab47e01`,市场 Codex/ZCode/Kimi ref 与双语导航为 0.14.2。该远端证据只覆盖第十六批及此前源码,本批仍需独立发布。
185+
- 临时 CodeGraph 快照同步后追踪 `evaluate_git_command → resolve_project_roots → repository_root` 与 `staging_intent`。发现显式 `cd` 到非 Git 目录后执行 commit/push 会回退调用者仓;显式 `git -C` 无效目标会落到 workspace 兜底;应用传入 cwd 仅用于仓库定位,拟暂存解析却读取进程全局 cwd。分别用真实临时 Git 仓和独立调用目录复现:前两类错误放行/泛化诊断,第三类遗漏新增 Python 文件。
186+
- 当前 `GitTargetError` 将显式目标不可绑定与无显式目标的 workspace 兜底区分;前者在应用边界返回 exit 2 和具体路径,不再检查错误仓。Git 根观察的 `SnapshotError` 同样不交给顶层 fail-open。拟暂存解析接受可选显式 cwd,并由应用传入同一调用目录;旧无参导入/调用仍可使用进程 cwd。真实 PreToolUse 子进程证明无效目标阻断,`git -C` 有效目标仍覆盖非 Git cd。
187+
- TDD RED 包含错误放行、错误兜底、遗漏 pathspec 与根观察异常;GREEN 后完整单测 **470/470、0 skipped**,真实 Hook 回归 **143/0/0**。ruff、架构门禁、语言 schema **57 项/11 规则**、vendor 离线与在线、本 change strict、diff whitespace 通过;受管技能与 lock 未改。
188+
- 这不是 Shell 求值器:条件链、动态拼接、命令替换、复杂引用和链内环境变化仍是明确边界。三宿主现场、Windows、联网漏洞库与全部语言工具链未因此获得验收。本批在此记录时尚未 bump/提交/发布。

‎scripts/codeguard/git_context.py‎

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
_INTERPRETERS = ("bash", "sh", "zsh", "python", "python3", "node")
2424

2525

26+
class GitTargetError(ValueError):
27+
"""显式 Git 目标无法绑定时拒绝猜测其它仓库。"""
28+
2629

2730
def _is_git_repo(p: Path) -> bool:
2831
"""只读查询 Git 仓边界;工具不可用时交由调用者降级。"""
@@ -34,7 +37,7 @@ def resolve_project_roots(command: str, cwd: Path | None = None) -> list[Path]:
3437
3538
链式发布(cd plugins && git commit && cd minimax && git push)操作
3639
多个仓库——每个 git 段的边界 = `git -C <path>` 显式指定的仓,否则取它
37-
之前最近的 cd(且必须是 git 仓);无 cd 则用 cwd(需是 git 仓)。
40+
之前最近的 cd(且必须是 git 仓);无 cd 才用 cwd(需是 git 仓)。
3841
去重保序,找不到任何边界返回 []。
3942
4043
**必须与 is_guarded 同源判定**(`_git_side_effect_sub` 归一化后判子命令):
@@ -46,6 +49,7 @@ def resolve_project_roots(command: str, cwd: Path | None = None) -> list[Path]:
4649
command = _flatten_substitutions(command)
4750
roots: list[Path] = []
4851
last_cd: Path | None = None
52+
explicit_cd = False
4953
caller_dir = (cwd or Path.cwd()).resolve()
5054
current_dir = caller_dir
5155
for seg in re.split(r"&&|\|\||;|\n", command):
@@ -56,7 +60,7 @@ def resolve_project_roots(command: str, cwd: Path | None = None) -> list[Path]:
5660
if m:
5761
target = (current_dir / m.group(1).strip("\"'")).resolve()
5862
current_dir = target
59-
# 兼容旧降级策略:非 Git 目录后回退调用方 cwd;不是完整 shell 求值。
63+
explicit_cd = True
6064
last_cd = target if target.is_dir() and _is_git_repo(target) else None
6165
continue
6266
if _git_side_effect_sub(seg) is None:
@@ -66,14 +70,16 @@ def resolve_project_roots(command: str, cwd: Path | None = None) -> list[Path]:
6670
c_path = (current_dir / c_path).resolve()
6771
if c_path is not None:
6872
root = c_path if c_path.is_dir() and _is_git_repo(c_path) else None
73+
if root is None:
74+
raise GitTargetError(f"git -C 显式目标不是可解析的 Git 工作树:{c_path}")
6975
else:
70-
root = last_cd or (caller_dir if _is_git_repo(caller_dir) else None)
76+
if explicit_cd and last_cd is None:
77+
raise GitTargetError(f"cd 显式目标不是可解析的 Git 工作树:{current_dir}")
78+
root = last_cd if explicit_cd else (caller_dir if _is_git_repo(caller_dir) else None)
7179
if root:
7280
root = repository_root(root)
7381
if root not in roots:
7482
roots.append(root)
75-
# 有意行为(勿"修掉"):cd 到非 git 目录后 last_cd=None,git 段回退用
76-
# 调用方 cwd。这是历史降级行为,不应声称等价于 shell 的 cd 语义。
7783
return roots
7884

7985

0 commit comments

Comments
 (0)