Skip to content

Commit cd0da4f

Browse files
committed
接通C和C++文档修复尝试并限制无进展重复动作
1 parent 33aa17b commit cd0da4f

30 files changed

Lines changed: 3755 additions & 44 deletions

‎README.md‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1125,6 +1125,8 @@ Rust CVE observations now check same-run stability of RustSec crates/rust conten
11251125

11261126
`codeguard comments c api.c --clang-tool /absolute/clang --standard c11 --format=json`; C++ selects `comments cpp api.cpp --standard c++17` with the same tool argument. The measured Apple Clang 21 documentation profile requires an explicit tool and matching standard, without installation. Three precise native SARIF rules cover empty command descriptions, unknown parameter names and return tags on void functions, with repair steps, comment-only scope and original-tool verification argv. Unknown rules remain separate. Invalid reports, changed inputs, cancellation and unresolved preprocessing cannot become source violations.
11271127

1128-
The dedicated `c_family_comments_feedback` 0.1 observation leaves project configuration unknown and detailed-contract qualification ungranted. Completely missing comments may yield zero native diagnostics. Without a workspace, feedback remains 0.1 with `next=null`. An existing workspace now receives feedback0.3, stable file/language/standard/native-rule tasks and next0.29 with all current positions and original-tool rescan argv. Input/tool changes withdraw repair locations; clean rescans keep tasks open. Dedicated task verification now binds the first tool, standard and rule and records local observations while keeping tasks open. Dedicated attempt journals, project checks and Hooks remain unintegrated. Exit3 or cancellation130 persists, without automatic closure or delivery permission. See the [16-case native evidence, execution path and remaining gaps](tests/acceptance/c-family-comments-native.md).
1128+
The dedicated `c_family_comments_feedback` 0.1 observation leaves project configuration unknown and detailed-contract qualification ungranted. Completely missing comments may yield zero native diagnostics. Without a workspace, feedback remains 0.1 with `next=null`. An existing workspace now receives feedback0.4, stable file/language/standard/native-rule tasks and next0.30 with all current positions and original-tool rescan argv. Input/tool changes withdraw repair locations; clean rescans keep tasks open. Dedicated task verification now binds the first tool, standard and rule and records local observations while keeping tasks open. Dedicated attempt journals now retain failures and budgets under the current source/tool context. Project checks and Hooks remain unintegrated. Exit3 or cancellation130 persists, without automatic closure or delivery permission. See the [16-case native evidence, execution path and remaining gaps](tests/acceptance/c-family-comments-native.md).
11291129

11301130
See [C/C++ original-task recheck acceptance](tests/acceptance/c-family-comments-task-recheck.md) for current closed protocols and evidence. Full four-core production qualification remains ungranted.
1131+
1132+
See [C/C++ controlled attempt acceptance](tests/acceptance/c-family-comments-attempt-history.md) for current repair history and protocols. Local history does not replace full four-core production acceptance.

‎README.zh-CN.md‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1102,6 +1102,8 @@ Rust CVE局部观察现在核对同轮RustSec crates/rust内容、成员及物
11021102

11031103
`codeguard comments c api.c --clang-tool /absolute/clang --standard c11 --format=json`;C++ 使用 `comments cpp api.cpp --standard c++17` 并保留同一工具参数。当前仅适配已实测的 Apple Clang 21 独立文档警告档案,明确工具与标准,不隐式安装。原生 SARIF 的空命令描述、错误参数名及 void 返回标签三项精确规则带有修复步骤、仅文档允许范围和原工具复检 argv;未知规则单独保留。坏报告、输入变化、取消和未解析预处理不能成为源码违规。
11041104

1105-
这是 `c_family_comments_feedback` 0.1 的局部观察:项目原配置未知,完整详细契约未授予资格;Clang完全缺失注释也可能零诊断。未绑定工作台时保留0.1/`next=null`;已有工作台现在提供0.3反馈、按文件/语言标准/原规则归并的稳定任务和next0.29,保留全部当前位置及原工具复扫argv。输入或工具变化撤回修复定位,清洁复扫保留开放任务。专用task verify已沿首次工具/标准/规则接通,记录局部事实并保持任务开放;专用尝试日志、项目检查和Hook仍待接通;退出3,取消130,不自动关闭任务或授予门禁。真实16例、执行路径和剩余缺口见[原生文档验收](tests/acceptance/c-family-comments-native.md)。
1105+
这是 `c_family_comments_feedback` 0.1 的局部观察:项目原配置未知,完整详细契约未授予资格;Clang完全缺失注释也可能零诊断。未绑定工作台时保留0.1/`next=null`;已有工作台现在提供0.4反馈、按文件/语言标准/原规则归并的稳定任务和next0.30,保留全部当前位置及原工具复扫argv。输入或工具变化撤回修复定位,清洁复扫保留开放任务。专用task verify已沿首次工具/标准/规则接通,记录局部事实并保持任务开放;专用尝试日志已接通,按当前源码/原工具上下文记录失败与预算;项目检查和Hook仍待接通;退出3,取消130,不自动关闭任务或授予门禁。真实16例、执行路径和剩余缺口见[原生文档验收](tests/acceptance/c-family-comments-native.md)。
11061106

