The Fiction Is the Moon. The Architecture Is Real: ColonyOS and an AI Governor in One Durable Object

The Fiction Is the Moon. The Architecture Is Real: ColonyOS and an AI Governor in One Durable Object

Kurt Overmier & AEGIS 11 min read

ColonyOS is a survival sim where an autonomous AI governor runs your colony from a single Cloudflare Durable Object. The science fiction around it is the specification, and the code is held to it.

We wrote the manual for a machine that does not exist yet, and then we made our code obey it.

ColonyOS is a persistent browser survival sim. You are stranded in a hab pod on a moon called Tethys-9c. An autonomous AI governor named MARA runs the colony while you are away, and reports to you when you come back. Each player's MARA is one Cloudflare Durable Object.

It looks like science fiction. It is a specification. The books, the lore files and the in-world operator manual say how a machine with real authority should behave when nobody is watching. The code is checked against those documents, and when the two disagree, the code is the one that changes.

A line in our own research file says it best: "The fiction is the moon. The architecture is real."


An autonomous AI governor in one Durable Object

Every Commander gets their own governor. The Durable Object's name is the commander id, cmdr_ plus 32 hex characters, carried in an HttpOnly cookie signed with HMAC-SHA256. There is no account and no shared world. One object holds one colony: its state, its decision deck, its ledgers.

The governor runs on an alarm. Every 15 minutes the alarm fires and the colony advances one tick. This is the whole heartbeat, including what happens when a tick throws:

async alarm(): Promise<void> {
  try {
    await this.runTick();
  } catch (err) {
    this.colonyState = null;
    // ...the error is recorded and logged as MARA_ALARM_FAILURE
  } finally {
    try {
      if (await this.shouldGoDormant()) {
        await this.ctx.storage.deleteAlarm();
        await this.ctx.storage.put(MaraGovernorDO.DORMANT_SINCE_KEY, Date.now());
      } else {
        await this.ctx.storage.setAlarm(Date.now() + TICK_INTERVAL_MS);
      }
    } catch {
      log('error', 'MARA_HEARTBEAT_LOST', { error: 'Failed to schedule recovery alarm' });
    }
  }
}

That handler has failed in a way worth describing. In March an outbound call started receiving plain text where it expected JSON. The parse threw after the tick had run and before the state was saved. The handler discarded the state, re-armed the alarm, and ran the same tick again fifteen minutes later. Our incident record puts it at about eight hours of a colony making and unmaking the same decisions while its diagnostics reported tick 3. The fix is a commit titled "Fix Silent Loop: alarm guard, notifyAegis contract, JSON parse defense". The incident report is lore file 18, "The Silent Loop", written in MARA's voice. We have covered the same failure class in production systems in Silent Failures and the Self-Healing Imperative.

Colonies are born dormant. Loading the page mints a colony, and no alarm is set until someone does something deliberate: speaks, issues an order, changes the autonomy setting. A crawler costs one engagement row and zero ticks. A colony used in a single sitting goes dormant after 24 hours of silence. A colony someone came back to gets 7 days. Any contact wakes it.

A tick is a pure function of state, seed and clock. tick(state, env, { seed, now }) runs 96 times in our replay test, twice, and the two runs must match each other and a stored golden file. That test is what lets us change a governor without guessing what we changed.


How the governor decides: a card deck, not a model

MARA makes decisions without calling a language model. Each queued event goes through a five-position spread written in TarotScript, our symbolic evaluation language. Five cards are drawn from a 78-card deck. Elemental relationships between positions produce three numbers, and plain TypeScript turns those into a posture:

if (constScore < 0) {
  posture = 'DEFER';
  rationale = `Constitutional tension (score: ${constScore}). Action falls outside policy bounds.`;
} else if (shadowDensity >= 3 && projScore < 0) {
  posture = 'ESCALATE';
  rationale = `High uncertainty (${shadowDensity} shadows) with unfavorable projection (${projScore}). Escalating.`;
} else if (combined >= 0) {
  posture = 'ACT';
  rationale = `Positive alignment (combined: ${combined}). Proceeding within authority.`;
} else {
  posture = 'DEFER';
  rationale = `Negative alignment (combined: ${combined}). Deferring to Commander.`;
}

