Assemble the plan. Seal the run. Prove what ships.
Constructicon is an execution and governance layer for agentic software engineering: sealed workflows, durable human collaboration, and proof-carrying Git changes.
Agents propose work and compose its structure. Constructicon validates that proposal, pins what will execute, scopes its capabilities, and records the evidence for external changes. Humans observe, advise, and approve through the same typed control plane.
Authored intent may be ergonomic. Executed reality must be explicit.
Developer preview. M1 through M7.1 are complete, and M8 (live executors) reached its bounded closure: executor contracts, networkless Linux containment, contained WRITE capture and gates, and three adapters with recorded evidence. Codex and Claude Code have accepted historical subscription READ and WRITE evidence; Pi has a qualified bounded local READ profile. M9 (self-improvement through evaluated candidates) delivered its bounded first phase: an installed fixed selector trial, run live once through owner approval, promotion and rollback. None of this enables a generally available production provider. See current status and open work.
An agent's proposal, a successful check, a human approval, and an installed change are different facts. Constructicon keeps the relationships between them explicit and recoverable:
What exact plan ran, against which component world, what evidence passed, what changed, and can the answer survive a crash or retry?
The model may change. The execution, recovery, and authority laws do not move into the model or its provider.
Within Constructicon's Git authority, proposed code reaches a protected ref through one exact, attested, idempotent Git transaction.
Gates run against the prepared merge commit into the current base.
merge_verified installs that exact commit. A moved base, missing evidence,
forged result, mismatched subject, or failed check moves nothing.
Agent, MCP client, or Python SDK
|
v
strict Ref | Graph | Loop
|
v
admission and typed rejection
|
v
sealed ExecutionManifest
|
v
capability-scoped, journaled execution
|
v
CheckResult -> Attestation -> EffectReceipt
|
v
exact verified Git transaction
Agents may author the work and its structure. They do not get to decide that their own work is safe, mint their own proof, or grant themselves more authority.
- Intent compiles. Execution is sealed. Admission resolves references, bindings, versions, loops, and grants into one immutable manifest. The walker executes only that manifest.
- Authority is physical. LLMs propose. Deterministic code validates, executes, reconciles, and disposes.
- Effects carry proof. Irreversible actions require a journal-minted attestation for the exact subject and sealed world.
- Crashes are normal. Completed invocations resume from checkpoints. Unknown external outcomes are reconciled before anything is repeated.
- Versions do not drift. Definitions are immutable, runs pin one
world_hash, and new versions affect future runs only through promotion. - Learning produces candidates, never mutations. A component cannot rewrite itself, promote itself, or define its own exam.
Journal-backed mailboxes carry typed requests, replies, and acknowledgements. A run can park while waiting for advice or approval, release its invocation resources, and wake from the durable reply after a process restart. Advice and approval have separate authority; a human decision does not replace evidence from deterministic checks.
panel() composes ordinary graph nodes with explicit membership and mapped
fan-in. The standard quorum aggregator evaluates typed member results under
an explicit policy. Human members use the same channel contracts; there is no
panel-specific scheduler. See channels and panels.
Claude Code, Codex, and Pi are the initial integration targets, not a closed
provider list. Future cloud APIs and local models can enter through compatible
task harnesses implementing the existing Executor / ExecutorProvider
contracts. Provider configuration, authentication, and native stream decoding
belong in the adapter; the graph language and walker do not grow provider
switches. An adapter is interchangeable only where it can enforce the admitted
capabilities.
Subscription reuse has bounded, revision-specific historical evidence for Codex and Claude Code, not general production availability. Pi's evidence is a pinned local model on a disposable hosted Linux runner, not a vendor account. Accepted ADR 0021 selects an operator-bound subscription route for the explicit v3 profile; gateway v1 under ADR 0018 is unchanged and unselected. The authentication record holds the evidence; nothing authorizes copying desktop credentials or silently substituting API billing. See adding an executor.
Constructicon currently targets Python 3.11 or newer and uses
uv for development. In Bash/Git Bash:
git clone https://github.com/sushiHex/constructicon.git
cd constructicon
uv sync --dev --python 3.11
PYTHONIOENCODING=utf-8 uv run verifyThe setup command selects standard CPython 3.11, matching the primary CI
interpreter, rather than an arbitrary installed interpreter variant. This
does not change the package's Python 3.11+ requirement. In PowerShell, use the
same setup commands, then $env:PYTHONIOENCODING = "utf-8" followed by
uv run verify.
verify runs the same credential-free gate as CI: Ruff, strict mypy,
import-linter, and pytest.
The separate Linux containment lane provisions its physical test boundary on GitHub Actions. Platform skips in a local run are not containment evidence.
To follow a proposed change through capture, trusted checks and recorded acceptance or refusal, run the existing credential-free maintenance rehearsal. It uses scripted native input and disposable Git state, not a model login or your working repository as a merge target.
For a runnable workflow that compares committed Python changes, parks for operator advice and completes after a process restart, follow the durable change-review example. It needs no model login and reports the existing metering fields without inventing usage or cost.
This example executes a deterministic Python task. It needs no model login, executor service, or protected Git repository.
Definitions must be importable after restart. Create demo_component.py in the
repository root:
from typing import Annotated
from pydantic import BaseModel
from constructicon.sdk import port_type, task
class Issue(BaseModel):
title: str
class Brief(BaseModel):
title: str
@task("demo/triage", output="brief")
async def triage(
issue: Annotated[Issue, port_type("demo/Issue")],
) -> Annotated[Brief, port_type("demo/Brief")]:
return Brief(title=issue.title)Then create demo.py:
import asyncio
from pathlib import Path
from constructicon.api.control import ControlPlane
from constructicon.api.system import Constructicon
from constructicon.core.control import (
ADMIN_SCOPE,
OPERATE_SCOPE,
READ_SCOPE,
AuthenticatedActor,
PromotionCommandResult,
RegistrationCommandResult,
RunResultPreviewV3,
RunSubmission,
)
from constructicon.core.run import RunStatus
from constructicon.sdk import flow
from constructicon.substrate.journal.sqlite import SqliteJournal
from demo_component import triage
async def main() -> None:
state_dir = Path(".constructicon")
state_dir.mkdir(exist_ok=True)
journal = SqliteJournal(state_dir / "demo.db")
system = Constructicon(journal=journal)
control = ControlPlane(system=system, store=journal)
launcher = AuthenticatedActor(
actor_id="static:demo-launcher",
auth_method="static",
scopes=frozenset({READ_SCOPE, OPERATE_SCOPE, ADMIN_SCOPE}),
)
await control.startup()
try:
registered = await control.registry_register(
launcher,
definition=triage,
idempotency_key="demo-register-triage-v1",
)
assert isinstance(registered, RegistrationCommandResult)
promoted = await control.registry_promote_initial(
launcher,
component=registered.component,
version=registered.version,
idempotency_key="demo-promote-triage-v1",
)
assert isinstance(promoted, PromotionCommandResult)
workflow = flow("demo/issue-to-brief", triage)
submitted = await control.runs_start(
launcher,
proposal=workflow.definition.body,
inputs={"issue": {"title": "Fix the flaky retry"}},
idempotency_key="demo-run-1",
)
assert isinstance(submitted, RunSubmission)
async with asyncio.timeout(30):
while True:
result = control.runs_result(launcher, submitted.run_id)
assert isinstance(result, RunResultPreviewV3)
if result.status not in (RunStatus.PENDING, RunStatus.RUNNING):
break
await asyncio.sleep(0.05)
assert result.status is RunStatus.SUCCEEDED, result.model_dump_json()
print(result.status.value, result.outputs)
finally:
await control.shutdown()
asyncio.run(main())Run it:
uv run python demo.pyExpected output:
succeeded {'brief': {'title': 'Fix the flaky retry'}}
Run the unchanged example again to replay the same command keys and read the same completed run. If you change a command's arguments, give that operation a new idempotency key; reusing a key with a different request is a refusal.
@task, flow, component, harness, loop, and panel are authoring sugar only.
They immediately lower to the same canonical Ref | Graph | Loop contracts
used by strict agent-authored JSON. There is no privileged SDK workflow model
and no trusted bypass around admission.
Install the optional MCP adapter and start a local stdio control plane:
uv sync --extra mcp --dev
uv run constructicon-mcp \
--database .constructicon/constructicon.dbThe MCP adapter is a thin transport over the same typed ControlPlane.
Mutating operations require caller idempotency keys, bounded responses use
revision-pinned pagination, and full immutable records remain available by
reference. Local registration and initial promotion are intentionally Python
launcher operations, not MCP tools.
The CLI does not provision executor or channel capabilities. Assemble those in a Python launcher; persisted definitions do not substitute for live capability bindings. The same MCP surface exposes human inboxes, replies, acknowledgements, and request-bound approvals under the actor's scopes.
For HTTP, Constructicon is authenticated or unavailable. Actor identity comes from a verified OAuth bearer token, never from a caller-controlled tool argument.
Constructicon 0.1.0 is a developer preview, not a hosted coding-agent service.
The execution and authority laws are governed by the
invariants and accepted ADRs.
Milestones M1 through M7.1 are complete, and M8 and M9 each closed a bounded
scope:
| Milestone | Capability |
|---|---|
| M1 | Sealed manifests, checkpoint resume, and idempotent effects |
| M2 | Persistent registry, crash hardening, cancellation, liveness, and projections |
| M3 | Protected Git authority, real gates, attestations, and exact verified merge |
| M4 | Generic bounded repair loops without a second scheduler |
| M5 | Agent-first JSON authoring, SDK sugar, introspection, and repairable admission |
| M6 | Durable authenticated command law, race-safe hosting, revision-pinned reads, MCP v2 adapter, and counterfactual replay |
| M7 | Durable channels, human advice and approval, restart-safe waiting, and deterministic panels |
| M7.1 | Explicit panel membership, ordered mapped fan-in, exact endpoint diagnostics, and strengthened counterfactual admission |
| M8 (bounded closure) | Executor policy and launch identity, networkless Linux containment, contained WRITE capture and gates, and Codex, Claude Code and Pi adapters with bounded evidence |
| M9 (bounded first phase) | A fixed self-improvement trial, run live once: catalog selection, scripted exam, owner approval, journal proof, promotion and rollback |
M8 closed under the bounded acceptance recorded in #42. It includes complete executor grant policy, content-bound launch identity, record-before-materialization leases, a networkless Linux launcher, owned READ/WRITE workspaces, and process cleanup that survives controller death. Failure of the trusted reaper itself is outside that recovery guarantee. The physical boundary is tested on GitHub Actions with hostile fixtures, not live model calls. Async WRITE capture runs staging Git inside that boundary, verifies an immutable pack, and atomically fences its exact candidate against acquisition closure.
Contained async gates use the same boundary to check the exact prepared merge snapshot. Runtime identification happens without a candidate mount; cancellation and descendant cleanup complete before authority is minted.
The Codex subscription adapter follows ADR 0021. Its implementation includes:
- a strict READ and WRITE operator adapter for the pinned client;
- operator-store custody with offline maintenance and activation;
- vendor egress through a host relay limited to the sealed vendor destinations, for one acquisition at a time;
- installation on a private Linux host from reviewed artifacts only;
- an authenticated-startup lane under the owner's
operator_authorizedoverage bound: the account's own settings bound spend, and Constructicon enforces no ceiling. It starts no turn while the account reports its spend control reached, and publishes the readback facts.
Credential-free CI exercises hostile fixtures. Separately authorized historical host sessions established bounded Codex READ and WRITE at distinct revisions and measured explicit refresh. Natural expiry-triggered refresh and actual live expired-login behavior remain unmeasured. See the accepted historical closeout.
The later q13 maintenance application was accepted, and its data-only parser vectors were recovered into an ordinary contribution in PR #250. The recovery record separates the historical exam from current-source regression evidence.
A second fixed maintenance task, the stored-reply extraction, had one
authorized live attempt (#397).
The application completed normally and accepted no candidate: the writer was
refused as capture-unchanged, because the attempt left the target at its
base. The window then withdrew its generation, parked the host and released
custody, with no retry
(outcome record).
The follow-up is open as #407,
the one open issue in the M8 milestone. Merged so far: instructions that name the
one write tool, where it runs and what is captured
(#408) and state the
guards that end an attempt
(#411); the retained
first request of a maintenance WRITE turn
(#409); retained
digests and lengths of an attempt's callback content and reply
(#410); and model-shaped
replies pinned to their refusals
(#412). None of these
shows that a model now writes; only a further authorized attempt can.
Claude Code is the independent second subscription adapter (#40). Its fixed pre-dispatch startup predicate, admitted READ composition and contained WRITE callback, capture and gate path were qualified, followed by one authorized live subscription READ and one live WRITE at recorded revisions.
Pi has a qualified bounded local READ profile: pinned Pi with a small local model on a disposable hosted Linux runner, one correlated READ with an unchanged workspace and joined teardown. That smoke does not establish live Pi through ControlPlane. The same workspace component runs unchanged through ControlPlane and RunHost under scripted Claude Code and Pi bindings; Codex's no-workspace profile is refused before dispatch. The composed contained WRITE proof installs the attested merge commit, reconciles an interrupted install without a second write, and keeps malformed READ output from checkpointing. See the bounded integration acceptance.
These results do not auto-enable a provider, supply general vendor conformance, or qualify another boot: fresh continuity and qualification remain required. The gateway route (#39) and OpenRouter (#47) remain unselected, and both are tracked outside the M8 milestone. See the implementation record for current evidence and the authentication assessment for the route decision and its historical investigation.
M9 learns through evaluated immutable candidates and explicit promotion, without letting the learner define its own exam (design, plan, #45).
The first phase is deliberately narrow. The installed
fixed selector trial
(python -m constructicon.api.m9_trial) asks a Codex READ to choose one entry
from a finite reviewed instruction catalog. A fixed scripted diagnostic exam
then evaluates the choice, the owner approves or rejects the exact candidate
edge through the durable approval channel, and the issuer mints journal proof
before any promotion. Promotion, its replay and rollback act only on that
exact edge. The trial survives operator process restarts, and a credential-free
rehearsal runs it with the shipped fake executor.
The bounded live trial completed end to end, closing #45: an owner-approved
Codex READ selected cite-evidence, the owner approved the exact candidate,
proof was issued, and promotion and rollback each ran with a replay before an
independent read confirmed the stable pointer back at the baseline
(live record).
This proves the lifecycle, not improved answers: the exam measures scripted
behavior, not prompt quality on real model answers, and free-form prompt bytes
remain deferred.
Constructicon is aimed at solo developers, teams, and researchers building agent-driven workflows over real repositories.
It is a good fit when you need:
- restart-safe, long-running software workflows
- exact provenance for code, checks, versions, and external effects
- an authority boundary independent of the model or agent provider
- reproducible and counterfactual runs against a recorded component world
- machine-shaped APIs with typed, repairable rejection
- durable human advice, approvals, and explicitly composed panels
- protected Git changes that are exact, attested, and idempotent
It is not a hosted coding-agent product, a prompt framework, or a general model router.
Almost every execution concept reduces to four nouns:
| Noun | Meaning |
|---|---|
| Definition | What may be reused |
| Manifest | What this run will execute |
| Invocation | Where one execution occurred |
| Receipt | What changed outside the run |
Everything else is a policy that transforms or admits these, a transport that carries them, a projection that renders them, or a capability leased to execute them.
L4 api ControlPlane, RunHost, MCP, system assembly
L3 sdk @task, component, flow, harness, loop, panel
L2 runtime registry, admission, manifest, walker, resume
L1 substrate journal, Git authority, workspaces, gates, executors, effects, channels
L0 core every contract in the system, defined once
Dependencies point toward contracts. The runtime never imports concrete substrate implementations, and the kernel is limited to the standard library plus Pydantic. CI enforces both rules.
- Work tracking: GitHub Issues, dependencies, ownership, and evidence-backed completion; plans and ADRs remain design authority
- Invariants: the laws every change must preserve
- Architecture: the complete current design and milestone acceptance tests
- Contributing: extension guides for agents and humans
- M8 implementation record: shipped foundations, remaining slices, and proof boundaries
- Executor authentication: accepted route decision and chronological feasibility evidence
- Linux CI evidence: runner qualification versus containment proof
- Historical planning archive: non-normative plans, recovered records, and implementation handoffs
- Self-improvement design: learning as candidates, never self-authorized mutation
- M9 selector trial guide: the installed fixed trial, its stages, and its live boundary
- Architecture decisions: why the system is shaped this way
Contributions are welcome, especially around real executor integrations, failure probes, channel transports, and examples.
Find ready work or propose an issue. Read how we track work before starting a substantive change so contributors and agent sessions share one queue.
Before adding a new concept, read the invariants, inspect
system.describe(), and look for an existing contract to compose. The full
repository gate is one command:
uv run verifyThe expected standard is simple: if a failure can happen between two durable facts, test the crash there.
MIT. See LICENSE.