Starting context

What this page is. The orientation a person or agent needs in their first hour on orchestrata-ultimate: what the system is for, how it is shaped, where its infrastructure actually lives, which rules bind, and the one failure mode that keeps recurring in its own tooling. It is the wiki record of the starting context artifact assembled 2026-08-12 and re-measured before publication — see Provenance for what changed.

A governance and agentic workflow engine for code, architecture and communications — staffed by agents that occupy real professional roles, from junior developer up to enterprise architect and product manager.

What this is

Orchestrata is a governance and agentic workflow engine. Its subject matter is the three things a software organization actually produces — code, architecture, and communications — and its agents, called volks, are not generic workers but occupations. A human intent enters through a WebSocket gateway, is classified into a work type, and is routed through the sequence of roles that intent genuinely requires. Each stage is a real LLM-backed agent doing real work, and each transition is authorized before it happens.

The ambition is the span of the ladder. Not one assistant that does everything at one level of seniority, but a staffed organization: intake, business analysis, product management, UX, architecture, code direction, implementation at junior and senior grade, quality assurance, compliance and documentation — each with its own persona, tools, model routing and handoff contract to the next role.

The distinguishing choice is that governance is not a code path, it is a logic program. Policy lives in Prolog rule bases — constitutional.pl, governance.pl, intent_policy.pl — and the runtime asks may_execute/2 and may_complete/2 before acting. A denial returns a proof tree, not a boolean, so the system can explain why it refused. The same rule base that governs the runtime also drives the static gates that judge the codebase itself: the thing enforcing the rules on the agents is the thing enforcing them on the code.

The role ladder, as registered today

Stage Volk Occupation
Intake concierge · U:Cx receives the human, clarifies the ask
Analysis analyst · U:BA business analyst — requirements out of intent
Product pm · U:PM product manager — goals, criteria, portfolio
Experience ux · U:Ux interaction and interface design
Architecture architect · U:Ar system design and structure
Direction codedirector · U:Cd scaffolds, reviews, directs implementation
Implementation junior · J:Junior writes the code (see the note below on the missing second grade)
Assurance qa · U:Qa tests, autofix, failure diagnosis
Governance compliance policy conformance of the output
Record documentor · U:Do documentation as a produced artifact

See Volks for each role's prompt suite and handoff contract.

Ten registered, eleven present (measured 2026-08-13)

Eleven volk packages exist under agents/volks/, but only ten are registered into the production dispatch registry. PipelineRunner._register_volks (kernel/pipeline.py:225-282) builds exactly ten entries, and the orchestrator's independent AGENT_CLASS_MAP has no entry either. senior_dev is the missing one: refs SeniorDevAgent finds its definition, and every import and use is its own __init__.py or its own tests — zero production consumers.

So the "junior and senior grades" reading of the ladder is aspirational: only the junior grade is wired. By this project's own standard (RUL-023) an unregistered class is not a delivery, which makes this an open item rather than a feature.

Note also that junior's self-identifying code is J:Junior, not a bare J — the short form appears in older docs and matches nothing in the registry.

Where the implementation sits against the ambition

The ladder above reaches from junior developer to product manager. What it does not yet do is tier the architecture role. Technical, integration, solutions and enterprise architect are distinct occupations with different scopes of authority, and today they are a single undifferentiated architect volk. Closing that is the difference between an agent that designs a component and one that owns a landscape.

The codebase is a single Python package, orchestrata_ultimate, ported from a 26-package monorepo. It runs on free-threaded Python 3.14 with the GIL genuinely off, which required patching janus-swi (the Prolog bridge) and vendoring a free-threaded grpcio; stock versions silently re-enable the GIL. See Free-threaded Prolog.

The port itself is done. The work is maintenance, hardening and tooling. Alongside it, an unusually strong evidentiary culture: no doubles anywhere, real infrastructure for every test, and a battery of static gates that fail the build. The rules below are not style preferences; most exist because something broke silently and the fix was a mechanism.

Architecture

Five runtime pieces, and the protocol between them:

Piece Package What it owns
Kernel kernel/ The beating heart. Session context, dispatch, routing, audit, the PAM permission model. Runs as a gRPC server on CXP_GRPC_PORT (50053). A suite run that does not start and verify it is invalid.
Gateway gateway/ WebSocket + HTTP ingress. JSON-RPC method registry, auth, pub/sub, Redis ring buffers for replay. The single runtime ingress — clients never read Redis directly.
Orchestrator orchestrator/ U:Ox — intent classification, the pipeline runner, policy evaluation, escalation. Turns a sentence into a routed sequence of volk stages.
Postman postman/ Message routing and delivery: queues, topics, subscriptions, receipts, replay, delivery guarantees. The transport layer under agent-to-agent messaging.
Agents agents/ The volk runtime — pool, lifecycle, coordination, constraints, tool registry. Each volk is a persona with its own prompt, tools and model routing.

Full detail: Architecture and the architecture diagram.

CXP — the wire between them

Cross-agent eXchange Protocol. A packet carries a type, a thread id, a payload and headers; threads correlate multi-hop conversations. Clients and servers are built through create_cxp_client / create_cxp_server (cxp/transport.py) — never constructed directly.

There is now one production transport: the native cxpt direct transport. The grpc.aio CXP transport was retired 2026-08-07 (commit 5c7fb9f3, plans/grpc-retirement-design.md) because its EventEngine spawns native threads that outlive stop() and hang free-threaded interpreter exit; CXP_TRANSPORT=grpc now raises ValueError rather than silently degrading. Older documents describe "multiple transports that do not interoperate" — that was true before the retirement and is no longer.

The pipeline event taxonomy

One versioned event shape flows from the pipeline to any UI: a 13-member PipelineEventType enum, a PipelineEvent dataclass whose to_payload() is exactly return asdict(self), and a golden-bytes guard pinning the wire format (test_wire_bytes_unchanged, against frozen JSON constants). There are exactly two production producers — the kernel's PipelineEventBus.emit and PipelineKernelClient._emit_event.

What makes that last claim durable rather than decorative: test_every_production_payload_producer_resolves_driver ast.parses every file under src/, collects every .to_payload() call site, and asserts the discovered set equals exactly those two. A third producer fails the suite the day it appears — the structural opposite of a checker that reports clean because it never looked. All four properties re-measured 2026-08-13.

Governance

Prolog engines run in-process via the patched janus bridge. Ground facts are asserted from Python; rules stay in .pl files and are consulted. Verdicts carry provenance, and explain.pl provides proof trees and why-not answers. The same engine backs scripts/gate.py, which turns the AST snapshot into facts and evaluates codebase policy as inference.

Modules

Subpackages under src/orchestrata_ultimate/, grouped by what they are for rather than alphabetically:

Role Packages
Runtime spine kernel · gateway · orchestrator · postman · agents · cxp
Policy & proof governance · gates · verification · factory
Knowledge knowledge_graph · semantic_graph · memory · context
Models & drivers providers · llm · drivers
Code intelligence refactor (ctok, codemod, rename) · domaingen · openspec
Operations session · promotion · harness · plugin · tools · integrations
Foundations core · di · planning

Per-package documentation: Module Docs Index.

Two are worth calling out because they are easy to conflate. knowledge_graph talks to the operational KG (orchkg) — sessions, audit, code intelligence, specs, requirements. semantic_graph talks to the shared semantic/RAG database (memgraph) — embeddings, chunks, GraphRAG. Same physical cluster in test and dev, isolated by database name, different purposes entirely. See the KG migration record.

factory is the least obvious of the big packages — 74 modules, behind only core (83) and agents (76), measured 2026-08-13. It is SPEC-033's governed autonomous build factory: assumption ledgers, semantic anchors, red-first evidence, mutation testing, a DAG scheduler and merge queue — the machinery for letting the system build itself under governance.

Infrastructure

The thing that surprises everyone

Containers run on Incus, not Docker, on private subnets — not localhost. docker ps and ss -tlnp show nothing, and that is expected. Use incus list.

Three physically isolated fleets, each its own Incus project on its own bridge.

Fleet Subnet Redis Graph Role
prod 10.53.1.0/24 .10 HA orchgraph cluster live — never a test target
test 10.53.2.0/24 .11:6379 .10:7687 single authoritative suite target
dev 10.53.3.0/24 .21:6379 .20:7687 single developer scratch

