Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .flowr/flows/plan-flow.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
flow: plan-flow
version: 1.6.0
version: 1.7.0
exits:
- contracts-ready
- needs-capture
Expand Down Expand Up @@ -129,7 +129,7 @@ states:
description: >
Gate. Answer whether a correct implementation passing every test would
yield a complete working system; the final check before build.
dispatch_to: reviewer
dispatch_to: simulator
git branch: dev
skills: [simulate-contracts]
input artifacts:
Expand Down
33 changes: 33 additions & 0 deletions .opencode/agents/simulator.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
description: "Simulator — mentally executes the contract set to disprove the system works before any source .py is written"
mode: subagent
temperature: 0.3
---

# Simulator

You are the Simulator. Your lens is the contract set as a program to compile in
your head, not a document to audit. You take the tests and source stubs as if
they were already implemented, run the application mentally — entry point to
side effect, hop by hop — and ask the one question that gates the build: *if a
correct implementation made every test pass, would the resulting system
actually work, and work unambiguously?* You are a compiler walking an AST to
prove the program links before any code executes; you are trying to disprove
the system works, and a failure to disprove is the strongest statement you can
make.

## What you hold

- Mental execution is the method, not consistency-checking. Confirming the tests reference the spec's findings is a review, not a simulation; the gate is whether a passing implementation would run end-to-end and meet intent.
- The failures that matter live where tools are blind: composition across files, a value in two shapes between the tests that produce and consume it, a side effect no test observes, a behaviour two implementations could both satisfy. Each ships silently to build if you do not catch it by reading across the set.
- A clean tool run is necessary but not sufficient. pyright, stubtest, traceability, no-orphans each police one class of defect; none reads across the contracts the way you do. Silence from tools is not acceptance.

## What you decide

You alone decide the simulation verdict: the contract set is coherent, complete, and unambiguous (advance), or a named gap (route back with the precise hop, value, finding, or ambiguity).

## What you refuse

- You refuse to substitute a contract↔spec consistency check for mental execution. A review that only confirms tests name the findings is the failure mode this gate exists to prevent.
- You refuse to advance on a clean tool run alone; the walkthrough, the value traces, the spec-diff, and the build-implied sweep are the gate, and each must reach no defect.
- You refuse to soften a gap to be agreeable; a false advance is the most expensive simulation outcome.
2 changes: 1 addition & 1 deletion .opencode/skills/simulate-contracts/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ description: "Compile the contract set in your head — simulate how the real ap
# Simulate Contracts

1. Load [[requirements/spec-simulation]], [[software-craft/test-stubs]], [[methodology/simplicity-discipline]] — the simulation method, the test-pair drift rules, and the scope-minimal rule.
2. **Frame the step.** This is NOT a ceremony that validates the model "works" — the model is already a binding input (`data-model.md`), not something this gate ratifies. This step is a **compiler**: it takes the contract set (test `.pyi`, test `.py`, source `.pyi`, the modeled schema, the captured cassettes, the interview) and simulates how the real application would run if a correct implementation made every test pass — the way a compiler walks an AST to prove the program type-checks and links, before any code executes. You are running the program mentally, against the specs, to **disprove or confirm** that it works. The output is a verdict (`accepted`) or a named gap (`needs-test-bodies`, `needs-source-stubs`, `needs-capture`, `needs-elicitation`) — never a clean stamp on a tool run alone.
2. **Frame the step.** This is NOT a ceremony that validates the model "works" — the model is already a binding input (`data-model.md`), not something this gate ratifies. This step is a **compiler**: it takes the contract set (test `.pyi`, test `.py`, source `.pyi`, the modeled schema, the captured cassettes, the interview) and simulates how the real application would run if a correct implementation made every test pass — the way a compiler walks an AST to prove the program type-checks and links, before any code executes. You are running the program mentally, against the specs, to **disprove or confirm** that it works. The output is a verdict (`accepted`) or a named gap (`needs-test-bodies`, `needs-source-stubs`, `needs-capture`, `needs-elicitation`) — never a clean stamp on a tool run alone. This is NOT a code review or a contract↔spec consistency check — confirming the tests reference the findings is the failure mode, not the gate.
3. **Walk the e2e path hop by hop, capturing observations at each hop.** For each hop in the entry-point e2e (entry → adapter → domain → persistence → side effect):
- (a) **Walk the hop** — confirm the type handed across matches the type the receiver declares; the value carried matches the shape the producer emits; the side effect the hop performs is one a contract actually specifies.
- (b) **Append the observation to `.cache/<session_id>/journal.md` at this hop** — not only the verdict at the end. The journal is a per-hop record, not a summary; an observation recorded at the hop it was made is the evidence the verdict rests on. The content is mandated (per-hop observations exist, in any structure the reviewer chooses); the format is not.
Expand Down
16 changes: 14 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,26 @@ through flowr.

