# Architecture Modonome ships as an npm package: a master prompt, state templates, machine-checkable schemas, and enforcing scripts. The prompt defines the rules. The templates, schemas, and scripts make those rules executable and checkable. Modonome runs beside a host repository and works through the surfaces that repository already has: files, issues, pull requests, CI checks, CODEOWNERS, and status docs. Four questions shape everything else, so this document answers them first: - **What is the engine?** The engine is the running control loop, started when a harness loads the prompt. It is the prompt-defined loop operating on the host repo, together with the enforcing scripts that run in CI. Loading the prompt starts an engine; the package is its definition. - **When does the prompt run?** A harness loads the core prompt on each turn of a run. The adoption pass runs once per repository. The CI ratchet runs on every pull request. - **Where does it run?** Three places: a local Node CLI for read-only commands, a harness for the loop (agent scope), and CI for the enforcing scripts (enforcement scope). One package, three execution contexts, and no central service. - **How does it relate to the host repo?** Repo-wise, Modonome installs as a development dependency and copies its state into the host's `.modonome/` directory. At runtime, it reads the host's CI, CODEOWNERS, tests, and conventions, and writes back through pull requests and state files. ## Where Modonome runs ```mermaid flowchart TB classDef dist fill:#eef2ff,stroke:#6366f1,color:#1e1b4b; classDef agent fill:#0f172a,stroke:#0f172a,color:#f8fafc; classDef ci fill:#fef3c7,stroke:#d97706,color:#78350f; classDef host fill:#f1f5f9,stroke:#475569,color:#0f172a; subgraph DIST["Modonome on npm: prompt, templates, schemas, scripts"] direction LR P["Core prompt
plus on-demand modules"] T["State templates"] S["Enforcing scripts"] end subgraph LOCAL["Local CLI (Node 20 or newer)"] CLI["npx modonome
dry-run, scaffold, validate, report"] end subgraph AGENT["Harness loads the prompt (agent scope)"] LOOP["Engine loop
adopt, sweep, make, check, gate, merge"] end subgraph HOST["Host repo (any stack)"] SURF["Files, issues, pull requests,
CI config, CODEOWNERS"] STATE[".modonome/ durable state
config, queue, decisions, learnings"] end subgraph CISCOPE["CI (enforcement scope)"] RAT["Ratchet plus validators"] end P -->|loaded each turn| LOOP T -->|scaffold once| STATE S -->|run on every pull request| RAT CLI -->|reads and proposes| HOST LOOP <-->|reads and writes back| SURF LOOP <-->|keeps authority in| STATE LOOP -->|opens pull request| SURF RAT -->|blocks merge on regression| SURF class P,T,S dist class LOOP agent class RAT ci class SURF,STATE,CLI host ``` | Context | What runs there | When it runs | What it can touch | | --- | --- | --- | --- | | Local CLI (Node 20+) | `dry-run`, `scaffold`, `validate`, `report` | On demand, driven by a person | Reads the repo; writes only the `.modonome/` files you choose to scaffold | | Agent harness (agent scope) | The engine loop: adopt, sweep, make, check, gate | Each harness turn while a run is active | The host's ordinary surfaces: branches, pull requests, and `.modonome/` state | | CI (enforcement scope) | Ratchet, validators, drift and style guards | On every pull request and on push to the default branch | Read-only judgment. It blocks merges and writes no application code | ## Prerequisites Modonome degrades gracefully. The read-only CLI and the CI enforcement need only Node.js. A specific agent framework matters for one tier alone: running the loop autonomously. | What you want | What it needs | When the environment lacks it | | --- | --- | --- | | See proposed work, scaffold state, validate, report | Node.js 20 or newer | Always available once Node is present; nothing else is required | | CI enforcement: ratchet, validators, drift, style | Node.js 20 or newer in your CI | Run the same scripts locally as a pre-merge gate | | Run the loop manually, with a person as the harness | Node.js plus someone following the Quickstart | This is the default path, and it needs no agent framework | | Run the loop autonomously | A harness that loads the prompt (a coding-agent CLI, a CI job that invokes one, or an agent session) plus model access (a local model, an already-paid subscription, or a capped API key) | Stay in manual or dry-run mode; the read-only commands and CI enforcement keep every guarantee | The takeaway for a team without an agent framework: you still get dry-run proposals, scaffolded state, schema validation, governance reports, and the full CI ratchet. Autonomy is the single tier that adds an agentic harness and model access, and it stays off by default until an owner arms it. ## The pieces - The prompt (`prompts/`). A cacheable core (`modonome.core.md`) holds the invariants, the config levers, the operating modes, and the security rules. On-demand modules cover the adoption pass, the state machine, the roles, the gates, the control panel, and the network. `modonome.bundle.md` is the generated single-file version for harnesses that want one file. - The templates (`templates/.modonome/`). The seed state files a host copies once: config, status, decisions, learnings, network, control panel, and a version marker. - The schemas (`schemas/`). The machine-checkable contracts for config, work items, the adoption map, knowledge packets, and metrics. The config schema is the source of truth for the lever set. - The scripts (`scripts/`). The enforcing code: build the prompt bundle, scaffold state, run a dry-run sweep, run the anti-gaming ratchet, validate config and packets, migrate config, check house style, and guard against drift. ## The agent loop The core cycle runs inside the agent on each turn. The ratchet sits deliberately outside this scope: it runs in CI on every pull request from a trusted base-branch copy, so a run keeps it intact. ```mermaid flowchart LR classDef queue fill:#f1f5f9,stroke:#475569,color:#0f172a; classDef role fill:#eef2ff,stroke:#6366f1,color:#1e1b4b; classDef gate fill:#fef3c7,stroke:#d97706,color:#78350f; classDef sink fill:#dcfce7,stroke:#16a34a,color:#14532d; queue[["Durable work queue
.modonome/work-items/"]] packet["Work packet
claimed and leased"] maker["Maker
one packet, test-fenced"] checker["Checker
independent pass"] gates["Gates
all pass before merge"] owner["Owner review
CODEOWNERS"] merge["Merge authority
lands when every gate is green"] repo[("Host repo")] learn["Staged learnings
LEARNINGS.md"] queue -->|claim and lease| packet packet --> maker maker -->|diff and rationale| checker checker -->|rework below cap| maker checker -->|approved| gates gates -->|Tier 2 protected path| owner gates -->|Tier 1 eligible| merge owner -->|approved| merge merge -->|pull request| repo gates -->|evidence| learn learn -->|owner promotes| repo class queue,packet queue class maker,checker,owner role class gates gate class repo,learn sink ``` The ratchet (`guard-ratchet.mjs`) runs as a separate CI step, outside agent scope, and blocks merge if any quality threshold regresses. The integration diagram below shows where it sits. ## Integration points Modonome runs without a central service. It reads and writes through surfaces the host repo already has: files, CI, issues, and pull requests. The boundary between agent scope and CI scope is a security invariant: the ratchet and the style linter run in CI from a base-branch copy, where they stay outside the agent's write access. ```mermaid flowchart TB classDef host fill:#f1f5f9,stroke:#475569,color:#0f172a; classDef harness fill:#eef2ff,stroke:#6366f1,color:#1e1b4b; classDef agent fill:#0f172a,stroke:#0f172a,color:#f8fafc; classDef ci fill:#fef3c7,stroke:#d97706,color:#78350f; subgraph host ["Host repo (any stack or runtime)"] cip["CI pipeline
Actions, Jenkins, GitLab, and similar"] bp["Branch protection
plus CODEOWNERS"] sd[".modonome/
config, queue, decisions, learnings"] end subgraph harness ["Harness that loads the prompt"] h1["Coding agent"] h2["CI job"] h3["Human session"] end subgraph engine ["Modonome engine (agent scope)"] adopt["Adopt
read instructions, CI, CODEOWNERS"] sweep["Dry-run sweep
propose bounded work"] maker["Maker
one packet, test-fenced"] checker["Checker
independent pass"] gates["Gates
all pass before a pull request"] merge["Merge authority"] end ratchet["Anti-gaming ratchet
guard-ratchet.mjs
CI scope, outside agent write access"] harness -->|loads prompt| engine sd <-->|durable state| engine host -->|instructions, gates, CODEOWNERS| adopt adopt --> sweep sweep --> maker maker --> checker checker --> gates gates --> merge merge -->|opens pull request| host cip -->|runs on every pull request| ratchet ratchet -->|blocks merge on regression| bp bp -->|enforces protection rules| merge class cip,bp,sd host class h1,h2,h3 harness class adopt,sweep,maker,checker,gates,merge agent class ratchet ci ``` The engine is stack-independent. It normalizes work by intent, evidence, and interface contract rather than by language or framework. The `docs/enterprise.md` adoption table lists ten estate types: product app repos, monorepos, microservice estates, mainframe, SAP, Oracle, Salesforce, ServiceNow, low-code or RPA, and data or BI. ## Where Modonome fits in your pipeline Modonome is an additive layer for a mature DevSecOps setup. It opens ordinary pull requests that flow through every gate you already run, and it adds one new required check, the ratchet. Existing tooling keeps its job. ```mermaid flowchart LR classDef mod fill:#0f172a,stroke:#0f172a,color:#f8fafc; classDef pipe fill:#f1f5f9,stroke:#475569,color:#0f172a; classDef gate fill:#fef3c7,stroke:#d97706,color:#78350f; subgraph MOD["Modonome (additive layer)"] eng["Engine loop
bounded Tier 1 and Tier 2 work"] rat["Anti-gaming ratchet
one new required check"] end subgraph PIPE["Your existing DevSecOps pipeline (unchanged)"] pr["Pull request"] scan["SAST, DAST, secret scan"] dep["Dependency and license scan"] own["CODEOWNERS review"] bp["Branch protection"] rel["Release and deploy"] end eng -->|opens a normal pull request| pr pr --> scan --> dep --> own --> bp --> rel rat -->|runs beside your other checks| bp class eng,rat mod class pr,scan,dep,own,rel pipe class bp gate ``` How it complements an established practice: - It defers to what you have. The adoption pass reads and respects host CI, CODEOWNERS, and branch rules, then works within them. - Pull requests run through your current SAST, DAST, dependency and secret scanning, and human review unchanged. The ratchet is one more required check beside them. - It preserves separation of duties. Maker, checker, and merge authority stay distinct, and high-risk paths (security, auth, dependencies, CI, secrets) route to a human by tier. - It fits existing secrets governance. Arming is an environment or CI secret, enforced at runtime, so a file the engine can write stays unable to arm it. - It feeds audit and compliance. Decisions, learnings, and metrics live in tracked files that your existing audit and review processes already read. ## Adoption (a one-time pass) Adoption is a one-time initialization pass that runs before the ongoing loop begins. Once the adoption map exists and `state` moves past `adopting`, this pass is skipped. ```mermaid stateDiagram-v2 [*] --> pre_adoption : repo has no .modonome/ pre_adoption --> adopting : scaffold run adopting --> dry_run : adoption map written dry_run --> armed : owner sets autonomy_enabled true armed --> governed : first cycle completes governed --> governed : steady-state cycles governed --> suspended : owner disables suspended --> governed : owner re-enables ``` ## Learning and self-improvement pipeline The engine has a defined self-improvement loop that tightens quality over time while keeping the owner in control of every promotion. ```mermaid flowchart LR classDef step fill:#eef2ff,stroke:#6366f1,color:#1e1b4b; classDef floor fill:#dcfce7,stroke:#16a34a,color:#14532d; signal["Correction signal
gate failure, review fix, rework"] capture["Follower captures
one generalized, evidence-backed lesson"] stage["Stage in LEARNINGS.md
fingerprinted, dated, capped at 20"] promote["Owner promotes
into canonical rules, config, or tests"] gate["Add a deterministic gate
when one fits"] signal --> capture --> stage --> promote --> gate gate -->|raises the floor| signal class signal,capture,stage,promote step class gate floor ``` Market and standards scans are planned for a dedicated market-researcher role (roadmap, not shipped). When implemented and enabled, sourced findings would flow to the steward role, which scores and routes proposals, and would default off. Net-new claims would need owner approval before any roadmap change. The proposal priority score (`safety + user_value + repo_fit + reuse + evidence - effort - blast_radius - uncertainty`) surfaces the highest-value, lowest-risk improvements first. ## Trust boundaries and security invariants Two boundaries hold structurally, backed by code and review rather than convention: **CI boundary.** The anti-gaming ratchet (`guard-ratchet.mjs`) and the house-style linter (`check-style.mjs`) execute from the trusted base-branch copy on every pull request, set up in `.github/workflows/ci.yml`. A pull request can edit those files, yet CI runs the base-branch version, so the gate that judges a change stays beyond the reach of that change. The drift guard (`check-drift.mjs`) runs the pull request's own scripts, because config levers are defined partly in script defaults; CODEOWNERS review protects it from a weakening edit. Regressions block merge automatically. The cross-repo knowledge network is roadmap, not shipped (see ADRs 014 through 019). Only the packet format and its validator (`validate-knowledge-packet.mjs`) exist today. When the network's import path lands, it is designed to join this same base-branch trust class: a scheduled job in `.github/workflows/modonome-network.yml` would run `poll-network.mjs`, `verify-packet.mjs`, and `validate-knowledge-packet.mjs` from the base branch only, never from a PR head (see `docs/adr/ADR-019-knowledge-network-execution-scope.md`). Those scripts and that workflow are not present in this repository yet. **CODEOWNERS boundary.** Any file in `bin/`, `scripts/`, `schemas/`, `templates/`, `prompts/`, or `.github/` requires a human CODEOWNER approval before merge. The `touches_protected_path: true` field in a work-item JSON is the signal; the agent reads it before claiming the item and escalates to an owner instead of merging on its own. ## Why this factoring - **One source of truth.** The config schema defines the levers. The prompt and templates follow it. `check-drift.mjs` fails the build if they disagree, so the four representations stay in agreement. - **Code over prose for anything load-bearing.** The ratchet, validators, and drift guard run in CI, outside the agent, so the guarantees hold even under prompt injection. - **Small context per turn.** A harness loads the core plus only the module it needs. The bundle stays available for portability. ## Calibration The design favors verified adoption over publication count, independent validation over self-reported scores, local repo gates over central claims, and lineage records over hidden memory. These choices come from practical experience with autonomous coding loops and from research on self-evolving agent systems, which repeatedly shows that unvalidated, volume-driven sharing degrades quality. Modonome keeps every concrete change behind a local gate.