Skip to content
About 4 min read

Artefacts and unit gates

How nodes hand off to one another, how artefact identity is composed, how unit gates decide, and why a downstream node cannot modify an upstream artefact.

Artefacts are the data plane

Nodes do not hand off through conversation; they hand off through artefacts. This is a central product choice: a conversation cannot be validated, cannot be referenced stably, and cannot be consumed safely downstream.

Every successful attempt freezes its own artefacts into an immutable version. What a downstream node reads is always the frozen version, never a temporary file in a runtime directory.

Artefact identity

Artefact identity is composed of four parts: the node identifier, the output name, the attempt identifier and the content digest.

This means the artefact of the same name produced by the same node in different attempts is a different artefact, not a second write to one artefact. A downstream node cannot modify an upstream version, because what it references is one specific, already frozen combination.

The flow's output declarations are the required contract; the artefact manifest reports what actually happened. Extra runtime artefacts can satisfy a declared optional or collection input, but cannot add a dependency edge.

The completion protocol

The core conditions for a node to succeed are:

  • every required business artefact declared by the flow has been produced;
  • the artefact manifest exists, is non-empty, and can enumerate the actual artefacts;
  • the result summary exists and contains valid content;
  • every unit gate passes.

The runner validates paths, file existence, size, format and digest, and then freezes the attempt.

Artefact validation happens before the read-only freeze, and summary format validation is mandatory. The evidence for every successful attempt is therefore complete and self-consistent.

Unit gates

A unit gate is a shell command you declare. Deterministic builds, tests, static checks and scans are all carried by it; the runner executes it only in this attempt's worktree and judges the result by exit code.

The runner image provides Go, Node and Python toolchains at the same time, so those repositories can run native verification inside the sandbox.

When a gate fails, the supervisor first sends the command, the exit code and the controlled output back to the current agent session, and performs a bounded number of repair reruns within the same attempt. The limit is frozen explicitly by the flow, and nodes cannot override it.

This is an important design detail: a gate failure is not an immediate failure, because giving the agent a chance to fix it is exactly what a human developer would do. But the count is capped, so there is no unbounded loop.

Code evidence and artefact evidence

The completion protocol freezes two kinds of reviewable evidence at once.

Code evidence binds the task, node, attempt and code revision. A caller may only submit normalised relative paths; the provider resolves objects from the frozen reference. Submitting a revision number, an object identifier or a physical repository path is not allowed, and the final task branch cannot be passed off as historical state.

Artefact evidence consists only of the artefact manifest, the result summary and the contract-declared outputs. After artefact contract validation the supervisor copies them atomically into a read-only snapshot outside the agent-writable directory. A later node modifying the runtime directory does not change the frozen content, and undeclared temporary files cannot be read through the interface.

Listings return only path, size, media type and digest metadata. Bodies are paged by bytes with an explicit per-page cap, supporting text or binary files of any size without resorting to enlarging connection message sizes.

The execution tree layout

Every attempt uses its own immutable directory:

.fusion/
  state.db
  stages/<stage-id>/attempt-<n>/
    artifacts.json
    result.md
    outputs/
  worktrees/

The canonical artefact manifest format is an object containing an artifacts array. The runner also accepts the top-level array that historical agents may have produced, but both formats go through the same field, path, file-existence and digest validation — compatibility parsing is not a downgrade to lenient acceptance.

Data lifecycle

Node files and snapshots are sandbox lifecycle data and do not enter the control plane database. Once a sandbox is gone, historical archiving is the job of the separate artefact archive mechanism.

When a task ends, the system-level knowledge consolidation hook produces a knowledge increment from the task inputs, artefacts, code changes, verification results and authorised interactions. A successful task archives, for every successful attempt, the artefact manifest, the result summary, all declared artefacts, and the final graph and version manifest; it does not archive the source worktree or undeclared temporary files.

When a task fails or is cancelled while its sandbox is still reachable, the platform archives the declared artefacts of completed nodes, the last failed attempt, the failure report and the diagnostic manifest. If the sandbox is already gone, the material cannot be re-uploaded; the platform relies on the trace data that has already reached the telemetry system and on the control plane's task-level failure record.

The final manifest produced by archiving is a read-only execution report, not a recoverable checkpoint. After a task ends the UI can read that report to show history, but cannot use it to restore the original sandbox execution.