feat(agent): plan-first gate, iterative follow-ups, reasoning persistence
P1 plan-first: run handler refuses without propose_plan (structural gate,
not SOUL.md prose). Plan window decoupled from set_goal — config_mutation
auto-run only on operator approval (assent window). Closes the approval-free
config_mutation hole confirmed in session d0d562e0.
P2 iteration: reopenSession flips terminal→executing, marks prior plan steps
replaced, clears outcome. proposePlan excludes replaced from in-flight check,
bumps generation. A follow-up on a completed session starts a new sub-task
with a fresh plan — no more errPlanInFlight dead end.
P3 reasoning: accumulate per-iteration text into the persisted row instead
of overwriting with the last text event. Reload shows intermediate thinking,
not just the final summary.
P4 read-only allowlist: add find, tree, locate, systemctl list-timers/
list-unit-files/show, timedatectl, hostnamectl, systemd-analyze, rclone
ls/lsl/md5sum/check/cryptcheck. Fixes the find misclassification from
d0d562e0.
P5 eval harness: new assertion kinds (proposes_plan, plan_before_run,
plan_generations), multi-turn followups, fetch /sessions/{id}/plan. Four
manifests under evals/.
P6 SOUL.md: strip degenerate-case carve-out, add ITERATE step, update
set_goal guidance.
VERSION 0.6.0 → 0.7.0
This commit is contained in:
@@ -15,6 +15,18 @@ func TestClassifyCommand_ReadOnly(t *testing.T) {
|
||||
"git status",
|
||||
"sudo cat /var/log/syslog",
|
||||
"ip a",
|
||||
// P4: newly added read-only verbs.
|
||||
"find /var/log/rclone-backup/ -name runs.jsonl",
|
||||
"tree /etc/caddy",
|
||||
"locate Caddyfile",
|
||||
"systemctl list-timers --all",
|
||||
"systemctl list-units --type=service",
|
||||
"systemctl list-unit-files --state=enabled",
|
||||
"systemctl show caddy",
|
||||
"timedatectl",
|
||||
"hostnamectl",
|
||||
"systemd-analyze blame",
|
||||
"rclone lsl proton:library-backup",
|
||||
}
|
||||
for _, c := range cases {
|
||||
if got := ClassifyCommand(c, ""); got != RiskReadOnly {
|
||||
@@ -99,6 +111,9 @@ func TestClassifyCommand_CompoundReadOnly(t *testing.T) {
|
||||
"docker ps | grep caddy",
|
||||
"systemctl status caddy 2>&1; journalctl -u caddy -n 5 --no-pager",
|
||||
"sudo systemctl status caddy; sudo journalctl -u caddy -n 5",
|
||||
// P4: the exact compound from session d0d562e0 — find + ls + tail +
|
||||
// echo + journalctl, all read-only segments.
|
||||
"ls -lt /var/log/rclone-backup/ | head -20 && tail -3 /var/log/rclone-backup/runs.jsonl || echo \"not found\" && find /var/log/rclone-backup/ -name 'runs.jsonl'",
|
||||
}
|
||||
for _, c := range cases {
|
||||
if got := ClassifyCommand(c, ""); got != RiskReadOnly {
|
||||
|
||||
Reference in New Issue
Block a user