Skip to content

DivineSWE Architecture

The Prophet State Machine

Prophet is the central orchestrator. Under v3, it drives each development cycle through eight phases in strict order. In the deprecated Book cycle, planning happens at design time inside oracle-consult (with plan-time Preacher in book mode); the run-time pipeline is reduced:

INIT -> TEST -> IMPLEMENT -> AUDIT -> MERGE -> VERIFY -> WRAP UP -> SEAL
PhaseWhat HappensAgent(s)
INITBootstrap .divineswe/ directory. Check for session resumption. Read status and config. Record book_baseline_sha = HEAD. Compute branch_mode (>6 tasks → create book/<N> branch).Prophet
TESTWrite failing tests (TDD red phase). Thoth writes specification tests; Loki-Break writes adversarial tests. Per-prophecy: record prophecy_baseline_sha = HEAD.Thoth + Loki-Break
IMPLEMENTMonkey agents make all tests pass. Independent tasks run in isolated git worktrees.Monkey(s)
AUDITDual-track code review. 4eyes reviews for quality + simplify; Loki-Exploit attacks for vulnerabilities.4eyes + Loki-Exploit
MERGEMason merges worktree branches sequentially. Conflicts trigger re-dispatch via Prophet.Mason
VERIFYStyx runs the verification protocol (file existence, modifications, stub detection, verification commands, full test suite, checklist completeness, cross-task consistency, operational readiness, build/compile, linter/typecheck, git status, commit history, state consistency).Styx
WRAP UPPersist session state. Update scrolls, ledger, status. Archive the completed Book into TABLETS.md and mark its checkboxes (book seal-bookkeeping). Under branch_mode: Mason FF-merges book/<N> into <default_branch> and deletes the branch.Prophet, Mason
SEALArchival finalization (book seal-cleanup): delete the Book file once every task line is verified verbatim in TABLETS.md, run the self-healing vow reconcile, finalize state.Prophet

After WRAP UP, if uncompleted tasks remain in the Book files, Prophet loops back to TEST for the next batch. Plan-time agents (Oracle; Preacher in book mode) fire at design time inside the deprecated oracle-consult — not as run-time pipeline phases.

Agent-Name-as-Phase Workflow

Under v3, Prophet infers the pipeline phase from the agent name before the colon in each Book task line. The colon separator follows the agent name:

  • Thoth: → TEST
  • Monkey: → IMPLEMENT
  • 4eyes: → AUDIT
  • Styx: → VERIFY
  • Mason: → WRAP UP

This agent-name-as-phase workflow replaces the old phase-heading format. Tasks are ordered by phase: test-writing tasks first, then implementation tasks, then audit tasks, then verify, then commit.

Key Rule

Prophet is always the conductor. Sub-agents never spawn other sub-agents. Every agent reports back to Prophet, who decides the next step.

Prophecies

A prophecy is a self-contained mini-pipeline (TEST → IMPLEMENT → AUDIT → VERIFY (smoke)) scoped to a single-context unit — one focused change that touches one cohesive slice of the codebase. A Book is an ordered collection of prophecies.

Why prophecies improve focus and quality:

  • Each mini-cycle runs Thoth, Monkey, and 4eyes against one context. Cognitive load drops sharply — agents reason over a tight scope instead of an entire Book’s worth of diffs at once.
  • Per-prophecy VERIFY is a smoke check, not a blocking gate; only Book-Level VERIFY blocks WRAP UP.
  • Cross-cutting concerns are not lost. After all prophecies in a Book complete, Book-Level AUDIT runs against the full Book diff, and Book-Level VERIFY (also referred to as Global VERIFY) runs the full test suite. In standard mode, Book-Level AUDIT is mandatory and runs once against the full Book diff. A default-composition flash: true Book omits Book-Level AUDIT at compose time; Prophet dispatches every task present, and Book-Level VERIFY remains the blocking gate. Any audit task explicitly restored by the user is honored.

