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/full-stack-plugins/codeguard-plugin.git",
"ref": "v0.15.5"
"ref": "v0.16.0"
},
"policy": {
"installation": "AVAILABLE",
"authentication": "ON_USE"
},
"category": "Developer Tools",
"version": "0.15.5",
"version": "0.16.0",
"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.15.5/assets/official-logo.png",
"icon": "https://cdn.jsdelivr.net/gh/full-stack-plugins/codeguard-plugin@v0.16.0/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.15.5/assets/official-logo.png"
"logo": "https://cdn.jsdelivr.net/gh/full-stack-plugins/codeguard-plugin@v0.16.0/assets/official-logo.png"
}
}
]
Expand Down
14 changes: 14 additions & 0 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "codeguard-plugin",
"owner": {
"name": "full-stack-plugins"
},
"plugins": [
{
"name": "codeguard",
"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.",
"version": "0.16.0",
"source": "./"
}
]
}
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.15.5+codex.20260923",
"version": "0.16.0+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": "代码规范守卫",
"zh-CN": "代码规范检查"
},
"version": "0.15.5",
"version": "0.16.0",
"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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

按版本段落提炼的主题摘要(生成于 2026-09-23,来源:git 历史 212 个提交与各 release 提交)。逐提交细节以 `git log` 与 GitHub Releases 为准;本文件按主题归纳,不逐条罗列。

## v0.16.0 — Claude 安装面与 Go CVE 生态

- Claude 安装面补件(新增 `.claude-plugin/marketplace.json`);CVE 新增 go 生态;
pathsep 修复;`strict_mode` 摘除。

## v0.15.x — Git 归因收敛与诊断安全

- **v0.15.4** 测试卫生与可见性:`tests/run_all.py`(809 行)拆分为
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ Output logs default to <project>/out/.codeguard-last.log; CLI --quiet disables l

## Configuration and coverage

Root codeguard.json may set gate_scope to delta or repo and customize extension/exclusion detection. User settings retain enabled_languages, auto_fix_on_save and lint_timeout_seconds. strict_mode is reserved and does not make PostToolUse block. See the [hook protocol](hooks/__protocol__.md).
Root codeguard.json may set gate_scope to delta or repo and customize extension/exclusion detection. User settings retain enabled_languages, auto_fix_on_save and lint_timeout_seconds. See the [hook protocol](hooks/__protocol__.md).

The registry contains **54 Stable adapters and 3 Planned entries**. “Stable” does not certify every toolchain or project. Markdown/YAML require project configuration; missing configuration is UNVERIFIED. Markdown findings are advisory. Generated and dependency directories are excluded from ordinary lint scope, not automatically accepted for commit. Python checks honor the project's own ruff configuration (ruff.toml / .ruff.toml / [tool.ruff]); when none exists, codeguard injects a default rule set pinned to the CI baseline (ruff==0.16.8) so verdicts do not drift with whichever ruff version a machine happens to have. Full command inventory: [languages](docs/LANGUAGES.md).

Expand Down
2 changes: 1 addition & 1 deletion README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ python3 scripts/run_check.py --mcp /path/to/project

## 配置与覆盖

仓根 codeguard.json 的 gate_scope 可选 delta/repo,也可定制扩展名和排除规则。用户设置保留 enabled_languages、auto_fix_on_save、lint_timeout_seconds。strict_mode 是保留字段,不会令 PostToolUse 阻断,详见[钩子协议](hooks/__protocol__.md)。
仓根 codeguard.json 的 gate_scope 可选 delta/repo,也可定制扩展名和排除规则。用户设置保留 enabled_languages、auto_fix_on_save、lint_timeout_seconds。详见[钩子协议](hooks/__protocol__.md)。

注册表含 **54 个 Stable 适配器和 3 个 Planned 项**。“Stable” 不证明全部工具链或项目已验证。Markdown/YAML 需要项目配置,缺配置为 UNVERIFIED;Markdown 违规只告警。生成物和依赖目录从普通 lint 范围排除,不等于允许入库。Python 检查优先使用项目自有 ruff 配置(ruff.toml / .ruff.toml / [tool.ruff]);项目无自有配置时注入钉扎在 CI 基线(ruff==0.16.8)的默认规则集,判定不随机器上 ruff 版本漂移。完整命令见[语言清单](docs/LANGUAGES.md)。

