Public Workflow CLI

Flow Agents exposes its supported consumer workflow surface through the primary package binary. Consumer repositories do not need a package.json, a local dependency, or a repository-owned writer script.

Use an exact package version from an isolated npm prefix. This prevents a repository-local dependency with the same version from intercepting the command. Generated workflow actions and doctor remediation include this isolation automatically:

flow_agents() (
  root=$(mktemp -d) || exit 1
  trap 'rm -rf "$root"' EXIT HUP INT TERM
  npm exec --yes --prefix "$root" \
    --package=@kontourai/flow-agents@3.6.0 -- flow-agents "$@"
)

flow_agents workflow start \
  --flow builder.build \
  --work-item provider:work-item-123 \
  --assignment-provider example-provider \
  --effective-state-json .kontourai/flow-agents/provider-assignment.json

flow_agents workflow status --json

flow_agents workflow evidence \
  --session-dir .kontourai/flow-agents/example \
  --expectation implementation-plan \
  --status pass \
  --summary "Implementation plan recorded." \
  --evidence-ref-json '{"kind":"artifact","file":".kontourai/flow-agents/example/example--plan-work.md","summary":"Reviewed implementation plan with Definition Of Done and task-to-criterion mapping."}' \
  --evidence-ref-json '{"kind":"artifact","file":".kontourai/flow-agents/example/acceptance.json","summary":"Stable acceptance criteria and required evidence."}' \
  --evidence-ref-json '{"kind":"artifact","file":".kontourai/flow-agents/example/handoff.json","summary":"Execution handoff and next action."}'

flow_agents workflow critique \
  --session-dir .kontourai/flow-agents/example \
  --verdict pass \
  --summary "Report-only review found no blocking findings." \
  --artifact-ref ".kontourai/flow-agents/example/example--deliver.md" \
  --lane-json '{"id":"code-review","status":"pass","summary":"The delivered implementation was reviewed.","evidence_refs":[{"kind":"artifact","file":".kontourai/flow-agents/example/example--deliver.md","summary":"Reviewed delivery report and changed scope."}]}'

builder.build accepts the stable, human-readable Work Item reference emitted by the selected provider adapter. Flow Agents persists that exact reference as the run subject; it does not infer provider identity from a GitHub-shaped string. Pass the resolved --assignment-provider; non-local providers also pass their standard assignment status result through --effective-state-json. Flow Agents verifies that the current actor is the confirmed holder, retains that provider result as selected-work evidence, and creates a local runtime lease mirror for atomic session mutation. A provider-backed Builder session also takes its branch only from the validated AssignmentStatus.assignment.record.branch. That branch is copied unchanged into the immutable provider snapshot, local assignment mirror, delivery artifact, state, and current-session projections; the public command deliberately has no caller branch override. Re-running start for the same Work Item resumes only when every existing projection still agrees with the current provider-authorized branch. A missing, malformed, or conflicting provider branch fails closed before session mutation. Do not repair such a contradiction by editing runtime artifacts: retain the conflicting session for evidence, release or supersede the provider assignment through its normal provider workflow, and begin a fresh provider-backed Work Item/session. This is the safe recovery boundary until a transactionally recoverable branch-reconciliation protocol exists. A direct local request can resume an existing bound session, but the public CLI does not invent a provider or create an unresolvable local binding.

Approved cross-repository rollouts

An approved portfolio or retrofit initiative does not authorize a retroactive Builder run. Before editing each target repository, create or select that target’s provider-backed Work Item, link it to the portfolio approval, and complete its normal pull-work selection and ownership preflight. Then bind the target Work Item through the public command:

flow_agents workflow start \
  --flow builder.build \
  --work-item kontourai/target-repository#123 \
  --assignment-provider github \
  --effective-state-json .kontourai/flow-agents/target-assignment-status.json

The provider status must confirm the calling actor holds that exact Work Item. start retains the provider result as selected-work evidence and begins at the canonical Builder entry step. A portfolio approval, a branch name, or a finished change is not a substitute for that binding. If the work has already been changed without a bound run, record the gap and create a follow-up Work Item; do not manufacture a prior session, use a private writer, or use a delivery/DECLARED exemption for agent-delivered work.

Follow the reported public next_action through planning, implementation, review, verification, and release readiness. A repository may make CI reconciliation of the session’s delivery bundle a required pull-request check. In that case, publish a provisional delivery after the pull request is open and before recording ci-merge-readiness:

flow_agents workflow publish-provisional-delivery-request \
  --session-dir .kontourai/flow-agents/kontourai-target-repository-123 \
  > provisional-delivery-request.json

# Sign provisional-delivery-request.json.authorization exactly as serialized with a
# configured lifecycle-operator Ed25519 key. Add only the signature block and store
# the resulting authorization outside the project checkout.
flow_agents workflow publish-provisional-delivery \
  --session-dir .kontourai/flow-agents/kontourai-target-repository-123 \
  --authorization-file /absolute/outside-project/provisional-delivery.authorization.json \
  --json