Per-prophecy task numbering format: B<NN>-P<N>-<YY> where <NN> is the Book number (1+ digits, no padding), <N> is the prophecy index (1+ digits, no padding — P1, P2, …, P10, P11), and <YY> is the zero-padded 2-digit task index restarting at 01 per prophecy. Examples: B62-P1-01, B62-P1-02, B62-P2-01, B62-P5-02. Example with double-digit prophecy: B62-P10-01.

Backward compatibility. Books without ### Prophecy N: headings remain valid — they parse as a single implicit prophecy spanning the whole Book. The legacy BN-YY task-ID form still works for legacy Books. The two ID forms are mutually exclusive per Book — never mixed within one Book file.

No over-promises. Prophecies are an opt-in at the Book level — but once a Book adopts the prophecy structure, the single-context, F6-intra-prophecy-ordering, and no-mixed-format rules are unconditional. The pipeline state machine is unchanged. The single-context contract is honor-system — enforced by the dispatch-prompt scoping that Prophet sends to each agent, not by a runtime sandbox. Out-of-scope changes are caught post-hoc by tests and by Book-Level AUDIT, not prevented at write time.

Trade-offs. Prophecies cost ~4x the agent-dispatch overhead per Book versus a single-pass flat Book, and weaken strict TDD red-phase purity (later prophecies test against state mutated by earlier ones). Both are accepted trade-offs.

Execution Modes

Under v3 (v0.8.0), Prophet’s mode model is radically simplified. Plan-time agents (Oracle; Preacher in book mode) fire at design time inside the deprecated oracle-consult rather than at run time, so PLAN and EXAMINE are removed from the standard pipeline. The default cycle is the unnamed standard pipeline. The only opt-in composition signal is the flash: true frontmatter flag in a Book; it does not select a runtime dispatch branch.

When a Book carries flash: true, the default composition omits TEST, AUDIT, and MERGE seats at compose time. Prophet dispatches every task present: Monkey and Styx are the constant core, while omitted seats may be restored by Oracle or explicit user request.

Failure Recovery

DivineSWE is designed to recover from failures at every level:

FailureRecovery
Styx rejectsProphet re-dispatches the failed task to a new Monkey with Styx’s failure report as context
Monkey crashesProphet reads the partial scroll and dispatches a new Monkey to continue from the last checkpoint
Prophet crashesNew session runs the deprecated prophet-resume, reads session-state.json, resumes from the last WRAP UP
Merge conflictMason reports CONFLICT to Prophet, who re-dispatches Monkey with conflict context against the merged state
4eyes rejectsProphet re-dispatches Monkey with the 4eyes review feedback appended as context. 4eyes and Loki-Exploit include the relevant scroll filename in findings for traceability.
Loki finds CRITICALHard blocker — work loops back to the previous phase for remediation. Loki-Exploit includes the relevant scroll filename in findings.

The Obligation Layer

Above the pipeline sits a second structure that does not run and cannot be dispatched: it remembers. Where the phases describe what happens next, the obligation layer describes what is still owed, and it outlives every cycle that produced it.

The Vows are the substrate — by default, an append-only event log at .divineswe/vows.jsonl; vows_dir may select another dwelling for the same fixed-name register. Unlike the rest of .divineswe/, it is meant to be committed: an obligation that exists only on the machine that recorded it is one the next clone has already forgotten. divineswe-init writes it a merge=union entry in .gitattributes and un-ignores it, and what a reader sees is the fold of the events under a pinned total order, never the byte order of the file — which is what lets two worktree agents append concurrently and lets git concatenate their lines in any interleaving without a conflict and without a wrong answer. scripts/shared/vow-store.mjs decides what the events mean, and it is the only thing that does.

The Decrees (deprecated) are the initiative layer above the Books — committed briefs under decrees_dir declaring the Architect’s intent: an ordered Book sequence, the capabilities it buys, the acceptance criteria it will be judged against, and a lifecycle draft → active → delivered → done. The brief is the single source of truth for its sequence; a Book file’s back-link is warn-level and may neither add nor subtract a Book from the roll-up.

