- Document non-blocking receive contract in perf_bench.rs docstring,
confirming no TCP deadlock race (Hoshe #1, critical)
- Make shadowcast parser order-independent — flush on new config header
instead of requiring Recursive after Symmetric (Hoshe #2)
- Fix p95 calculation: use floor(0.95*(N-1)) nearest-rank instead of
ceil(0.95*N)-1 which was off-by-one at N=50 (Hoshe #4)
- Error on --compare when no baseline file exists (Hoshe #5)
- Add D-031 10tps assumption comment to TICK_BUDGET_US (Tyre #1)
- Strengthen snapshot assertion: require warmup + half measurement
window instead of warmup + 1 (Tyre #2)
- Regenerate baseline with corrected p95 (356µs, was 526µs)
Hoshe #3 (.PHONY) was already addressed — perf-baseline is in the
.PHONY declaration on Makefile line 10.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds `make perf-baseline` — boots the full server plugin stack with
real content, measures 50 ticks (5 warmup), captures per-tick timing,
entity counts, and process RSS. Includes shadowcast benchmarks. Saves
structured JSON to tests/perf/baseline.json for regression detection.
Supports --compare mode (>20% threshold).
First baseline: mean 366µs, p95 526µs (0.5% of D-026 100ms budget).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Check 9 tested `target in npc_rels` which missed NPCs with no
relationship entries. Changed to `target in self.npcs` so the
advisory warning fires correctly for all NPCs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Technical project descriptor with game architecture, simulation
parameters, and content model. Version field (0.1.9) is now the
canonical version — Cargo.toml synced, CLAUDE.md and start-sprint
skill updated to reference it during release workflow.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Step 7 now transitions all unblocked sprint tickets to in_progress
immediately rather than deferring to agents (who forget). Completes
the ticket lifecycle: start-sprint → in_progress, push-pr → review,
sprint stop → done.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Step 7 scans commit messages for #NNN ticket refs and transitions
in_progress tickets to review status. Only in_progress → review;
other statuses are left alone.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
sprint stop now marks in_progress/review tickets as done
automatically — agents often forget to update status after merging.
Backlog/ready tickets are left as carry-over candidates since they
were never started.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When invoked on main, /start-sprint now closes the active sprint,
bumps the version to v0.1.N, moves changelog entries under the new
version heading, tags, and pushes. Team branch behavior unchanged.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Generated by headless --import after audio merge. These are needed
for stable UID references across editor sessions.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
ticket create previously had no way to set descriptions, causing
agents to work around with raw SQL or mangled titles.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
build-client used --quit without --import, which failed to create
.godot/ and register class_name types after a clean. game target
only depended on build-server, skipping client entirely. clean now
preserves the .godot/ directory itself while clearing contents.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Cast Variant to String via str() before passing to _on_room_change
- Clear _current_room_id on null room transition (fixes re-entry skip)
- Add push_error for failed dir creation and file writes in _save_report
- Fix docstring: tests/gauntlet-stats.json → user://dev/gauntlet-stats.json
- Namespace stats path to user://dev/ to avoid save data collision
- Replace print() with push_warning in _save_report (codebase consistency)
- Downgrade client-only wire guard from push_warning to silent return
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- golden-diff restores committed file even on cargo test failure
- Wire checklist-validate into pre-pr-content gate
- Fix schema description: condition IDs are globally unique, not
per-file; document room_id prefix naming convention
- Add schema file missing error handling in validate-checklist
- Add scope discriminator field (per_room/cross_room) to schema
- Check pyyaml and jsonschema packages in setup-tooling
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Re-generate monologue chimes (were oversized placeholders) and
fog_recognition (was silent). Fix sample rate headers on remaining
assets (192kHz→44.1kHz). All 8 UI assets now at 44.1kHz stereo,
LUFS -16 normalized, Vorbis q6, durations within D-038 spec.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
F12 pauses simulation, shows modal LineEdit prompt, saves three files
to user://bug-reports/gauntlet-t{tick}-{timestamp}/: snapshot.json
(full ObserverSnapshot), render.txt (simplified client-side text
render), description.txt (tester notes + tick/room/stance metadata).
Esc cancels without saving. Double-activation guard prevents stacking.
BUG_REPORT action added to InputMapper with wire guard in SimBridge
(client-only, never sent to server). Dialog on ModalLayer (CL 30).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
GauntletHUD in UILayer shows TIMER: MM:SS (PB: MM:SS). Timer starts on
room entry, resets on room change, records personal bests to
user://gauntlet-stats.json. Session summary printed on disconnect.
Hidden in non-gauntlet mode (anti-tedium guard).
Adds room_id and gauntlet_mode fields to GameState, parsed from
ObserverSnapshot. Main.gd wires update_from_state() and finalize().
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Golden targets: make golden-diff shows color diff if simulation output
changed, make golden-update regenerates and stages for review.
Checklist schema: JSON Schema for 7 condition types evaluable from
ObserverSnapshot. Per-room YAML checklists for 3 Gauntlet rooms plus
cross-room checks. Validation script + make checklist-validate/generate.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add SimBridge._last_snapshot = null to P3 before_test() (contamination risk)
- Clarify mono.is_visible is custom property, not CanvasItem builtin
- Camera smoothing test uses approximate equality instead of exact
- Propagate inner _encode_message errors in array/dict encoding
- Add explanatory comment on int_64 encoder branch
- Document unfalsifiable gauntlet guard as intentional future-proof
- Remove loose D-053 citation from LERP_SPEED pin
- Assert FogOverlay is sibling of FogGroup under World
- Add CANVAS_MODAL=30 (ModalLayer) assertion in P3-Z04
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fail on encode errors instead of silently writing empty .msgpack files
- Fail test on missing/empty fixture dir instead of silent skip
- Add all missing action variants (MoveSouth, MoveEast, MoveWest,
Unpause, ToggleStanceDown, WalkAway) to GDScript fixture generator
- Add GDScript fixture staleness check to make pre-pr
- Validate repo root detection before writing outside client/
- Add file.flush() before close in headless mode
- Document fixture failure recovery in DEVOPS.md
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Documents the {domain}-{action} naming pattern for new skills
so future skills follow the convention established in the kit.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Claude-native starter kit that bootstraps multi-agent team
infrastructure for any project. Clone once, install as a global
skill, run /kit-install in any project directory.
Includes:
- 3-tier profile system (minimal/standard/full: 3-12 agents)
- 16 agent archetype templates with personality spectrum
- 18 skill templates using domain-action naming convention
- Stakeholder persona panel for workshops and PR reviews
- SQLite ticketing DB with CLI tools (config-based DB paths)
- Decision tracking, sprint lifecycle, workshop orchestration
- Multi-git-host support (GitHub, Gitea, GitLab)
- /kit-update skill for syncing with source repo evolution
- Naming theme support for agent identity/flavor
- Smoke tests for all three profile tiers
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Regression guards for Sprint 9 QA features:
- F12 bug report (2): no-crash without handler, no queued input action
(stubs for when #495 WRONG button lands)
- Gauntlet UI hidden (3): no gauntlet nodes visible in default mode,
no room_id/gauntlet_mode in normal snapshots, stays hidden across
multiple ticks
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The int_64 branch condition `-(1 << 63) <= value` overflowed in
GDScript's signed 64-bit arithmetic, making the branch unreachable.
Negative values beyond int_32 range were incorrectly encoded as
uint_64 (0xcf) instead of int_64 (0xd3). Replaced with `value < 0`.
Updated boundary tests BV-N15 and BV-N16 to expect correct int_64
header byte.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Bump PROTOCOL_VERSION from 7 to 8 to match server. Three changes:
1. Add dialogue_response field decoding (DialogueResponseEvent with
line_id, text, speaker_entity_id) from server #305/D-028.
2. Fix Interact encoding: server changed PlayerAction::Interact from
unit variant to struct variant with {target_entity_id, verb}.
Extract _encode_action() helper to handle this consistently.
3. Update all test assertions that checked version=7 or expected
Interact as a bare string.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
test_monologue_not_duplicated_after_consumption was failing because
poll_snapshot() in test mode returns _test_snapshot() without
consuming _last_snapshot. The carry-forward logic then incorrectly
preserved the monologue. Fix: directly clear _last_snapshot to
simulate the live-mode consumption path.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Separate workspace crate at tooling/test-client/ importing bridge
types from server crate. CLI: --connect, --replay, --text, --json,
--quiet, --golden, --ticks. Exit codes: 0=success, 1=golden mismatch,
2=connection error. Golden file comparison with recursive JSON diff.
JSONL replay loader for tick-scheduled input sending.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
format_snapshot_text(&ObserverSnapshot) -> String pub-exported from
server crate. Entity labels as kind:entity_id sorted by distance,
room name stubbed as (unknown) until Gauntlet constants land.
10 unit tests. Consumed by tooling/test-client for --text mode.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sprint 9 theme: Gauntlet — test infrastructure backbone with test
client binary, Gauntlet rooms 1-3, golden file suite, and client QA
harness. 23 tickets across server (9), client (6), CI (6), audio (2).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
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>
7 client tickets closed (#435-437, #470, #476-478) after
PR #25 and PR #26 reviews completed and merged.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update existing snapshot fixtures for protocol v8 (dialogue_response
field). Add 14 raw boundary value fixtures and 5 snapshot boundary
tick fixtures for encoding edge case coverage.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implement full dialogue selection pipeline (D-028): 4-layer filtering
engine with access tier, situation derivation, trust tier, and weighted
topic+mood scoring via SimRng. Add ContentSlug component for stable
content identity across save/load. Add walk-away KG recording with
IncompleteInteraction events per D-064 three-phase consequences. Bump
protocol to v8 with DialogueResponseEvent. Fixes#305, #427, #452.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add AnomalyMarker component and detect_anomalies() system that flags
entities with KG relationship PersonOfInterest or Contradicted state
for urgent cognitive delay (0.3s vs 0.6s normal). Add
trigger_recognition_monologue() that fires monologue at delay START
(when grey blob appears), not at completion — the monologue IS the
recognition process per D-060. Includes v0.1 fallback recognition
lines and cooldown tracking. Fixes#450, #451.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add CLI argument parsing for test infrastructure: --test-mode enables
deterministic seed (42) and warn-level tracing to stderr, --port allows
OS-assigned ports (--port 0), --seed overrides RNG seed. Prints
LISTENING:{port} to stdout after bind for test harness discovery.
Extracts setup_proof_room() for reuse. Fixes#459.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace HashSet with BTreeSet for visible_ids, sort visible_tiles by
coordinates, sort visible entities in snapshot by entity_id, and sort
movers by Entity bits in validate_movement. Required by D-010 principle 4
(deterministic simulation). Fixes#456, #457, #458.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Critical fixes:
- hide_dialogue() sent PAUSE instead of UNPAUSE, permanently freezing
simulation after every dialogue (both reviewers)
- Confrontation monologue hardcoded in GDScript constant, violating
D-042/D-020 — moved to ui-strings.yaml as dialogue.confrontation_beat
- Walk-away WASD didn't call set_input_as_handled(), letting movement
event propagate and potentially stepping on the same frame
- is_dialogue_active() returned _is_showing only — interaction list
could flash during 300ms fade gap. Now includes dialogue_active state
- Removed dead _last_dialogue_id / get_dialogue_id() state (never read)
Warnings addressed:
- Audio registry now scans res://audio/ recursively (subdirs registered)
- add_bus_effect guarded against duplicate calls in tests
- int64 encoder dead code tagged KNOWN-DEFECT, filed as ticket #516
- D-073 zone crossfade stub comment clarifies Sprint 9+ deferral
- listening_focus dip documents caller tick-gate responsibility (D-069/D-071)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Define VIS_HIDDEN/PERIPHERAL/FORWARD and EXP_UNEXPLORED/EXPLORED/
VISIBLE in FogState. Replaces 7 magic number usages in _resize() and
update_from_state(). Provides stable assertion targets for fog tests.
Implements #476.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Agents were sending outputs as messages instead of writing files,
which prevented Qatux (documenter) from reading other agents' work.
Now each round task instructs agents to write to
docs/workshops/{name}/{agent}-roundN.md, and between-round steps
verify files exist before proceeding.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
4-track workshop targeting the class of bugs from Sprint 6-7: blocking
I/O, serialization boundaries, state desync, off-by-one encoding.
Participants: Tyre, Hoshe, Dudley, Stig. Covers integration test
architecture, serialization boundary tests, client test infrastructure,
and test gap prioritization. Includes catalogue of 6 real bugs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Document client-side movement throttle rates per stance, hold-to-move
input model with composite diagonals, and crouch ticks-per-move value.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
10 gdUnit4 tests verifying camera behavior: SimBridge test mode
connection, snapshot pipeline, player position extraction, camera
anchor in _ready(), smoothing disable/re-enable cycle, camera tracking
across frames, and player movement following.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Entity renderer: add framerate-independent position lerping so entities
slide between tiles instead of snapping. Tuned for Sprint snappiness
and Walk/Careful fluidity.
Fog shader: set ColorRect to transparent fallback so a shader load
failure doesn't paint solid white over the world. Track camera position
(not player position) so fog stays synced during smooth camera pan.
Restructure GLSL to avoid early return (some GPU drivers miscompile it).
Minor type fixes: typed Array[Vector2] in cursor_renderer tick drawing,
untyped Array in inventory_grid to avoid Godot typed-array cast issues.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Off-by-one in all four signed int branches: upper bound used <= instead
of < (e.g., value <= 128 matched int8 instead of falling through to
uint8). Tick 128 was encoded as int8 -128, causing server deserialization
failure. Also remove stray debug prints from nil/false decode paths.
Fixes bug #4 (MessagePack encodes tick 128 as -128).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Three client input/bridge fixes:
1. Pause toggle: add UNPAUSE action and toggle logic based on
GameState.game_time.tick_rate. Wire UNPAUSE in sim_bridge.gd.
2. Hold-to-move: replace press-event movement with polled _process()
direction sampling. Composite diagonals via simultaneous keys
(W+D → northeast). Client-side throttle per stance (D-053):
Sprint=200ms, Walk=400ms, Careful=600ms, Crouch=800ms.
3. Snapshot carry-forward: when a newer snapshot overwrites an
unconsumed one, carry forward current_monologue and current_dialogue
so one-shot events aren't silently dropped.
Fixes bugs #5 (monologue lost on overwrite) and #6 (overwrite spam).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Camera2D's internal smoothed_camera_pos starts at (0,0) and lerps
toward global_position, causing a visible white-screen drift on startup.
Disable position_smoothing in _ready(), snap camera to player position
from the first snapshot, then re-enable smoothing with reset_smoothing()
after the first anchored frame. Add tick guards to monologue/dialogue
consumption to prevent re-triggering when client FPS > sim tick rate.
Fixes bug #2 (camera doesn't center on player at startup).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>