Policy: desktop-command rule only at command start; workspace reset restores permissions; worker state typing; test report draft
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
3 changed files +9 −4
modified
services/research-runner/src/policy.ts
+1 −1
@@ -83,7 +83,7 @@ export const DENIED_COMMAND_PATTERNS: Array<{ re: RegExp; reason: string }> = [ | ||
| 83 | 83 | { re: /\/var\/autoscholar\/(?!runs\/)/, reason: "worker root outside the run workspace" }, |
| 84 | 84 | { re: /ANTHROPIC_API_KEY|WORKER_TOKEN|AUTOSCHOLAR_|\.env(\b|$)/, reason: "credential access" }, |
| 85 | 85 | { |
| 86 | − re: /(^|[\s;&|(])(open|say|afplay|screencapture|caffeinate)(\s|$)/, | |
| 86 | + re: /(^|[;&|]\s*)(open|say|afplay|screencapture|caffeinate)\s+(-|\.|\/|~|https?:)/, | |
| 87 | 87 | reason: "desktop/session interaction", |
| 88 | 88 | }, |
| 89 | 89 | { |
modified
services/research-runner/src/runner.ts
+6 −1
@@ -161,7 +161,12 @@ export class ResearchRunner { | ||
| 161 | 161 | } |
| 162 | 162 | } |
| 163 | 163 | if (!resumed) { |
| 164 | − if (existed) await rm(ws, { recursive: true, force: true }); | |
| 164 | + if (existed) { | |
| 165 | + await chmod(join(ws, "input"), 0o755).catch(() => {}); | |
| 166 | + for (const f of ["CLAUDE.md", "input/CLAUDE.md", "input/run.json"]) | |
| 167 | + await chmod(join(ws, f), 0o644).catch(() => {}); | |
| 168 | + await rm(ws, { recursive: true, force: true }); | |
| 169 | + } | |
| 165 | 170 | for (const d of [ |
| 166 | 171 | "input", |
| 167 | 172 | "plan", |
modified
services/worker/src/main.ts
+2 −2
@@ -205,10 +205,10 @@ class Worker { | ||
| 205 | 205 | } |
| 206 | 206 | |
| 207 | 207 | private async execute(job: Awaited<ReturnType<WorkerClient["lease"]>>["job"] & object) { |
| 208 | − const state = { | |
| 208 | + const state: { fencingToken: number; cancel: boolean; restart?: boolean; events: RunEventInput[] } = { | |
| 209 | 209 | fencingToken: job.fencingToken, |
| 210 | 210 | cancel: job.cancelRequested, |
| 211 | − events: [] as RunEventInput[], | |
| 211 | + events: [], | |
| 212 | 212 | }; |
| 213 | 213 | this.running.set(job.runId, state); |
| 214 | 214 | const renew = setInterval(async () => { |
| 215 | 215 | |