Luigit
repositories / smith

smith

There are many coding harnesses - but this one is fast

owned by admin

.system/plans/SMH-PLAN-P3EL04N4-deterministic-provider-and-tool-fault-simulation/index.md

Raw
Rendered preview

id: SMH-PLAN-P3EL04N4 type: plan title: "Deterministic Provider and Tool Fault Simulation" spec: SMH-SPEC-SPEC0001 status: draft depends_on: [SMH-PLAN-DFOG846Z]

Deterministic Provider and Tool Fault Simulation

Intent

Smith's flakiness comes from providers and tools, not the OS. Simulate their misbehavior deterministically, in the spirit of TigerBeetle's simulator, scaled to Smith's risk. The core is already a pure function over one ordered event log; faults enter only through that log.

Decisions

  • Faults come from a seeded schedule; same seed, same run, same trace.
  • Time is injected; no sleeps, no wall-clock waits, deadlines on every wait.
  • A failing seed is a regression: it is checked in and replayed on every run.
  • Oracles check invariants, not scripts: no lost durable record, no torn result shown as success, every effect ends in one explicit outcome, cancellation always settles, bounds always hold.
  • Real HTTP and process paths are exercised at the edges; the core loop runs against simulated streams.
  • New skill fault-simulation teaches authors to add a fault kind, an oracle, and a pinned seed.

Fault catalog

Source Faults
Provider stream timeout before first byte, stall mid-stream, truncated body, malformed SSE, malformed JSON, 429 and 5xx, auth expiry, oversized body, duplicate or reordered tool-call fragments
Tool nonzero exit, hang past timeout, huge output, binary output, partial output then failure, cancellation mid-effect
Harness cancellation at every chunk boundary, storage write failure during effect recording

Behaviors

Ordered by delivery value.

  1. A seeded provider fault schedule drives an eval turn; the run settles with an explicit outcome and a replayable trace.
  2. Oracles assert durable-effect and cancellation invariants after every simulated turn.
  3. Tool faults run through the real tool boundary with bounded output and recorded mutation state.
  4. Real HTTP edge: a local scripted server replays provider faults through the shared HTTP engine.
  5. Seed sweep: cargo x sim runs N seeds; failures print the seed and write it to the regression corpus.
  6. Nightly CI runs a larger sweep; push runs the pinned corpus.
flowchart LR
  b1["1 Seeded provider faults"] --> b2["2 Invariant oracles"]
  b2 --> b3["3 Tool faults"]
  b2 --> b4["4 HTTP edge faults"]
  b3 --> b5["5 Seed sweep command"]
  b4 --> b5
  b5 --> b6["6 CI sweep"]

Structure

flowchart TB
  sched["Fault schedule (seed)"] --> sprov["Simulated StreamFn"]
  sched --> stool["Simulated tool effects"]
  sched --> clock["Injected clock and cancel"]
  sprov --> agent["smith-core agent loop"]
  stool --> agent
  clock --> agent
  agent --> store["Session store and trace"]
  store --> oracle["Invariant oracles"]
  corpus["Pinned seed corpus"] --> sched

Touches

  • smith-harness: fault schedule, simulated provider stream beside mock_stream, simulated tool effects, oracles.
  • smith-core: agent loop, tools, store, trace; injection seams only where missing.
  • smith-harness/src/http.rs: HTTP edge fault server for behavior 4.
  • xtask: sim command; nightly job in .ci/nightly.kdl.
  • .pi/skills/fault-simulation/SKILL.md: new testing skill.
  • .system/RULES.md Testing: one line adding simulation as a testing kind; needs human approval.

Risks

  • Seams added for injection must not change production behavior or cost; instruction budgets gate that.
  • Oracles too weak prove nothing; each oracle lands with a mutation proving it catches a planted fault.
  • Schedule explosion; keep fault kinds few and composable.

Exit

  • Every fault kind in the catalog runs under a seed and settles with an explicit outcome.
  • Every oracle has a planted-fault test it catches.
  • A failing seed replays byte-identically from the corpus.
  • cargo x sim and the nightly sweep run green without retries.