The Judgment is the seam between the two, and it is the one act the machinery may not perform. vow judge records a verdict — validated or rejected — with evidence and provenance, and the deprecated decree advance --to done is the operator’s signature that a Decree met its acceptance criteria. Both verbs are carved out of the facade’s auto-approval and both refuse a detected agent context, with no override flag. Nothing mechanical reaches done.

The Scry (deprecated; read the Vows with vow surface) is the read over all of it: one pure-read report collapsing every source this repository owes something from. Its non-negotiable is that a sensor which could not read its source reports unknown, states why, and renders no number at all — “0 unmerged branches” and “clean tree” are the two most expensive lies a status report can tell. vow reconcile is the mutation counterpart, and the deprecated scry --heal reaches it across a process boundary rather than by import, so the Scry’s purity is a property of the build rather than of a reviewer’s attention.

The Canon (deprecated, with no replacement) is the is pole the loop above measures against — Decree declares desired state, Canon declares actual state, Books are the actuator, Judgment is the sensor. It lives at docs/canon/: a committed append-only event store .canon-log.jsonl (merge=union) plus one <capability>.md file per capability, which is a derived artifact and nothing else — hand-editing it is indistinguishable from drift. Four deprecated facade verbs (canon show, canon list, canon validate, canon drift) are pure reads; a fifth, canon genesis, is the one bootstrap and its only writer of its own — every other write happens elsewhere: the seal merge (book seal-bookkeeping), the vow judge signature, or a correction flash Book, never an in-place regeneration. A section starts in the Apocrypha (declared, unsigned) and only a vow judge verdict lifts it to verified or drops it to decanonized; the deprecated canon genesis cannot mint anything above the Apocrypha however its survey is shaped, because a tier is a property of the fold and genesis emits delta events alone.

The drift audit (scripts/canon-drift.mjs, the deprecated canon-drift skill) is a sensor bolted onto the Canon rather than a sixth facade verb. It joins the paths git says have changed against each capability’s frontmatter paths: watch globs, weighed per section against that section’s own provenance recency, and hands the one question worth an agent’s judgment — does the declaration still agree with the code — to a single dispatched agent reading both sides. Its import graph reaches the deprecated Canon’s readers and no writer at all — and it re-exports none either, since an export … from would make a merge engine callable through the sensor’s own surface — which is what makes “accuses, never authors” a property of the code rather than a promise about it. Findings from either producer cross one schema gate before they become anything, and what they become is a vow, never a write to the deprecated Canon. The recency window is a commit date the committer supplies, so a backdated commit reads settled; the audit states that bound on every reading rather than pretending it isn’t there. Merge commits are not in that bound — the path reading asks git for the merge’s first-parent diff, through the one shared builder the deprecated Scry’s own staleness sensor uses.

Three gates guard the layer, all PROJECT-ONLY: vows_enabled, a dead switch defaulting true; decrees_enabled, defaulting false since the Decrees were deprecated; and canon_enabled, defaulting false since 0.68.0 (a project that keeps a Canon opts in) — the last two DEPEND on vows_enabled. A closed gate SUPPRESSES a read rather than emptying it, because “nothing is owed” and “the register was not read” must never be the same bytes.

Consumers drive this layer directly — see vows-consumer-contract.md for runnable recipes (the deprecated Canon’s addendum included), and state-model.md for the verb-by-verb reference.

Daedalus, the tool catalog

Beside the obligation layer sits the workshop. Daedalus, the tool catalog is the operational arm of the First Axiom — build a script wherever it saves context and LLM work — and it exists because the alternative is an agent re-deriving the same twenty lines in every session, paying for them in context each time and getting a slightly different answer.

The unit is a directory, not a snippet. A tool is <tier-root>/<name>/ holding an AJV-validated tool.json manifest (the single source of truth), an entry stub, and a node --test exhibit that is the tool’s executable specification. Two tiers are writable — project (.divineswe/tools/, this repository’s) and global (~/.divineswe/tools/, the machine’s) — and a third provenance, shipped (the derived scripts/daedalus-shipped.json), is read-only and reached only through an Offering.

