Process transparency for any required-path work. Flow shows why a process was allowed to move forward — gate by gate, with the evidence behind each transition.
Agents skip steps, accept weak evidence, summarize work as complete, and lose the thread after compaction. Flow is the small thing missing in the middle: a record of the required path, the evidence each gate expected, the evidence that was actually collected, and the exceptions that need explicit human trust. It does not run agents or replace CI. It does not replace the systems that run work. It explains why the work was allowed to advance.
npm install -D @kontourai/flow
npx flow init
npx flow validate-definition examples/agent-dev-flow.json --json
npx flow start examples/agent-dev-flow.json --run-id dev-1847
npx flow attach-evidence dev-1847 --gate verify-gate \
--file ./test-output.json --kind command
npx flow report dev-1847Release history: CHANGELOG.md records published package changes.
Docs map: docs/README.md points to product, architecture, contributor, repo structure, and ADR docs. Contributor setup lives in docs/contributing.md.
Flow v0.1 is local and file-backed.
Developer architecture guide: docs/developer-architecture.md explains Flow lifecycle and enforcement diagrams, product ownership boundaries, and current versus future Resource Contract alignment.
Agentic development workflows are the first wedge: plan, implementation, verification, publish, release, and learning gates with evidence that survives handoff and context compaction.
npx flow init
npx flow start .flow/definitions/agent-dev-flow.json --run-id dev-1847 --params subject=feature-search-filters
npx flow attach-evidence dev-1847 --gate plan-gate --file ./acceptance.md --kind acceptance-criteria
npx flow evaluate dev-1847
npx flow status dev-1847 --format summaryThe summary output is designed for humans and agents:
flow run: agent-dev-flow / feature-search-filters
current step: verify
PASS plan gate: acceptance criteria linked
PASS implementation gate: scoped files changed
BLOCK verify gate: browser evidence missing
expected: tests, lint, screenshot, Veritas readiness
next action: run browser check before publish
continuation: resume from verify, not chat memory
report: .flow/runs/dev-1847/report.md
flow init [--cwd <path>]
flow validate-definition <path> [--json] [--cwd <path>]
flow validate-transition <request-json> [--cwd <path>]
flow start <definition> [--run-id <id>] [--params key=value ...] [--cwd <path>]
flow status <run-id> [--format summary|json|markdown] [--cwd <path>]
flow attach-evidence <run-id> --gate <gate> --file <file> [--kind <kind>] [--route-reason <reason>] [--route-metadata <json-file>] [--cwd <path>]
flow evaluate <run-id> [--gate <gate>] [--cwd <path>]
flow accept-exception <run-id> --gate <gate> --reason <reason> --authority <authority> [--cwd <path>]
flow config preview <proposal> [--format summary|markdown|json] [--cwd <path>]
flow config apply <proposal> [--accept-conflict <path> ...] [--exception-reason <reason>] [--authority <authority>] [--format summary|markdown|json] [--cwd <path>]
flow report <run-id> [--format summary|markdown|json] [--cwd <path>]
flow version-release-report <fixture-json> [--format json|markdown] [--cwd <path>]
flow console --run <run-id> [--cwd <path>] [--host 127.0.0.1|localhost|::1] [--port <port>]
flow resume <run-id> [--cwd <path>]
flow list [--cwd <path>]
--cwd <path> scopes local Flow files and relative inputs for CLI commands
that read or write project state. For example, flow start flow-definition.json --cwd /tmp/workspace writes the run under /tmp/workspace/.flow/ and resolves
flow-definition.json from /tmp/workspace.
Flow v0.1 is local and file-backed. A run is stored at .flow/runs/<run-id>/:
definition.jsonis the normalized Flow Definition snapshot used by this run. It is copied from the authored definition at run start; if the authored input used the Resource Contract envelope, the persisted snapshot is the flat Flow Definition spec.state.jsonis the authoritative mutable Flow Run state. It followsschemas/flow-run.schema.jsonand recordsrun_id, definition identity, subject, status, current step, transition history, gate outcomes, accepted exceptions, next action, and update time.evidence/manifest.jsonis the append/update evidence index for this run. It followsschemas/gate-evidence.schema.json, carries the run and definition identity, and points at copied evidence files.evidence/<id>.*contains copied evidence artifacts attached through the CLI or compatible local adapters.report.mdis a derived human-readable Flow Report regenerated fromdefinition.json,state.json, andevidence/manifest.json.report.jsonis the derived machine-readable Flow Report regenerated from the same run files.
The continuation contract is intentionally simple: flow resume <run-id> reads only the run directory and prints the current step, next action, open gates, accepted exceptions, and a one-line instruction for the next agent.
state.json is the continuation authority. Reports and console projections are explanations of the current run files; they are not the source of truth for gate evaluation or resume.
Downstream console code can project a local Flow Run into a deterministic read model:
import { projectFlowRunFromFiles } from "@kontourai/flow";
const projection = await projectFlowRunFromFiles("dev-1847", {
cwd: process.cwd()
});
console.log(projection.current_step);
console.log(projection.gates);The root package exports projectFlowRun, projectFlowRunFromFiles, and the local console server helpers from @kontourai/flow.
Public package usage is limited to the package root and the flow CLI:
import {
validateDefinition,
projectFlowRunFromFiles,
startFlowConsoleServer
} from "@kontourai/flow";Generated dist/ domain files are packaged implementation output. Do not import internal package subpaths; they are not part of the npm package API.
projectFlowRunFromFiles reads local .flow/runs/<run-id>/definition.json, state.json, evidence/manifest.json, and optional report.json. It is read-only, local-file-first, deterministic, and Flow-owned. It preserves explicit external refs for Surface, Veritas, artifacts, pull requests, CI, and release reports when those refs already exist in local run files; it does not synthesize refs from git, network calls, hosted services, or Markdown report parsing.
This API is the Flow boundary for console consumers. The packaged local console uses this projection; hosted behavior, companion console startup, and kontour-console integration remain outside the v0.1 package boundary.
flow console --run <id> starts a loopback-only local operator console for a run stored under .flow/runs/<run-id>/. The server reads the run through projectFlowRunFromFiles, serves static compiled UI assets, and exposes the projection at /api/projection.
npm run build
node dist/cli.js console --run console-projection-fixture --cwd examples/scenarios/console-projection --port 0The console shows the process graph, transition timeline, current run status, gate details, evidence, and links from the local projection. It does not start hosted services, authenticate users, collaborate across machines, or discover remote Surface/Veritas systems.
Surface and Veritas refs keep normal HTTP(S) URLs when provided. Companion-scheme refs are mapped to deterministic local companion URLs: surface://... becomes http://127.0.0.1:51231/..., and veritas://... becomes http://127.0.0.1:51232/.... When a ref only has a local artifact path, the console links it through /artifacts/<relative-path> if the path stays inside the selected run directory; unsafe absolute or parent-traversal paths are displayed as fallback text instead of being served.
flow attach-evidence --kind <kind> accepts these documented kinds:
commandfileciveritas-readinesshuman-attestationtrace-link
Unknown kinds are accepted as custom and stored with the originally requested kind. The v0.1 CLI attaches evidence from files; richer adapters can write the same manifest shape.
Failed evidence can carry route-back metadata:
flow attach-evidence dev-1847 --gate verify-gate --file ./test-output.json \
--kind command --status failed --route-reason implementation_defect \
--classifier-kind manual --classifier-source cli --classifier-confidence 0.75 \
--analytics-loop-key verify:implementation_defect --expectation-id tests-passedFor nested metadata, pass --route-metadata ./route-metadata.json. The file may contain route_reason, expectation_ids, classifier, diagnostics, and analytics. CLI flags override overlapping route_reason, classifier, analytics.loop_key, and expectation_ids values from the file. Flow uses only route_reason, the Flow Definition route map/policy, and persisted route-back transitions to select the route; classifier, diagnostics, and analytics are recorded for reports and learning but do not affect routing.
Flow Definitions describe what each gate expects before a run can advance. The authored form is expects, an array of typed expectation entries. In v0.1, authored expectations use kind: "surface.claim" so gate evidence carries an explicit claim shape.
A surface.claim expectation includes:
idkind: "surface.claim"requireddescriptionclaim.type- optional
claim.subject - optional
claim.accepted_statuses - optional
explore_hint
claim.subject is intentionally open so projects and kits can name their own process subjects. Common examples include flow-run, flow-step, work-item, change, pull-request, release, decision, and artifact.
Project config owns trusted producer mappings and gate overrides. Flow Agents may author, adapt, or install that config as part of a kit or runtime adapter, but the authoritative source of truth is the Flow project config that Flow loads for the run.
A surface.claim evidence entry may be backed by a copied Surface TrustReport or Trust Snapshot JSON file:
npx flow attach-evidence <run-id> \
--gate verify-gate \
--file ./trust-report.json \
--trust-artifactFlow consumes a neutral artifact shape:
{
"schema_version": "0.1",
"artifact_type": "trust-report",
"subject": "builder.verify",
"producer": "ci/main",
"status": "trusted",
"issued_at": "2026-05-26T00:00:00.000Z",
"expires_at": "2026-06-02T00:00:00.000Z",
"authority_traces": ["github:main"],
"claims": [
{ "type": "quality.tests", "status": "trusted" }
]
}artifact_type is trust-report or trust-snapshot. Flow projects the first claim into the normal claim.type, claim.subject, and claim.status matching fields. Explicit --claim-*, --producer, and --authority-trace flags still work and can override the parsed projection for local workflows.
Gate evaluation accepts only claims whose type, optional subject, accepted status, freshness, trusted producer or authority trace, and local integrity metadata satisfy the Flow expectation and .flow/config.json. Unsatisfied artifacts are not hidden as generic missing evidence: reports include claim diagnostic reason codes such as stale, rejected, untrusted_producer, authority_gap, integrity_mismatch, and subject_mismatch.
This is a Surface-shaped Flow contract. Flow does not import Veritas internals or use Veritas-specific schema fields as the runtime contract. Veritas may produce evidence, but Flow evaluates only the neutral artifact fields above plus the Flow Definition and project config.
Release readiness is a local-file-first Flow contract for deciding whether a release should proceed or hold. It defines lane policy and adapter output shape; it does not replace ServiceNow, Jira, PagerDuty, deployment systems, freeze calendars, or approval systems.
schemas/release-readiness-policy.schema.json describes:
- open lane ids such as
change-approval,deployment-window, andfreeze-state - the
surface.claimeach lane requires - open risk classes such as
mediumorhigh - the required lanes for each risk class
schemas/release-readiness-result.schema.json describes normalized output for later report rendering: decision, risk_class, required_lanes, lane outcomes, evidence refs, external_links, and native_refs.
Fixture adapters map provider-shaped local JSON into Flow evidence, not opaque approval booleans. Each adapter emits kind: "surface.claim" with claim.type, claim.subject, claim.status, producer, authority_traces, copied external_links, and copied native_refs.
import {
changeManagementFixtureAdapter,
deploymentWindowFixtureAdapter,
evaluateReleaseReadiness,
freezeStateFixtureAdapter
} from "@kontourai/flow";
const evidence = [
...changeManagementFixtureAdapter(changeRecord, { subject: "kai-2026.06" }),
...deploymentWindowFixtureAdapter(deploymentState, { subject: "kai-2026.06" }),
...freezeStateFixtureAdapter(freezeState, { subject: "kai-2026.06" })
];
const result = evaluateReleaseReadiness(policy, {
subject: "kai-2026.06",
riskClass: "high",
evidence
});Required lanes pass only when their Surface-shaped claim satisfies the policy. Missing, pending, rejected, stale, untrusted, or authority-gap evidence returns decision: "hold". See examples/scenarios/release-readiness/ for the scenario policy, adapter records, and equivalent Flow Definition expectation.
The Version Release Report is a local-file-first artifact projection for a versioned release. It combines a changeset, Flow-shaped verification evidence, a ReleaseReadinessResult, accepted exceptions, accepted risks, native_refs, and external_links into deterministic JSON or Markdown.
Generate from an explicit local fixture file:
npm run build
node dist/cli.js version-release-report examples/scenarios/version-release-report/complete.json --format json
node dist/cli.js version-release-report examples/scenarios/version-release-report/missing-required-evidence.json --format markdownUse the library API when embedding the projection:
import {
projectVersionReleaseReport,
renderVersionReleaseReportMarkdown
} from "@kontourai/flow";
const report = projectVersionReleaseReport(fixtureJson);
console.log(renderVersionReleaseReportMarkdown(report));schemas/version-release-report.schema.json describes the projected report. Missing required verification evidence or required release lanes become explicit gaps and set decision: "hold"; they are never summarized as ready. Provider-native ids and URLs are preserved as data in native_refs and external_links; Flow does not call hosted release portals, replace release managers, or invent provider-specific semantics for this artifact. See examples/scenarios/version-release-report/ for complete and missing-evidence inputs.
Kits can propose Flow project config, but local .flow/config.json remains authoritative. Preview a proposal before applying it:
npx flow config preview ./kit-flow-config.json --format json
npx flow config preview ./kit-flow-config.json --format markdownPreview is read-only. The JSON report includes stable buckets for proposed_changes, accepted_changes, rejected_changes, conflicts, unchanged, exceptions, merged_config, and summary. Each change records a machine-readable path, section, operation, reason, and source values when relevant.
Flow accepts two authored Project Config shapes:
- The v0.1 flat shape used by existing
.flow/config.jsonfiles, with top-levelschema_version,trusted_producers, andgate_overrides. - The Resource Contract shape shown in
examples/flow-project-config-resource-contract.json, withapiVersion,kind: "FlowProjectConfig",metadata, andspec.
Resource-shaped Project Config files map spec to the same flat runtime config.
Config merge reports and applied .flow/config.json output stay flat, so
existing tools that read trusted_producers and gate_overrides do not need to
migrate.
Apply is explicit:
npx flow config apply ./kit-flow-config.json --format jsonAdditive proposals under trusted_producers and gate_overrides are accepted when the local path is absent. Matching values are recorded as unchanged. Differing local trusted producer mappings or gate overrides are conflicts and are rejected by default, so Flow does not silently overwrite project authority.
To accept a conflicting proposal, pass the exact conflict path or a parent path plus an exception reason and authority:
npx flow config apply ./kit-flow-config.json \
--accept-conflict '$.trusted_producers.quality.tests' \
--exception-reason 'project owner accepted kit producer update' \
--authority 'project-owner'Flow Agents kit install or activation may consume the JSON report to show install logs, detect conflicts, and decide whether to ask for explicit exception acceptance. Flow Agents consumes this contract; it does not own the authority semantics. Flow core does not add UI Console behavior, remote trust or signature verification, hosted workflows, provider settings, or cross-repo Flow Agents implementation as part of config merge.
For the current step, flow evaluate applies the v0.1 rules:
- all required typed expectations are satisfied:
pass - any required typed expectation is missing:
block - any attached gate evidence marked failed:
route-back - no authored expectations and no decision:
wait - an accepted exception on a gate counts as
pass
When a gate passes, Flow advances to the step's next value. When a gate blocks, Flow keeps enough state for another process or agent to resume without chat memory.
Flow core owns provider-neutral transition legality. A runtime, adapter, or agent workflow can propose a transition, but Flow decides whether that transition matches the authored Flow Definition, current state, gate outcomes, route-back policy, and persisted transition history.
Validate a proposed transition from a file:
npx flow validate-transition ./transition-request.jsonThe request shape is intentionally small and stable:
{
"definition": { "id": "agent-dev-flow", "version": "0.1", "steps": [], "gates": {} },
"current_state": { "status": "active", "current_step": "verify", "transitions": [] },
"proposed_transition": {
"from_step": "verify",
"to_step": "publish",
"status": "allowed",
"gate_id": "verify-gate"
},
"manifest": { "schema_version": "0.1", "evidence": [] }
}The result is machine-readable:
{
"valid": false,
"status": "route-back",
"diagnostics": [
{
"code": "transition.gate.route-back",
"severity": "error",
"path": "$.proposed_transition",
"message": "gate verify-gate returned route-back"
}
],
"transition": {
"from_step": "verify",
"to_step": "implement",
"status": "blocked",
"gate_id": "verify-gate"
}
}Definitions that do not declare stricter route or gate policy keep the permissive v0.1 behavior. Route reason ids remain open unless a gate declares a closed route policy such as route_back_policy.allow_unknown_reasons: false. Attempt counting is deterministic: Flow derives attempts from persisted state.transitions, not caller-supplied counters.
Flow Agents consumes this contract downstream when writing its own workflow state, but Flow does not know about Flow Agents sidecars, GitHub pull requests, boards, or any other provider. A Builder Kit-like path such as verify -> evidence -> publish-change -> release-readiness -> merge is just a Flow Definition with steps and gates; Flow rejects jumps across required gates because the proposed transition does not match the definition and evidence state, not because those names are special.
A gate can route failed evidence back to a specific step by adding on_route_back to the gate definition:
{
"step": "verify",
"on_route_back": {
"missing_evidence": "verify",
"implementation_defect": "implement",
"plan_gap": "plan",
"decision_gap": "plan",
"default": "implement"
},
"route_back_policy": {
"max_attempts": 2,
"on_exceeded": "block"
}
}Route reason ids are open strings. Flow documents these standard recommended ids but does not enforce a closed enum:
missing_evidence: Flow or an evidence producer found that required gate evidence is absent.implementation_defect: the implementation failed the gate and should return to implementation.plan_gap: the plan or acceptance shape is insufficient and should return to planning.decision_gap: the work needs a decision or clarification before it can proceed.
Custom reason ids are allowed when a project, kit, or adapter needs narrower routing. Add custom ids to on_route_back when they should select a specific step, and include default for unknown or omitted reasons. If a failed evidence item has no route_reason, Flow uses default when present and otherwise falls back to the gate's own step. Flow only infers missing_evidence when Flow itself detects missing required evidence.
Route-back attempts are deterministic. Flow counts prior persisted route_back transitions with the same gate id, route reason or default, source step, and selected target step. Timestamps, classifier data, diagnostics, analytics metadata, and in-memory counters do not affect routing or attempt counts.
When route_back_policy.max_attempts is exceeded, on_exceeded decides the outcome. A step id routes the run to that recovery step and records both the selected route and recovery step. The special value block blocks the run at the current step while recording the exceeded route-back attempt. Flow validates new route targets against defined step ids; block is only special for route_back_policy.on_exceeded.
Flow Run state and reports expose route-back details for continuation and analysis: selected route, final route target, route reason, attempt, max attempts, exceeded state, evidence refs, expectation ids, classifier, diagnostics, analytics loop key, and recovery step. The CLI records these metadata fields through flow attach-evidence, but Flow core remains neutral: Builder Kit or Flow Agents policy can choose reason ids and mappings, while Flow itself only applies the authored Flow Definition, route_reason, and persisted transition history.
For an adversarial-review pattern, see the reference definition in examples/adversarial-pass-flow.json and the boundary notes in docs/adversarial-pass.md. The example models produce -> adversarial-review -> resolve, routes adversarial defect reasons back to the documented steps, and treats external Survey escalation records as per-round evidence while Flow owns only orchestration, route-back policy, and transition accounting.
Validate arbitrary Flow Definition JSON before starting a run:
npx flow validate-definition examples/builder-kit-flow.json
npx flow validate-definition examples/flow-definition-resource-contract.json --json
npx flow validate-definition examples/invalid-claim-expectation-flow.json --jsonFlow accepts two Flow Definition authoring shapes:
- The v0.1 flat shape used by existing examples such as
examples/agent-dev-flow.json, with top-levelid,version,steps, andgates. - The Resource Contract shape shown in
examples/flow-definition-resource-contract.json, with the Flow DefinitionapiVersion,kind: "FlowDefinition",metadata, andspec.
Resource-shaped Flow Definitions map to the same runtime model as flat v0.1 definitions:
| Resource field | Runtime field |
|---|---|
metadata.name |
id |
spec.version |
version |
spec.steps |
steps |
spec.gates |
gates |
The flat v0.1 Flow Definition shape remains supported for compatibility. Existing definitions, examples, local run snapshots, reports, and workflows that use top-level id, version, steps, and gates do not need to migrate to the Resource Contract envelope.
Resource Contract support currently covers authored Flow Definition and authored Flow Project Config inputs. It does not migrate Flow Run state, gate evidence manifests, reports, transition validation results, Surface-shaped evidence semantics, Flow Agents workflow artifacts, or Builder Kit adapters. In v0.1, .flow/runs/<run-id>/state.json remains the flat Flow Run state contract described by schemas/flow-run.schema.json.
--json emits a stable machine-readable payload:
{
"valid": false,
"path": "examples/invalid-claim-expectation-flow.json",
"error_count": 6,
"diagnostics": [
{
"code": "definition.expectation.claim.required",
"severity": "error",
"path": "$.gates.verify-gate.expects[0].claim",
"message": "surface.claim expectations must include claim"
}
]
}Diagnostics cover shape errors, unknown gate step references, route-back targets, malformed expects, invalid kind: "surface.claim" entries, missing claim.type, optional expectations, claim.subject, and claim.accepted_statuses. validateDefinition(definition) remains the pass/throw validation API; it uses the same diagnostics internally and throws the first diagnostic message for invalid definitions.
The package also exports the runtime primitives used by the CLI:
import {
startRun,
attachEvidence,
evaluateRun,
loadRun,
validateRunTransition,
validateDefinitionWithDiagnostics
} from "@kontourai/flow";
const result = validateDefinitionWithDiagnostics(definition);
if (!result.valid) console.error(result.diagnostics);
const transitionResult = validateRunTransition({
definition,
current_state: state,
proposed_transition: { from_step: "verify", to_step: "publish", gate_id: "verify-gate" },
manifest
});
if (!transitionResult.valid) console.error(transitionResult.diagnostics);Config merge helpers are exported for local installers and adapters:
import {
previewFlowConfigMerge,
applyFlowConfigMerge,
renderConfigMergeMarkdown
} from "@kontourai/flow";
const report = previewFlowConfigMerge(localConfig, proposedConfig);
console.log(renderConfigMergeMarkdown(report));Runtime code and tests reference the JSON Schemas in schemas/:
flow-definition.schema.jsonflow-run.schema.jsongate-evidence.schema.jsonflow-report.schema.jsonflow-transition-validation-request.schema.jsonflow-transition-validation-result.schema.json
npm test and npm pack fail if the checked schemas drift from the v0.1 runtime contract.
Flow is not an agent runtime, multi-agent orchestrator, task board, repo standards engine, hosted service, or hosted web UI. Surface owns portable trust state, Veritas owns repo readiness semantics, and Flow Agents owns agent-facing workflow distribution.