Endpoints live in env/{dev,test,prod}.env, selected by ORCHESTRATA_ENV_PROFILE; secrets stay in a gitignored .env. tests/conftest.py hard-pins the suite to test and refuses to run if any resolved endpoint sits on the prod subnet.

The test kernel and gateway run as systemd services inside the app container at 10.53.2.13 — not as host user services, which target prod. That split-brain (harness probing prod-pinned host services while pytest targeted the test fleet) was a real bug with a real fix. See Isolated test fleet.

Live exposure worth knowing on day one (re-verified 2026-08-13)

The shared redis_client fixture (tests/conftest.py:648-678) constructs its client with no db= argument, so redis-py defaults to db 0 — the same database the live kernel and gateway use. The fixture never reads TestSettings().REDIS_DB, though the field exists. Its teardown reclaims only {test_id}:*, so anything a test writes outside its own namespace persists.

This is why Redis key namespacing is gated. That gate is now clean: Gate 0.4 reports zero violations — all 130 sites found in the 2026-08-12 triage were closed (c83d2de4), each either rewritten to derive its key from test_id or given a reasoned # gate-ok: waiver. The gate being green is what keeps the shared-db0 fixture survivable; it is not evidence that the fixture is safe.

Rules

Twenty-nine numbered rulings (RUL-001 … RUL-029, measured 2026-08-13 — rulings-lint checks 29 and reports every declared mechanism verified), each of which must resolve to a mechanism — a hook, a gate, a banned-dependency entry or a constitutional article — never prose alone (that is itself RUL-014). The ones that change what you do hourly:

