feat: INV-16 弱模型安全任务描述 — Arc 危险词检测 + 否定约束强制

问题:Do Worker 可能是廉价模型,字面理解任务。"清理旧产品实现"+src/ = 全删。
根因:Arc 用强模型规划,没考虑 Do Worker 推理能力弱。

修复:
- SKILL.md: 新增 INV-16 — 禁止歧义词、否定约束显式化、文件范围精确化、完成标准可验证
- commands/arc.md: 新增"弱模型安全"章节,4 条硬规则
- arc_mode.py: _audit_task_safety() 代码级扫描危险词和目录级文件范围
  - 危险词: 清理/清除/删除所有/重构整个/重写全部 等
  - 目录级范围(src/)+无否定约束 → 警告
  - 警告写入 execution-plan.json 的 safetyWarnings 字段
  - parallel_review_mode 在写 plan 前自动执行

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
AirLongDian
2026-06-12 09:36:28 +08:00
parent 759922ceb9
commit 3dcb87f941
3 changed files with 49 additions and 0 deletions

View File

@@ -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)