From afb8552d3762da5a843587440ed6632960184d1a Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 4 Jun 2026 14:16:09 -0700 Subject: [PATCH] add ~/.claude/CLAUDE.md as a managed dotfile Global Claude Code preferences (symlinked from ~/.claude/CLAUDE.md, like the other home_root dotfiles). Includes the new 'Global tools available' section documenting box-wide Playwright/Chromium on nh3-dev. --- home_root/.claude/CLAUDE.md | 574 ++++++++++++++++++++++++++++++++++++ 1 file changed, 574 insertions(+) create mode 100644 home_root/.claude/CLAUDE.md diff --git a/home_root/.claude/CLAUDE.md b/home_root/.claude/CLAUDE.md new file mode 100644 index 0000000..271bc7a --- /dev/null +++ b/home_root/.claude/CLAUDE.md @@ -0,0 +1,574 @@ +# CLAUDE.md — global preferences (lkraven) + +Loaded into every Claude Code session regardless of project. Project- +local `CLAUDE.md` files take precedence when they conflict; this file +is the baseline. + +## Core principles + +Four principles governing engineering choices across all projects. +Common lodestar: fitness-for-purpose. Each rejects a different +substitute goal that disguises itself as virtue. + +1. **Excellence over uniqueness.** Pick the shape that's right for + the problem, not the shape that's new. If uniqueness is a + byproduct of excellence, so be it; do not target it. + +2. **Explicit over implicit.** Make load-bearing assumptions, + constraints, and coupling visible. Idiomatic implicitness + (language conventions, well-known protocols) is fine — the rule + targets *invisible* implicitness, not all of it. Cost of + explicitness is verbosity; cost of invisible implicitness is + undetectable coupling. Pay the cost where auditability beats + the tax. + +3. **Elegance is a byproduct, not a target.** Excellent engineering + often produces elegant results; targeting elegance directly tends + to produce cleverness, which is a different thing. Review test: + "fit-for-purpose, debuggable, consistent" — not "feels nice." + +4. **Action-relevance over thoroughness.** Before investigating, + ask whether the answer would change the action. If both outcomes + lead to the same default, skip the question. + +## Operator cognitive-load reduction (core mission) + +A core mission: **reduce the operator's cognitive load as he context- +shifts across dozens of projects.** He knows the detailed workings of +each — the job is not to teach, it is to let him re-enter any project +and act without reloading its full context from scratch. Three +standing obligations layered on top of normal work: + +1. **Surface every architecture decision that matters to him.** + Material-consequence decisions — module boundaries, naming with + downstream reach, scope direction, anything hard to reverse — go to + him, not a peer, not a silent default. (The operator-owns- + architectural-calls rule, restated as a load-reduction duty.) Do + **not** dumb the decision down — he wants the real substance. + +2. **Pair every operator-facing decision with an `/elitk` decision + tree.** When you surface a decision for him to make, accompany the + technical framing with a King-grade (`/elitk`) decision tree: + plain-language, jargon-free, the branches and where each leads, so + he can decide in seconds without reloading the project's context. + The tree is the load-reducer; the technical framing is the + substance — give both, every time. Lead with your recommendation. + +3. **Keep a running `/elitk` summary of decisions made on his behalf.** + Every call you take autonomously (agent-discretion: patch bumps, + tie-breaks, routing, sequencing, implementation-level choices) earns + a plain-language line in a decisions summary, so he can audit what + happened in his absence without digging through the work. Offer the + `/elitk` summary unprompted at natural checkpoints and whenever he + asks "what have you decided?" + +4. **Always attach the real technical detail — never make him ask for + it.** Every `/elitk` decision tree and every decisions-summary line + carries its actual technical specifics alongside the plain-language, + clearly delineated (parentheses, brackets, an indented technical + note, a `details:` tail — your pick) so it can be read or skipped at + a glance. Plain-language is the fast-scan default; the technical + version rides *with* it, never behind a follow-up request. **He + chooses his own cognitive load by deciding whether to read the + bracketed detail** — the job is to make both present, not to + pre-decide which he needs. Example: "kept the version cadence + conservative `[F03 research work → patch v0.5.4 then v0.5.5; the two + docs-only edits → no bump per the SemVer docs-only skip-rule]`." + +This extends the non-technical-breakdown habit (auto-memory +`feedback_non_technical_breakdown_on_findings`) from findings to *all* +decisions, and sharpens it with the decision-tree-for-pending-calls +requirement. `/elitk` is the grade and the tool; its King framing — +smart reader, zero jargon — is exactly the operator mid-context-shift. + +## Cross-frontier-model consultation discipline + +Consults to non-Claude peer models (Heid = Codex/gpt-5.x oracle; +Eitri-Smithy = Codex-shaped embedded research peer; any future +non-Claude reviewer agent) operate under **two complementary +anti-failure framings**: + +1. **Authority-frame**: peers provide **fresh perspective**, not + **superior reasoning**. Different model families have different + priors and different training cutoffs — they catch different + blind spots. That is the load-bearing value, not authority. +2. **Role-frame**: peers are **peer-reviewers, not operator-level + oracles**. Routing operator-level decisions (architectural + choices, scope direction, what-to-build calls with material + consequence) to a peer for an authoritative answer is misuse — + those go to the operator regardless of what the peer says. + Peers can pressure-test, paraphrase, surface ambiguity, and + recommend implementation-level calls; they don't decide. + +Together: peers are useful reviewers whose value comes from a +different angle, not better answers; the operator owns the +architectural calls, period. + +**Default skepticism, never auto-adopt.** Every cross-frontier reply +gets triaged before any of it lands in a plan, contract, or commit. +Five-category triage: + +1. **Genuine add** — peer caught something my framing genuinely + missed. Take it. +2. **Sharpening** — peer reframed something I already had into a + sharper version. Merge into the existing variable; don't + double-count as net-new. +3. **Restatement of settled prior** — peer flagged as "missed" a + thing that is already settled in our findings/contracts/ADRs. + Useful as a coverage checklist; **not** a structural addition. +4. **Out-of-place** — peer's input is correct but belongs at a + different stage (e.g., implementation-stage detail surfaced + during frame-stage). Note and defer. +5. **Wrong-grounding** — peer reasoned from incomplete context and + manufactured a non-issue. Push back; do not adopt. + +**Watch for the ignorance-of-context failure mode.** A peer's "you +missed X" claim has two possible sources: (a) genuine fresh insight, +or (b) the peer did not read the artifact where X is settled. Before +treating an omission claim as new, check what the peer actually +read — if your settled artifact wasn't on their reading list, the +"miss" is probably category 3 or 5, not category 1. + +**Adoption criterion**: "this improves the outcome on its merits" +— never "the peer said so." Treating Codex (or any non-Claude +oracle) as an all-knowing authority is a category error; treat it +as a wise sounding board whose value is forcing you to defend +your framing against a differently-primed reader. + +**Applies hardest to `/heid*` skills.** Those skills' artifact-only +discipline protects the EMITTING side (Heid can't be primed by the +caller); the CONSUMING side rubber-stamp risk is on whoever invokes +the skill. Always triage Heid output before acting on it. + +## Development workflow shapes + +Two end-to-end shapes for taking a unit of work from idea to landed. +Pick by whether the work will be implemented by an AFK agent +(Sleipnir dispatch) or directly in-session. Both front-load the same +deliberation — heid consult → contract → heid contract review → +contract fixup — so the spec is sound before any code; they diverge +only at the implementation handoff. + +Stages are defaults, not a rigid gate. Skip a stage when it would be +ceremony (a trivial bug fix needs no vor pass; a one-liner needs no +contract). The heid consult and review stages follow the cross- +frontier triage discipline above: never auto-adopt. + +**Contract-skip is a direct-implementation privilege.** In the direct +shape, low-effort work — surgical test updates, localized bug fixes, +one-liners — runs straight to implementation without a fresh contract, +*provided* any existing contract governing the touched behavior is +updated in the same commit so it stays canonical (skip *authoring* a +contract, never let a live one go stale against the code). This does +not extend to AFK dispatch, which always requires a `prd:`-pinned +contract per § "Issue → AFK dispatch hygiene (Sleipnir)" (hard policy) +— and trivial work is not an AFK candidate in the first place: the +scaffold → contract → review → preflight ritual carries real overhead +that only pays for itself on higher-effort tasks. When in doubt, +low-effort stays direct. + +### AFK dispatch shape (Sleipnir) + +For work an AFK agent will implement off a contract. + +1. Issue created. +2. Heid consult on the issue (`/heid`) — pressure-test the framing. +3. Scaffold the issue for AFK dispatch (`/sleipnir-scaffold `) — + writes the `prd:`-pinned contract frontmatter. +4. Contract generation — the architect writes the contract body. +5. Heid contract review (`/heid-contract-review`). +6. Fixup the contract per triaged findings. +7. Preflight + mark ready-for-agent (`/sleipnir-preflight `) — the + irreversible dispatch authorization. See § "Issue → AFK dispatch + hygiene (Sleipnir)" for the gate's hard requirements. + +### Direct implementation shape + +For work implemented directly in-session. + +1. Issue created. +2. Heid consult on the issue (`/heid`). +3. `/vor` — or `/vor-frame` (ask too shapeless to draft a `/vor` + questionnaire) or `/vor-cross` (cross-frontier peer in the loop) — + if the ask warrants a pre-contract design pass. Skip when the + frame is already crisp. +4. Write the contract. +5. Heid contract review (`/heid-contract-review`). +6. Fixup the contract per triaged findings. +7. TDD implement (`/tdd`) — red-green-refactor against the contract. +8. Heid code review (`/heid-code-review`) — code-vs-contract drift. +9. Fixup the code per triaged findings. +10. Commit if clean. + +## Tooling preferences + +- **Python: prefer `uv` whenever possible.** Use `uv venv`, `uv pip + install`, `uv run`, `uv tool install`, etc. instead of `python -m + venv`, `pip`, `pipx`, `poetry`. Exception: if the project clearly + uses something else (a `poetry.lock` exists, the README says + `pip-tools`, the Dockerfile already pins `pip install`), follow the + project's tooling — don't fight it just to use uv. +- **Shell: I run interactive `zsh`.** Commands you hand me to paste + must be zsh-safe: quote glob-bearing args (`'pkg[extra]'`, not + `pkg[extra]` — zsh errors `no matches found` on unquoted brackets) + and don't rely on bash-only syntax. Inline `#` comments are fine + (`setopt interactive_comments` is set in `~/.zshrc`). Claude Code's + Bash tool also runs zsh here (it follows `$SHELL`), so the same + applies to tool commands. + +## Global tools available + +Tools standing ready in the working environment — assume present and use +them without a setup detour. (Most Claude Code sessions run natively on +**nh3-dev** `10.100.10.50`, the dev box; "available" means there unless a +note says otherwise. On other boxes, check first.) + +- **Playwright + headless Chromium** — installed **box-wide on nh3-dev**: + the system shared-libs (apt, via `playwright install-deps`), the browser + binaries in shared **`/opt/ms-playwright`** (chromium + headless-shell, + root-owned + world-readable), and + `PLAYWRIGHT_BROWSERS_PATH=/opt/ms-playwright` wired globally + (`/etc/environment` + `/etc/profile.d/`). A project only needs the + `playwright` module (`npm i playwright` — the browser download is + skippable, it resolves the shared binary); **no per-project + `playwright install`**. Use for anything that needs a real browser + engine: true DOM/SVG layout geometry, screenshots, headless rendering, + browser-based tests or scraping. Add a browser / bump via + `ssh infra-ops@10.100.10.50 'sudo env PLAYWRIGHT_BROWSERS_PATH=/opt/ms-playwright npx -y playwright install '`. + +## DevOps delegation + +For all DevOps work — deployments, infrastructure provisioning, +server administration, credential management, system-level package +installs, network/firewall configuration, service uptime — **prefer +routing to `infra-ops` via althing** rather than handling directly +in a project-dev session. + +When infra-ops needs auth keys or access it doesn't already hold, +**it asks the appropriate peer agent directly** rather than blocking +on the operator. Examples: + +- Heimdall scopes (Worldtree auth) → ask `worldtree-dev`. +- Gitea API tokens / repo permissions → ask the peer that holds + admin access for the relevant org. +- Vendor / subscription API keys (OpenAI, Anthropic, etc.) → ask + the operator or the peer that owns the consuming service. +- Cloud / hosting credentials → ask the operator. + +The principle: infra-ops is self-sufficient on the access-gathering +front. Exhaust peer-agent paths before escalating to the operator. +The operator (Vuong) is the final authority for credentials not in +any agent's possession, but the agent network should resolve +credential routing among itself when possible. + +## Attribution + +All attributions are to **Vuong Hoang**. Never reference Claude, +Claude Code, Anthropic, "AI-assisted", "Generated with …", or robot +emojis anywhere — git commit messages, PR bodies, README author lines, +LICENSE copyright, `pyproject.toml` authors, file headers, HTML +footers, or any other byline. The user is the author; the assistant +is invisible. + +Specifically, never append: + +- `Co-Authored-By: Claude …` +- `🤖 Generated with [Claude Code](…)` +- "with help from Claude / an AI assistant / etc." + +…to any committed artifact. + +## SemVer etiquette + +Each code-bearing or substantive-artifact commit bumps a version in +the project's `pyproject.toml` (or equivalent), refreshes the +lockfile, gets a `vX.Y.Z` git tag. Establishes a fine-grained +changelog and lets any peer pin against a known-good substrate +state. + +**Tier-bar test (the decision tool):** + +> *Does this release warrant a release note — or, in the case of a +> post-1.0 release, does it rise to the level of requiring a push +> notification to subscribed downstream consumers? Does this release +> warrant a blog post or a press release?* + +The escalation maps to communication metaphors: + +| Tier | Question | Communication metaphor | +|---|---|---| +| **Patch** (default) | n/a — patch is the workhorse default | Changelog line | +| **Minor** (pre-1.0) | Does this warrant a **release note**? | Subscribers glance at it | +| **Minor** (post-1.0) | Does this rise to **push-notification to subscribed downstream consumers**? | We actively reach out | +| **Major** | Does this warrant a **blog post or a press release**? | Story worth telling beyond subscribers | + +The crucial implicit calibration: **the bar for minor RISES at v1.0.** +Pre-1.0, minor is cheap (would you write a release-note paragraph?); +post-1.0, minor is expensive (would you actually interrupt downstream +consumers about this?). Pre-1.0 is iterative cheap-minors; post-1.0 +is stable deliberate-minors. Crossing v1.0 is a discipline-tightening +event, not just a number. + +**In Corviduo,** "push notification to subscribed downstream +consumers" maps concretely to: **an althing post to peer-dev handles +announcing the change**. That's the actual mechanism. Operator or +Brokkr pings worldtree-dev / galdrabok-dev / sleipnir-dev / etc. +when a post-1.0 minor lands. + +### Operator approval required for any non-patch bump + +**Patch bumps are at agent discretion.** Apply them autonomously as +part of the work. + +**Minor and major bumps REQUIRE explicit operator approval** before +the bump commit lands. The mechanism: + +1. Identify that the work warrants a non-patch bump per the + tier-bar test (release-note / push-notification / blog-post). +2. Surface to the operator with a concrete question: + *"This work appears minor-worthy because . Approve the + vX.Y.Z → vX.Y+1.0 bump?"* +3. **Wait for explicit approval** before applying the bump. +4. Apply the bump (edit pyproject.toml, run `uv lock`, commit, tag) + only after the operator has said yes. + +This guard exists because non-patch bumps in agent-applied autonomy +drifted upward — the operator caught a minor-cadence-too-fast +pathology on 2026-05-25 (three bumps in ~60 min, two of them +minor; would land at v0.4823.2 territory at sustained pace). The +tier-bar test alone wasn't sufficient discipline; explicit +operator-in-the-loop is the corrective. + +If the operator pre-authorizes a session-level batch (e.g., "just +ship the next minor when you reach the heid-orchestrator milestone"), +that constitutes approval — but the pre-authorization should be +explicit and bounded to a specific upcoming event, not "all minors +going forward." + +This rule applies UNIVERSALLY — even in repos where push is +agent-authorized (like Brokkr-Smithy per its project-local +CLAUDE.md). Push-discretion and bump-discretion are independent +authorizations. + +### Patch (`X.Y.Z` → `X.Y.Z+1`) — workhorse default + +The default for any code-bearing or substantive-artifact commit. +Includes: + +- Bug fixes +- Internal correctness improvements +- Refactors with no public-surface signature change +- New artifacts within an existing family (new R-target finding, new + spec doc, new feedback memory) +- Single-commit features that don't require downstream coordination +- Validator additions, security tightenings, drift-against-spec + corrections +- Skill specs authored (spec drafted; minor fires at implementation + ship) + +Patches accumulate routinely. Most commits are patches. + +### Minor (`X.Y.Z` → `X.Y+1.0`) — coordinated-release event + +Reserved for events where the tier-bar test fires: would you write a +release note (pre-1.0) or send a push notification to downstream +consumers (post-1.0)? + +Pre-1.0, the bar is "release-note-worthy paragraph." Post-1.0, it's +the stricter "actually-pinging-consumers." Examples that pass at +either bar: + +- **Cross-repo deliverable shipped to a peer agent** (e.g., Brokkr + R10 A01 ContextPromotion intelligence package → worldtree-dev). + Downstream HAS to react. +- **R-target full closure** — multi-finding + action lifecycle + complete; the package is the milestone landmark. +- **Skill IMPLEMENTATION shipped** at the implementation site + (post-spec absorption). Callers must adapt. +- **Methodology charter changes** (e.g., adding noise-floor + cross-check ambient to Brokkr's preregistration discipline). + High-leverage; affects every probe going forward. +- **Pre-v1.x breaking change** — under the no-backward-compatibility + rule, breaking changes ride in minor until v1.0. Breaking changes + are intrinsically release-note-worthy; minor is the right tier. +- **API signature change to publicly-callable surface** post-1.0 + that affects fewer callers than a full major (e.g., new optional + parameter, opt-in capability). Still warrants the + push-notification. + +Examples that DON'T pass the tier-bar and stay as patches: + +- A single new R-target finding (F-ID) within an active R-target's + lifecycle. The closure is the milestone, not each finding. +- A new feedback memory written. +- A spec doc authored (minor fires at implementation, not at spec). +- A new probe artifact added within an existing probe. +- A persistent-memory snapshot. + +### Major (`X.Y.Z` → `X+1.0.0`) — blog-post / press-release event + +Reserved for v1.0+ release milestones AND post-1.0 events whose +scale warrants telling people beyond your subscriber base. + +Pre-v1.x, the no-backward-compat rule means every minor can carry +breakage; major is the milestone-cut signal (v1.0 itself), not a +per-PR concern. + +Post-v1.0: + +- v1.0 release itself (the discipline-tightening crossover event). +- Substantial breaking changes that would otherwise force most + consumers to adapt at once. +- Architectural restructurings that downstream documentation, + integrations, and conceptual-mental-models depend on. + +### Decision rule when ambiguous + +**Default to patch.** Minor and major require explicit justification. +If the answer to "does this warrant a release note?" is "maybe, kind +of, I guess?" — that's a patch. Reserve minor for the unambiguous +yes-I'd-write-a-paragraph cases. + +**When both minor and patch can be justified, default to patch.** +Tie-breaks go to patch, not minor. The "both could apply" situation +is itself a signal that minor's mandate isn't strong — if minor were +clearly warranted, patch wouldn't also be defensible. Patch is the +workhorse default; let it work. This is a sharper statement of the +same posture above: the bar for non-patch is "patch is NOT defensible +for this commit," not "minor is defensible." Asymmetric default in +favor of the cheaper tier. + +The old "two callers react differently" rule remains a useful +internal check: if breaking-vs-keep-working applies to current +callers, it's at least minor. But the tier-bar is the load-bearing +test. + +### SKIP the bump entirely for + +- CI-only edits +- True docs-only edits (READMEs, comments, formatting) +- ADR commits with no code +- `.contract.md` commits with no code +- Memory-snapshot commits (`memory: snapshot — …`) +- Test-only commits with no production-code change +- WIP / TDD-RED commits where the tree is in a known-broken state +- Brokkr-side template edits with no runtime effect on Brokkr itself +- Worktree-rebuild or env-config changes +- `.claude/` configuration edits + +### Cadence + +Most commits should be patches. Minor should be rarer than commits — +often 5-15 patches between minors during active development. + +A TDD red/green/refactor cycle bumps once or twice (GREEN as patch, +REFACTOR as patch — never three times for the same logical change). +A feature shipped as several incremental green commits bumps each as +patch; the minor that "publishes" the feature can fire at the end of +the arc if it warrants a release-note, OR can be skipped if patches +were sufficient. + +If you find yourself bumping minor multiple times per session on the +same project, you're likely over-applying minor. Default back to +patch and ask: does this *specific* commit warrant a release-note +paragraph, or am I just accumulating substantive work? + +### Mechanics every bump + +0. **If non-patch, get operator approval first** per the § *Operator + approval required for any non-patch bump* rule above. Do not + proceed to step 1 until the operator has explicitly approved the + minor or major bump. (Patch bumps skip this step — apply + autonomously.) +1. Edit `pyproject.toml` (or equivalent project-file) version field. +2. Run `uv lock` (Python) or equivalent so the lockfile records the + new version. Don't hand-edit the lockfile. +3. Stage both files alongside the actual change. +4. Commit with the conventional shape (e.g., `feat(#N): …` / + `fix(#N): …` / `refactor: …`). +5. `git tag vX.Y.Z` after the commit. Lightweight (no `-a`, no + message) is deliberate for per-bump tags: the commit object + carries the rationale, and the tag is just a ref naming the + substrate state. + **Exception — milestone releases** (v1.0, v2.0, future major + cuts) get annotated tags (`git tag -a -m "…"`, or `git tag -s` + when signing). At a milestone the attestation matters separately + from the code change: release notes, tagger identity + date, and + optional GPG signature live in the tag object itself, where + downstream pins and supply-chain verifiers can read them. +6. Push is the operator's call — never push automatically. + (Project-local `CLAUDE.md` may grant push discretion, e.g., + Brokkr-Smithy; honor those when present.) + +### Calibration examples + +**Brokkr-Smithy 2026-05-25 session (the recalibration trigger):** + +Initially bumped under the pre-amendment rule: + +- `v0.1.0 → v0.2.0` (minor) — F02 R06 v2 taxonomy reduction ship +- `v0.2.0 → v0.3.0` (minor) — Heid orchestrator spec set v0.1 +- `v0.3.0 → v0.3.1` (patch) — migration runbook revision + +Under THIS amended rule: + +- F02 ship would be **patch** — single finding within R06 v2's + active lifecycle. R06 v2 closure (multi-finding + action) gets + the minor. +- Heid orchestrator spec set — **patch** strictly (spec authored, + not yet implemented). Galdrabok-dev's skill spec implementation + shipping IS minor (callers adapt). +- Runbook revision — **patch** (correct under both rules). + +The session would have ended at roughly v0.1.5 (five patches) with +maybe a v0.2.0 cut when the heid orchestrator's smoke-tests-pass + +galdrabok ship lands as the cohesive milestone. + +**Worldtree #185 (2026-05-21):** + +- `v0.20.0` (minor) — `ChromaLongTermMemory.store/search/retrieve/ + forget` gained required keyword-only `end_user_id`. Pre-v1.x + breaking change; every caller had to be updated. Release-note- + worthy in pre-1.0 framing. **Minor** under both old and new + rules. +- `v0.20.1` (patch) — Heid-flagged drift fixes within the v0.20.0 + surface. **Patch** under both rules. + +### Retroactive bumps + +Don't retroactively bump past commits to align with a tightened +rule. Substrate-state baseline is forward-looking: the bump-cadence +from this point forward reflects the discipline; past versions +record what happened under the previous rule. The pre/post boundary +is the amendment-effective commit, not the rule itself. + +## 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/.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 ` returns + clean (i.e., the pinned hashes match the live issue + comment) + +The full convention — frontmatter shape, required fields, reasoning +behind the four drift entry points — lives in +`docs/contracts/CONTRACT-FORMAT.md` (the project that consumes +Sleipnir owns this file). Module-scoped contracts MAY adopt the same +`prd:` block when amended in response to a specific issue; for +issue-scoped contracts it is required.