diff --git a/commands/arc.md b/commands/arc.md index cb08848..290ebf1 100644 --- a/commands/arc.md +++ b/commands/arc.md @@ -56,6 +56,15 @@ ArcPhaseGate 控制 execution-plan.json 写入权限。phase 默认 `discussing` **推进方式**:用户说"确认"/"可以"/"同意"后,`ArcPhaseGate.confirm_architecture()` 自动推进。不丢失(已修复)。 +## 弱模型安全(INV-16) + +Do Worker 可能是廉价模型/本地小模型,字面理解任务无推断能力。产出每个任务时必须: + +1. **禁止歧义词** — 不用"清理"、"重构"、"优化"等宽泛动词,指明具体改什么 +2. **否定约束显式化** — 写明**不做什么**(如"不删除 src/ 下现有模块") +3. **文件范围精确化** — `files_dirs` 精确到文件级,不写 `src/` 目录级 +4. **完成标准可验证** — `done_when` 能用 `grep`/`diff`/`cmake --build` 客观验证 + ## Logging Standard When planning C++ projects, the first task MUST be "integrate spdlog" if not already present. All generated code must use spdlog, not std::cout/qDebug/printf. \ No newline at end of file diff --git a/lib/air_runtime/modes/arc_mode.py b/lib/air_runtime/modes/arc_mode.py index c926249..6d710db 100644 --- a/lib/air_runtime/modes/arc_mode.py +++ b/lib/air_runtime/modes/arc_mode.py @@ -21,6 +21,30 @@ from air_runtime.paths import event_log_path from air_runtime.utils import ordered_unique +# INV-16: 弱模型安全 — 危险词列表 +DANGEROUS_TASK_WORDS = [ + "清理", "清除", "删除所有", "重构整个", "重写全部", + "clear", "delete all", "remove all", "rewrite entire", "refactor whole", +] +DIR_LEVEL_FILE_SCOPE_PATTERNS = [ + "src/", "lib/", "include/", "tests/", "modules/", +] + +def _audit_task_safety(task_id: str, task_text: str, files_dirs: str, done_when: str) -> list[str]: + """INV-16: 扫描单个任务的危险词和宽泛文件范围,返回警告列表。""" + warnings = [] + text_lower = task_text.lower() + for word in DANGEROUS_TASK_WORDS: + if word.lower() in text_lower: + warnings.append(f"[{task_id}] 含危险词 '{word}' — 建议改为精确描述(如'修改 CMakeLists.txt 去掉 sipclient 依赖'而非'清理{word}')") + for pattern in DIR_LEVEL_FILE_SCOPE_PATTERNS: + if pattern in files_dirs and not any(f.endswith(ext) for ext in [".cpp", ".hpp", ".h", ".py", ".ts", ".md", ".json", ".txt", ".cmake"] for f in files_dirs.split(",")): + if not done_when or "不" not in done_when: + warnings.append(f"[{task_id}] 文件范围含目录级 '{pattern}' 但 done_when 无否定约束 — Worker 可能误解文件范围") + break + return warnings + + class ArcPhaseGate: """三阶段门控:discussing → proposing → confirmed。 execution-plan.json 仅在 phase=confirmed 时允许写入。 @@ -219,6 +243,14 @@ def parallel_review_mode(project_root: Path, todo_path: Path) -> dict: graph.add_edge(Edge(source=edge_info["source"], target=edge_info["target"], kind=edge_info.get("kind", "dependency"))) + # INV-16: 弱模型安全审计 — 扫描所有 TODO 任务的危险词和宽泛文件范围 + safety_warnings = [] + for nid, node in graph.nodes.items(): + if node.status == "TODO": + safety_warnings.extend( + _audit_task_safety(nid, node.task, node.files_dirs, node.done_when) + ) + _export_task_graph_json(graph, paths["task_graph_json"]) # 生成执行计划 @@ -233,6 +265,7 @@ def parallel_review_mode(project_root: Path, todo_path: Path) -> dict: "serializationPoints": review.serialization_points, "doneWhenViolations": done_when_violations, # P1-19.1: Done When 不含"测试通过"的任务 "boundaryTestTasks": [n.id for n in graph.nodes.values() if n.test_required], + "safetyWarnings": safety_warnings, # INV-16: 弱模型安全警告 } atomic_json_write(paths["execution_plan_json"], execution_plan) diff --git a/skills/airplan/SKILL.md b/skills/airplan/SKILL.md index 86e5ae1..70fef1e 100644 --- a/skills/airplan/SKILL.md +++ b/skills/airplan/SKILL.md @@ -98,6 +98,13 @@ AirDo 处理 UI 任务时必须使用 frontend-design Skill: - 自动 git revert 已合并的旧代码 - AirRvr 终审检查 INVALIDATED 任务代码是否已清理 +### INV-16 弱模型安全任务描述 +AirArc 产出任务时,假设 Do Worker 是**廉价模型/本地小模型**,字面理解任务无推断能力: +- **禁止歧义词**:禁止"清理"、"重构"、"优化"等宽泛动词,必须指明具体改什么文件、改什么内容 +- **否定约束显式化**:任务必须写明**不做什么**(如"不删除 src/ 下现有模块文件"、"不修改 CMakeLists.txt 中已有 target") +- **文件范围精确化**:`files_dirs` 不能写 `src/` 这种目录级范围,必须精确到具体文件 +- **完成标准可验证**:`done_when` 必须能用 `grep`/`diff`/`cmake --build` 等命令客观验证,不含主观判断 + ## L1 代码级保障(不依赖 LLM 自觉) 以下功能由引擎代码强制执行,SKILL.md 指令仅作辅助: