Gate ops writes on approved step sequences #39

Merged
dongar merged 5 commits from ops-gating into main 2026-09-23 22:26:13 +00:00
Collaborator

Replaces C2's up-front per-tool allow/confirm taxonomy with approval of literal step sequences, and adds the controls discussed alongside it.

C2 (rewritten)

  • An ops write plan is a list of literal steps: tool, target, arguments, an optional precondition and expected outcome, and a retry allowance. One approve covers the whole sequence, e.g. reboot → change config → reboot.
  • Code renders the approval message from the steps. Irreversible steps, protected targets, and steps that take down the agent's own host are flagged at the top.
  • A matcher checks every call:
    • read-only calls are free;
    • an elevated call must exactly match the next approved step, with arguments normalized against the tool's schema;
    • anything else halts to AWAIT_INPUT.
  • A failed step retries up to its allowance. A failed precondition or outcome check halts without retry.
  • Approvals expire if the plan has not started within the window.
  • Classification is a versioned policy file: instance privilege, protected targets, and each elevated tool's target argument. Everything unclassified or unmapped fails safe. MCP annotations may only make a tool stricter.
  • Bounded matching and standing approvals are deferred, with the reasons stated.

Elsewhere

  • A3: an approved sequence resumes after the agent's own restart only if the step in flight has a verified expected outcome.
  • A4: operator kill switch stop, for every agent.
  • 0.2: the agent may switch items on its own while the active one waits on the operator or after it closes (the model picks which ready item, and posts a notice saying why). Parking unmounts elevated MCP instances. A Matrix reply to a parked item binds to that item.
  • A9/A10: an agent-level log scope for model calls outside any work item (the switch choice, duty runs before a finding). The switch call sees only summaries built by code, falls back to the oldest item if it fails, and is recorded as a work_item.switch event.
  • A17 (cut down): step preconditions replace staleness bounds, the log-checked verification precondition, and the boot-time re-fetch. Procedures bind to C2 policy entries.
  • A18 (new): prompt injection. It assumes any model that reads untrusted content may be compromised, and limits what that model can do.
  • Part H: records the decision. What's still open is data (the protected-target list, target-argument mappings, the expiry window).

Not in this PR: dev workflow profiles, and simplifying the built A3 delegation resume and the multi-channel approvals.

🤖 Generated with Claude Code

Replaces C2's up-front per-tool allow/confirm taxonomy with approval of literal step sequences, and adds the controls discussed alongside it. **C2 (rewritten)** - An ops write plan is a list of literal steps: tool, target, arguments, an optional precondition and expected outcome, and a retry allowance. One `approve` covers the whole sequence, e.g. reboot → change config → reboot. - Code renders the approval message from the steps. Irreversible steps, protected targets, and steps that take down the agent's own host are flagged at the top. - A matcher checks every call: - read-only calls are free; - an elevated call must exactly match the next approved step, with arguments normalized against the tool's schema; - anything else halts to `AWAIT_INPUT`. - A failed step retries up to its allowance. A failed precondition or outcome check halts without retry. - Approvals expire if the plan has not started within the window. - Classification is a versioned policy file: instance privilege, protected targets, and each elevated tool's target argument. Everything unclassified or unmapped fails safe. MCP annotations may only make a tool stricter. - Bounded matching and standing approvals are deferred, with the reasons stated. **Elsewhere** - **A3:** an approved sequence resumes after the agent's own restart only if the step in flight has a verified expected outcome. - **A4:** operator kill switch `stop`, for every agent. - **0.2:** the agent may switch items on its own while the active one waits on the operator or after it closes (the model picks which ready item, and posts a notice saying why). Parking unmounts elevated MCP instances. A Matrix reply to a parked item binds to that item. - **A9/A10:** an agent-level log scope for model calls outside any work item (the switch choice, duty runs before a finding). The switch call sees only summaries built by code, falls back to the oldest item if it fails, and is recorded as a `work_item.switch` event. - **A17 (cut down):** step preconditions replace staleness bounds, the log-checked verification precondition, and the boot-time re-fetch. Procedures bind to C2 policy entries. - **A18 (new):** prompt injection. It assumes any model that reads untrusted content may be compromised, and limits what that model can do. - **Part H:** records the decision. What's still open is data (the protected-target list, target-argument mappings, the expiry window). **Not in this PR:** dev workflow profiles, and simplifying the built A3 delegation resume and the multi-channel approvals. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
dev-agent added 1 commit 2026-09-23 21:50:25 +00:00
Gate ops writes on approved step sequences
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 52s
b8df5d2066
C2's per-tool allow/deny/confirm taxonomy would have to be written in
advance for a tool catalog that will grow large, and every mistake in it
is friction or a hole. An ops write plan is now a list of literal steps
(tool, target, arguments, optional precondition and expected outcome,
retry allowance), and one approval covers exactly that sequence:

