Skip to content
Back to skills

Verify Accepted Steering

ASecurity

Checks that Accepted Steering is not replayed after a daemon crash. Use when changing Steering dispatch, the send-start fence, durable Steering transitions, startup recovery, or per-owner dispatch serialization.

  • 26 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 22, 2026
ai-agentspythongojavabashsqltestinggitdatabasesecurity

Works with

  • terminal

Security analysis

A100/100

Scanned October 22, 2026

npx -y skills add n1majne3/CyberPenda --skill verify-accepted-steering --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Verify Accepted Steering?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Verify Accepted Steering
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/n1majne3-verify-accepted-steering/badge)](https://www.skillsdirectory.com/skills/n1majne3-verify-accepted-steering)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: verify-accepted-steering
description: Checks that Accepted Steering is not replayed after a daemon crash. Use when changing Steering dispatch, the send-start fence, durable Steering transitions, startup recovery, or per-owner dispatch serialization.
---

# Verify Accepted Steering recovery

**Property:** The Harness sends each Accepted Steering request to the Runtime at most once across daemon crashes.
**Harm:** A replay can repeat a security-testing action that the operator accepted only once.

## Run the check

1. Read `CONTEXT.md`, `docs/adr/0023-require-accepted-steering-to-settle-durably.md`, and `docs/agents/async-tests.md`.
2. Compare the covered code with the sync commit below. Include local changes. Review each changed function against the model actions before interpreting a pass:

   ```bash
   git diff b82d62365cbc6f41cf32dbb9285b2132b24c4e98 -- internal/daemon/steering.go internal/daemon/task_handlers.go internal/daemon/server.go internal/steering/steering.go internal/owner/steering.go internal/store/store.go internal/daemon/finish_task_resume_test.go
   ```

3. From the repository root, run:

   ```bash
   uv run --no-project python -I verification/accepted-steering/check.py
   ```

   Requirements: Go as specified by `go.mod`, Java 8 or later, UV, and Python 3.11 or later. The first run downloads the pinned TLC 1.7.4 release (TLC 2.19), checks its SHA-256, and caches it in the system temporary directory. Later runs use that cache. No Python packages are required. No Model Provider or Sandbox is used.
4. A pass requires both TLC and the real Go crash-cut tests to pass. Expect 159 distinct model states at the checked-in bounds and eight Go subtests. The normal run took about 40 seconds on the validated Windows machine, including Go build overhead; first-time compilation can take longer.
5. After changing the model, runner, test fixture, or covered ordering, run the sensitivity check:

   ```bash
   uv run --no-project python -I verification/accepted-steering/check.py --self-test
   ```

   It must find `Invariant NoReplay is violated.` in the model mutant and `NO_REPLAY:` in the real-code mutant, then pass the unmodified model and code. Expected mutant failures are printed; only the final exit status decides whether the sensitivity check passed.

## Scope

The model explores every reachable ordering for **one Runtime Owner, two distinct accepted requests, and at most two crashes**, including a crash during recovery. There is one dispatcher. SQLite commits are atomic and durable. A Runtime receives each dispatcher call once. Dispatch starts again only after startup recovery and a Runtime becomes available.

The Go test uses the real dispatcher, SQLite store, and startup recovery with fake delivery callbacks. It reopens the database at four crash cuts for each of two requests. It does not start a Runtime. A Go build overlay supplies the test and scratch mutation; existing workspace files are read-only.

This is bounded model checking, not a proof of all Go code. It does not prove eventual delivery, FIFO, simultaneous dispatcher exclusion, Runtime-internal retries, network delivery semantics, multi-daemon safety, SQLite power-loss behavior, or Session-specific lifecycle behavior. A post-fence request can have **zero** deliveries and still correctly require operator action.

## Coverage record

Sync commit: `b82d62365cbc6f41cf32dbb9285b2132b24c4e98`

| Code | Model action or assumption |
| --- | --- |
| `internal/steering/steering.go`: `Accept` | `Accept`: one committed record and queue order |
| Same file: `OldestPending` | `SelectPending`: select the oldest pending row |
| Same file: `MarkDispatchStarted`, `transition` | `Fence`: commit `dispatch_started` before delivery |
| `internal/daemon/steering.go`: `dispatchAcceptedSteering` | `SelectPending`, `Fence`, `Send`, `Settle` ordering |
| `internal/steering/steering.go`: `MarkApplied`, `MarkActionRequired`, `NonTerminal`, `transition` | `Settle`, `RecoverFenced`: separate durable transactions |
| `internal/daemon/steering.go`: `recoverAcceptedSteering`, `recoverTaskPendingSteering`, `triggerAcceptedSteeringDispatch` | `RecoverFenced`, `ResumeDispatch`; pending requests wait for a live Runtime |
| `internal/daemon/server.go`: `NewServer` | `Restart`: run recovery before returning the server |
| `internal/daemon/task_handlers.go`: `enqueueProviderTaskControlWithSettlement` | Assumed single dispatcher per owner; not proved by this model |
| `internal/owner/steering.go`: `SteeringState`, `Terminal` | Durable state vocabulary |
| `internal/store/store.go`: `Open` | SQLite transaction and single-daemon storage assumptions |

The test reuses `newFinishTaskFixtureAt` in `internal/daemon/finish_task_resume_test.go`. Review fixture changes too. The model and runner live in `verification/accepted-steering/`.

## Diagnose and maintain

- **TLC counterexample:** translate its `phase`, `durable`, and `deliveries` into code steps. Check every atomic boundary and assumption against the coverage record. See `verification/accepted-steering/README.md` for the expected replay trace and limits.
- **Go failure:** use the named crash cut and durable outcome. A compiler, download, checksum, or timeout error is a tool/setup failure, not a counterexample. The runner never counts such an error as a successful mutation check.
- **Model/code mismatch:** correct the mapping and rerun both checks. Do not treat a model pass as verification of changed code before this review.
- **Real defect:** preserve the counterexample and report it. Do not weaken the property or fix product code unless requested.
- **Intended protocol change:** update the model, crash-cut test, and mutation together. Keep the fence-after-send negative control capable of failure. Run the sensitivity check and affected product tests.
- Move the sync commit forward **only after** confirming that every covered function still matches the model and assumptions at that commit. Record new results in the verification README. A green command alone is not that confirmation.

Use `/pstack:maintain-formal-verification-skill` when a relevant change did not recheck this mapping.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.