Expand Down
2 changes: 1 addition & 1 deletion bin/codeguard
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# codeguard fix [--lang LANG] [path] # 自动修复 lint 问题
# codeguard cve [--ecosystem E] [--severity S] [--fix] [--json] [path]
# # CVE 依赖漏洞扫描
# # 生态: maven(别名 java) / node / python / rust / universal(别名 trivy)
# # 生态: maven(别名 java) / node / python / rust / go / universal(别名 trivy)
# # 退出码: 0 通过 / 1 无法验证 / 2 存在漏洞 / 3 参数错误
# codeguard dockerfile [--json] [path] # Dockerfile 安全风险检查(hadolint + trivy config)
# codeguard detect [path] # 检测项目语言
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.15.5",
"version": "0.16.0",
"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
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-09-24
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
## Context

在飞大重构(refactor-codeguard-architecture,5.5/5.6)已把执行内核/判定/Java/CVE/状态全部模块化到 `scripts/codeguard/`,四个缺口是它范围之外的挂账项:安装面缺件、生态覆盖、跨平台 PATH、死配置。四项互不相交且与在飞文件仅 config.py 一处相邻(摘两行死配置,属该模块的清理型修改)。

## Goals / Non-Goals

**Goals:**

- Claude 宿主安装面闭环(清单 + 版本链 + 回归锁)。
- go 生态进入规范映射,自动选择与显式选择(含别名)同源,阈值语义与既有生态一致。
- PATH 分隔符跨平台正确;死旋钮不留假象。

**Non-Goals:**

- 不做 govulncheck 原生接入(无严重度输出,阈值语义无处安放;trivy 对 gomod 原生解析已满足扫描与严重度过滤)。
- 不动 5.6 归档、死代码清理(在飞重构的地盘)。
- 不实现 `strict_mode` 阻塞语义(与协议 §1 矛盾,永久移除)。

## Decisions

1. **go 的解析器复用 trivy 格式、身份走规范映射**——`_PARSERS["go"] = _trivy` 是格式复用;`_result("go", …)` 保证"结果中报告的标识来自同一份权威映射"(spec 既有要求)。若让 go 报成 universal,命令行 `--ecosystem go` 的输入标识与输出标识就分叉了。
2. **保留 UNKNOWN 进 severity 过滤**(同 scan_trivy 注释):先滤掉缺严重度发现会让解析器把它们当不存在——假 PASS。测试锁住该语义。
3. **`.claude-plugin/marketplace.json` 同时进 bump 链**——只补清单不补发版链 = 下一版必漂移;`bumpPlain` 对单点 version 字段即覆盖,两行接入。
4. **README 句级删除而非保留标注**——strict_mode 的"保留"状态只制造配置噪音;文档与解析同批消失,测试双向锁死。
5. **paths.py 用 `os.pathsep` 而非双平台分支**——语义就是"PATH 的分隔符",抽象层早该在。

## Risks / Trade-offs

- [go 报告格式依赖 trivy] → 与 universal 同一依赖面,无新增失败模式;precheck(go.mod/go.sum)保证非 go 项目走不到扫描。
- [.claude-plugin 清单形状无法在本机装 Claude 验证] → 形态逐字段对齐 canvas 仓先例(074a580),版本链由 bump 与测试双锁;宿主现场安装仍属外部验收(同 5.4 的表述纪律)。
- [strict_mode 从配置中消失] → 从无消费点;用户 yaml 里写了它也只被忽略(与现状一致),README 不再误导。

## Migration Plan

1. 规格先行(两份 ADDED delta),归档前 strict 校验。
2. 实现 + `tests/test_gap_closure_20260923.py` 同批;全套(unittest/run_all/check_architecture/ruff/openspec)绿后按仓规 minor bump 0.16.0。
3. PR/CI/不可变 tag/Release 闭环,市场仓在主检出对齐新 main 后同步。
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
## Why