This command is available only to the active bound builder.build run at merge-ready-ci. It first seals the already-reviewed and verified source checkpoint with status: "provisional" and phase: "ci-readiness". The request binds the exact project/session/Work Item, live assignment generation, canonical definition version and digest, Flow head and gate visit, authenticated publish-change provider record and immutable head, source snapshot, checkpoint, bundle, attestation, and mutually exclusive companion digests. Publication transports those exact bytes; the root-owned coordinator rechecks every binding, appends a signed-authorization event under the Flow run lock, and installs a purpose-specific signed completion before the package records the delivery. It then writes only that session’s delivery/<slug>/ transport. Commit and push those companion files before provider checks and before recording ci-merge-readiness, so the provider’s Trust Verify check can reconcile the PR revision. It is not a release decision, does not add a ci-merge-readiness claim, and cannot complete or declare the run. delivery/DECLARED remains unavailable to agent work.

After those provider checks, record the explicit readiness decision and complete learning. Only when the canonical builder.build run has advanced through learn to completed done, publish the terminal CI-visible delivery evidence through the primary public CLI, commit that superseding delivery output, and push the resulting head:

flow_agents workflow publish-delivery \
  --session-dir .kontourai/flow-agents/kontourai-target-repository-123 \
  --json

This command derives the repository and session from the bound artifact; it does not accept a caller-selected output repository or private-writer escape hatch. It refuses a missing bundle, a partial Builder run, an unreconciled bundle shape, a stale or non-holder actor, and a positively identified checkpoint/checkout mismatch. Public test verification stamps the canonical Git workspace snapshot alongside its successful command observations. Before sealing, publishing requires both that stamped verification snapshot and the canonical live review graph to match the exact current workspace. The one supported continuation is a checkpoint-bound provisional delivery: terminal publication permits it only when the verification base is an ancestor of the current checkout, every committed and uncommitted change since that base is confined to the same delivery/<slug>/ transport, and the provisional bundle and checkpoint still match their session-local digests. A missing, altered, stale, unrelated, or concurrent-session delivery fails closed; re-run review and verification instead of borrowing its evidence. Sessions whose older test evidence lacks this snapshot also fail closed. The publisher holds the session subject lock and rechecks the identical snapshot after sealing, immediately before copying, and after the copy. A post-copy source change restores the exact prior delivery/<session>/ destination (if any) and leaves every sibling delivery untouched before failing. It then seals against the derived target checkout’s current HEAD, replaces stale companions with one newly emitted signed or in-toto companion, and verifies that companion binds both the checkpoint digest and current trust bundle before copying the set into delivery/<session>/. Trust Verify accepts a provisional candidate only when the checked PR revision differs from the authenticated published head by exactly the fixed checkpoint-bound files in that one delivery/<slug>/ directory.

At terminal publication, the Git delta may contain all four transport files, or exactly the three mutable files: trust.bundle, trust.checkpoint.json, and the signed or in-toto companion selected by the attestation descriptor. The three-file form is permitted only when trust.checkpoint.attestation.json is raw-byte identical in the terminal revision and the checkpoint revision. Even when Git omits that descriptor from the delta, Trust Verify still treats it as one of the validated four transport files at the checked revision and compares its raw bytes with the checkpoint revision. Ordinary ancestry, tree equivalence, inherited bundles, extra source changes, altered or missing companions, and unrelated session bundles cannot satisfy the check.

Terminal publication is unavailable while learn is active, even when a release decision is positive; provisional publication is the only CI-transport path before learning closes.

builder.shape uses a caller-supplied, safe slug. Derive it from a selected title using lowercase ASCII words separated by single hyphens. Never inject raw request text into a shell command or use it as a slug:

flow_agents workflow start --flow builder.shape \
  --task-slug onboarding-alerts \
  --summary "Shape onboarding alerts into independently actionable slices."
flow_agents workflow status --session-dir .kontourai/flow-agents/onboarding-alerts --json

For tests-evidence, supply one criterion object for every accepted criterion and one or more substantive commands that were actually run. Repeat --command when criteria require different checks. Every command needs a matching top-level command reference, and every passing criterion must cite at least one of those exact commands. A passing observation must also report a positive executed-test or assertion count; a successful zero-test run is rejected. Do not use placeholders such as true or a version command as behavior proof:

flow_agents workflow evidence \
  --session-dir .kontourai/flow-agents/example \
  --expectation tests-evidence \
  --status pass \
  --command "npm test" \
  --summary "The project test command passed for the implemented criterion." \
  --evidence-ref-json '{"kind":"command","excerpt":"npm test","summary":"Exact substantive project test command recorded for this verification result."}' \
  --criterion-json '{"id":"<criterion-id>","status":"pass","evidence_refs":[{"kind":"command","excerpt":"npm test","summary":"Exact substantive project test command run for this criterion."}]}' \
  --evidence-ref-json '{"kind":"artifact","file":".kontourai/flow-agents/example/example--plan-work.md","summary":"Accepted criterion and verification mapping."}'

An embedding host whose current runtime identity cannot reproduce the active assignment actor must establish an expiring recovery-capable session binding, then authorize each ordinary evidence mutation separately. Run evidence-request with the exact evidence arguments, sign the emitted signing_payload with a registered lifecycle-authority key, add that signature to the emitted authorization, and pass the protected signed file to the otherwise identical evidence command:

