Skip to content

Commit 863ffef

Browse files
committed
补充 CFQuery PostgreSQL 方言原生反证并保护待裁定语料
1 parent 1f54ebd commit 863ffef

20 files changed

Lines changed: 719 additions & 1 deletion

‎.github/workflows/ci.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ jobs:
4949
- name: Verify Linux WASM worker resource boundary
5050
run: |
5151
# 帮助目录须保留当前构建特性;默认 suite 无法证明 WASM 入口状态。
52-
cargo test --locked -p codeguard-cli --features wasm-precheck --test help_command_contract --test rules_list_cli --test version_cli --test rust_lint_cli --test ruby_lint_cli --test check_all_ruby --test ruby_native_hook --test ruby_project_version --test shell_lint_cli --test shell_workbench --test check_all_shell --test shell_native_hook
52+
cargo test --locked -p codeguard-cli --features wasm-precheck --test help_command_contract --test rules_list_cli --test version_cli --test rust_lint_cli --test ruby_lint_cli --test check_all_ruby --test ruby_native_hook --test ruby_project_version --test shell_lint_cli --test shell_workbench --test check_all_shell --test shell_native_hook --test cfquery_postgres_dialect
5353
cargo test --locked -p codeguard-cli --features wasm-precheck --test workspace_msrv --test crate_boundaries
5454
cargo test -p codeguard-runtime --features wasm-precheck --test process_contract
5555
cargo test -p codeguard-runtime --features wasm-precheck --test wasm_grammar_load --test wasm_recovery_scan --test wasm_empty_block_scan --test wasm_root_child_scan --test dart_upstream_corpus

‎README.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -741,3 +741,5 @@ flowchart LR
741741
Edit feedback uses outer protocol 0.21 and inner 0.11, preserving earlier schemas. Dialogue includes current SC rules, Unicode scalar positions, persisted task IDs, and recheck commands; source and free-form tool messages are excluded. Missing tools, unsupported dialects, selected-tool failures, and persistence failures remain incomplete. No bundled Shell WASM fallback is claimed. Failed writes run no checker; repair-ready events call the existing task verifier, and zero diagnostics never close a task.
742742

743743
The [acceptance record](tests/acceptance/shellcheck-hook-baseline.md) distinguishes real ShellCheck output, controlled fixtures, offline npm installation, and live host sessions. Claude-shaped replay does not prove acceptance in a real installed host or a complete project delivery gate.
744+
745+
CFQuery SQL comparisons require a database dialect. PostgreSQL accepts an empty SELECT list but rejects its DISTINCT variant; the fixed WASM reports zero recoveries for both. The isolated native evidence does not promote generic pending labels. See [dialect evidence](docs/CFQuery-SQL-Dialect-Evidence.md); project SQL adaptation and grammar repair remain open.

‎README.zh-CN.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -724,3 +724,5 @@ flowchart LR
724724
编辑反馈外层协议0.21、内层0.11,旧协议保留。对话仅显示当前 SC 规则、Unicode 标量位置、实际已同步任务 ID 及复检命令,排除源码和原生自由文本。缺工具、不支持方言、工具失败和工作台保存失败保持未完成;当前不存在 Shell 内置 WASM,不虚构兜底。失败写入不检查;`repair_ready` 复用既有任务复检,零诊断不关闭问题。
725725

