Files
settled-reach/docs/sprints/sprint-9/ci.md
T
jpmschweitzerandClaude Opus 4.6 bccdcfcdcb docs(docs): add frontmatter to all sprint briefings
Standardized YAML frontmatter on all 115 sprint briefing files across
sprints 1-26 with title, description, type, status, sprint number, and
team fields.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 00:15:45 +01:00

141 lines
7.9 KiB
Markdown

---
title: "Sprint 9 — CI Briefing"
description: "make pre-pr target, content cross-reference validation, fixture staleness check"
type: sprint
status: archived
sprint: 9
team: "ci"
---
# Sprint 9: Gauntlet — CI Tasks
**Goal:** Build the test infrastructure backbone — test client binary, Gauntlet rooms 1-3, golden file suite, and client QA harness — so every future sprint can be validated end-to-end.
**Branch:** `ci`
**Agents:** Justine (build/deploy)
## Carry-over from Sprint 8
| # | Title | Status | Notes |
|---|-------|--------|-------|
| #460 | make pre-pr target | backlog | Critical — did not start in Sprint 8. Linchpin for the pre-PR validation chain. Blocks #465. |
| #464 | Content cross-reference validation (9 checks) | backlog | Critical — extends `tooling/validate-content`. Standalone from #460. |
| #465 | Fixture staleness check in make pre-pr | backlog | Blocked by #460. |
| #475 | make fixtures-client target (GDScript-generated fixtures for Rust) | backlog | #474 completed Sprint 8 — now unblocked. |
## New Tickets
| # | Title | Blocked by |
|---|-------|------------|
| #475 | make fixtures-client target (GDScript-generated fixtures for Rust) | — (#474 done Sprint 8) |
| #486 | make golden-diff + make golden-update targets | #485 (server) |
| #497 | Checklist YAML schema + make checklist generation | #487 (server) |
## Key Decisions
- `decisions/architecture.md` — D-030 (testability architecture: pre-PR chain, fixture staleness, Layer 3 integration tests; total runtime <3min for pre-PR target)
- `decisions/architecture.md` — D-020 (server binary is a standalone Rust binary; `make pre-pr` must build it as part of the chain)
## Notes
### #460 — make pre-pr target
What exists: The top-level `Makefile` has `validate-content` (wraps `tooling/validate-content`) and individual `ci-server`, `ci-client` targets (see `docs/DEVOPS.md`). The `make pre-pr` target does not yet exist.
What to deliver: `make pre-pr` in the top-level `Makefile` as an ordered chain:
1. `lint-server` (Clippy)
2. `build-server` (cargo build)
3. `test-server` (cargo nextest)
4. `lint-client` (GDScript linter if any)
5. `build-client`
6. `test-client` (gdUnit4 headless)
7. `validate-content` (schema validation)
8. Fixture staleness check (stub hook for #465)
Total runtime target: <3 minutes on a clean build. Branch-specific variants: `make pre-pr-server` (steps 1-3 only), `make pre-pr-client` (steps 4-6 only), `make pre-pr-content` (step 7 only). These let individual teams run their own slice.
Gotcha: Server binary must be built before Layer 3 tests (which spawn it as a subprocess per D-030). Ensure `build-server` precedes `test-server` in the chain. Use `$(MAKE)` for sub-targets to get proper error propagation.
### #464 — Content cross-reference validation (9 checks)
What exists: `tooling/validate-content` is an executable script that runs YAML schema validation. Extend it with a cross-reference pass.
What to deliver: 9 cross-reference checks in `tooling/validate-content` (or a companion script it calls):
1. `canonical_id` uniqueness — no two content items share an ID
2. Relationship target resolution — every `target_id` in a relationship block resolves to a known entity
3. Location slug resolution — every `location_slug` references a known location
4. Dialogue location resolution — every dialogue `location` field resolves
5. Fact tag validity — every fact tag is in the registered tag vocabulary
6. Line pool tag coverage — every monologue line's trigger tags exist in content
7. Archetype consistency — every NPC archetype value is a known enum variant
8. Routine phase validity — every routine `phase` field is a valid DayPhase value
9. (Check 9 is Bidirectional relationship consistency — advisory warning, non-blocking, see #515 for full impl; stub it here as a TODO comment)
Exit 0 if all checks pass (warnings OK for check 9). Exit 1 on any blocking failure. Output: per-check pass/fail with file+line reference for failures.
### #465 — Fixture staleness check in make pre-pr
What exists: `server/tests/gen_fixtures.rs` generates `.msgpack` files at `client/tests/fixtures/msgpack/`. The fixtures committed to git are the source of truth. If code changes alter fixture output without regenerating, client tests will fail with misleading errors.
What to deliver: A script (or Makefile target `check-fixture-staleness`) that:
1. Runs `cargo test gen_fixtures` to regenerate fixtures into a temp location
2. `git diff` the output against `client/tests/fixtures/msgpack/`
3. Exit 1 if any fixture differs (stale fixtures = false positive in client tests)
4. Print a clear message: "Fixtures stale — run `make fixtures-regen` to update"
Integrate as step 8 in `make pre-pr` (blocked by #460 providing the chain structure). Also expose as a standalone `make check-fixtures` target.
### #475 — make fixtures-client target (GDScript-generated fixtures for Rust)
What exists: #474 was completed in Sprint 8 — GDScript encoding asymmetry tests are done and validated. This target is now unblocked. It exercises the reverse direction: GDScript encoder → Rust decoder.
What to deliver: `make fixtures-client` Makefile target that:
1. Runs the Godot headless GDScript test that generates `.msgpack` files at `server/tests/fixtures/gdscript/`
2. The Rust integration test in `server/tests/serialization.rs` (or a new file) then verifies it can decode those files
This validates the full bidirectional protocol: Rust encodes → GDScript decodes (#474), GDScript encodes → Rust decodes (#475). Together they close the cross-encoder compatibility loop.
### #486 — make golden-diff + make golden-update targets
What exists: Blocked by #485 (server golden file suite). The golden file lives at `tests/golden/gauntlet_tick_10.json` (created by #485).
What to deliver: Two Makefile targets:
- `make golden-diff`: runs the golden file test, shows a diff if the output has changed (use `diff --color` or `jq` for pretty output). Exits 1 if changed.
- `make golden-update`: regenerates `tests/golden/gauntlet_tick_10.json` from a fresh run and stages it with `git add`. Does NOT commit — leaves the diff for developer review.
These are developer workflow targets, not CI gates. Document in `make` help output.
### #497 — Checklist YAML schema + make checklist generation
What exists: Blocked by #487 (server Gauntlet rooms — provides room IDs for checklist scope). Checklists live at `content/gauntlet/rooms/{room_id}/checklist.yaml` (per-room) and `content/gauntlet/cross_room_checks.yaml`.
What to deliver:
- YAML schema definition (JSON Schema or serde-compatible struct): 7 condition types: `player_near`, `player_facing`, `entity_present`, `entity_absent`, `expected_monologue`, `expected_dialogue`, `expected_interaction_verb`. Each condition has `id`, `description`, `condition_type`, and type-specific fields.
- `make checklist-generate` Makefile target: validates all checklist YAML against the schema, outputs a summary of condition counts per room
- `make checklist-validate` target: runs the schema check standalone (useful in pre-PR chain)
The checklist format feeds into #503 (client auto-checklist progress tracking) in Sprint 10. Design the schema with that consumer in mind — conditions should be evaluable from an `ObserverSnapshot`.
## Dependency Chain
```
#460 (make pre-pr) — start immediately, no blockers
-> #465 (fixture staleness check)
#464 (content cross-reference validation) — standalone, parallel to #460
#474 (done Sprint 8) -> #475 (make fixtures-client, unblocked)
#485 (server, golden suite) -> #486 (make golden-diff + golden-update)
#487 (server, Gauntlet rooms) -> #497 (checklist YAML schema)
```
## PR Workflow
When ready to submit, create a PR with `tea` CLI. **All flags are required** to avoid TTY prompts (see CLAUDE.md "Gitea access" section):
```bash
tea pr create --repo jpmschweitzer/settled-reach --login schweitz --title "feat(ci): sprint 9 gauntlet — pre-pr chain, content validation, golden targets" --description "body" --base main --head ci
```