flow_agents workflow evidence-request \
  --session-dir .kontourai/flow-agents/example \
  --expectation implementation-scope \
  --status pass \
  --summary "Implementation remained inside the accepted scope." \
  > evidence-request.json

flow_agents workflow evidence \
  --session-dir .kontourai/flow-agents/example \
  --expectation implementation-scope \
  --status pass \
  --summary "Implementation remained inside the accepted scope." \
  --authorization-file /absolute/outside-project/evidence-authorization.json

The authorization binds the exact assignment generation, assignment actor key and struct, the independently named host routing key and routing-binding generation, Flow head and manifest, Trust Bundle, evidence arguments, canonical project/run/subject, nonce, and expiry. The external coordinator verifies and durably redeems it before the normal evidence transaction runs. A pointer alone is routing metadata, never bearer authority; replay, binding retirement/replacement, assignment takeover, or changed Flow, trust, or evidence arguments fail closed before another mutation.

When a current root-signed lifecycle completion already binds a Trust Bundle and its external resolution ledger, ordinary workflow evidence correctly refuses to invalidate that completion. If a legitimate later public critique or gate claim has already made that receipt stale, do not rewrite or delete it, append a resolution event, or use history repair. First request and sign the completion-only refresh (the authorization file must remain outside the project):

flow_agents workflow recover-exact-current-completion-request \
  --session-dir .kontourai/flow-agents/example > completion-recovery-request.json

# Sign completion-recovery-request.json.authorization with the configured operator key.
flow_agents workflow recover-exact-current-completion \
  --session-dir .kontourai/flow-agents/example \
  --authorization-file /absolute/outside-project/completion-recovery-authorization.json

This narrow action is available only at the one open builder.build verify gate. It binds an authenticated stale same-run root completion, the raw current bundle and ledger bytes, complete cross-reviewer resolution coverage, critique and edge projections, subject, raw Flow definition and canonical ordered gate-policy digests, Flow head/manifest, fixed transition, nonce, and expiry. It writes no claim, ledger event, bundle, or stale receipt; the coordinator first durably stages and root-signs an exact five-artifact Flow-only publication plan. It activates Flow’s native recovery fence before the first postimage and keeps that exact generation active through root completion/nonce persistence and receipt installation. Prepared retry uses the matching recovery lock, accepts exact all-new state, rolls exact all-old or mixed old/new state forward from the staged postimages, and rejects unknown or mismatched state without restoring foreign bytes. Finalization verifies the exact receipt, postimages, and fence generation, opens the fence through Flow, and then removes the plan and stages. The plan only hashes the bundle, ledger, and stale receipt; it never snapshots or restores them.

The canonical attachment ID and stored filename include the signed authorization digest in addition to the unchanged request-envelope digest. Reusing the same authorization-file path for a later, distinct signed recovery therefore creates a distinct attachment while the durable completion still binds the request digest. Replaying the same signed authorization returns the immutable completion without another attachment. Use it only after all final independent critique/resolution work is complete, and then use reseal for the final verification evidence.

Use the two-stage reseal only for the final builder.build verify evidence after critique resolution:

flow_agents workflow reseal-verification-evidence-request \
  --session-dir .kontourai/flow-agents/example \
  --expectation tests-evidence \
  --status pass \
  --command "npm test" \
  --summary "Final verification passed after the resolved review." \
  --evidence-ref-json '{"kind":"command","excerpt":"npm test","summary":"Final substantive verification command."}' \
  --criterion-json '{"id":"<criterion-id>","status":"pass","evidence_refs":[{"kind":"command","excerpt":"npm test","summary":"Final verification command for this criterion."}]}' \
  > reseal-request.json

# Sign reseal-request.json.authorization using the configured lifecycle operator key,
# write the signature block into a protected file outside the project, then:
flow_agents workflow reseal-verification-evidence \
  --session-dir .kontourai/flow-agents/example \
  --authorization-file /absolute/outside-project/reseal-authorization.json