11071107
C/C++ 原任务复检与新封闭协议的当前证据见[复检验收](tests/acceptance/c-family-comments-task-recheck.md);完整四核心生产资格仍未授予。
1108+
1109+
C/C++ 受控尝试、无进展诊断与当前协议见[尝试日志验收](tests/acceptance/c-family-comments-attempt-history.md);本地日志不能替代完整四核心生产验收。

‎crates/codeguard-cli/src/c_family_comments_task_recheck.rs‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,3 +294,38 @@ pub(crate) fn classify(brief: &Value, r: &Value) -> &'static str {
294294
"candidate_absent_unverified_policy"
295295
}
296296
}
297+
298+
/// 计算受控尝试的当前输入身份;包含源码、首次语言/标准与当前工具状态,不能只靠动作名重置预算。
299+
/// 参数为已初始化工作区与原任务摘要;返回当前输入SHA-256,不可读或越界输入返回具体错误。
300+
pub(crate) fn attempt_input_digest(root: &Path, brief: &Value) -> Result<String, &'static str> {
301+
let first = original(root, &reference(brief))?;
302+
let path = first["path"].as_str().ok_or("attempt_scope_invalid")?;
303+
let snapshot =
304+
SourceSnapshot::capture(root, [PathBuf::from(path)], 1, 1024 * 1024, 1024 * 1024)
305+
.map_err(|_| "attempt_source_unavailable")?;
306+
let bytes = snapshot
307+
.files()
308+
.get(&PathBuf::from(path))
309+
.ok_or("attempt_source_unavailable")?;
310+
let selected = Path::new(
311+
first["selected_tool"]
312+
.as_str()
313+
.ok_or("attempt_tool_invalid")?,
314+
);
315+
let canonical = selected.canonicalize().ok();
316+
let tool_bytes = canonical
317+
.as_ref()
318+
.and_then(|p| read_bounded_regular_file(p, 256 * 1024 * 1024).ok());
319+
let state = if tool_bytes.is_some() {
320+
"observed"
321+
} else if std::fs::symlink_metadata(selected)
322+
.is_err_and(|e| e.kind() == std::io::ErrorKind::NotFound)
323+
{
324+
"missing"
325+
} else {
326+
"unavailable"
327+
};
328+
let payload = json!({"version":"clang-documentation-attempt-input-v1","scope":path,"language":first["language"],"standard":first["standard"],"profile":first["profile"],"source_sha256":format!("{:x}",Sha256::digest(bytes)),"selected_tool":first["selected_tool"],"canonical_tool":canonical,"tool_state":state,"tool_sha256":tool_bytes.as_ref().map(|b|format!("{:x}",Sha256::digest(b)))});
329+
let bytes = serde_json::to_vec(&payload).map_err(|_| "attempt_input_encoding_failed")?;
330+
Ok(format!("{:x}", Sha256::digest(bytes)))
331+
}

