ouroboros/docs/architecture/01-high-level-architecture.md
Anton Razzhigaev 98ca8a13d5 Retire completed campaign artifacts and keep repository reports explicit
Remove completed campaign records, one-time adoption/transplant machinery and
incidental line floors. Keep current contracts and generated inventories with
their readers, and direct optional domain reports to stdout or an explicit file.
Document continuing-purpose review in the existing handbook and checklists.

No version bump; ordinary release gates and runtime behavior are preserved.

Co-authored-by: Ouroboros <311266734+ouroboros-agent@users.noreply.github.com>
2026-09-18 01:07:51 +03:00

190 KiB
Raw Blame History

1. High-Level Architecture

This chapter is the structural index of the running system: the module tree from the desktop launcher down through the supervisor to every core package, the gateway and CLI boundaries, the two-role process topology of launcher and server, the platform substrate their locks and fingerprints rest on, and the on-disk data layout. It exists so a reader can find the owner of any behaviour by name before reading its code, and so a renamed module or a moved durable file surfaces as a documentation change instead of silent drift.

User
  │
  ▼
launcher.py (PyWebView)       ← desktop window; immutable release-reviewed outer shell running the packaged copy outside managed hot-swap
  │
  │  spawns subprocess
  ▼
server.py (Starlette+uvicorn) ← HTTP + WebSocket on configurable host:port (default localhost:8765; Docker/non-loopback via OUROBOROS_SERVER_HOST=0.0.0.0); its lifespan APPLIES the boot provider normalization in-process and persists no provider decision — the route is re-derived by every consumer (the task-start projection, the settings GET and onboarding reads, the context-fit route resolver). Startup is a read, with one exception that lives inside the read seam: the lifespan's `load_settings()` runs `context_mode_compat.normalize_and_persist_context_mode_compat`, which rewrites the `OUROBOROS_CONTEXT_MODE`/`OUROBOROS_CONTEXT_MODE_AUTO_LOW` compat pair left by the RETIRED persistent auto-Low mechanism — and only that pair — when it actually changed and the settings lock is held. What retired is that mechanism, not the keys: `OUROBOROS_CONTEXT_MODE` is the live owner-selected context horizon in §7's settings table, and `OUROBOROS_CONTEXT_MODE_AUTO_LOW` survives only as its provenance tombstone
  │
  ├── web/                     ← Web UI (SPA with ES modules in web/modules/; §3)
  │   ├── ui.css + modules/ui_primitives.js ← One shared palette/control stylesheet for the SPA, onboarding and optional author pages; self-contained safe fields, collection, escaping and tone/status functions, re-exported by existing helpers
  │   ├── modules/page_header.js, ui_interactions.js, scroll_fade.js ← Header/tab markup and selected-state keyboard binder; dialog focus, menu behavior and independent popup geometry; scroll-edge decoration tied to actual overflow, all with owned teardown
  │   ├── modules/chat_decision.js, question_presentation.js, chat_render_batch.js, task_phase_chip.js, lifecycle_card.js ← Chat helpers: the typed decision (quiz) cards and the Main question pointer shown to the owner, with one pure lifecycle/action/preview projection shared by both (its Python twin: `project_dialogue.QUESTION_STATUS`); keyed timeline items, DOM patches, history-control presentation and reading anchors; pure desired-phase chip projection where terminal truth wins; skill lifecycle card state with best-effort polling
  │   ├── modules/chat_history.js, chat_history_replay.js ← Chat-instance page navigation with bounded payload retention and exact return handles; source-keyed historical narration merging and selection/focus protection without live-task authority
  │   ├── modules/project_work_pointer.js ← Project-only navigation to the existing loaded root cards; pure target/label selection plus one button/coverage binding, with no execution or history authority
  │   ├── modules/model_wait.js ← Model-wait views inside existing chat cards: revision/attempt-aware snapshots and owner actions through the shared decision ingress; the host retains wait and execution ownership
  │   ├── modules/dashboard.js, logs.js, costs.js, files.js ← Dashboard tab-strip host with static guard markers; Logs page (backfill plus live-stream duplicate guard); Costs page (breakdown buckets — an open zero is never shown as free); Files page (file browser over `/api/files/*`, downloads through the host bridge)
  │   ├── modules/skills.js, marketplace.js, skill_review_card.js, skill_publish_flow.js ← Installed skills UI (review, grant, enable, repair, update, uninstall, delete); ClawHub marketplace inside the Skills page; Skill Review chat cards; typed detail rows for the publish dialog
  │   ├── modules/settings_ui.js, settings_catalog.js, settings_controls.js, settings_local_model.js, mcp_settings.js ← Settings page in reading order (Accounts → Secrets → Models → Agents); model-catalog refresh with a 25-second bound and a sequence guard; effort-segment and form-control binders; the local-model form; MCP settings cards that keep masked tokens until edited
  │   ├── modules/model_roles.js, model_chooser.js ← Shared Models editor for Settings and onboarding: per-role source, model, account and context drafts, plus ordered fallback rows; the editable chooser is shared with actor/reviewer route editors, and catalog arrival enriches suggestions without assigning a value or replacing the input
  │   ├── modules/subagents_settings.js, subagent_status_primitives.js, reviewer_slots.js, route_editor_primitives.js, harness_accounts.js, harness_login_cards.js, claudexor_status_store.js ← Agents surfaces: the Available subagents editor shared by Settings and first-run onboarding; pure status/meta projection of one subagent card (its live session verdict is reused by Review lanes); Review lanes rows; neutral route-editor primitives shared by both editors; Agent accounts; host-neutral agent login cards (controller + view); the ONE client-side store over `GET /api/claudexor/status` (`facetReadState`)
  │   ├── modules/onboarding_agents_step.js, onboarding_overlay.js, project_create.js, utils.js ← the first-run "Connect your accounts" step; the framed wizard's sandbox policy kept in one place because it is a security boundary; the New Project dialog and project row actions; shared frontend utilities (escaping, formatting)
  │   ├── modules/review_presentation.js, review_dom_patch.js, harness_presentation.js ← Review Checkpoint grouping/status, keyed DOM reconciliation, neutral harness identity presentation; read-side only; `executorIdentityMarkup` renders projected card identity/model facts at that existing presentation owner
  │   └── modules/widgets.js + widget_module.js + widget_frame.js + widget_card.js + widget_reorder.js + widget_chart.js + widget_list.js + masonry.js ← Widgets page host (`mountTab` dispatcher, card registry, declarative renderer) + the two framed mounts (extension-route iframe; module `srcdoc` iframe with its CSP/sandbox constants, parent fetch/resize bridge and disposer) + the child-side bootstrap served into the module frame (bridge grammar, `Response` rebuilt over a stream, resize reports, dispose acknowledgement) + the framed card chrome (launch policy incl. `retain`, Start/Stop, policy menu, facade) + key-order reorder handles + declarative chart/table helpers + pure list helpers (per-card and order-independent change signatures, keyed patch plan) + the key-ordered masonry that writes only `--masonry-*` custom properties
  │
  ├── supervisor/              ← Background thread inside server.py
  │   ├── active_activity.py   ← Process-local owner of in-flight native chat actors, including preparation and post-task delivery (`DirectActivityRegistry`); private actor handles support controls and writer drain, public snapshots feed `/api/state` `active_direct_turns` and WS typing frames (`activity_id`, `client_message_id`, `phase`, `kind`); no queue records
  │   ├── message_bus.py       ← Queue-based local message bus (Web UI + reviewed transport skills)
  │   ├── workers.py           ← Multiprocessing worker pool (forkserver on Linux, spawn on macOS/Windows; never fork from the multi-threaded supervisor)
  │   ├── worker_assignment.py, worker_chat_lane.py, worker_health.py, worker_pool_lifecycle.py, worker_process.py, worker_promotion.py ← The pool's leaves: handing a pending task to a free worker and refusing the ones that must not run; the direct chat lane and its resume after a restart (conversation stays admitted while the authorized assisted resolver holds the repository, and the owner-control path is preloaded before conflict markers land); health-owned crash detection and terminal-file recovery through the reaper queue; lifecycle-owned execution admission and pool population (readiness, exhausted-slot disablement, pid records, reaping, respawn) and `kill_worker_tree`, the ONE worker tree-kill every teardown and backstop uses — the installation's daemon roots spared always, kept services only on one task's cancel or timeout; what runs INSIDE a worker child process from entry to crash record; and turning a chat turn — or a project scope — into a queued task, refusing typed — the workspace family with its cause and repair in `detail` (single durable writer `_persist_promote_rejection`) and announcing a Project start only once the task is really queued
  │   ├── worker_owner_wait.py ← Queue-owned active-capacity transfer for required owner waiting: the original task stays RUNNING and its process stays custodied, while another worker receives the active slot; correlated grant consumes the checkpoint before another model round
  │   ├── state.py             ← Persistent state (state/state.json) with file locking
  │   ├── queue.py             ← Task queue (PENDING/RUNNING lists) + activity-based timeout enforcement; the ONE task-state authority — the lifecycle/publication/transition modules below extend it without becoming second authorities; exact-attempt main-LLM in-flight state spares only the idle rail
  │   ├── queue_schedules.py, queue_snapshot.py, queue_timeouts.py ← Queue leaves re-exported through `supervisor.queue`: recurring schedules (the durable file, the skill sync, what they enqueue); the durable queue snapshot a restart finds and what it may restore; and activity-based liveness — which running task has stopped being alive
  │   ├── cognitive_operations.py ← Typed in-memory LLM/review/VLM operation leases for the idle rail; no scheduler or durable timing ledger
  │   ├── task_model_wait.py   ← Live model-wait event projection and forwarding, with task-attempt/owner checks and quota-clock reads for queue liveness
  │   ├── task_admission.py    ← Token-owned admission reservations fence duplicate user-ingress ids before Project/workspace/attachment side effects; schedule-dispatch refusals project through the same boundary; queue.py stays the state authority
  │   ├── task_lifecycle.py    ← Cancellation custody — the ONE settle owner of durable cancel intents: claim → capture → confirmed death → natural-completion re-check → owed delivery registration → settle → delivery/cleanup, plus the `sweep_cancel_intents` watchdog and the queue-owned root-budget admission fence; every custody rule it enforces is stated once in §10 (cancellation custody)
  │   ├── cancel_publication.py ← Cancellation settlement publication, re-imported by `task_lifecycle.py`: typed CANCEL_* outcome vocabulary, artifact-honest cancelled result fields, physical-ledger cost reconstruction, salvage adapter, owed-before-settle outbox registration, publication of the STORED terminal truth, capture-miss terminalization/delivery adapter
  │   ├── queue_transitions.py ← Queue-owned lifecycle transitions that are not cancellation custody: acceptance-fence open/inspect/seal, explicit budget resume, typed `stop_evolution_tasks` (per-task typed outcomes through the durable-intent ingress, never an in-place prune; an incomplete stop leaves the campaign OPEN via the durable `evolution_owner_stopped` flag, the settle-time backstop in events.py closes it when the last live evolution task settles, and the OWNER start ingresses — `/evolve start`, an owner-sourced toggle event — clear the flag BEFORE minting a fresh campaign, while the agent's `toggle_evolution` against the set flag is refused: the owner's stop is sticky, В12), and fenced Project deletion (cascade only lineage ROOTS — descendants fall with their trees, one cascade and one summary per tree; tombstone only after provable quiescence; a settled-but-LIVE root still mints the coordination intent, and wind-down defers and RE-CHECKS bounded instead of re-running the cancel pass over a settled-lingering set, which would deliver duplicate owner summaries); imports nothing from task_lifecycle; `supervisor.queue` re-exports these names
  │   ├── terminal_delivery.py ← Durable terminal-answer delivery seam: restart-surviving `delivery_id` dedupe + bounded PENDING outbox `state/terminal_deliveries.json` (owed before enqueue, cleared in the delivering write, replayed on boot and on the supervisor tick), shared by natural final answers (every root registers at durable-result persistence), cancel salvage, cascade digest, and non-retry reap; the cascade digest enumerates descendants by ANCESTRY (parent-chain walk, never `root_task_id` equality); eviction past outbox capacity is disclosed via typed `terminal_delivery_exhausted`, never a silent pop; salvage messages carry a bounded preview plus a full-copy receipt (path, size, full 64-hex sha256 or an explicit marker) and route by lineage chat — no resolvable chat records a typed `terminal_delivery_handoff` row; reads/mutations are row-strict per §10; the delivery id digests only the STABLE part (task id + status framing + core answer) so a replay whose rebuilt note shrank dedups instead of double-sending; the per-origin projection is `host_salvage` receipt / `host_notice` own text kept as a System row with its markdown / `custody_notice` the custody audit as its own typed card row (`terminal_custody_notice`, an unreconciled-runs note rides it and never the assistant text) / `model_final` assistant projection
  │   ├── task_reaper.py       ← Single-owner off-loop queue/pump for timeout teardown and health-prepared terminal-file/crash jobs, with same-job deferred replay bound to the captured worker/attempt/root, so old file recovery cannot replace a newer execution; keeps supervisor intake responsive. An unconfirmed death holds the slot reaping and the task RUNNING with task_reaper_wedged; confirmed death precedes delegated-custody reconciliation and retry. No cancel intents minted (§5 Supervisor Loop).
  │   ├── owner_stop.py        ← Owner graceful stop: `finalize_then_cancel` policy as an axis on the SAME durable cancel intent (monotonic — immediate HARDENS a pending graceful, never softens back; hardening revokes an unread control via mailbox revocation, and the loop revalidates durable policy at drain); one deterministic typed `finalize_now` control whose first line is the `owner_requested_finalization` literal, routed by the loop to its own rail (zero or one tool-less turn); descendants settle first with a bounded child projection fed to the root's final turn; the grace budget starts at the durable control DRAIN (first drain wins), bounded by `request + OWNER_STOP_OUTER_CAP_SEC`, and neither anchor is ever progress-extended; `running_owner_stop_tasks` bypasses only the generic idle/finalization-grace rails; a COMPLETED finalize root suppresses the redundant cascade summary
  │   ├── schedule_time.py     ← Cron/timezone schedule time parsing helpers
  │   ├── evolution_lifecycle.py ← Evolution campaign state + transaction lifecycle: campaign file IO, start/pause, begin/update transaction, cycle-outcome recording, deterministic worktree cleanup, owner cycle reports, idle dispatch over queue-owned state, supervisor auto-restart request
  │   ├── events.py            ← Worker→supervisor event dispatcher with exact attempt/execution/round/call correlation for the process-local active main-LLM row; composes the frozen subagent task text (`_compose_subagent_text`; the acting `[WRITE SURFACE]` block states only the write-root authority boundary — actor identity comes from the immutable configured snapshot, startup/wake facts from bootstrap); an event type absent from `EVENT_HANDLERS` is DROPPED into a truncated `unknown_worker_event` row, and `tests/test_worker_event_registry.py` pins the registry by AST scan — an unexplained allowlist entry is exactly the silent blessing the scan exists to end; the scan is shape-bounded, and outside its reach the discipline is code review; holds shrink-only byte debt above the module byte ceiling
  │   ├── subagent_task_truth.py ← Delegation-truth enrichment of the subagent `task_done` transport frame (`enrich_task_done_event`)
  │   ├── event_taxonomy.py, events_budget.py, events_chat_delivery.py, events_coop_checkpoint.py, events_evolution_done.py, events_project_routing.py, events_runtime_controls.py, events_schedule_task.py, events_subagent_admission.py, events_task_done.py, events_worker_reports.py ← The handler leaves `events.py` merges into `EVENT_HANDLERS`, one owner per family: the declared disposition of every event kind the runtime puts on `EVENT_Q` (`event_taxonomy.py`, the registry the AST scan reads); usage-accounting and budget-pause reports; owner-facing chat delivery (text, media, typing; a terminal answer's host notice and custody notice become their own System rows after the answer, the custody row a typed `card_row` of the task's card); cooperative repository checkpoints when a task tree goes quiescent; terminal handling of an evolution task and its campaign; where a chat turn becomes a task and where a project scope is bound (one publication boundary around every promote outcome: a host-issued act that is refused gets its one typed System row there, a tool-issued one only its receipt); posture changes that are not one task's state; the `schedule_subagent` admission gates (chat target, depth, worker pool, active-child cap) and their refusals, with deliberately no semantic duplicate gate — exact task-id fencing, caps and cost ceilings are the floor and the parent decides what to spawn; admission facts for a requested subagent (census, caps, constraint); resolution of a terminal event into durable truth and delivery; and what a running worker reports about itself
  │   ├── task_dispatch.py     ← Pure admitted-event→worker-payload construction, including the identical top-level/metadata depth and configured-route projections consumed by workers
  │   ├── log_addressing.py    ← Explicit audience for task-scoped live log events: `address_task_event` (lineage from the RUNNING row, project binding wins, explicit chat_id preserved — 0 is `HIDDEN_CHAT_ID`, the hidden partition of the Skill Review panel and headless runs without a registered project; A2A frames are suppressed at the `push_log` choke, not by dishonest addressing), `make_server_log_sink`, `address_handler_push`
  │   ├── steering.py          ← Steering-message delivery to running tasks, keyed on the event's host-minted `issuer` fact: an OWNER turn writes owner text (generation bump, room veto from the registry lane, owner acknowledgement/notice), a TASK speaking for itself writes a `task_message` row with `independent_task` provenance to any host-listed active independent root (no veto, no chat, one `task_message_routed` Logs row naming author and target); mailbox routing to the drive the worker drains, plus a typed refusal while a cancel intent is pending (steering is fenced during a stop — what makes the owner-stop single-turn rail safe)
  │   ├── plan_obligation.py   ← The Swarm planning obligation follows the work (owner 3=A): when a root whose `force_plan` is still unmet promotes, the admission seam stamps the new root and this releases the promoter's flag on its live queue row inside the same transaction, so one snapshot persist shows both facts; the transfer receipt rides the admission record and the promoter's task details
  │   ├── direct_roots.py      ← The off-lock `state/direct_roots.json` fragment of live direct-chat roots the main loop writes beside the queue snapshot (actor locks only tried, one aggregate `incomplete` fact, cleared at queue init) so a worker can list them without the server's registry
  │   ├── telemetry_events.py  ← Durable handlers for RARE typed telemetry-only worker events (merged into `EVENT_HANDLERS` like `_CEH`): a type-agnostic passthrough appends each row verbatim to events.jsonl, beside the `task_message_injected` sibling shaping the A2A row; membership is bounded by contract — every dispatch is a durable append, so high-rate narration never joins this registry
  │   ├── git_ops.py           ← Git operations (clone, checkout, rescue, rollback, push, credential helper) and the shared bounded local-Git process runner
  │   ├── git_ops_remotes.py, git_ops_rescue.py, git_ops_reset.py, git_ops_updates.py ← Git-operation leaves re-exported through `git_ops.py`: personal persistence remote (`origin`) configuration and push; the rescue/snapshot machinery destructive tree movement takes first; checkout/reset admission, dependency sync and safe restart; and managed-update status, official tags and update preparation
  │   ├── update_source.py     ← Official update-source selection + network policy through the bounded Git runner
  │   ├── update_recovery.py   ← Exact owner Restore/promotion: pinned prior HEAD, rescue-before-reset, one captured SHA for local/remote promotion
  │   ├── update_merge.py      ← Managed-update engine: exact-target 3-way plan, direct clean fast-forward, stash-first reviewed assisted merge (both lanes stash dirty work before the authoritative replan; VERSION + carrier tokens projected before the M0 pin), transaction (`m0_tree`, `tests_evidence`, `stash_sha`/`local_work_carrier`, `failed_update_ref`), verified rollback/smoke, phase-dispatched boot recovery (the marker-cleanup phase only retries the tx-marker unlink when the repository already holds its final state); disclosed residual: M0 is a pin-once forensic baseline in the resolver-writable tx marker — review discloses it and does not re-verify
  │   ├── update_candidate.py  ← Candidate/carrier primitives (re-exported by update_merge.py): private-index tree serialization, rerere-neutral merges (prevent silent rr-cache resolution replay), failed-update preservation branches and marker-guarded stash restore; publishes forensic tests_evidence from the runner's process-held proof, never durable-file reuse authority (§6 Git and commit review)
  │   ├── update_carriers.py, update_merge_plan.py ← Carrier-aware managed-update conflict resolution (the version/contract carriers a merge may not resolve by hand), and merge planning with live materialization
  │   └── update_merge_policy.py ← Presentation-only doc/code/hot conflict labels; every conflict uses the same reviewed assisted path
  │
  └── ouroboros/               ← Agent core (runs inside worker processes)
      ├── config.py            ← SSOT: paths, settings defaults, load/save, PID lock (§7)
      ├── settings_defaults.py, settings_scales.py, model_slots.py, review_model_routes.py, runtime_limits.py ← The settings vocabularies `config.py` re-exports, one owner each: the key set with its shipped defaults plus `RETIRED_SETTING_KEYS`/`RETIRED_COMMA_LIST_SETTING_KEYS` (`settings_defaults.py`); the closed scales and setting-effect vocabulary (`IMMEDIATE_SETTINGS` / `RESTART_REQUIRED_SETTINGS`); model-slot resolution and the frozen `ResolvedModelTarget`; the reviewer model lists the API-pinned review surfaces run; and the numeric runtime knobs with their clamps. `ouroboros.config` stays the one import surface — a new key and default belong to the leaf, never to the facade
      ├── version.py           ← Version string from the VERSION file with importlib.metadata fallback
      ├── secret_masking.py    ← Exact Settings/MCP wire-placeholder emitters/recognizers + top-level secret repair before env overlay and persistence
      ├── settings_integrity.py ← Task-local in-memory ordinary-settings read view and strict settings-snapshot integrity pin; `OUROBOROS_SETTINGS_SHA256` enables the trust root
      ├── credential_shapes.py ← Credential leaf names plus physical owner credential locations; ordinary root reads never import shape policy
      ├── update_channels.py   ← Closed Stable/QA/Development channel mapping and update-network defaults
      ├── update_letter.py     ← The update letter: full `base..target` commit material including merged branches (EVERY subject with its full sha, excluding commits reachable from base) + README history rows added along the target's first-parent line (not transient branch rows), each naming its source diff commit (only bodies and the oldest row texts are bounded, and disclosed; the paragraph's shape is asked of the model, never policed by the host), one accounted LIGHT-slot call with the ordinary task context, `state/update_letter.json`, one projection shared by the Updates payload and the Runtime context `official_update` fact
      ├── colab_bootstrap.py   ← Google Colab source-mode bootstrap: official update source, stable local `ouroboros` branch, Drive-backed settings/data, personal origin, no-UI server command, native Telegram setup
      ├── cli.py               ← Source/headless CLI over gateway tasks, logs, settings, skills, marketplace, local-model, and MCP wrappers
      ├── packaged_cli.py      ← Packaged desktop CLI bridge: resolves bundle roots, bootstraps the launcher-managed repo, delegates to cli.py
      ├── packaged_cli_install.py ← Packaged CLI installer planning/execution for user-local command shims
      ├── agent.py             ← Task orchestrator; the dispatch-note pair lives in `subagent_dispatch_notes.py` (same-name re-exports). The outer catch around `run_llm_loop` delegates terminal projection to `_task_exception_terminal`: `_LoopExitContext.attach_exception_evidence` retains the loop's own accumulated objects on the original exception, while missing captures are explicitly unknown. A failed cold-source read never supplies fabricated zero counters or unverified checkpoint bytes; the trace summary, loop usage, task metrics, chat/history counters and post-task summary preserve that absence. The loop's tally rides `loop_outcome.usage` (ABI-3's honest loop plane); the top-level `total_rounds`/`prompt_tokens`/`completion_tokens` stay the LEDGER's answer from `reconstruct_task_cost`. An internal `task_exception` is `failure.kind = "runtime"`, never a fabricated provider failure
      ├── agent_startup_checks.py ← Worker-boot verification: dirty repo, version sync, budget, memory files, health checks
      ├── agent_task_pipeline.py ← Task execution pipeline orchestration; freezes one shared non-final subtree-cost snapshot for summary/reflection before the terminal checkpoint records final spend; hands the summary and reflection prompts the commit/advisory review lens PLUS the task's own acceptance-panel projection, and an absence statement names the lens it describes; calls the swarm-efficiency rollup owned by task_finalization.py at pipeline end
      ├── agent_dispatch.py, post_task_synthesis.py ← The agent's delegated-child dispatch seam, and the post-task synthesis workers the pipeline runs after a terminal result
      ├── task_finalization.py ← Terminal delivery + sealed final ground truth: live final-answer delivery before blocking post-task (final event selected by the finalizing task's id; buffered copy retained under one `delivery_id`), the sealed final package (submitted final text, the durable result's artifact manifest, and task-related completion observations) fed to summary/reflection as a prompt input, never a validator; owns the per-task `swarm_efficiency` rollup (subagent_count / fanout_count / fanout_interval_sec_total / `lanes_requested` — a rollup built from pre-dispatch fanout events cannot truthfully report effective lanes, which are per-child dispatch facts; `planned` stays null, never inferred as 0 from absent events; host-attested Swarm intent is the typed metadata `force_plan_source == "swarm"`, never prompt inspection, and a Swarm task that fanned out nothing records a minimal `no_fanout_observed` block instead of silence); a fanned-out root additionally carries a `depth` block (`requested_depth`/`permitted_depth`/`attempted_depth`/`achieved_depth` plus a typed status, `host_visible_only`) built from the root contract and its subtree's depth provenance, so a root that never carried its own request recovers it from the children it scheduled, and the task result carries it (the terminal task_summary row states no depth sentence)
      ├── mutation_attribution.py ← Root-task baseline capture in the existing task result; clean-at-baseline Git candidate projection; terminal projection includes the committed interval delta
      ├── process_interpreters.py ← Interpreter resolvers for the user process launch surfaces: one-time pre-guard unversioned-Python resolver + post-gates Node ladder (PATH-first health probe, bundled fallback, attested child-env PATH prepend; the probe EXECUTES a candidate, so it runs only after the dispatch gates approve the call)
      ├── post_task_checkpoint.py ← Durable root post-task phase/final-cost checkpoint shared by task finalization and Project naming recovery
      ├── presence_profile.py  ← Strict reviewed `presence:` behavior-profile parser (instructions, context topics, runtime defaults, portable capability requests)
      ├── presence_runtime.py  ← Symbolic `main`/`light` defaults; owner-local overrides clamped to the global round limit
      ├── presence_capabilities.py ← Host-owned installation selections for portable Presence capability requests, including an optional owner-selected working folder
      ├── presence_authority.py ← Immutable positive capability ceiling compiled from one reviewed profile, its selected exact targets, and the constant cognitive-memory baseline (`tool_capabilities.COGNITIVE_MEMORY_TOOL_NAMES`) — Ouroboros's own memory faculty in every admitted channel, never authority for the correspondent
      ├── presence_bindings.py ← Owner-created revocable transport-room → behavior-skill bindings with exact origin/destination identity
      ├── presence_admission.py ← Fresh review/enablement/profile/state admission + immutable per-turn Presence snapshot
      ├── presence_context.py  ← Presence instructions, exact event facts, declared knowledge-topic projection
      ├── presence_runner.py   ← Fresh-agent Presence turns: cross-process installation cap, per-conversation serialization, idempotency, typed result, dialogue provenance
      ├── dialogue_provenance.py ← Shared exact transport-provenance rendering for history, memory, and consolidation
      ├── extension_companion.py ← Host-supervised companion processes for transport skills (§12)
      ├── extension_reconcile_queue.py ← Durable worker→server extension reconcile markers + server pickup loop
      ├── event_bus.py         ← Typed in-process event bus for skill subscriptions
      ├── evolution_checkpoints.py ← Append-only campaign/eval checkpoint ledger for evolution progress
      ├── evolution_fingerprint.py ← Canonical fingerprint for evolution-campaign objectives; SSOT for repeat gating
      ├── improvement_backlog.py ← Durable advisory improvement backlog: recurrence-counted dedup (bump count/last_seen, never drop), priority+recurrence+recency ranking, close-on-commit `close_backlog_items`, size-triggered `groom_backlog`; parser-safe locked writer; entries carry priority/kind
      ├── loop.py              ← High-level LLM tool loop and its one-shot finalization nudges, ordered nanny → red-verification → masked-verification → no-op-attempt; continuous `FINAL ANSWER:` latching captures the latest typed candidate every round (tool-count-stamped, no prose mining) so review/nudge/forced-finalization paths never erase a structured answer; all marker prompting is gated on `task_contract.answer_protocol="final_answer_line"` via the `answer_protocol_active` SSOT (the gate is sufficient — an empty `expected_output` cannot suppress it) while the latch/extractor stay unconditional; `outcomes.extract_final_answer` (re-imported here) structurally rejects the outcome-tier ledger identifiers as answers — internal enum vocabulary is never a deliverable, and `solved` stays extractable as an ordinary English word. The nanny nudge (`loop_nudges._nanny_finalization_message`, re-exported here) fires once for a harness child finalizing with ZERO durable start attempts (blocked and uncustodied attempts count, so an exact-route startup fault is not accused of skipping delegation); it reads custody evidence from the canonical (budget) root via `delegate_custody.custody_root` and branches PENDING ≠ FAILED — a started-but-unsettled run gets a wait reminder, never a failure accusation, which would invite a duplicate concurrent run; an actually-injected nudge is stamped by the WORKER as a durable custody row, and a COMPLETED harness child with zero runs carries the typed `nanny_finalized_after_nudge_without_delegation` disclosure (stamped by `subagents._disclose_native_only_substrate` at the completion seam; visibility, never a gate); a configured session child finalizing without a succeeded leaf run carries the typed `CONFIGURED_ACTOR_INCOMPLETE`/`CONFIGURED_ACTOR_UNKNOWN` fact (`subagent_bootstrap.actor_first_unresolved_fact`; host children ride along as auxiliary `direct_child_statuses`, never a substitute for the leaf), and a successful run's later silence stays proportional to the measured burn (the `NANNY_METERED_OVERRUN` reminder in `loop_nudges`, metered by `nanny_pacing.nanny_metered_since_delegate_activity`/`nanny_burn_phrase`)
      ├── acceptance_settlement.py ← What happens to a paid acceptance panel that outlives the answer it reviewed: the quorum/completion mailbox wake carrying each reviewer's own verdict, the delivery-under-a-running-panel terminal (wait by default, conscious finish, `previous_revision_accepted` on a PASS over the earlier revision), and the post-terminal supplement that stamps a host-composed `late_settlement` note on the collected panel, republishes it, and announces it once in the task's room as a `card_row="reviews"` System row
      ├── loop_acceptance.py, loop_acceptance_review.py ← Acceptance machinery (moved whole out of `loop.py`, which keeps the checkpoint, run-record and message rails; every name with an external caller is re-exported from `loop` so external callers, patch sites and the acceptance-writer inventory keep one import surface — a moved name nobody outside references is not re-exported). The fence and its obligations: eligibility, begin/end/supersede, subtree snapshots, the final-answer latch, the closed typed reason set `ACCEPTANCE_DECISION_REASONS`, the sole decision merge point `_set_acceptance_decision`, and obligation collection/reopen/disposition. The run: the host evidence packet (`_build_host_acceptance_evidence` over `review_evidence.build_task_acceptance_evidence`, plus the forced-rail child debt and the unhashed dialogue history), the one substantive panel (`_execute_task_acceptance_panel`: reviewer rows, wave-budget admission, the free zero-physical refusal, the exact-hash wallet stamp, the timing event), the bounded `acceptance_dialogue_history`, and the paid identity + free-replay `_refuse_identical_acceptance`; the `dialogue_status` reducer is `review_verdict.aggregate_dialogue_status` (the vote SSOT, re-exported through `review_substrate`; these are its consumers). `loop_acceptance_review.acceptance_retrieving_work_order` renders the delivery-conditional work order of the retrieving rows (session: FULL packet + absolute pointers + access disclosure; native: packet without its freely degradable tail + real data root) onto `ReviewRequest.slot_session_tasks` — the FULL packet stays the `evidence_refs` authority
      ├── loop_llm_call.py     ← Single-round LLM call + usage accounting
      ├── transcript_prefix.py ← Append-only transcript invariant between the sends of one loop execution: the one `sent_in_previous_send` predicate every producer that appends behind a sent row consults (owner follow-ups, task messages, quiz answers, roster notes and the acceptance observation alike — the #929 carve-out generalized); per-message content digests (role, plain text, tool-call identity — cache markers, block shape and private custody keys are not content) and the `prompt_prefix_break` checkpoint fact (`kind` = system_rewritten | tail_replaced | rewritten | shrunk, plus `sanctioned_by`, stamped by the compaction seams through `sanction_rewrite` and read on the transcript each round actually dispatched; a context-fit reprojection after a real overflow is recorded as an ordinary break, a real cache cost); it RECORDS, never blocks — OpenAI-family caches reuse a previous request only when it is a byte-prefix of the next, so a transient tail or an in-place rewrite discards the whole conversation cache (measured 2026-09-14, #906)
      ├── loop_transport.py    ← Transport-outage wait episodes and provider-failure terminal text; bounded backoff with free redial
      ├── loop_delivery.py ← Delivery candidates and delivery control: the candidate dataclass with inherited host-control-episode provenance, the hold-control literals, the control prompt and its cycle, whole-body classification and the duplicate-key/trailing-object parsers, child-result dispositions, the delivery evidence state, acceptance bindings, candidate publish/replace/degrade, the subagent handoff and the no-tool final; `loop` re-exports the underscore names
      ├── loop_budget.py, loop_forced_finalization.py, loop_messages.py, loop_model_call.py, loop_nudges.py, loop_round_limits.py ← The rest of the round driver, one rail per leaf, all re-exported from `loop`: the budget rails (the shared warm/cold post-tool decision, cost ceilings and tree accounting, soft landing, budget-exceeded handler, resource cleanup, service finalization); forced finalization of a task that ran out of road (orphan notes, child claims and the absorption gate, swarm-action enforcement, owner-directive drain, the one forced model call); owner-message text plumbing (extraction, append-or-merge of user turns, stale-image eviction, owner-directive bookkeeping, round-progress text); the per-round model call (context-fit identification, measurement and memory, dispatch, main-context reclaim, overflow-retry predicates, the cross-model fallback chain); the mid-task steering notes (self-check, time and cost milestones, nanny economics, round checkpoints, plan-forcing and finalization nudges); and the round-limit and terminal-drain handling (owner-stop drain and its window, incoming-message drain, round compaction and its usage accounting)
      ├── task_pacing.py       ← Task-pacing SSOT: deadline/cost milestones, finalization reserve, BudgetSnapshot, acceptance launch/improvement rails — `review_launch_allowed` / `improvement_pass_allowed`, the floor evaluated ONCE per panel at loop admission, no review-duration prediction (owner R52/R55; semantics: §6 Task lifecycle; cap SSOT: `review_cycles.py`, §6 Review stack)
      ├── vision_routing.py    ← Send-time image routing SSOT: inline vision vs generic captions vs placeholders on a per-send message copy (`OUROBOROS_IMAGE_INPUT_MODE`, `OUROBOROS_MODEL_VISION`)
      ├── fallback_cooldown.py ← Per-process 429-aware cooldown for the `OUROBOROS_MODEL_FALLBACKS` chain: a transiently-failed model is parked for a short window so fallback walks and repeated rounds skip it; advisory, default-on, fail-soft, passive heal; per-process only — honestly not a swarm-wide governor
      ├── model_concurrency.py ← Per-(model,use_local) `BoundedSemaphore` capping concurrent provider calls (`OUROBOROS_MODEL_MAX_CONCURRENCY`, default 3) so a task's own loop + subagent threads + status pings cannot self-DoS one model's rate limit; excess threads WAIT deadline-bounded; wraps only the provider call in `loop_llm_call.call_llm_with_retry`; per-process only
      ├── project_naming.py    ← SSOT for LLM-first project naming: bounded light-model title with deterministic fallback, shared by admission naming (`admission_names`: headless runs and chat promotion, no model call), turn-into-project conversion (gateway/projects.py), `ensure_project_scope`, and the lazy turn namer (`spawn_turn_namer`: a direct Main turn is named on its first non-addressing tool call, one bounded Light call, never for a greeting); the provider call goes through the model_concurrency slot
      ├── loop_tool_execution.py ← Tool dispatch and tool-result handling
      ├── deadline_utils.py    ← Shared deadline parsing/remaining-time helpers + the transport-vs-logical wait seam for loop milestones and process-tool/review timeouts
      ├── observability.py     ← Private forensic execution ledger: redaction, gzip CAS blobs, call manifests, trace refs
      ├── model_send_seal.py ← The runtime invariant `model-visible ⟺ logged` for `model_send`: a reconstruction mismatch is a typed durable fact, and the call is NOT blocked — dispatch authority stays with the pre-existing in-memory identity re-check
      ├── cancel_intents.py    ← Durable cancel-intent projection: compact locked `state/cancel_intents.json` of ACTIVE intents (request id, claim owner/pid + claim GENERATION fencing every mutation, `scope` recording single-vs-cascade so a watchdog replay re-runs the right shape) + forensic `cancel_intent` ledger rows; the ONE ingress `request_cancel` for the agent tool, HTTP single/cascade, and boot migration of legacy latch files — intent never rides the canonical task status; reads are strict and fail closed per §10 (typed `CancelIntentProjectionCorrupt`; enforcement degradation is owner-visible, never a silent "no intent"); a quarantined malformed row discloses once per row content — a ~20 s watchdog must not append the same disclosure forever, and a restart re-announcing once is honest; owns `claim_is_abandoned` and the `allow_settled_target` live-ownership exception (§10, cancellation custody)
      ├── owner_hurry.py       ← Owner "hurry": a typed TASK-LOCAL acceleration latch, never a chat message; the durable `owner_hurry` projection is written by `update_json_locked` touching only its own keys — never `write_task_result`, whose status-regression guard could drop concurrent terminal fields — keyed by the real attempt identity `task["_attempt"]`; while latched, the next acceptance panel is skipped with zero reviewer calls (`acceptance_skip_applied`), remaining improvement passes overlay to 0 through `effective_budget_profile` (the immutable task_contract is never rewritten), and force-plan becomes task-locally advisory; the effect DIES WITH THE ATTEMPT (`retry_reset` on every same-id requeue producer), a never-applied request is marked `not_applied_before_terminal`, and the non-chat `owner_hurry` events are hidden from chat by `log_events.js`
      ├── owner_quiz.py        ← Owner-quiz lifecycle projection: worker-side `record_asked`, request-id-idempotent first-answer-wins `record_answered` (option index validated against the STORED labels), structural-only `reconcile_terminal` (open → expired_terminal at task done; no host TTL) which also closes the PAIRED `owner_wait` under the same task-result authority — repairable on a second pass after a partial pair write, including an answered quiz whose worker resume was not yet granted, while preserving the recorded answer — `quiz_states` replay; same locked-writer idiom as owner_hurry, touching only the `owner_quiz` and paired `owner_wait` keys
      ├── owner_wait.py        ← Native owner-answer continuation: completed-tool source checkpoint, original-process sleep, and same-task recovery only through an acknowledged planned-restart handoff; active capacity belongs to supervisor/worker_owner_wait.py
      ├── routing_wait.py      ← Root-parameterized SSOT of the durable routing-receipt waits (`wait_for_promotion_admission`, `wait_for_routing_annotation`); tools/control.py keeps thin wrappers, so the gateway picker dispatcher confirms clicks through the SAME receipts the LLM routing tools poll
      ├── outcomes.py          ← Typed task-outcome and acceptance-decision authority keeping the lifecycle/execution/objective/review/artifact/verification/child-absorption axes separate; policy denials, cosmetic exits, and ignored outcomes never masquerade as genuine tool failures; receipt reconciliation lives in `_outcome_receipts.py`, trace classification in `_outcome_tool_errors.py`; a verification ledger above the inline threshold rides as a stub whose `summary` is re-projected from the refreshed artifact file at finalization, and the stub is never a source for entries or outcome axes (the ledger embeds the task contract, which its entry count excludes, so a stub is the normal shape for a swarm root)
      ├── outcome_receipt_store.py ← Durable verification-receipt path/append/read authority + exact-row union of forked-child and canonical replicas; owns the zero-run WRITE enum (`incomplete`/`unknown` only — a zero-run "complete" is unverifiable self-report); outcomes.py re-exports the compatibility names
      ├── depth_evidence.py    ← Pure requested/permitted/attempted/achieved depth projection for root acceptance; missing admitted permission stays evidence-unknown rather than reconstructed from mutable live config
      ├── _outcome_receipts.py ← Receipt parsing and the ONE canonical receipt identity (`receipt_canonical_identity` → `ReceiptIdentity`; invariant in §10): three independent components — `criterion_id`; structurally canonical `check` text PAIRED with its `check_rendering` stamp (quoted shell punctuation is data, not syntax, and receipts from different renderings are never the same verification — the stored string alone cannot say which renderer wrote it); and the raw-sorted `canonical_path_set` (whitespace untouched — a leading space is a legal filename byte); `ReceiptIdentity.key` selects ONE typed (kind, value) and sameness is that key's equality, never a match across kinds — the parts are disclosures, never the comparison; the per-kind normalization answer lives in the closed `IDENTITY_KINDS`/`KIND_NORMALIZES_COMMAND_TEXT` table, so a fourth kind must state its own answer in its own row rather than inherit a default; the outstanding sets `unreconciled_failed`/`unreconciled_masked` scan every candidate against ALL later reconcilers and collapse repeated failures of one check onto the freshest receipt; the shared disclosed projections (`receipt_identity_projection`, `disclosed_list_projection`) make every bound explicit — exact omitted counts plus a hash over the injective serialization, string bounding via the SSOT `utils.truncate_review_artifact`, never a hand-rolled slice; `verification_receipt_ledger_row` splats that projection, so a new receipt key is dropped unless added there
      ├── _outcome_tool_errors.py ← Leaf SSOT for tool-trace status vocabularies and execution-axis classification; outcomes.py re-exports
      ├── code_intelligence.py ← Internal code inventory: derived-only file facts, hashes, polyglot symbol/import/call extraction via tree-sitter with Python on stdlib `ast`, a visible `structural_unavailable` fallback when a grammar is missing, and an incremental JSON cache (no raw source)
      ├── code_intelligence_architecture.py ← Architecture facts over the pinned domain/contract/persistence carriers: `owner_of`, the domain quotient, and the facade inventory (`docs/inventories/FACADE_INVENTORY.md`)
      ├── code_search_rg.py    ← Optional ripgrep-backed search for search_code; every match is post-filtered through the protected/secret gates
      ├── pricing.py           ← Exact-route best-effort provider-catalog lookup with nullable estimates; no static model tariffs (they go stale) and not the monetary ledger
      ├── usage_accounting.py  ← Append-only physical-model-attempt monetary authority: reserved→dispatched→settled|unresolved (or reserved→released), short cross-process check+append+fsync lock, conservative global/root admission, validated replay/torn-tail quarantine, compatibility projections, resumable legacy import; application candidates carry exact raw/context identities + a pre-dispatch manifest on the same attempt id
      ├── _usage_response.py   ← Pure provider-response usage normalization for physical accounting; a zero-usage body error settles at a confirmed $0 to release the reservation, so a provider storm cannot manufacture phantom budget exhaustion. It is the one NORMALIZER of a provider's usage block for accounting (its importers are `usage_accounting.py` and `loop_llm_call.py`). Not the only READER of that block: every provider adapter reads the raw `usage` dict for its own response envelope, so a "consolidation" here would centralize a read that was never centralized
      ├── _usage_rows.py       ← Pure row arithmetic (summaries, limit/integrity decoration, physical-call counts, breakdown buckets, the exact Skill Review wave/slot projection); no I/O or locks; re-exported by usage_accounting.py
      ├── _usage_rows_memo.py  ← Validated-rows memo + fingerprint-keyed render cache + in-lock warm read cache; every cache resumes via the substrate's `LedgerResumeState` fingerprint and falls back to the authoritative locked read on any doubt
      ├── _usage_cache_splits.py ← process-local `(task, provider, route identity, review surface)` last-observed prompt-cache split; non-durable and re-exported from `usage_accounting.py`; a lost entry only re-prices a full cache write
      ├── skill_review_usage.py ← Read-only cached projection of final physical-attempt rows for one exact `(review_skill, review_wave_id)`; no second ledger or persisted totals
      ├── usage_ledger.py      ← Durable append-only ledger substrate: cross-process locking, atomic append+fsync, row/transition validation, torn-tail quarantine; one-way seam — accounting imports it, never the reverse
      ├── usage_compaction.py, usage_legacy_import.py ← Seq-preserving compaction of that monetary ledger, sitting BESIDE the substrate rather than inside it, and the one-time legacy usage-telemetry import
      ├── cost_projection.py   ← The ONE projection of task cost for every producer surface: `accounted_upper_bound_usd` is the honest name for the settled+reserved+unresolved upper bound the ledger reports; the retired `cost_usd[_with_children]` spellings are read-only tolerance for stored legacy records (a diverged stored pair resolves deprecated-wins) and are never emitted — the write/read seams strip them; null projects as None (never $0.00); finality is never fabricated; the `COST_OPENNESS_FIELDS` accounting markers ride beside every amount; producers pass their source through `cost_projection`/`with_cost_aliases` instead of hand-assembling the pair
      ├── delegate_custody.py  ← Durable custody for delegated (Claudexor) runs: the SSOT is the `delegate_run_*` rows in the canonical event log plus ONE compact incident projection `<drive_root>/logs/containment_faults.jsonl` — the event log grows without bound, and a tail-bounded scan can bury an unresolved fault; OWNED/FOREIGN/UNKNOWN ownership replay survives worker restart; the per-intention invocation id rides the wire as `Idempotency-Key` (the deterministic per-logical-start hash is only the pending-invocation LOOKUP identity; reuse only via the explicit `retry_of` token); run settlement is decoupled from registration cleanup — `settled` follows the idempotent ledger row while the owned-registration obligation survives on `project_owned` with its own sharer tie-break and sweep, and the terminal audit discloses `deferred_project_retirements` additively; typed cancel vocabulary (confirmed | requested | failed | containment_fault_run_may_still_be_live) with durable faults riding the health invariants; one `daemon_says_absent` predicate decides everywhere that a 404 is the daemon ANSWERING the resource is gone, never a failure to find out; an ABSENT custody log is a positively-established clean state while an EXISTING-but-unreadable one audits as typed `delegated_run_state_unknown:custody_log_unreadable`, never cleanly reconciled; patch-apply intent rows (`delegate_run_patch_apply_started`/`_resolved` + the `patch_apply_pending` replay flag) make a crashed disposition typed-AMBIGUOUS instead of falsely rejected; `run_not_owned` refusals disclose `owner_task_id`/`run_settled`/`run_terminal_state`, and `run_ownership_unknown` names `get_task_result` as the ownership-free cross-task read
      ├── delegate_custody_reconcile.py, delegate_state_sweep.py ← Reconciliation of delegated runs — the settle-or-cancel sweeps and their recovery; a review-owned row is cancelled only behind an owner cancellation and a review invocation is retained, never re-posted — and the terminal-plus-age sweep of the recovery/supervision state they leave behind
      ├── delegate_custody_usage.py ← Pure usage and terminal-state projections over delegated-run custody rows; the cross-process custody usage lock; the reviewer usage observers (one `llm_usage` row per ledger attempt, rows for physically dispatched failed sends, one row per delegated run across executors)
      ├── delegate_hold.py     ← Unknown-provider hold: parks the task in supervised_wait, waits for the leaf wake, never resends
      ├── delegate_source_coverage.py ← Oversized-work-order source custody: canonical interval union/completeness, strict durable receipt bounds, replay-safe start binding, durable delivery confirmation for safe receipt retry, terminal cannot-verify projection, apply refusal — incomplete source cannot authorize a terminal PASS/apply; reuses `get_task_result` + the existing interaction seam; no alternate store
      ├── delegate_evidence.py ← Read-side execution-evidence projection over the custody rows (`task_execution_evidence`: started/settled/succeeded/failed counts, terminal-state axis, `evidence_read_failed`, disclosed subscription spend, `nanny_nudge_recorded`, and `delegate_start_attempted` counting blocked and uncustodied attempts too, so a refused-but-obedient nanny is never disclosed as nudge-ignoring); owns the stamp writers `record_nanny_nudge_stamp`/`record_start_blocked`; projects `applied_access_profiles` — the access the engine actually served, read off SETTLED rows only (empty = no receipt disclosed it, never "no access") — and `acceptance_patch_dispositions`, the bounded section over `delegate_run_patch_verdict` rows (cap 20 with the exact omitted count, `unreviewed_delegated_apply` headline); absence of the section means NO disposition was recorded, never "reviewed clean", and an unreadable custody log is the typed `evidence_read_failed` marker, never an empty-therefore-clean section
      ├── synthesis_cost_text.py ← Synthesis-prompt renderers for the pre-synthesis cost/outcome snapshot over the SSOT `cost_display`; re-exported by agent_task_pipeline.py
      ├── llm.py               ← Multi-provider LLM routing (OpenRouter/OpenAI/compatible/Cloud.ru/MiniMax/DeepSeek/GigaChat/Anthropic); canonical conversations stay function-shaped while the physical-send seam delegates exact-route request adaptation to the request-wire leaves below
      ├── llm_routing.py, llm_attempt.py, llm_messages.py, llm_capability_policy.py, llm_fallback.py, llm_pricing.py, llm_openai_compatible.py, llm_anthropic.py, llm_gigachat.py, llm_local.py, llm_claudexor.py ← The client's leaves behind that facade, which re-exports the historical names: provider target resolution, client construction, route affinity, remote dispatch and subscription metadata; physical-attempt candidates and send-time prompt-cache policy; transcript shaping for the wire and the reasoning-artifact contract; route capability metadata and the learned parameter/effort policy; the recovery ladder a failed or poisoned send is retried on; the live provider price catalogs (OpenRouter, Cloud.ru) and settled-cost projection; and the wire lanes — OpenAI-compatible, native Anthropic, GigaChat, local llama.cpp and caller-owned Claudexor model operations, with their route-specific context contracts
      ├── llm_stream.py        ← Complete Chat Completions and native Messages SSE assembly inside one physical attempt; private wire/partial evidence and terminal framing, with existing response normalization and monetary custody
      ├── net_transport.py     ← Shared httpx transport construction for remote LLM clients; TCP-keepalive socket options
      ├── model_wait.py        ← Quota/auth waits bound to the existing task or phase owner: same-call continuation, role overrides, quota-aware clocks and typed stop/deadline propagation; its completed-call choices and quota union also survive native owner-wait continuation
      ├── transport_custody.py ← Typed transport facts for the physical-attempt custody seam
      ├── openrouter_attribution.py ← Canonical OpenRouter application attribution, centralized so forks do not compete under the same external application identity
      ├── openai_chat_custom.py ← Pure direct-OpenAI Chat function→custom codec: deterministic compact schemas, exact full-schema/catalog binding, tool-choice projection, prior-call replay, canonical response normalization, parser-issued validation sidecars; no Responses transcript or second stored history
      ├── openai_chat_dispatch.py ← Direct-OpenAI Chat policy leaf: custom+requested reasoning first, exact-dialect fallback with the same reasoning, then task-local explicit `none` only when the physical-attempt rail still permits it; owns private sidecar consumption + the bounded schema-error continuation
      ├── request_wire_contract.py ← Provider-neutral exact-route request profile: closed `set_value`/`drop_field`/registered `replace_dialect` actions, 14-day success-only evidence store `data/state/request_wire_compatibility.json`; task-local explicit `none` can never become durable dispatch authority — a task-local availability fallback must not teach the route
      ├── request_wire_resolution.py ← Deterministic request-profile composition with source-predicated effort bounds/transitions; contradictions fail open to the requested effort with `conflict=True`
      ├── request_wire_receipts.py ← Factory-bound wire candidates + semantic-success receipts (exact serializer digests; tool-choice semantics cannot change)
      ├── request_wire_attempt.py ← Physical-attempt validation — a settled accounting attempt for the exact candidate; public `usage.request_wire` disclosure
      ├── request_wire_custom_validation.py ← Custom-call validation; a validation failure may prove wire acceptance but cannot authorize tool execution (`allows_execution` gate)
      ├── request_wire_recovery.py ← One sync/async wire-recovery machine: durable evidence applied immediately before send, reactive evidence committed only after terminal semantic success, ordered terminal disclosures
      ├── anthropic_native_custody.py ← Whole-block replay custody for Anthropic native reasoning (same provider/endpoint/API/model); opaque type/order/size/digest projections
      ├── reasoning_artifacts.py ← Sealed-vs-portable reasoning-artifact classification, shape-first and fail-closed; only sealed artifacts pin an endpoint — portable reasoning stays failover-eligible; the `SIGNED_PORTABLE` roster is a decaying external provider fact (inventory: docs/DEVELOPMENT.md), extended only by a fresh cross-provider replay probe
      ├── llm_observability.py ← Persists public call projections; strips private sidecars from durable records while returning them in-process
      ├── llm_probe.py         ← Oversized-context evidence probe + Provider Test transport with physical accounting; no retry, fallback, or learning
      ├── mcp_client.py        ← MCP client: parses MCP_SERVERS, validates transports, masks tokens, prefixes tools `mcp_<server>__<tool>`, guarded SDK import; MCP descriptions/results stay untrusted data (§6)
      ├── safety.py            ← Safety supervisor call with a bounded newest-first context budget (the omission marker is reserved INSIDE the budget); a 429 on the safety check is an infrastructure fact about the supervisor, not a verdict about the tool call — one deadline-capped retry, then the typed `⚠️ SAFETY_UNAVAILABLE` non-verdict telling the agent to retry the same call, not reword it; process-local storm latch answers in-window checks without provider calls; durable `safety_check_rate_limited` audit event; structured insufficient-quota keeps its PERMANENT classification and still blocks as a verdict; the serialized SUBJECT has its own 250k-char budget (`_SAFETY_SUBJECT_CHAR_BUDGET`, rendered `ensure_ascii=False`) and an over-budget subject is refused fail-closed with the typed `⚠️ SAFETY_SUBJECT_TOO_LARGE_BLOCKED` denial plus a durable `safety_subject_too_large` event — never truncated, because anything past a cut would run unreviewed; the fail-open cases are owned by prompts/SYSTEM.md
      ├── consciousness.py     ← The alarm clock of Background Consciousness: WHEN Ouroboros wakes up on its own. No thread and no private loop — the supervisor pass calls `tick(now)`, whose ordered typed outcomes are disabled → a live wake → a live owner direct turn → not yet due → the rolling-24h allowance → an owner chat must be bound → launch; the launch itself is `supervisor.workers.handle_wake_direct`, an ordinary Main direct turn (§6). The next wake is `last finish + interval` (the model's `set_next_wakeup` or the default, clamped into the owner's [min, max]; a runner failure doubles it up to max); `notify(reason)` pulls it forward to one shared floor. The legacy observation inbox, if present, is moved once to the archive unread
      ├── consciousness_wake.py ← The wake-up MESSAGE and the wake's envelope: `prompts/CONSCIOUSNESS.md` rendered as the turn's USER message with every placeholder substituted from existing readers (tasks settled since the last wake, open owner cards, owner-message count, level, allowance, interval) and an explicit `(+N more)` line instead of a silent cut; `wake_task_metadata` is the origin/authority envelope `handle_wake_direct` carries
      ├── consciousness_authority.py ← The three autonomy levels of a consciousness wake-up (observe/act/full, carried as `metadata.consciousness_autonomy` beside `metadata.initiator`), the one helper that derives a level's two consequences at task build (`disabled_tools` as an exception list, `runtime_mode_cap=light` below Full), the origin keys everything a wake starts inherits, and the stricter-of-install-and-cap mode the tool dispatcher's light gates read; for a consciousness-origin task `disabled_tools` binds at dispatch only so its prompt prefix matches an owner turn's
      ├── consciousness_allowance.py ← Rolling-24h spend of consciousness (its wakes plus the roots they started) read off the usage ledger: roots by the category of final rows inside the 48 h fold horizon, every money row kind under them through the one `_usage_rows._summary` reducer, fingerprint-memoized selection with a per-call time filter, typed `allowance_unknown` on a read failure; the single admission door in `supervisor/queue.py` and the alarm read it
      ├── consolidator.py      ← Dialogue consolidation with a generation-aware cursor over the ordered archive chain; an unfindable generation appends a loud durable `[MEMORY GAP]` block, never a silent offset reset; a run that advances without a new failure clears `last_consolidation_error`, and a knowledge-nomination batch that is not fully published leaves `last_unpublished_nominations` in `dialogue_meta.json` (a fully published batch clears it)
      ├── memory.py            ← Scratchpad, identity, chat history
      ├── knowledge.py         ← `ouroboros/knowledge.py`: shared linked-Markdown note addressing, exact source reads, revision-checked writes and generated shelf indexes for global and project knowledge; one writer preserves authored understanding, unknown metadata and provenance so concurrent cognition cannot silently overwrite a newer note or invent understanding from a truncated prefix
      ├── memory_journal_compaction.py ← Digest-only compaction of old memory-journal snapshots: the digest replaces the snapshots it summarizes, never a silent drop
      ├── project_facts.py     ← project_id resolution (explicit `--project-id` or workspace-path hash); per-project knowledge dir `projects/<id>/knowledge` isolated from `memory/knowledge`; journal/workpad helpers
      ├── task_tree_ledger.py  ← Append-only `data/task_trees/<root>/blackboard.jsonl`: EPHEMERAL swarm coordination in typed validated rows (prose is never authoritative), distinct from the durable project journal it is mirrored into by `tools/project_journal.py::mirror_tree_coordination_to_journal`; size-capped writes; exposed via `tree_note`/`tree_read` with the tail injected each turn; pruned on root terminal
      ├── projects_registry.py ← Durable `data/state/projects.json`: 80-char names, `active|deleting|tombstoned`; deletion preserves bindings/history/folder/memory; a tombstone blocks resurrection; reconcile registers existing stores and NEVER prunes
      ├── project_dialogue.py  ← Read-only chat lens + append-only `logs/chat_annotations.jsonl`; the sidecar never owns routing except the `needs_manual_target` decision card (token+options validate the click; first-wins closing rows); `build_owner_message_ref` mints refs at ingress; `routing_refusal_cause` composes the owner-facing `cause` sentence for every refused routing act from one host table, and `room_membership` keeps admission-notice rows in the chat they were sent to
      ├── project_lease.py     ← One-writer-per-project lease in `assign_tasks`; same-project subagent swarms exempt; `""` is no lane
      ├── context.py           ← Main agent context assembly; places ordered subagent-catalog JSON under `## Available subagents` in the semi-stable block; the knowledge index always carries each note's authored summary, and an unauthored shared overview renders as a visible gap line, never as silence
      ├── main_context_authority.py ← Deep-copies the context authority; replaces only oversized raw result strings with source-resolvable narrative or a typed gap
      ├── client_surface.py    ← Closed-key bounded client-surface normalizer; surface identity excludes viewport/narrow_layout; mailbox surface-change note
      ├── context_fit.py       ← Deterministic Max/Low/Nano context projections from one immutable core with labelled measurement + typed reclaim deficit; Nano owns the compact projection and bounded output target; no routing/retry/global-mode authority; owns the message-side transcript cache seal (exactly ONE message-side breakpoint: the task-contract boundary until a rolling tool-result seal qualifies, migrated in the same call so the four-breakpoint cap can never drop it)
      ├── context_budget.py    ← Context budget vocabulary + typed reclaim SSOT (owner-Low 200K economy target and Nano bounded horizon); owns `estimate_message_chars` (images counted at `IMAGE_BLOCK_CHAR_EQUIVALENT`, replayed `reasoning_content` counted on the DeepSeek echo lane), the bounded basis of the local compaction proxy; remote fit and the density witness measure on `context_fit.estimate_context_prompt_tokens`
      ├── context_mode_compat.py ← One-window compatibility shim for the retired persistent context auto-Low state
      ├── capability_evidence.py ← Sourced capability evidence in `data/state/capability_evidence.json` (confirmed/asserted/unprobeable/failed): authorizing readers require fresh evidence, and unknown fails the ≥1M gates closed; owns `observe_token_density` — the density witness calibrates on the bounded-proxy basis the fit estimator measures, while budget reservation keeps RAW, because over-counting money is the safe direction and the two consumers split on purpose; owns `cold_start_density_probe` too — the one bounded exact-model send that sources a witness when a review pack is refused or degraded under the cold floor; exact-route dispatch authority lives in `request_wire_compatibility.json`
      ├── context_layout.py    ← Doc-layout SSOT: tier-0 always full; a caller declares the VIEW it wants of a reference book and `book_navigation` owns the compact one — the authored chapter introductions with each chapter's own `##`-`####` index and line ranges into the PHYSICAL chapter file, because a composed-book offset addresses the wrong bytes of the entrypoint (a legacy single-file revision is mapped as the one source it is); ARCHITECTURE composed in Max and navigated in Low/Nano; DEVELOPMENT full-or-pointer by task binding; reduction is by relocation with a visible pointer, never silent truncation
      ├── reference_books.py   ← `ouroboros/reference_books.py`: one ordered Architecture/Development reader over the explicit Markdown chapter membership both books now carry, with authored-introduction overviews, physical source/revision/range views and exact composition of a legacy single-file revision for historical reads; `book_path_role`/`book_entrypoint_for` are the pure path question every consumer that must treat a chapter exactly as it treated the monolith asks instead of carrying its own chapter list; `validate_reference_books` runs on the tracked tree in the test suite (`tests/test_reference_book_validation.py`) and takes any candidate tree for preflight, so a missing chapter, an unlisted one or a lost authored introduction fails there rather than at the next review that assembles a book
      ├── local_model_server.py ← Read-only local formatter measurement and serving-process probe; uses the same tokenizer/template/context path as the local model without generating a reply or creating a second accounting attempt
      ├── context_compaction.py ← Atomic-unit compaction: exact checkpoint, gap-free map/fold, provenance capsules, transactional apply on the caller's basis; an unfinished Anthropic native unit is ineligible; opaque custody never enters summarizer text
      ├── context_health.py    ← Health invariants for the reading task (`build_health_invariants`; memory-maintenance lines surface an incomplete dialogue-knowledge publication and a failed last consolidation); delegated-run obligations stay globally visible — a preserved-and-invisible result is how work rots on disk — while the instruction is ownership-aware, so a non-owner is never handed a call that structurally refuses: it states the rule statically (owner-only while the owner task is live, a live top-level holder of the same target once it is terminal) and reads no per-orphan task result. The caller threads its own `active_root`, so when that root already satisfies the recorded target under the same predicate the apply gate asks (`delegate_shared.orphan_apply_target_ok`), the static rule is followed by the concrete `integrate_delegated_patch` call — one comparison over a value the caller already holds, still no per-orphan task result. `build_health_invariants` runs ONCE per task attempt from `build_llm_messages` (a wake-up is one such attempt), so the block is a task-start snapshot and does not refresh mid-task
      ├── context_runtime_facts.py ← The runtime section's FACT builders: what the host can honestly say it knows about this turn
      ├── headless.py          ← Child-drive isolation, workspace patch artifacts, memory export helpers; a sensitive-looking untracked credential is excluded per-file and disclosed as `sensitive_blocked`
      ├── headless_status.py ← Artifact and task lifecycle vocabulary shared by the headless owners
      ├── workspace_patch_rules.py ← Pure patch-exclusion rules (env/cache sets, junk regex, lockfiles, credential-shaped names); the I/O checks + `untracked_capture_veto_reason` stay in headless
      ├── workspace_patch_capture.py ← Workspace patch capture: the patch artifact, its manifest, and its git plumbing
      ├── coop_checkpoint.py   ← Quiescent checkpoint commits of cooperative trees (detected by supervisor/events.py, run off the drain thread): a tree qualifies only through a MUTATIVE child's `write_root` — owner-attached folders are never auto-committed; credential-shaped files excluded + disclosed; quiescence revalidated pre-mutation; a root whose owner is mid merge/rebase/cherry-pick/revert is SKIPPED with the operation named in its receipt (`skipped`), because staging an interrupted operation consumes its MERGE_HEAD and commits a half-resolved tree
      ├── delegate_output.py   ← Atomic staged full outputs under `delegated_runs/<run>.json` (sha256+length); `acknowledge_staged_output_read` hooks read_file's task_drive path; once-per-run `delegate_run_output_consumed` row — a disclosure, never a gate
      ├── delegate_directory.py ← Directory-result custody and explicit apply/discard projection for delegated file outputs; preserves manifest, source identities, binary artifacts and partial-delivery receipts through the existing artifact owner
      ├── workspace_file_outputs.py ← Capture and apply owner for ordinary-folder file results; records exact before/after identities, binary artifacts and retained unknown-preimage custody without a second workspace store
      ├── delegate_containment.py ← Engine-derived isolation facts: a home-isolation breach is exactly two facts (`harness_home_isolated: false`, or applied home == the operator's own); a home nested under `$HOME` is disclosed-unconfined (`home_nested_under_operator_home`), never relabelled as isolation; absence is reported unproven
      ├── delegate_progress.py ← Transport read bound + transient Git-object retry (`poll_bound`); renewal/wake policy lives in delegate_supervision; publishes event-local executor observations from the already-polled owned timeline, not a current-executor authority
      ├── nanny_pacing.py      ← Metered-silence pacing: only `BASELINE_RESET_TOOLS` (`delegate_start`/`schedule_subagent`) reset the burn; supervision verbs advance the round baseline while dollars accumulate — coordination never buys metered silence
      ├── delegate_interactions.py ← Child-interaction custody: reported-interaction memo, bounded display scalars with whole answer keys, typed `waiting_on_user` with an immutable spill file, strict `_delegate_answer` validation with typed rejections (`subscription_window_exhausted` carries `reset_at`; transport death/5xx is `delivery_unknown`)
      ├── delegate_shared.py   ← Shared delegate leaf (`_fail`/`_emit`/`_owned_run` — OWNED/FOREIGN/UNKNOWN from durable rows — plus `orphan_disposition_status`, the disposition-only OWNED upgrade for a terminal owner's orphan held by a top-level principal; `_owned_run` governs wait/cancel/answer and is deliberately NOT widened); one-way seam, facade re-exports
      ├── route_spec.py        ← Neutral route primitive: kind/target/pin normalization + effort validation; semantic owners keep their own spelling
      ├── configured_subagents.py ← Canonical `OUROBOROS_SUBAGENTS` parser/serializer: strict validation, stable ids, fingerprinting; owner free text is never host-parsed
      ├── subagent_runtime.py  ← Immutable task-start subagent snapshots, exact `subagent_id` selection, typed alternatives, bounded deterministic legacy-input seam
      ├── subagent_route_health.py ← Route health: the ONE manifest reader behind every delegated dispatch
      ├── subagent_work_order.py ← Complete chosen work-order compiler and normalized host authority without arbitrary admission cuts; exact-source readers and legacy source-response validation share the unchanged renderer
      ├── subagent_bootstrap.py ← Host pre-start of the exact snapshotted leaf BEFORE the first metered round, through the same wrapper as `delegate_start(prompt="")`; branch order recovery → fences → blocked → pre-start, and a fence-wake outranks every terminal because a fence may hide a live run; the host never waits (`configured_session_started` receipt); only a definite typed refusal ends unrun at $0 — everything ambiguous wakes the model, because a false "spent nothing" terminal over a possibly-live run is the one direction classification must never fail toward
      ├── delegate_supervision.py ← Event-only sleeping-nanny loop: quiet windows renew without a model call; terminal/interaction/fault/addressed/control (or one reasoned checkpoint) triggers a durable wake with fresh coordination context (parent intent, time, tree spend, host-visible descendants and root review capacity — every fact observed READ-ONLY, so a metadata-poor task reports `time.state = "not_set"` rather than latching an anchor from a poll; polling writes nothing of its own and inherits only the canonical usage-ledger reader's bounded maintenance — the torn-tail quarantine after a SINGLE crash mid-append, which every reader performs identically (a crash inside that repair itself, a torn quarantine sink, is a known residual: issue #586), the empty `state/` directory the reader's lock lives in on a never-initialized root, and recovery of `usage_attempts.lock` through the owner-aware kernel/inode rule in §1 Platform substrate — each pinned by a regression; an absent ledger answers known-zero settled spend through that same canonical reader); replay returns the stored snapshot
      ├── delegate_start_instructions.py ← Stable host start instructions + a complete separately-hashed coordination appendix; host pre-start sends no appendix
      ├── delegate_recovery.py ← Narrow exact-leaf recovery for proven crash + planned self-restart; validates bindings; vetoes every no-resume cause
      ├── delegate_registration_policy.py ← `persistent_registration` + the STARTED-row field tables
      ├── delegate_pending.py  ← Durable pending-invocation replay preserving the original idempotency key + canonical start body
      ├── delegate_terminal.py ← Terminal reconciliation + custody-audit persistence, split by surface: counters stay a frozen historical snapshot while `actual_substrate` and the envelope mirror are rewritten from live custody, so the executor chip reads live truth while history stays a snapshot; audit-only in both directions — unreadable custody proves nothing; review-owned rows and invocations are the panel's, never the task's open delegation; the custody notice is its own typed card row (`terminal_custody_notice`); `refresh_recently_settled_terminals` rides a durable byte-offset cursor (`state/delegate_terminal_refresh_cursor.json`, 5 MB per tick, deferred map for still-running parents)
      ├── subagent_dispatch_notes.py ← Dispatch-time executor notes for delegated children (configured-nanny charter note; non-configured branch keeps "decide your delegation plan first"); agent.py keeps re-exports
      ├── subagent_messages.py ← Bounded durable child-message identity shared by the final frame, recovery, compact persistence, and replay; `executor_observation_meta` separately validates/copies task-bound progress actor facts without changing final-lineage fields
      ├── subagents.py         ← Subagent envelopes + bounded legacy compatibility; `configured_subagent` snapshots dispatch through subagent_runtime
      ├── subagent_worktrees.py ← Worktree lifecycle + durable registry `state/subagent_worktrees.json` with ops lock and startup orphan reconciliation; `provision_genesis_project` (never registry/GC); execution snapshots pinned by `refs/ouroboros/delegated/`; standalone payload snapshots (CAS hash, writer-race abort); removal only explicit or custody-cross-checked startup GC — fail-closed: an unreadable custody log replays as "no open runs", so the prune skips entirely rather than destroy a child's only copy of its work (prune events are emitted at the server.py call site)
      ├── artifacts.py         ← Attachment staging into `artifact_store/attachments/` (secret-source skip, bounded, read_file manifest); artifact records exclude attachments + `chat_media/`; scratch fingerprints (`.scratch_manifest.json`, both roots) gate patch exclusion only while content matches; the undeclared-output guard stat-verifies post-exec; `delegated_capture_read_target` rebinds `delegated_runs/` reads to the canonical drive
      ├── retention.py         ← Unified GC retention SSOT: clamp/age-cutoff + legacy-key seed picker
      ├── workspace_preflight.py ← Read-only external-workspace git/manifest/toolchain snapshot used by gateway task creation
      ├── project_sources.py   ← Folder attach validation (realpath, not the home root, no repo/data overlap); opt-in `init_git`, NEVER auto-init; atomic server-side clone with `GIT_TERMINAL_PROMPT=0` and typed `auth_required`; provenance + `clone_url` recorded; attaching IS the trust grant (`trusted_at` automatic)
      ├── promotion_source.py  ← Promoted-task source admission off the event-drain loop, only after an executor/id reservation
      ├── workspace_admission.py ← Shared admission for `/api/tasks` + promotion: disjoint git root, Project binding, `workspace="none"`, bounded preflight, loud refusal of a broken binding; empty-Project promotion provisions idempotent genesis, and a failure is typed `workspace_provisioning_failed` on the promotion path (supervisor/workers.py) — never a fallback onto the system repo; `workspace_repair_hint` composes the model-facing cause + repair for every refused folder from its typed source
      ├── local_model.py       ← Local LLM lifecycle (llama-cpp-python)
      ├── local_model_autostart.py ← Local model startup helper
      ├── deep_self_review.py  ← Deep self-review of the whole system against BIBLE.md on the configured `deep_review` reviewer row (`reviewer_slot_config.deep_review_slot`; absent = the packed api row synthesized from `OUROBOROS_MODEL_DEEP_SELF_REVIEW`). THREE deliveries by the row's `retrieves` predicate. A direct api row is the PACKED review: deep-review atlas + the full memory whitelist on a ≥1M route → one `chat_observed` call, byte-identical on the wire to the pre-row review (golden digest test); a bounded in-prompt OMITTED section is reserved inside the fixed budget; `atlas_assembly_failed` (over hard budget, or a REQUIRED artifact omitted) ships no pack at all — the compact manifest is the atlas default, so there is no compact retry rung — and a final-shrink rebuild (tighter hard budget by the measured overage) precedes the gate, which remains the fail-closed last assertion; a required set that does not fit under a COLD density cap (no fresh exact-model witness — the refusal precedes every send, so the model could never record one) gets ONE bounded probe send on the exact model (the shared rung `capability_evidence.cold_start_density_probe`, the same one the commit gate runs: a slice of the real pack — `review_helpers.density_probe_sample` — `DENSITY_PROBE_MAX_TOKENS` output tokens, through `chat_observed`) that records the witness, then ONE rebuild under the recalibrated cap; a pack that still does not fit is the typed `deep_self_review_pack_unfit` refusal whose text asks the owner to switch the `deep_review` row to a retrieving delivery or a larger-window model — the host never falls back to another delivery on its own; centrality ranking (reverse in-degree) is deep-review-only. A configured-subagent api row is a NATIVE inspection episode and an `agent_session` row a delegated session, both through `review_execution._review_route_executor` exactly like the advisory: a hand-built `ReviewRequest(surface="deep_self_review")` whose route-owned task carries the role prompt, up to seven memory files inline byte-exact — EVERY whitelisted entry with its disposition (`inlined` / `missing` / `empty` / `oversized` / `read_error`) in the task's memory section, in the usage fact `deep_review_memory` and in the header (`memory=n/7`) — BIBLE.md as a MANDATORY full read and ARCHITECTURE/DEVELOPMENT/CHECKLISTS as `generate_doc_nav_map` navigation maps; `policy["output_contract"]` = the report contract plus the deep review's coverage-header sentence (the shape is `report` either way) and `policy["native_data_root"]` = the real runtime root (readable by the reviewer's tools; the memory whitelist itself arrives inline); a `ReviewSlot` with an explicit logical window (the task's absolute ceiling narrowed by the owner deadline); `record_reviewer_slot_executions("deep_self_review", …)` for «Выполняется как» — recorded on all three retrieving outcomes (responded, empty response, executor exception) from a usage that already carries `deep_review_memory`, which the returned usage keeps too (a typed failure included, together with the executor's failure custody); the durable execution projection itself persists route/model/status/capability_delta and typed failure facts only, never a deep-review-only field; prompt/response custody through `persist_call`. Every delivered report is prefixed by the host provenance header (`<!-- deep-review provenance: delivery, model, memory[, memory_missing/memory_empty/memory_oversized/memory_read_error], coverage, incomplete, attestation[, rounds, tool_calls, receipts, end_reason, transcript, landing — native only] -->` + one human line; every comment value AND every external value on the human line sanitized and bounded (`_header_value`); `incomplete` is derived per delivery — the native episode's typed `native_incomplete`, the packed call's provider stop marker — the OpenAI-compatible `response_finish_reason == "length"` or the direct-Anthropic message `stop_reason == "max_tokens"` — as `output_reserve`, a session's completeness `unobserved`); after a native episode BIBLE.md coverage (`read` / `partial(fraction)` / `missing` / `unobserved`) is derived by `_native_read_coverage` from the executed repository-root `read_file` receipts on the reader's `opened_path` and `opened_root` (contract and edge rules: its docstring and the «Deep self-review» section) and anything but `read` is disclosed in the header and as a typed `capability_delta`, never refused; a session's coverage is `unobserved`. Availability is route-aware (`deep_review_route`): the packed row keeps the ≥1M floor (a window CONFIRMED below 1M by the shared `reviewer_window` resolver is a typed refusal — the pack is never shrunk to a smaller window; an unknown window keeps the full-window assumption, disclosed as `window=assumed_1000000`) and the `OPENAI_BASE_URL` trust rule, a native row needs its model's credentials, a session row the substrate's `route_health`. Every failure returns TYPED usage (`execution_status=infra_failed` + reason code) so `agent.py` never overwrites `memory/deep_review.md` with an error
      ├── review.py            ← Repository size-ratchet inventory, code collection, and complexity metrics; official CI enforces the shrink-only module/function/byte ceilings while every local surface only warns (§6)
      ├── size_ratchet_manifest.py ← Generated data-only size-debt manifest (regenerated by scripts/regenerate_size_ratchet.py)
      ├── review_execution_projection.py ← Pure read-side reviewer-execution projection: bounded rows, 2000-char post-redaction string bound, unknown shapes ship as disclosed JSON; kinds `api` | `harness` | `native` — the native tool-round episode is an API execution with a different DELIVERY, projected as its own kind so the owner can tell a retrieving review from a packet review on the same model
      ├── preflight_runner.py  ← Hermetic pre-commit test runner: ONE hardened raw-bytes `git diff --binary … HEAD` capture, because a staged+unstaged diff pair cannot faithfully materialize unmerged entries; capture/apply failure is a typed `PREFLIGHT_CANDIDATE_ASSEMBLY` block, never a test verdict; node lane first, then the two-pass parallel/serial pytest split under one budget (`LANE_EXCLUSION_EXPR` is the marker-lane SSOT); a dead xdist worker or a missing required plugin is a distinct named block, never a retry or silent serial fallback
      ├── preflight_node.py    ← Content-keyed Node test lane: bundled signed node first then PATH, floor 20.11; typed `PREFLIGHT_NODE_MISSING`/`PREFLIGHT_NODE_TOO_OLD` hard blocks and `NODE_TESTS_FAILED` on a red suite, never a silent skip; both CI jobs mirror `cd web && node --test tests/*.test.js`
      ├── review_substrate.py  ← Review slot coordinator (the row-identity mint and paid stamp live in `review_dispatch.py`, the slot builders in `reviewer_slot_config.py`, the verdict reducers in `review_verdict.py` — all re-exported here): duplicate ids run as independent slots; per-actor records keep transport/parse/verdict/coverage/quorum/hashes distinct with a compact projection outward; acceptance enforces adaptive quorum, one substantive interaction per actor (≤2 physical sends on a packet row; one bounded episode on a native row; one delegated session on a session row — a retrieving row's verdict is equally authoritative, owner R1), provenance, and public-info anti-cheat; task acceptance and plan review follow each configured row's delivery kind (`api_chat` packet in-process, `agent_session` retrieving reviewer, a configured-subagent api row as the native episode) — task acceptance through the same `reviewer_slot_config.triad_delivery_slots` builder as plan and skill review (owner R2, 2026-09-01); a session's narrative is canonicalized by the surface's output SHAPE (`triad_review.review_output_shape`: `array` — bare `[]` or a findings array, so a clean verdict survives `empty_array_is_verified_clean` unchanged; `object` — the whole acceptance verdict; `report` — passed through verbatim, no schema asked); the delivery seam below it is owned by review_execution.py (§6 Review stack)
      ├── review_custody.py    ← Process-local physical review custody: independent deadlines, late-result settlement, stable retry identity, duplicate-dispatch suppression; not durable scheduling
      ├── review_owner_custody.py ← Paid attempts record `(server session, pid)`; confirmed owner-death batches skip irrelevant ledgers, share one event read off-lock, then reconcile the current locked state; live/delegated owners remain recoverable
      ├── review_execution.py  ← The ONE review-delivery seam below the substrate: closed route vocabulary with THE delivery-class predicate beside it (`delivery_retrieves(route, subagent_id)`: a hosted session or a configured-subagent api row retrieves the subject itself and never receives the packet — `ReviewSlot.retrieves`, `ConfiguredReviewerSlot.retrieves`, admission, packet fit and the surfaces' request builders all call this one definition), immutable `ReviewAssignment` bound once via `_review_route_executor`, the single physical seam `_execute_slot_attempt`, typed `ReviewAttemptResult`; no cross-transport fallback — a route that cannot deliver raises on its own slot (`ReviewRouteUnavailable`), and the durable prompt record and both physical sends share one byte-identical rendering; `ApiChatReviewExecutor` renders lazily and memoizes (digest-pinned); `AgentSessionReviewExecutor` runs one delegated read-only session — `outputSchema` is sent only when the route's own live manifest declares it and trusted only on `outputConformance == "passed"`, else strict parsing then light-model extraction disclosed as `capability_delta`; `review_output_contract(request)` is the ONE governance text every delivery honours (the api pack renders it into its byte-stable segment; a surface hands the same text to its retrieving rows as `policy["output_contract"]`), and `ROUTE_OWNED_POLICY_KEYS` (`output_contract`, `native_data_root`) are consumed by the retrieving executors and never rendered into the api pack's Policy JSON; per-row delivery via `OUROBOROS_REVIEW_ROUTES`/`OUROBOROS_SCOPE_REVIEW_ROUTES`, session target `OUROBOROS_REVIEW_SESSION_ROUTE` falling back to `OUROBOROS_SUBAGENT_HARNESS`; task acceptance follows its configured rows like every surface (owner R2). Disclosed residual (pre-existing release behaviour, b9bcc2da; issue #588): a compatibility transport that raises with positive physical capture invokes the paid stamp after the send; if the tree's last paid cycle is consumed concurrently at that late stamp, the wallet refusal replaces the captured exception and the substrate may resend
      ├── review_native_episode.py ← NativeToolRoundReviewExecutor: one read-only inspection episode for configured-subagent api rows, including advisory; window-derived transcript bound, owner deadline and paid ledger, no round cap. Host-observed read receipts and typed terminal custody keep retrieval distinct from assembled coverage (§6 Review delivery).
      ├── review_verdict_extraction.py ← Session/native verdict canonicalization: strict parse first, then light-model extraction to the review's own contract; branches on the surface's output SHAPE (`triad_review.review_output_shape`): `array` keeps the historical findings ladder; `object` (task acceptance) keeps the WHOLE verdict object on the schema, strict and extraction branches (an acceptance object is never reduced to its findings list, and `[]` is not a strict object verdict); `report` (deep self-review) passes the product through verbatim, never extracted
      ├── review_session_custody.py ← Exact delegated-review recovery validation + pre-POST durable invocation checkpoint; no scheduler or state store
      ├── review_slot_cancel.py ← Slot-cancel honesty: a cancel outcome reports only what it PROVED ("host-cancelled" only on a confirmed own-state receipt; confirmed failed/interrupted is attributed to the run's own terminal); a succeeded run whose result read fails is typed `ReviewSessionSucceededResultUnavailable` after one bounded retry, never "may still be live"
      ├── review_actor_aggregation.py ← Contract aggregation for completed review actor rows; demotes non-contract-valid responses
      ├── review_session_usage.py ← UsageScope-to-custody attribution for delegated review sessions
      ├── review_thread_continuity.py ← Thin Claudexor thread operations for delegated plan reviewers
      ├── commit_admission.py  ← Deterministic commit-admission SSOT: release checks + auto-sync, staged-Python syntax compile, `run_tests_preflight_with_proof` forwarding actual runner evidence to ordinary/managed consumers; the advisory and commit gates both delegate here; the disclosure-only `preflight_test_proof` row also carries `pass_seconds` (each executed pass's own wall clock, empty on a reused proof) and `budget_sec` (the resolved total timeout), since a green gate renders no pytest output to record it
      ├── reviewer_slot_config.py ← Structured reviewer-slot SSOT: stable ids, route targets, per-slot effort, disclosure-only execution records, save/runtime validation (`reviewer_slot_save_check`, whose only disclosure is the one-time R12 notice `acceptance_delivery_disclosure` when a save first makes the triad retrieve); a row is EITHER an inline route OR a `subagent_id` (materialized at load; unresolvable = typed refusal); `is_session` is transport while `retrieves` is delivery class; advisory shares the row vocabulary (+`enabled`, `disabled_reason`), and so does the optional `deep_review` singleton (fixed id `deep_review_slot_1`, no `enabled`; `deep_review_slot()` returns the saved row or the packed api row synthesized from the legacy `OUROBOROS_MODEL_DEEP_SELF_REVIEW` key, whose own effort outranks `OUROBOROS_EFFORT_DEEP_SELF_REVIEW` only when set); malformed config refuses EVERY surface — commit/scope/advisory/plan/skill review, deep self-review and task acceptance (owner R3); `triad_delivery_slots` is THE triad-row builder: plan review, skill/commit review (as aligned vectors through `commit_triad_delivery`) and task acceptance all read the rows through it, so no surface reads a projection of the panel instead of the panel; the legacy comma keys remain a runtime projection of api model ids for legacy consumers only
      ├── review_state.py      ← Durable advisory pre-review state (`state/advisory_review.json`)
      ├── review_state_model.py, review_state_records.py, review_state_custody.py, review_records.py, review_verdict.py, review_projection.py, review_evidence_sections.py ← The review ledger and its vocabularies, re-exported through `review_state.py`: the in-memory ledger and every transition it permits; the record types and the pure rules that shape them; durable custody of in-flight invocations plus attempt-history hygiene; the typed panel records and hardness vocabulary shared by every review surface; the pure reducers from panel actor rows to a verdict, a tier and a capsule; panel identity and the compact redacted projection of a run; and the bounded, provenance-tagged sections of the task-acceptance evidence packet
      ├── review_cycles.py     ← Shared paid-cycle cap SSOT (`OUROBOROS_REVIEW_MAX_CYCLES`, positive int or `unlimited`); the four per-gate meanings live in the module docstring (§10)
      ├── review_dispatch.py   ← Review row-identity mint + the write-ahead PAID stamp: typed pre-start refusals stay $0 while a late worker or crash cannot race away the durable paid fact; acceptance binds a strict exact-hash tree-wallet claim to that same stamp on every delivery its rows run — the API ledger transition of a packet row, each paid send of a native episode, `START_REQUESTED` of a session (owner R11: the paid identity is material, not route; one idempotent claim per panel); a wallet/cancellation veto at the claim releases the reservation (the launch floor is the loop gate's, evaluated once at admission; the R23 clamps bound a running panel), and, on the canonical paths, no reviewer transport proceeds on any row (the compatibility positive-capture path disclosed under `review_execution.py` — issue #588 — is the known exception)
      ├── reviewer_window.py   ← ONE typed `ReviewerWindow` per route (window/status/stale/observed_at + computed `blocking_authority_allowed`); metadata-only probe, per-route-locked, rate-limited by the evidence TTL — never a process-lifetime memo that would outlive the record; fail-closed sub-floor with no evidence; reserves scale to sub-1M windows
      ├── triad_review.py      ← Shared review primitives: JSON-array extraction (repo + skill), per-actor records, quorum/degraded accounting; owns `REVIEW_JSON_ARRAY_CONTRACT`/`REVIEW_JSON_MATRIX_CONTRACT`; a clean verdict is the WHOLE response `[]` (± one fence, ± `NO_FINDINGS`) — a refusal cannot be distinguished from a benign preamble by structure, so prose or a bare sentinel is a parse failure; the contract text lives beside `empty_array_is_verified_clean` so the two cannot drift; also owns `REVIEW_OUTPUT_SHAPES` / `review_output_shape(surface)` — the ONE form fact (`array` | `object` | `report`) the retrieving-route canonicalizer, the session output schema (`review_execution.review_session_output_schema`) and the strict parser branch on; shape is form only — acceptance rules, tier classification and quorum authority stay with their owners
      ├── onboarding_wizard.py ← Shared desktop/web onboarding bootstrap + validation (§2)
      ├── subscription_install_presets.py ← Pure sibling install compilers from one normalized draft + one discovery snapshot; output is linear, unpinned, exact-discovery-backed, all-or-nothing
      ├── settings_setup_contract.py ← SSOT for the setup contract, derived bootstrap state, payload validation, and the moved `TOTAL_BUDGET` resolver authority `resolve_total_budget_usd`
      ├── owner_mailbox.py     ← Per-task user message mailbox (compat module name); full revocation-aware drain and wait-local proven-empty peek; the closed task-message provenance set (`ancestor_task`, `peer_via_ancestor`, `system`, `descendant_task`, `independent_task`) and its render ladder
      ├── peer_roster.py       ← Host-listed independent roots as a worker reads them (owner 6C/6=A): pooled roots from `state/queue_snapshot.json`, direct roots from the supervisor's `direct_roots.json` fragment, hidden-partition roots included; the addressability gate `forward_to_worker` consults, and the `[INDEPENDENT_ROOTS]` TAIL note the round appends only when the roster changed (40 rows shown, the cut and any stale/unreadable projection disclosed)
      ├── launcher_bootstrap.py ← Bundle-to-repo bootstrap + managed sync helpers (used by launcher.py)
      ├── launcher_onboarding.py ← First-run onboarding as the desktop launcher presents it (serves the gateway /onboarding page; §2)
      ├── launcher_server_reaper.py ← POSIX same-install server discovery, pre-signal descendant capture, root-first termination, live identity revalidation, bounded survivor reporting; PID-lock-owning launcher only
      ├── launcher_windows_runtime.py ← Windows-only pythonnet/pywebview runtime preparation
      ├── provider_models.py   ← Model-ID helpers; the `ACTIVE_MODEL_SETTING_KEYS` vs `LEGACY_MODEL_SETTING_KEYS` split keeps Heavy out of startup/Provider Test/new consumers while migration/history still read it
      ├── runtime_mode_policy.py ← Protected-path policy (safety-critical files, frozen contracts, release/managed invariants) shared by the registry, git tools, and gateway guards
      ├── schedule_contract.py ← Schedule id, 5-field cron, IANA timezone validation SSOT
      ├── reflection.py        ← Execution reflection and pattern capture
      ├── post_task_evolution.py ← The worker writes a durable promotion signal; the supervisor idle tick applies it via the existing gated enqueuer (one-shot autostop); never enqueues from the worker, never fires from evolution/subagent tasks
      ├── repo_remotes.py      ← Role-based remotes: `managed` is the read/update-only official source; `origin` is the personal target auto-configured from the GitHub token
      ├── review_evidence.py   ← Same-execution commit-review source selection, redacted browser/vision calls and actual same-round image-attachment observations, with canonical source handles and exact pending reuse (§6, Git and commit review); bounded provenance-tagged task-acceptance evidence from effective task/plan claims, verification support, artifacts, tool trajectory, obligations, and retrieval facts; ingress claims win over the current closed plan wave, projected without mutating the live task contract; for harness-dispatched tasks the packet carries a host-attested `substrate_execution` section and the sibling `delegated_patch_dispositions` from delegate_evidence — VISIBILITY ONLY, zero typed rules tie substrate to the verdict: acceptance judges quality, never the execution route, and because `integrate_delegated_patch` has no review facts on its path the packet ATTESTS the apply rather than inventing a review
      ├── review_evidence_refs.py ← Leaf SSOT of the evidence-ref vocabulary + exact-membership resolver; unsupported claims cannot certify (`CLAIM_ID_UNSUPPORTED`)
      ├── review_status_projection.py ← Leaf commit-review status projection over `review_state` records (`build_review_projection` / `build_review_status_payload` and the typed run-failure reason renderer); re-exported by `review_evidence` so the historical import sites keep resolving
      ├── semantic_dedup.py    ← LLM-first semantic dedup, fail-open None; consumed by improvement_backlog + review_state
      ├── betterleaks_runtime.py ← Pinned Betterleaks runtime resolver (six platform artifacts, packaged-resource-first)
      ├── skill_loader.py      ← Skill discovery over `data/skills/{native,clawhub,ouroboroshub,external}` + `OUROBOROS_SKILLS_REPO_PATH`; `.self_authored.json` marker; per-skill state under `data/state/skills/<name>/`
      ├── skill_readiness.py   ← Execution readiness and phase-specific next actions from review, hash, enablement, grants, dependencies and peer conflicts; acceptance also exposes actual loaded revision/state without inferring a passed functional test
      ├── skill_dependencies.py ← Shared dependency-spec resolution and installed-readiness probe for skills
      ├── skill_repair_admission.py ← Selected-skill development admission: immutable `base_content_hash` and observed `expected_content_hash`; verify before each payload operation and advance after opaque process work with attribution unproven, without a long shell lock or rollback
      ├── skill_owner_attestation.py ← Owner attestation lane: the owner may skip the expensive LLM skill review for skills they authored themselves
      ├── skill_publish_snapshot.py ← Immutable captured-byte authority for publication
      ├── skill_publish_scanner.py ← Exact-byte Betterleaks evidence; publication applies the mode policy in §6
      ├── skill_publish_result.py ← Typed publish attempt/receipt + finalization veto
      ├── skill_publish_github.py ← GitHub publication transport after the local gates
      ├── skill_publish_eligibility.py ← Passive publish visibility + `task_start_allowed`
      ├── skill_review_status.py ← Verdict aggregation → `executable_review` (anchors the §13 readiness statuses); current Advisory author acceptance may remain valid while the original critic hash/status is stale, while Blocking requires fresh critic authority
      ├── skill_review_passes.py ← One multi-model pass or chunked quorum; reserves the complete operation roster before dispatch, rejoins exact logical waves from lifecycle history, and binds process-local custody to wave/chunk rather than a restart index
      ├── skill_review.py      ← Skill review orchestration: preflight + advisory critic via `run_advisory_critic`; tri-model gate against the Skill Review Checklist (docs/CHECKLISTS.md) + docs/CREATING_SKILLS.md
      ├── skill_review_prompt.py, skill_review_packs.py, skill_review_output.py, skill_review_rebuttals.py ← The skill reviewer's leaves: its prompt contract, governance context and waves; the reviewable payload — what a reviewer may see and how much of it; the parsed findings, aggregate verdict and rendering; and the review-history evidence a reviewer reads before re-judging
      ├── skill_review_history.py ← Write-ahead review-history marker (`physical_attempt_v1`) and idempotent `state/skill_review_root_tasks.jsonl` projection; append failures emit typed `skill_review_history_append_failed`
      ├── skill_review_cycles.py ← Paid skill-review cycle counting, exact prior-wave selection, $0 replay and typed exhaustion; shared cap SSOT is review_cycles.py
      ├── extension_loader.py  ← Extension loading: in-process pure-Python via `PluginAPIImpl`, child-process proxies for isolated-dep/native extensions
      ├── extension_process_runner.py ← Extension child processes: scrubbed env, per-skill deps, timeouts, graceful host errors
      ├── extension_route_stream.py ← Portable stdio response frames and ASGI relay; child standard responses retain headers/HEAD/Range/background work, parent backpressure and exact-bundle cancellation use the existing runner process owner and supervised_futures
      ├── extension_ui_validation.py ← The one host-owned declarative-schema-v1 widget validator
      ├── extension_isolated_deps.py ← Legacy/forced in-process bridge for isolated-dependency extensions
      ├── extension_health.py  ← Durable process-qualified per-skill health at `data/state/skills/<name>/health.json`; server observation is authoritative, worker observation is a handoff-qualified view
      ├── extension_plugin_api.py, extension_registry_state.py, extension_liveness.py, extension_child_catalog.py, extension_import_staging.py, extension_surface_names.py ← The extension runtime's leaves: the `PluginAPI` object handed to one extension's `register(api)`; the process-wide registries of the surfaces live extensions own; the liveness authority for one extension (what it should be and what it is); host-side validation of the surface descriptors a child catalog run returns; the staged import trees for in-process extensions and their reclamation; and the provider-safe naming and syntax rules for extension surfaces
      ├── skill_token.py       ← Opaque Host Service token minting/validation (§12)
      ├── marketplace/         ← ClawHub + OuroborosHub: `clawhub.py`, `ouroboroshub.py` (hub update via adopt transaction with VERIFIED `rolled_back`/`rollback_errors`, `.pre-adopt` retention disclosure), `fetcher.py`, `adapter.py`, `install.py`, `install_specs.py` (normalized third-party dependency install metadata for bounded per-skill prefixes), `isolated_deps.py`, `provenance.py` (+ publication receipt `state/skills/<n>/ouroboroshub.json`)
      ├── skill_lifecycle_queue.py ← Single FIFO skill-mutation lane + event snapshot (§13)
      ├── skill_lifecycle_actions.py ← Shared grant/toggle effects and owner-action admission for UI, launcher, CLI and task adapters; existing chat/quiz/mailbox source resolution, exact target/revision, no new permission store
      ├── skill_uninstall_state.py ← Marketplace-uninstall tombstones and explicitly authorized local payload/state deletion; separate operations with separate retention contracts
      ├── skill_review_runner.py ← Writes `review_job.json` + `skill_review_*` events; separate review, dependency and process-qualified extension outcomes; unchanged verdict replay can resume dependencies without another panel or overriding owner disable
      ├── server_auth.py       ← Non-localhost network gate via `OUROBOROS_NETWORK_PASSWORD` (warns when unset; see §8 packaging note)
      ├── server_control.py    ← `restart_current_process` + `execute_panic_stop`
      ├── server_entrypoint.py ← CLI parsing + port binding helpers
      ├── server_runtime.py    ← Startup/onboarding wiring + WS liveness
      ├── server_web.py        ← `NoCacheStaticFiles`, web-dir resolver and fixed-source `read_author_kit_assets(repo_dir)` for optional author-owned routes; no endpoint or cache
      ├── server_process.py, server_liveness.py, server_maintenance.py, server_restart.py, server_owner_routing.py, server_routing_context.py ← Server leaves the composition root calls: the facts one server process shares with every leaf; wedge detection for the supervisor generation; the upkeep a generation owes the drive; the restart-adjacent helpers used at shutdown, the owned-work stop of the owner's manual Restart and the planned restart's engine-pin daemon stop; where one owner message goes; and the bounded facts one owner turn is allowed to address
      ├── task_continuation.py ← Durable review continuation state
      ├── task_results.py      ← Durable task results `task_results/<id>.json`; locked `task_acceptance_review_accounting` — the claim is minted at first physical reviewer dispatch, and a claim without a recoverable terminal host run is UNKNOWN, never permission to re-dispatch (double-spend fence); its read-only root review-capacity projection for configured-session wakes is WALLET and cancellation only (`root_task_id`, `cap_cycles`, `claimed_cycles`, `remaining_cycles`, `binding_seen`, `dedupe`, `state`, `reason` — no time axis: the launch rule `task_pacing.review_launch_allowed` is evaluated once per panel at loop admission (owner R55; the paid claim inside the dispatch stamp checks cancellation and the wallet only), and a descendant reads its own window from the coordination `time` fact)
      ├── task_result_schema.py ← Task-result schema admission: the `_schema_version` stamp, the classifier, and the quarantine an unstamped, future, malformed or retired-key row lands in
      ├── task_status.py       ← Effective-status SSOT, lineage, bounded waits; worker-side `task_has_live_queue_ownership` (§10, cancellation custody); the DESTRUCTIVE orphan predicate keeps the same fail-open-toward-liveness polarity — an in-process direct actor (`supervisor.active_activity` registry, deliberately absent from PENDING/RUNNING) and a missing/invalid/stale queue snapshot can never prove a task dead
      ├── git_shell_policy.py  ← Structural git argv classifiers for the shell guards
      ├── protected_artifacts.py ← Execute-only black-box policy for protected artifacts
      ├── shell_parse.py       ← Shared command/argv normalization and POSIX wrapper grammar; retained inspection helpers supply observed targets, not semantic permission judgments (§6 Safety and runtime mode)
      ├── argv_budget.py       ← Argv admission counts encoded bytes of argv PLUS environment (ARG_MAX charges both; per-arg `MAX_ARG_STRLEN`, Windows unit limit); asked by skill_exec before exec
      ├── workspace_executor.py ← Workspace process backends: `local` and network-none `docker_exec`
      ├── deliverables_paths.py ← Lexical + case-folded deliverables path views
      ├── tool_capabilities.py ← SSOT for the core/parallel-safe/untruncated/stateful-browser tool sets and the cognitive-memory tool class every Presence ceiling carries
      ├── tool_access.py       ← ToolProfile × ResourceRoot × Operation matrix, affordance map, closed-enum `required_capabilities` check
      ├── tool_access_types.py, tool_access_roots.py, tool_access_paths.py, tool_access_user_files.py ← The access matrix behind that facade: the closed access vocabulary and the profile × root × operation policy matrix; who is acting and where each resource root physically lives; the physical path primitives; and the `user_files` confinement with its secret-name policy and path resolution
      ├── tool_policy.py       ← Round-one tool visibility (the sets live in tool_capabilities)
      ├── browser_policy.py    ← The browser tool's target and control-request policy: task-granted concrete origins, metadata/private/reserved refusals, and the three-valued Ouroboros control-service identity (`runtime_service_kind`: proven kind / unknown / none) that both the URL decision and the owner-operation request shapes consume; `tools/browser.py` keeps the Playwright lifecycle (§6 Web access mechanisms)
      ├── skill_payload_binding.py ← Skill payload targeting: `.seed-origin` distinguishes native vs external; read/list/search only for read profiles; bounded manifestless skill_publish recovery
      ├── utils.py             ← SSOT for atomic JSON, timestamps, hashes, sanitization, subprocess helpers, `truncate_review_artifact`
      ├── markdown_source.py   ← `ouroboros/markdown_source.py`: byte-preserving Markdown structure shared by books and knowledge notes; physical LF/UTF-8 ranges and authored metadata/links stay tied to source SHA, while lazy per-source native parsers and `MarkdownSourceError` keep missing grammars or malformed YAML visible without breaking context import or replacing original bytes
      ├── world_profiler.py    ← Generates WORLD.md
      ├── contracts/           ← Frozen ABI package (§11)
      │   ├── tool_context.py  ← ToolContextProtocol
      │   ├── tool_abi.py      ← ToolEntryProtocol + GetToolsProtocol
      │   ├── chat_id_policy.py ← SSOT for human-visible vs synthetic chat ids (§12)
      │   ├── task_contract.py ← Frozen task-contract normalization and effective acceptance-claim binding (semantics: §11.1)
      │   ├── task_constraint.py ← `VALID_WRITE_SURFACES` + surface/write_root validation, fail-closed
      │   ├── skill_payload_policy.py ← Payload path resolution/confinement/sidecar detection
      │   ├── skill_manifest.py ← Unified skill manifest parser (`VALID_SKILL_TYPES`: instruction|script|extension)
      │   ├── schema_versions.py ← Opt-in `_schema_version` stamping helpers (§11.2)
      │   └── plugin_api.py    ← PluginAPI, ExtensionRegistrationError, FORBIDDEN_SKILL_SETTINGS, VALID_EXTENSION_PERMISSIONS, VALID_EXTENSION_ROUTE_METHODS
      ├── gateways/            ← Thin outbound transport adapters; no business logic
      │   └── claudexor.py     ← Loopback daemon client: discovery (`discover_daemon_at` reads `<config_dir>/daemon/control-api.json`), handshake, runs, cached quota GET + explicit quota POST; the token stays inside; account-surface translations are read-only; prefers the OWNED daemon via `claudexor_daemon.owned_daemon_provisioned`
      ├── claudexor_runtime.py ← Reviewed engine pin (version/SHA/URL/SHA-256/size/protocol/Node/entrypoints, nullable CLI): seed-or-download, verify + staged extract + probe + atomic promote under `data/state/cx`; no mutable `current` pointer or background updater — the reviewed pin IS the next-spawn selection, and a `null` CLI honestly identifies a pre-CLI closure; read-only resolvers; `OUROBOROS_CLAUDEXOR_BIN` stays an explicit operator override
      ├── claudexor_daemon.py  ← Installation-owned Claudexor lifecycle over `data/claudexor`: lazy first use from worker/server, authenticated attach, purpose-bound startup custody and independent startup/admission waits; `stop_outcome` owns explicit same-home CLI shutdown and measured/Popen fallback (§9). Atomic ownership marker publication, metadata-only runtime status, provisioned warmup through the same ensure, the start-failure spawn latch (§9), and `install_missing_harness_cli`
      ├── claudexor_startup_failure.py ← Typed vocabulary of a failed owned-daemon start (#844): `ExitFact` (exit code/signal plus the descriptor fact; `failed_without_control` is the spawn-latch predicate), the diagnostic-only classification of the child's OWN log interval (`heap_exhausted` | `writer_lease_contended` | `engine_floor` | `unclassified`), the latch record, its refusal text and the two supervisor-row shapes; stdlib only — never spawns, stops, waits or reads more than that interval (§9)
      ├── gateway/             ← Gateway Boundary v1: browser-facing route ownership + frontend contract SSOT (see below)
      │   ├── contracts.py     ← Active WS/HTTP envelope contract owner
      │   ├── decision_contracts.py ← Typed request/response contracts for decision families, re-exported by contracts.py; each ingress owns runtime validation
      │   ├── endpoint_index.py ← `HTTP_ENDPOINTS` index (re-exported by contracts.py); routers own the Route objects
      │   ├── schema.py, task_list_scan.py ← The executable gateway contract — JSON Schema derived from the TypedDicts, validating ingress — and the stat-invalidated compact result facts shared by list ordering, SSE discovery and Main routing
      │   ├── router.py        ← Starlette route collector for /api/* and /ws
      │   ├── ws.py            ← WS manager, extension WS dispatch, broadcast
      │   ├── state.py         ← /api/health + /api/state
      │   ├── tasks.py         ← Headless task create/list/get/cancel/events; cancel accepts `stop_policy` (empty = immediate; `finalize_then_cancel` → 202 + open intent → supervisor/owner_stop.py; unknown → 400)
      │   ├── task_events.py   ← Task-event SSE endpoint: legacy GET ranks plus read-only POST v2 physical-chain cursors
      │   ├── task_hurry.py    ← POST hurry ingress: exact one-field `{request_id}` body — extra fields refused, because hurry carries no text by design and a smuggled field must not become a side channel; queue-owned admission atomically initializes an absent pooled lifecycle through task_results.write_task_result(create_only=True), preserving existing rows and excluding direct turns; idempotent projection (semantics: owner_hurry.py)
      │   ├── task_decision.py ← ONE `POST /api/decisions` ingress with family-parsed ids (`quiz:` here, `routing:` → routing_decision.py, `interaction:` reserved); writes `KIND_QUIZ_ANSWER`, broadcasts `quiz_state` (lifecycle: owner_quiz.py; ABI: §11.1)
      │   ├── task_model_wait.py ← Shared model-wait decision effects over the existing mailbox, with live-owner/revision checks, optional role persistence and history-row projection
      │   ├── routing_decision.py ← Validates a click against the durable `needs_manual_target` row, recovers the original text, dispatches the existing `steer_task`/`promote_chat_to_task`, confirms through routing_wait receipts; replay-stable derived identities
      │   ├── logs.py          ← Read-only runtime log tail
      │   ├── onboarding.py    ← `POST /api/onboarding/complete`: install-time latch, shared validation, live engine read, preset compile, single settings write under lock through the shared bounded writer seam; a typed 503 persists nothing (§2) — except 503 `settings_save_timeout` (`saved: null`), the seam's unknown outcome
      │   ├── onboarding_host.py ← GET /onboarding: side-effect-free wizard page served as ES modules
      │   ├── owner_settings.py ← Settings-lock-as-precondition + `CommitBoundary`
      │   ├── settings.py      ← /api/settings + /api/owner/*; `GET /api/reviewer-slots` with row limits (triad 10 / scope 4 / advisory 1 / deep_review 1) and typed `config_error`, never a 500; the response carries the deep self-review singleton — the saved `deep_review` row, or the packed api row synthesized from `OUROBOROS_MODEL_DEEP_SELF_REVIEW` labeled `synthesized_from` so the editor can say it is not saved yet — attached beside a `config_error` too as the legacy-derived repair placeholder, never an effective row (none is effective until the malformed setting is repaired; `deep_review_slot()` raises)
      │   ├── presence_settings.py ← Owner-facing runtime overrides and working-folder selection for reviewed Presence behavior skills
      │   ├── control.py       ← /api/reset, /api/command, /api/git/*, /api/update/*, /api/evolution-data HTTP handlers
      │   ├── update_progress.py ← Process-local stages owned by the synchronous update executor; status projection and WS invalidation, never recovery authority
      │   ├── schedules.py     ← Cron schedule HTTP surface
      │   ├── files.py         ← File Browser + chat upload
      │   ├── ui_preferences.py ← `state/ui_preferences.json`: widget order, per-card widget start-mode overrides (`widget_start_mode`, values from `extension_ui_validation.WIDGET_START_MODES`), nested subagent expansion
      │   ├── models.py        ← Model catalog + provider probes + local-model lifecycle
      │   ├── extensions.py    ← extensions/skills HTTP surface (GET /api/extensions, GET /api/extensions/<skill>/manifest, GET /api/extensions/<skill>/module/<entry:path> — reviewed module sources served from the live loader registration, ALL /api/extensions/<skill>/<rest:path>, POST /api/skills/<skill>/toggle, POST /api/skills/<skill>/delete, POST /api/skills/<skill>/review, POST /api/skills/<skill>/grants)
      │   ├── extension_receipts.py ← Process-qualified extension index/toggle/reconcile receipt projection
      │   ├── widgets.py       ← GET /api/widgets: the Widgets card list projected from the in-memory extension snapshot (live UI tabs + the owning skill's live payload `content_hash` as `revision`) with no discovery, reconcile, hashing or writes on the read path; homes the `WidgetTab`/`WidgetsResponse`/`ExtensionLiveSnapshot` TypedDicts that `gateway/contracts.py` re-exports, importing no transport at module level
      │   ├── skill_publish.py ← Read-only publish preflight with scan cache; one five-state response; no task or GitHub effect
      │   ├── marketplace.py   ← ClawHub + OuroborosHub HTTP surface
      │   ├── mcp.py           ← MCP HTTP surface backed by the shared MCPManager
      │   ├── claudexor_accounts.py ← Agent accounts HTTP surface (Settings → Agents → Accounts): six thin proxies — counted by HANDLER, two serving more than one route or action — over the owned daemon's account truth: GET /api/claudexor/status[?include=models] (side-effect-free daemon/runtime state + harness catalog + credential profiles + quota windows, each facet stamped with its read state; the additive `unified_accounts` feature fact reads the engine's own /v2/operations catalog — `get:account-pools` present = the unified account model, an unreadable catalog fails closed to the legacy rendering); POST /api/claudexor/wake (owner-initiated daemon start); POST /api/claudexor/login (one Connect intent: install/repair the managed runtime, start or attach the owned daemon, create or re-adopt its setup job; a structural `not_supported` missing-binary create response invokes `install_missing_harness_cli` — claudexor_daemon.py owns the whole operation — and creates the same login job exactly once more); GET/DELETE /api/claudexor/login/{job_id} (canonical snapshot/cancel); POST /api/claudexor/login/{job_id}/input (the owner's answer to a waiting engine prompt); POST /api/claudexor/login/{job_id}/reconcile (explicit proof-of-empty after `termination_unconfirmed` — a terminal job is not automatically release proof: custody holds until reconcile records `status=empty`); DELETE/PATCH /api/claudexor/credential-profiles/{harness}/{profile_id} (one route, two row actions, the engine's strict `{enabled}` body passed through). Zero auth logic and zero vendor recipes live here; the browser never sees the daemon token; the `{job, cursor, sequence, deviceCode?}` envelope passes through verbatim; `harness_login_cards.jobDetail()` renders the escaped untruncated message only beside a settled non-success verdict
      │   ├── claudexor_quota.py ← Explicit owner quota-refresh transport: POST /api/claudexor/quota/refresh discovers the already-owned daemon, performs the mandatory handshake (ordinary 60 s control-plane read bound), and delegates exactly once to the engine's quota POST (90 s foreground bound); the envelope returns verbatim; no lifecycle start, cached status composition, quota policy, retry, or daemon token crosses this boundary; GET /api/claudexor/status stays passive
      │   ├── host_service.py  ← Loopback-only Host Service API (§12)
      │   ├── history.py       ← Shared Chat room/quiz/media/review/terminal projection + cost breakdown factories
      │   ├── history_contracts.py ← Descriptive paged Chat history response, re-exported by contracts.py
      │   ├── history_paging.py ← Physical range selection over retained chat/progress JSONL chains, frozen room-bound page/continuation cursors and read gaps; no stored history copy
      │   ├── cost_breakdown.py ← Ledger-derived dashboard buckets and root-task detail breakdown over the same physical-attempt authority; `history.py` and `tasks.py` keep their historical import seams
      │   ├── projects.py      ← GET/POST /api/projects, /from-task, /update, /delete
      │   └── _helpers.py      ← Shared request-root/coercion/JSON error envelope and `run_sync_to_completion`, the settled worker wait for request-owned blocking work
      ├── tools/               ← Auto-discovered tool plugins (registry.py owns discovery; frozen module list for packaged builds)
      │   ├── registry.py      ← Tool registry SSOT: loads tool modules, exposes schemas, executes safely; owns the shell-guard/process-tool membership sets
      │   ├── core.py          ← File/data tools (read_file, write_file, list_files) + code search and digest helpers
      │   ├── core_file_tools.py, core_secret_paths.py, core_artifacts.py ← Core-tool leaves: the read/list file tools with the shared resource-access helpers, and the verbs a task uses to put something in front of a human; `core_secret_paths.py` owns the restricted-subagent physical read-denial policy (owner secrets/control state, child and canonical data roots, repository credential locations, listing redaction); list/search/query prepare shared locations once per call while target resolution and file identity remain live
      │   ├── shell.py         ← Process tools `run_command`/`run_script` (in-process `_active_subprocesses` tracking; §9)
      │   ├── shell_guards.py  ← Shared process-path inspection helpers and retained target extractors; process admission is owned by registry_guard_process (§6)
      │   ├── registry_core.py, registry_guards.py, registry_guard_process.py, tool_context.py ← The registry's leaves: the execution authority (load modules, expose schemas, dispatch safely); the host-owned pre-dispatch guards (capability/resource, managed-update and skill-payload constraints); and process admission over the prepared target, explicit task resources and selected Supervisor coverage, with post-execution observations (§6); and `ouroboros/tools/tool_context.py`, the concrete `ToolContext` + `BrowserState` imported by `registry.py` and `registry_core.py` (the protocol it satisfies is `contracts/tool_context.py`)
      │   ├── git.py           ← Git/write tools with the advisory, triad, and scope review commit gates (§8)
      │   ├── git_plumbing.py, git_repo_edit.py, git_vcs_ops.py, git_review_cycle.py, git_evolution.py ← The git tool's leaves, re-exported by the facade: the low-level plumbing shared by the git owners; the uncommitted repo write and exact-match edit surface; generic VCS inspection and rollback; staging plus the advisory/triad/scope review and reviewed-material binding the commit gate consumes; and evolution-campaign authority at the reviewed-commit and publication boundaries
      │   ├── search.py        ← Web search tool (OpenAI Responses API, LLM-first overridable defaults)
      │   ├── browser.py       ← Playwright browser tools with per-ToolContext lifecycle and thread affinity (§6)
      │   ├── vision.py        ← Vision LLM tools for browser screenshots and uploaded images
      │   ├── vision_process.py ← Tracked vision-child IPC: validated model/physical-attempt receipts, result recovery and parent-owned cancellation
      │   ├── knowledge.py     ← Persistent topic-based knowledge files with an auto-maintained index
      │   ├── memory_tools.py  ← Memory registry tools for tracking data sources, gaps, and trust
      │   ├── health.py        ← Codebase health tool: complexity metrics and self-assessment
      │   ├── compact_context.py ← LLM-requested tool-history compaction trigger; stores the pending request for the next round
      │   ├── control.py       ← Control tools: restart, timeout settings, scheduling, review, chat history, model switching; publishes the strict `subagent_id`+objective `schedule_subagent` contract, and `wait_task` emits the burst/absorb advisory and compact wait projections (§6)
      │   ├── control_delegation.py ← Delegation-budget and in-task project-scoping affordances (`ensure_project_scope` handler)
      │   ├── control_events.py, control_routing.py, control_runtime.py, control_scheduling.py, control_subagent_spec.py, control_task_results.py ← The control tools' leaves: emitting one control event and waiting for its durable handler outcome; routing real work out of a conversation lane into a supervised task; runtime self-control (restart, promotion, evolution, memory — identity and scratchpad written to the canonical root from every room, model); scheduling one live subagent — what the parent asked for and nothing else; the published `schedule_subagent` parameter surface and its validation; and absorbing a child — reading one result, or waiting on a batch of them
      │   ├── tool_discovery.py ← Tool-discovery meta-tools: confirm registration, no delayed capabilities
      │   ├── tool_result.py, tool_catalog.py, tool_resolution.py ← Dispatch-side vocabulary: the typed internal tool result with its byte-compatible legacy text adapter (the producer stamps outcome facts; a note append degrades rather than rewrites); the intrinsic tool descriptors shared by tool modules and registry dispatch; and argument normalization with physical target binding
      │   ├── review_response.py ← Pure response-envelope projection for multi-model review rows
      │   ├── shell_process.py, shell_effects.py, shell_outputs.py ← The command-running substrate: the process execution shared by every command tool; what a command did to its working tree and which of it was throwaway; and declared process outputs — resolution, fingerprints, artifact registration, and the per-path export-eligibility rules that reuse the workspace-patch credential-shape SSOT
      │   ├── plan_review_artifacts.py ← Exact plan-review waves and full operative specs in existing source handles, bounded successor index, and reviewer-continuation inputs; reconstructs the API transcript
      │   ├── evolution_stats.py ← Generates evolution.json metrics from sampled git history
      │   ├── owner_delivery.py ← Owner event delivery: live queue XOR `pending_events` fallback with sticky deferral, preserving narrative order after the first live failure; lineage stamped
      │   ├── deliverables_shell.py ← cp/mv/ln into deliverables with symlink checks
      │   ├── shell_audit.py   ← Post-exec custody audit for process tools
      │   ├── process_facts.py ← Typed process-fact seam consumed by loop_tool_execution for the same call; the regex harvest stays a read fallback
      │   ├── write_shape.py   ← Retained interpreter/non-interpreter syntax helpers; process permission is owned by the task/resource and Supervisor contract in §6
      │   ├── extension_dispatch.py ← Extension tool dispatch (contracts preserved; discovery stays in registry.py)
      │   ├── release_sync.py  ← `sync_release_metadata` (version carriers) used by commit-admission preflight; `_preflight_check` uses `check_history_limit`; agents may call it directly; the carrier-span SSOT (`VERSION_CARRIER_SPANS`, `substitute_carrier_spans` — the ONE span primitive the managed-update resolver and the commit-triad pack cut share — and the `carrier_only_change` predicate: a carrier changed only inside its declared version spans)
      │   ├── review_synthesis.py ← Shared synthesis helpers; the parser/aggregator lives in plan_spec.py
      │   ├── ci.py            ← CI trigger/monitoring
      │   ├── claude_advisory_review.py ← `preflight_review` with the callable `advisory_review` compat alias; admission policy lives here; api_chat rows ride review_native_episode, agent_session rows ride the AgentSessionReviewExecutor; a native episode that ends on its own transcript bound reaches the caller as the typed non-blocking `ADVISORY_SKIPPED: native_transcript_bound_exceeded` (keyed on the episode's structured `native_transcript_cap_exceeded` code, never on message text; not the provider window vocabulary) carrying the bound, the refused chars and the paid rounds, and every episode exception keeps `failure_custody()` as the advisory meta's `usage` (never an empty `{}`); on the native route the documents the prompt's MANDATORY FULL READ pointers name are measured from the files at prompt-build time (`preflight_review_prompt._mandatory_read_corpus_chars`, wire chars) and declared to the episode as its mandatory reading, so the bound is lifted to hold them when the advisory model's window allows and otherwise the prompt's MANDATORY READ budget section and the usage both carry the typed `native_mandatory_read_exceeds_bound` — never a silent full-read contradiction
      │   ├── preflight_review_prompt.py, preflight_review_run.py ← The preflight (advisory) pre-review: prompt assembly with its git captures, and the run with its result parsing; its changed-context pack applies the shared span-only release-carrier cut over the pair the advisory reviews — HEAD→working tree, the text the pack reads — with the same `PACK EXCLUSION NOTE` (the native episode keeps `read_file` for a withheld carrier)
      │   ├── recent_tasks.py  ← Read-only context recovery
      │   ├── commit_gate.py   ← Commit gate: `_record_commit_attempt` (LLM claim synthesis), `classify_review_block`/`attempt_block_class`, `check_identical_verdict_refusal`, `count_paid_review_cycles`/`check_review_cycles_ceiling`, `commit_review_contract_fingerprint`
      │   ├── git_rollback.py  ← Wraps `git_ops.rollback_to_version`
      │   ├── git_pr.py        ← Five PR tools (non-core)
      │   ├── github.py        ← Issue + PR tools (frozen tool module): shared process binding selects the active Project; explicit repo flows through every subcall; missing implicit Project targets fail visibly. Discovery reads token sources or native CLI configuration without an authentication probe; explicit Hub/API transport retains its own target. `_gh_run` is the structured transport read (exit code, bounded redacted stderr head, observed HTTP status, failure class) that `_gh_cmd` projects onto the string ABI; the transport publishes only its own target refusals (`GH_TARGET_INVALID`/`GH_TARGET_REQUIRED`) into the tool-result sidecar; a process outcome publishes nothing there, because the publication transaction owns its own final result.
      │   ├── parallel_review.py ← Triad + scope review orchestration: assembly of both packets, the money admission call (`review_admission.py`), the scope-first hold, and the executor transitions that carry the admitting usage scope (`contextvars.copy_context`) into every seat
      │   ├── plan_review_references.py ← Reference projection that also writes its own provenance rows (`append_jsonl` into `logs/progress.jsonl`, `emit_log_event`), never a second plan authority
      │   ├── plan_review.py   ← `plan_task` engine: evidence, packet, fan-out over the review substrate, `plan_review_state` v2, the shared `OUROBOROS_REVIEW_MAX_CYCLES` cap, free identical replays; no scouts, Atlas, or plan_class
      │   ├── plan_review_runtime.py ← Plan-review deadline rail, `ReviewSlot` rows, `plan_slot_fit` + `preflight_oversize`, health snapshot + `plan_wave_replay_decision`, `plan_review_advisory_open` emitter
      │   ├── plan_review_collect.py ← The event route's collection side: the per-slot settlement progress line and the ONE system mailbox frame the last released slot writes, plus the $0 collection of an open wave through the engine's own resume path (drain window 0; reconcile-before-supersede); no wave state of its own
      │   ├── plan_spec.py     ← Pure plan-spec parsing/aggregation (`resolve_constitutional`); no I/O
      │   ├── plan_evidence.py ← Bounded plan-evidence manifest; the runtime data plane is denied
      │   ├── plan_packet.py   ← Reviewer packet; the governance pack inlines BIBLE + ARCHITECTURE in full for self-modification plans, nav maps otherwise
      │   ├── plan_render.py   ← Wave view + `PLAN_REVIEW_CONTROL_JSON` footer; no independent behaviour
      │   ├── review.py        ← Acceptance review + multi-review adapters
      │   ├── review_multi_model.py, review_file_pack.py, review_prompt_text.py ← Commit-triad leaves: the sync/async multi-model fan-out entry with its per-row dispatch through the review substrate and their shared limits; reviewable file classification and the packs read from the working tree (the touched pack takes the caller's `exclude_paths` — the advisory seam's shape — and marks a withheld path once; `span_only_release_carriers` is the ONE carrier-cut predicate the advisory, triad and scope packs share — release carriers changed only inside their declared version spans on a VERSION-bearing change, over the pair each pack reviews — and `pack_exclusion_note` its one disclosure (`CARRIER_CUT_REASON`); `triad_pack_exclusions` adds the commit triad's second class, governance docs byte-identical to the inlined prefix copy, with the `PACK EXCLUSION NOTE` the call site appends after the OMISSION NOTE; a managed subject keeps every full text); and the fixed reviewer prompt vocabulary plus the sections built from prior rounds
      │   ├── review_context_atlas.py ← Repository atlas for scope_review + deep_self_review (plan review does not consume it)
      │   ├── query_code.py    ← Read-only code intelligence; `root=user_files` with path guards, denied to subagents
      │   ├── edit_ops.py      ← `apply_patch` + `edit_batch` with shared `_syntax_check`/`_unified_diff` backing write_file
      │   ├── media.py         ← `ocr_pdf`, `youtube_transcript`, `extract_video_frames` (dependency-optional, typed capability envelopes; frames under `artifact_store/video_frames`)
      │   ├── verify.py        ← Independent check execution through the SAME pre-exec guard machinery (shell-guarded, deliberately NOT a process-command tool); receipts append to `<drive_root>/task_results/artifacts/<task_id>/verification_receipts.jsonl`; `expected_match` kinds: substring (default) · exact · exact_line · json_equals · bytes_equal; an owner-settings change is detected and reported as a typed note, never auto-reverted — an auto-revert would undo concurrent differences without proving causation, and POST-execution checks cannot gate a receipt already written, so verify rides the PRE-execution guards; verification reads only public task info (anti-cheat); the exit-masking sensor feeds the advisory nudge without changing status, and `run_command`/`run_script` read the SAME sensor to append ONE advisory note plus `exit_masking_reasons` to a masked GREEN result envelope — status, `is_failure` and the reported returncode unchanged, no receipt written, outside the verification ledger and receipt reconciliation, using the shared typed shell lexer so subshell grouping does not hide masking and quoted operators remain literal arguments; `delegation_zero_run` writes only `incomplete`/`unknown` and only after the custody scan proves no open run — a self-reported "complete" with zero runs is unverifiable authority
      │   ├── review_helpers.py ← Shared review helpers (governance-doc loading, checklist section slicing, prompt-size SSOT, the density-calibrated input cap and the probe sample `density_probe_sample` — a slice of the real atlas content — every packed review surface measures on)
      │   ├── review_binary_context.py ← Staged/parent Git object metadata for review packs
      │   ├── review_subject.py ← `ManagedReviewSubject`; `capture_review_diff` stays byte-identical for non-managed callers
      │   ├── review_admission.py ← Pre-dispatch admission for both packets ($0 on a deterministic block): `fit_triad_prompt`, typed `not_dispatched` seats, typed oversize outcome; the commit gate's money admission (`commit_gate_paid_seats` prices every paid seat, `admit_commit_gate_wave` admits the wave whole through `review_wave_budget_gate`); the commit gate's cold-start density rung (`density_probe_before_size_refusal`, the packed deep self-review's rung shared) before either packet is refused or degraded for size on a cold store
      │   ├── review_revalidation.py ← Review-contract fingerprint revalidation
      │   ├── scope_review.py  ← Enforcement/budget-aware whole-repo scope reviewer (§6 Review stack)
      │   ├── scope_review_session.py ← Session scope delivery from the SAME `build_scope_review_prompt` (canonical docs as nav maps); coverage manifest is forensics, never a gate; session admission per BIBLE P3 (≥200K sourced window)
      │   ├── scope_window.py  ← `scope_window` resolution + ReviewerWindow constants
      │   ├── scope_review_contract.py ← Pure scope-item parser (`normalize_scope_items`); also consumed by scripts/validate_scope_receipt.py
      │   ├── scope_review_pack.py, scope_review_budget.py ← Scope-review assembly and its money: the touched context (a span-only release carrier on a VERSION-staged commit keeps no snapshot by design — `_carrier_span_only_paths`, the shared cut over the same HEAD→index pair the pack reviews: named in the dedup note, declared diff-only to the atlas with that reason so the durable coverage row stays truthful, traced as the ladder's first entry; never for a managed subject or an artifact the atlas owes in full), atlas and guaranteed-fit ladder, and the token limits, reserves and oversize classification that bound them
      │   ├── services.py      ← Service mini-manager with process-group cleanup
      │   ├── skill_exec.py    ← list_skills/skill_review/toggle_skill/skill_owner_action/skill_exec; runtime allowlist python/python3/bash/node/deno/ruby/go; gated by enablement + fresh review + hash
      │   ├── skill_publish.py ← Thin publish transaction over the four leaves; success is PR-receipt-gated
      │   ├── skill_preflight.py ← Read-only skill preflight; a module widget's declared `render.entry` is checked for existence and containment inside the skill directory, and parsed with classic-script grammar because the widget frame runs it as an inline script
      │   ├── project_journal.py ← journal_write/read, workpad_read/write, journal_tail_digest (over-limit rejected); owns `mirror_tree_coordination_to_journal`, the durable-journal mirror of tree coordination
      │   ├── presence.py      ← configure_presence, initiate_presence, typed completion/cancel
      │   ├── task_tree.py     ← tree_note/tree_read (storage SSOT: task_tree_ledger.py)
      │   ├── followup.py      ← One deferred follow-up into `state/scheduled_tasks.json`; exactly one trigger (`once` ISO or 5-field cron+tz); cap 2 pending, over-limit refused; preserves the SOURCE address (top-level `project_id` so `resolve_project_id` sees it, plus the originating `chat_id`) instead of defaulting to the global owner chat — an unscoped task's follow-up still takes the existing `owner_chat_id` default. The existing scheduler consumes a one-shot on the typed tombstoned-Project refusal, retaining its failed task and last error; deleting Projects and transient refusals remain retryable
      │   ├── join_ledger.py   ← Child-result absorption: validates lineage + exact hashes; dispositions integrated/irrelevant/deferred; `CHILD_RESULT_STALE`; keeps peek_task/discard_child_result
      │   ├── delegate.py      ← Delegation facade verbs `delegate_start` (with `retry_of`), `delegate_wait`, `delegate_cancel`, `delegate_answer`; the host pre-start rides the same `delegate_start(prompt="")` wrapper and the shared `subagent_runtime.exact_start`; supervision/recovery/custody/transport live in the named leaf modules (§6)
      │   ├── delegate_integration.py ← Delegated-patch integration: `_mutation_authority`, `_provision_snapshot` (registered before the start intent), retry-binding validation, `_capture_terminal_patch`; the skill-payload cluster (`_payload_mutation_authority`, `_rebind_payload_reference`, `_write_payload_patch_artifacts` — git diff --binary; reserved paths refuse the WHOLE apply as `blocked_reserved_paths` with the candidate preserved) and `integrate_payload_patch` (CAS, index-free git apply in NO-REPOSITORY mode — `GIT_CEILING_DIRECTORIES` pinned at the resolved PARENT of the payload, because git still searches the ceiling entry itself, so an ancestor Git worktree above the runtime data root cannot make git treat the payload as a subdirectory prefix and silently skip every hunk at rc=0 while `--numstat` prints nothing; the same env bounds the `--numstat -z` touched-path reader; a post-apply live hash equal to the BASELINE with a non-empty touched set is refused typed as `INTEGRATE_APPLY_NO_OP` with the apply intent resolved and nothing disposed; the busy-check refuses a second delegation only while a run whose OWNER TASK IS STILL LIVE, or whose terminality cannot be proven, has open custody on the same payload, QUEUES the extension reconcile request via `request_extension_reconcile`)
      │   ├── delegate_payload_patch.py, delegate_terminal_evidence.py, subagent_integration_delegated.py ← Delegation leaves: the skill-payload patch pipeline (capture artifacts, guards, the live apply); the terminal story of ONE delegated run as the parent reads it; and `integrate_delegated_patch`, the delegated-run disposition seam
      │   ├── subagent_integration.py ← integrate_subagent_patch (sha256, 3-way --index, protected-path gated, genesis refused), external-workspace audited verdict, `coop_already_in_tree` no-op, compare_subagent_patches
      │   └── patch_verdict.py ← The ONE verdict writer for both patch pipelines (re-exported as `_write_verdict`): verdict subjects are minted and classified by the writer (`run_<rid>`), never prefix-matched by readers; each decision lands twice — artifact + typed `delegate_run_patch_verdict` custody row — so the acceptance packet reads one replayable store; a failed artifact write is disclosed on the row
      ├── delegate_start_claims.py ← One short pre-transport transaction serializing the zero-run/custody recheck + `START_REQUESTED` append; the nested payload claim is taken only when selected; transport and waiting stay outside claim locks
      ├── process_containment.py ← Env-token container membership (`OURO_PROC_CONTAINER_*`; /proc environ on Linux, `ps -E` on macOS, kill-on-close Job Object on Windows) with live-state read at reap — containment is unconditional because a surviving descendant can become invisible to ordinary parent-child traversal once the controller exits, and Windows spawns suspended-then-adopt so a child cannot execute before Job membership takes effect; an attributed alive-or-undeterminable member is an honest hard-block answer, never a kill guarantee; unreadable strangers are warnings, never members by uid/start-time alone (an unobserved detached descendant that hides its token remains a disclosed detection gap); `process_group_has_live_members` excludes zombie-only service groups while retaining live children and unknowns; policy layered over platform_layer
      ├── process_custody.py   ← spawn_supervised + durable process_ledger.jsonl; reap_orphaned_processes checks strict identity and retained_purposes across generations; start_parent_lifeline watches the spawner; quiesce_custodied_services checks all group members. live_daemon_root_pids/live_kept_service_pids select teardown exclusions; process_stop_snapshot binds asynchronous stop fallback to the observed rows; stop_ledgered_processes requires measured identity and confirmed exit. Complements platform primitives and existing panic tracking (§1 Runtime topology; §9 Shutdown).
      ├── platform_layer.py    ← Cross-platform process helpers, the descendant-enumeration seam, the Windows Job Object ABI
      ├── verified_download.py ← Shared exact-size/digest verification and atomic cached byte delivery; consumers retain their own transport timeout and error vocabulary
      └── node_runtime.py      ← Execution-probed Node runtime health (`node_runtime_health`, memoized by path/mtime/size — a missing binary is never cached, and a timeout verdict is re-probed only by a larger budget), `select_skill_node_runtime`, `skill_node_emergency_path_dir`

Devtools boundary

devtools/ (including devtools/benchmarks/cybergym/) lives outside the runtime and package discovery: no runtime imports, normal review, artifacts in an external output root; a sentinel-marked isolated root suppresses rotation warnings. devtools/e2e_live/ is the live E2E stand: K staggered isolated real servers running the owner-shaped scenarios SM1 (a design-system-consistent brand-accent change landed as a reviewed release, the product's own review policy shaping the work), SW1 and SK1 with acceptance over durable artifacts and a browser probe, admitted through the same seed gate and manifest seams as the benchmark launchers (DEVELOPMENT "Live E2E stand").

Gateway Boundary v1

ouroboros/gateway/ is the single inbound browser/CLI boundary: contracts.py owns the envelopes (with the endpoint index in endpoint_index.py), router.py collects the routes, and files.py/host_service.py stay separate trust boundaries. The ouroboros/contracts/api_v1.py compatibility re-export is gone with the envelope aliases, so gateway/contracts.py is the one envelope owner; the contract is also EXECUTABLE — gateway/schema.py validates ingress against JSON Schema derived from those TypedDicts. Domain handlers translate transport into calls on existing runtime owners and must not acquire a second copy of queue, review, settings, or lifecycle policy. The facade exists for dependency direction: the UI evolves without importing the agent body, and the runtime evolves without ad-hoc browser contracts.

gateway/owner_settings.py is the ONE owner-scoped settings WRITE seam (the generic POST, the single-decision endpoints, and onboarding; membership = calling _owner_update_settings, directly with a transform or through _owner_write_settings with a whole document). The settings lock is a precondition — a timed-out acquisition refuses before any precondition or write — and CommitBoundary marks the commit instant so a later-step failure is reported as that step, with saved a field on BOTH sides of the boundary: an envelope that merely omits the field would be ambiguous. The invariant prose lives in the module docstring.

Frontend calls go through web/modules/api_client.js with the JSDoc mirror web/modules/api_types.js; gateway parity tests pin the mirror. Extension HTTP lives under /api/extensions/<skill>/… with namespaced WS dispatch.

CLI / Headless Boundary

ouroboros.cli is a client of the same gateway/queue — no second task engine. Its parser is the command-surface SSOT (server, run, tasks, chat, logs, evolve, schedule, settings, skills, marketplace, local-model, MCP); streaming commands reserve stdout for the final answer/patch/result/JSONL and send progress to stderr.

POST /api/tasks creates an ordinary managed root; GET /api/tasks is a non-materializing list; GET /api/tasks/<id> returns the effective durable result; /events is the archive-aware SSE stream (§3 Chat); /artifacts/<name> serves simple filenames confined to data/task_results/artifacts/<task_id>/ — a stored arbitrary path is not a download capability. The CLI refuses any delegation_role other than root, the gateway rejects caller lineage/subagent labels, and only schedule_subagent creates children. Reserved service metadata is written after caller metadata. Admission reserves the task id plus a worker-pool slot under one queue lock; a failure rolls back only the token-owned row with a loud typed refusal. The parsed request's complete admission and attachment staging run off the HTTP event loop through gateway._helpers.run_sync_to_completion; a cancelled HTTP waiter retains that worker until durable admission or rollback settles, without cancelling the admitted task. Detail reads and SSE terminal materialization use the same settled wait, and v2 closes its row iterator only after the outstanding read finishes. Attachments are copied into the effective task drive before enqueue; artifact-store references are not host-path authority.

Workspace tasks default memory_mode=forked; shared is rejected for an external workspace and materialized on a forked child drive for project scope — the stored memory_mode reports what was requested while drive_root reports where the task executes, so isolation does not depend on relabelling the request; the mode isolates the execution drive and the knowledge seed, while identity and scratchpad writes still land on the canonical root the next context reads.

--detach returns only after durable admission; --no-stream polls to completion; waiters treat a result terminal only after the artifact state leaves pending/finalizing, and an explicitly-partial cost gets a bounded 60-second finality wait before partial flags stay visible. ouroboros run exits 0 only for a completed lifecycle, a clean execution axis, no failed/degraded objective, and a finished artifact bundle — strict exit semantics keep shell automation from interpreting "the model answered" as "the requested workspace deliverable exists"; --patch/--patch-out are stricter still (failed/missing patch, no-change, empty payload, or unfinished finalization is an error).

CLI schedules and skill-manifest schedules enqueue ordinary supervisor tasks — no parallel scheduler. resync_skill_schedules() mirrors manifests (executable skills with supervised-task permission only) into the same table after lifecycle changes and on ticks; a blank timezone means the DST-aware system zone, with a fixed-offset fallback only when the zone is unrecoverable; the active schedule digest rides task/consciousness context.

Packaged CLI artifacts are a tiny wrapper + installer, not a second PyInstaller runtime: packaged_cli locates repo.bundle, its manifest, and python-standalone, bootstraps the launcher-managed repo, and invokes the same ouroboros.cli under the embedded interpreter with canonical env. Packaged server is refused — it would bypass launcher-owned bootstrap, process identity, restart, and cleanup. run --start is loopback-only, starts the desktop app when no ready gateway answers, follows data/state/server_port, and waits for /api/health + supervisor_ready. Nested AppImage extract-and-run gets a private TMPDIR because the type-2 runtime keys extraction by TMPDIR + digest; a marker-gated AppRun custodian removes the verified extracted child after the launcher exits.

Release builds also carry Node and ripgrep. Skill-side Node resolves bundled-first via node_runtime.select_skill_node_runtime() (rolling back to a healthy PATH node when the bundled candidate fails the health probe), while the four generic process launch surfaces run the opposite policy (process_interpreters.resolve_process_node): a PATH candidate that passes the execution health probe stays byte-identical in argv and child env, and the bundled runtime substitutes only when that candidate is missing or probe-dead, attesting the child-env PATH prepend — never inside a non-local executor backend. The Node downloader verifies the official archive against published SHASUMS and the macOS signing pass re-signs it under the hardened runtime; ripgrep is archive-hash verified, and search_code still pre-enumerates policy-approved files before invoking it, so bundling a faster binary does not widen search authority. Every bundled consumer searches bundled_resource_bases(): OUROBOROS_BUNDLE_DIR → frozen root → interpreter-ancestor roots → source checkout — server/CLI children run from the managed repo with neither _MEIPASS nor an in-bundle module path, and ancestor recovery covers older launchers starting newer checkouts.

The embedded interpreter must never write into the signed application (codesign seal): entry processes suppress bytecode before project imports, and embedded_python_env() redirects bytecode to data/state/pycache and user installs to data/state/python-userbase (pip_install_target_args() adds --user for direct python-standalone invocations and aliases). The pip helper first recognizes an invoked virtual environment from pyvenv.cfg beside its standard bin/Scripts directory, before resolving the executable symlink; confirmed venv installs stay inside that environment. Disclosed residual: the userbase outranks bundle site-packages and nothing prunes or versions it — recovery is manual (remove the directory, relaunch).

Workspace binding changes the contextual repo, never the system repo for BIBLE/prompts/review governance. /api/tasks and project-room promotion share workspace_admission.validate_workspace_root() (exists, ordinary directory or exact Git worktree root, disjoint from the system repo and data drive, resolved/bidirectional/case-folded); an empty Project binding is idempotently provisioned as a standalone git repo unless workspace="none". Ordinary folders support direct file/process work; Git-specific operations require a Git worktree. Binding changes the default file/process/VCS target plus memory/lease/preflight/finalization; it does not remove top-level tools or downgrade the Architecture context in Max mode (root=system_repo stays; root=skill_payload takes bucket+skill_name). The workspace executor is a process-routing boundary: executor_ref is host-owned, mappings must cover the workspace without overlapping system repo/data, network=none only when the backend implements it, and executor processes enter durable custody records.

Ordinary-directory sessions negotiate mutability.workspaceKinds from the engine catalog and submit execution.workspaceKind=directory on the existing agent mode. The parent selects directory_strategy=direct|copy and optional scope_paths; copy requires an explicit selected input footprint while direct may name future output paths for capture. Geometry is a WRITE-side request: only a write-capable child on an ordinary folder opens such a session, so copy or a non-empty scope_paths named for a read-only child is a typed schedule-time argument refusal that states the repair, and direct with no selected paths is the documented default — on a shape that never uses geometry it means exactly what omitting both means and starts the same run, rather than dying at the host's pre-start. The stable project address and observed execution directory remain separate facts. The engine owns copy materialization, per-file CAS, apply and discard; the host preserves the complete before/after artifact closure through the existing custody path. No full-tree direct baseline copy, second file engine, scheduler or retention timer is introduced. A missing capability on an older serving engine is an explicit refusal, and file or GUI work is not judged from an empty text diff.

Directory manifests retain source and execution roots, isolation, declared footprint, completeness and exact per-file references. Complete means the selected footprint, not the entire source folder. Artifact bodies stream with digest checks without the diagnostic preview cap. Copy apply uses the existing durable apply intent and idempotency key; a lost response stays pending and reuses that identity. Partial selections keep undisposed changes in engine custody, and explicit discard records rejection without undoing applied effects. Canonical captured bytes survive execution-copy cleanup and later reads.

Workspace preflight snapshots git state (bounded porcelain rows), manifests/scripts, and tool availability into the full workspace_preflight.json artifact with a bounded summary in metadata; tools_on_path/tools_missing_from_path are named that way because shutil.which measures PATH presence, not executability, and the structured keys stay frozen because they ride durable, replaying task metadata; a collection failure is a disclosed error summary, never a fictitious full artifact.

Completion compares against the captured preflight base (task-local commits stay in the delta, not git diff HEAD); the patch is bound to task_constraint.base_sha; a moved HEAD fails closed only for self_worktree (a shared tree relies on reverse-patch verification); an unborn repo diffs against the canonical empty tree. Patch capture streams the tracked binary diff plus admitted untracked files, excluding scratch/cache/junk/incidental-lockfile entries with per-file reasons; otherwise eligible oversized/binary untracked outputs ride complete manifest+zip file artifacts, and tracked files whose old or current size exceeds 50 MiB stay in the same file-reference manifest (deletions explicitly name the baseline and absent current file) instead of a giant Git patch; generated output (dist/, build/) is governed by the project's own .gitignore, honoured through --exclude-standard, not by a host name rule — git-ignored files are outside the capture universe and are not listed as exclusions; a sensitive-looking untracked credential is excluded per-file and disclosed as sensitive_blocked. workspace_patch.json is written for EVERY workspace finalization (including no-change and failed) and is the truth source for CLI strict-patch — it distinguishes omitted vs no-op vs failed; workspace.patch exists only for ready_with_changes.

Forked/empty task state lives under data/state/headless_tasks/<task_id>/data: a forked drive copies identity.md, WORLD.md, registry.md (a project fork carries memory/knowledge/patterns.md and omits global knowledge; an empty drive starts blank); dialogue, scratchpad, mailbox, and history never cross. The child drive is execution state: the result copies back to the canonical root, declared artifacts rebase to data/task_results/artifacts/<task_id>/ (missing source = copy failure; collisions get a deterministic suffix), and verification-receipt replicas union with exact-row de-dup. Once the canonical result is terminal, late copy-back and effective reads pass through the same pure field-custody projection — the parent-owned terminal marker and cost/round/token fields cannot be overwritten. memory_export.json is an explicit artifact, never merged automatically.

Complete input sets are preserved in the existing artifact store. task_contract.attachment_manifest is a preview of at most 25 rows; an additive attachment_manifest_ref names the full immutable JSON under source_handles/context_checkpoints with count, size and SHA. Pure contract normalization preserves this shape; inheritance, owner-mailbox reads, physical retries and copy-back resolve the complete file closure through artifacts, verifying captured bytes before reuse. Legacy inline lists remain readable. Ordinary artifact and input copy failures share child_ref_promotion pending custody, retry and cleanup protection for both headless and direct-task drives. A preview never substitutes for an unreadable full reference. Native-image bounds and transport-specific Telegram limits remain separate from complete work-order delivery.

Automatic genesis output listing is discovery, separate from artifact custody. Unreadable directories and changing files remain explicit rows; complete and gap_count disclose coverage and a bounded artifact error note survives projection. An available listing with gaps does not turn an otherwise successful capture into FAILED. Actual copy/ZIP capture still requires stable source bytes, descriptor and path identity and any expected digest; growth beyond initial regular-file size fails immediately instead of waiting indefinitely for EOF.

The two router continuation tools require an explicit predecessor_task_id ("" = fresh; omission or null refused before lookup, enqueue, or spend); predecessor source metadata survives snapshot/restore, and Main receives a defensive provider-only copy (inline threshold, persisted narrative, bounded legacy row, or an explicit gap — never a raw head/tail substitute), while exact reads and work orders stay full.

System self-modification, external workspace, and genesis remain distinct task classes; a genesis child gets an inspectable deliverable_manifest.json listing with streamed sizes and hashes for readable, stable regular files and explicit gap rows otherwise; symlinks stay un-followed. Listing gaps do not fail the task, while actual artifact copies still require verified stable bytes. Global/system installs stay runtime-policy reviewed, and sudo is always non-interactive (sudo -n).

Immutable artifact identity is owned by the existing artifact-record merge: collection, effective results and manifest refresh retain the captured size/SHA and disclose changed bytes. Rebased immutable files preserve that identity and name; an already verified canonical copy survives a later child change. A failed copy remains a per-file failure and a pending ref in the existing child-copy projection, keeping both GC roots until the file is promoted, while other files materialize; the existing artifact-bundle owner reports failed/missing and public, routing and terminal-event projections use that aggregate. The stored capture lifecycle remains distinct so pending-ref retry can rebuild the bundle after successful copying; no artifact observation rewrites task lifecycle, price or objective. Mutable outputs retain their normal refresh/version behavior. The task-artifact endpoint is a synchronous Starlette route so materialization, private-source reads and full-file verification run in its existing worker pool, including HEAD requests.

Startup file recovery follows prior-process custody and precedes the actual drive-prune pass; unknown ownership or unresolved/protected sources defer task-source pruning for that pass. GC removes a headless child drive only when the canonical parent is terminal, artifact finalization is terminal, retention has elapsed, and the recorded child path matches the expected directory — everything needed after child-drive deletion must cross the canonical handoff before a task is presented as settled; canonical results, artifacts, genesis repos, and memory exports survive.

Runtime topology

Two continuity roles: launcher.py owns the PID lock, bundle bootstrap, the server process, presentation, the restart signal, and cleanup (the packaged launcher runs outside the managed repo); server.py is the self-editable inner runtime. Native packages ship an opt-in systemd user unit as an alternate ingress, not a third role — deliberately without a restart policy, because the launcher owns managed restart, the crash fuse, and panic-to-complete-stop (KillMode=control-group).

Spawn custody: POSIX children start in a new session/process group; Windows creates the server suspended, assigns a kill-on-close Job, then resumes — failure to establish Job custody refuses to run. The launcher Job permits explicit breakaway; only the shared daemon requests it, while ordinary generation children remain covered by Job close. Lazy worker and direct-server starts use the same platform helper. An old packaged or external Job that cannot confirm breakaway retains the previous working spawn with a disclosed survive-close limitation; managed source updates cannot replace the immutable launcher. The launcher records data/state/server_process.json (PID, pgid, server/repo paths, requested and actual ports, argv, creation time) and re-proves identity before cleanup. Forced tree/group cleanup excludes the shared daemon subtree; existing listener sweeps retain their separate scope.

Same-install reaper (launcher_server_reaper.py): holding the PID lock licenses the reap, which runs at main() preflight and at the top of every launcher generation. A PID is proven only on three live facts — the exact <REPO_DIR>/server.py argv token, OUROBOROS_DATA_DIR, and OUROBOROS_MANAGED_BY_LAUNCHER=1 — revalidated immediately before the signal, with descendants captured before the root signal and the whole pass bounded to three rounds. Kills require the byte-exact /proc environment: ps -E output never authorizes a kill, because argv is indistinguishable from an env assignment there, so non-/proc hosts stay report-only. Server selection does not require a custody row — missing server records are the defect being repaired. Caller-supplied retained daemon roots filter descendants before final root revalidation. POSIX-only; Windows generation children die with the launcher Job while the shared daemon breaks away; never on panic or window-close. The startup stray check is report-only and annotates same_install/foreign.

Durable process custody (ouroboros/process_custody.py): spawn_supervised() records every long-lived child in data/state/process_ledger.jsonl — {pid, pgid, fingerprint{start_time, cmd_sha256}, purpose, scope task|session|daemon, owner_task, session_id}. The custody reaper runs at server startup and on the 10-minute supervisor tick and kills only entries whose generation or task owner is gone, by STRICT fingerprint — never by command-line class, so dev and packaged instances can coexist. The POSIX start-time fingerprint is a downgrade-safe /proc-first + ps -o lstart= pair (a rollback meeting an unknown token would prune every row WITHOUT a kill, orphaning processes; the mint order and platform details are specified under "Platform substrate" below). A recorded bare tick never authorizes a kill. Current-generation session processes take a cheap non-zombie liveness check that only ever KEEPS; daemon entries and explicitly retained legacy installation-process records are kept, with skill companions the exception — reaped on owner-uninstall or foreign generation, log-only by default (process_would_reap), fail-safe keep-all on an unknown live-skill set. start_parent_lifeline() gives our python entrypoints a watchdog that group-suicides when the spawning parent dies: inside a multiprocessing child it waits on the spawner's parent sentinel (EOF on supervisor death under fork, spawn and forkserver alike — under forkserver the ppid is the forkserver, which outlives a dead supervisor while any worker holds its alive pipe, so a ppid watch would never fire), a plain subprocess falls back to its ppid. _active_subprocesses, existing port sweeps, and generation Job Objects complement durable custody. Every worker tree-kill (supervisor/worker_pool_lifecycle.kill_worker_tree: pool shutdown/restart/update, unready replacement, cancel and timeout) and custody reaping of a stale session ancestor preserve retained daemon subtrees. Windows uses native creation FILETIME plus canonically quoted psutil argv for new fingerprints and one PID/PPID snapshot for selective tree termination; it never applies taskkill /T to an ancestor of a retained branch. Legacy empty-birth Windows rows keep their earlier liveness-only retention but cannot authorize forced signals (§9).

Launcher lifecycle: the lifecycle thread removes stale port state, starts the server, follows the actual port file, and waits for health. Exit 42 requests a managed restart (refresh bundle metadata/remotes, sync dependencies); a failed dependency install retries once, then startup proceeds under the crash fuse — an offline install with already-satisfied dependencies may still be healthy. Five ordinary crashes within 120 seconds stop automatic restart; a panic exit performs full cleanup and terminates the outer process rather than the retry loop.

Presentation: the Linux browser fallback checks DISPLAY/WAYLAND_DISPLAY before touching pywebview; GTK needs a live Gdk.Display.get_default(), while Qt is trusted on env alone — probing it constructs a QGuiApplication that can itself abort, so the probe would cause the crash it exists to avoid. On probe failure the same launcher supervises the same server, prints the authoritative URL, and opens the system browser best-effort — the browser is the owner's application, deliberately outside process custody and teardown. A repeated launch that loses the PID lock soft-polls the port file (~10 s) and opens the last-read loopback URL best-effort. Browser-mode SIGINT/SIGTERM handlers only set the shutdown event; sys.exit paths leave PID-lock release to the registered atexit owner, because a second release could unlink a newer launcher's lock.

Extension children, delegated runtimes, services, the local model, and companions all sit beneath these roles: every long-lived process enters the custody ledger or a process group. Disclosed residual: shutdown admission is not atomic with publishing a spawned child (a signal can land between Popen and the record) — tracked, not a reason for a second launcher.

Platform substrate

platform_layer.py owns OS observations and lock/process primitives; their callers own policy. kernel_file_locks_enforced probes once per real directory under a module lock, using a scratch file rather than a failed live acquisition. Unsupported-lock errors and ENOLCK select a recorded name-only tier; an unprobeable directory stays enforced for that call and is retried later. Contention retries, other kernel errors fail closed, and callers may refuse specific name-tier causes. The name tier uses O_EXCL plus identity recheck/unlink without kernel exclusion; monetary compaction refuses it while appends retain their existing policy.

A won file lock must still have a readable descriptor/path inode identity; a creator evicted before acquiring its hold recontends, and unreadable identity is not proof. Owner-aware recovery reaches the existing kernel/inode check immediately after confirmed owner death and never evicts a live writer. Unknown metadata and callers without owner-aware recovery retain the stale-age grace; permission denial is not proof of death. POSIX judges and unlinks the stale inode under its flock; Windows unlocks/closes the probe before identity-checked deletion and relies additionally on open-handle deletion refusal (CPython omits FILE_SHARE_DELETE), not POSIX's single-reclaimer guarantee. Refresh returns ownership, not a courtesy heartbeat: losing it requires abandoning protected work. Release unlinks only the held identity, before close on POSIX and after unlock/close on Windows. Windows contenders can transiently hold the path open, so unlink retries within its bound; swallowing that refusal would strand a stamp bearing a live owner's PID. LockFileEx covers one fixed byte beyond the short owner stamp, keeping the stamp readable despite mandatory locking and supporting empty files. Its OVERLAPPED is rebuilt, not cached per recyclable fd. Violation means contention; invalid-function/not-supported map to unsupported-lock errnos; other Win32 errors preserve their classification.

Birth identity is separate from PID presence. Linux prefers ticks plus boot id, then the ps wall-clock token, then separator-qualified bare ticks as a disclosed cross-boot collision limit; recovered observation capability can change the token form. The custody ledger keeps the legacy start_time spelling and the optional boot-qualified sibling so an older reader does not silently discard every owned row after rollback. Windows uses exact creation FILETIME; full command identity remains independent. Presence uses non-signalling process handles on Windows and retains access-denied/unknown presence rather than authorizing cleanup. Win32 calls declare full-width HANDLE arguments/results and snapshot last-error at the call; omitted declarations truncate 64-bit handles. Job termination/close checks false BOOL returns as failures, not just exceptions, so survivors remain disclosed.

Bundled resources use the §1 CLI/headless lookup order rather than assuming the managed server runs inside the frozen app. Node health/selection stays in node_runtime; the platform's lazy PEP 562 re-exports avoid its eager import cycle while preserving existing caller names. Platform TCP keepalive is specified with the shared transport in §6; kernel dead-peer detection does not shorten a cognitive operation's deadline.

Data layout (~/Ouroboros/)

~/Ouroboros/ is the default application root; APP_ROOT, DATA_DIR, and SETTINGS_PATH are independently env-overridable (ouroboros/config.py, §7).

~/Ouroboros/
├── repo/                          ← the self-modifying git repository; launcher-managed git clone keeps server.py in sync (never copied per launch — §2)
│   ├── ouroboros/                 ← core package (module map above)
│   ├── supervisor/                ← supervisor package
│   ├── web/                       ← Web UI; ES-module pages under web/modules/
│   ├── docs/                      ← ARCHITECTURE.md + architecture/ (this map: entrypoint + chapters), DEVELOPMENT.md + development/ (engineering handbook: entrypoint + chapters), CHECKLISTS.md (review checklists SSOT), CHECKLISTS_ARCHIVE.md, CREATING_SKILLS.md, DESIGN.md, DEPLOYMENT.md
│   └── prompts/                   ← SYSTEM.md, SAFETY.md, CONSCIOUSNESS.md (the wake-up message template, not a second system prompt)
├── data/
│   ├── settings.json              ← user settings (API keys, models, budget)
│   ├── task_results/              ← durable task results (task_results/<id>.json, every write stamped `_schema_version: 1`; an unstamped, future, malformed or retired-key row is QUARANTINED with log-only visibility and keeps its id occupied rather than being re-minted); artifacts/<task_id>/ holds .artifact_manifest.json (private metadata) + artifact files; .scratch_manifest.json declares ephemeral scratch {abs_path: sha256} excluded from patch capture only while content matches
│   ├── artifact_versions/<task_id>/ ← artifact recovery history, last 5 versions per name
│   ├── task_drives/<task_id>/     ← task-scoped scratch, including live per-call manifests; startup prunes terminal tasks after the headless retention window
│   ├── task_trees/<root>/blackboard.jsonl ← append-only swarm blackboard + beacons; tree-scoped and ephemeral (task_tree_ledger.py), pruned on root terminal
│   ├── state/
│   │   ├── state.json             ← runtime state + compatibility cost projection; never the monetary authority
│   │   ├── queue_snapshot.json    ← durable PENDING/RUNNING recovery projection + worker counts + explicit worker_pool_disabled_reason
│   │   ├── usage_attempts.jsonl   ← append-only monetary authority: per-attempt id + state transitions; a settled attempt with cost=None and a numeric reservation bound counts at the bound
│   │   ├── skill_review_root_tasks.jsonl ← append-only compact index produced by `skill_review_runner._append_terminal_history` through `skill_review_history.append_history_once` and consumed with a bounded tail by `skill_readiness._skill_names_from_review_history`; derived projection of per-skill `review_history.jsonl`, retained append-only, with a 20 MB warning at `context_budget.SKILL_REVIEW_ROOT_TASKS_WARN_BYTES`
│   │   ├── usage_attempts.quarantine.jsonl ← loud quarantine of a proven-corrupt final row; the validated prefix stays readable
│   │   ├── usage_import_watermark.json ← resumable idempotent legacy-import watermark
│   │   ├── request_wire_compatibility.json ← cross-process locked, schema-versioned 14-day exact-route wire evidence (request_wire_contract.py)
│   │   ├── capability_evidence.json ← sourced model-capability evidence (capability_evidence.py)
│   │   ├── process_ledger.jsonl   ← durable process-custody ledger (process_custody.py; Runtime topology)
│   │   ├── server_port            ← active HTTP port for launcher/browser handoff
│   │   ├── server_port.bindings.json ← informational endpoint snapshot owned by `server_process.py`: the main, Host Service and local-model owners publish their actually bound host/port with the owning pid and process fingerprint while they hold it (`record_service_binding`/`clear_service_binding`; compare-and-remove, so a late close cannot erase a replacement); a browser identity fact, never a grant or a custody ledger
│   │   ├── server_process.json    ← launcher-owned server identity record for relaunch cleanup
│   │   ├── advisory_review.json   ← durable advisory/review ledger (runs, attempts, obligations, commit-readiness debts)
│   │   ├── deep_self_review_context.json ← last Atlas manifest + model metadata
│   │   ├── code_intel/<repo_key>/inventory.json ← code-inventory facts; no raw source cache
│   │   ├── evolution_metrics_cache.json ← per-tag metrics cache regenerated by /api/evolution-data
│   │   ├── evolution_campaign.json ← campaign objective/progress/history/budget
│   │   ├── evolution_checkpoints.jsonl ← append-only per-cycle checkpoints
│   │   ├── post_task_evolution_request.json ← worker-written one-shot promotion signal; consumed + deleted by the supervisor idle tick; dropped while evolution_owner_stopped
│   │   ├── post_task_evolution_counter.json ← per-drive every_n counter
│   │   ├── scheduled_tasks.json   ← cron (5-field + tz) and one-shot {type:"once", run_at} schedules; consumed one-shot receipts age out past the unified GC retention
│   │   ├── claudexor_rotation_provisioning.json ← receipt of the last rotation-reconcile settings POST
│   │   ├── update_letter.json     ← the last update letter (key = base/target/channel/ref, state, text, `last_good`); kept after apply and projected as pending/applied/superseded/other against the live HEAD (update_letter.py)
│   │   ├── projects.json          ← Project registry: immutable id/chat identity, working folder, lifecycle/routing fence, revision; tombstones are durable and never age-pruned
│   │   ├── project_task_bindings.json ← schema v1 root↔Project bindings with REQUIRED typed origin; one-way enrichment; tombstoning never removes a binding
│   │   ├── ui_preferences.json    ← owner-local layout preferences + monotonic project_seen_revision ACKs
│   │   ├── cancel_intents.json    ← compact locked projection of ACTIVE cancel intents; the forensic trail is typed cancel_intent rows in logs/supervisor.jsonl, never read back (cancel_intents.py)
│   │   ├── terminal_deliveries.json ← bounded delivered-dedupe + PENDING terminal-answer outbox (terminal_delivery.py)
│   │   ├── extension_companions.json ← runtime snapshot of live companion processes
│   │   ├── extension_reconcile/   ← worker-written markers consumed by the server lifespan pickup task
│   │   ├── review_continuations/  ← durable blocked-review continuations (+ corrupt/ quarantine; archived/ holds settled un-resumed rows ≥7 days, never deleted)
│   │   ├── workspace_executor_processes/ ← durable local/docker executor cleanup records
│   │   ├── headless_tasks/<task_id>/data ← forked/empty child execution drives whose live per-call manifests are promoted at terminal; until then their refs are not resolvable by the canonical reader (#805; CLI / Headless Boundary above)
│   │   ├── pycache/               ← embedded-interpreter bytecode (packaged builds; CLI / Headless Boundary above)
│   │   ├── python-userbase/       ← embedded-interpreter user installs (packaged builds)
│   │   ├── betterleaks/           ← versioned scanner runtime + archive cache, created only by the explicit source-checkout installer
│   │   ├── cx/                    ← managed Claudexor store: immutable <version>-<sha12>/ trees each with managed-runtime.json + node/, cache/ of verified archives, install.lock
│   │   └── skills/<name>/         ← per-skill state plane: review.json (content_hash, findings, reviewer_models, raw actor records, advisory_result — findings stay authoritative), owner_attestation.json (owner-issued marker; removal invalidates, content edit stales via content_hash, the agent can never forge it), review_history.jsonl (append-only terminal history; raw reviewer text never exposed to chat), accepted_rebuttals.json (injected into later review prompts), deps.json (isolated-dependency install fingerprint), auto_repair.json (marketplace auto-repair dedup by payload hash), ouroboroshub.json (publication receipt; malformed reads as published=null + typed diagnostic), health.json (server-authoritative health plus worker qualifier; flags live→broken regressions across restarts), auth_token.json (content-hash-bound Host Service token), enabled.json ({"enabled": bool, "updated_at": iso_ts, "actor": host_actor}), extension_calls/ (transient per-call child-process payloads), __extension_imports/<pid>-<uuid>/skill/ (staged import trees — §13)
│   ├── claudexor/                 ← Ouroboros-owned Claudexor home (CLAUDEXOR_CONFIG_DIR): daemon descriptor/token, credential profiles, runs, ouroboros-owned.json, daemon.log; never the operator's ~/.claudexor
│   ├── memory/
│   │   ├── identity.md            ← durable identity
│   │   ├── scratchpad.md          ← auto-generated from scratchpad_blocks.json (rendered newest-first; FIFO eviction of the oldest blocks until BOTH the 10-block count cap and the SCRATCHPAD_MAX_CONTENT_CHARS content cap hold)
│   │   ├── dialogue_blocks.json   ← consolidated dialogue memory blocks (dialogue_summary.md remains a read-only legacy fallback when present)
│   │   ├── dialogue_meta.json     ← consolidation cursor/metadata for the dialogue blocks
│   │   ├── WORLD.md               ← host profile generated on first run
│   │   ├── knowledge/             ← topic files + auto-maintained index; patterns.md (Pattern Register), improvement-backlog.md (backlog SSOT), *_journal.jsonl + *history.jsonl provenance
│   │   ├── deep_review.md         ← written by the deep-self-review task
│   │   ├── registry.md            ← memory awareness map
│   │   └── owner_mailbox/         ← per-task user message files
│   ├── projects/<id>/knowledge/   ← per-project facts + provenance sidecars; logs/task_reflections.jsonl holds full reflections with a bounded pointer row in the canonical log
│   ├── observability/             ← canonical private forensic ledger: blobs/<sha256>.json.gz compressed CAS payloads (0600) + terminal-promoted calls/<task_id>/<call_id>.json manifests
│   ├── services/<task_id>/<service>.log ← service runner logs; public tool output is bounded redacted tails + private blob refs
│   ├── logs/
│   │   ├── chat.jsonl             ← canonical chat: one logical message stored once, projected into Main/Project lenses
│   │   ├── chat_annotations.jsonl ← compact routing status by client_message_id; presentation-first, with the token-bound `needs_manual_target` decision card as the one routing-authority exception
│   │   ├── progress.jsonl         ← runtime ledger: progress/thinking stream
│   │   ├── events.jsonl           ← runtime ledger: lifecycle, llm_round/llm_usage, errors
│   │   ├── tools.jsonl            ← runtime ledger: tool calls
│   │   ├── supervisor.jsonl       ← runtime ledger: workers/supervisor
│   │   ├── task_reflections.jsonl ← canonical reflection log
│   │   └── containment_faults.jsonl ← append-only compact projection of containment incidents (delegate_custody.py)
│   ├── archive/                   ← rotated logs, rescue snapshots, archived managed repos
│   └── uploads/                   ← chat file attachments (paperclip)
├── Deliverables/                  ← bare user_files filenames land here (OUROBOROS_DELIVERABLES_ROOT; sibling of projects/, outside repo/ and data/, never GC-pruned)
└── ouroboros.pid                  ← launcher PID lock; platform lock auto-released on crash

Every entry of this tree is probed against the tree and the runtime sources by the generated docs/inventories/DATA_LAYOUT_INVENTORY.md, so a durable file renamed in code while its row here survives is red, not silent.