Skip to content

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.

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.

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:

Terminal window
reflow login
reflow 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-storage
reflow flows list

Create 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:

Terminal window
reflow flows create --name checkout --file /tmp/checkout.md
reflow flows read checkout --json
reflow plan checkout
reflow apply checkout

Wait 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 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.

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:

Terminal window
reflow flows move preview checkout --to repository
reflow 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:

Terminal window
reflow flows move preview checkout --to knowledge_base
reflow 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>.

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.

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.