#465: Fixture staleness check — Built into pre-pr-fixtures target. Regenerates fixtures, checks git diff, exits 1 on stale (blocker per Tyre's argument).
Schema fix — Added focused (mood) and greeting (situation) to dialogue-pool schema for Sprint 7-8 content.
Current validation results
Pass 1 (schema): 47 validated, 0 errors
Pass 2 (cross-references): 0 errors, 21 warnings (npc_count mismatch + missing reciprocal relationships — real content issues for copy team)
Files changed
File
Change
Makefile
8 new pre-PR targets
tooling/validate-content
ContentIndex class with 9 cross-reference checks
content/_schema/dialogue-pool.schema.json
Added focused, greeting enum values
docs/DEVOPS.md
Pre-PR checks documentation
Test plan
make help shows new targets
make --dry-run pre-pr shows correct chain
make validate-content runs both passes successfully
Cross-reference checks detect real issues (npc_count, reciprocal relationships)
Schema validation passes after enum fix
## Summary
Sprint 8 CI team deliverables from the Test Architecture Workshop (Epic #455):
- **#460: `make pre-pr` target** — Full pre-PR chain: lint → build → test → content validation → fixture staleness. Branch-specific variants: `pre-pr-server`, `pre-pr-client`, `pre-pr-content`.
- **#464: Content cross-reference validation (9 checks)** — Extends `tooling/validate-content` with Pass 2 (ContentIndex): canonical_id uniqueness, relationship targets, location slugs, dialogue locations, fact_ids, triangle membership, npc_count, dialogue line_ids, bidirectional relationships.
- **#465: Fixture staleness check** — Built into `pre-pr-fixtures` target. Regenerates fixtures, checks git diff, exits 1 on stale (blocker per Tyre's argument).
- **Schema fix** — Added `focused` (mood) and `greeting` (situation) to dialogue-pool schema for Sprint 7-8 content.
## Current validation results
- Pass 1 (schema): 47 validated, 0 errors
- Pass 2 (cross-references): 0 errors, 21 warnings (npc_count mismatch + missing reciprocal relationships — real content issues for copy team)
## Files changed
| File | Change |
|------|--------|
| `Makefile` | 8 new pre-PR targets |
| `tooling/validate-content` | ContentIndex class with 9 cross-reference checks |
| `content/_schema/dialogue-pool.schema.json` | Added `focused`, `greeting` enum values |
| `docs/DEVOPS.md` | Pre-PR checks documentation |
## Test plan
- [x] `make help` shows new targets
- [x] `make --dry-run pre-pr` shows correct chain
- [x] `make validate-content` runs both passes successfully
- [x] Cross-reference checks detect real issues (npc_count, reciprocal relationships)
- [x] Schema validation passes after enum fix
Adds 'focused' to mood enum and 'greeting' to situation enum in
dialogue-pool.schema.json. Both values are used by Sprint 7-8
dialogue content but were not added to the schema at the time.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Well-structured 2-pass validation engine with 9 meaningful cross-reference checks. Clean Makefile additions following existing conventions. One dead function and one logic gap worth noting.
#
File
Severity
Issue
1
validate-content:85-94
warning
_file_type defined but never called — dead code, remove
2
validate-content:~293
warning
_check_4_dialogue_locations silently passes when district_locs is empty set — dialogue referencing nonexistent location won't be caught if district has no locations declared
3
Makefile:~160
warning
pre-pr-fixtures suppresses stderr with 2>/dev/null — if fixture generation fails, error is swallowed and git diff check proceeds against stale fixtures (false pass)
4
validate-content:~168
suggestion
_scan_knowledge regex fallback undocumented — explain what catalog format triggers it
5
validate-content:~299
suggestion
_check_5_fact_ids early return prints no message when skipping — add advisory note to output
Example commit message uses placeholder vN — provide concrete example
Tyre (Architecture): REQUEST_CHANGES
2-pass architecture sound, branch-scoped pre-PR variants well-designed. One critical logic bug and one scoping gap need fixing.
#
File
Severity
Issue
1
Makefile:~148 pre-pr-fixtures
critical
2>/dev/null on cargo test --test gen_fixtures swallows compilation/runtime failures — fixture generation that errors produces false pass on the staleness check (the exact scenario this gate prevents)
2
validate-content:~416 _check_8
warning
Line ID uniqueness check is per-file only — two dialogue files for same location with overlapping IDs would pass. Should be cross-file.
3
validate-content:~441 _check_9
suggestion
Bidirectional relationship check will produce false warnings on intentional asymmetric relationships (D-034) — document that asymmetric is valid
4
dialogue-pool.schema.json:~91
suggestion
focused brings mood count to 9 but D-035 says "8 moods for v0.1" — update decision or document addendum
Verdict: CHANGES REQUESTED
Key issues:
pre-pr-fixtures2>/dev/null must be removed — swallowed errors defeat the safety gate (both reviewers flagged)
_check_8_dialogue_line_ids should validate cross-file, not just per-file
Dead function _file_type — remove
Empty district_locs bypass in check 4 — silent false negative
## Review: ci → main (type: code)
### Hoshe (Code Quality): APPROVE
Well-structured 2-pass validation engine with 9 meaningful cross-reference checks. Clean Makefile additions following existing conventions. One dead function and one logic gap worth noting.
| # | File | Severity | Issue |
|---|------|----------|-------|
| 1 | validate-content:85-94 | warning | `_file_type` defined but never called — dead code, remove |
| 2 | validate-content:~293 | warning | `_check_4_dialogue_locations` silently passes when `district_locs` is empty set — dialogue referencing nonexistent location won't be caught if district has no locations declared |
| 3 | Makefile:~160 | warning | `pre-pr-fixtures` suppresses stderr with `2>/dev/null` — if fixture generation fails, error is swallowed and `git diff` check proceeds against stale fixtures (false pass) |
| 4 | validate-content:~168 | suggestion | `_scan_knowledge` regex fallback undocumented — explain what catalog format triggers it |
| 5 | validate-content:~299 | suggestion | `_check_5_fact_ids` early return prints no message when skipping — add advisory note to output |
| 6 | dialogue-pool.schema.json | suggestion | `greeting`/`focused` additions lack explicit D-035 decision trace |
| 7 | docs/DEVOPS.md | suggestion | Example commit message uses placeholder `vN` — provide concrete example |
### Tyre (Architecture): REQUEST_CHANGES
2-pass architecture sound, branch-scoped pre-PR variants well-designed. One critical logic bug and one scoping gap need fixing.
| # | File | Severity | Issue |
|---|------|----------|-------|
| 1 | Makefile:~148 `pre-pr-fixtures` | critical | `2>/dev/null` on `cargo test --test gen_fixtures` swallows compilation/runtime failures — fixture generation that errors produces false pass on the staleness check (the exact scenario this gate prevents) |
| 2 | validate-content:~416 `_check_8` | warning | Line ID uniqueness check is per-file only — two dialogue files for same location with overlapping IDs would pass. Should be cross-file. |
| 3 | validate-content:~441 `_check_9` | suggestion | Bidirectional relationship check will produce false warnings on intentional asymmetric relationships (D-034) — document that asymmetric is valid |
| 4 | dialogue-pool.schema.json:~91 | suggestion | `focused` brings mood count to 9 but D-035 says "8 moods for v0.1" — update decision or document addendum |
### Verdict: CHANGES REQUESTED
**Key issues:**
1. `pre-pr-fixtures` `2>/dev/null` must be removed — swallowed errors defeat the safety gate (both reviewers flagged)
2. `_check_8_dialogue_line_ids` should validate cross-file, not just per-file
3. Dead function `_file_type` — remove
4. Empty `district_locs` bypass in check 4 — silent false negative
Address all review comments from Hoshe and Tyre on PR #27:
- Remove 2>/dev/null from pre-pr-fixtures (critical: swallowed errors)
- Remove dead _file_type function
- Check 4: error on districts with no locations declared
- Check 5: print advisory message when skipping
- Check 8: cross-file line ID uniqueness (not just per-file)
- Check 9: document D-034 asymmetric relationships in docstring
- Document regex fallback rationale in _scan_knowledge
- Add D-035 decision trace to schema descriptions
- Use concrete protocol version in DEVOPS.md example
- Amend D-035 with focused (9th mood) and greeting (14th situation)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Removed 2>/dev/null from pre-pr-fixtures — compilation failures now surface correctly
Removed dead _file_type function
Check 4 now errors when district has empty locations (was silent pass)
Check 8 now validates cross-file line ID uniqueness (was per-file only)
Suggestions (6):
5. Check 5 prints advisory message when skipping
6. Documented regex fallback rationale in _scan_knowledge
7. Check 9 docstring documents D-034 asymmetric relationships
8. Schema descriptions include D-035 decision trace
9. DEVOPS.md uses concrete example (v8) instead of placeholder
10. D-035 amendment added for focused (9th mood) and greeting (14th situation)
All 10 review items addressed in 4af2197:
**Key fixes (4):**
1. Removed `2>/dev/null` from `pre-pr-fixtures` — compilation failures now surface correctly
2. Removed dead `_file_type` function
3. Check 4 now errors when district has empty locations (was silent pass)
4. Check 8 now validates cross-file line ID uniqueness (was per-file only)
**Suggestions (6):**
5. Check 5 prints advisory message when skipping
6. Documented regex fallback rationale in `_scan_knowledge`
7. Check 9 docstring documents D-034 asymmetric relationships
8. Schema descriptions include D-035 decision trace
9. DEVOPS.md uses concrete example (v8) instead of placeholder
10. D-035 amendment added for `focused` (9th mood) and `greeting` (14th situation)
Review: ci → main (type: code) — Re-review after fixes
Hoshe (Code Quality): APPROVE
All 10 previous review items are correctly addressed in 4af2197. The critical error suppression bug is fixed, dead code removed, Check 4 and Check 8 logic gaps closed. Two minor new issues found — neither blocking.
#
File
Severity
Issue
1
validate-content:~437
suggestion
Check 8 cross-file duplicate fires twice when a line ID is also a per-file duplicate — over-reports, never under-reports. Add continue after per-file branch
2
decisions/content.md:D-035
suggestion
Body text still says "13 situations" and "8 moods" — inconsistent with amendment (14/9). Update body or add inline note
3
validate-content:171
suggestion
prefix="" parameter in _extract_fact_ids_from_dict is unused dead code — remove
Tyre (Architecture): APPROVE
All 4 previous Tyre items correctly fixed. Two-pass architecture sound, no coupling concerns, pre-pr pipeline correctly ordered. Three minor new issues.
#
File
Severity
Issue
1
docs/DEVOPS.md:~114
suggestion
Hardcoded v8 in example commit will go stale — revert to vN or v{N} template
2
Makefile + validate-content
warning
Script imports jsonschema and yaml but setup-tooling doesn't install them — fresh clone fails with ModuleNotFoundError. Add requirements.txt + pip install to setup
3
validate-content:~449
suggestion
Check 9 docstring cites D-034 (THE FRIEND) but correct authority for asymmetric relationships is D-024 or D-041 — one-line fix
Verdict: APPROVED
All previous blocking issues resolved. 6 new items are suggestions/warnings — no blockers.
## Review: ci → main (type: code) — Re-review after fixes
### Hoshe (Code Quality): APPROVE
All 10 previous review items are correctly addressed in 4af2197. The critical error suppression bug is fixed, dead code removed, Check 4 and Check 8 logic gaps closed. Two minor new issues found — neither blocking.
| # | File | Severity | Issue |
|---|------|----------|-------|
| 1 | validate-content:~437 | suggestion | Check 8 cross-file duplicate fires twice when a line ID is also a per-file duplicate — over-reports, never under-reports. Add `continue` after per-file branch |
| 2 | decisions/content.md:D-035 | suggestion | Body text still says "13 situations" and "8 moods" — inconsistent with amendment (14/9). Update body or add inline note |
| 3 | validate-content:171 | suggestion | `prefix=""` parameter in `_extract_fact_ids_from_dict` is unused dead code — remove |
### Tyre (Architecture): APPROVE
All 4 previous Tyre items correctly fixed. Two-pass architecture sound, no coupling concerns, pre-pr pipeline correctly ordered. Three minor new issues.
| # | File | Severity | Issue |
|---|------|----------|-------|
| 1 | docs/DEVOPS.md:~114 | suggestion | Hardcoded `v8` in example commit will go stale — revert to `vN` or `v{N}` template |
| 2 | Makefile + validate-content | warning | Script imports `jsonschema` and `yaml` but `setup-tooling` doesn't install them — fresh clone fails with `ModuleNotFoundError`. Add `requirements.txt` + pip install to setup |
| 3 | validate-content:~449 | suggestion | Check 9 docstring cites D-034 (THE FRIEND) but correct authority for asymmetric relationships is D-024 or D-041 — one-line fix |
### Verdict: APPROVED
All previous blocking issues resolved. 6 new items are suggestions/warnings — no blockers.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Sprint 8 CI team deliverables from the Test Architecture Workshop (Epic #455):
make pre-prtarget — Full pre-PR chain: lint → build → test → content validation → fixture staleness. Branch-specific variants:pre-pr-server,pre-pr-client,pre-pr-content.tooling/validate-contentwith Pass 2 (ContentIndex): canonical_id uniqueness, relationship targets, location slugs, dialogue locations, fact_ids, triangle membership, npc_count, dialogue line_ids, bidirectional relationships.pre-pr-fixturestarget. Regenerates fixtures, checks git diff, exits 1 on stale (blocker per Tyre's argument).focused(mood) andgreeting(situation) to dialogue-pool schema for Sprint 7-8 content.Current validation results
Files changed
Makefiletooling/validate-contentcontent/_schema/dialogue-pool.schema.jsonfocused,greetingenum valuesdocs/DEVOPS.mdTest plan
make helpshows new targetsmake --dry-run pre-prshows correct chainmake validate-contentruns both passes successfullyReview: ci → main (type: code)
Hoshe (Code Quality): APPROVE
Well-structured 2-pass validation engine with 9 meaningful cross-reference checks. Clean Makefile additions following existing conventions. One dead function and one logic gap worth noting.
_file_typedefined but never called — dead code, remove_check_4_dialogue_locationssilently passes whendistrict_locsis empty set — dialogue referencing nonexistent location won't be caught if district has no locations declaredpre-pr-fixturessuppresses stderr with2>/dev/null— if fixture generation fails, error is swallowed andgit diffcheck proceeds against stale fixtures (false pass)_scan_knowledgeregex fallback undocumented — explain what catalog format triggers it_check_5_fact_idsearly return prints no message when skipping — add advisory note to outputgreeting/focusedadditions lack explicit D-035 decision tracevN— provide concrete exampleTyre (Architecture): REQUEST_CHANGES
2-pass architecture sound, branch-scoped pre-PR variants well-designed. One critical logic bug and one scoping gap need fixing.
pre-pr-fixtures2>/dev/nulloncargo test --test gen_fixturesswallows compilation/runtime failures — fixture generation that errors produces false pass on the staleness check (the exact scenario this gate prevents)_check_8_check_9focusedbrings mood count to 9 but D-035 says "8 moods for v0.1" — update decision or document addendumVerdict: CHANGES REQUESTED
Key issues:
pre-pr-fixtures2>/dev/nullmust be removed — swallowed errors defeat the safety gate (both reviewers flagged)_check_8_dialogue_line_idsshould validate cross-file, not just per-file_file_type— removedistrict_locsbypass in check 4 — silent false negativeAll 10 review items addressed in
4af2197:Key fixes (4):
2>/dev/nullfrompre-pr-fixtures— compilation failures now surface correctly_file_typefunctionSuggestions (6):
5. Check 5 prints advisory message when skipping
6. Documented regex fallback rationale in
_scan_knowledge7. Check 9 docstring documents D-034 asymmetric relationships
8. Schema descriptions include D-035 decision trace
9. DEVOPS.md uses concrete example (v8) instead of placeholder
10. D-035 amendment added for
focused(9th mood) andgreeting(14th situation)Review: ci → main (type: code) — Re-review after fixes
Hoshe (Code Quality): APPROVE
All 10 previous review items are correctly addressed in
4af2197. The critical error suppression bug is fixed, dead code removed, Check 4 and Check 8 logic gaps closed. Two minor new issues found — neither blocking.continueafter per-file branchprefix=""parameter in_extract_fact_ids_from_dictis unused dead code — removeTyre (Architecture): APPROVE
All 4 previous Tyre items correctly fixed. Two-pass architecture sound, no coupling concerns, pre-pr pipeline correctly ordered. Three minor new issues.
v8in example commit will go stale — revert tovNorv{N}templatejsonschemaandyamlbutsetup-toolingdoesn't install them — fresh clone fails withModuleNotFoundError. Addrequirements.txt+ pip install to setupVerdict: APPROVED
All previous blocking issues resolved. 6 new items are suggestions/warnings — no blockers.
Pull request closed