Files
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

373 lines
17 KiB
Markdown

# 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:
```toml
[[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`](docs/contracts/CONTRACT-FORMAT.md) (v2.1 is current; v2.0 and v1 contracts remain accepted)
- Parser: [`docs/contracts/contract_parser.py`](docs/contracts/contract_parser.py) — `--validate` checks required fields; `--list` shows function signatures; `--dir` batch processes
- Drift checker: [`scripts/contract_drift_check.py`](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`](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):
```bash
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.