Q-077 promoted to full workshop brief with 9 reference implementations, 7 key questions, 5 zone types, and agent assignments (Tyre, Gestalt, Nigel, Miri, Ozzie). Also: Q-089 through Q-092 filed (starfield, Markov names, event audio, modular settings menu), make clean-imports target added. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
405 lines
14 KiB
Makefile
405 lines
14 KiB
Makefile
GODOT := $(shell command -v godot4 2>/dev/null || command -v godot 2>/dev/null)
|
|
|
|
.PHONY: help setup build check-protocol client server game stop test lint ci ci-client ci-server clean \
|
|
decisions-sync decisions-coverage decisions-active decisions-orphan \
|
|
db-backup db-install validate-content check-fact-ids setup-hooks \
|
|
audit \
|
|
pre-pr pre-pr-lint pre-pr-build pre-pr-test pre-pr-validate pre-pr-fixtures \
|
|
pre-pr-server pre-pr-client pre-pr-content \
|
|
fixtures-client fixtures-gauntlet golden-diff golden-update \
|
|
checklist-validate checklist-generate \
|
|
build-sr-voice run-sr-voice test-voice-mock test-voice-real \
|
|
perf-baseline debug-schedule \
|
|
test-ipc-fixtures test-ipc-protocol test-ipc-integration test-ipc-benchmark \
|
|
screenshot visual-movie test-visual visual-update
|
|
|
|
# --- Configuration ---
|
|
|
|
GODOT_VERSION ?= 4.6
|
|
|
|
# Default
|
|
help:
|
|
@echo "The Settled Reach — Development Commands"
|
|
@echo ""
|
|
@echo " make setup Install dev dependencies (Rust, Godot, tooling)"
|
|
@echo " make build Build client and server"
|
|
@echo " make game Build and run the full game (server + client)"
|
|
@echo " make stop Stop any running server instance"
|
|
@echo " make client Run the Godot client (test mode)"
|
|
@echo " make server Run the Rust simulation server"
|
|
@echo " make test Run all tests"
|
|
@echo " make test-ipc-fixtures Layer 1: IPC serialization fixtures"
|
|
@echo " make test-ipc-protocol Layer 2: mock IPC protocol tests"
|
|
@echo " make test-ipc-integration Layer 3: real subprocess round-trip"
|
|
@echo " make test-ipc-benchmark IPC latency benchmark (blocked: #555/#556)"
|
|
@echo " make lint Run all linters"
|
|
@echo " make ci Run full CI pipeline locally"
|
|
@echo " make ci-client Run client CI checks"
|
|
@echo " make ci-server Run server CI checks"
|
|
@echo " make check-protocol Verify server/client protocol versions match"
|
|
@echo " make clean Remove build artifacts and caches"
|
|
@echo ""
|
|
@echo " make db-backup Backup shared database to git (main only)"
|
|
@echo " make db-install Restore shared database from backup"
|
|
@echo ""
|
|
@echo " make decisions-sync Sync decisions/*.md into SQLite"
|
|
@echo " make decisions-coverage Decision-to-ticket coverage by domain"
|
|
@echo " make decisions-active List active decisions"
|
|
@echo " make decisions-orphan Decisions without implementing tickets"
|
|
@echo " make audit Run cargo audit (security advisory check)"
|
|
@echo " make validate-content Validate content YAML against schemas"
|
|
@echo " make check-fact-ids Check fact_id references against knowledge catalogs"
|
|
@echo " make fixtures-client Generate GDScript->Rust cross-encoder fixtures (#475)"
|
|
@echo " make golden-diff Show diff if golden file output has changed"
|
|
@echo " make golden-update Regenerate golden file and stage for commit"
|
|
@echo " make checklist-validate Validate checklist YAML against schema"
|
|
@echo " make checklist-generate Validate checklists + print condition summary"
|
|
@echo " make perf-baseline Run performance benchmarks and save baseline"
|
|
@echo ""
|
|
@echo " make screenshot Ad-hoc visual capture (SCENARIO=name, default: fog_3state)"
|
|
@echo " make visual-movie Flow capture with contact sheet (FLOW=name)"
|
|
@echo " make test-visual Run visual golden regression tests"
|
|
@echo " make visual-update Regenerate visual goldens and stage for commit"
|
|
@echo ""
|
|
@echo " make pre-pr Run all pre-PR checks (lint, build, test, validate, fixtures)"
|
|
@echo " make pre-pr-server Server-scoped pre-PR (lint, build, test, fixtures)"
|
|
@echo " make pre-pr-client Client-scoped pre-PR (lint, build, test)"
|
|
@echo " make pre-pr-content Content-scoped pre-PR (schema + cross-ref validation)"
|
|
@echo ""
|
|
@echo " make setup-hooks Install pre-commit hooks (included in setup)"
|
|
@echo " make build-sr-voice Build sr-voice LLM inference service"
|
|
@echo " make serve-sr-voice Start sr-voice server (ARGS='--model <path>')"
|
|
@echo " make run-sr-voice Submit to sr-voice server (ARGS='generate|batch|benchmark ...')"
|
|
@echo " make stop-sr-voice Stop sr-voice server"
|
|
@echo " make test-voice-mock Test voice pipeline with mock sr-voice"
|
|
@echo " make test-voice-real Test voice pipeline with real sr-voice + Gemma 2B"
|
|
@echo " make debug-schedule Print bevy_ecs schedule graph (diff for PR artifacts)"
|
|
@echo ""
|
|
@echo " GODOT_VERSION=4.6 make setup Override Godot version"
|
|
|
|
# --- Setup ---
|
|
|
|
setup: setup-rust setup-godot setup-tooling setup-hooks decisions-sync
|
|
@echo "Dev environment ready."
|
|
|
|
setup-rust:
|
|
@tooling/install-rust
|
|
|
|
setup-godot:
|
|
@GODOT_VERSION=$(GODOT_VERSION) tooling/install-godot
|
|
|
|
setup-tooling:
|
|
@echo "Checking tooling dependencies..."
|
|
@command -v python3 >/dev/null 2>&1 || { echo "Install Python 3"; exit 1; }
|
|
@command -v curl >/dev/null 2>&1 || { echo "Install curl (required for Godot download)"; exit 1; }
|
|
@command -v unzip >/dev/null 2>&1 || { echo "Install unzip (required for Godot download)"; exit 1; }
|
|
@python3 -c "import yaml" 2>/dev/null || { echo "Install PyYAML: pip install pyyaml"; exit 1; }
|
|
@python3 -c "import jsonschema" 2>/dev/null || { echo "Install jsonschema: pip install jsonschema"; exit 1; }
|
|
|
|
setup-hooks:
|
|
@git config core.hooksPath .config/hooks
|
|
@echo "Git hooks path set to .config/hooks"
|
|
|
|
# --- Build ---
|
|
|
|
check-protocol:
|
|
@SERVER_V=$$(grep 'pub const PROTOCOL_VERSION' server/src/bridge/types.rs | sed 's/.*= *//;s/[^0-9]//g'); \
|
|
CLIENT_V=$$(grep 'const PROTOCOL_VERSION' client/scripts/protocol/protocol.gd | sed 's/.*= *//;s/[^0-9]//g'); \
|
|
if [ "$$SERVER_V" != "$$CLIENT_V" ]; then \
|
|
echo "ERROR: Protocol version mismatch — server=$$SERVER_V, client=$$CLIENT_V"; \
|
|
echo " Fix: update client/scripts/protocol/protocol.gd to match server/src/bridge/types.rs"; \
|
|
exit 1; \
|
|
fi
|
|
|
|
build: check-protocol build-server build-client
|
|
|
|
build-server:
|
|
cd server && cargo build
|
|
|
|
build-client:
|
|
@test -n "$(GODOT)" || { echo "Godot not found. Run 'make setup' first."; exit 1; }
|
|
@# First import may error on theme/font loading before the import scan completes.
|
|
@# Run twice: first pass generates imports silently, second pass validates clean.
|
|
@$(GODOT) --headless --path client --import --quit 2>/dev/null || true
|
|
$(GODOT) --headless --path client --import --quit
|
|
|
|
# --- Run ---
|
|
|
|
server:
|
|
cd server && cargo run --bin settled-reach-server
|
|
|
|
client:
|
|
@test -n "$(GODOT)" || { echo "Godot not found. Run 'make setup' first."; exit 1; }
|
|
$(GODOT) --path client
|
|
|
|
game: stop build
|
|
@test -n "$(GODOT)" || { echo "Godot not found. Run 'make setup' first."; exit 1; }
|
|
@echo "Starting server..."
|
|
@cd server && cargo run --bin settled-reach-server &
|
|
@sleep 2
|
|
@echo "Starting client..."
|
|
@SR_LIVE=1 $(GODOT) --path client
|
|
@$(MAKE) stop
|
|
|
|
stop:
|
|
@lsof -ti :9876 | xargs -r kill 2>/dev/null || true
|
|
@echo "Stopped any running server on port 9876"
|
|
|
|
# --- Test ---
|
|
|
|
test: test-server test-client
|
|
|
|
test-server:
|
|
tests/run-rust
|
|
|
|
fixtures:
|
|
cd server && cargo test --test gen_fixtures -- --ignored
|
|
|
|
fixtures-gauntlet:
|
|
cd server && cargo test --test gen_gauntlet_fixtures -- --ignored
|
|
|
|
fixtures-client:
|
|
@test -n "$(GODOT)" || { echo "Godot not found. Run 'make setup' first."; exit 1; }
|
|
@echo "Generating GDScript fixtures for Rust decoder..."
|
|
$(GODOT) --headless --path client -s res://tests/gen_client_fixtures.gd
|
|
@echo "Verifying Rust can decode GDScript fixtures..."
|
|
cd server && cargo test --test serialization gdscript_generated_fixtures
|
|
@echo "--- Fixtures-client: PASS ---"
|
|
|
|
golden-diff:
|
|
@echo "Regenerating golden output for comparison..."
|
|
@mkdir -p .cache/golden
|
|
@cp server/tests/golden/proof_room_tick_10.json .cache/golden/before.json
|
|
@cd server && UPDATE_GOLDEN=1 cargo test --test golden_suite -- proof_room_tick_10_matches_golden; \
|
|
rc=$$?; \
|
|
cp ../server/tests/golden/proof_room_tick_10.json ../.cache/golden/after.json 2>/dev/null; \
|
|
cp ../.cache/golden/before.json ../server/tests/golden/proof_room_tick_10.json; \
|
|
if [ $$rc -ne 0 ]; then echo "Cargo test failed (golden file restored)."; exit $$rc; fi
|
|
@if diff -q .cache/golden/before.json .cache/golden/after.json >/dev/null 2>&1; then \
|
|
echo "--- Golden file: UP TO DATE ---"; \
|
|
else \
|
|
echo "--- Golden file has CHANGED ---"; \
|
|
echo ""; \
|
|
diff --color -u .cache/golden/before.json .cache/golden/after.json || true; \
|
|
echo ""; \
|
|
echo "Run 'make golden-update' to accept changes."; \
|
|
exit 1; \
|
|
fi
|
|
|
|
golden-update:
|
|
@echo "Regenerating golden file..."
|
|
@cd server && UPDATE_GOLDEN=1 cargo test --test golden_suite -- proof_room_tick_10_matches_golden
|
|
@git add server/tests/golden/
|
|
@echo "--- Golden file updated and staged ---"
|
|
@echo "Review with: git diff --cached -- server/tests/golden/"
|
|
|
|
test-client:
|
|
tests/run-godot
|
|
|
|
test-ipc-fixtures:
|
|
tests/run-ipc-fixtures
|
|
|
|
test-ipc-protocol:
|
|
tests/run-ipc-protocol
|
|
|
|
test-ipc-integration:
|
|
tests/run-ipc-integration
|
|
|
|
test-ipc-benchmark:
|
|
tests/run-ipc-benchmark
|
|
|
|
# --- Clean ---
|
|
|
|
clean-imports:
|
|
@echo "Removing Godot import cache..."
|
|
rm -rf client/.godot/imported/
|
|
@echo "Re-importing assets (this may take a while on first run)..."
|
|
$(GODOT) --headless --path client --import --quit
|
|
@echo "Import cache rebuilt."
|
|
|
|
# --- Lint ---
|
|
|
|
lint: lint-server lint-client
|
|
|
|
lint-server:
|
|
cd server && cargo clippy -- -D warnings
|
|
cd server && cargo fmt --check
|
|
|
|
lint-client:
|
|
@test -n "$(GODOT)" || { echo "Godot not found. Run 'make setup' first."; exit 1; }
|
|
@echo "Checking GDScript for errors..."
|
|
@$(GODOT) --headless --path client --quit 2>&1 | grep -i "SCRIPT ERROR" && { echo "GDScript errors found"; exit 1; } || echo "No script errors found"
|
|
|
|
# --- Pre-PR verification ---
|
|
|
|
pre-pr: pre-pr-lint pre-pr-build pre-pr-test pre-pr-validate pre-pr-fixtures audit
|
|
@echo ""
|
|
@echo "=== PRE-PR: ALL CHECKS PASSED ==="
|
|
@echo "Safe to create PR."
|
|
|
|
pre-pr-lint: lint-server lint-client
|
|
@echo "--- Lint: PASS ---"
|
|
|
|
pre-pr-build: build-server build-client
|
|
@echo "--- Build: PASS ---"
|
|
|
|
pre-pr-test: test-server test-client
|
|
@echo "--- Tests: PASS ---"
|
|
|
|
pre-pr-validate: validate-content check-fact-ids
|
|
@echo "--- Content validation: PASS ---"
|
|
|
|
pre-pr-fixtures:
|
|
@echo "Checking Rust->GDScript fixture staleness..."
|
|
@cd server && cargo test --test gen_fixtures -- --ignored
|
|
@if git diff --quiet client/tests/fixtures/; then \
|
|
echo "--- Rust fixtures: UP TO DATE ---"; \
|
|
else \
|
|
echo ""; \
|
|
echo "--- RUST FIXTURES STALE ---"; \
|
|
echo " Protocol changed but fixtures not regenerated."; \
|
|
echo " Stale fixtures make all client tests FALSE POSITIVES."; \
|
|
echo ""; \
|
|
echo " Changed files:"; \
|
|
git diff --stat client/tests/fixtures/; \
|
|
echo ""; \
|
|
echo " Fix: commit the updated fixtures with your protocol change."; \
|
|
exit 1; \
|
|
fi
|
|
@echo "Checking GDScript->Rust fixture staleness..."
|
|
@$(MAKE) fixtures-client
|
|
@if git diff --quiet server/tests/fixtures/gdscript/; then \
|
|
echo "--- GDScript fixtures: UP TO DATE ---"; \
|
|
else \
|
|
echo ""; \
|
|
echo "--- GDSCRIPT FIXTURES STALE ---"; \
|
|
echo " Protocol changed but GDScript fixtures not regenerated."; \
|
|
echo " Stale fixtures make cross-encoder tests FALSE POSITIVES."; \
|
|
echo ""; \
|
|
echo " Changed files:"; \
|
|
git diff --stat server/tests/fixtures/gdscript/; \
|
|
echo ""; \
|
|
echo " Fix: commit the updated fixtures with your protocol change."; \
|
|
exit 1; \
|
|
fi
|
|
|
|
# Branch-specific variants (faster, scope-appropriate)
|
|
|
|
pre-pr-server: lint-server build-server test-server pre-pr-fixtures audit
|
|
@echo "=== Server pre-PR: PASSED ==="
|
|
|
|
pre-pr-client: lint-client build-client test-client
|
|
@echo "=== Client pre-PR: PASSED ==="
|
|
|
|
pre-pr-content: validate-content check-fact-ids checklist-validate
|
|
@echo "=== Content pre-PR: PASSED ==="
|
|
|
|
# --- CI (run locally) ---
|
|
|
|
ci: ci-server ci-client
|
|
|
|
ci-server: lint-server build-server test-server
|
|
|
|
ci-client: lint-client build-client test-client
|
|
|
|
# --- Database ---
|
|
|
|
db-backup:
|
|
@tooling/db-backup
|
|
|
|
db-install:
|
|
@tooling/db-install
|
|
|
|
# --- Decisions ---
|
|
|
|
decisions-sync:
|
|
@tooling/db/decisions-sync
|
|
|
|
decisions-coverage:
|
|
@tooling/db/sqlite-query "SELECT d.domain, COUNT(DISTINCT d.id) as decisions, COUNT(DISTINCT t.decision_ref) as with_tickets FROM decisions d LEFT JOIN tickets t ON d.id = t.decision_ref WHERE d.status='active' AND d.type='confirmed' GROUP BY d.domain"
|
|
|
|
decisions-active:
|
|
@tooling/db/sqlite-query "SELECT id, domain, title FROM decisions WHERE status='active' AND type='confirmed' ORDER BY domain, id"
|
|
|
|
decisions-orphan:
|
|
@tooling/db/sqlite-query "SELECT id, title FROM decisions WHERE type='confirmed' AND status='active' AND id NOT IN (SELECT DISTINCT decision_ref FROM tickets WHERE decision_ref IS NOT NULL)"
|
|
|
|
# --- Content Validation ---
|
|
|
|
validate-content:
|
|
@tooling/validate-content
|
|
|
|
check-fact-ids:
|
|
@tooling/check-fact-ids
|
|
|
|
audit:
|
|
cd server && cargo audit
|
|
|
|
checklist-validate:
|
|
@tooling/validate-checklist --check
|
|
|
|
checklist-generate:
|
|
@tooling/validate-checklist
|
|
|
|
perf-baseline:
|
|
@tooling/perf-baseline
|
|
|
|
# --- Schedule debug (#346) ---
|
|
|
|
debug-schedule:
|
|
@echo "Dumping bevy_ecs schedule graph..."
|
|
@cd server && cargo run --bin settled-reach-server -- --dump-schedule
|
|
|
|
# --- Visual test harness ---
|
|
|
|
screenshot:
|
|
@tests/run-visual --screenshot $(SCENARIO)
|
|
|
|
visual-movie:
|
|
@tests/run-visual --movie $(FLOW)
|
|
|
|
test-visual:
|
|
@tests/run-visual
|
|
|
|
visual-update:
|
|
@tests/run-visual --update
|
|
|
|
LIBCLANG_PATH ?= /usr/lib64/rocm/llvm/lib
|
|
BINDGEN_CLANG_ARGS ?= -I/usr/lib64/rocm/llvm/lib/clang/19/include
|
|
SR_VOICE_ENV = LIBCLANG_PATH=$(LIBCLANG_PATH) BINDGEN_EXTRA_CLANG_ARGS="$(BINDGEN_CLANG_ARGS)"
|
|
|
|
SR_VOICE_PORT ?= 8321
|
|
|
|
build-sr-voice:
|
|
cd server/sr-voice && $(SR_VOICE_ENV) cargo build --release
|
|
|
|
serve-sr-voice:
|
|
cd server/sr-voice && $(SR_VOICE_ENV) cargo run --release -- serve $(ARGS)
|
|
|
|
run-sr-voice:
|
|
cd server/sr-voice && $(SR_VOICE_ENV) cargo run --release -- $(ARGS)
|
|
|
|
stop-sr-voice:
|
|
@lsof -ti :$(SR_VOICE_PORT) | xargs -r kill 2>/dev/null || true
|
|
@echo "Stopped sr-voice on port $(SR_VOICE_PORT)"
|
|
|
|
test-voice-mock:
|
|
@echo "Running voice pipeline test (mock sr-voice)..."
|
|
cd server && SR_VOICE_MOCK=1 cargo test --test voice_pipeline -- --nocapture
|
|
@echo "Results: .tmp/voice-test/results.txt"
|
|
|
|
test-voice-real:
|
|
@echo "Running voice pipeline test (real sr-voice + Gemma 2B)..."
|
|
@test -f server/sr-voice/target/release/sr-voice || { echo "Build sr-voice first: make build-sr-voice"; exit 1; }
|
|
@test -f server/models/gemma2.gguf || { echo "Model not found: server/models/gemma2.gguf"; exit 1; }
|
|
cd server && cargo test --test voice_pipeline -- --nocapture
|
|
@echo "Results: .tmp/voice-test/results.txt"
|
|
|
|
# --- Clean ---
|
|
|
|
clean:
|
|
cd server && cargo clean || true
|
|
rm -rf .cache/*
|
|
rm -rf client/reports
|
|
@echo "Clean complete."
|