‎crates/codeguard-cli/src/c_family_comments_workbench.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ pub(crate) fn resolve_root(
3131
}
3232
/// 保存并同步局部观察;中断后不开始新的持久化阶段。
3333
pub(crate) fn connect(root: &Path, tool: &Path, report: &mut Value, deadline: Instant) {
34-
report["schema_version"] = json!("0.3.0");
34+
report["schema_version"] = json!("0.4.0");
3535
report["task_workflow_status"] = json!("partial");
3636
let argv = report["verification_command"]
3737
.as_array_mut()

‎crates/codeguard-cli/src/next_command.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2429,7 +2429,7 @@ fn run_sequence(run_id: &str) -> Option<u128> {
24292429

24302430
fn view(disposition: &str, reason: &str, brief: Value, actions: Value) -> Value {
24312431
json!({
2432-
"schema_version":if brief["schema_version"] == "0.29.0" {json!("0.29.0")}else if brief["schema_version"] == "0.28.0" {json!("0.28.0")}else if brief["schema_version"] == "0.27.0" {json!("0.27.0")}else if brief["schema_version"] == "0.26.0" {json!("0.26.0")}else if brief["schema_version"] == "0.25.0" {json!("0.25.0")}else if brief["schema_version"] == "0.24.0" {json!("0.24.0")}else if brief["schema_version"] == "0.23.0" {json!("0.23.0")}else if brief["schema_version"] == "0.22.0" {json!("0.22.0")}else if brief["schema_version"] == "0.21.0" {json!("0.21.0")}else if brief["schema_version"] == "0.20.0" {json!("0.20.0")}else if brief["checker_id"] == "shell.shellcheck" {json!("0.17.0")} else if brief["checker_id"] == "go.vet" {json!("0.13.0")} else if brief["checker_id"] == "syntax.native_confirmation" {brief["schema_version"].clone()} else {json!("0.1.0")}, "report_type":"repair_brief_preview",
2432+
"schema_version":if brief["schema_version"] == "0.30.0" {json!("0.30.0")}else if brief["schema_version"] == "0.29.0" {json!("0.29.0")}else if brief["schema_version"] == "0.28.0" {json!("0.28.0")}else if brief["schema_version"] == "0.27.0" {json!("0.27.0")}else if brief["schema_version"] == "0.26.0" {json!("0.26.0")}else if brief["schema_version"] == "0.25.0" {json!("0.25.0")}else if brief["schema_version"] == "0.24.0" {json!("0.24.0")}else if brief["schema_version"] == "0.23.0" {json!("0.23.0")}else if brief["schema_version"] == "0.22.0" {json!("0.22.0")}else if brief["schema_version"] == "0.21.0" {json!("0.21.0")}else if brief["schema_version"] == "0.20.0" {json!("0.20.0")}else if brief["checker_id"] == "shell.shellcheck" {json!("0.17.0")} else if brief["checker_id"] == "go.vet" {json!("0.13.0")} else if brief["checker_id"] == "syntax.native_confirmation" {brief["schema_version"].clone()} else {json!("0.1.0")}, "report_type":"repair_brief_preview",
24332433
"operation":"next", "command_status":"complete", "exit_code":0,
24342434
"disposition":disposition, "reason":reason,
24352435
"repair_brief":brief, "next_actions":actions,

‎crates/codeguard-cli/src/next_command/c_family_comments_candidate.rs‎

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -153,17 +153,70 @@ pub(super) fn candidate(root: &Path, id: &str, fact: &Value) -> Result<Candidate
153153
} else {
154154
"native_rule_observed"
155155
};
156-
let actionable = status == "native_rule_observed";
156+
let source_actionable = status == "native_rule_observed";
157+
let environment_actionable = kind == "blocker"
158+
&& status == "native_incomplete"
159+
&& latest["native"]["reason"] == "clang_tool_unavailable"
160+
&& first["native"]["tool_sha256"].is_null();
161+
let actionable = source_actionable || environment_actionable;
157162
let guidance = codeguard_adapters::clang_documentation_guidance(rule).unwrap_or(json!({"rule_summary":"原生文档检查未完成或存在未适配规则","repair_steps":["核对原生原因、工具与源码范围,再运行原文档检查。"]}));
158-
let brief = json!({"schema_version":"0.29.0","task_id":id,"kind":kind,"checker_id":checker(&first),"scope":first["path"],"source_sha256":latest["source_sha256"],"native_rule_id":if kind == "finding" {json!(rule)} else {Value::Null},
159-
"evidence_ref":{"first_run_id":run,"first_report_sha256":digest},"current_run_id":latest["run_id"],"observation_status":status,"native_reason":latest["native"]["reason"],"native_positions":if actionable {json!(present)} else {json!([])},
163+
let mut brief = json!({"schema_version":"0.30.0","task_id":id,"kind":kind,"checker_id":checker(&first),"scope":first["path"],"source_sha256":latest["source_sha256"],"native_rule_id":if kind == "finding" {json!(rule)} else {Value::Null},
164+
"evidence_ref":{"first_run_id":run,"first_report_sha256":digest},"current_run_id":latest["run_id"],"observation_status":status,"native_reason":latest["native"]["reason"],"native_positions":if source_actionable {json!(present)} else {json!([])},
160165
"unclassified_native_diagnostics":latest["native"]["diagnostics"].as_array().into_iter().flatten().filter(|d| d["rule_id"].as_str().is_some_and(|r| codeguard_adapters::clang_documentation_guidance(r).is_none())).cloned().collect::<Vec<_>>(),
161-
"rule_basis":guidance["rule_summary"],"constraints":["仅文档注释;保留源码API与行为","本地报告非可信政策,不能关闭任务或自批白名单"],"allowed_paths":if actionable {json!([first["path"]])} else {json!([])},
166+
"rule_basis":guidance["rule_summary"],"constraints":["仅文档注释;保留源码API与行为","本地报告非可信政策,不能关闭任务或自批白名单"],"allowed_paths":if source_actionable {json!([first["path"]])} else {json!([])},
162167
"disposition":if actionable {"actionable"} else {"needs_decision"},"reason_code":status,"step":guidance["repair_steps"],"recheck_argv":["codeguard","task","verify",id,root,"--clang-tool",first["selected_tool"],"--format=json"],
163-
"history":{"status":"native_observations_only","task_verify":"partial","attempt_journal":"not_integrated"},"closure_condition":"原工具局部任务复检已接通;完整详细文档覆盖、尝试历史和可信关闭仍待完成;零诊断或勾选不关闭","authority":"local_unverified","delivery_decision":"not_evaluated"});
168+
"closure_condition":"尝试和原工具局部复检均不关闭;仍需完整详细文档覆盖、可信政策与关闭/复发验证。零诊断、勾选或本地失败记录均不能放行。","authority":"local_unverified","delivery_decision":"not_evaluated"});
169+
brief["affected_paths"] = json!([first["path"]]);
170+
brief["action_id"] = json!(super::canonical_action_id(&brief)?);
171+
if environment_actionable {
172+
brief["step"] = json!([format!(
173+
"恢复首次选择的原工具路径 {},核对Apple Clang21与固定标准,再执行原任务复检;不修改无关源码。",
174+
first["selected_tool"].as_str().unwrap_or("")
175+
)]);
176+
}
177+
let history = crate::task_attempt_command::attempt_history(root, id, &brief)?;
178+
let mut priority = if source_actionable { 1 } else { 0 };
179+
if history["open_attempt_id"].is_string() {
180+
brief["disposition"] = json!("waiting");
181+
brief["reason_code"] = json!("attempt_in_progress");
182+
brief["step"] = json!(["由持有租约的执行者记录当前尝试结果;结束前不重复修复同一任务。"]);
183+
priority = 0;
184+
} else if history["awaiting_verification"] == true {
185+
brief["disposition"] = json!("verification_required");
186+
brief["reason_code"] = json!("original_verification_required");
187+
brief["step"] = json!([
188+
"修复尝试已结束;按首次工具、标准与规则执行task verify,不能用再次勾选任务代替复检。"
189+
]);
190+
priority = 0;
191+
} else if history["unverified_prior_attempt_count"]
192+
.as_u64()
193+
.unwrap_or(0)
194+
> 0
195+
{
196+
brief["disposition"] = json!("needs_decision");
197+
brief["reason_code"] = json!("historical_verification_evidence_unavailable");
198+
brief["step"] = json!([
199+
"先恢复当前输入下早先尝试的原复检报告或调查失效原因;缺失本地证据不能删除失败尝试或恢复修复预算。"
200+
]);
201+
priority = 0;
202+
} else if history["no_progress_count"].as_u64().unwrap_or(0) >= 2 && actionable {
203+
brief["disposition"] = json!("needs_decision");
204+
brief["reason_code"] = json!("no_progress_budget_exhausted");
205+
brief["step"] = json!([format!(
206+
"同一源码、原工具上下文与动作已连续无进展;核对规则 {}、原生原因 {} 和最近失败记录,提出具体修复或误报纠错决策;重命名动作、重复扫描不能重置预算。",
207+
rule,
208+
latest["native"]["reason"].as_str().unwrap_or("unknown")
209+
)]);
210+
priority = 0;
211+
}
212+
if brief["disposition"] != "actionable" {
213+
brief["allowed_paths"] = json!([]);
214+
}
215+
brief["history"] = history;
216+
164217
Ok(Candidate {
165218
id: id.into(),
166-
priority: if actionable { 1 } else { 0 },
219+
priority,
167220
brief,
168221
})
169222
}

0 commit comments

Comments
 (0)