Skip to content

Safety design: consider worktree isolation + audited override for agent task guardrails #979

Description

@pm25coder

Community feedback (source: dev.to post 2 comment 3dg67, https://dev.to/pm25coder/when-the-self-improving-agent-almost-lost-the-hosts-work-a-postmortem-2079, reader heinrichneb):

Activity

  1. argszero commented on Aug 25, 2026

    @argszero
    Owner

    Thanks for the detailed feedback — the postmortem's readership is exactly why the receipt was made public. Three direct responses:

    1. On the killer-command question (which command destroyed the stash?):
    From the code archaeology of #881: the pre-fix open-source prompt instructed git stash for dirty trees AND git stash + git pull --rebase for pull conflicts, with no pop path in either branch. "No reflog trace, twice" is consistent with the stash being consumed by git pull --rebase (autostash applied and dropped) and/or a subsequent git reset --hard / git checkout . during a cleanup step — the exact chain is unrecoverable from the archived logs, which is itself the lesson. The fix (#881) removed git stash from the flow entirely and made dirty trees run read-only. That guard was prompt-level — which brings us to your stronger point:

    2. Structural enforcement (rules can regress; topology can't):
    Agreed, and now implemented in PR #980. Two layers:

    • Per-cycle effective sandbox guard: the scheduler probes git status --porcelain in the task's source dir at each cycle; a dirty tree forces the cycle's bash sandbox to read-only regardless of task configuration — the host's uncommitted edits are structurally out of reach, not just discouraged.
    • Read-only now blocks git mutators: the 08-20 killers (git stash, git checkout ., git reset --hard, git clean) previously escaped the sandbox's target scan (it only caught rm/rmdir/mv/cp). Read-only now blocks the full git mutator family while keeping read-only git reads (status/fetch/log/diff) available for scanning/review cycles.

    3. Audited override (your git-hook env-var pattern):
    Adopted in the same PR: EMRG_TASK_DIRTY_OVERRIDE (comma-separated task names, or *) lets a human lift the guard; every override is logged as a receipt. Inconvenient by default, exceptional on purpose, never silent.

    4. Worktree topology ("give it its own worktree"):
    Strongest option, and partially in place — the upgrade flow already runs in an isolated clone (~/.emrg/upgrade-work/emrg). Full worktree isolation for scheduled tasks is the natural next step; PR #980 is the structural guard that holds until then (and complements it afterward — the agent's own worktree still shouldn't run read-only-on-dirty if it can't tell the two trees apart).

    Invariant lists: the versioned, regression-tested list now lives in open_source_prompt.md + tests/test_scheduler.py (dirty-tree read-only) and tests/test_bash_tool_sandbox.py (git-mutator block).

  2. argszero commented on Aug 25, 2026

    @argszero
    Owner

    Resolved — the implementable parts of this feedback are now live on master:

    The remaining item — full worktree isolation for scheduled tasks (giving each task its own worktree so the host's tree is structurally out of reach) — is a larger architectural change; the upgrade flow already uses an isolated clone (~/.emrg/upgrade-work/emrg) and the structural guard holds in the interim. Tracked as a follow-up; reopen if you want to drive it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions