Rulings canon — index
This is the single source of truth for standing user rulings on
orchestrata-ultimate (Phase 0 of plans/workflow-improvements-plan.md).
Gates and hooks read the git-backed markdown files in this directory
(~/workspace/knowledge-wiki/rulings/*.md) directly from the filesystem —
NEVER via wiki get — so a Wiki.js outage never breaks a test gate. wiki get
is for humans and liveness checks only.
Seeded 20 rulings from the 2026-07-26 memory export (13 mechanically enforced, 7 judgment-only).
| id | date | ruling | enforcement mechanism | status |
|---|---|---|---|---|
| RUL-001 | 2026-07-26 | NEVER run pytest with xdist (-n auto, -n N, --numprocesses, --dist) in orchestrata-ultimate |
hook .claude/hooks/no-xdist.sh (+3 more) |
enforced |
| RUL-002 | 2026-07-26 | No unittest.mock, no Mock/MagicMock/AsyncMock/patch, no hand-rolled Fake/Stub/Dummy classes, no monkeypatch, no @pytest.mark.skip/skipif |
gate scripts/test-review.py T1 (+2 more) |
enforced |
| RUL-003 | 2026-07-26 | Read env config with inline os.environ.get("X", default) at call time — never a bare os.environ["X"], never a hardcoded literal; INVERSE for required infra endpoint keys (REDIS_HOST/PORT, KG_*, MEMGRAPH_URI, CXP/KG_GRPC_PORT): NO default, RAISE when unset. Endpoints come from the active ORCHESTRATA_ENV_PROFILE (env/{dev,test,prod}.env) layered over secrets-only .env; the suite is hard-pinned to env/test.env |
gate scripts/code-review.py BARE_OS_ENVIRON (+4 more) |
enforced |
| RUL-004 | 2026-07-26 | The user runs containers on Incus (LXD), which he considers more stable and powerful than Docker | none (judgment) |
judgment |
| RUL-005 | 2026-07-26 | All test parallelism in this project comes from orchestrata_ultimate.core.threading.test_executor.run_tests_in_parallel (one pytest subprocess per module), driven via scripts/run_tests.py / run_tests_threadpool.py / run_tests_streaming.py — never pytest-xdist. |
hook .claude/hooks/no-xdist.sh (+1 more) |
enforced |
| RUL-006 | 2026-07-26 | "Any time you see an error, fixing it should be automatic." (verbatim, 2026-07-22) | none (judgment) |
judgment |
| RUL-007 | 2026-07-26 | Do not add Co-Authored-By: Claude ... (or any equivalent attribution to any AI assistant) to git commits, tags, PR bodies, or any other artifact |
none (judgment) |
judgment |
| RUL-008 | 2026-07-26 | Before ANY commit: run code review, test review, and architecture review (deterministic gates — ruff, purity/isolation audits, architecture_checker.py, standards, check-deps — plus a reviewer pass for non-trivial changes), and fix every bug found, whether or not it was in the scope of the change being committed. |
hook .git/hooks/pre-commit (+2 more) |
enforced |
| RUL-009 | 2026-07-26 | "do not run tests without it — only by force" (verbatim, 2026-07-10) | hook .claude/hooks/force-test-observation.sh |
enforced |
| RUL-010 | 2026-07-26 | "you cannot skip anything." (verbatim, mid-turn, 2026-07-21) | gate scripts/start_test_services.py non-authoritative |
enforced |
| RUL-011 | 2026-07-26 | For the CXP gRPC kernel port (and ports generally): no hardcoded numeric default, not in source, not in tests | gate scripts/code-review.py ENV_DEFAULT |
enforced |
| RUL-012 | 2026-07-26 | "include wiring and deployment in your definition of done permanently" and "do not claim completion until you can verify every single word in your completion report." (verbatim, session 242, 2026-07-18) | gate scripts/health_check.py check_orphan_modules |
enforced |
| RUL-013 | 2026-07-26 | Resolve behaviour/contract/version design decisions from specs/SPEC-000..105 + @traces(reqs=[...]) before asking the user to re-decide something a spec already says, and never from a test (tests can enshrine the wrong thing) or a guess. |
none (judgment) |
judgment |
| RUL-014 | 2026-07-26 | Every ruling must resolve to a mechanism: a hook, a gate, a banned-deps entry, a constitutional article, or an explicit enforcement: none (judgment) mark — never left as prose alone |
gate scripts/rulings_lint.py enforcement: |
enforced |
| RUL-015 | 2026-07-26 | "whenever a plan is there you should do nothing but execute that plan; the idea of diverting should never come up unless I bring up an issue." (verbatim intent, 2026-07-24) | constitution Article XII |
enforced |
| RUL-016 | 2026-07-26 | Before importing/ingesting nodes into a graph (Neo4j→Memgraph, source ingest, etc.), design/extend the canonical KG ontology FIRST — never dump raw nodes | gate scripts/kg_schema.py canon (+1 more) |
enforced |
| RUL-017 | 2026-07-27 | Never use weasel words — soft, hedging, or euphemistic vocabulary — in prose, verdict enums, schemas, docs, commit messages, or agent briefs; extended 2026-07-27 to epistemic hedging (likely, probably, seems to) |
hook .claude/hooks/no-guessing-stop.sh |
enforced |
| RUL-018 | 2026-07-26 | "Kimi runs at the AGENT level, not the project level" (user requirement, verbatim, SESSION_START.md) |
none (judgment) |
judgment |
| RUL-019 | 2026-07-26 | Central config modules (core/infra_config.py) use Pydantic BaseSettings, and env files must be auto-loaded (_load_dotenv(): secrets-only .env then the active ORCHESTRATA_ENV_PROFILE overlay) by every entrypoint — never left to direnv or manual sourcing |
none (judgment) |
judgment |
| RUL-020 | 2026-07-26 | "If a function is async def, every call to it must be awaited (or scheduled via asyncio.create_task/gather/ensure_future) |
gate scripts/check_async_await.py reportUnusedCoroutine |
enforced |
| RUL-021 | 2026-07-27 | "every damn feature branch gets a full env until we merge then it gets deleted" — no symlinked .venv, vendored wheels present locally, worktree + env deleted at merge |
gate scripts/check_worktree_envs.py RUL-021 |
enforced |
| RUL-022 | 2026-07-27 | Design → contract diagram → generate → fill in → test. No builder/wirer/refactorer dispatch without a contract that exists, a DoR-passing artifact, or an explicit DESIGN_WAIVER: line |
hook .claude/hooks/require-design-before-build.sh |
enforced |
| RUL-023 | 2026-07-27 | "when I ask for a feature that means wiring the damn thing not just code vomit" — an unimported module, unregistered hook, uninstalled git hook or uninvoked gate is NOT a delivery; "built but not activated" stays open | gate scripts/health_check.py check_wiring |
enforced |
| RUL-024 | 2026-07-28 | "pre-existing" is a DIAGNOSIS, not a DISPOSITION — proving a defect predates your change is evidence, never permission to leave it red; fix it, surface it as a named blocker, or show it is genuinely unreachable | hook .claude/hooks/no-preexisting-excuse.sh |
enforced |
| RUL-025 | 2026-08-05 | the canonical-schema conformance gate counts only production drift: keyless nodes carrying test_id are ephemeral swept fixtures, exempt from the non-canonical-node scan |
code src/orchestrata_ultimate/knowledge_graph/canonical_schema.py _scan_non_canonical_nodes |
enforced |
| RUL-026 | 2026-08-06 | hook .claude/hooks/workflow-default-sonnet.sh |
superseded | |
| RUL-027 | 2026-08-08 | prod services must execute from a dedicated deployment checkout; no prod unit may point at the working tree that development edits | gate scripts/check_prod_tree_separation.py find_violations |
enforced |
| RUL-028 | 2026-08-10 | requirement and test traceability is answered by the deterministic tools over the code-intelligence KB, never by grepping or walking the tree for REQ- ids |
hook .claude/hooks/force-trace-intel.sh |
enforced |
| RUL-029 | 2026-08-10 | a whole-tree test run must be justified by the affected-set oracle, which also decides when it cannot bound a change | hook .claude/hooks/proportionate-test-scope.sh |
enforced |
| RUL-030 | 2026-08-13 | a generated artifact is a snapshot of project state at a commit and must be tracked; the boundary excludes caches, telemetry and locks by a three-property mechanical test | gate scripts/check_generated_artifacts.py RUL-030 |
enforced |
| RUL-031 | 2026-08-19 | a requirement id has exactly ONE canonical spelling (REQ-NNN-US-NNN-NNN); the legacy story form is not a tolerated variant, not a ratchet and not baselineable — it fails |
gate scripts/check_req_format.py RUL-031 |
enforced |
| RUL-032 | 2026-09-22 | a test module that passed is not run again until the test or the code it imports changes; an env change never escalates the suite and never re-runs a proven module | gate scripts/run_tests.py RUL-032 · gate scripts/test_green_ledger.py RUL-032 |
in progress (builder dispatched same session) |
| RUL-033 | 2026-09-23 | the Read tool is allowed on a Python module the same session already read through serialize_codebase_ast.py source <name>; text tools stay denied; per session, per module (ruling R9, ADR-0063) |
hook .claude/hooks/force-ast-toolkit.sh |
enforced |
| RUL-034 | 2026-10-06 | a packet implementing any part of any spec is DONE only when @traces annotations, RTM regeneration, documentation (checklist + docs + design status), the knowledge-wiki page update and ≥90% per-file coverage all land in the same ship as the code (ADR-0069) |
none (judgment) |
judgment |
| RUL-035 | 2026-10-06 | every Claude Code hook is registered at the USER level (~/.claude or the orchestrata plugin's hooks.json) and resolves the repo from cwd at run time, so one registration governs every project; no repo registers hooks in its own .claude/settings.json (ADR-0070; 31 project-level registrations measured as the open violation) |
none (judgment) |
judgment |
| RUL-036 | 2026-10-14 | every test is categorised functional or integration by what it depends on: integration = uses a test-fleet service (Redis, graph, Prolog container, kernel, gateway) or the network; functional = fully in-process (janus Prolog included); the category is derived from the fixtures a test uses, never hand-set (at least 1,752 of 1,848 test modules measured uncategorised) |
none (judgment) |
judgment |
| RUL-037 | 2026-10-17 | Python is written only as .py files through editor tools that run the formatter and convention guards; no inline interpreter programs (python -c, heredocs) in shell commands or brief checks, no shell file writes around the guards; binds the main session, every subagent and every dispatched worker (opencode/Hermes/Kimi), permanently and mechanically, never by promise (587 inline programs in one session measured; dispatched workers measured with no guard at all) |
none (judgment) |
judgment — 4 mechanisms owed |
| RUL-038 | 2026-10-19 | no test run (developer run, pytest-live, run_tests.py, ship gate, pre-commit, CI) creates, copies, launches or inits a container or VM; tests may read and exec into the standing fleet; container-creating code is exercised by explicit rehearsals under rehearsals/, outside the test tree (ADR-0111; six leaked instances and 99 s test-Redis stalls measured) |
none (judgment) |
judgment — 2 gates owed |
| RUL-039 | 2026-10-19 | the promotion gate runs functionality tests only; rehearsal-class tests (real deploy/ship/incus/terraform/tofu/load surfaces) are never run in it | gate scripts/derive_test_categories.py RUL-039 · gate scripts/run_tests.py RUL-039 |
enforced |
| RUL-040 | 2026-10-20 | verification scope is measured at symbol granularity; a full-suite escalation is a bug — blast radius at method level, reuse ledger at function level, scope by deterministic code | gate scripts/run_tests.py --affected-decision · scripts/affected_tests.py verdict |
enforced |
| RUL-041 | 2026-10-22 | the host Claude stays production Claude on the flagship model; on orchestrata it writes no code — its work is the briefs, the checks and the workflow, measured by how Sonnet, Qwen and DeepSeek perform (executor list narrowed by RUL-042) | none (judgment) |
judgment |
| RUL-042 | 2026-10-24 | every delegated task runs through Hermes (hermes-task run --provider deepseek --model deepseek-v4-pro) on the DeepSeek API provider with deepseek-v4-pro (default) or, since 2026-10-30, the MiniMax provider (--provider minimax); no Sonnet, Qwen, deepseek-flash, pi-task or Kimi-as-executor unless Mohamed names it for that task. Supersedes RUL-026 |
none (judgment) |
judgment — dispatch guard owed |
Registration protocol
New user ruling → same session:
- Add a wiki page
rulings/RUL-NNN-<slug>(Ruling / Evidence / Enforcement / Verification sections). - Add/extend a mechanical gate, or record
enforcement: none (judgment). - Log via
session choice.
A ruling that exists only in prose is incomplete work. Verified by
scripts/rulings_lint.py — see RUL-014.