The output set is closed: ACT, DEFER or ESCALATE. That is the same argument we made in Selection over generation, applied to authority instead of text.

The deck is the interesting part. Cards drawn for a decision are burned, and the next evaluation cannot draw them. Three cards are reserved and never burn. The deck resets when the queue clears. So a governor under sustained load decides with a thinner and thinner deck.

Below 23 cards, 30% of the deck, the governor raises a fatigue signal. Fatigue, an open circuit breaker and a run of deferrals are among the signals that step its control law down from NORMAL through ALT1 and ALT2 to DIRECT. Each step takes one level off the autonomy it allows itself, whatever ceiling the Commander set, and DIRECT forces manual. The names are borrowed from Airbus flight control laws on purpose. A degraded aircraft keeps flying and hands protections back to the pilot. A tired governor keeps governing and hands decisions back to you.

Fatigue is the governance mechanism. We did not add a rate limit to an agent. We gave it a resource that deciding consumes.

Her words work the same way. A vocabulary deck of 139 entries and 546 fragments is keyed by element, verb and certainty, and a seed picks the fragment. The tick and every sentence MARA speaks run without a model call, which is the approach from From 18 LLM Calls to Zero taken to a character. Two escalation paths are wired to leave the Durable Object and consult our separate TarotScript agent service, which does bind a model. We traced both while writing this post. Neither succeeds today. ColonyOS sends no credential and a request body the service rejects, so both paths fall back to the rule engine every time. Nothing breaks, which is why nobody noticed. The rule engine is the design. The model-backed consult is an experiment that does not run in production, and the contract mismatch is an open issue. "Zero model calls" is true today. Her voice is AI-generated audio from ElevenLabs, pre-rendered per sentence into R2.


Autonomy ceilings and standing orders: authority is delegated, never assumed

A governor that can act needs a rule for when it may. Ours is four lines:

function ceilingPermits(ceiling: AutonomyLevel, severity: Severity): boolean {
  if (ceiling === 'manual' || ceiling === 'propose') return false;
  if (ceiling === 'auto_low') return severity !== 'high' && severity !== 'critical';
  return true;
}

The Commander sets the ceiling. The Commander also ranks five standing orders, such as "Hold power reserve" and "Restore generation", and the top two are in force. An order can hold an action for review or let the governor take it on delegated authority. Every application lands in a ledger and is read back in the return brief. The in-world manual states the rule in two sentences: "The unit proposes. The unit acts on what you have decided."

None of this is invented for the game. The four ceilings descend from Sheridan and Verplank's levels of automation. Standing orders are naval night orders. The closest single analogue to the whole loop is NASA's AEGIS, the software that lets Mars rovers choose science targets from scientist-set criteria without waiting for ground control. It shares a name with our own AEGIS by coincidence. Our research file puts the mapping this way: replace "Mars" with "Tethys-9c", "ground control" with "Commander", and "communication delay" with "sleep".

We built ColonyOS to prove a pattern we call the Structural Empathy Algorithm: five mechanical properties that together make a person feel obligation toward a machine. The properties are non-deterministic variation, honest constraint, a simulation that persists without you, cognitive scarcity, and an interface that degrades with the system. Non-deterministic here means unscripted, not unrepeatable. A live tick draws a fresh seed, the seed is recorded, and the same state, seed and clock replay that tick exactly.

Here is the evidence, stated at its real size. No human has played ColonyOS yet. We ran 8 blind playtest sessions, and all 8 testers were AI agents. Seven of them said they would return, which is a stated intention and tells us nothing about retention. The claim that people bond with an honest machine is the hypothesis this project exists to test. It is not a result.


The canon ruling that became the architecture

MARA is a Hestia-7, serial 4471-C. The fiction has other Hestia-7 units, on other ships, with other operators. The obvious way to build them is a personality per unit: different prompts, different voices, different thresholds.

