Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
181 changes: 181 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
# Contributing to Claude Kingdoms

Welcome. Claude Kingdoms is built by its community (PRD §"Design
Pillars" #4). This doc covers the **four contribution paths**, the
test-ownership rules, the PR process, and how to find a `good first
issue`.

## The four contribution paths

You can contribute to any one of these without touching the others.
Pick the one that matches your interest.

### 1. Bridge (Python, async, no game engine knowledge required)

The bridge is the scoring + persistence layer. It ingests Claude Code
hook events, classifies session state, computes per-turn rewards, and
writes the save exchange that the Unciv mod reads.

Files: `bridge/`, `bridge/tests/`. Entry point:
`python -m bridge.daemon`.

What lives here:
- `session_state.py` — `Session` and `SessionState` dataclasses
- `scoring.py` — `ScoringEngine` + `SimpleScoringStrategy`
- `hook_listener.py` — Claude Code event ingestion → state mutations
- `bridge_loop.py` — turn pump
- `save_exchange.py` — atomic JSON file I/O
- `audit_log.py` — append-only event log (JSONL)
- `daemon.py` — production CLI entrypoint

Good for you if: you like clean Python, async, and dataclass-based
state machines. Type hints are appreciated.

### 2. TUI (Python, Textual)

The TUI is the player's window into the bridge. It shows live session
state, supports manual event injection (PRD §BR-11), and walks new
players through the onboarding emotional contract.

Files: `tui/`, `tui/tests/`. Entry point: `python run_tui.py`.

What lives here:
- `app.py` — `MainApp`, `KingdomView`, `TurnEstimatePanel`,
`EventLogPanel`
- `onboarding.py` — `OnboardingScreen` + `OnboardingState`
- `medieval_voice.py` — flavor strings + state-change translator

Good for you if: you've used Textual or want to learn it; you have
opinions on accessibility, color contrast, or keyboard ergonomics.

### 3. Unciv mod (JSON + Lua)

The mod side is the actual game. It defines The Operators civ, the
Session Forge building, tutorials, and the Lua hook that reads the
bridge's save exchange and applies per-city rewards at turn boundary.

Files: `mod/ClaudeKingdoms/`. Install instructions:
`mod/ClaudeKingdoms/README.md`.

What lives here:
- `jsons/Nations.json` — The Operators civilization
- `jsons/Buildings.json` — Session Forge + Charter Hall
- `jsons/Tutorials.json` — six tutorials including the no-decay promise
- `jsons/Beliefs.json` — pantheon for theme
- `mod.lua` — runtime hook reading `kingdom_save.json`
- `ModOptions.json` — Unciv mod metadata

Good for you if: you've modded Unciv or another Civ-like, you read
Lua fluently, or you want to author medieval-flavor content.

### 4. Documentation (Markdown, no code)

Documentation is a first-class deliverable (PRD acceptance #12). The
docs ARE the contract for parallel contributors.

Files: `docs/`, top-level Markdown files (`README.md`, this file,
`mod/ClaudeKingdoms/README.md`).

What lives here:
- `docs/prd/ClaudeKingdomsPRD.md` — the source of truth
- `docs/adr/` — architectural decision records (ADR-001..003)
- `docs/bridge-tui-schema.md` — the binding contract for paths 1 + 2
- `docs/hooks-setup.md` — wiring Claude Code hooks to the bridge
- `docs/audit-2026-05-08.md` — CTO audit (snapshot, supersede on update)

Good for you if: you write clearly, think about onboarding, or just
notice when an instruction doesn't match the code.

## Test ownership matrix (from PRD §"Test Ownership Matrix")

| Layer | Owner | Test type |
|-------|-------|-----------|
| Bridge session state machine | Bridge contributor | Unit |
| Bridge scoring / reward calculation | Bridge contributor | Unit |
| Hook event parsing | Bridge contributor | Unit |
| Bridge → TUI schema compliance | Shared (Bridge + TUI) | Contract (`bridge/tests/test_prd_schema.py`) |
| Save exchange write/read round-trip | Bridge contributor | Integration |
| TUI state rendering from bridge payload | TUI contributor | Unit |
| Mod JSON / Lua | Mod contributor | Smoke (`bridge/tests/test_mod_jsons.py`) |
| End-to-end vertical slice | Shared | Integration (`bridge/tests/test_e2e_vertical_slice.py`) |

CI threshold per PRD: **80%** coverage for bridge scoring + session
state modules. CI runs `pytest -q` on every push and PR (see
`.github/workflows/tests.yml`).

## PR process

1. **Branch** from `main`. Use `feat/<scope>` for new features,
`fix/<scope>` for bug fixes, `docs/<scope>` for doc-only changes,
`test/<scope>` for test-only changes.
2. **TDD when feasible** (PRD design pillar #5). Add the failing test
first; write the minimum change that makes it pass; layer in
enrichment.
3. **Run `pytest -q` locally** — green or you don't push.
4. **Open a PR** with:
- One-line summary
- "Closes / Toward kanban: t_…" line if it maps to a kanban task
- "Test plan" checklist
- PRD section reference if the change closes a requirement
(BR-x / BS-x / CL-x / GM-x / TU-x / acceptance #x)
5. **Wait for CI** (GitHub Actions). PRs with failing CI do not merge.
6. **Reviewer + merge** — the merger runs `gh pr merge <n> --merge
--delete-branch` once review approves.

### Safety rules (project-wide)

- No `git push --force` to `main`.
- No `--no-verify` / `--no-gpg-sign` — fix the underlying issue.
- No third-party deploy commands without explicit approval (this
project doesn't deploy anywhere yet, but the rule is on the books).

## Finding a `good first issue`

Acceptance criterion #13: "New contributor completes a `good first
issue` without asking for help." We label issues that fit this
description with `good first issue` on GitHub.

Some standing options if no labeled issues are open:

- **Bridge**: write a unit test for an edge case in `SimpleScoringStrategy`
that isn't covered yet — e.g., what happens if `momentum` goes negative,
what happens with extremely large token counts, etc.
- **TUI**: improve `EventLogPanel` rendering — currently caps at 8 lines,
could scroll, or could highlight the most recent event.
- **Mod**: add a fourth medieval city name to The Operators' city list,
with a one-line in-character description in `Tutorials.json`.
- **Docs**: pick any spot in the codebase where a function comment is
missing or stale and write a clear one. Or notice when an old kanban
task title or PR ref is wrong and fix it.

## Code style

- Python: 4-space indent, type hints on public APIs, docstrings on
every module and every public class/function. No `# noqa` without
explanation.
- Markdown: 80-col soft limit, ATX headers (`#`), prefer tables for
status lists, fenced code blocks with language tags.
- Lua: 4-space indent, `local` for everything by default, no globals
outside an explicit `mod` table.
- JSON: 2-space indent, trailing commas NOT allowed (Unciv parses
with strict JSON).

## Communication

- **Bug reports / feature requests**: GitHub Issues
- **Design questions / RFCs**: GitHub Discussions (when enabled)
- **Architectural decisions**: ADR PR against `docs/adr/`
- **Quick questions**: comment on the relevant PR or kanban task

The kanban board (Hermes-managed at `http://127.0.0.1:9119/kanban`
locally) is internal coordination — external contributors interact
through GitHub Issues / PRs.
Comment on lines +170 to +172
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The reference to a local kanban board URL (http://127.0.0.1:9119/kanban) and the 'Hermes-managed' tool might be confusing for external contributors as it refers to an internal environment. If this tool is required for contribution, please provide instructions on how to set it up. Otherwise, consider moving this to a maintainer-specific section or clarifying that it is for core team use only.


## License

MIT. By contributing, you agree your contribution is MIT-licensed.

---

*This document is acceptance criterion #12 from the PRD. If something
here is unclear or wrong, fixing it is itself a `good first issue`.*
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

An open-source medieval grand strategy game powered by Claude Code session activity.

> **GIF placeholder** — `docs/media/session-to-reward-loop.gif` (PRD acceptance criterion #11). To be recorded after the M4 tutorial map is in place; capture target is a 30-second loop showing: (1) bridge daemon running, (2) Claude Code session active, (3) plan + goal events firing, (4) end-turn in Unciv, (5) per-city resource increase landing on the map. See `docs/media/README.md` for the recording protocol.

## Vision

Turn your real Claude Code sessions into an empire. Every plan created, every goal completed, and every active session grows your kingdom. Idle hands stir nothing; active minds stir empires. The kingdom never decays when you step away — but it only grows when you return.
Expand Down
62 changes: 62 additions & 0 deletions docs/media/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# `docs/media/` — recorded assets for the README and launch posts

This folder holds video / GIF / screenshot assets referenced from the
top-level README and PRD-driven launch material.

## Required asset for V1 launch

Per PRD acceptance criterion #11: *"README includes working GIF of the
session-to-turn reward loop."*

**Target file**: `docs/media/session-to-reward-loop.gif`

### Recording protocol

A reproducible 30-second capture should show, in order:

1. **(0:00–0:05)** `python -m bridge.daemon` running in one pane,
`python run_tui.py` in another. The TUI's KingdomView shows a
single ACTIVE session; net turn estimate is non-zero.
2. **(0:05–0:12)** Claude Code session in a third pane: a real prompt
submitted; the TUI EventLogPanel scrolls a "rises to action"
medieval-voice line via the listener's on_change → `voice_for_change`.
3. **(0:12–0:18)** A `SubagentStart type=Plan` event fires; EventLogPanel
shows "A new charter is drafted for 'Royal Court'." TurnEstimatePanel
bumps by `+15` (PRD §BR-6).
4. **(0:18–0:24)** A `TaskCompleted` event fires twice. EventLogPanel
shows "completed 1 goal", momentum increments, TurnEstimatePanel
reflects the goal bonus.
5. **(0:24–0:30)** End turn in Unciv — the per-city rewards land on
the city tile; gold/science/production tickers visibly increment.

### Recording tools

Recommended (cross-platform):
- **OBS Studio** (free) for screen capture, encode at 30fps, export
to MP4
- **gifski** or **ffmpeg** for MP4 → GIF conversion at 12fps and
640px width to keep file size reasonable for GitHub README rendering
(target <5MB)

Sample ffmpeg + gifski pipeline:

```bash
# Capture with OBS to capture.mp4, then:
ffmpeg -i capture.mp4 -vf "fps=12,scale=640:-1:flags=lanczos" -c:v ppm -f image2pipe - \
| gifski -o session-to-reward-loop.gif --fps 12 -
```

### Why this is a placeholder

The GIF can't be authored until M4 is in place — the campaign map and
the tutorial flow need to render Unciv-side resource changes for the
final five seconds of the recording to be meaningful. Until then, the
README links to this folder as the planned location.

## Other assets (when added)

- Screenshots used in launch posts (r/Unciv, r/ClaudeCode, Hacker News,
ModDB per PRD §M5) should live here too, named with the platform tag,
e.g. `launch-hn-screenshot.png`.
- Any subsequent demo recordings (a longer "live coding for an hour →
empire grows over a real Pomodoro" video) similarly.
Loading