ADR 0041 - Wire CLI Command Surface

Defines `wire` as the first-party command for compiling and running Wire programs, separate from the durable `cortex-pulse` service.


On this page
  1. Status
  2. Context
  3. Decision
  4. Alternatives Considered
  5. Consequences
  6. Positive
  7. Negative
  8. Obligations
  9. Related

ADR 0041 - Wire CLI Command Surface

Status

Proposed - this ADR defines the command surface for the standalone Wire track. It does not implement the command.

Context

Cortex is a standalone substrate, but the current executable story is split:

  • Wire can parse and compile source into a compiled circuit.
  • Pulse can execute stage plans through the Haskell library and the durable cortex-pulse service.
  • The stock cortex-pulse binary intentionally starts with an empty task registry.
  • Useful executor bindings have mostly appeared in downstream applications.

That is correct for production embedding, but it leaves no first-party path for learning, demos, smoke tests, or small local Wire programs. A user should be able to write a .wire file, compile it, inspect the compiled artifact, and run a small program without creating a downstream service.

The command must not blur the architectural boundary. The durable runtime service remains Pulse. The Wire command is a developer and local-execution surface over the compiler, standard executor bindings, and an explicit local runner mode.

Decision

Cortex should provide a first-party command named wire.

The initial command surface is:

wire FILE
wire build FILE
wire run FILE

wire FILE is the default local experience. It is shorthand for wire run FILE, so a flake user can run a checked-out example with:

nix run .#wire examples/wire/interactive-priority-planner.wire

wire build FILE compiles Wire source using the standard Cortex registry and writes the compiled CompiledCircuit JSON artifact. By default it writes pretty JSON to stdout. --out FILE may write the artifact to disk.

wire run FILE compiles the same source, lowers the compiled circuit through the standard Cortex bindings, and executes it through the in-memory Pulse runner defined by ADR 0043.

The command is intentionally shaped like a small command family rather than a one-off demo binary. Future subcommands can add checks, formatting, package/build-cache behavior, registry inspection, or durable submission without changing the executable name.

wire and cortex-pulse have different roles:

CommandRole
wireWork with Wire source locally: compile, inspect, run, test, benchmark.
cortex-pulseRun the durable Pulse service with a host-supplied task registry.

The first implementation should expose wire through the same build surfaces as other executables: the Cabal executable stanza, Nix package/app output, and a just build-wire convenience target.

Alternatives Considered

  • Extend cortex-pulse with Wire subcommands - rejected because cortex-pulse is the durable service shell. Mixing local source tooling into it would make the service command look like the authoring command and would obscure the empty-registry boundary.
  • Name the command cortex-wire - rejected because the user-facing language command should be short and stable. The package and flake output can still make the Cortex origin clear.
  • Only provide Haskell library APIs - rejected because it keeps Cortex technically standalone while preventing basic standalone use, tutorials, CLI smoke tests, and local benchmark runs.
  • Make wire build produce a new runnable bundle format immediately - rejected for v1. The existing compiled circuit JSON is the compiler artifact already present in the system. A richer bundle can be added later if execution needs cached registry metadata or lockfiles.

Consequences

Positive

  • Cortex gains a standalone authoring and demo path that does not depend on a downstream product.
  • CompiledCircuit becomes an inspectable artifact for examples, tests, and debugging.
  • The local run path can dogfood Wire, CorePure, node-boundary wrapping, and simple host effects.
  • Future benchmarking can target a stable command instead of ad hoc test harnesses.

Negative

  • Cortex now owns CLI UX compatibility for the wire command.
  • The command needs careful docs so users do not confuse local in-memory runs with durable Pulse service execution.
  • Adding a Haskell executable changes Cabal and materialized Nix plans.

Obligations

  • Implement wire build, wire run, and the bare-file wire FILE shorthand as small wrappers around library APIs, not as a second compiler or second runtime.
  • Keep wire run honest about its execution mode: local, in-memory, and non-durable unless a future subcommand explicitly targets the durable service.
  • Document the relationship between wire, cortex-pulse, compiled circuits, and downstream bindings in the Usage guide.
  • Add CLI tests or smoke tests that run without Postgres.