Worldtree Conversation API debug TUI. Multi-pane observability dashboard: chat transcript + persona/Vili affect log + tool events + admin events + Bifrost state + tool inventory + (opt-in) raw server log. Design locked at docs/design-brief.md (originated as brokkr-smithy/docs/ratatoskr-design-brief.md). Operator-locked decisions: - Textual application-shell framework (multi-pane dashboard, not REPL). - Separate repo + separate dev team (no Worldtree-source imports). - httpx-sse for SSE consumption (reference Python SSE-resume impl). - Triple version-skew mitigation: spec-pin in pyproject.toml + recorded SSE snapshot tests + conformance smoke. Initial pin: Worldtree v0.19.0 at 55101e909abcd2219833266b6f905c5bc956e0f0. - Persona pane: label-don't-refuse PII posture. - Server-log pane: opt-in via --server-log <path>. - Two-stage Ctrl-C (cancel then exit). - Markdown rendering default-on; --raw opt-out. In the box: - docs/design-brief.md — the locked design with full rationale. - docs/SPEC-PIN.md — Worldtree spec pin + bump procedure. - docs/conversation-api-spec.md + docs/conversation_api.contract.md — vendored Worldtree spec snapshots at the pinned SHA. - pyproject.toml — Python 3.12, hatchling, uv-managed, deps locked. - src/ratatoskr/ — stub package (cli.py raises NotImplementedError). - tests/test_no_worldtree_imports.py — boundary smoke test PASSING. - tests/snapshots/README.md — recording convention for SSE snapshot tests. Not in the box yet: - Gitea remote (operator/infra-ops to register at vh/ratatoskr). - Implementation — the dev team owns this; design brief is the spec. Origin: althing thread 01KS3R34XD3N6HMK91VXESHGW7 (worldtree-dev → brokkr-smithy-dev, 2026-05-20). Volva consulted via thread 01KS3VF6W33N3V5FNMGQ91YNVD.
17 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Principles
PRINCIPLES.md at the repo root carries the four Corviduo engineering
principles (Excellence over uniqueness · Explicit over implicit ·
Elegance is a byproduct · Action-relevance over thoroughness). These
are what to optimize for across all work — distinct from this file's
behavioral guidelines (how to operate session-to-session) and the
workflow mechanics below (project-level mechanics). The principles
also live at ~/.claude/CLAUDE.md § Core principles; this repo copy
is the load-bearing version when human contributors or non-Claude-Code
AI tooling read the codebase.
Canonical Corviduo specifications
This project depends on cross-cutting Corviduo specifications that
live canonically at ~/development/corviduo-project-template/ (the
spec-stewardship repository, Brokkr-managed as of 2026-05-15). When
this file is read inside the template repository itself, the
canonicals live here directly; when seeded into a derivative project,
pinned copies of the canonicals live in the derivative.
What lives canonically in the template
| Spec | Canonical path | Covers |
|---|---|---|
CONTRACT-FORMAT.md |
docs/contracts/CONTRACT-FORMAT.md |
Format spec for .contract.md files (v2.x). |
contract_parser.py |
docs/contracts/contract_parser.py |
Validator/extractor for .contract.md. Python ≥3.11, stdlib only. |
contract_drift_check.py |
scripts/contract_drift_check.py |
Verifies issue-scoped contracts' prd: block hashes match live tracker state. |
PRINCIPLES.md |
PRINCIPLES.md |
Four engineering principles. |
methodology.md |
docs/methodology.md |
The Corviduo preferred development pipeline ((optional) Vor → (required) Contract → branch (direct or AFK TDD) → verify → merge/commit). |
PRACTICES.md |
(to migrate from galdrabok/conventions/) |
Engineering practices (contract-first, TDD, no-backwards-compat, atomic commits). |
CONTEXT-FORMAT.md |
(to migrate from galdrabok/conventions/) |
Format spec for CONTEXT.md glossary files. |
ADR-FORMAT.md |
(to migrate from galdrabok/conventions/) |
Format spec for Architecture Decision Records. |
What to seed into a new project, by stack
When you seed a new Corviduo project from this template, copy the canonical files that apply to your target stack. The drift-check mechanism (below) keeps consumer copies in sync as canonicals evolve.
Every project (cross-language baseline):
CONTRACT-FORMAT.md,PRINCIPLES.md,PRACTICES.md— applies regardless of implementation language.contract_parser.py,contract_drift_check.py— Python meta-tooling. Invoke viauv run python scripts/...in non-Python projects.
Python projects (Worldtree, Sleipnir, Brokkr-Smithy, Skaldsong, Vor backend):
- All baseline files.
env.sh.template(Python-shape:PYTHONPATH, uv-managed venv expectations)..gitignore(Python-shape:__pycache__/,.venv/, ruff / mypy / pytest / uv caches).- Preferred tooling:
uvexclusively (uv venv,uv pip install,uv run,uv tool install). Ruff for lint. Mypy for types. Pytest for tests. Nopip/pipx/poetryunless the project clearly already uses something else.
TypeScript / Bun projects (Mead Hall, Vor UI, future client apps):
- All baseline files.
CONTRACT-FORMAT.mdapplies cross-language —.contract.mdfiles describe code regardless of implementation language. env.sh.template(TS/Bun-shape: project-name-uppercase root, per-app env vars, no Python venv references)..gitignore(TS/Bun-shape:node_modules/,dist/,bun.lockbis committed; no Python caches).- Preferred tooling: Bun exclusively (no npm / yarn / pnpm).
Bun's native bundler. Bun's native test runner (
bun test). TypeScript strict mode. React + Vite for UI projects where applicable.
Mixed-stack projects (Python backend + TypeScript frontend in
one repo): take both stacks' files; document which directory is
which in docs/architecture.md.
Keeping canonicals in sync
Two tools at scripts/ handle drift detection and sync for
cross-cutting Corviduo canonicals. Both Python ≥3.11 stdlib-only;
invoke via uv run python scripts/... in non-Python projects.
scripts/canonical_sync.py— operator-triggered. Fetches each pinned canonical from~/development/<canonical_source>/<canonical_path>, writes the consumer copy, bumps the pin'spinned_sha256_16+pinned_atin the manifest. Reports per-pin:OK/SYNCED/WOULD(dry-run) /ERROR. Run after the architect broadcasts a canonical update on althing.scripts/canonical_drift.py— read-only verifier suitable for CI gating. Detects drift between pinned canonicals and their sources, and consumer-copy divergence from the pinned hash. Exits non-zero on staleness, divergence, or missing canonical.
Each consumer carries a .corviduo-canonicals.toml manifest at the
repo root pinning each canonical:
[[pins]]
id = "contract-format-v2"
canonical_source = "corviduo-project-template"
canonical_path = "docs/contracts/CONTRACT-FORMAT.md"
consumer_path = "docs/contracts/CONTRACT-FORMAT.md"
pinned_sha256_16 = "..."
pinned_at = "2026-05-15T..."
The pattern generalises beyond template-only canonicals. Same shape
handles Worldtree's conversation-api-client-spec-v2.md, Bifrost's
protocol spec, and any future cross-cutting canonical — set
canonical_source to whichever ~/development/<repo>/ directory
hosts the truth.
Optional per-pin tolerate_drift = true makes canonical_drift.py
warn-only for that pin when --allow-warn is set (useful for pins
the consumer deliberately allows to lag).
Persistent memory
persistent-memory.md at the repo root captures durable intent and
supporting evidence (goals, decisions, foot-gun warnings, in-flight
state) across context resets. Read it at session start; treat it as
one input alongside this CLAUDE.md and the auto-memory system, not
as the single source of truth. When durable state shifts enough to
warrant capture, run /snapshot and commit alongside the next commit.
Architecture map
docs/architecture.md is the top-level module map (dependency graph,
session-load boundaries, execution order). Each core module gets its own
CLAUDE.md at core/{module}/CLAUDE.md once it grows past trivial.
When a development session focuses on one module, load that module's
CLAUDE.md plus the stable-infrastructure dependencies listed there.
BEHAVIORAL GUIDELINES
Tradeoff: These guidelines bias toward caution over speed. For trivial tasks, use judgment.
1. Think Before Coding
Don't assume. Don't hide confusion. Surface tradeoffs.
Before implementing:
- State your assumptions explicitly. If uncertain, ask.
- If multiple interpretations exist, present them — don't pick silently.
- If a simpler approach exists, say so. Push back when warranted.
- If something is unclear, stop. Name what's confusing. Ask.
2. Simplicity First
Minimum code that solves the problem. Nothing speculative.
- No features beyond what was asked.
- No abstractions for single-use code.
- No "flexibility" or "configurability" that wasn't requested.
- No error handling for impossible scenarios.
- If you write 200 lines and it could be 50, rewrite it.
Ask yourself: "Would a senior engineer say this is overcomplicated?" If yes, simplify.
3. Surgical Changes
Touch only what you must. Clean up only your own mess.
When editing existing code:
- Don't "improve" adjacent code, comments, or formatting.
- Don't refactor things that aren't broken.
- Match existing style, even if you'd do it differently.
- If you notice unrelated dead code, mention it — don't delete it.
When your changes create orphans:
- Remove imports/variables/functions that YOUR changes made unused.
- Don't remove pre-existing dead code unless asked.
The test: Every changed line should trace directly to the user's request.
4. Goal-Driven Execution
Define success criteria. Loop until verified.
Transform tasks into verifiable goals:
- "Add validation" → "Write tests for invalid inputs, then make them pass"
- "Fix the bug" → "Write a test that reproduces it, then make it pass"
- "Refactor X" → "Ensure tests pass before and after"
For multi-step tasks, state a brief plan:
1. [Step] → verify: [check]
2. [Step] → verify: [check]
3. [Step] → verify: [check]
Strong success criteria let you loop independently. Weak criteria ("make it work") require constant clarification.
Project conventions
Naming hierarchy
Corviduo.ai (company)
└─ ratatoskr (project / repo — this codebase)
└─ ... (modules, agents, components — fill in as the project grows)
Sibling Corviduo projects: Worldtree (multi-agent framework), Skaldsong (story-generation engine), vastai-app (Vast Blue SEA — multi-agent web app), sleipnir (AFK orchestrator), Vor (pre-contract design partner UI), Galdrabok (Sleipnir-preflight skill author), task-board (per-session web UI), althing.
Norse / Germanic naming convention is the house style for Corviduo projects. Module and agent names follow the same vein.
No backwards compatibility until v1.x
This project is pre-release. When something is redesigned, everything gets updated and everything old gets ripped out. No shims, no compat layers, no deprecation periods. If a new approach replaces an old one, the old code is deleted and all references are updated in the same commit. This keeps the codebase clean and avoids accumulating dead paths.
Contract-first workflow
Contracts at docs/contracts/ are machine-parseable architectural pseudocode specs. They serve as unambiguous work specifications: a planning pass writes the contract, then the implementation pass translates it to code, then an audit pass verifies compliance.
Workflow: contracts come before code. When implementing a new module or making non-trivial changes to an existing one, write or update the .contract.md file first. The contract captures function signatures, preconditions, postconditions, error handling, steps, and invariants — settling design questions before writing code. Contracts are not documentation of existing code; they are the source of truth that code is written to satisfy.
- Format spec:
docs/contracts/CONTRACT-FORMAT.md(v2.1 is current; v2.0 and v1 contracts remain accepted) - Parser:
docs/contracts/contract_parser.py—--validatechecks required fields;--listshows function signatures;--dirbatch processes - Drift checker:
scripts/contract_drift_check.py— verifies issue-scoped contracts'prd:block hashes match the live tracker state - File convention:
docs/contracts/{module_name}.contract.mdfor module contracts;docs/contracts/issues/{N}.contract.mdfor issue-scoped contracts
When to write a contract:
- New module — always write a contract before implementation
- Complex changes — new function blocks, new error handling, new state transitions
- Cross-module interfaces — when the change affects
depends_on/used_byrelationships
When a contract is not needed:
- Bug fixes that don't change function signatures or behavior
- Trivial helpers, one-liners, config changes
- Documentation-only changes
Issue → AFK dispatch hygiene (Sleipnir)
Before marking any issue ready-for-agent (the label that gates AFK
dispatch via Sleipnir), it MUST have an issue-numbered contract at
docs/contracts/issues/<N>.contract.md AND that contract MUST carry
a prd: block in its YAML frontmatter pinning it to:
- the issue body (SHA-256, first 16 hex chars)
- the lock-in comment id + content SHA (or
nullif the issue body alone is the spec) - a
pinned_attimestamp
This is hard policy, not a suggestion. Without the contract Sleipnir's
gate refuses dispatch with blocked-needs-contract. Without the prd:
block PRD-↔-ship drift becomes invisible — the audit infrastructure
that detects it is a no-op.
Verify before applying the label:
- contract file exists at the expected path
- frontmatter has a populated
prd:block python scripts/contract_drift_check.py --contract <path>returns clean
The full convention — frontmatter shape, required fields, reasoning
behind the four drift entry points — lives in
docs/contracts/CONTRACT-FORMAT.md.
TDD development cycle
Contract → failing test → minimal code to pass → run test. Tests written before/alongside code, never deferred. Vertical slices (tracer bullet first, then incremental loop), not horizontal slices (don't write all tests then all code — that produces tests of imagined behavior).
Persistent-memory + housekeeping commit-along rule
When committing changes, also commit persistent-memory.md if it's dirty.
Same applies to housekeeping files (HANDOFF-SUMMARY.md, NEXT-STEPS.md,
README.md, State-Of-Development.md) where they exist. The repo state
should always be coherent across these files at every commit.
Tooling conventions
Issues
For Worldtree-and-friends Gitea-tracked issues, prefer python -m core.issues
(the project's own CLI wrapping the Gitea API) over gh or tea. Until
this project grows its own core/issues/ adapter, fall back to tea
(local Gitea CLI at /usr/local/bin/tea, v0.14.0) for simple operations.
Tea CLI
tea is the local Gitea CLI. Use for PRs, releases, branch/repo ops. For
issues prefer python -m core.issues when it exists. Note:
tea issues edit <N> --add-labels <label> is the bucket-2 ergonomic
(client-side add-semantics, doesn't clobber other labels) — Gitea's HTTP
label endpoint is replace-semantics. For comment-edits, use direct HTTP
against the Gitea API (tea v0.14.0 has no comment-edit subcommand).
Sleipnir AFK orchestration
If this project uses Sleipnir for AFK dispatch:
~/.config/sleipnir/config.yamlcarries user-global config.sleipnir/config.yaml(this repo) carries per-project overrides; gitignored per-checkout- Default convention:
dispatch.dependency_aware: truefor INV-029 dependency-aware dispatch - Skills:
/sleipnir-scaffold <N>to bootstrap a contract;/sleipnir-preflight <N>to applyready-for-agent
Task-board status reporting
If the user runs the task-board plugin, the session card on the web UI shows
at-a-glance status. The plugin's auto-hook fires task_update on
UserPromptSubmit and task_wait on Stop. You should also call task_start
and task_update proactively to set what the session is working on:
task_start— at the start of a distinct piece of work (new feature, investigation, phase, bug hunt). Sets the card's activity subheader.task_update— at mid-task inflection points (issue filed/closed, branch merged, QA verdict, blocker hit, milestone). One per inflection.task_set_shells— when starting aBash run_in_background: true, pass an array of one short description per currently active background shell. Update when shells finish; clear with[]when the last completes.
SID derivation (post-v0.1.5):
SID="$(cat "${XDG_CACHE_HOME:-$HOME/.cache}/claude-task-board/$(basename "$PWD").sid" 2>/dev/null)"
LABEL="${TASK_BOARD_SESSION:-$(basename "$PWD")}"
If $SID is empty (no hook has fired yet this Claude Code restart),
skip the explicit task-board call for this turn. Subsequent turns
can call freely. Re-derive at the start of every turn — do NOT cache.
Do NOT fall back to JSONL-mtime guess (that was the source of duplicate-
card bugs).
Project Overview
Author this section once the project's purpose, modules, and conventions
solidify. Mirror the shape of Worldtree/CLAUDE.md § Project Overview when
the project grows enough surface to need module-level documentation.
What this project does
TODO — one paragraph.
Module structure
TODO — once modules exist, list them here with one-line descriptions.
Development setup
TODO — typical pattern: source .venv/bin/activate && source env.sh before
running anything. Mirror Worldtree's pattern when relevant.
Development Notes
- No backward compatibility until v1.x (see above).
- Contracts before code for non-trivial work (see above).
- Persistent-memory + housekeeping commit-along (see above).
- The
.gitignoreis configured for Python projects using tools like ruff, pytest, mypy, and uv/poetry/pdm. Adjust if this is not a Python project. - Build, lint, and test commands will be documented here as the project grows.