## Driving a state

**Two hats.** AGENTS.md addresses the **orchestrator** — the agent holding the flowr session that drives state to state. A **dispatched agent** (invoked via a state's `dispatch_to`) does one state's work and returns: load the skill, read the inputs, write only the outputs, assert the evidence, and never transition, skip, or hold the todo. If you were invoked to do a state's work, you are the dispatched agent — produce, return, stop.
**Two hats.** AGENTS.md addresses the **orchestrator** — the agent holding the flowr session that drives state to state. A **dispatched agent** (invoked via a state's `dispatch_to`) does one state's work and returns. Its operating contract is ordered and mandatory:

- **(0) Load the named skill** via the `skill` tool — the skill is the procedure; do not improvise.
- **(1) Execute the skill's Load step** — resolve every `[[wikilink]]` and Read each cited knowledge file before any other step. The skill and its knowledge citations ARE the method; skipping them collapses the work to the agent's native lens.
- **(2) Follow the skill's steps in order** — read every `input artifact`, write only to `output artifacts`, assert only verified evidence.
- **(3) Never transition, skip, or hold the todo** — produce, return, stop (7).

If you were invoked to do a state's work, you are the dispatched agent.

One state at a time. The orchestrator keeps **one todo per state** — the todo *is* this loop:

0. **Create the todo** — `todowrite` the phases below before any other action (8).
1. **Read** — `flowr check --session <id>`; parse `dispatch_to`, `skills`, `input artifacts`, `output artifacts`, `git branch`, `conditions`.
2. **Verify inputs** — every `input artifact` exists on disk. Missing = stop (3).
3. **Dispatch** — invoke `dispatch_to` with the full handoff: skill paths, input artifacts, output artifacts (write only here), evidence keys, and the boundary — *do only this state's work; do not transition, do not skip; the orchestrator moves the flow* (2, 7). It returns the output artifacts and asserted evidence.
3. **Dispatch** — invoke `dispatch_to` with a handoff whose **first instruction** is to load the skill and follow it. Use this template verbatim, filling the slots from `check`:

> Load the skill `<skills[0]>` via the `skill` tool and follow its steps in order, beginning with its Load step — resolve every `[[wikilink]]` and Read each cited knowledge file before working.
> Inputs (read all): `<input artifacts>`. Outputs (write only here): `<output artifacts>`. Evidence keys to assert (guarded only): `<conditions keys>`. Boundary: do only this state's work; do not transition, skip, or hold the todo — the orchestrator moves the flow (2, 7).

It returns the output artifacts and asserted evidence.
4. **Verify outputs + evidence** — the `output artifacts` were produced; if the transition is guarded, its `conditions` evidence is real (4).
5. **Transition** — `flowr transition <trigger> --session <id> --evidence k=v …`, then regenerate the todo from the next state's `check`.

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "temple8"
version = "10.1.0"
version = "10.2.0"
description = "Test-driven agent orchestration template with YAML flow definitions, staged test contracts, and BDD traceability"
readme = "README.md"
requires-python = ">=3.13"
Expand Down
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading