Skip to content

Latest commit

 

History

History
151 lines (124 loc) · 8.87 KB

File metadata and controls

151 lines (124 loc) · 8.87 KB

AGENTS.md: Open Northland project contract

Open Northland is a TypeScript reimplementation of Cultures - 8th Wonder of the World. Read this file before editing. Package-local AGENTS.md files add narrower rules.

CLAUDE.md and client command files are adapters. Durable project rules belong here or in the nearest package contract.

Repository and legal boundary

The repository may sit beside an owned game installation and the CulturesNation DataCnmd/ folder. They are pipeline inputs only. Never commit original files, decoded content, binary probes, or reference captures from the original.

This is an independent GPL-3.0-or-later implementation. Do not copy or translate another engine's code. Base format and behavior work must use the sources allowed by docs/SOURCES.md. The canonical legal wording is in docs/LEGAL.md.

Non-negotiable rules

  1. The sim is pure and deterministic. packages/sim cannot use Math.random, wall-clock time, DOM, I/O, Pixi, render, or app imports. Same seed and input must produce byte-identical state.
  2. Sim state is fixed-point. Rendering may interpolate floats. Create Fixed values only through fx.*.
  3. Content is data. Goods, jobs, buildings, tribes, graphics bindings, and balance belong in validated content or the committed fallback catalog. Systems must not grow id-specific rules.
  4. Use the strongest readable source. Prefer mod .ini, then base plaintext .ini, then decoded .cif. Binary claims need byte-level evidence from the owned copy and synthetic tests.
  5. Name approximations. A passing test proves internal behavior, not fidelity. Record whether a mechanic, constant, timing, or visual choice comes from extracted data, readable semantics, byte-level evidence, a published standard, observation, or an approximation.
  6. Treat scale as a budget. Per-tick simulation work scales with active work, not entity pairs. Per-frame rendering and audio work scales with the visible screen, not the map. Measure that claim instead of asserting it: docs/DEVELOPMENT.md says which tool answers which question, and what voids a measurement.
  7. Keep durable context small. Current tasks live in docs/tickets/. Stable rules live in an AGENTS.md. Completed investigation belongs in Git history.

Code quality

  • Prefer names and structure that explain the code without PR context.
  • Prefer no comment when names, types, and tests already state the contract. A useful comment records one otherwise-hidden fact: a unit, invariant, ownership boundary, non-obvious constraint, or source basis. Do not narrate control flow or restate the implementation.
  • Comments describe the current contract, never its history. Never put calendar dates, user/author attribution, conversation, plan, ticket, or PR references, or labels such as "user decision", "feedback", or "revised" in code comments. State source basis impersonally (manual, .ini key, byte evidence, observation, or approximation); keep decision history in the ticket or commit.
  • JSDoc is not required for every export, interface member, or local helper. Do not document a symbol when its name and type already state the contract.
  • Write one direct sentence about one fact. Most comments fit in one to three physical lines; treat anything longer as a structural problem and shorten the comment, improve the code, or move the detail to a test, ticket, or focused document. Only indivisible protocol layouts, security/legal boundaries, and byte-level format evidence justify a longer block.
  • Do not write mini design documents above modules or exports. Avoid phase and caller inventories, {@link} chains that restate the import graph, repeated examples, rhetorical asides, emphasis through capitals, and chains of parenthetical remarks.
  • When behavior changes, rewrite or delete its comment so only the new invariant remains; never append a dated correction or revision note. Leave unrelated historical comments to a dedicated comment pass instead of widening a feature diff.
  • Give each fact one durable home. Investigation, benchmarks, caller inventories, and decision history belong in tests, tickets, or the completing commit, not repeated in production JSDoc.
  • When extracting or moving code, review comments across the old and new modules as one budget. Moving prose is not an improvement, and a behavior-preserving refactor should not grow that budget unless it exposes a previously unstated invariant. Do not add a module header or JSDoc to every new export by default.
  • Refactor structure before adding a long comment about phases, branch purpose, or ownership.
  • Group by feature. When a file passes roughly 300 lines or mixes concerns, extract the relevant concern into a feature folder and preserve public imports through a small barrel when useful.
  • Delete dead code and commented-out blocks. Git is the archive.
  • Deduplicate when a second real caller proves the shared concept. Do not add speculative helpers.
  • Leave touched code cleaner, but do not turn a bounded task into a repository rewrite.
  • Do not add another responsibility, narrative section, or longer orchestration path to an already overgrown file. Extract the concern related to the task; an existing or newly filed cleanup ticket does not permit making the file worse.
  • Enforce boundaries through package structure, types, and existing lint or hygiene checks where possible. Do not add a one-off regex source scanner to prove a local refactor; reserve source scans for repository-wide syntactic contracts that cannot be expressed by those mechanisms.

Use strict TypeScript deliberately: no any, narrow unknown, prefer discriminated unions with exhaustive switches, use string-literal unions rather than enum, mark stable data readonly, use import type, and prove absence cases instead of using non-null assertions.

Working with content

Before changing extraction or a content join, inspect all three:

  1. the real source file in the owned copy;
  2. the decoder or extractor;
  3. generated content/ir.json.

Schema names, fixtures, and tickets are not source evidence. .ini keys are case-sensitive, list shapes vary, and numeric ids may be scoped.

Decoded maps already carry final ground-pattern choices. The current observed projection is a staggered raster with 68 px cell width, 38 px row step, elevation lift TILE_HALF_H / 32, and pre-lift depth sorting.

The sim uses the original half-cell lattice: 2W x 2H, with cell (c, r) at node (2c + (r & 1), 2r). Integer sim commands, footprints, and navigation use half-cell nodes. Fixed-point positions use fractional visual-tile coordinates. nav/halfcell.ts is the conversion seam; cell grids pass through halfCellMapFromCells before becoming a TerrainGraph.

Tickets and workflow

One ticket under docs/tickets/ describes one actionable task. Verify its claims before executing it. Delete a completed ticket in the completing commit; rewrite a partial one to the exact remaining work.

A ticket is a compact task specification, not an investigation transcript. State the verified problem, bounded scope, and verification path; omit development history, large code excerpts, and exhaustive caller inventories unless they are necessary to execute the task safely.

File deferred work only when it is verified, actionable, valuable enough to schedule, and not already covered. Group closely related findings. Minor observations can stay in the current report instead of becoming permanent tracker noise.

/worktree is the primary isolated workflow: create a worktree, implement one requested task, verify and review it, update the ticket, ask for approval, then fast-forward merge. Other workflows are documented under .claude/commands/.

Verification

  • Prove behavior at the lowest useful layer: unit, integration, headless scenario, then browser scene.
  • Normal code expects npm run check, npm run build, and npm test.
  • Pipeline and schema changes also need npm run test:pipeline against the owned copy.
  • Real-content loaders and joins need npm run test:content when local content exists.
  • Golden hashes move only for intentional behavior changes.
  • Visual and audio changes need human review. Automated checks can prove data decisions, stability, and absence of obvious crashes, not final pixels or sound.
  • Player-visible mechanics should have a registered acceptance scene when it adds useful state and presentation coverage.

Commands and local tools are listed in docs/DEVELOPMENT.md. Test modes are explained in docs/TESTING.md.

Package contracts

Load the relevant file when working in that area:

  • packages/sim/AGENTS.md
  • packages/render/AGENTS.md
  • packages/audio/AGENTS.md
  • packages/app/AGENTS.md
  • packages/data/AGENTS.md
  • packages/content-resolver/AGENTS.md
  • packages/vfs/AGENTS.md
  • packages/installer/AGENTS.md
  • packages/desktop/AGENTS.md
  • packages/web/AGENTS.md
  • tools/asset-pipeline/AGENTS.md