--- 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 ```