Commit Graph

161 Commits

Author SHA1 Message Date
6530625f4d fix(theme): drift-guard test, interactive stylebox states, ThemeKeys font consts, richer showcase (whole-branch review)
- build_game_theme.gd: extract build_theme() as a static func returning the
  fully-built Theme; _init() is now a thin save+quit wrapper. Enables a test
  to build a fresh Theme in memory without running the SceneTree main loop.
- test_theme_resource.gd: add test_committed_tres_matches_builder() — builds
  a fresh Theme via the preloaded builder and compares bg_color against the
  committed game_theme.tres for PrimaryCTA/normal, ParchmentCard/panel, and
  DarkPanel/panel. Catches "palette/builder changed, .tres not regenerated."
- build_game_theme.gd: give Tab, TabActive, and Chip explicit hover/pressed/
  focus styleboxes (focus is StyleBoxEmpty to suppress the default ring) so
  they no longer fall back to Godot's default gray button on interaction.
  Add a disabled stylebox + font_disabled_color to PrimaryCTA for the
  unaffordable-CTA state the 2a shell will need.
- theme_keys.gd: add HEADING/ACCENT/MONO font-role consts (kept out of ALL,
  which is stylebox-variation-only); build_game_theme.gd and
  theme_showcase.gd now reference them instead of raw StringName literals.
- theme_showcase.gd: add an italic DM-voice RichTextLabel (EB Garamond
  italic face, spec §6) and two semantic-coloured chips (BLOOD for
  aggressive actions, GOLD for pay/faith) alongside the existing neutral
  chip, demonstrating the script-applied colouring from spec §5.3.
- dark_bay.gdshader: comment noting the stripe uses FRAGCOORD (screen-space)
  while the vignette uses UV (node-local) — intended for full-bleed use.
- surfaces/*.gd: ## comments documenting the accepted deviation from spec
  §5.4 (uniforms set at runtime from Palette rather than baked into the
  .tscn) — no behavior change.
- Regenerated game_theme.tres via build_game_theme.gd.

Full suite: 125/125 (was 124, +1 drift-guard test).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GFDm1ku9WDUacK2S78m2be
2026-07-10 20:59:05 -05:00
0082765ee7 fix(theme): showcase renders every §6 element (3rd surface, 3 variations, all fonts, labelled swatches)
- _surfaces(): add VignetteOverlay.tscn alongside ParchmentPanel/DarkBay,
  backed by a Palette.STEEL ColorRect so the dim is visibly rendering.
- _variations(): add ItemTileEmpty (next to filled ItemTile), ParchmentInset,
  and DarkPanel stylebox nodes.
- _fonts(): new section rendering default serif body, Accent
  (Architects Daughter), and Mono (JetBrains Mono) labels at real sizes.
- _swatches(): wrap each ColorRect in a VBoxContainer with a Mono caption
  Label naming its Palette const, per spec's "labelled swatches."

No raw hex / Color(...) literals introduced; all colour via Palette.*, all
styleboxes via ThemeKeys.* variation names.
2026-07-10 20:46:25 -05:00
7954c579d3 feat(theme): showcase harness — the human-eyeball proof
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 20:39:09 -05:00
73fcf2d096 feat(theme): parchment/dark-bay/vignette shader surfaces as drop-in scenes
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 20:34:52 -05:00
9091707535 feat(theme): game_theme.tres (fonts + stylebox variations) via builder 2026-07-10 20:29:22 -05:00
3981047ec6 feat(theme): bundle EB Garamond, Architects Daughter, JetBrains Mono (OFL) 2026-07-10 20:25:06 -05:00
888b2b32f5 feat(theme): palette tokens as the single colour source 2026-07-10 20:21:42 -05:00
233b1088cf docs(plans): add M3-a shared Theme implementation plan
Five TDD tasks: palette tokens, bundled OFL fonts, script-built
game_theme.tres, three shader surfaces, showcase eyeball proof.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 20:19:13 -05:00
2d7ed469bf docs(specs): add M3-a shared Theme design
First of three M3 cycles (Theme -> shell 2a -> Title). Palette.gd consts
as the single source of truth; game_theme.tres for flat-bordered UI;
shaders for the three signature surfaces. EB Garamond replaces
proprietary Georgia. Proof is a human-eyeballed showcase harness.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 20:13:25 -05:00
29474e5751 docs(charter+roadmap): pivot to the tactical CRPG (the POC is answered)
The aliveness POC (M0-M2) is proven, so redefine the project as the tactical
CRPG the /mockups describe. Charter: §1 reframed (Code of Conquest / The
Margreave), §10 combat = tactical + action-economy but GRIDLESS (tokens are
flavor, no positional rules), §15 = button-driven actions + free-text NPC
dialogue (Adjudicator reshaped to the optional free-text escape hatch), §16
adopts /mockups as the UI/systems bible, §17 rewritten to the game's scope.
Two conflicts flagged not silently decided (§18): damage determinism (§7 vs
mock ranges → M5) and class names (§8 vs mock callings → M4).

Roadmap: M0-M2 kept as the built engine; M3-M9 re-sequenced around the mock
screens (Theme+shell → creation → combat → dialogue → inventory/sheet → world
systems → framing/AI-flavor/persistence). Streaming stays shelved; v2 NPC
ideas preserved, re-homed to M6.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 16:12:48 -05:00
49bc6b22c0 docs(mockups): add the UI/systems bible (11 screens + README)
High-fidelity HTML/CSS/JS design references for the tactical-CRPG direction —
title, character creation, character sheet, inventory, world map, quest log,
shop, pause/settings, dialogue, combat HUD, main exploration window. README is
the handoff spec (visual system, per-screen state models, Godot translation
notes). Not production code — the source of truth for the game's look + systems.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 16:06:23 -05:00
b639cab0c2 docs(roadmap): advance milestone marker M2 -> M3
M2 (prove aliveness) build-complete + live-proven; feel confirmed in playtest.
Active build focus is now M3 (make it a game), starting with the Adjudicator.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 15:47:01 -05:00
57acfb75d9 docs(roadmap): considering-state done; shelve streaming for the POC
Flip considering-state to done+merged+live-confirmed. Strike the streaming
item — the considering-state reframes the wait and is tested/live; real
streaming's transport rework + mid-stream failure surface isn't worth it for
the POC. Streaming spec retained as a record (banner SHELVED). Includes the
human's folded-in further-down roadmap ideas.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 15:44:15 -05:00
099714d4f6 Merge feature/considering-state into dev
Considering-state + transport timeout (M2 anti-freeze; streaming parked).
While a model call is in flight the client rotates authored in-character
'the Master considers…' lines (§13); HttpTransport now sets a request timeout
(35s, rejects <=0) so a hung call degrades to the fallback instead of spinning
forever. Human-confirmed working live, including the degrade path (API down →
fallback). 5 tasks, whole-branch review MERGE AS-IS. Rotation tuned to 3.0s.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 15:33:58 -05:00
6d7eeaab27 tune(client): considering rotation 2.0s -> 3.0s (phrases linger longer)
By-hand cold-start test showed 3 phrases before the response; 1.5x the
cadence so each line stays on screen a touch longer.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 15:31:59 -05:00
c5644d381e feat(client): harnesses show the considering-state around the call
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 15:09:45 -05:00
82b2de19bb feat(client): ConsideringIndicator — rotates think-lines on a Timer 2026-07-10 15:06:31 -05:00
6bd5e4f84a fix(client): HttpTransport sets request timeout (no more infinite hang) 2026-07-10 15:03:29 -05:00
377adb10b2 feat(client): ProxyConfig.request_timeout_seconds (default 35s, reject <=0)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 15:00:40 -05:00
a171d40781 feat(client): ConsideringPhrases — authored rotating think-lines (§13) 2026-07-10 14:57:38 -05:00
2c32bba320 docs(plan): considering-state + transport timeout implementation plan
5 TDD tasks: ConsideringPhrases (pure) + authored considering.json;
ProxyConfig.request_timeout_seconds (default 35s, reject <=0); HttpTransport
applies it (closes the infinite-hang gap); ConsideringIndicator node shim
(Timer rotates a Label); wire both harnesses around the await.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 14:55:00 -05:00
96432bee87 docs(spec): considering-state + transport timeout; park streaming
Pivot M2 anti-freeze from streaming to a lighter considering-state: a rotating
in-character 'the Master considers…' indicator (authored content, §13 spirit)
on the proven non-streaming loop, plus the HttpTransport request-timeout fix so
a hung call yields to the fallback instead of spinning forever. Meets §14's
anti-freeze goal by reframing the wait; near-zero new failure surface. Streaming
design PARKED (banner + roadmap ○), revisit if playtest shows the wait hurts.
Conscious §14 deviation recorded per §18.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 14:37:20 -05:00
1ed863d3fe docs(spec): Narrator streaming (M2) design
Real token streaming to hide the ~2s call (§14). Proxy emits its own minimal
NDJSON (delta/done/error); /dm/narrate becomes a 200 stream (422 stays sync,
model errors become an in-stream frame). Client reworks to an HTTPClient
poll-loop StreamTransport behind a testable seam; hold-back tag filter;
keep-partial mid-stream degrade; folds in the HttpTransport timeout fix.
Narrator first; NPC fast-follow.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 14:23:32 -05:00
1a6e8e8616 Merge fix/npc-harness-luck-descriptor into dev
NPC harness built a canon log with an empty player.luck_descriptor, which the
schema rejects (minLength 1) → /npc/speak 422. Build the player through
LogPlayer with a non-empty §7 fortune line. Human-confirmed working live.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 13:38:17 -05:00
81db962a9d fix(client): npc harness must set player.luck_descriptor (schema requires non-empty)
The throwaway harness hand-built a minimal canon log and left luck_descriptor
as the default "", which fails the canon-log schema (minLength 1) → /npc/speak
422s and the harness silently degrades to fallback. Build the player through
LogPlayer with a non-empty §7 fortune line. Verified: request now 200s and Fenn
answers in-voice.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 13:30:45 -05:00
d788225754 Merge feature/npc-conversation into dev
Bounded NPC conversation (/npc/speak), M2 core experiment. Server role is a
thin drop-in on the M1 pipeline (persona+knowledge server-side); client adds a
pure MoveValidator + MoveApplier over the proven DmService loop — validates
moves against live state, drops invalid, keeps prose (§6). Live-proven vs
qwen3.5 (Fenn in-voice, grounded in knowledge, no Luck leak). Live smoke caught
+ fixed two TagExtractor tag-format drifts. 18 tasks, all reviewed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 13:23:00 -05:00
af1a3aa726 docs(roadmap): M2 Bounded NPC conversation done + live-proven
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 13:17:18 -05:00
2b1c11b1e6 fix(client): TagExtractor tolerates paren-less moves + scrubs misformatted move tags (live-review LF1/LF2)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 13:15:18 -05:00
86d1352b19 test(api): gated live smoke — Fenn answers /npc/speak in voice
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 13:07:24 -05:00
ed2311b62c chore(client): commit Godot .uid sidecars for new npc scripts (Tasks 10-15)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 13:03:04 -05:00
87f337bffd feat(client): throwaway NPC harness — drive /npc/speak on screen
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 13:02:13 -05:00
c347da6cec fix(api): npc.md — zero-arg move examples need parens for TagExtractor 2026-07-10 12:59:14 -05:00
832cdc65ca feat(client): NpcService.speak — post, extract, validate moves (§6)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 12:55:52 -05:00
5181c3e74a feat(client): authored NPC fallback line (§13)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 12:51:13 -05:00
c0dcc8df82 feat(client): MoveApplier — validated moves to game state 2026-07-10 12:47:51 -05:00
a2100f802f feat(client): NpcResult model 2026-07-10 12:45:23 -05:00
4c0b4e41c3 feat(client): pure MoveValidator — membership is the whole test 2026-07-10 12:41:45 -05:00
1b67b3984b feat(client): NpcContent.available_moves — the legality home 2026-07-10 12:39:10 -05:00
3b71fcdcc0 feat(client): CanonLog.add_quest/has_quest for offer_quest 2026-07-10 12:36:37 -05:00
1d1ae37281 feat(client): GameState move targets — remove_item, reveal/gift tracking
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 12:34:33 -05:00
9d2f93bbf2 fix(api): package /content into the image so npc content resolves 2026-07-10 12:30:36 -05:00
a2c654c047 content: author Fenn + the NPC role prompt body 2026-07-10 12:26:04 -05:00
0c3d64d068 feat(api): wire POST /npc/speak (422 unknown npc, 502 model error) 2026-07-10 12:22:07 -05:00
004cc21724 feat(api): npc.run service — thin drop-in on the model pipeline 2026-07-10 12:18:01 -05:00
76c04b45d2 feat(api): render_npc_digest — persona/knowledge/moves/utterance 2026-07-10 12:14:34 -05:00
6cd5003930 feat(api): route the npc role to its own model 2026-07-10 12:11:54 -05:00
69729f7673 feat(api): content.load_npc + content-root resolver 2026-07-10 12:08:50 -05:00
55a2ae6f19 docs(plan): bounded NPC conversation implementation plan
18 TDD tasks: server npc role (content.load_npc, routing, npc digest,
npc.run, /npc/speak, Fenn + prompt, Docker content packaging); client
NpcService + pure MoveValidator + MoveApplier + NpcContent legality +
GameState/CanonLog move targets + NPC fallback + throwaway harness;
gated Fenn live smoke.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 12:03:58 -05:00
097ac618f4 docs(spec): bounded NPC conversation (/npc/speak) design
M2 core experiment. Server owns persona+knowledge (spoilers/IP, no DB);
client owns live state and computes available_moves. Free text straight
to the NPC prompt (no Adjudicator). Sibling NpcService + pure MoveValidator;
moves validated against state, invalid dropped, prose always kept (§6).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 11:36:44 -05:00
7db1eb8f26 docs(roadmap): M2 Client HTTP loop done + live-proven; NPC conversation next
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 11:15:38 -05:00