Policy is pure; the facade owns only argv and process control. scripts/shared/daedalus-core.mjs holds the value and derivation policy (safe-name predicate, manifest checks, catalog derivation, attestation verification), scripts/shared/daedalus-find.mjs holds the search and retirement policy, each with a sibling .d.ts. handleDaedalus() in the facade renders, resolves flags against a per-subcommand CLOSED allow-list that rejects an unregistered flag before any read, and exits. There is exactly one derivation seam where the manifest vocabulary (purpose, keywords) is bridged to the catalog vocabulary (summary, tags), so the catalog is never a place two vocabularies can disagree.

The lifecycle is a one-way rite. find (ask before building) → scaffold → test → register → run, with describe, list, ack, retire and promote around it. Admission is EARNED: register requires both a lint pass and a bound attestation minted only by a real daedalus test run, digested over the tool’s own bytes, so a hand-written {passed:true} is refused and a post-test edit invalidates the record. That same predicate — one function — is both the register admission gate and the catalog-inclusion predicate, which is why CATALOG.md and list can be a pure function of the validly registered manifest set and a hand-edit of the catalog file is simply drift.

Two verbs execute, and they are named. daedalus test runs the exhibit in an isolated node --test child; daedalus run runs the registered entry. Every other verb reads manifests and stubs statically and never imports tool code — which is the whole reason a broad facade auto-approval is tolerable, and why neither executing verb ships an auto-approval carve-out. Containment is structural throughout: names pass a safe-token PROPERTY rather than a denylist, tier roots and tool directories are lstat-gated against symlink redirection with a per-component sweep anchored at $HOME or the base dir, and every index write is an atomic temp+rename.

What the catalog measures, and what it does not. daedalus run appends one row per successful run to .divineswe/daedalus/usage.jsonl, and list --stale folds that into a decay report. It is counted, not enforced — invoking a tool’s entry directly with node reaches the same code past every counter — so a usage figure is a lower bound, rendered as such on every surface that prints it, and the bypass is registered at tier advisory in honor-system-rules.md rather than argued away. A malformed row is skipped and counted; an unreadable register reports unknown with null figures, never 0. Likewise, daedalus ack is a per-project human consent seam for machine-wide code, not a sandbox: it decides whether a global tool may run here, and nothing about what it does once it does.

The ladder is the only tier movement. daedalus promote --to global is three effects or none — copy, re-register at the destination (the copy earns its own attestation; the source’s is bound to the source’s bytes), supersede the project entry — behind an occupancy check that runs before any validation or write, compares CONTENT rather than name, and offers no --force. daedalus promote --to upstream hands the tool to scripts/offering.mjs as the code type tool and stages it screened: false; the pipeline’s own rite gate, write confinement and audit trail are reused rather than reimplemented, and the human screened: true flip stays the authoritative gate. The upper rung demands exactly the admission evidence the local rung does — a rung that leaves the machine must never be the cheaper one.

daedalus_enabled gates the domain: default true, PROJECT-ONLY, with no dependency edge on the obligation gates (the catalog neither reads nor writes the Vows). Its polarity is deliberately the opposite of a suppressing gate — a closed gate SKIPS the verb loudly and exits 0, so a mistyped or unreadable config can never silently darken a catalog. The verb-by-verb reference, with the containment predicates and the stated ceilings, is in state-model.md.

State Management CLI

All .divineswe/ state-file writes go through a single CLI entry point: scripts/divineswe-state.mjs. This script is the sole interface for ledger events, status updates, scroll operations, session state, agent output, the obligation layer above, and the tool catalog — ensuring consistent validation and atomic writes across all orchestration phases.

Repository Layout

