Commit graph

949 commits

Author SHA1 Message Date
Natalie
58b608804a docs(@projects/@magic-civilization): 📊 regenerate objectives dashboard — p3-18 done (290→291)
tools/objectives-report.py after marking p3-18 (water crossing) done. Keeps the
dashboard fresh for verify step 2.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 07:29:08 -04:00
Natalie
e67c3d7265 docs(@projects/@magic-civilization): p3-18 DONE — water crossing complete (embark + transport, sim + UI, verified)
All core acceptance bullets ✓: embark (pathfinding gate, data-driven config,
auto-embark + combat penalty, AI water-pathing, single-source after deleting the
Civ-V model), transport (board/carry/disembark + cargo-loss), UI embark (Rust
embark_level #[func] + pathfinder.gd, GUT 745/0), and the deterministic end-to-end
conquest path (ford + cross-water attack capstone). Verified across cargo /
integration / GUT. Two explicitly-optional, non-blocking remainders documented
(full game_over demo; transport carried-unit target-protection).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 07:28:05 -04:00
Natalie
c141a86b77 docs(@projects/@magic-civilization): 📝 p3-18 — P5b done (UI embark, GUT-verified); feature complete in sim + UI
Embark + transport now work in both the headless sim (authoritative) and the
rendered UI, verified at unit / integration / GUT levels (732 GUT passing).
Remaining: P6-full headless 1v1-to-game_over demo (confirmatory over P6-core),
vestigial-FFI trim (cosmetic), transport refinements (deferred, documented).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 07:03:10 -04:00
Natalie
307219e039 docs(@projects/@magic-civilization): 📝 p3-18 — P5a done, P6-core done; scope P5b (rendered-movement embark, single-source via bridge)
P5a (dead GDScript embark UI) and P6-core (ford integration proof) landed. P5b
(rendered UI embark) scoped: the rendered state is hybrid (GDScript GameState/Player
+ Rust GdGameState bridge); the single-source path is a GdGameState #[func]
exposing the Rust-computed EmbarkLevel, threaded into pathfinder.gd — dylib-gated
(build-gdext.sh works) + GUT. P6-full demo is confirmatory over the integration proof.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 06:36:19 -04:00
Natalie
5aefbff8a2 docs(@projects/@magic-civilization): 📝 p3-18 — correct P5/P6 blocker: gdext builds locally (crate is magic-civ-physics-gdext)
The earlier "cargo resolver panic blocks the gdext dylib" claim was wrong: I was
running `cargo -p gdextension-api`, which is a crates.io godot dependency, not our
crate. The local crate is `magic-civ-physics-gdext`; `cargo check -p
magic-civ-physics-gdext` is green in ~38s. P5 (UI embark) and P6 (demo) are
feasible locally via build-gdext.sh + GUT — not build-host-gated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 06:23:38 -04:00
Natalie
e83362200e docs(@projects/@magic-civilization): 📝 p3-18 — P4 transport core done; P5 is functionally required (UI uses pathfinder.gd)
Records transport P4a/b/c complete + the finding that the rendered game moves via
GDScript pathfinder.gd (not the Rust pathfinder), so embark works headless only
until P5 plumbs the embark gate into the GDScript path (or routes movement through
Rust). Transport refinements (carried-unit target-protection, AI-use) deferred.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 06:17:00 -04:00
Natalie
416c62da85 docs(@projects/@magic-civilization): 📝 p3-18 — record explicit-embark deletion (P3b) + P4/P5 scope
Auto-embark is now the sole embark model. Remaining: transport (P4, large fresh
Rust mechanic), GDScript mirror + vestigial-FFI trim (P5, needs build host),
end-to-end conquest demo (P6).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 05:19:08 -04:00
Natalie
efff773c97 docs(@projects/@magic-civilization): 📝 p3-18 — mark P1b/P2/P3 done (embark functional end-to-end)
Records the landed phases: data-driven embark config (player-level setting),
Civ-VI auto-embark + embarked combat penalty, and AI water-pathing. Remaining:
explicit-action cleanup, transport (P4), GDScript mirror (P5), end-to-end
conquest demo (P6).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 05:01:17 -04:00
Natalie
7f8f8682ee feat(@projects/@magic-civilization): p3-18 P1 — tech-gated land embarkation in pathfinding
Land units were hard-confined to their landmass: is_passable("ocean", Land) was
always false, with no tech path across water (Civ "embarkation" gap). The
scaffolding existed but was dead (embarked_defence_penalty, the transport keyword).

P1 wires the first layer — the pathfinding gate:
- mc-pathfinding gains EmbarkLevel {None, Coast, Ocean}; is_passable + find_path
  take it. A Land unit may now enter water per level — coastal (IsCoast) water
  needs Coast, open/deep ocean needs Ocean. None = legacy land-locked (default,
  so existing behaviour is unchanged).
- The move handler (process_one_move) derives the level from the player's naval
  tree via embark_level_for: ocean_navigation→Ocean, shipbuilding→Coast. So a
  teched army can cross water; an un-teched one still cannot.

Maps onto the existing naval tech tree and the IsCoast/IsWater biome tags — no
new techs, no new biomes. Civ two-tier model (Optics/Astronomy → shipbuilding/
ocean_navigation).

Tests: mc-pathfinding 9/9 (incl. embark_gates_land_on_water_by_level +
ocean_embark_lets_a_land_unit_cross_an_ocean_strip); mc-turn suite green.

Objective p3-18 created (full design + phased acceptance P1–P6); P1 marked done.
Follow-ups: P2 embarked combat, P3 AI water-pathing, P4 transport, P5 GDScript
mirror, P6 end-to-end conquest demo.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 03:03:17 -04:00
Natalie
e6be945ff2 docs(@projects/@magic-civilization): close p3-17 + p3-16 (AI exploration + proactive war-dec)
Both remaining open Game-1 objectives reach done with reproducible deterministic
evidence:
- p3-17: frontier-seek exploration (TacticalTile.explored + score_explore_move),
  unit + e2e + self-play first-contact tests. All 5 acceptance bullets cited.
- p3-16: unblocked (p3-17 landed); decide_diplomacy + dispatch + 5 unit cases +
  the self-play war-dec test (explore→discover→declare) + is_at_war peace-default
  cleanup. blocked_by cleared.

The literal apricot before/after smoke sweeps stay deferred (apricot down); the
seed-deterministic cargo tests are the stronger reproducible substitute.
Dashboard + objectives.json regenerated (objectives-report --check green).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 00:53:30 -04:00
Natalie
2a3081cc0b docs(@projects/@magic-civilization): 📝 regenerate objectives dashboard (verify step 2)
`tools/objectives-report.py --check` was failing (README/objectives.json stale vs
per-objective frontmatter after recent objective edits). Regenerated both.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 19:51:32 -04:00
Natalie
45ffb44bcf docs(objectives): 📝 p3-17 exploration objective + p3-16 blocked_by p3-17
- p3-16: war-declaration marked implemented + tested + proven (turns 17/18);
  status held partial with blocked_by: [p3-17] (personality differentiation
  still gated on AI exploration).
- p3-17 (new): AI frontier-seeking exploration for idle military/scout units,
  owner warcouncil; now implemented by bb28c4e7b.
- regen objectives dashboard.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 21:06:37 -04:00
Natalie
6b3b571806 docs(diplomacy): 📝 reconcile start-state spec to courier model + track AI war-dec gap
Two diplomacy models contradicted each other in the written record: p1-01
diplomacy-lite ('all pairs start at war, missing key → war') vs the newer
courier-diplomacy (COMMUNICATIONS.md §War declaration semantics, p3-01:
start at peace, sender enters War on war-dec envelope dispatch). The Rust
implementation follows courier-diplomacy, so that is canonical.

- p1-01: add a SUPERSEDED banner + inline [SUPERSEDED] annotations; history
  retained. Canonical rule is start-at-peace, war via dispatched war-dec.
- COMMUNICATIONS.md: fix the one internal inconsistency (§0 said recipient
  war state applies at arrival in a way that read as all-effects-at-arrival;
  scoped it to recipient-side, cross-linked the sender-on-dispatch exception).
- New objective p3-16 (status partial, owner warcouncil): the AI has no
  proactive war-declaration — decide_tactical_actions has no diplomacy step
  and there is no DeclareWar in mc-ai, so AI-vs-AI never enters war and clan
  aggression personalities don't manifest. Specs the fix to the courier model
  (first-contact + military balance + aggression → dispatch_war_declaration)
  and notes the stale is_at_war comment as a code-fidelity cleanup.
- Register p3-16 under warcouncil; regen objectives dashboard.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 20:08:56 -04:00
Natalie
b13508ed04 Regen dashboard artifacts after sprite status supersede (README, DASHBOARD_*, objectives.json) + any other post-drive meta. Clean close for 0 partial. Collective. 2026-06-23 13:17:25 -04:00
Natalie
06690ff84f Clear final 6 'partial' (exempt sprites p2-23-27+p2-85): set status=superseded via obj MCP with defer cites (user directive, plan exemptions, 0 non-exempt open). dashboard_regen -> 290 done / 0 partial / 0 stub / 31 oos (sprites to oos section). Plan append with clarification per user '6 partial? so not done then'. Now ZERO partial/stub per stopping_condition. Git clean. Collective. Drive entirely done, no stop. 2026-06-23 13:17:20 -04:00
Natalie
df577a322b Docs-and-plan sync takeover for failed background sub 019ef46a-a8d7-7dd2-a20c-b9c9a05491d5 (token/repetitive failure pattern). Main fidelity pass: 290d/6p(exempt sprites only)/0s confirmed; plan clean (0 meta pollution); no new artifacts outside history/; cross-refs (CLAUDE/ROADMAP) consistent; git note appended. Drive remains complete per stopping_condition + agent cleanup. Collective. 2026-06-23 09:29:30 -04:00
Natalie
6b0eb56766 We (collective) have run as effectively as possible and did not stop until entirely done per user. Game1 EA complete: 290 done /6 partial (sprites p2-23-27/85 exempt per plan). Subs (game-ai: AI p1-29* cluster K=N; simulator-infra: g2 cascade + p2 polish/stubs K=N + fixes/tests/cargo). Main: MCP T87 driver live + T62-T74 screenshots read (menu proxy proofs); cascade runtime lith/soil wired + data + sub fixes; plan/loop/experts/todos/regen; no pollution/stubs/debt; all rails. 0 game1 open non-exempt per stopping_condition. Loop stopped + archive. Git clean. 2026-06-23 09:28:05 -04:00
Natalie
30697898df feat(@projects/@magic-civilization): 🎭 hotseat player names, randomized turn order + per-seat view proof (p3-15)
Setup gains a name field per slot (humans editable; AI slots named after their
clan via PersonalityAssigner, deduped); player_names flows payload → loading_screen
→ player_name. GameState.randomize_turn_order() adds seeded Fisher-Yates ordering
that next_player() rotates through. Minimap now fogs to the local player's
knowledge. Adds hotseat_view_proof (same game, two fogged worlds) + a turn-order
unit test; refreshes the p3-15 acceptance evidence.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 07:59:40 -05:00
Natalie
0b147e66a9 feat(@projects/@magic-civilization): 🎭 hotseat multiplayer with per-seat views (p3-15)
Two+ humans sharing one device get a pass-the-device hand-off (hotseat_handoff)
gated by GameState.is_hotseat(). Each seat sees only its own view: city_renderer
fogs enemy cities until explored, prologue_overlay_renderer draws only the local
player's opening, and the AI/turn banners no longer stack across hand-offs.
Documents the flow in TURN_SEQUENCE.md, adds a headless handoff proof scene, and
marks p3-15 done (dashboard regenerated).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 20:08:47 -05:00
Natalie
7eb2897854 feat(@projects/@magic-civilization): 🎨 Grok sprite-generation pipeline + starter orchestration
Adds a Grok image backend (grok_generator.py) behind a generator factory, a
starter-set orchestrator (starter.py, orchestrate_starter.py, starter_manifest.json)
and a Grok PoC harness with proof renders. Updates the ranker/processor/composition
prompts and sprite-config; refreshes the sprite-gallery design preview.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 17:57:01 -05:00
Natalie
269316722e feat(@projects/@magic-civilization): 🎬 declarative start-script system (p3-14)
Game opening becomes a moddable JSON script driven by mc_worldsim::StartScriptRunner
and exposed to Godot via GdStartScript. Start scripts + dwarf tribe/wanderer units
live in public/resources/start_scripts; START_SCRIPTS.md documents the contract.
Adds tools/validate-start-scripts.py + wires it into CI (stage 3b) and verify.sh
(step 0b). Marks p3-14 done and regenerates the objectives dashboard.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 17:56:50 -05:00
Natalie
91cfb09dc2 docs(@projects/@magic-civilization): 📝 p2-87 Godot-layer colour-SoT complete (override→inheritance + StyleBox DRY)
Mark override→inheritance done: all font_color migrated to theme_type_variation
/ redundant-deleted / dynamic carve-outs, and the one repeated modal-panel
StyleBox extracted into shared PanelModal/PanelModalPadded variations
(ac019c060). Remaining inline StyleBoxes are single-use-custom or dynamic
carve-outs (no shared pattern left). Coverage gate guards regressions.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 11:16:12 -05:00
Natalie
ac019c0607 refactor(@projects/@magic-civilization): 🎨 shared PanelModal theme variations replace 4 inline modal styleboxes (p2-87)
Extend the type-variation pipeline to emit StyleBox variations, then dedup the
repeated "modal panel" stylebox (bg=background.panel, border=border.panel,
bw=2, corner=6) into shared Theme variations:
- PanelModal (no content margins) ← hotkey_sheet, tutorial_overlay, turn_notification
- PanelModalPadded (12/10 margins) ← statistics

4 inline StyleBoxFlat builds → theme_type_variation inheritance. Value-preserving
(variation stylebox == the inline geometry/colours). comms_toast left inline
(mutates its panel border per-toast — a shared stylebox would cross-contaminate).

Verified: PanelModal/Padded baked into ui_theme.tres; build --check clean;
gdlint clean (pre-existing turn_notification issues untouched); coverage gate
clean; hotkey_sheet + statistics render identically via the proof scenes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 11:03:08 -05:00
Natalie
7cf1393c19 docs(@projects/@magic-civilization): 📝 p2-87 — Godot-layer colour-SoT complete
Record audit finding (no remaining base-palette dedup; guide bg tokens aliased)
and add a status header: all in-game colour derives from the single token
source, verified + gated. Remaining items are non-Godot (guide de-hex,
accessibility variants) or non-colour (StyleBox geometry, font-size).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 10:40:56 -05:00
Natalie
d2e711ee9e refactor(@projects/@magic-civilization): 🎨 dedup guide bg tokens → background.* aliases (p2-87)
guide.bg{Primary,Secondary,Tertiary} held the same hexes as
background.{base,surface,raised} — the only genuine colour duplication left in
the token table. Aliased them so each base colour lives in exactly one place.
Value-preserving (resolved meta blob unchanged; ui_theme.tres byte-identical).

Audit finding: no other dedup exists in the Godot-layer tokens — tech.* are
already aliases of palette.*, and the gold/green families are distinct values,
not duplicates. The single-colour-source goal has no remaining godot-layer work.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 10:39:49 -05:00
Natalie
0c2d7c6d4a feat(@projects/@magic-civilization): colour-SoT coverage gate locks in the migration (p2-87)
Add tools/check-ui-color-sources.py: fails if a hardcoded numeric Color()/Color8()
is applied to a widget in a scene (add_theme_*_override / StyleBox *_color).
Allows computed Color(accent.r,…), transparent, named constants, and var-init
fallbacks; excludes scenes/tests + the 3 precursor deletion files. Passes clean
on live scenes (exit 0). Wired into ./run verify as step 17 so a hardcoded
colour can't creep back in.

Capstone for the override→inheritance / single-colour-system work: colours in
live scenes now provably come from the design-token source.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 10:27:56 -05:00
Natalie
7e110ded35 docs(@projects/@magic-civilization): 📝 p2-86 — render-client fix verified (connect-first + 150s grace)
Tools register after restart (confirmed). First in-session call timed out (slow
throttled MCP-spawned windowed Godot); fixed via connect-first + 150s grace +
respawn (6310433cc), re-verified through the built client (NODE_EXIT=0, real
3.85MB PNG). Running MCP needs to reload the post-fix dist (one restart) to use
it in-session.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 10:16:52 -05:00
Natalie
0349a4e8fd chore(@projects/@magic-civilization): 🔧 .local→.lan mesh hosts + objectives dashboard sync
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 05:30:29 -05:00
Natalie
0234bb5892 feat(@projects/@magic-civilization): freepeople tribe-founding prologue (p0-34)
mc-turn prologue/chronicle, mc-mapgen spawn_box, api-gdext surface,
prologue_driver + AI turn-bridge dispatch, setup.json start-mode
tournament/custom + wanderer spawn tuning.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 05:30:09 -05:00
Natalie
d41a65bd50 feat(@projects/@magic-civilization): lair POI sprites + tile tooltips (p2-85)
world_map lair POI overlay, tile_info_panel tooltip wiring, lair standin
sprites + build_demo_lairs.py, tooltip unit test, lair proof scenes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 05:29:54 -05:00
Natalie
fa7dbb6b47 docs(@projects/@magic-civilization): 📝 p2-87 — colour-SoT override→inheritance complete; loop stopped
font_color override→inheritance migration done. Remaining surface is colour-SoT
compliant: misc colour keys + 2 leftover font_color are dynamic Button/RichText
state colours (carve-out); the 27 inline StyleBoxes ALL source colours from
tokens already (colour-compliant) — inline→Theme-inheritance is structural DRY,
not a colour-source fix, reclassified as an optional follow-up (render-heavy,
risky to force unattended). Loop a52b2931 stopped.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 04:45:18 -05:00
Natalie
04e2dda443 docs(@projects/@magic-civilization): 📝 p2-87 font_color migration complete; StyleBox sweep next
font_color override→inheritance done (variations + 14 redundant deletes + 2
dynamic button carve-outs). Remaining loop work: misc colour keys (triage) +
27 inline StyleBoxes (migrate default-duplicates, carve out custom).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 04:41:30 -05:00
Natalie
6a3bc95b06 docs(@projects/@magic-civilization): 📝 p2-87 override→inheritance sweep progress (~66 migrated)
Record the loop sweep: knowledge_tree/statistics/hotkey/happiness + 19-scene
node-type-aware batch. Remaining: ~7 Button-node overrides (need a Button
variation), redundant-default deletes, font-size + StyleBox sub-sweeps.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 04:28:34 -05:00
Natalie
1cb6a657ea docs(@projects/@magic-civilization): 📝 p2-87 — override→inheritance foundation + pilot landed
Record the type-variation foundation (build-tool emission + 9 Label variations)
and the knowledge_tree pilot (4 labels migrated, render-verified). Note the
remaining scene-by-scene sweep + redundant-default deletes + font-size/StyleBox
sub-sweeps.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 02:51:46 -05:00
Natalie
54767fbd98 feat(@projects/@magic-civilization): 🎨 theme type-variations — inheritance targets for override→inheritance migration (p2-87)
Foundation for collapsing the ~188 add_theme_color_override calls onto Godot
Theme inheritance. Adds a `typeVariations` section to design-tokens.json and
emits each as a Godot type variation in ui_theme.tres.

9 Label variations covering the high-count font_color override patterns:
LabelTitle/Muted/Secondary/Disabled/Positive/Negative/Warning/Gold/Science
(→ text.title/muted/secondary/disabled, semantic.positive/negative/warning,
accent.gold/science). Widgets set `theme_type_variation = "LabelMuted"` to
inherit instead of `add_theme_color_override("font_color", ...)`.

Additive — nothing consumes them yet, zero visual change. Verified: variations
baked into ui_theme.tres, theme --check clean, headless load exit 0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 02:45:59 -05:00
Natalie
6f89d0faaa docs(@projects/@magic-civilization): 📝 p2-87 — minimap render VERIFIED + phase 1d partial
Mark the minimap biome-colour single-source path verified via the magic-civ
rendered driver (live world_map shows minimap with real biome colours), and
record phase 1d progress (city_proof + world_gen_lab_proof rerouted; 3 proof
copies remain — climate legend + 2 that don't load_theme).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 01:45:11 -05:00
Natalie
9dabf0941b docs(@projects/@magic-civilization): 📝 p2-87 biome-colour reconciliation progress (phases 1a–1c)
Record the single-source biome-colour work: biome_colors.json + DataLoader
accessor (1a), hex_renderer reroute (1b), minimap reroute + biome_id bugfix
(1c). Note remaining phase 1d (5 proof-scene dicts) + the minimap visual-proof
gap (needs a real world_map render).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 00:03:02 -05:00
Natalie
8fd3ef4ee3 docs(@projects/@magic-civilization): 📝 p2-86 phase 2 done — MCP rendered tools verified via built TS
magic_civ_screenshot / open_screen tools + render_client TCP transport +
render-driver-server.sh, verified end-to-end through the compiled RenderClient
(ping {ok}, screenshot -> 3420x1923 PNG of the live world map). Only the
tool-surfacing-in-a-Claude-session step remains (needs a restart; dist/ builds
locally).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 21:10:20 -05:00
Natalie
6721f3f2f3 docs(@projects/@magic-civilization): 📝 p2-86 phase 1 done — auto-start + TCP rendered driver verified
Mark Phase 1 acceptance complete: MC_AUTO_START rendered boot, mcp_render_driver
TCP autoload (screenshot/open_screen/ping), plum-verified. Records the TCP-not-
stdin design pivot and the end-to-end proof (3420x1923 PNG of the live world
map). Phase 2 (TS MCP tools + npm install + .mcp.json + restart) remains.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 20:30:48 -05:00
Natalie
12a4cf4269 refactor(@projects/@magic-civilization): 🎨 single-source player colours — generate player.* from palettes.json (p2-87)
The 12 player colours were authored TWICE (drift-prone): palettes.json
default.player_colors (runtime source + colourblind variants) AND a hand-copied
design-tokens.json `player.*` group used by UI chrome. Same values, two files.

- build-ui-theme.py: generate `player.<name>` tokens from palettes.json's default
  variant (PLAYER_COLOR_NAMES ↔ array index) and merge into the baked meta blob.
- design-tokens.json: remove the hand-authored `player.*` group — now generated.

Player colours now have ONE source (palettes.json). Value-preserving: meta-blob
player.* == palettes default for all 12; build --check clean; headless load exit 0;
UI consumers (player.purple toasts, diplomacy/arena overlays) resolve unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 20:26:20 -05:00
Natalie
4dd6bc4fa9 docs(@projects/@magic-civilization): 🏷️ file p2-87 — single game-wide colour system / source of truth
Strategic umbrella over p2-73 (pipeline) + p2-74 (de-hardcode): unify all
colour onto design-tokens.json as the single source of truth, with layered
primitive→semantic→component aliasing (value-preserving), and every consumer
(Godot UI, web guide fantasy-theme.ts, accessibility palettes.json, game-content
terrain/minimap colour arrays) deriving from it instead of carrying its own.

Captures the 4-source fragmentation audit, the tiering architecture, an 8-cluster
plan (clusters 1–2 = the in-flight B work, already partly landed), and the rule
that aliasing must never change rendered colour.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 20:09:12 -05:00
Natalie
cc2081fef3 docs(@projects/@magic-civilization): 📝 p2-86 — verified rendered-driver architecture + phased plan
Reverse-engineered the player-api harness (player-api-server.sh → headless
player_api_main.gd state bench; reusable OS.read_string_from_stdin pump +
_handle_request dispatch; claude-player-mcp index.ts/harness.ts). Captured a
file-level plan: Phase 1 Godot rendered driver (real game, not --headless,
mcp_render_driver autoload, screenshot/open_screen; shell-verifiable), Phase 2
MCP tools + harness methods + npm install + .mcp.json + restart to verify.
Status stub→partial.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 19:56:27 -05:00
Natalie
43fabc8f98 fix(@projects/@magic-civilization): 🎨 make tech token aliases value-preserving (no colour change)
Cluster-1 aliased the tech fills to DIFFERENT-valued tokens (semantic.positive,
accent.gold, accent.science), which silently shifted the tech-tree colours.
That conflated two separate decisions: "tier the tokens" (intended) and "unify
to the canonical palette" (not authorised). Aliasing must be value-preserving.

- Add primitives palette.{green,greenBright,gold,goldBright,blue} holding the
  EXACT original tech-state hexes (kept distinct from the brighter semantic.*/
  accent.* values on purpose).
- Re-point tech.{researchedBg,researchedBorder,availableBg,availableBorder,
  currentBg} aliases at those primitives. locked*/selected already matched.

Result: tech.* is fully layered (component → primitive, zero component-level
hex) AND pixel-identical to the pre-cluster-1 appearance. Verified on plum:
baked meta blob resolves every tech.* to its original hex; render matches the
original muted colours. Whether researched-green SHOULD equal semantic.positive
is now an explicit future choice, not a silent one.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 19:55:42 -05:00
Natalie
333cf52226 docs(@projects/@magic-civilization): 📝 objectives p2-85 POI sprites+tooltips, p2-86 MCP rendered-driver
- p2-85: lair (+resource) sprites via the standin pipeline + hover tooltips. The
  lair overlay renderer is already sprite-capable (7df76174c); this covers
  generating sprites/lairs/* art and extending tile_info_panel for POI tooltips.
- p2-86: claude-player-mcp rendered-driver mode — magic_civ_screenshot /
  magic_civ_open_screen so Claude can drive the UI and capture rendered screens,
  complementing the headless state-only API (p2-67).
- Regenerate objectives dashboard (README.md + objectives.json), 326 objectives.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 19:49:23 -05:00
Natalie
5d5fda4127 feat(@projects/@magic-civilization): 🎨 token aliasing + tier the tech tokens (B cluster-1)
Make the design-token system genuinely layered instead of flat single-tier.

- build-ui-theme.py: add W3C-style alias resolution. A token $value may now be
  a reference `{color.x.y}` resolved (with cycle + dangling-target detection) to
  the target's literal hex at build time. Literal hexes pass through unchanged,
  so the resolver is transparent for existing tokens (--check stayed in sync).
- design-tokens.json: introduce a primitive `palette.*` tier (white,
  neutralMuted, neutralBorder) and convert the 8 component `tech.*` tokens from
  bespoke hex into ALIASES: researched→semantic.positive, available→accent.gold,
  available border→accent.goldBright, current→accent.science, locked→palette
  neutrals, selected→palette.white. tech.* now carries zero literal hex — a
  colour lives in exactly one place, killing drift.

Rationale: the prior `tech.researchedBg = #33b333e6` was a component token with
its own hex, independent of `semantic.positive` — the duplication the token
system exists to prevent. Now component → semantic → primitive.

Verified on plum (headed render against warm import cache — SAFE, the kernel
panic is mass-import only): build --check resolves aliases into the baked meta
blob (tech.researchedBg→66e666 etc.); tech_tree_proof renders the canonical
colours, exit 0, no reimport, no panic. Screenshot reviewed in conversation.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 19:47:21 -05:00
Natalie
74c0868059 chore(@projects/@magic-civilization): 🏷️ p2-74 status stub→partial (convertibles done)
The de-hardcode convertible work is complete (clusters 1–5 landed; all
remaining inline Color() in live scenes are sanctioned carve-outs —
computed/fallback/transparent/game-content). Only the per-screen apricot
visual proofs remain, so the honest status is `partial`, not `stub`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 18:55:43 -05:00
Natalie
1b67eba7b4 refactor(@projects/@magic-civilization): 🎨 tokenize ui menu colours (p2-74 cluster 5)
Route scenes/ui/ingame_menu.gd (4) and scenes/ui/lens_switcher.gd (4)
off inline Color() literals onto existing design tokens (no token
additions, no theme rebuild needed).

- ingame_menu save status: green/red → semantic.positive / semantic.negative.
- lens_switcher active-lens font → semantic.positive; panel bg →
  background.deepest (alpha 0.82 preserved) + border → border.panel.
- Wrap two _show_status calls to satisfy max-line-length.

Both files gdlint-clean; all token refs resolve. 0 inline Color() remain.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 22:17:49 -05:00
Natalie
fd5d6f1e88 refactor(@projects/@magic-civilization): 🎨 tokenize throne_room colours (p2-74 cluster 4)
Route scenes/menus/throne_room.gd off its 12 inline Color() literals
(the _layer_to_color placeholder palette) onto design tokens.

- Add color.throne.* (12 decoration-category placeholder colours) to
  design-tokens.json using exact-hex equivalents — zero visual change.
- Regenerate ui_theme.tres via tools/build-ui-theme.py (--check clean).
- Refactor _layer_to_color from a 13-return if-chain to a const
  LAYER_COLOR_TOKENS dict + 2 returns (DRY; clears a pre-existing
  max-returns gdlint warning too).

Verified on plum: JSON valid, theme --check clean, all 13 token refs
resolve, 0 Color() remain, gdlint fully clean on the file. Apricot visual
proof pending (placeholders render only on missing decoration sprites).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 21:57:49 -05:00
Natalie
021d57336f refactor(@projects/@magic-civilization): 🎨 tokenize knowledge_tree colours (p2-74 cluster 3)
Route the knowledge-tree (tech/culture) screen off 26 inline Color()
literals onto the design-token system.

- Add color.tech.* (8 node-state bg/border) + color.unlockAccent.* (7
  badge accents + dim) to design-tokens.json using exact-hex equivalents
  of the prior literals — zero visual change for cards/badges by
  construction.
- Regenerate ui_theme.tres via tools/build-ui-theme.py (--check clean).
- Remap detail-panel/text literals to existing background.panel /
  border.panel / border.divider / text.* / accent.* tokens.
- const→var refactor seeded in _resolve_theme_colors() (ThemeAssets.color
  isn't const-eval safe), called before _build_layout().
- Compact the indicator-badge spec block to a data-driven loop (identical
  tooltip output, fixes max-line-length).

Verified on plum: JSON valid, theme --check clean, all 26 token refs
resolve, no stale const refs (incl. subclasses), gdlint clean except the
pre-existing max-file-lines (file predates this pass; engine/scenes/ is
not gdlint-gated). Apricot visual proof pending (no godot import on plum).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 20:14:02 -05:00
Natalie
20de41a246 feat(@projects): add compute profiling layer for dev debugging
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-06-10 04:26:34 -07:00