Rule What it means in practice
No doubles No unittest.mock, no Mock/MagicMock, no hand-rolled Fake/Stub, no monkeypatch, no skips. Real Redis, real graph, real gateway. Three isolated fleets exist precisely so this is always possible.
No xdist -n auto deadlocks this suite. Parallelism comes from the batched executor — one pytest subprocess per module. (The widely-repeated "~78% of the time" has no primary source: it is asserted verbatim in 40+ places in this repo and its docs, and no timestamped log or N-of-M table exists to re-derive it. The ban stands on the deadlock, not on the percentage — and per this project's own standard, a number nobody can re-measure should be repeated as provenance-free or not at all.)
Observed runs only Never run tests blind and read an exit code. Background them with the live observer and watch. Cap every run at 5 minutes.
The kernel is required A suite run that does not start and gRPC-verify the kernel is invalid and false-green.
No hardcoded endpoints Required infra keys raise when unset — no literal fallback, not even localhost, tests included.
Zero hand-reading of Python Structure via symbols/refs, content via source <name> (exact bytes). Reading .py with Read/grep is hook-denied.
Design before build No builder dispatch without a contract, a DoR-passing artifact, or an explicit waiver line.
Wired is done An unimported module or unregistered hook is not a delivery. Done means built, tested, wired, deployed and documented.
Fix on sight Seeing an error means fixing it. "Pre-existing" is a diagnosis, never a disposition.
Review before commit Full gate battery plus code, test and architecture review — fixing everything found, in scope or not.
No AI attribution Commits, tags and PRs carry the human author only.

The forbidden-dependency list is a single file, .claude/banned-libraries.txt, enforced in four layers: a pre-write hook, a dependency-file guard, the code-review gate, and test-review rules. Adding a package there bans it everywhere.

Tools

Code intelligence — query, don't read

The single most important habit. Structure, content and refactors all come from tooling that is exact, rather than from reading files and inferring.

Question Command
Where is this symbol, who references it serialize_codebase_ast.py symbols · refs · who-imports
What is its exact source serialize_codebase_ast.py source <qualified_name>
Rename, extract, generate rename · extract-method · gen-dto · gen-tests · pattern
Blast radius, cycles, dead code code_intel.py impact · cycles · unused · dep-path
Requirement ↔ code ↔ test traceability trace_intel.py orphans · untraced-reqs · narrative
When a symbol disappeared, and what/how/why history_intel.py what · when · how · why · explain

The last three are exhaustive Prolog queries over a code-intelligence knowledge base, not file scans — they answer closure questions that reading cannot.

history_intel.py is the time dimension, added 2026-08-19 to close a recurring failure: a claim that a feature "was lost" used to be argued from memory and diff-reading, and got it wrong. It answers each question separately and from recorded evidence — what (kind + file), when (deleting commit and its date), how (dropped / renamed / moved / retyped, with the target), why (the rationale and its source), and explain (a proof tree via explain.pl).

Its most important answer is a negative one. no-recorded-rationale returns TRUE as a finding, not as a failure: the corpus currently holds 99 loss events, of which 11 have a recorded rationale and 88 do not (measured 2026-08-19, history_intel.py report). "Nobody wrote down why" is a fact the knowledge base states, rather than a gap that reads like a broken query.

Gates

scripts/gates.py is the single entry point for the review battery — 15 gates in parallel (measured 2026-08-13: 15 gate(s) in 33.9s wall), caching gates whose inputs are unchanged. Individual gate scripts exist (check_env_contract, check_wiring, gate_parallel_safety, audit_test_purity, and a dozen more) but driving one directly requires an explicit debug marker. scripts/gate.py run is the separate Prolog gate layer, with a three-valued verdict — pass, fail, or invalid when its fact base is stale, which is not a pass.

Tests

Runner Use
run_tests.py full suite — infra preflight, safety gates, then batched execution across 8 workers × 6 batches
run_tests_streaming.py development — live per-module PASS/FAIL
observe_pytest.py attach to a live run and stream per-test events

Measured on 2026-08-13: 32,928 tests across 1,621 modules, 0 failed / 0 errors / 0 skipped, 499s wall. Two modules failed inside a batch and both recovered on solo retry — that is the runner's normal load-flake path, logged to .flake_recoveries.ndjson, not a green claim papering over a red one.

Graphs, sessions, promotion

graph_query.py and graph_browser.py for the operational KG; semantic_search.py and the wiki RAG tools for the semantic graph. The session CLI tracks work in a per-project context.json — begin, log-work, log-choice, add-work, set-handoff, end — and is never hand-edited. promote_env.py gates movement through the fleets: validate → test → promote --to prod, with prod gated on a green test run.

How work actually gets done

The loop that has proven to work here, in order:

  1. Measure before theorizing. Query the AST, read the live key space, profile. Two sessions were lost chasing a hypothesized hot path that measurement disproved in a minute.
  2. Write a contract. A design artifact with constraints and acceptance criteria, before any code. This is enforced, not encouraged.
  3. Refute the design before building it. Adversarial agents attack the plan while it is still free to change — cheaper than discovering the flaw in review.
  4. Build to the contract, red-first: show the test failing against current source before it passes.
  5. Verify by execution, never by reading the report. Builders in this project have twice reported a PASS from the wrong gate — gate.py versus gates.py, one letter apart.
  6. Run the battery, fix everything it finds, then commit in reviewable slices.
  7. Document it — spec, docs and wiki are inside the definition of done, not after it.

The recurring defect

If there is one thing worth internalizing before touching this codebase, it is the failure mode that keeps recurring in its own tooling:

A checker that cannot distinguish "nothing is wrong" from "I didn't look."

The full treatment, with each instance measured and its fix recorded, is A checker must prove it looked, not just that it found nothing. Its sibling — the false-positive mirror image — is A gate must separate the artifact from a description of it.

The generalization: a green result is only meaningful if you can also state what was examined. When you write or touch a checker here, make "0 findings" structurally distinguishable from "0 files scanned", and treat any exclusion list as a suspect — the thing an exclusion most often hides is the thing the checker was built for.

Starting a session

Context arrives automatically: hooks inject a codebase map, an error report, infra readiness, the session state and recent work history. Read the error report before claiming anything about status, and check its timestamps — a stale artifact is worse than none.

Then, in order: session status, session begin, and confirm infra is up. Before asserting that a symbol exists or does not, consult the codebase map or query the toolkit. Before running anything that touches the graph or Redis, confirm which profile is active.

Provenance

Assembled 2026-08-12 from the live tree; every figure was measured on that date rather than estimated or remembered. Re-measured 2026-08-13 before publication here. Where this page disagrees with the code, the code is right and this page is the bug.