The request executes the existing evidence writer once into a retained transaction candidate; it does not attach or publish that candidate. Its unsigned authorization binds the current raw bundle, candidate bytes and transaction id, unchanged ledger digest/length/tail, exact current completion raw/core identity, canonical Flow step/gate, head and manifest, critique projection, run subject, nonce, and expiry. It also binds the exact target verify expectation and the predecessor/current claim id, status, raw-JSON digest, ordered index, and replace delta. The signed action invokes only the fixed lifecycle helper. The coordinator derives the protected current verify-gate requirements, requires the target exactly once, and rejects predecessor or replacement gate_claim metadata that does not match the current expectation’s step, claim type, and subject type. It acquires Flow’s native run-mutation lock before capturing a closed transaction plan over exactly six artifact identities: session bundle, Flow manifest, Flow state, request-keyed stored attachment, JSON report, and Markdown report. The root-signed plan contains no artifact paths; it binds the request, authorization key and nonce, pinned reducer identity, result core, and exact pre/post presence, mode, size, and digest for each fixed identity. Old and new images are durably staged in fixed siblings and reread before publication. It permits replacement of only that one ordered target claim; every other claim, including other verify-gate claims, must remain byte-identical and in the same order. It requires a byte-identical critique projection, attaches the candidate to the builder.build verify gate, commits the exact candidate bytes without appending a sixth ledger event, and installs a new root-signed exact-current completion. A provider-neutral Flow recovery fence becomes active before the first postimage and remains active through durable root completion and exact receipt installation; all canonical readers and ordinary Flow mutations fail closed while active. Flow’s native writer assigns a unique generation and durably publishes it; the dedicated finalizer requires that exact generation before reopening. Consumers bind the generation, file bytes, and run-directory identity across their complete supported reads and reject symlinked fixed Flow ancestry. Before root records a nonce or any plan/stage exists, the helper preflights the installed mutation lock, recovery lock, active writer, and generation-bound finalizer APIs. Recovery accepts only an exact all-old or all-new generation. Mixed, malformed, or unknown generations are quarantined with the fence left active for offline recovery. An active legacy recursive reseal journal is never auto-restored. Publication also preflights the fixed, protected verification-reseal-atomic-replace.cjs host capability. That administrator-supplied capability must implement kontourai.atomic-expected-preimage-replace.v1: atomically compare the named leaf’s exact preimage and install or delete only the authorized postimage. It receives a pinned parent descriptor and basename, while the coordinator independently rechecks the parent and postimage. Root validates its fixed protected artifact; only the caller-identity worker executes its code. The reference coordinator ships no pathname or descriptor-only fallback and refuses on every platform before coordinator state, nonce, plan, stage, fence, or artifact mutation when the capability is absent or invalid. Portable request creation and external signing remain available. After reopening, the signed plan remains the cleanup recovery marker until every fixed stage is removed; replay validates the exact receipt/postimages and safely finishes interrupted cleanup. Stale, altered, replay-mismatched, or wrong-gate requests fail closed; durable nonce/completion and transaction recovery make an exact completed retry a replay.

The public lifecycle verbs are pause, resume, release, cancel, archive, resolve-critique, repair-critique-resolution-history, and reseal-verification-evidence. Pause, resume, and release require the current assignment actor and an explicit reason. critique records the clean-critique claim but does not independently attach it to Flow or advance a gate. Cancel and archive require a signed user/operator authorization file. Flow owns the canonical run transition; Flow Agents validates assignment and request binding and projects the resulting run. Critique derives reviewer identity from the calling runtime actor. An active implementation assignment is required, and its actor cannot review its own work; the delegated reviewer invokes the command directly under a distinct identity. The public interface does not accept a caller-selected reviewer label. Every critique includes an explicit pass, fail, or not_verified verdict and at least one substantive --lane-json. Passing critiques additionally require local reviewed --artifact-ref values and every lane to pass; reviewed files and the workspace snapshot are hashed into the stored review target so later implementation changes invalidate stale clean critiques.

Current local runtime actor IDs provide coordination-level separation, not a cryptographic identity guarantee. A policy that requires externally attested reviewer identity must keep that assurance NOT_VERIFIED until the runtime supplies a trusted delegation credential.

Resolving repaired critique history

workflow resolve-critique closes a historical failing or not-verified review without deleting it or borrowing the earlier reviewer’s identity. It is only available during builder.build verification. It requires an Ed25519-signed user/operator authorization handled by an externally provisioned lifecycle-authority helper. Administrators provision protocol v1 at the immutable path /usr/local/libexec/kontourai/flow-agents-lifecycle-authority-v1; callers cannot select another executable. The helper must be outside the project, package, and worktree, OS-owned, executable, and non-writable by the runtime user, group, or world through every path component. Platforms without a supported ownership adapter fail closed. The helper—not package JavaScript—owns signature and registry verification, locking, nonce replay protection, preimage CAS, atomic bundle/history writes, canonical evidence attachment, and any Flow synchronization for the authorized transition. The authorization binds the exact canonical project root, run, subject, pre-mutation bundle digest, critique IDs and hashes, expected resolving reviewer, nonce, request time, and expiry. Ambient runtime identity and actor overrides do not authorize this operation.

Requests and responses use strict single-line JSON envelopes. A response is accepted only when its protocol version, action, canonical request SHA-256 digest, status, and exact action-specific result match the request. Empty, multi-line, malformed, or extended responses fail closed. The helper must independently reject unknown fields/actions, canonicalize and constrain every received path, derive the run/project/artifact roots rather than trusting claimed relationships, and perform mutation only after its own locked precondition and compare-and-swap checks. Package-side graph validation never invokes a live verification subprocess or treats a helper response as authorization. It verifies the coordinator’s pinned Ed25519 completion receipt and requires its result digest to bind the exact resolved graph before Builder consumes the transition.

For a signed critique resolution, the coordinator accepts up to 16 MiB only for the canonical Flow evidence manifest. The protected descriptor, O_NOFOLLOW, regular-file, group/world-mode, and mandatory JSON checks remain in force. Definitions, state, trust bundles, authorizations, journals, keys, and responses retain their smaller existing limits; this is not a general input-size increase.