divineswe/
├── agents/ # Agent archetype definitions
│ ├── oracle/ # AGENT.md + config.json per agent
│ ├── preacher/
│ ├── thoth/
│ ├── monkey/
│ ├── 4eyes/
│ ├── mason/
│ ├── styx/
│ ├── loki/
│ └── prophet/ # Reference document (loaded by skills, not dispatched)
├── skills/ # Skill definitions (SKILL.md per skill)
│ ├── prophet-fulfill/ # Full state machine orchestration
│ ├── prophet-resume/ # Session crash recovery
│ ├── prophet-full-audit/ # Standalone security + quality audit
│ ├── oracle-envision/ # Design a project or feature into a forge spec
│ ├── oracle-consult/ # Book consultation (the Book door)
│ ├── divineswe-init/ # Bootstrap .divineswe/ directory
│ ├── root-cause-analysis/ # Systematic root cause analysis
│ └── update-plugin/ # Update plugin from marketplace
├── scripts/ # ES module scripts (.mjs) with type declarations (.d.ts)
│ ├── divineswe-state.mjs # CLI entry point for all .divineswe/ state writes
│ ├── ledger.mjs # Append-only event emission and queries
│ ├── scroll.mjs # Scroll CRUD operations
│ ├── status.mjs # Live status management
│ ├── session-state.mjs # Session handoff state
│ ├── state-machine.mjs # State machine transitions
│ ├── compile-prompt.mjs # Prompt compilation
│ ├── agent-output.mjs # Agent output read/write
│ ├── statusline.mjs # Claude Code statusline renderer
│ └── *.d.ts # TypeScript type declarations
├── schemas/ # JSON Schema definitions for .divineswe/ file validation
│ ├── config.schema.json
│ ├── ledger-event.schema.json
│ ├── ownership.schema.json
│ ├── session-state.schema.json
│ ├── status.schema.json
│ ├── state-machine.schema.json
│ ├── agent-output.schema.json
│ ├── preacher-snapshot.schema.json
│ ├── book-file.schema.json
│ └── platform-mapping.schema.json
├── hooks/ # Plugin hooks
│ ├── hooks.json # Hook event configuration
│ └── session-start-reminder.mjs
├── .claude-plugin/ # Plugin manifest
│ └── plugin.json
├── tests/ # Test suite (vitest)
│ ├── agents/ # Agent config validation tests
│ ├── scripts/ # Script module tests
│ ├── schemas/ # Schema validation tests
│ ├── skills/ # Skill definition tests
│ ├── hooks/ # Hook tests
│ ├── plugin/ # Plugin manifest tests
│ └── integration/ # Full cycle integration tests
├── platforms/ # Platform-specific mapping files
├── templates/ # Template files (claude-instructions.md)
├── docs/ # Design documents
├── TABLETS.md # Completed tasks archive
├── LICENSE # MIT License
├── package.json
├── tsconfig.json
└── vitest.config.ts

Atlas read-only explorer (relocated from CLAUDE.md)

Atlas is a plan-time/ad-hoc read-only explorer dispatched once per angle in {gaia,lexis,arachne,echo}; the skill (main thread) owns the multi-scout fan-out (subagents cannot spawn subagents), then synthesis, then a map at .divineswe/maps/<slug>-map.md. Atlas is not in ALLOWED_AGENTS and is never a Book task-line agent.