codegraph 深查(2026-09-23)对当前 HEAD 实测出四个长期挂账的小缺口:① `hooks/hooks.json` 引用 `${CLAUDE_PLUGIN_ROOT}` 5 处、Claude 是声明宿主,但仓内**没有** `.claude-plugin/` 清单——Claude 宿主安装面缺件(canvas 仓先例:074a580 补清单);② CVE 扫描缺 go/gomod 生态(语言注册表有 go,自动选择映射到空,跑不出任何依赖漏洞检查);③ `scripts/paths.py` 5 处硬编码 `":"`,Windows 上 PATH 拼接/分割必错(4.1 记录在案的未验收面,修兼容是纯正确性);④ `strict_mode` 死旋钮——`config.py` 只解析零消费(PostToolUse 恒 exit 0 是协议 §1 设计,阻塞语义与之矛盾),README 也自述"保留未接线",假旋钮误导配置。

## What Changes

- 新增 `.claude-plugin/marketplace.json`(对齐 canvas 仓形态:顶层仓库名 + owner + plugins[0] 条目),并把该清单纳入 `bump-plugin.mjs` 的版本链(否则下次发版必漂移)。
- CVE 新增 **go** 生态:规范映射独立条目(aliases `golang`/`gomod`、languages `go`、markers `go.mod`/`go.sum`),扫描器走 trivy(原生解析 gomod),**报告格式复用 trivy JSON 解析器**、生态身份按规范映射报告——格式是格式,身份是身份;保留 UNKNOWN 进过滤(防假 PASS 同 universal 语义)。
- `paths.py` 全部改为 `os.pathsep`(5 处)。
- 摘除 `strict_mode`:config 解析 + defaults + README 双语句同步删除(保留解析 = 假旋钮)。

## Capabilities

### New Capabilities

无。

### Modified Capabilities

- `plugin-manifest-contracts`: 新增 Claude 宿主市场清单的存在性与版本链要求。
- `cve-dependency-scan`: 新增 go 生态经规范映射可扫的要求(含别名归一与阈值语义保持)。

## Impact

`scripts/codeguard/{cve,cve_scanners,cve_reports,config}.py`、`scripts/paths.py`、`scripts/bump-plugin.mjs`、`.claude-plugin/marketplace.json`(新)、README 双语、新增 `tests/test_gap_closure_20260923.py`。退出码/JSON schema 不变;`strict_mode` 配置键移除(从无消费点)。5.6 归档与死码清理属在飞 `refactor-codeguard-architecture`,本变更不触碰。
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
## ADDED Requirements

### Requirement: Go ecosystem SHALL be scannable through the canonical map

go/gomod SHALL 是规范映射中的一等生态(标识 `go`,别名至少含 `golang`/`gomod`),支持自动选择(项目含 `go.mod` 或 `go.sum` 时按语言映射命中)与显式选择(别名规范化到同一标识)。扫描结果中报告的生态标识 MUST 为 `go`(输入标识与输出标识同源);阈值语义 MUST 与其他生态一致(阈值及以上 + 缺严重度发现不被预过滤——不得产生假 PASS)。非 go 项目 SHALL 在扫描前被前置条件判为无法验证而非有漏洞。

#### Scenario: A Go project auto-selects the go ecosystem

- **WHEN** 项目含 `go.mod` 且检测到 go 语言文件
- **THEN** 自动选择解析为生态 `go` 并调用其扫描器

#### Scenario: Alias selection canonicalizes

- **WHEN** 命令行显式选择 `--ecosystem golang`(或 `gomod`)
- **THEN** 规范化为 `go`,结果中报告的标识也是 `go`

#### Scenario: Missing severity data is not pre-filtered

- **WHEN** 扫描报告含缺严重度的 go 依赖发现且阈值为 HIGH
- **THEN** 该发现不被预过滤丢弃(与 universal 同语义),按判定规则计数

#### Scenario: Non-Go project without markers is unverified