726726
[验收记录](tests/acceptance/shellcheck-hook-baseline.md)区分真实 ShellCheck 报告、受控工具测试、npm 离线安装及实际宿主会话。Claude 形状重放通过不代表真实已安装宿主或完整项目门禁已验收。
727+
728+
CFQuery的SQL语法对照必须绑定数据库方言:PostgreSQL可接受空SELECT列表,却拒绝DISTINCT空列表。当前隔离原生验证揭示固定WASM对两者均零恢复,不能将无方言样例升级为已确认错误。详见[方言证据](docs/CFQuery-SQL-Dialect-Evidence.zh_CN.md);项目SQL原生适配与grammar修复仍开放。
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
use codeguard_runtime::{ProcessOutcome, ProcessSpec, Termination, run_process};
2+
use serde_json::Value;
3+
use sha2::{Digest, Sha256};
4+
use std::{
5+
collections::BTreeMap,
6+
ffi::OsString,
7+
path::PathBuf,
8+
sync::atomic::AtomicBool,
9+
time::{Duration, Instant, SystemTime, UNIX_EPOCH},
10+
};
11+
12+
fn oracle() -> Value {
13+
serde_json::from_slice(include_bytes!(
14+
"../../../tests/acceptance/evidence/cfquery-postgres-oracle-2026-10-06.json"
15+
))
16+
.unwrap()
17+
}
18+
19+
#[test]
20+
fn native_sql_dialect_counterevidence_does_not_relabel_generic_pending_case() {
21+
let evidence = oracle();
22+
assert_eq!(evidence["authority"], "development_only");
23+
assert_eq!(evidence["grammar_qualified"], false);
24+
assert_eq!(evidence["delivery_decision"], "not_evaluated");
25+
let cases = evidence["cases"].as_array().unwrap();
26+
assert_eq!(cases.len(), 2);
27+
for case in cases {
28+
assert_eq!(case["dialect"], "postgresql");
29+
assert_eq!(case["query_execution"], "not_executed_prepare_only");
30+
assert_eq!(
31+
case["source_sha256"],
32+
format!(
33+
"{:x}",
34+
Sha256::digest(case["source"].as_str().unwrap().as_bytes())
35+
)
36+
);
37+
}
38+
assert_eq!(cases[0]["native_valid"], true);
39+
assert_eq!(cases[1]["native_valid"], false);
40+
assert_eq!(cases[1]["sqlstate"], "42601");
41+
let corpus: Value = serde_json::from_slice(include_bytes!(
42+
"../../../tests/fixtures/grammar_regression_v0_2.json"
43+
))
44+
.unwrap();
45+
let generic = corpus["cases"]
46+
.as_array()
47+
.unwrap()
48+
.iter()
49+
.find(|c| c["id"] == "cfquery-missing_select_list")
50+
.unwrap();
51+
assert_eq!(generic["source_sha256"], cases[0]["source_sha256"]);
52+
assert_eq!(generic["label"], "pending");
53+
assert_eq!(generic["cohort"], "provisional_syntax");
54+
}
55+
56+
/// 独占且无网络的原生SQL语法夹具;来源:OpenSpec S14.17明确方言原生对照。
57+
struct PostgresFixture {
58+
tool: PathBuf,
59+
id: Option<String>,
60+
}
61+
impl PostgresFixture {
62+
fn run(&self, args: &[&str]) -> ProcessOutcome {
63+
let env = [
64+
"PATH",
65+
"HOME",
66+
"DOCKER_HOST",
67+
"DOCKER_CONTEXT",
68+
"DOCKER_CONFIG",
69+
]
70+
.into_iter()
71+
.filter_map(|k| std::env::var_os(k).map(|v| (OsString::from(k), v)))
72+
.collect::<BTreeMap<_, _>>();
73+
run_process(
74+
&ProcessSpec {
75+
executable: self.tool.clone(),
76+
args: args.iter().map(OsString::from).collect(),
77+
cwd: std::env::temp_dir(),
78+
env,
79+
stdin: None,
80+
deadline: Instant::now() + Duration::from_secs(15),
81+
output_limit_bytes: 64 * 1024,
82+
},
83+
&AtomicBool::new(false),
84+
)
85+
}
86+
}
87+
impl Drop for PostgresFixture {
88+
fn drop(&mut self) {
89+
if let Some(id) = &self.id {
90+
let _ = self.run(&["rm", "--force", id]);
91+
}
92+
}
93+
}
94+
95+
#[test]
96+
#[ignore = "requires explicit CODEGUARD_DOCKER_TOOL and already cached pinned PostgreSQL image; never pulls"]
97+
fn isolated_native_postgres_confirms_empty_projection_and_distinct_counterexample() {
98+
let tool =
99+
PathBuf::from(std::env::var_os("CODEGUARD_DOCKER_TOOL").expect("explicit Docker path"));
100+
assert!(tool.is_absolute());
101+
let mut fixture = PostgresFixture { tool, id: None };
102+
let evidence = oracle();
103+
let image = evidence["image_id"].as_str().unwrap();
104+
let existing = fixture.run(&["image", "inspect", "--format", "{{.Id}}", image]);
105+
assert_eq!(existing.termination, Termination::Exited(0));
106+
assert_eq!(String::from_utf8(existing.stdout).unwrap().trim(), image);
107+
let name = format!(
108+
"codeguard-pg-oracle-{}-{}",
109+
std::process::id(),
110+
SystemTime::now()
111+
.duration_since(UNIX_EPOCH)
112+
.unwrap()
113+
.as_nanos()
114+
);
115+
let started = fixture.run(&[
116+
"run",
117+
"--detach",
118+
"--rm",
119+
"--pull=never",
120+
"--network",
121+
"none",
122+
"--name",
123+
&name,
124+
"--tmpfs",
125+
"/var/lib/postgresql:rw",
126+
"-e",
127+
"PGDATA=/var/lib/postgresql/data",
128+
"-e",
129+
"POSTGRES_HOST_AUTH_METHOD=trust",
130+
image,
131+
]);
132+
assert_eq!(
133+
started.termination,
134+
Termination::Exited(0),
135+
"{:?}",
136+
started.stderr
137+
);
138+
let id = String::from_utf8(started.stdout).unwrap().trim().to_owned();
139+
assert!(id.len() == 64 && id.bytes().all(|b| b.is_ascii_hexdigit()));
140+
fixture.id = Some(id.clone());
141+
let mut ready = false;
142+
for _ in 0..40 {
143+
if fixture
144+
.run(&["exec", &id, "pg_isready", "-U", "postgres"])
145+
.termination
146+
== Termination::Exited(0)
147+
{
148+
ready = true;
149+
break;
150+
}
151+
std::thread::sleep(Duration::from_millis(250));
152+
}
153+
assert!(ready, "isolated server readiness exceeded");
154+
let version = fixture.run(&["exec", &id, "postgres", "--version"]);
155+
assert_eq!(version.termination, Termination::Exited(0));
156+
assert_eq!(
157+
String::from_utf8(version.stdout).unwrap().trim(),
158+
evidence["server_version"].as_str().unwrap()
159+
);
160+
for case in evidence["cases"].as_array().unwrap() {
161+
let sql = format!(
162+
"CREATE TEMP TABLE users (id integer); PREPARE codeguard_case AS {};",
163+
case["source"].as_str().unwrap()
164+
);
165+
let result = fixture.run(&[
166+
"exec",
167+
&id,
168+
"psql",
169+
"-X",
170+
"-U",
171+
"postgres",
172+
"-v",
173+
"ON_ERROR_STOP=1",
174+
"-v",
175+
"VERBOSITY=verbose",
176+
"-c",
177+
&sql,
178+
]);
179+
assert_eq!(
180+
result.termination,
181+
Termination::Exited(case["native_exit_code"].as_i64().unwrap() as i32)
182+
);
183+
if case["native_valid"] == false {
184+
assert!(String::from_utf8(result.stderr).unwrap().contains("42601"));
185+
}
186+
}
187+
let removed = fixture.run(&["rm", "--force", &id]);
188+
assert_eq!(removed.termination, Termination::Exited(0));
189+
fixture.id = None;
190+
}
191+
192+
#[cfg(all(feature = "wasm-precheck", unix))]
193+
#[test]
194+
fn current_cfquery_worker_preserves_real_native_disagreement_without_fake_clean() {
195+
let evidence = oracle();
196+
let directory = std::env::temp_dir()
197+
.canonicalize()
198+
.unwrap()
199+
.join(format!("cg-cfquery-dialect-{}", std::process::id()));
200+
std::fs::create_dir(&directory).unwrap();
201+
for case in evidence["cases"].as_array().unwrap() {
202+
let source = directory.join(format!("{}.sql", case["id"].as_str().unwrap()));
203+
std::fs::write(&source, case["source"].as_str().unwrap()).unwrap();
204+
let output = std::process::Command::new(env!("CARGO_BIN_EXE_codeguard"))
205+
.args(["grammar", "probe", "cfquery"])
206+
.arg(&source)
207+
.arg("--format=json")
208+
.output()
209+
.unwrap();
210+
assert_eq!(output.status.code(), Some(3));
211+
let report: Value = serde_json::from_slice(&output.stdout).unwrap();
212+
assert_eq!(report["source_sha256"], case["source_sha256"]);
213+
if case["native_valid"] == true {
214+
assert_eq!(report["recoveries"], serde_json::json!([]));
215+
}
216+
assert_eq!(report["status"], "incomplete");
217+
assert_eq!(report["grammar_qualified"], false);
218+
assert_eq!(report["delivery_decision"], "not_evaluated");
219+
}
220+
std::fs::remove_dir_all(directory).unwrap();
221+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# CFQuery SQL dialect evidence
2+
3+
A grammar's zero recovery count is not a SQL semantic verdict. PostgreSQL permits `SELECT FROM users` with an empty output list, while `SELECT DISTINCT FROM users` is a syntax error. The [official SELECT reference](https://www.postgresql.org/docs/18/sql-select.html#SQL-SELECT-COMPATIBILITY) documents this distinction.
4+
5+
An isolated, already cached PostgreSQL 18.6 fixture confirms both outcomes using PREPARE without executing the SELECT queries. The pinned CFQuery WASM reports no recovery nodes for either source. The second sample is therefore a real disagreement for this database dialect; the first cannot be universally described as invalid SQL.
6+
7+
```mermaid
8+
flowchart LR
9+
A[CFQuery source and datasource context] --> B{Dialect established?}
10+
B -->|No| C[Retain unresolved dialect and provisional label]
11+
B -->|Yes| D[Applicable native syntax check]
12+
A --> E[Bounded WASM candidate observation]
13+
D --> F[Compare the same source bytes]
14+
E --> F
15+
F --> G[Preserve native disagreement and evidence scope]
16+
```
17+
18+
This diagram describes the required project integration. Current delivery contains the isolated development oracle, regression tests, and candidate probes; it does not add a project SQL checker. The existing generic case remains pending, frozen corpora and historical metrics are preserved, and neither grammar qualification nor a whitelist is approved. The two targeted samples are not independent holdout or language accuracy acceptance.
19+
20+
The [acceptance record](../tests/acceptance/cfquery-postgres-dialect.md) identifies the immutable image, version, source fingerprints, runtime-controlled process boundaries, offline/no-network fixture, and cleanup. Future integration must establish datasource dialect/version and retain dynamic-template and schema uncertainty before classifying project code.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# CFQuery SQL 方言证据
2+
3+
零恢复节点不等于完整SQL语法或语义正确。PostgreSQL允许空输出列表的`SELECT FROM users`,却拒绝`SELECT DISTINCT FROM users`;[官方SELECT说明](https://www.postgresql.org/docs/18/sql-select.html#SQL-SELECT-COMPATIBILITY)明确区分两者。
4+
5+
本机已有PostgreSQL18.6固定镜像在无网络、无持久存储的隔离夹具中,通过PREPARE确认上述结果,不执行待检SELECT。固定CFQuery WASM对两份同字节输入都报告零恢复。因此第二份是有明确方言的真实漏检,第一份不能被一概认为是非法SQL。
6+
7+
```mermaid
8+
flowchart LR
9+
A[CFQuery源码及datasource上下文] --> B{数据库方言明确?}
10+
B -->|否| C[保留未知方言与待裁定标签]
11+
B -->|是| D[适用的原生语法检查]
12+
A --> E[有界WASM候选观察]
13+
D --> F[比较同一源码字节]
14+
E --> F
15+
F --> G[保留差异与证据适用范围]
16+
```
17+
18+
图中表达项目接入要求。当前交付是隔离原生对照、回归契约和候选观察,尚未新增项目SQL检查器。原无方言样例保持pending,冻结语料和历史指标保留,不批准grammar资格、白名单或关闭任务。这两个有目的样例不是独立holdout,也不是语言精度验收。
19+
20+
[验收记录](../tests/acceptance/cfquery-postgres-dialect.md)给出镜像、版本、源码摘要、Rust受控进程、禁止拉取/网络及清理证据。后续项目接入须先确认datasource方言和版本,保留动态模板及schema依赖的不确定性。

‎docs/Codeguard-Architecture.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1065,3 +1065,5 @@ flowchart LR
10651065
Edit feedback uses outer protocol 0.21 and inner 0.11, preserving earlier schemas. Dialogue includes current SC rules, Unicode scalar positions, persisted task IDs, and recheck commands; source and free-form tool messages are excluded. Missing tools, unsupported dialects, selected-tool failures, and persistence failures remain incomplete. No bundled Shell WASM fallback is claimed. Failed writes run no checker; repair-ready events call the existing task verifier, and zero diagnostics never close a task.
10661066

10671067
The [acceptance record](../tests/acceptance/shellcheck-hook-baseline.md) distinguishes real ShellCheck output, controlled fixtures, offline npm installation, and live host sessions. Claude-shaped replay does not prove acceptance in a real installed host or a complete project delivery gate.
1068+
1069+
CFQuery SQL comparisons require a database dialect. PostgreSQL accepts an empty SELECT list but rejects its DISTINCT variant; the fixed WASM reports zero recoveries for both. The isolated native evidence does not promote generic pending labels. See [dialect evidence](CFQuery-SQL-Dialect-Evidence.md); project SQL adaptation and grammar repair remain open.

‎docs/Codeguard-Architecture.zh_CN.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1065,3 +1065,5 @@ flowchart LR
10651065
编辑反馈外层协议0.21、内层0.11,旧协议保留。对话仅显示当前 SC 规则、Unicode 标量位置、实际已同步任务 ID 及复检命令,排除源码和原生自由文本。缺工具、不支持方言、工具失败和工作台保存失败保持未完成;当前不存在 Shell 内置 WASM,不虚构兜底。失败写入不检查;`repair_ready` 复用既有任务复检,零诊断不关闭问题。
10661066

10671067
[验收记录](../tests/acceptance/shellcheck-hook-baseline.md)区分真实 ShellCheck 报告、受控工具测试、npm 离线安装及实际宿主会话。Claude 形状重放通过不代表真实已安装宿主或完整项目门禁已验收。
1068+
1069+
CFQuery的SQL语法对照必须绑定数据库方言:PostgreSQL可接受空SELECT列表,却拒绝DISTINCT空列表。当前隔离原生验证揭示固定WASM对两者均零恢复,不能将无方言样例升级为已确认错误。详见[方言证据](CFQuery-SQL-Dialect-Evidence.zh_CN.md);项目SQL原生适配与grammar修复仍开放。

‎docs/Codeguard-Technical-Design.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1544,3 +1544,5 @@ flowchart LR
15441544
Edit feedback uses outer protocol 0.21 and inner 0.11, preserving earlier schemas. Dialogue includes current SC rules, Unicode scalar positions, persisted task IDs, and recheck commands; source and free-form tool messages are excluded. Missing tools, unsupported dialects, selected-tool failures, and persistence failures remain incomplete. No bundled Shell WASM fallback is claimed. Failed writes run no checker; repair-ready events call the existing task verifier, and zero diagnostics never close a task.
15451545

15461546
The [acceptance record](../tests/acceptance/shellcheck-hook-baseline.md) distinguishes real ShellCheck output, controlled fixtures, offline npm installation, and live host sessions. Claude-shaped replay does not prove acceptance in a real installed host or a complete project delivery gate.
1547+
1548+
CFQuery SQL comparisons require a database dialect. PostgreSQL accepts an empty SELECT list but rejects its DISTINCT variant; the fixed WASM reports zero recoveries for both. The isolated native evidence does not promote generic pending labels. See [dialect evidence](CFQuery-SQL-Dialect-Evidence.md); project SQL adaptation and grammar repair remain open.

‎docs/Codeguard-Technical-Design.zh_CN.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1545,3 +1545,5 @@ flowchart LR
15451545
编辑反馈外层协议0.21、内层0.11,旧协议保留。对话仅显示当前 SC 规则、Unicode 标量位置、实际已同步任务 ID 及复检命令,排除源码和原生自由文本。缺工具、不支持方言、工具失败和工作台保存失败保持未完成;当前不存在 Shell 内置 WASM,不虚构兜底。失败写入不检查;`repair_ready` 复用既有任务复检,零诊断不关闭问题。
15461546

15471547
[验收记录](../tests/acceptance/shellcheck-hook-baseline.md)区分真实 ShellCheck 报告、受控工具测试、npm 离线安装及实际宿主会话。Claude 形状重放通过不代表真实已安装宿主或完整项目门禁已验收。
1548+
1549+
CFQuery的SQL语法对照必须绑定数据库方言:PostgreSQL可接受空SELECT列表,却拒绝DISTINCT空列表。当前隔离原生验证揭示固定WASM对两者均零恢复,不能将无方言样例升级为已确认错误。详见[方言证据](CFQuery-SQL-Dialect-Evidence.zh_CN.md);项目SQL原生适配与grammar修复仍开放。

0 commit comments

Comments
 (0)