Completion verification always reads the fixed public key at /etc/kontourai/flow-agents-lifecycle-authority-v1/completion-verification-key.pem; no command, authorization, or environment setting can choose another key. On Darwin only, the standard protected /etc alias resolving exactly to /private/etc is accepted. Every resolved component and the final O_NOFOLLOW Ed25519 key descriptor are validated as protected. Different alias targets, deeper or writable symlinks, non-root-owned components, all non-Darwin symlinks, and all helper-path symlinks are rejected. The helper itself remains pinned and symlink-free.

Administrators upgrade the direct source packaging/lifecycle-authority/coordinator.mjs through the privileged installer. They verify the installed coordinator’s bytes and SHA-256 separately from the signed runtime digest, which continues to identify runtime-v1.mjs; the installer preserves its prior coordinator/runtime/pin/ reducer set for rollback. This operational path is administrator-owned and cannot be selected or overridden by package callers.

The helper and its provider-neutral key registry are deployed and configured by runtime administrators outside source control. Flow Agents ships neither helper configuration nor keys. Missing, untrusted, repository-local, or writable helpers fail closed. The privileged coordinator only verifies authority, serializes and records the operation, then gives a one-use signed capability to a worker running as the invoking non-root user; repository artifacts are read and written only by that unprivileged worker.

Use immutable metadata.critique_record_id values from the two trust-bundle critique records. The resolving critique must be verified, current against the workspace, later in the writer-issued predecessor hash chain, and cover every failed or not-verified lane plus every open finding from the earlier critique. When both reviews target Git worktrees, the resolving commit must descend from the earlier reviewed commit. The explicit per-lane and per-finding edges are the policy-defined relationship between the two reviews.

flow_agents workflow resolve-critique \
  --session-dir .kontourai/flow-agents/example \
  --prior-record-id '<earlier-critique-record-id>' \
  --resolving-record-id '<later-passing-critique-record-id>' \
  --authorization-file critique-resolution.authorization.json

The earlier record remains in trust.bundle with its original reviewer, findings, timestamps, superseded_by reference, and critique_resolution audit record. Repeating the identical valid request is a no-op. Missing, ambiguous, circular, stale, equal-snapshot, wrong-subject, or unauthorized requests fail without changing the bundle.

The signed authorization is consumed once under the subject lock. Resolution also appends a separately hashed event binding the authorization digest and exact edge. The local event chain is tamper-evident; deployments requiring non-repudiation should additionally retain the signed authorization and anchor the resulting state in their provider-neutral durable audit store.

Repairing an irrecoverable legacy authority-history gap

workflow repair-critique-resolution-history-request and workflow repair-critique-resolution-history are deliberately distinct from ordinary resolution. They are available only for an already-superseded, cross-reviewer edge whose original resolve-critique event is absent from the external lifecycle-authority.resolution-events.json ledger. They do not reconstruct that original event, signature, timestamp, reviewer, or Trust Bundle claim. Instead, a newly signed repair authorization records the missing original event ID and authorization digest with the fixed disclosure reason coordinator-external-ledger-overwrite-v1.

The request binds the exact protected Trust Bundle bytes, external-ledger digest/length/tail, current signed completion digest, preserved edge digest, both critique records and hashes, reviewer, snapshots/heads, project/run/ subject, nonce, request time, and expiry. Changing any of those values, finding the original event, or finding a prior repair rejects without mutation. A successful repair appends exactly one repair-critique-resolution-history event, writes a new root-signed completion and Flow attachment, and leaves trust.bundle byte-identical. The strict graph accepts exactly one authority proof per cross-reviewer edge: either its original event or one repair for a missing original. Zero, both, duplicates, unmatched events, altered edge data, or an invalid event chain fail validation.

The historical bridge has three jointly required anchors: the root-signed historical completion; the canonical Flow manifest entry selected by that completion request SHA-256 plus its protected stored Trust Bundle snapshot; and the request-keyed root-only durable operation, completion, and applied nonce records. The coordinator accepts only one ledger prefix that reproduces the historical completion core with that stored snapshot. A missing or tampered durable record, attachment, snapshot, critique/edge projection, or an ambiguous prefix fails closed.

An old completion proves continuity for this repair request; it is never a current completion. Builder synchronization, artifact validation, ordinary resolution, and final gates continue to require an exact-current receipt and must reject it. This remains true when a later critique is appended without a new completion. Only a successful bridge produces the one new exact-current completion and Flow attachment those strict consumers can use.

The root-owned helper verifies both durable-state and historical anchors before it grants a one-use worker capability, then verifies them again immediately before mutation. The worker performs raw Trust Bundle and ledger compare-and- swap checks during preparation and again before publication. The request lock serializes operator actions: an exact completed request replays without overwriting a newer receipt; prepared recovery repeats the checks; and any session/Flow fault rolls back both artifact trees without a partial event or attachment. The serialized operator flow is read-only request generation, external Ed25519 signing, one helper invocation, then retention of the root-signed completion; neither a repository file nor package caller is a durable authority root.

# Read-only: emit the precise payload that an external operator must sign.
flow_agents workflow repair-critique-resolution-history-request \
  --session-dir .kontourai/flow-agents/example \
  --prior-record-id '<earlier-critique-record-id>' \
  --resolving-record-id '<later-passing-critique-record-id>' \
  > critique-history-repair.request.json