- **WHEN** 项目缺 `go.mod` 与 `go.sum` 时显式选择 go 生态
- **THEN** 前置条件判定为无法验证(缺标志文件),不产生"有漏洞"结论
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
## ADDED Requirements

### Requirement: Claude Code marketplace manifest SHALL exist and track the release version

`.claude-plugin/marketplace.json` MUST 存在且为合法 JSON,形态为市场清单(顶层仓库标识与 owner,`plugins[]` 含 `name`/`description`/`version`/`source`)。`plugins[0].version` MUST 与各宿主 manifest 的版本一致,且发版工具 MUST 将该文件纳入版本链更新(版本漂移按契约失败)。

#### Scenario: Claude host installs the plugin

- **WHEN** 检查发布仓的 `.claude-plugin/marketplace.json`
- **THEN** 文件存在、可解析、`plugins[0]` 的 name 为插件 id、`source` 为 `"./"`,且 version 与 `kimi.plugin.json` 等 manifest 一致

#### Scenario: A release bumps the version

- **WHEN** 发版工具执行版本升级
- **THEN** `.claude-plugin/marketplace.json` 的版本随其余 manifest 同步更新,读回校验覆盖该文件
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
## 1. Specification

- [x] 1.1 两份 ADDED delta(manifest 版本链 / go 生态规范映射)
- [x] 1.2 `openspec validate --strict` 通过

## 2. Implementation

- [x] 2.1 `.claude-plugin/marketplace.json`(canvas 仓形态)+ `bump-plugin.mjs` 版本链接入
- [x] 2.2 go 生态:`scan_go`(trivy、UNKNOWN 保序)+ `_PARSERS["go"]` 格式复用 + ECOSYSTEM_SCANNERS 条目(别名/语言/标志)
- [x] 2.3 `paths.py` 5 处 `os.pathsep`;`config.py` 摘除 `strict_mode`;README 双语句同步

## 3. Verification

- [x] 3.1 `tests/test_gap_closure_20260923.py`:清单形态/版本链/bump 覆盖锁、go 映射/别名/前置条件/trivy 格式解析 parity、pathsep 源级锁、strict_mode 双向消失锁
- [x] 3.2 全套终验(unittest / run_all / check_architecture / ruff / openspec --all)
27 changes: 25 additions & 2 deletions openspec/specs/cve-dependency-scan/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@

## Purpose
定义 `codeguard cve` 的生态覆盖边界:哪些生态必须给出可验证结论、无原生扫描器时如何兜底、生态标识如何被接受与报告、严重级别阈值如何统一作用于每个扫描器,以及「通过 / 存在漏洞 / 无法验证」三类结果如何判定与退出。

## Requirements

### Requirement: Universal fallback for ecosystems without a native scanner

当项目被识别到的语言不属于任何已有原生扫描器的生态时,系统 SHALL 使用通用扫描器给出结论,而不是报告「无可扫描生态」。
Expand Down Expand Up @@ -93,3 +91,28 @@
#### Scenario: npm findings below configured severity
- **WHEN** npm 返回非零但报告只有阈值以下的漏洞
- **THEN** 当前阈值判定 PASS,并保留原始工具退出码

### Requirement: Go ecosystem SHALL be scannable through the canonical map

go/gomod SHALL 是规范映射中的一等生态(标识 `go`,别名至少含 `golang`/`gomod`),支持自动选择(项目含 `go.mod` 或 `go.sum` 时按语言映射命中)与显式选择(别名规范化到同一标识)。扫描结果中报告的生态标识 MUST 为 `go`(输入标识与输出标识同源);阈值语义 MUST 与其他生态一致(阈值及以上 + 缺严重度发现不被预过滤——不得产生假 PASS)。非 go 项目 SHALL 在扫描前被前置条件判为无法验证而非有漏洞。

#### Scenario: A Go project auto-selects the go ecosystem

- **WHEN** 项目含 `go.mod` 且检测到 go 语言文件
- **THEN** 自动选择解析为生态 `go` 并调用其扫描器

