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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ Version output includes `cli_version`, `target`, and protocol information. Disco

The workspace requires `std`. The opt-in `wasm-precheck` build feature uses a bounded Rust worker with pinned Java, TypeScript, and TSX grammar candidates. It currently reaches only single-file `lint java` and `lint typescript` requests without explicit native context; `.tsx` uses its own grammar. It is absent from the published npm `0.1.2` package. No `no_std`, completed project-wide WASM fallback, zero-unsafe, or fastest-runtime claim is made. Runtime OS calls require safety review; a comprehensive security audit is not claimed.

The current source-built CLI's `codeguard grammar status --format=json` reports the coverage gap without loading grammars or running lint: the pinned CodeGraph source has 30 vendored WASM files plus two distinct grammars resolved through its dependency; CodeGuard has three unqualified candidates and zero released syntax capabilities. The separate [coverage inventory](grammars/codegraph-coverage.json) is not an approved asset manifest. COBOL's 16.4 MB source asset also exceeds the current Rust loader's 8 MiB limit.
The current source-built CLI's `codeguard grammar status --format=json` reports the coverage gap without loading grammars or running lint: the pinned CodeGraph source has 30 vendored WASM files plus two distinct grammars resolved through its dependency; CodeGuard has four unqualified asset candidates (Java, Python, TypeScript, TSX) and zero released syntax capabilities. Python is pinned and Rust-loadable but has no CLI fallback path. The separate [coverage inventory](grammars/codegraph-coverage.json) is not an approved asset manifest. COBOL's 16.4 MB source asset also exceeds the current Rust loader's 8 MiB limit.

### npm installation and one-off use

Expand Down
2 changes: 1 addition & 1 deletion README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ cargo build --locked -p codeguard-cli

工作区要求 `std`。可选 `wasm-precheck` 构建特性已用固定的 Java、TypeScript、TSX grammar 候选资产与有界 Rust worker,为缺少显式原生上下文的 `lint java`、`lint typescript` 单文件请求提供疑似语法观察;`.tsx` 使用独立 grammar。公开 npm `0.1.2` 不含该路径。不声称 `no_std`、已完成项目级 WASM 兜底、零 unsafe 或性能最快。运行层系统调用需要安全审查,当前不宣称已完成整体安全审计。

当前源码构建的 CLI 可用 `codeguard grammar status --format=json` 只读展示来源覆盖缺口,不加载 grammar 或运行 lint:固定 CodeGraph 来源含 30 份随仓 WASM,另有两种独立 grammar 从其依赖取得;CodeGuard 当前有三份未验收候选,已发行语法能力为零。[覆盖库存](grammars/codegraph-coverage.json)不是已批准资产清单。COBOL 来源资产约 16.4 MB,还超过当前 Rust 加载器的 8 MiB 限额。
当前源码构建的 CLI 可用 `codeguard grammar status --format=json` 只读展示来源覆盖缺口,不加载 grammar 或运行 lint:固定 CodeGraph 来源含 30 份随仓 WASM,另有两种独立 grammar 从其依赖取得;CodeGuard 当前有 Java、Python、TypeScript、TSX 四份未验收资产候选,已发行语法能力为零。Python 已固定并通过 Rust 加载试验,但尚未接入 CLI 兜底。[覆盖库存](grammars/codegraph-coverage.json)不是已批准资产清单。COBOL 来源资产约 16.4 MB,还超过当前 Rust 加载器的 8 MiB 限额。

### npm 安装与一次性调用

Expand Down
21 changes: 18 additions & 3 deletions crates/codeguard-adapters/src/grammar_asset_manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const CODEGRAPH_LICENSE_SHA256: &str =
"e6d98f98c666bebe065ac2492a0a19232cc318d4d67bac3ca42ffb77bacc8809";
const JAVA_COMMIT: &str = "94703d5a6bed02b98e438d7cad1136c01a60ba2c";
const TYPESCRIPT_COMMIT: &str = "f975a621f4e7f532fe322e13c4f79495e0a7b2e7";
const PYTHON_COMMIT: &str = "bffb65a8cfe4e46290331dfef0dbf0ef3679de11";