# After the operator adds the Ed25519 signature outside the worktree:
flow_agents workflow repair-critique-resolution-history \
  --session-dir .kontourai/flow-agents/example \
  --prior-record-id '<earlier-critique-record-id>' \
  --resolving-record-id '<later-passing-critique-record-id>' \
  --authorization-file critique-history-repair.authorization.json
flow_agents workflow pause --reason "Waiting for a decision"
flow_agents workflow resume --reason "Decision received"
flow_agents workflow release --reason "Handing work back"
flow_agents workflow cancel --authorization-file cancel.json
flow_agents workflow archive --authorization-file archive.json

workflow status is read-only. It reads the actor-scoped current-session pointer, the projected state, and the canonical Flow run without rewriting either store. Its next_action is freshly derived from the canonical run, so a stale sidecar projection cannot misdirect recovery.

Bounded Continuation Driver

workflow drive lets the active implementation assignment run multiple Flow steps without a human continuation prompt. Flow remains authoritative: the runtime adapter receives the current projected action, but its completed result means only that one model turn ended. The driver returns done only after the canonical Flow run is terminal.

The adapter command is an explicit JSON argv file whose executable must be an absolute path. Flow Agents invokes it directly without a shell, writes one versioned continuation-turn request to stdin, and requires exactly one JSON result on stdout:

{ "argv": ["/absolute/path/to/runtime-adapter", "--profile", "builder"] }
{ "status": "completed", "summary": "Turn ended; synchronize canonical evidence." }

A completed result may also include a generic JSON evidence object of at most 65,536 bytes. Flow does not interpret its domain semantics. Trust-sensitive callers can ask the long-lived driver to attest the exact request/result sequence it observed by providing a one-time Ed25519 private key:

flow_agents workflow drive \
  --session-dir .kontourai/flow-agents/example \
  --adapter-command-file .kontourai/flow-agents/runtime-adapter.json \
  --evidence-signing-key-file /absolute/protected/one-time-ed25519-private.pem \
  --evidence-checkpoint-dir /absolute/protected/empty-checkpoint-directory \
  --max-turns 6 \
  --json

The key file must be an absolute canonical regular file. The driver reads it no-follow and unlinks it before any adapter starts, retains the key only in driver memory, and adds an evidence_attestation to the final JSON outcome. That attestation carries the public key, a base64 payload containing the canonical outcome and ordered adapter requests/results, and an Ed25519 signature over the exact payload bytes. Consumers must compare the public key with the key they pinned before launch, verify the signature, and then validate any evidence-specific schema. Without this optional flag, the outcome is not externally authenticated.

An evidence checkpoint directory is optional and requires both the signing-key and JSON flags. It must be an absolute canonical, non-symlink, empty directory provisioned by the caller outside the model’s writable workspace. After each accepted adapter result is canonically synchronized and measured, the driver publishes one bounded signed checkpoint there. Each checkpoint binds the exact accepted-turn journal record, the canonical gate projection at that point, its sequence, and the digest of its predecessor. Its machine-readable evidence_scope: accepted_prefix and drive_completion: not_attested fields prevent an accepted adapter result from being interpreted as proof that the drive returned. Publication uses an unpredictable same-directory staging file, fsync, and an atomic no-replace link to checkpoint-NNNNNN.json. Incomplete staging files are ignored. Consumers must pin the launch public key and verify the directory with the package’s verifyContinuationEvidenceCheckpoints export.

A verified checkpoint proves only the ordered accepted prefix and canonical state measured at its publication time. It does not prove that the whole drive completed. A later timeout or process termination may prevent a final aggregate attestation while leaving earlier checkpoints valid. Malformed final files, gaps, reordering, key mismatch, cross-run substitution, and signature or chain failures are rejected rather than projected as partial success.

Every JSON outcome also carries canonical_gate_projection, a compact observation copied from the final synchronized Flow state while the continuation lock is still held. It identifies the run and definition, current status and step, evaluated gate statuses, matched evidence ids, trust diagnostic codes, and accepted exceptions. This projection is final-output telemetry only: it is not included in continuation snapshots, adapter requests, or model context. When --evidence-signing-key-file is used, the projection is inside the signed outcome bytes; otherwise consumers may display it but must not treat it as authenticated proof.

An adapter may instead park on a process or deadline. A pending barrier is persisted and does not consume another turn when workflow drive is invoked again:

{ "status": "wait", "barrier": { "kind": "pid", "pid": 12345 }, "summary": "Waiting for the verification process." }
flow_agents workflow drive \
  --session-dir .kontourai/flow-agents/example \
  --adapter-command-file .kontourai/flow-agents/runtime-adapter.json \
  --context-policy fresh \
  --max-turns 6 \
  --turn-timeout-ms 900000 \
  --barrier-wait-ms 300000 \
  --json

--context-policy warm remains the default and requests one new adapter context for the mission, then resumes it. --context-policy fresh requests a new context for every bounded Flow action. Both policies pass the same canonical gate-action handoff and preserve the same Flow gates, evidence rules, mission budget, and adapter authority. The selected policy is persisted with the mission and cannot be changed on resume. Adapters must honor the request’s context_strategy.thread value and must not infer context routing from model names. This is a context-management capability, not permission to drop gates, invent evidence, or replay a prior transcript into a nominally fresh context.