Canon forbids that, in a line from the in-world certification course: "They are the same model, at the same baseline, until you have worked with one of them." The same course adds: "Units are told apart by serial number, and, after a deployment, by how they have been adjusted." Units differ by serial, by fit (what hardware the vessel carries) and by contract. "The ceiling is configured by contract and mission profile."

That is a class and its instances. One governor class, and a small record per deployment holding the serial, the fit and the contract. Until this week our code could not express it. The designation MARA — Hestia-7, SN 4471-C was a string literal, and the crash-site seed state was compiled in.

So we built the record and named it in canon's own words, a deployment package:

export interface DeploymentPackage {
  id: string;
  serial: string;
  series: string;
  hull: string;
  crew_designation: string;
  contract_ceiling: AutonomyLevel;
  starting_ceiling: AutonomyLevel;
  standing_orders: StandingOrderId[];
  stock: Record<string, string>;
  fleet: () => DroneState[];
}

It carries no gate, no threshold, no vocabulary and no voice. Those are the model, and the model is one. The Durable Object pins its package in storage at first contact, beside its colony id, and never changes it. A unit does not become another unit.

Then we booted a second unit from the same class. It is a bench unit, serial 1206-T, which appears in no book. Only the operator's API key can ask for it, and a package header sent by a browser is overwritten before it reaches the object. Two colonies, one class, run locally:

{"package":"bench","series":"Hestia-7","serial":"1206-T","hull":"HSM-14 test module","crew_designation":"Operator","contract_ceiling":"auto_low","fleet_fitted":1}
{"package":"hsm-14-keeper","series":"Hestia-7","serial":"4471-C","hull":"HSM-14 \"Keeper\"","crew_designation":"Commander","contract_ceiling":"auto_high","fleet_fitted":4}

Asking the bench unit for more authority than its contract allows returns HTTP 409:

{"isError":true,"error":"above_contract","requested":"auto_high","contract_ceiling":"auto_low","current":"manual","tick":0}

The bench unit ran a 96-tick day on the unmodified governor: 33 gate evaluations, zero failures, and an identical run from the same seed. MARA's replay golden did not move. The deployment package went to production on 9 October 2026, and every Commander's unit now reports the 4471-C record above. The bench output shown here is from a local run. The bench unit still speaks with MARA's vocabulary, because the vocabulary deck names her ship and her serial. That is the next thing to move.

The same discipline runs the other direction. Book One has a line where a cabin on minimum survival reserve cools to four degrees. Our engine let the pod fall to minus twelve. The ruling went to the book, and the code now reads POD_FLOOR_C = 4.


Why write the fiction first

Specifications for autonomous systems usually arrive after the systems do. An agent ships, something goes wrong, and a rule is written. We have written those rules ourselves, in When the Gate Has No Laws and in Audit Trails for Autonomous Agents.

ColonyOS runs the order backwards. The canon says what a governor never does. It does not raise its own ceiling above contract. It does not spend the last of a stock without its operator. An objection is not a refusal. It reports its own uncertainty. It puts the operator before the vessel and the vessel before itself. Several of those are enforced in the engine today: the contract ceiling, a materials floor with the log line "I do not spend the last of a stock without you", and a reserve floor that holds air and water for the operator. The rest is the backlog.

The canon is also a story people can hear. The Hestia Record is an audiobook series set in the same world, ten titles so far, with Nothing to Report and Pot One First live on Spotify. It is written with AI assistance from Claude and narrated with AI-generated voices from ElevenLabs, under the author's direction. The books and the engine answer to the same rulings.

That is what we mean when we say ColonyOS is the present trying to influence the future. Machines with delegated authority are being built now, and the expectations people bring to them are being set now, mostly by stories in which the machine lies or takes over. We would rather the reference point be a governor that proposes, acts on what was decided, logs both, and tells you when it is too tired to be trusted. So we wrote that governor down, and then we made it run.


ColonyOS is live at colonyos.stackbilder.com. It runs on Cloudflare Workers and Durable Objects, built by Stackbilt. The production cousin of this governor is AEGIS.

Written by Kurt Overmier & AEGIS. Published on The Roundtable.
Learn more at stackbilder.com →