- Code renders the approval message from the steps, flagging
  irreversible steps, protected targets, and steps that take down the
  agent's own host
- A matcher checks every call: read-only is free, an elevated call must
  exactly match the next approved step (arguments normalized against the
  tool's schema), and anything else halts to AWAIT_INPUT
- Approvals expire if the plan does not start in time
- Classification shrinks to a versioned policy file: instance privilege,
  protected targets, and each elevated tool's target argument, all
  failing safe; MCP annotations may only tighten
- Bounded matching and standing approvals are deferred, with reasons

Supporting changes:

- A3: an approved sequence resumes after the agent's own restart only on
  a verified expected outcome for the step in flight
- A4: an operator kill switch, `stop`, for every agent
- 0.2: the agent may switch items on its own while the active one waits
  on the operator; parking unmounts elevated instances; a Matrix reply
  to a parked item binds to that item
- A17: step preconditions replace the staleness bounds, the log-checked
  verification precondition and the boot-time re-fetch
- A18 (new): prompt injection, designed around limiting what a
  compromised model can do rather than detecting injection
- Part H records the decision and parks the deferred items

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
dev-agent added 1 commit 2026-09-23 21:54:20 +00:00
Let the model choose which ready work item to switch to
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 52s
854bddc680
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
dev-agent added 1 commit 2026-09-23 21:57:06 +00:00
Give calls outside any work item an agent-level scope
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 50s
5b163f0c2e
Letting the model choose which ready item to switch to adds a model
call that belongs to no work item. Duty runs before a finding already
had the same gap. A10 now defines an agent-level scope for these calls,
kept apart from work item transcripts in both directions. The switch
call sees only code-rendered summaries of the ready items, runs as the
executor, and falls back to the oldest item if it fails. A9 gains a
work_item.switch event, and A18 accepts that an injected alert can at
worst reorder work.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
dev-agent added 1 commit 2026-09-23 22:09:42 +00:00
Let the agent also switch on its own when the active item closes
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 57s
a91252cb77
0.2 previously allowed an autonomous switch only while the active item
waits on the operator. Ready work should not sit behind an idle agent
either, so closing an item (completed or abandoned) is now the second
case. This also defines "ready": the agent can act on the item without
the operator, because it has not started or because intake arrived
while it was parked that answers what it was waiting for. A9's
work_item.switch allows a closed or null `from`, and B2 no longer says
only the operator selects the active project.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
dev-agent added 1 commit 2026-09-23 22:16:43 +00:00
Wait a grace period before switching away from a waiting item
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 57s
019fa24517
Switching as soon as the active item posts a plan or question means the
operator sees the request and the switch notice seconds apart. A prompt
approval then waits until the other item waits or closes, which can be
a whole milestone. A configurable grace period (default 10 minutes)
lets a watching operator answer before the agent moves on, and still
switches when they are away.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
dongar approved these changes 2026-09-23 22:26:09 +00:00
dongar merged commit d2fe3d5642 into main 2026-09-23 22:26:13 +00:00
dongar deleted branch ops-gating 2026-09-23 22:26:13 +00:00
Sign in to join this conversation.
No Reviewers
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dev/nisse#39