Driver state and its append-only event stream live under .kontourai/flow-agents/<slug>/continuation-driver/. The mission turn count survives reinvocation; subsequent invocations must use the same --max-turns value. The request contains the canonical run id, definition id, current step, projected next_action, iteration, and budget. Builder turns additionally carry one bounded top-level gate_action_envelope with immutable skill identities, declared artifacts/evidence, requirement satisfaction and unresolved ids, typed public workflow.evidence/workflow.critique argv or product-operation bindings, one-turn stop semantics, product-declared implementation policy, and prior canonical progress/stagnation. Parameter values are appended as separate argv entries; adapters must not perform string substitution into a shell command. The envelope is request-only and is not duplicated in projected next_action or durable state.json. It does not mutate or replace the runtime system prompt. Adapter errors are recorded as failed turns and fail open to canonical resynchronization and the next bounded turn; they cannot bypass the persisted mission budget. The Builder Flow projection supplies the canonical continue/wait/done/failed disposition, so the generic driver does not duplicate Flow lifecycle semantics. Human-decision and paused Flow states park, while remediable blocked and accepted-exception states continue; failed Flow runs stop as failed. Assignment ownership is revalidated before every adapter turn. A session-scoped process lock rejects concurrent drivers and safely removes unique lock files left by exited owners. The adapter argv plus the content digests of its executable and absolute regular-file arguments are bound to the mission on first invocation and rechecked before every turn. Adapter process groups are terminated after every non-wait result. In addition, state rollback or deletion is rejected when its append-only event history proves turns already started. These local coordination records detect accidental or in-process rollback; they are not a cryptographic boundary against a process that can rewrite the entire artifact directory.

Authenticated publish-change

publish-change is a provider-neutral product operation with a GitHub gh-CLI adapter as the first implementation. It is not a generic operation runner and it is not a generic evidence interface. A configured status projects the executable argv beginning with:

flow-agents publish-change execute --session-dir .kontourai/flow-agents/<slug>

The status projection supplies this operation only when its effective ChangeProvider is configured and compatible. It then describes the bounded --title, --body, --head-ref, --base-ref, and optional --draft inputs. The command accepts those named flags only; it does not accept a result JSON, a caller-selected expectation or operation id, or a private-writer switch. It derives the repository, immutable head SHA, current assignment actor, canonical run, and current gate-visit identity from the active session rather than trusting caller copies.

Configuration is explicit. Project settings live at <repo-path>/context/settings/change-provider-settings.json; optional machine-global settings live at $HOME/.config/flow-agents/change-provider-settings.json. Resolve and inspect the effective settings without running a mutation:

flow-agents effective-change-provider-settings --repo-path . --json

Settings are deep-merged in this order, where each later value wins:

  1. global defaults
  2. matching global project entry
  3. project defaults
  4. matching project entry

The currently supported configured provider declares role ChangeProvider, kind github, capabilities change.create and change.observe, and executor gh-cli; credentials remain in the authenticated gh environment, never in these settings. An absent configuration remains external_capability_required; an invalid or incompatible configuration remains unavailable with its compatibility reason. Neither state exposes an executable completion claim, and both must remain an explicit external capability/verification gap rather than a successful publish.

For a configured provider, the GitHub adapter resolves gh only from fixed trusted absolute locations (never caller-controlled PATH), authenticates it, queries pull requests by configured repository, base ref, head ref, and immutable head SHA, and verifies the title, body, and draft intent before returning a result. It creates only when no exact match exists. If creation has an ambiguous failure (for example, a timeout after GitHub accepted it), it queries again and recovers exactly one matching published pull request. An exact open record supports the normal path; an exact merged record supports truthful reconciliation when provider work completed before the local workflow caught up. Multiple candidates, wrong repository/base/head/SHA/intent, a closed-but-unmerged record, malformed output, or an unauthenticated provider fail rather than selecting or creating another record.

The durable result is bounded to 65,536 bytes and is written only by the Flow-owned completion transaction as publish-change.result.json. It records the bound run/definition/step/gate visit, provider kind/configuration/adapter, repository, provider record id and number, HTTPS URL, normalized published state (open or merged), base ref, head ref and SHA, the bound assignment_actor, the authenticated GitHub provider_actor, and observation time. Title, body, and draft are authenticated request intent rather than free-form result fields. Before persistence, Flow reacquires the subject lock and revalidates assignment ownership, active gate visit, exact request binding, and effective provider configuration; it then re-observes the provider record, attaches only pull-request-opened, requires that bound evaluation to advance exactly one canonical step, and projects the resulting state.

A caller-authored publish-change.result.json, generic adapter JSON/evidence, or a package internal/private writer cannot complete this gate. Provider/authentication failures leave the gate unresolved; retry the public operation after correcting the provider condition, relying on the exact-match recovery protocol rather than a blind second create. Provider stdout/stderr and authentication material are deliberately excluded from result artifacts, trust bundles, diagnostics, logs, and test snapshots. Local deterministic coverage does not itself prove a live provider operation; privileged live recovery remains a separate verification activity.

