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 independentAGENT_CLASS_MAPhas no entry either.senior_devis the missing one:refs SeniorDevAgentfinds its definition, and every import and use is its own__init__.pyor 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 bareJ— 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
architectvolk. 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 psandss -tlnpshow nothing, and that is expected. Useincus 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_clientfixture (tests/conftest.py:648-678) constructs its client with nodb=argument, so redis-py defaults to db 0 — the same database the live kernel and gateway use. The fixture never readsTestSettings().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 fromtest_idor 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:
- 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.
- Write a contract. A design artifact with constraints and acceptance criteria, before any code. This is enforced, not encouraged.
- 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.
- Build to the contract, red-first: show the test failing against current source before it passes.
- Verify by execution, never by reading the report. Builders in this
project have twice reported a PASS from the wrong gate —
gate.pyversusgates.py, one letter apart. - Run the battery, fix everything it finds, then commit in reviewable slices.
- 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.
Related
- Project overview — the one-paragraph journey of an intent, current version and state.
- Table of contents — the narrative reading path through this wiki.
- Architecture · Volks · Isolated test fleet · Free-threaded Prolog
- Blockers · Open decisions