fix(s03): match Windows del as a command word

This commit is contained in:
mameikagou
2026-08-26 00:18:53 +08:00
parent 04486201fc
commit 44e33d0ec3
55 changed files with 866 additions and 331 deletions

View File

@@ -222,6 +222,10 @@ command line から直接 Goal を設定することもできます。
python s17_goal_loop/code.py "/goal python -m pytest が exit code 0 で終了する"
```
## 継承する権限ルール
この章は s04 の permission hook を引き継ぐ。command の先頭または shell separator`;``&&``||``|``&`、括弧、改行)の直後にある完全な `rm`/`del` command word だけを大文字小文字を区別せず検出する。`model``delimiter``echo del test.txt` は危険な command として扱わない。
## s16 との関係
s16 は「複数の仕事をどう実行するか」を扱いました。どの step を並列化し、結果をどう検証し、中断後にどう resume するかを決めます。

View File

@@ -222,6 +222,10 @@ You can also set a Goal directly from the command line:
python s17_goal_loop/code.py "/goal python -m pytest exits with code 0"
```
## Inherited permission rule
This chapter carries forward the permission hook from s04. It recognizes `rm` and `del` case-insensitively only as complete command words at the start of a command or after a shell separator (`;`, `&&`, `||`, `|`, `&`, parentheses, or a newline). It does not treat `model`, `delimiter`, or `echo del test.txt` as destructive.
## Relationship to s16
s16 answers how a batch of work should run: which steps are concurrent, how results are verified, and how an interrupted run resumes.

View File

@@ -222,6 +222,10 @@ python s17_goal_loop/code.py
python s17_goal_loop/code.py "/goal python -m pytest 退出码为 0"
```
## 继承的权限规则
本章沿用 s04 的权限 hook只在命令开头或 shell 分隔符(`;``&&``||``|``&`、括号或换行)之后,按大小写不敏感方式识别完整的 `rm`/`del` 命令词。`model``delimiter``echo del test.txt` 不会被当成危险命令。
## 与 s16 的关系
s16 解决“一批工作怎样执行”:哪些步骤并行,结果怎样验证,失败后怎样恢复。

View File

@@ -31,6 +31,7 @@ import asyncio
import glob
import json
import os
import re
import subprocess
import sys
import time
@@ -45,7 +46,14 @@ DEFAULT_STOP_HOOK_BLOCK_CAP = 8
MAX_GOAL_LENGTH = 4000
CLEAR_ALIASES = {"clear", "stop", "off", "reset", "none", "cancel"}
DENY_LIST = ["rm -rf /", "sudo", "shutdown", "reboot", "mkfs", "dd if="]
DESTRUCTIVE = ["rm ", "> /etc/", "chmod 777"]
DESTRUCTIVE_COMMAND_WORD = re.compile(
r"(?i)(?:^|[;&|()\n])\s*(?:rm|del)(?=\s|$|[;&|()])"
)
DESTRUCTIVE = ["> /etc/", "chmod 777"]
def contains_destructive_command(command: str) -> bool:
return bool(DESTRUCTIVE_COMMAND_WORD.search(command))
class GoalError(Exception):
@@ -598,7 +606,9 @@ class AgentSession:
for pattern in DENY_LIST:
if pattern in command:
return f"Permission denied by deny list: {pattern}"
if any(keyword in command for keyword in DESTRUCTIVE):
if contains_destructive_command(command) or any(
keyword in command for keyword in DESTRUCTIVE
):
print(f"\n[permission] {name}({arguments})")
if input("Allow? [y/N] ").strip().lower() not in {"y", "yes"}:
return "Permission denied by user"