Immediately before spawning an adapter turn, the driver writes a transient, schema-versioned active-turn.json beside its mission state and passes a raw 32-byte turn secret plus the path-safe, signed run id in FLOW_AGENTS_CONTINUATION_TURN_SECRET and FLOW_AGENTS_CONTINUATION_RUN_ID to that child. Only the secret’s SHA-256 is persisted in the signed record. The driver’s schema-1-compatible mission state separately stores the ephemeral public-key digest before the adapter starts, so replacing and correctly re-signing the entire active-turn record with another key does not replace the signer anchor. The driver clears that digest with the active-turn step on every completion, error, cleanup, terminal, waiting, and budget path. It replaces every inherited continuation capability variable but preserves ordinary FLOW_AGENTS_ACTOR. The shared actor resolver remains ordinary: it never accepts continuation data as an identity override. When an assignment-gated public workflow command finds that ordinary resolution does not match, it may use only a live signed active-turn record bound to the exact session, turn secret, run id, assignment file and actor struct, mission, adapter identity, expiry, and driver lock; it returns the signed assignment identity only for that active-turn evidence gate. Pause, resume, release, cancel, and archive remain control-plane operations: they require ordinary actor identity or their existing explicit external authority and never accept this turn capability. The private key remains only in the driver process. The Stop hook resolves the signed run id under the canonical artifact root and fully validates that exact session before consulting ordinary current pointers. Once the base signed turn remains valid, that exact session stays selected even if canonical Flow has become paused, blocked, completed, or another canonical disposition; Stop never falls back to a conflicting actor or global pointer. It securely validates canonical state against the run’s definition and treats only canonical active as authority to make the ordinary unfinished canonical-gate warning advisory so the adapter can return control to the driver. It never advances a Flow gate, releases assignment or liveness for a continuation-owned nonterminal run, or relaxes evidence, integrity, false-completion, malformed-state, or configuration blocks. The record is removed when the child completes, errors, or times out; parent identity changes leave it to expire instead of unlinking through a replacement.

This is cooperative same-user protection, not cryptographic filesystem isolation from a hostile same-UID process. A same-UID process that can rewrite both mission state and authority records or control the driver process remains outside this boundary. Within the cooperative boundary, the mission digest anchors the driver’s ephemeral signer, while descriptor reads, final-path inode rechecks, and realpath/device/inode parent rechecks detect practical replacement races. Active-turn and lock records are capped at 16 KiB; canonical assignment and continuation mission records are capped at a conservative 1 MiB so valid provider metadata is not rejected. PID liveness is best-effort only: PID reuse and same-UID process control remain outside this local coordination boundary.

The event stream records turn_completed, gate_not_advanced, turn_failed, and best-effort authority_cleanup_failed. Cleanup failures are audited but do not replace the adapter or canonical outcome. Failed turns carry failure_kind of timeout or adapter_error; a completed adapter turn whose canonical run remains active at the same current step records gate_not_advanced. These events describe driver execution only and do not change canonical Flow state. Adapter-returned evidence is not interpreted as gate evidence; only the public workflow evidence path can attach evidence for Flow evaluation. Same-step canonical evidence or declared-artifact hash changes are recorded as progress, while repeated no-progress turns are classified as possible stagnation and then stagnant without fabricating a gate outcome. Progress uses run-wide canonical evidence/artifact manifests and resumes from the durable last_progress baseline after interruption or reinvocation. Kit metadata, skill source, and observed artifact reads are bounded descriptor-stable regular-file reads that reject symlinks and identity changes. Request-facing declared and required artifacts exclude control state.json, even where legacy kit ownership metadata retains it. Kit validation and envelope construction both cap an action at 16 skills and a flow at 128 distinct observable file artifacts, excluding virtual trust-bundle refs and control artifacts consistently. Synchronization measures an interrupted, waiting, terminal, or callback-failed turn before clearing its recovery marker. Evidence-free canonical gate evaluation is limited to accepted exceptions and gates whose effective expectations are all optional; ordinary missing-required gates remain unevaluated. Signed drives reserve aggregate attestation capacity before adapter execution when another bounded signed result cannot fit. When a protected checkpoint directory is supplied, each accepted turn is also signed and published atomically after canonical measurement. These records prove an accepted prefix only; canonical terminality still comes from the final synchronized outcome. The complete serialized adapter result is capped at 74,000 bytes, and preflight reserves that exact maximum plus the actual request and JSON structure. Accepted request/result pairs and measured progress are journaled durably before the active marker is cleared. Restart idempotently completes missing audit writes, and signed attestation fails closed when persisted accepted events lack journal coverage.

Compatibility Doctor

Run doctor through the exact isolated package helper defined above:

flow_agents workflow doctor --json

The report distinguishes the executing CLI from a repository-local dependency and reports the workflow/writer contract, installed hook and writer package, active Kits, Builder Kit content, Flow runtime and definition, workflow-state schema, and trust-bundle schema. Incompatible or missing installed components produce a nonzero exit and an exact, version-pinned init command that preserves the recorded runtime and active Kits.

The package may use lower-level writer modules internally. They are not a supported consumer or skill surface. Consumer guidance and Builder skills use flow-agents workflow exclusively.