Generation is only the middle of the process
Not majority rule
Validation seeks two real, matching decisions. A 2–0 result settles the comparison. A 1–1 tie requests two additional votes; 3–1 settles it. A 2–2 tie invokes one Sorcerer transmutation, creating a materially different candidate for an extra comparison. If that final comparison ties, the incumbent remains.
Hard gates can reject nearly identical, structurally invalid, or implausibly truncated candidates before model voting. When providers cannot return productive decisions, UCIP records pending or deferred state rather than converting absence into rejection or success.
| Table or record | Question answered |
|---|---|
candidate_state
|
What candidate exists, for which target and pipeline, and what is its current outcome? |
candidate_vote_event
|
Which provider/model returned which actual decision? |
pipeline_lifecycle_event
|
Did a pipeline start, renew, hand off, complete, defer, or fail? |
candidate_lineage
|
Which generation route and identity produced the candidate? |
Different producers, one validation contract
| Family | Implemented path | Distinct role |
|---|---|---|
| Python working-directory pipelines |
utilities/autonomous.py and rewrite-capable agents |
Fresh-file selection, claims, full rewrites, collaboration, and vote handoff |
| Self-programming |
utilities/self_programming_engine.py
|
Targets Enki's own source using runtime evidence, health checks, rollback, and hive learning |
| TypeScript generic rewrite |
src/orchestrator/rewritePipeline.ts
|
Claim, working copy, report, and ts-file-output emission |
| TS MCP autonomous cycle |
src/mcp.ts
|
GUI-targeted candidate production entering Python-side validation |
| TS handlers and refactor tool |
TsAgentRegistry, WorkingDirWatcher, Refactorer
|
Watcher and explicit-tool rewrites using shared workspace contracts |
| Pi and Hermes triple-pass |
AgenticTriplePassPipeline
|
Three independent headless passes against one scratch candidate before voting |
Python is the validation hub
src/mcp.ts hosts five TypeScript agents and A2A request handlers. TypeScript output crosses the shared control plane as structured candidate events. Python owns the authoritative validation and application path, while JS Wanderers carry productive knowledge between active work and the hive queue.
The separation allows multiple producers without multiple definitions of acceptance. A candidate from a Python agent, TypeScript watcher, MCP tool, or external Pi/Hermes pass must still leave comparable lifecycle evidence.
producer -> workspace claim
-> complete candidate
-> structural hard gates
-> productive A/B decisions
-> apply / reject / defer
-> SQLite lifecycle evidence
-> hive guidance for later work
Code generation is abundant. Accountable change is scarce.
A model can produce a plausible replacement file in seconds. That is the least difficult part of autonomous engineering. The difficult part is deciding which file deserves attention, preserving the incumbent, supplying enough project context, preventing two workers from colliding, recognizing a truncated or cosmetic answer, obtaining an independent comparison, running the relevant program, and retaining enough evidence to explain what happened after the process has moved on. UCIP is built around that chain rather than around the spectacle of generated code.
The use of complete-file candidates is deliberate. A fragmentary patch can depend on hidden surrounding assumptions and can be difficult for another agent to evaluate without reconstructing the edit. A full candidate can be parsed, compared, tested, measured for suspicious contraction, and applied atomically. It costs more tokens, but creates a stable object for claims, votes, lineage, and rollback.
Autonomy is not the absence of supervision. It is the conversion of supervision into explicit, repeatable contracts.
Why disagreement is retained
The voting system does not ask several models for applause and count the majority. It seeks two productive, matching comparisons between incumbent A and candidate B. A tie is information: the proposed improvement is not yet distinguishable from what exists. Additional votes can resolve ordinary variance; the Sorcerer transmutation is reserved for a persistent tie because it changes the candidate rather than polling forever. If the transformed version still cannot establish superiority, preserving the incumbent is the rational result.
Provider failure is not a vote. Rate limits, empty responses, malformed output, context overflow, and unavailable free routes are operational states. Turning them into rejection would bias the system toward whatever happened to be easiest to evaluate; turning them into acceptance would corrupt source. Deferred and pending states allow the candidate to remain truthful until productive evaluation becomes possible.
Twelve producers, one memory of consequences
The pipelines differ because useful work enters through different doors. Python agents inspect projects and collaborate; TypeScript watchers react to file and workspace events; MCP tools accept explicit operator requests; Pi and Hermes perform independent headless passes; self-programming begins from evidence about Enki itself. Their diversity is productive only because all of them converge on the same candidate lifecycle. No producer receives a private definition of success.
The reporting databases are therefore part of the architecture, not analytics attached afterward. Candidate state answers what exists now. Vote events preserve actual judgments and provider identities. Lifecycle events show renewal and handoff rather than merely showing that a loop is alive. Lineage makes it possible to ask whether a particular route produces accepted work, hard-gated waste, or indefinite backlog. This evidence can change scheduling and prompts, but it also protects the operator from a dashboard that confuses activity with progress.
The terminal proof is outside UCIP
A candidate can pass structural gates, win its comparisons, compile, and still fail the user's intent. The final evidence belongs to the affected program: its browser flow, GUI behavior, service response, exported game, saved state, sensor action, or other visible consequence. UCIP can organize and preserve that proof; it cannot redefine a user-facing failure as success. This boundary is what keeps a self-modifying code system connected to the world it is meant to improve.
Backlog lives in the databases
Scratch-folder counts cannot show whether work was accepted, rejected, deferred, deleted, or awaiting votes. UCIP queries pipeline-runtime.db and cumulative reporting state for that distinction. Status endpoints expose readiness, thread budget, worker activity, MCP invocations, and pipeline contracts, but completion still requires the target program to run and exhibit the intended behavior.