Where tests are saved
New teams start with Keep tests in Reflow. Your team can share and run tests without adding test files to the application repository. Each test is a Markdown flow with its own saved versions. Application knowledge pages describe how the app works; tests have their own entries under Flows and Knowledge.
Choose a location
Section titled “Choose a location”Use reflow collections create or MCP manage_collections to choose your application
and accept the current Where new tests are saved default. An application collection groups tests for one application,
including tests kept in Reflow and tests kept in its repository.
Choose Keep tests in Reflow for a trial without test files in Git. Choose Keep tests in the repository when your team wants to review test source in Git. The same choice appears in hosted onboarding. Owners and admins can change the default in Settings → Team → Test storage. Members use the team default. If you are using the local dashboard, follow its Team settings link to make the change in the hosted app.
Changing the default affects new tests. It never moves an existing test, resets a
mailbox or replaces named variables. A collection can contain tests from both
storage locations. Each test shows its source location. The application plugin lock
has its own retained storage location; changing the new-test default does not move
it. get_reflow_context and loaded skills describe the new-test preference and
report the existing lock location separately.
In knowledge-base mode, the shared knowledge base holds corpus pages and candidate revisions. Do not maintain another corpus in the repository or a private folder. Temporary knowledge editing lets an agent edit pinned pages as private files and upload exact bytes. Git mode intentionally versions tests with application changes; committed corpus publication is optional.
Start without adding test files
Section titled “Start without adding test files”You still need your application’s Git checkout, its running services and the runtimes declared by your flows. Ordinary plan/apply and dashboard Play use that checkout to detect application changes. Select the checkout as well as the target URL.
From the application Git checkout:
reflow loginreflow collections create --repo . --json# Use the returned collection_id below.reflow init --collection <collection-id>reflow target http://localhost:3000 --group checkout --collection <collection-id>reflow config get test-storagereflow flows listCreate infers the checkout name and GitHub origin; use --name or
--repository-id owner/name to override. reflow collections list lists the
current team’s applications; reflow collections select <id> remembers an existing
one in the private profile. A checkout without a GitHub remote receives a local
association. No test files or settings are changed. See collections.
Ask your agent to read get_reflow_context, load flow-authoring and create a
small test through manage_flows. It follows the current team default. For human
authoring, keep a temporary draft outside the checkout and use:
reflow flows create --name checkout --file /tmp/checkout.mdreflow flows read checkout --jsonreflow plan checkoutreflow apply checkoutWait for Reflow to confirm the save, then read the saved version before running it. To edit a saved
test, read it first and supply its version with
reflow flows save checkout --file /tmp/checkout.md --base-version <version-id>.
If someone else saves first, your draft stays available. Read their version and
apply your edits to it before saving again.
Keep private bindings, inputs, plugin caches, captures and installed agent skills
outside the application checkout, for example under ~/.reflow/. init installs
plugins; it does not create test files or change the team’s preference. Check
git status after your trial. Ordinary Reflow operations do not add files or edit
.git in knowledge-base mode. An agent’s independent shell edits remain under
your instructions and its own permissions.
Plan and run tests
Section titled “Plan and run tests”plan and apply use all runnable tests in the selected collection, wherever
they are saved. To run a subset, pass a test ID, slug or registered Markdown path.
A plan can contain up to 20 flows, including dependencies. Select a smaller subset
if your collection is larger.
needs can connect a repository test to a shared test in the same collection.
Dependencies resolve to exact source versions before execution. Missing sources,
ambiguous identities and conflicting copies stop the affected plan. Repository
tests absent from the selected branch are reported as exclusions; a test that
depends on one cannot run.
Repeat unchanged to reuse complete evidence. Edit application code or an earlier step to invalidate the affected work. Storage preference changes do not change execution inputs. Taint and reset keep their existing meanings; see Repair and rerun and Test data.
Edit repository tests on the device that has your checkout. flows read returns
the file hash to pass as --base-hash when saving. The hosted dashboard can export
a draft for you to save there. Reflow also keeps historical copies of the source
used for execution; edit the repository file to change future runs.
Renaming a test in Reflow changes its display name and preserves its slug and
named data. After renaming a repository file yourself, register its new path with
reflow flows map-path <test-id> --path tests/new-name.md. Matching names or
contents alone do not establish that two files are the same test.
Move existing tests
Section titled “Move existing tests”Moves are separate from changing the default. Start on the author device with the correct collection and checkout selected. A move keeps the canonical test ID and slug, exact source bytes, historical versions, evidence and approvals.
To move a shared test into Git:
reflow flows move preview checkout --to repositoryreflow flows move stage --transfer <transfer-id># Review and commit the staged test using your normal Git workflow.reflow flows move commit --transfer <transfer-id> --commit <full-commit-sha>The preview lists the versions, dependencies and destination paths to review. Staging stops if a destination contains different text or the path is unsafe. Reflow starts using the repository copy after it verifies your commit and confirms the move. Until then, it uses the shared version. Teammates must update their checkouts to the commit containing the moved tests.
To move a repository test into Reflow:
reflow flows move preview checkout --to knowledge_basereflow flows move commit --transfer <transfer-id>The original file remains for explicit cleanup. Reflow recognizes an unchanged
former copy without running a duplicate; a divergent former copy is a conflict.
Moves leave Git commits, pushes, file cleanup and expectation approval to you.
Dependencies can stay in the other storage location within the same collection.
Use --keep-dependencies to confirm that choice when a preview lists dependencies
you have not selected.
After interruption or an uncertain response, use
reflow flows move inspect --transfer <transfer-id>. To abandon a prepared move,
use move cancel; already staged files remain yours to inspect. A committed move
requires a new reverse transfer. Do not create another transfer just to retry an
uncertain response. Authoring responses also retain operation/session IDs for
reflow flows operation --operation-id <id> --operation-session <session>.
Existing teams
Section titled “Existing teams”Teams created before this option keep Repository as their initial default. A Reflow operator must review their existing application and repository associations before enabling collections. Conflicting duplicates need a decision about which source to use. Historical versions and approvals remain available, and activation does not move source files.
Use a CLI version that supports the team’s storage settings. After activation, older authoring and run entrypoints return an upgrade/context error instead of creating another writable head. Exact flow-ID/version runs remain available as explicit historical selections. For CI, follow the collection setup for GitHub Actions. Installed agent skills should read current context before authoring. Reflow does not rewrite your agent instructions when the team default changes.
For an advanced single-flow run without a checkout, manage_device_jobs start
executes one exact saved version. It does not provide incremental plan/apply.
Review exports must use evidence from the execution that produced them; do not
rerun a controller test just to obtain an export.
Reviewed plans and interrupted file creation
Section titled “Reviewed plans and interrupted file creation”A plan has a semantic fingerprint and a separate storage fingerprint. A preference
change alone leaves both execution reuse and named test data intact. A changed
source head or authority requires a new plan even when its bytes are identical.
When pinning an inspected CLI plan, pass both --fingerprint and
--storage-fingerprint; MCP apply takes fingerprint and storage_fingerprint.
An ordinary reflow apply prepares and validates its current plan automatically.
MCP creates and move previews take policy_revision from get_reflow_context.
This prevents a cached instruction from silently changing the destination.
reflow flows create <name> --file - also accepts source on stdin.
Repository creates retain the original privately, reserve the test identity, write
the file, and confirm the destination. A pending reservation cannot execute or be
adopted as another test. Recovery checks the original test ID and source against
the server, including after a restart loses the local confirmation. Recover
the file with reflow flows recover-create --operation-id <id> --operation-session <session> --collection <id>. Reflow never resubmits an
uncertain registry mutation automatically. Recovery preserves existing files and stops if their contents differ. Reflow uses
a private lock outside the checkout to prevent two authoring operations from
writing at once. After a crash, check that the recorded process has exited before
removing its stale lock.
After a manual file rename removes the old path, map-path requires
--base-hash from the old source read. It records the former bytes separately
from the new destination. Test details link related historical records, including their versions, runs and
approvals.
Freeze a KB test for base/head review
Section titled “Freeze a KB test for base/head review”A controller run can become a frozen team review without putting test files in the
application repository. Use the author MCP profile and manage_execution for the
whole workflow. Do not rerun the test with manage_device_jobs, manufacture Git
flow paths, or create application commits just to publish evidence.
Publishing shares the frozen originals with authorized members of your Reflow team, including shell output, captured files and screenshots. Private inputs are excluded from the manifest projection; that does not make original evidence private to its author. Inspect the retained evidence before publishing.
For each existing base/head application checkout, select its target with a distinct
validity epoch, inspect plan, then apply with its exact fingerprints and a stable
execution request ID. Keep the returned controller run_id. These are separate
executions against the chosen application targets, not publication retries. Wait for
run to report a terminal status. Failed, cancelled, timed-out and skipped runs are
eligible; missing or unconfirmed step receipts remain explicit gaps, never passes.
The first increment supports at most 201 planned and 201 recorded steps, iteration
zero only. Reused-step evidence is refused with unsupported_reused_evidence;
nonterminal runs are refused with nonterminal. Inspect that same run and stop on
these refusals. Publication never silently reruns it. SQL and shell-only runs need
no fabricated Browser provenance. Nullable legacy MIME/size metadata stays unknown.
The following JavaScript illustrates MCP calls; manage_execution and
review_changes stand for tool invocations. Choose and retain each review UUID once.
Read the existing application commit/tree IDs from each checkout; these labels do
not attest which application build was actually deployed. Keep the same app and
repository labels on both sides.
const source = await manage_execution({ action: "review_source", run_id: baseRunId });// Stop if source.state === "refused". Copy source.expected exactly, including// collection/flow/version/sourceHash, targetEpoch, testDataEpoch and group.const baseRequest = { id: baseReviewId, title: "Checkout — base", runId: source.runId, expected: source.expected, appContext: { trust: "caller_declared", app: "checkout", repository: "owner/application", revision: { commit: baseCommit, tree: baseTree }, },};const reserved = await manage_execution({ action: "prepare_review", review: baseRequest });// Require state === "reserved" (or inspect an already published same ID).// Team comes from the selected connection, never from the request.const published = await manage_execution({ action: "publish_review", id: baseReviewId, manifest_hash: reserved.manifest_hash,});const base = await manage_execution({ action: "review_publication", id: baseReviewId });// Require state === "published" and descriptor_state === "verified".// Repeat for headRunId/headReviewId with its own source.expected and Git labels.prepare_review reserves source binding, quota and namespace through native Zero;
publish_review rechecks the observation, verifies and materializes reserved
originals, and publishes through native Zero. Admission, native acceptance and
publication are different facts. Inspect receipt.admission, receipt.native and
state; a timeout/profile switch after a possible send stays unconfirmed.
review_publication is read-only and reports the same ID as reserved, published or
unconfirmed. An absent row does not prove rejection. Keep the exact request, ID and
manifest hash after uncertainty. Same-session duplicates reconcile without another
mutation; after reconnecting, inspect first and make any same-ID retry explicitly.
No helper replays execution or invents a replacement ID. Receipts are bounded and
session-only; they are not a durable outbox. A cached receipt.native: "rejected"
also remains fixed for the lifetime of that device-service connection: duplicate
calls inspect it rather than resubmitting. Reconnecting an MCP host can reuse the
same device service and is not a guaranteed retry. Keep the original ID, diagnose
the native refusal, and inspect that ID from a new device-service connection
before any deliberate same-request retry. An absent row or an unconfirmed receipt
is never proof that a mutation was rejected.
For comparison, use the exact verified descriptor.check from each publication.
Its testSource identifies the collection flow; its visual keys distinguish step,
provider call and checkpoint name. Inserting a step before a snapshot shifts its key. The comparison then shows
one removed and one added capture, which cannot be paired as a change. Do not invent keys from filenames or use the
controller run ID as a device job ID. Publish this explicit version-2 selection:
const selection = { formatVersion: 2, kind: "change_review", appContextTrust: "caller_declared", id: comparisonId, teamId: selectedTeamId, title: "Checkout base/head", app: "checkout", repository: "owner/application", createdAt: comparisonCreatedAt, scope: { label: "Selected KB checkout test", exclusions: ["Other application behavior"] }, authored: { intent: "Explain the application change", summary: "Describe observed differences" }, base: { revision: { commit: baseCommit, tree: baseTree }, checks: [base.descriptor.check] }, head: { revision: { commit: headCommit, tree: headTree }, checks: [head.descriptor.check] }, runs: [ { side: "base", key: base.descriptor.check.key, id: base.descriptor.id, manifestHash: base.descriptor.manifestHash }, { side: "head", key: head.descriptor.check.key, id: head.descriptor.id, manifestHash: head.descriptor.manifestHash }, ], knowledge: { base: null, head: null }, // Or independently selected frozen KB reviews.};await review_changes({ action: "prepare_walkthrough", selection });// Inspect coverage and gaps. Media is optional; only add deliberately prepared,// relevant changed visuals before freezing the final selection.const comparison = await review_changes({ action: "publish", selection });// Require published state; retain this selection and ID after uncertainty.Use the returned comparison ID/selection hash, repository and head commit with
review_changes prepare_comment, or export_comment plus a new absolute
outputDirectory outside the application checkout. Inspect its preparation receipt
before handing off the local Markdown and optional verified media. Neither action
posts a PR comment. Existing Git/device review formats and their captured-source
requirements remain unchanged.