/// 代码来源、许可和每份候选 grammar 的固定身份。
#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
Expand Down Expand Up @@ -68,7 +69,7 @@ pub struct GrammarAsset {
pub release_status: String,
}

/// 读取仓内固定清单,并检查 CodeGraph 许可证及三份资产的原始字节。
/// 读取仓内固定清单,并检查 CodeGraph 许可证及四份资产的原始字节。
pub fn bundled_grammar_candidates() -> Result<GrammarAssetManifest, String> {
let manifest = parse_grammar_asset_manifest(include_bytes!("../../../grammars/manifest.json"))?;
let codegraph_license = include_bytes!("../../../grammars/LICENSE.codegraph");
Expand All @@ -85,6 +86,10 @@ pub fn bundled_grammar_candidates() -> Result<GrammarAssetManifest, String> {
include_bytes!("../../../grammars/typescript/parser.wasm").as_slice(),
include_bytes!("../../../grammars/typescript/LICENSE").as_slice(),
),
"python" => (
include_bytes!("../../../grammars/python/parser.wasm").as_slice(),
include_bytes!("../../../grammars/python/LICENSE").as_slice(),
),
"tsx" => (
include_bytes!("../../../grammars/tsx/parser.wasm").as_slice(),
include_bytes!("../../../grammars/typescript/LICENSE").as_slice(),
Expand All @@ -110,7 +115,7 @@ pub fn parse_grammar_asset_manifest(raw: &[u8]) -> Result<GrammarAssetManifest,
|| manifest.codegraph_license != "LICENSE.codegraph"
|| manifest.codegraph_license_sha256 != CODEGRAPH_LICENSE_SHA256
|| manifest.build_tool != "tree-sitter-cli 0.25.10 build --wasm"
|| manifest.assets.len() != 3
|| manifest.assets.len() != 4
{
return Err("grammar 清单版本、来源或资产数量不符".into());
}
Expand All @@ -119,7 +124,7 @@ pub fn parse_grammar_asset_manifest(raw: &[u8]) -> Result<GrammarAssetManifest,
.iter()
.map(|asset| asset.language.as_str())
.collect();
if languages != BTreeSet::from(["java", "typescript", "tsx"]) {
if languages != BTreeSet::from(["java", "python", "typescript", "tsx"]) {
return Err("grammar 语言资产缺失或重复".into());
}
for asset in &manifest.assets {
Expand All @@ -135,6 +140,16 @@ pub fn parse_grammar_asset_manifest(raw: &[u8]) -> Result<GrammarAssetManifest,
"java/LICENSE",
"52ed137b039cd9c46409bc22e89938af911c95b157feae2d040b51e6084369a7",
),
"python" => (
"https://github.com/tree-sitter/tree-sitter-python",
PYTHON_COMMIT,
"v0.23.6",
"python/parser.wasm",
"a7fdc587e77bd729b9f5b783c659be23c896e305a2c374472bed7114d9e01fac",
456131,
"python/LICENSE",
"d724405ce238a22c0d35769c5a36b386ad5958192efe8bbb304fb2896254575f",
),
"typescript" => (
"https://github.com/tree-sitter/tree-sitter-typescript",
TYPESCRIPT_COMMIT,
Expand Down
19 changes: 18 additions & 1 deletion crates/codeguard-adapters/tests/grammar_asset_manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@ use codeguard_adapters::{
#[test]
fn bundled_candidates_pin_source_bytes_license_and_abi_without_claiming_support() {
let manifest = bundled_grammar_candidates().expect("bundled manifest");
assert_eq!(manifest.assets.len(), 3);
assert_eq!(manifest.assets.len(), 4);
for asset in &manifest.assets {
let (wasm, license) = match asset.language.as_str() {
"java" => (
include_bytes!("../../../grammars/java/parser.wasm").as_slice(),
include_bytes!("../../../grammars/java/LICENSE").as_slice(),
),
"python" => (
include_bytes!("../../../grammars/python/parser.wasm").as_slice(),
include_bytes!("../../../grammars/python/LICENSE").as_slice(),
),
"typescript" => (
include_bytes!("../../../grammars/typescript/parser.wasm").as_slice(),
include_bytes!("../../../grammars/typescript/LICENSE").as_slice(),
Expand Down Expand Up @@ -64,4 +68,17 @@ fn changed_wasm_license_or_abi_never_qualifies_a_candidate() {
assert!(verify_grammar_asset(&asset, wasm, license).is_err());
asset.sha256 = "0".repeat(64);
assert!(verify_grammar_asset(&asset, wasm, license).is_err());

let python = manifest
.assets
.iter()
.find(|asset| asset.language == "python")
.expect("Python candidate");
let python_wasm = include_bytes!("../../../grammars/python/parser.wasm");
let python_license = include_bytes!("../../../grammars/python/LICENSE");
assert!(verify_grammar_asset(python, python_wasm, python_license).is_ok());
let mut altered_python = python_wasm.to_vec();
altered_python[64] ^= 1;
assert!(verify_grammar_asset(python, &altered_python, python_license).is_err());
assert!(verify_grammar_asset(python, python_wasm, license).is_err());
}
4 changes: 2 additions & 2 deletions crates/codeguard-cli/tests/grammar_status_cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ fn codegraph_coverage_is_explicit_and_never_claims_parser_or_gate_completion() {
assert_eq!(report["report_type"], "grammar_coverage_inventory");
assert_eq!(report["codegraph_grammar_count"], 32);
assert_eq!(report["codegraph_vendored_count"], 30);
assert_eq!(report["candidate_count"], 3);
assert_eq!(report["candidate_count"], 4);
assert_eq!(report["released_count"], 0);
assert_eq!(report["authority"], "source_inventory_only");
assert_eq!(report["parser_capability"], "unverified");
Expand All @@ -25,7 +25,7 @@ fn codegraph_coverage_is_explicit_and_never_claims_parser_or_gate_completion() {
assert_eq!(asset["released"], false);
assert!(!asset["gap"].as_str().unwrap().is_empty());
}
for language in ["java", "typescript", "tsx"] {
for language in ["java", "python", "typescript", "tsx"] {
let asset = assets
.iter()
.find(|row| row["language"] == language)
Expand Down
23 changes: 23 additions & 0 deletions crates/codeguard-runtime/tests/wasm_grammar_load.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,34 @@
use codeguard_runtime::WasmGrammar;

const JAVA: &[u8] = include_bytes!("../../../grammars/java/parser.wasm");
const PYTHON: &[u8] = include_bytes!("../../../grammars/python/parser.wasm");
const TYPESCRIPT: &[u8] = include_bytes!("../../../grammars/typescript/parser.wasm");
const TSX: &[u8] = include_bytes!("../../../grammars/tsx/parser.wasm");

#[test]
fn pinned_grammars_load_offline_and_parse_valid_sources() {
let mut python = WasmGrammar::load(
"python",
PYTHON,
"a7fdc587e77bd729b9f5b783c659be23c896e305a2c374472bed7114d9e01fac",
14,
)
.expect("固定 Python WASM 应可由 Rust 加载");
assert_eq!(python.abi_version(), 14);
assert!(
!python
.parse(b"def greet(name):\n return name\n")
.unwrap()
.root_node()
.has_error()
);
assert!(
python
.parse(b"def greet(\n")
.unwrap()
.root_node()
.has_error()
);
let mut java = WasmGrammar::load(
"java",
JAVA,
Expand Down
4 changes: 2 additions & 2 deletions docs/Codeguard-Architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ The existing [OpenSpec change](../openspec/changes/introduce-rust-codeguard-cli/
| [Core aggregation](../crates/codeguard-core/src/aggregate.rs), [delivery gate](../crates/codeguard-core/src/delivery_gate.rs) | Pure result semantics, not trusted public gate availability |
| [Acceptance records](../tests/acceptance) | Scoped observations, test method, and residual gaps |

WASM requirements and 18 implementation tasks are recorded in the existing change. An opt-in Rust worker, pinned Java/TypeScript/TSX grammar candidates, and narrow single-file feedback schemas now exist. Project-wide native-first routing, qualified grammar ranges, stable syntax tasks, and host integrations remain incomplete; design examples are not current command output.
WASM requirements and 18 implementation tasks are recorded in the existing change. An opt-in Rust worker and narrow Java/TypeScript/TSX single-file feedback paths now exist; Python is an additional pinned, Rust-loadable asset candidate without CLI fallback. Project-wide native-first routing, qualified grammar ranges, capability-matched task closure, and host integrations remain incomplete; design examples are not current command output.

## 2. Architectural drivers

Expand Down Expand Up @@ -241,7 +241,7 @@ A completed native violation never selects fallback to obtain a clean result. A

Reuse pinned CodeGraph grammar WASM artifacts and applicable upstream licenses, source references, patches and corpus cases. Do not copy CodeGraph's graph extraction or source-blanking heuristics into a syntax verdict. CodeGraph's `src/extraction/grammars.ts` loads language artifacts through `web-tree-sitter`; successful loading there does not prove compatibility with Codeguard's Rust runtime. The local source review on 2026-09-28 found modified grammar artifacts and about 65 MB of grammar files, so a live directory is not a release input.

The read-only `codeguard grammar status` command now projects a [pinned CodeGraph coverage inventory](../grammars/codegraph-coverage.json): 30 vendored WASM files and two dependency-provided grammars, with Java, TypeScript and TSX as CodeGuard candidates and none qualified for release. This inventory is deliberately separate from the pinned [candidate asset manifest](../grammars/manifest.json). In particular, the COBOL source file exceeds the current loader's 8 MiB input limit. Inventory rows never trigger loading or count as supported parser capability.
The read-only `codeguard grammar status` command now projects a [pinned CodeGraph coverage inventory](../grammars/codegraph-coverage.json): 30 vendored WASM files and two dependency-provided grammars, with Java, Python, TypeScript and TSX as CodeGuard asset candidates and none qualified for release. Python has no CLI fallback route. This inventory is deliberately separate from the pinned [candidate asset manifest](../grammars/manifest.json). In particular, the COBOL source file exceeds the current loader's 8 MiB input limit. Inventory rows never trigger loading or count as supported parser capability.

```text
grammars/ # proposed release assets, not project state
Expand Down
4 changes: 2 additions & 2 deletions docs/Codeguard-Architecture.zh_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
| [核心聚合](../crates/codeguard-core/src/aggregate.rs)、[交付门禁](../crates/codeguard-core/src/delivery_gate.rs) | 纯结果语义,不代表公开可信门禁已可用 |
| [验收记录](../tests/acceptance) | 限定范围的观察、测试方法和剩余缺口 |

WASM 的规范与 18 项实施任务已纳入既有 change;可选 Rust worker、固定 Java/TypeScript/TSX grammar 候选资产和局部单文件反馈 schema 已存在。项目级原生优先调度、grammar 版本范围验收、稳定语法任务及宿主接线仍未完成;设计示例不是当前命令输出。
WASM 的规范与 18 项实施任务已纳入既有 change;可选 Rust worker 与 Java/TypeScript/TSX 局部单文件反馈路径已存在。Python 新增为固定且通过 Rust 加载试验的资产候选,尚未接入 CLI 兜底。项目级原生优先调度、grammar 版本范围验收、任务的能力匹配关闭及宿主接线仍未完成;设计示例不是当前命令输出。

## 2. 架构驱动

Expand Down Expand Up @@ -241,7 +241,7 @@ flowchart TD

复用固定版本的 CodeGraph grammar WASM,以及适用的上游许可证、源码引用、补丁和语料。不能把 CodeGraph 的图提取或源码遮盖启发式直接用于语法判定。CodeGraph 的 `src/extraction/grammars.ts` 通过 `web-tree-sitter` 加载语言资产,在那里可加载不证明兼容 Codeguard 的 Rust 运行时。发行时必须固定不可变的来源与资产清单,不能把正在修改的本地目录直接当作发行输入。

只读 `codeguard grammar status` 现投影[固定来源覆盖库存](../grammars/codegraph-coverage.json):CodeGraph 随仓 30 份 WASM,依赖提供另两种独立 grammar;CodeGuard 有 Java、TypeScript、TSX 三份候选,尚无已验收发行能力。覆盖库存与[候选资产清单](../grammars/manifest.json)分开,不能凭库存行自动加载或宣称支持。尤其 COBOL 来源资产超过当前加载器 8 MiB 限额。
只读 `codeguard grammar status` 现投影[固定来源覆盖库存](../grammars/codegraph-coverage.json):CodeGraph 随仓 30 份 WASM,依赖提供另两种独立 grammar;CodeGuard 有 Java、Python、TypeScript、TSX 四份资产候选,尚无已验收发行能力。Python 只通过固定字节与 Rust 加载试验,未接入 lint。覆盖库存与[候选资产清单](../grammars/manifest.json)分开,不能凭库存行自动加载或宣称支持。尤其 COBOL 来源资产超过当前加载器 8 MiB 限额。

```text
grammars/ # 规划中的发行资产,不是项目状态
Expand Down
4 changes: 2 additions & 2 deletions docs/Codeguard-Technical-Design.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ The existing [OpenSpec change](../openspec/changes/introduce-rust-codeguard-cli/

Current source is the authority for callable behavior. Target contracts are labelled as such. The product priority is configuration discovery → native results → useful repair guidance. Internal consistency checks support this experience; they are not a demand for users to manually construct execution certificates.

WASM requirements and 18 implementation tasks are recorded in the existing change. Candidate Rust worker, pinned Java/TypeScript/TSX assets, and narrow single-file reports now exist behind an opt-in feature; project-wide native-first routing, qualified grammar ranges, and host integrations remain incomplete. Design examples are not current command output.
WASM requirements and 18 implementation tasks are recorded in the existing change. Candidate Rust worker and narrow Java/TypeScript/TSX single-file reports now exist behind an opt-in feature; Python is pinned and Rust-loadable but has no CLI fallback. Project-wide native-first routing, qualified grammar ranges, and host integrations remain incomplete. Design examples are not current command output.

## 2. Technology choices and trade-offs

Expand Down Expand Up @@ -191,7 +191,7 @@ The opt-in CLI build first checks for a local ESLint 10 package and a single ord

Import only pinned WASM bytes with upstream license, commit/patch provenance, SHA-256, ABI, tested runtime and language/dialect ranges, corpus reference and known gaps. Verify each copied CodeGraph artifact in the selected Rust Tree-sitter runtime; do not copy TypeScript extraction logic or assume CodeGraph support equals syntax acceptance. A release manifest belongs to distribution assets, not writable `.codeguard/` project state.

Use `codeguard grammar status --format=json` to query the separate source coverage inventory. It reports 32 distinct CodeGraph grammar assets, three CodeGuard candidates, and zero released capabilities without running a parser. The two dependency-provided assets lack pinned bytes, and COBOL exceeds the current 8 MiB loader limit; these remain explicit gaps before any per-language qualification.
Use `codeguard grammar status --format=json` to query the separate source coverage inventory. It reports 32 distinct CodeGraph grammar assets, four CodeGuard asset candidates, and zero released capabilities without running a parser. Python is Rust-loadable but has no CLI lint fallback. The two dependency-provided assets lack pinned bytes, and COBOL exceeds the current 8 MiB loader limit; these remain explicit gaps before any per-language qualification.

Use a parent-controlled parser worker with a total deadline, per-file input bound, memory/process limit and capped diagnostics. Lazy-load selected grammars, parse without general network/filesystem imports, and terminate a stuck worker without losing native results from other modules. Host-specific enforcement and Rust MSRV compatibility must be tested; numeric production budgets remain measurement-driven rather than invented promises.

Expand Down
Loading
Loading