---
id: SMH-PLAN-P3EL04N4
type: plan
title: "Deterministic Provider and Tool Fault Simulation"
spec: SMH-SPEC-SPEC0001
status: draft
depends_on: [SMH-PLAN-DFOG846Z]
---

# Deterministic Provider and Tool Fault Simulation

## Intent

Smith's flakiness comes from providers and tools, not the OS.
Simulate their misbehavior deterministically, in the spirit of TigerBeetle's simulator, scaled to Smith's risk.
The core is already a pure function over one ordered event log; faults enter only through that log.

## Decisions

- Faults come from a seeded schedule; same seed, same run, same trace.
- Time is injected; no sleeps, no wall-clock waits, deadlines on every wait.
- A failing seed is a regression: it is checked in and replayed on every run.
- Oracles check invariants, not scripts: no lost durable record, no torn result shown as success, every effect ends in one explicit outcome, cancellation always settles, bounds always hold.
- Real HTTP and process paths are exercised at the edges; the core loop runs against simulated streams.
- New skill `fault-simulation` teaches authors to add a fault kind, an oracle, and a pinned seed.

## Fault catalog

| Source | Faults |
| --- | --- |
| Provider stream | timeout before first byte, stall mid-stream, truncated body, malformed SSE, malformed JSON, 429 and 5xx, auth expiry, oversized body, duplicate or reordered tool-call fragments |
| Tool | nonzero exit, hang past timeout, huge output, binary output, partial output then failure, cancellation mid-effect |
| Harness | cancellation at every chunk boundary, storage write failure during effect recording |

## Behaviors

Ordered by delivery value.

1. A seeded provider fault schedule drives an eval turn; the run settles with an explicit outcome and a replayable trace.
2. Oracles assert durable-effect and cancellation invariants after every simulated turn.
3. Tool faults run through the real tool boundary with bounded output and recorded mutation state.
4. Real HTTP edge: a local scripted server replays provider faults through the shared HTTP engine.
5. Seed sweep: `cargo x sim` runs N seeds; failures print the seed and write it to the regression corpus.
6. Nightly CI runs a larger sweep; push runs the pinned corpus.

```mermaid
flowchart LR
  b1["1 Seeded provider faults"] --> b2["2 Invariant oracles"]
  b2 --> b3["3 Tool faults"]
  b2 --> b4["4 HTTP edge faults"]
  b3 --> b5["5 Seed sweep command"]
  b4 --> b5
  b5 --> b6["6 CI sweep"]
```

## Structure

```mermaid
flowchart TB
  sched["Fault schedule (seed)"] --> sprov["Simulated StreamFn"]
  sched --> stool["Simulated tool effects"]
  sched --> clock["Injected clock and cancel"]
  sprov --> agent["smith-core agent loop"]
  stool --> agent
  clock --> agent
  agent --> store["Session store and trace"]
  store --> oracle["Invariant oracles"]
  corpus["Pinned seed corpus"] --> sched
```

## Touches

- `smith-harness`: fault schedule, simulated provider stream beside `mock_stream`, simulated tool effects, oracles.
- `smith-core`: agent loop, tools, store, trace; injection seams only where missing.
- `smith-harness/src/http.rs`: HTTP edge fault server for behavior 4.
- `xtask`: `sim` command; nightly job in `.ci/nightly.kdl`.
- `.pi/skills/fault-simulation/SKILL.md`: new testing skill.
- `.system/RULES.md` Testing: one line adding simulation as a testing kind; needs human approval.

## Risks

- Seams added for injection must not change production behavior or cost; instruction budgets gate that.
- Oracles too weak prove nothing; each oracle lands with a mutation proving it catches a planted fault.
- Schedule explosion; keep fault kinds few and composable.

## Exit

- [ ] Every fault kind in the catalog runs under a seed and settles with an explicit outcome.
- [ ] Every oracle has a planted-fault test it catches.
- [ ] A failing seed replays byte-identically from the corpus.
- [ ] `cargo x sim` and the nightly sweep run green without retries.