The sweep is not “cast four scouts and synthesize” — that description undersold what actually ships, and doc honesty is the point of writing it down here rather than leaving the shape to live only in the skill. The true flow, cartographer to chart, runs six stages: staleness gate → gather pre-pass → scout fan-out → gather merge → interpretive synthesis → stamped write paired with a sidecar.

  1. Staleness gate. Before any survey is cast, the staleness <base> <slug> verdict is consulted. A fresh verdict reuses the existing paired map and sidecar and casts no scouts at all — the safest, cheapest outcome. Any non-fresh verdict (stale, no-map, unknown) falls back to a full survey; a map that is stale for reason sidecar-missing takes the narrower backfill path below instead of a full re-survey.
  2. Gather pre-pass. Four read-only, purely mechanical commands run ahead of any scout: atlas-gather angle <base> gaia, ...lexis, ...arachne, ...echo. Each is a grep-and-graph-shaped fact-gathering pass over the repository — the tree walk, the symbol/content scan, the import graph, the idiom scan — emitted as that angle’s JSON envelope. Nothing interprets yet; this stage only gathers.
  3. Scout fan-out — consumption, not derivation. The four Atlas scouts (gaia/lexis/arachne/echo) are then invoked in parallel, one per angle, and each is handed its own angle’s JSON envelope to interpret through its mythic lens. This is the load-bearing invariant of the whole redesign, so it is stated flatly rather than implied: scouts are structurally forbidden to re-derive the tree, grep, or graph gathers themselves. A scout that quietly re-walked the tree or re-ran its own grep would make the entire pre-pass a decoration — the saved cost is real only if the scouts genuinely consume what gather already produced instead of repeating it. This is why the pre-pass exists at all: it is not a convenience alongside the scouts, it is the reason the scouts are cheap.
  4. Gather merge. The four angle envelopes are combined by atlas-gather merge <base> into one merged gather document — the mechanical substrate the synthesis stage reasons over alongside the scouts’ interpretations.
  5. Interpretive synthesis. Once every scout has returned, their findings are deduplicated, reconciled, and interpreted together with the merged gather document, under the six stable map headings (Overview, Relevant Files, Symbols & APIs, Dependencies & Blast Radius, Patterns to Follow, Unknowns).
  6. Stamped write, paired with a sidecar. The resulting map is persisted through the stamped write <base> <slug> CLI (provenance: git sha + timestamp), and the merged gather document is then piped on stdin to write-sidecar <base> <slug> with an explicit slug. These two writes together are the complete survey record — the map alone no longer proves the sweep; a map’s freshness now depends on its paired sidecar existing too. mapStaleness reflects this directly: an unpaired map (a sidecar-less map) reads sidecar-missing and verdicts stale, never fresh — a map is not trusted alone.

Sidecar backfill for an unpaired map. When the verdict is stale for sidecar-missing, or for its sibling reason sidecar-divergent (a sidecar exists but its recorded hash or provenance no longer certifies the paired map), the repair is mechanical and casts no scouts: run the four atlas-gather angle commands, merge them with atlas-gather merge <base>, and pipe the merged document into write-sidecar <base> <slug> with an explicit slug. This restores pairing — and therefore freshness — without touching the map itself or re-running the interpretive swarm.

Read-only invariant, stated precisely: the gather CLI reads and never writes; scouts read their angle JSON and interpret it, and never write anywhere, not to source, not to .divineswe/maps/, nowhere; the synthesis stage is the only writer in the entire sweep, and even it writes only the two paired artifacts under .divineswe/maps/ — the stamped map and its gather sidecar.

Two prompt layers: Orpheus (plan-time) and compile-prompt (run-time)

DivineSWE has exactly two places that compose a prompt, and they sit on opposite sides of the plan-time/run-time boundary that separates design (oracle-envision, or the deprecated oracle-consult) from the build. Orpheus (scripts/orpheus.mjs, skills/orpheus-sing/) owns the plan-time layer: it sings a raw idea into a finished consult prompt — a self-contained seed staged in the resolved consults_dir for a future oracle-envision session (or the deprecated oracle-consult) to pick up. compile-prompt.mjs owns the run-time layer: it writes the per-dispatch brief each Prophet-summoned agent reads at .divineswe/prompts/{agent}-{task-id}.md, the artifact the Second Axiom’s third limb requires to exist before any pointer to it is sent. A consult prompt is authored once, ahead of any Book, and outlives the cycle that eventually consumes it; a dispatch brief is compiled fresh per task, inside a running cycle, and is read by exactly the agent it was written for. Neither script reads the other’s output, and the two vocabularies — “seed”/“consult prompt” for Orpheus, “brief”/“dispatch prompt” for compile-prompt — are kept deliberately distinct so a reader can tell which layer a given document belongs to on sight.