Files
ratatoskr/CLAUDE.md
T
vh 9703eb2b6b init: seed Ratatoskr from corviduo-project-template + ship v0 scaffold
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.
2026-05-20 20:38:22 -07:00

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 via uv 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: uv exclusively (uv venv, uv pip install, uv run, uv tool install). Ruff for lint. Mypy for types. Pytest for tests. No pip / pipx / poetry unless the project clearly already uses something else.

TypeScript / Bun projects (Mead Hall, Vor UI, future client apps):

  • All baseline files. CONTRACT-FORMAT.md applies cross-language — .contract.md files 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.lockb is 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's pinned_sha256_16 + pinned_at in 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--validate checks required fields; --list shows function signatures; --dir batch 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.md for module contracts; docs/contracts/issues/{N}.contract.md for 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_by relationships

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 null if the issue body alone is the spec)
  • a pinned_at timestamp

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.yaml carries user-global config
  • .sleipnir/config.yaml (this repo) carries per-project overrides; gitignored per-checkout
  • Default convention: dispatch.dependency_aware: true for INV-029 dependency-aware dispatch
  • Skills: /sleipnir-scaffold <N> to bootstrap a contract; /sleipnir-preflight <N> to apply ready-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 a Bash 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 .gitignore is 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.