docs(ci): document source-canonical asset pipeline rule
Adds `.claude/rules/asset-pipeline.md` describing the full pipeline — generators, meta stamp, pre-push hook, how to make DB/schema changes, and why direct systems.db edits are forbidden. CLAUDE.md and DEVOPS.md point at the rules file; sprint-start template now reminds teammates to read it before touching DB sources. CLAUDE.md also gains the missing `decision show` row in the CLI tool table (companion to #723's `decision show` subcommand). Refs: #859 #723 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
# Asset Pipeline — Source-Canonical Rule
|
||||
|
||||
`server/data/systems.db` is a **read-only, deterministic snapshot** produced by the
|
||||
generator pipeline. It is checked in to the repo as a build artefact so the Godot
|
||||
client can ship it without a build step, but **it is never the source of truth**.
|
||||
|
||||
---
|
||||
|
||||
## The Golden Rule
|
||||
|
||||
> **Edit sources, not the DB.**
|
||||
|
||||
If you need to change economics data, modify the TOML/JSON source files.
|
||||
If you need to change atlas markers, modify the `markers.json` files.
|
||||
Never run `UPDATE` or `INSERT` directly on `server/data/systems.db` outside of a
|
||||
migration — those changes will be silently overwritten by the next `make regen-db`.
|
||||
|
||||
---
|
||||
|
||||
## What produces systems.db
|
||||
|
||||
Three generators write to `systems.db` in sequence:
|
||||
|
||||
| Generator | Command | Source files |
|
||||
|-----------|---------|--------------|
|
||||
| `generate_brands` | `tooling/generate-brands` | `server/src/bin/generate_brands/main.rs` |
|
||||
| `import_economics` | `python3 tooling/economy-db/import_economics.py` | `tooling/economy-db/import_economics.py` |
|
||||
| `generate_atlas` | `python3 tooling/planet-gen/generate_atlas.py --seed 42` | `tooling/planet-gen/generate_atlas.py` |
|
||||
|
||||
`make regen-db` runs all three in the correct order.
|
||||
|
||||
---
|
||||
|
||||
## The meta table stamp (#855, #856)
|
||||
|
||||
After every successful non-dry-run, each generator writes a row to the `meta` table:
|
||||
|
||||
```sql
|
||||
CREATE TABLE meta (
|
||||
generator_name TEXT PRIMARY KEY, -- 'import_economics' | 'generate_atlas' | 'generate_brands'
|
||||
schema_version TEXT NOT NULL, -- SHA-1 of server/data/systems-schema.sql at generation time
|
||||
generator_sha TEXT NOT NULL, -- SHA-1 of the generator source file(s)
|
||||
generated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
```
|
||||
|
||||
The `generator_sha` is the SHA-1 of the generator source file content. If the source
|
||||
changes and `regen-db` is not re-run, the stamped SHA will differ from the current file
|
||||
SHA — this is what the pre-push hook detects.
|
||||
|
||||
---
|
||||
|
||||
## How to make a DB change
|
||||
|
||||
### Normal data changes (economics, atlas markers)
|
||||
|
||||
1. Edit the source files (TOML, JSON, markers.json).
|
||||
2. Run `make regen-db`.
|
||||
3. Run `make check-systems-db` to confirm the stamp is fresh.
|
||||
4. Stage and commit:
|
||||
```bash
|
||||
git add server/data/systems.db
|
||||
git commit -m "chore(db): regen systems.db — <what changed>"
|
||||
```
|
||||
|
||||
### Schema changes (new tables or columns)
|
||||
|
||||
1. Add the DDL to `server/data/systems-schema.sql`.
|
||||
2. Add migration SQL to `MIGRATION_SQL` in `import_economics.py` if the change
|
||||
affects existing DBs (idempotent `CREATE TABLE IF NOT EXISTS` or `ALTER TABLE`).
|
||||
3. Run `make regen-db`.
|
||||
4. Stage `server/data/systems-schema.sql` and `server/data/systems.db` together.
|
||||
|
||||
---
|
||||
|
||||
## Pre-push hook (#857)
|
||||
|
||||
`.config/hooks/pre-push` (installed via `make install-hooks`) checks that whenever
|
||||
`server/data/systems.db` is in the push, its meta stamp matches the current generator
|
||||
source SHAs. If not, the push is rejected with:
|
||||
|
||||
```
|
||||
systems.db is stale — run `make regen-db` before pushing.
|
||||
Stale generators: ['import_economics']
|
||||
```
|
||||
|
||||
Fix: run `make regen-db`, stage `server/data/systems.db`, amend or add a commit.
|
||||
Or use `/pr-push` — it detects stale generator sources and reruns `make regen-db`
|
||||
automatically before pushing.
|
||||
|
||||
The check script is `tooling/check-systems-db-stamp`. Run it interactively with
|
||||
`make check-systems-db` or `python3 tooling/check-systems-db-stamp --verbose`.
|
||||
|
||||
---
|
||||
|
||||
## /pr-push integration (#858)
|
||||
|
||||
The `/pr-push` skill checks whether any generator source files are modified on the
|
||||
branch. If they are, it automatically runs `make regen-db` and stages the updated
|
||||
`server/data/systems.db` before pushing — preventing pre-push hook rejections on
|
||||
branches that modify generators without regenerating.
|
||||
|
||||
---
|
||||
|
||||
## Why direct DB edits are forbidden
|
||||
|
||||
Two branches that both commit `server/data/systems.db` changes produce a binary
|
||||
merge conflict. Git cannot diff or merge binary SQLite files. Sprint 36 hit this
|
||||
exact class of problem. The meta stamp + pre-push hook is the systematic fix:
|
||||
|
||||
- Regeneration is deterministic (same sources → same DB, byte-for-byte)
|
||||
- Only one branch modifies generator sources at a time (per team scope rules)
|
||||
- The pre-push hook is a hard blocker before the binary conflict can land
|
||||
|
||||
---
|
||||
|
||||
## Future: savegame migration lineage
|
||||
|
||||
The `meta.schema_version` field records the schema SHA at generation time. When the
|
||||
savegame system is built (Phase 5+), a save file can record which systems.db snapshot
|
||||
it derives from, enabling forward migration without branching the DB file itself.
|
||||
@@ -423,6 +423,9 @@ Task(
|
||||
|
||||
1. Read the sprint briefing: docs/sprints/sprint-{N}/{team}.md
|
||||
2. Read the decision files referenced in the briefing.
|
||||
If your work touches systems.db sources (markers.json, TOML files,
|
||||
or generator code), read .claude/rules/asset-pipeline.md before
|
||||
modifying anything.
|
||||
3. Check TaskList for available work.
|
||||
4. Claim an unblocked task (TaskUpdate with owner: your name),
|
||||
mark it in_progress, and implement it.
|
||||
|
||||
Reference in New Issue
Block a user