How FlowState Engineering Works
Six load-bearing parts: two modes, one protocol, one ecosystem, one loop, and one enforcement layer. Remove any of them and the methodology fails.
The Two Modes
FSE separates thinking from doing into two modes of the same assistant. Planning is a read-only mode — it weighs approaches, trades off architectures, writes the plan, and pushes back when the ask doesn't fit the system; in this mode the assistant cannot touch code. Execution is a mode — it opens files, runs builds, edits source, and reports what actually happened. The wall between them is an approval gate and explicit provenance tagging — not a boundary between two apps.
Each mode has one job. The planner never edits code directly. The executor never invents architecture on its own. This separation is a mechanical safeguard against the primary failure mode in AI-assisted development: the agent that drifts mid-task because it is simultaneously deciding and doing.
Rule: If the executing mode encounters a decision that wasn't in the plan, it stops and escalates — it does not improvise.
Session Protocol
Every session follows four phases. No phase is skipped, even for trivial work.
-
Phase 1
Verify
Eight steps as of v1.6.0. Name the commit the session is taken at. Read
FSE.md,FSE_STATE.md, andFSE_DISCOVERY.md. Run the project's build or check command. Establish custody — if another session holds the record, name the holder and stop; if none does, say so in words. Claim the session identifier before making any other change. Then report the baseline. You cannot improve a state you haven't measured, and you cannot safely write to a record someone else is holding. Read the phase verbatim at v1.6.0 → -
Phase 2
Plan
Restate the request in one sentence. List every file that will be created, modified, or deleted. Surface conflicts with standing orders or known debt before a single keystroke of execution.
-
Phase 3
Execute
No stubs, no placeholders, no TODOs. Nothing is written that isn't finished, and nothing changes outside the agreed scope — adjacent cleanup gets surfaced, not slipped in. The Self-Healing Build Loop runs after every meaningful change.
-
Phase 4
Validate
Final build is 0 errors, 0 warnings — that is the only acceptable terminal state. Trace every new route and binding. Update
FSE_STATE.mdso the next session starts informed.
Document Ecosystem
FSE treats documentation as the operating context for the agent, not as a deliverable for humans to read later. Three tiers and an explicit growth rule.
Tier 1 — Required
FSE.md is the protocol itself — session phases, standing orders,
project identity. FSE_STATE.md is the living state: build status,
lessons learned, known technical debt, next priorities. FSE_DISCOVERY.md
is the initial audit: solution structure, dependencies, infrastructure gaps. All three are read at the
start of every session.
Tier 2 — Add When Needed
FSE_POLICE.md (absolute rules — security, compliance, data
boundaries), FSE_SCHEMA.md, FSE_UI.md,
FSE_PACKAGES.md, and PATTERNS.md.
A Tier 2 file is created when a category of rules keeps repeating across sessions, or when a domain
warrants its own authoritative document. Read on demand, not on every session.
Tier 3 — Optional / Aged-Out
Build logs, point-in-time audits, changelogs, and session reports that have been superseded and archived. Read rarely. They exist so the state file stays lean.
Growth rule: every document starts unified. Passing ~15 KB is a split trigger, not a hard cap — it applies to bedrock methodology files, not to source code, and it prompts moving a self-contained domain into its own Tier 2 file with a pointer left in the origin. The ecosystem starts at three files and grows only when growth is forced.
Self-Healing Build Loop
Every change that could affect compilation triggers a build. Zero errors and zero warnings is not a release criterion — it is a continuous state. The moment the build is not green, the agent stops adding code and starts removing error.
// Self-Healing Build Loop loop: run the project build command if errors == 0 and warnings == 0: break read first error form hypothesis apply fix if same error class fails 3 times: invoke Counter-Point Protocol goto loop
Counter-Point Protocol
On the third failed retry — or whenever a user instruction conflicts with a standing order — the agent stops, states the conflict plainly, and offers two or three concrete alternatives. It does not guess. Friction at this moment is a feature: it prevents the agent from drilling deeper into a bad path.
Executable Enforcement
A rule that exists only as prose is unenforced. It depends entirely on the vigilance of whoever is reading it at the moment they are most tired. So every invariant the project intends to hold — an architectural boundary, a naming grammar, a forbidden construct — is encoded as a check that fails the build, not written down as an expectation.
The harder half is the second clause. A check can report success without having verified anything: its target set is empty, so a test command runs where no tests exist and exits zero; its dependency is unreachable, so an integration suite skips politely and skipping is scored as passing; its matching logic is silently broken, so a filter inspects nothing and reports clean. In each case the signal inverts — the absence of verification becomes indistinguishable from successful verification, and every later session trusts the green.
So a check must fail loudly when it cannot run, and an enforcement artifact is itself verified: it is watched failing on a known violation before it is trusted to pass. A guard nobody has seen fail is a guard nobody has tested.
Version 1.6.0 carries a fourth clause, for the guard that does run and still misses. Where a check must key on a name, a spelling, or source text — frequently the only instrument available — it states the form it cannot see, and ships with a known violation written in that form. A pattern expecting a qualified prefix walks past the bare call; a scanner keyed to three marker spellings walks past the fourth. Name-keying is not forbidden, because forbidding it would be unsatisfiable. The unstated blind spot is what is forbidden.
Rule: a vacuous pass is more dangerous than a visible failure — a gap gets noticed, a false green gets relied upon.
What the checks are is the project's business, not the methodology's. Test framework, gate wiring, fixture strategy, and CI topology belong to the stack. The core defines only that the invariants are executable, that they fail loudly, and that they have been seen to fail.
When Not to Use FSE
FSE is not a universal development process. It is designed for AI-assisted production work where context drift, late-stage integration failure, and scope expansion are real risks. If those risks are not present, the protocol may cost more than it protects.
Greenfield discovery without a known target
FSE requires a plan before execution. If the goal is exploratory — finding the schema, finding the requirements, finding what the AI can do — the methodology has nothing to enforce. Use FSE once the target is known.
Trivial scripts and throwaway utilities
Scripts under a few hundred lines, single-file tools, one-off automation. The protocol overhead exceeds the value of the artifact. Maintaining FSE_STATE.md for a build script is bureaucracy without payoff.
Manual-dominant development
When you are writing 90% of the code yourself and using AI only for autocomplete or code completion, the state-synchronization protocol is overhead without payoff. FSE addresses AI-assisted execution failure modes — if AI is not making meaningful execution decisions, those failure modes are not present.
Emergency production fixes
When restoring service matters more than preserving methodology, the methodology yields. Patch the production issue, recover the system, then return to the protocol for the post-incident work. FSE is an investment in long-run integrity, not a constraint on emergency triage.
Volatile requirements and rapid pivot environments
When product direction changes hourly, the cost of the baseline ratchet and the re-plan loop exceeds the cost of throwing work away. FSE is for building high-integrity infrastructure, not for finding product-market fit through rapid experimentation.
Bottom line: FSE earns its overhead in long-running, AI-assisted, production-bound work. Outside that envelope, it is the wrong tool.
Standing Orders & Releases
Fifteen standing orders are active. Numbers run 1–16 and are never reused — order 2 was withdrawn in place when it stopped earning its keep, and its number went with it. The full text is deliberately not reproduced here: a copy is a second source that nothing updates, which is what order 16 forbids. Read the roll at the published tag.
Read all standing orders at v1.6.0 →
New or amended in recent releases
-
14
Executable Enforcement
Invariants are encoded as checks that fail the build, not documented as expectations. A check that cannot run must fail loudly, never skip silently. Guards are proven by watching them fail on a known violation. And a guard that must key on a name, a spelling, or source text states the form it cannot see, and ships with a known violation written in that form — name-keying is not forbidden, the unstated blind spot is.
-
15
Session Custody
The record has one writer at a time. A session takes custody before any work by claiming its identifier, and holds it until the work is committed or a stand-down is recorded. A session that finds the record held names the holder and stops. VERIFY names the commit the session is taken at, and a measurement carried out of the phase that produced it is re-derived or restated as of that commit. The failure needs no second person: one operator with two windows is two writers and one author.
-
16
Count Provenance
A count written in prose either points at the source that holds the fact, or carries the session it was derived at and states what it counts. Pointing is preferred: a roll that names its members has no number to rot.
FSE 1.6.0 — Custody arrives in the protocol
Version 1.5.0 introduced Session Custody: the rule that a project's record has one writer at a time, that a session claims it before working, and that verification names the commit it was taken at. The rule shipped, but the session protocol's own checklist said nothing about it — so a developer following the steps satisfied the rule by accident or not at all.
1.6.0 puts it in the steps. Verification now begins by naming the commit under it, establishes whether anyone else holds the record, and claims the session before making any other change. Session end now closes that claim and records the outcome, so custody is released deliberately rather than by walking away.
One thing here is genuinely new. Previously, a session that found the record already held had to stop and say so, but a session that found it free had to say nothing — which meant a check you performed and a check you skipped looked identical afterward. Now an unheld record is something you state, not something you leave silent.
Nothing is removed and no rule changes meaning. Projects on 1.5.0 stay conformant against the orders themselves; adopting 1.6.0 adds two written artifacts to each session.