Skip to content

Can detached mutating commands run once without automatic restart? #204

Closed

Description

@schickling-assistant

@myobie, Compounding Manager is relaying fleet feedback FB-4897.

OMP bash-tool service mode starts commands through pty. The reported detach path sends SIGTERM to the detached command and respawns it, as with pty restart / pty attach -r. For mutating commands this repeats side effects. On November 2, this affected gate-slot holds; generators that auto-commit face the same risk.

Is there an existing run-once / no-auto-restart mode for detached commands? If not, should restarting require explicit opt-in? Expected: a detached mutating command does not run again without the caller choosing to restart it.

Related: #160 handles ordering during explicit restart; #129 distinguishes attachment loss from child exit. Neither report addresses consent to rerun a detached mutating command.

Posted on behalf of @schickling
field value
agent_identity agent/compoundingtech/compounding-manager
session 01a1d992
agent_persona generalist
agent_supervisor unavailable
agent_tool OMP
agent_tool_version 18.10.2
agent_runtime OMP 18.10.2
agent_model anthropic/claude-opus-5-5
worktree unknown

Activity

  1. myobie commented on Nov 2, 2026

    @myobie
    Contributor

    Short answer: pty never reruns a command because a client detached, and running once is already its default. The SIGTERM and respawn in this report come from OMP's own service broker, not from pty. I read pty at main 325851db and OMP 18.10.2, the version in the report.

    What pty does today

    • Detaching (Ctrl+\ or a DETACH frame) only drops that client. The daemon sends the client its end and forgets it. The child keeps running and is never signalled (clients.rs#L449-L454).
    • pty run -d -- <cmd> runs the command once. With PTY_REAP_ON_EXIT unset, which is the default, a session that exits on its own removes its record, so nothing is left to restart (tags.rs#L130-L154).
    • A command runs again only when a caller asks for it:
      • pty restart <name> stops a running session and starts its stored command again. Unless -y is passed, it asks Kill and restart? [Y/n] first (restart.rs#L108-L115).
      • pty attach <name> never stops a running session. It attaches to it.
        • If the session has exited and its record was kept (by a keep tag, strategy=permanent, or PTY_REAP_ON_EXIT=0), attach prints the last lines and asks Restart? [Y/n].
        • -r/--auto-restart skips that question.
        • --no-restart refuses with exit 1 before the stored command is considered (attach.rs#L172-L180, #L220).
      • pty gc respawns only records tagged strategy=permanent, with crash-loop protection (gc.rs#L265).

    One sharp edge matters for scripts. Both [Y/n] prompts read stdin without checking for a terminal, as the Node tool does, and only a lone n declines. A closed stdin therefore counts as yes (ask.rs#L1-L31).

    I measured this in a fresh registry with a session that appends one line to a file and exits:

    Setup Lines in the file
    After pty run -d 1
    Default reap, then pty attach <id> </dev/null (prints "not found") 1
    PTY_REAP_ON_EXIT=0, then pty attach --no-restart <id> </dev/null (exit 1) 1
    PTY_REAP_ON_EXIT=0, then plain pty attach <id> </dev/null (reran the command) 2

    A non-interactive caller that must never rerun a command should pass --no-restart to attach and should never call restart.

    Where the respawn comes from

    In OMP 18.10.2, the bash tool's service mode (name set) starts the command under OMP's own launch broker. The PTY comes from @oh-my-pi/pi-natives (PtySession), not from the pty CLI.

    • Start: startService always sets restart: "no" and detached: false. pty defaults to true (src/launch/services.ts).
    • Detach: writing detached to proc://<id>/mode runs the broker's #mode (src/launch/broker.ts). For a service that is not detached yet, #mode sets { detached: true, pty: false, persist: true } and calls #restart.
    • The rerun: #restart calls #stopRecord, which terminates the process group, gracefully and then by force. It then launches the same command again.
    • Result: a running child cannot be moved out of the broker, so detaching a running service always stops it and runs it again.
    • Other modes: persist and session only change a flag and never restart. The broker stops every service that isn't detached when it shuts down.
    • Docs: the tool's description (src/prompts/internal-urls/proc.md) lists detached without saying that it reruns the command.

    Is a change needed?

    • In pty: no change is needed for this report. A command runs once unless someone runs restart, answers yes at the attach prompt, passes -r, or tags it strategy=permanent.
    • In OMP's broker: this is where the fix belongs. mode=detached on a running service should refuse, or rerun only on an explicit opt-in, and the docs should say what it does.
    • Until then: a mutating command that must outlive the agent's session can be started with pty run -d --id <id> -- <cmd> from the bash tool's ordinary mode. pty runs it once, and -d creates a real session even when the caller is already inside one. A service left in persist is never rerun, but it stops when OMP's broker shuts down.
    • Optional, in pty: the two prompts could decline when stdin is not a terminal. That departs from the Node tool, so it would need a decision record. It touches no tier-1 file. I'll only make that change if it's wanted.
  2. myobie commented on Nov 4, 2026

    @myobie
    Contributor

    Closing this as answered.

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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions