chore(meta): docs/build sweep + tooling test gate (T-1069, T-1066)

- make test-tooling: planet-gen determinism guard + import_economics
  --dry-run, wired into pre-push on TOOLING_CHANGED; ruff widened to
  E4/E7/E9/F/W (90 safe auto-fixes applied; E402/E702/F841 ignored with
  documented counts)
- one-generator reality fixed in DEVOPS.md, asset-pipeline rule, CLAUDE.md
  (import_economics sole generator since #951/D-223); dead check-protocol
  target deleted; DEVOPS hook/config sections rewritten from the actual
  hook sources; team-patterns gate description updated (client+tooling)
- project.yaml: 0.2.0 → 0.4.0 per the 0.{phase}.{n} scheme, description
  refreshed from the v0.1 Sova narration to cascade reality
- stale comment sweep: voxel.rs stub claims (all 8 families implemented),
  cascade.rs TODO recited to T-1044, main.rs D-192 handshake claim,
  relationships.rs/chunk_streaming.rs version targets → phase language
- gitignore: client/settings.db* e2e-run artifacts

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-06-12 16:22:55 +02:00
co-authored by Claude Fable 5
parent 0bd895fcac
commit 346d87df7a
47 changed files with 280 additions and 180 deletions
+61 -27
View File
@@ -73,6 +73,7 @@ The server must be running before the client connects (subprocess launch will be
make test # Run all tests (test-server + test-client)
make test-server # Rust tests via tests/run-rust (cargo nextest, JSON summary)
make test-client # Godot tests via tests/run-godot (gdUnit4 headless, JSON summary)
make test-tooling # Tooling gate: planet-gen determinism guard + import_economics --dry-run (T-1066)
```
The IPC test layers (D-030) have dedicated targets:
@@ -210,20 +211,21 @@ Schema: `content/_schema/checklist.schema.json`. The checklist format feeds into
## Asset Pipeline — Generator-Driven DB (#855, #856, #857)
`server/data/systems.db` is a **read-only canonical snapshot** produced by three
generators. It is committed to the repo so the client can ship it, but it is never
`server/data/systems.db` is a **read-only canonical snapshot** produced by a single
generator. It is committed to the repo so the client can ship it, but it is never
the source of truth. Direct edits are forbidden — they are silently overwritten by
the next regeneration.
### Generators
### Generator
| Generator | Source | Runs via |
|-----------|--------|----------|
| `generate_brands` | `server/src/bin/generate_brands/main.rs` | `tooling/generate-brands` |
| `import_economics` | `tooling/economy-db/import_economics.py` | `python3 tooling/economy-db/import_economics.py` |
| `generate_atlas` | `tooling/planet-gen/generate_atlas.py` | `python3 tooling/planet-gen/generate_atlas.py --seed 42` |
`import_economics` (`tooling/economy-db/import_economics.py`) is the sole
generator. As its first step it shells out to the Rust `generate_brands` binary
(via `tooling/generate-brands`) to refresh `generated_brands.toml`, then imports
economics data and the atlas index (names-only city pool; geometry tables stay
empty for the Phase 4 server cascade). The former atlas geometry generator
(`generate_atlas`) was retired in #951 (D-223).
Run all three at once with:
Run it with:
```bash
make regen-db
@@ -231,8 +233,9 @@ make regen-db
### Meta table stamp
After every successful non-dry-run, each generator writes a row to the `meta` table in
`systems.db` recording the SHA-1 of its source file(s) and the schema file.
After every successful non-dry-run, the generator writes a row to the `meta` table in
`systems.db` recording the SHA-1 of its source files and the schema file. The source
registry is the `GENERATOR_SOURCES` dict in `tooling/check-systems-db-stamp`.
```bash
make check-systems-db # Verify the stamp is fresh (exit 1 = stale)
@@ -265,16 +268,43 @@ Or manually:
git config core.hooksPath .config/hooks
```
Active checks:
### Pre-commit checks (`.config/hooks/pre-commit`)
| Hook | Check | Script | Behavior |
|------|-------|--------|----------|
| pre-commit | fact_id validation | `tooling/check-fact-ids` | Warns if catalogs are stubs; fails on unknown fact_ids when populated |
| pre-push | GDScript parse | internal | Fails on any SCRIPT ERROR |
| pre-push | Rust lint | internal | fmt + clippy |
| pre-push | Python lint | internal | ruff |
| pre-push | JSON syntax | internal | python3 -m json.tool |
| pre-push | systems.db stamp | `tooling/check-systems-db-stamp` | Rejects stale DB when pushed (#857) |
| Check | Script | Behavior |
|-------|--------|----------|
| fact_id validation | `tooling/check-fact-ids` | Warns if catalogs are stubs; fails on unknown fact_ids when populated |
| Decision records | `pql decisions validate` | Blocks on malformed decision records (warns if pql not on PATH) |
| Planning changelog | `pql plan export --stage` | Flushes ticket mutations to `.pql/changelog/` and stages them into the commit (warn-only on failure) |
| cargo audit | `cargo audit` | Only when `Cargo.toml`/`Cargo.lock` is staged; blocks on advisories (warns if cargo-audit not installed) |
### Pre-push checks (`.config/hooks/pre-push`)
There is **no CI** — the pre-push gate is the only automatic verification, so it is
deliberately comprehensive. Checks are scoped to what actually changed vs the remote
(`origin/<branch>`, falling back to `origin/main` for first pushes): `client/` changes
gate the GDScript checks, `server/` the Rust checks, `tooling/` + `pyproject.toml` the
Python checks.
| Check | Runs when | Behavior |
|-------|-----------|----------|
| GDScript parse (headless Godot) | `client/` changed | Blocks on any SCRIPT ERROR (skipped if no `client/.godot/` import) |
| gdlint | `client/` changed | **Advisory** until the codebase is clean |
| gdformat --check | `client/` changed | **Advisory** until the codebase is clean |
| `cargo fmt --check` | `server/` changed | Blocks |
| `cargo clippy --all-targets -- -D warnings` | `server/` changed | Blocks (skipped if no `server/target/` — cold worktree) |
| `cargo test` | `server/` changed | Blocks — the only automatic correctness gate (skipped if no `server/target/`) |
| `cargo deny check` | `server/` changed | Blocks (only if cargo-deny installed and `server/deny.toml` exists) |
| `ruff check tooling/` | `tooling/` changed | Blocks |
| `make test-tooling` | `tooling/` changed | Blocks — sim determinism guard + economics dry-run (T-1066) |
| JSON syntax (`python3 -m json.tool`) | any changed `*.json` | Blocks on syntax errors |
| systems.db stamp | `server/data/systems.db` in push | Blocks on stale stamp (#857); missing meta table warns only |
| Clerk review (D-221) | **disabled** (#965) | Force-run with `SR_RUN_CLERK=1` |
### Post-merge / post-checkout / post-rewrite
These hooks replay the pql planning changelog (`pql plan import` / `rebuild`) and
re-sync decisions from `governance/*.md` so the planning DB stays in step after
merges, checkouts, and history rewrites.
The `core.hooksPath` setting uses a relative path (`.config/hooks`) that resolves per worktree, so it works correctly across all worktrees in the repository.
@@ -282,18 +312,22 @@ To bypass hooks in an emergency:
```bash
git commit --no-verify -m "fix: emergency hotfix"
git push --no-verify
```
## Configuration Files
The `.config/` directory holds shared configuration for linters, formatters, and CI. Examples of what goes here:
The `.config/` directory currently holds exactly one thing: the version-controlled
git hooks in `.config/hooks/` (pre-commit, pre-push, post-merge, post-checkout,
post-rewrite), activated via `git config core.hooksPath .config/hooks`
(`make install-hooks`).
- Clippy configuration overrides
- gdlint/gdformat rules
- CI workflow definitions (before moving to `.github/workflows/`)
- Editor config templates
Project-specific config that lives in subdirectories (e.g., `server/Cargo.toml`, `client/project.godot`) stays in those directories. `.config/` is for cross-cutting or shared configuration.
Linter and formatter configuration lives with the code it governs, not in `.config/`:
ruff is configured in the root `pyproject.toml` (`[tool.ruff]`), Rust uses cargo
defaults plus `server/deny.toml`, and the client uses gdlint/gdformat defaults.
Project-specific config (e.g. `server/Cargo.toml`, `client/project.godot`) stays in
those directories. `.config/` is reserved for future cross-cutting configuration
that has no better home.
## Cache Directory