#### Scenario: Alias selection canonicalizes

- **WHEN** 命令行显式选择 `--ecosystem golang`(或 `gomod`)
- **THEN** 规范化为 `go`,结果中报告的标识也是 `go`

#### Scenario: Missing severity data is not pre-filtered

- **WHEN** 扫描报告含缺严重度的 go 依赖发现且阈值为 HIGH
- **THEN** 该发现不被预过滤丢弃(与 universal 同语义),按判定规则计数

#### Scenario: Non-Go project without markers is unverified

- **WHEN** 项目缺 `go.mod` 与 `go.sum` 时显式选择 go 生态
- **THEN** 前置条件判定为无法验证(缺标志文件),不产生"有漏洞"结论

14 changes: 14 additions & 0 deletions openspec/specs/plugin-manifest-contracts/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,17 @@ For each released manifest, the test contract SHALL assert that `len(glob("skill
- **WHEN** a directory `skills/<x>/SKILL.md` exists but `<x>` is neither in any lock source nor in `plugin-local-skills.json`
- **THEN** the test fails with the same symmetric-set difference, pointing at the orphan directory

### Requirement: Claude Code marketplace manifest SHALL exist and track the release version

`.claude-plugin/marketplace.json` MUST 存在且为合法 JSON,形态为市场清单(顶层仓库标识与 owner,`plugins[]` 含 `name`/`description`/`version`/`source`)。`plugins[0].version` MUST 与各宿主 manifest 的版本一致,且发版工具 MUST 将该文件纳入版本链更新(版本漂移按契约失败)。

#### Scenario: Claude host installs the plugin

- **WHEN** 检查发布仓的 `.claude-plugin/marketplace.json`
- **THEN** 文件存在、可解析、`plugins[0]` 的 name 为插件 id、`source` 为 `"./"`,且 version 与 `kimi.plugin.json` 等 manifest 一致

#### Scenario: A release bumps the version

- **WHEN** 发版工具执行版本升级
- **THEN** `.claude-plugin/marketplace.json` 的版本随其余 manifest 同步更新,读回校验覆盖该文件

7 changes: 6 additions & 1 deletion scripts/bump-plugin.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,12 @@ const today = new Intl.DateTimeFormat("en-CA", {
const repoDir = path.join(workspace, plugin.localDirectory);

const edits = [{ file: catalogPath, description: `${pluginId}: ${oldVersion} -> ${newVersion}` }];
const plainManifestRels = [".zcode-plugin/plugin.json", "kimi.plugin.json"];
const plainManifestRels = [
".zcode-plugin/plugin.json",
"kimi.plugin.json",
// Claude 宿主市场清单(plugins[0].version 单点,bumpPlain 首个 version 匹配即覆盖)
".claude-plugin/marketplace.json",
];
if (fs.existsSync(path.join(repoDir, "plugin.json"))) plainManifestRels.push("plugin.json");

for (const rel of plainManifestRels) {
Expand Down
5 changes: 3 additions & 2 deletions scripts/codeguard/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ def load_user_config() -> dict:
cfg_path = Path.home() / ".zcode" / "settings.local.yaml"
defaults = {
"enabled_languages": [],
"strict_mode": True,
# strict_mode 已移除:从未有消费点(PostToolUse 恒 exit 0 是协议 §1 设计,
# 阻塞语义与之矛盾),文档行同步摘除——保留解析等于给用户假旋钮。
"auto_fix_on_save": True,
# 默认 300s:Maven 冷缓存 install -DskipTests 普遍超 2 分钟(旧 120s
# 实测把超时误报为阻断)。AI 可在 ~/.zcode/settings.local.yaml 覆盖。
Expand All @@ -34,7 +35,7 @@ def load_user_config() -> dict:
if not m:
return cfg
block = m.group(1)
for key in ("strict_mode", "auto_fix_on_save"):
for key in ("auto_fix_on_save",):
mm = re.search(rf"{key}:\s*(true|false)", block)
if mm:
cfg[key] = mm.group(1) == "true"
Expand Down
Loading
Loading