AI_PERSONALITY_TINTS — single source of truth для personality colors

Codex audit round 5: AI_PERSONALITY_TINTS в defaults.ts имел base cyan
для aggressive/trickster/ghost, тогда как MainMenuScene хардкодит
правильные #ff6090/#a0e0ff/#c0f0ff. Code drift.

Fix:
- defaults.ts AI_PERSONALITY_TINTS заполнен реальными tints из MainMenuScene
- MainMenuScene импортирует AI_PERSONALITY_TINTS, использует константы
  вместо hardcoded hex

Теперь one source of truth:
- defaults.ts::AI_PERSONALITY_TINTS — code
- visual-style.md::AI-личности таблица hex — docs
- asset-prompts.md::EXCEPTION group B — prompts
Все три синхронизированы.

186/186 tests, typecheck/lint/build .

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
aevgarik
2026-05-24 19:52:15 +03:00
parent b40bc1a516
commit 26462629ca
2 changed files with 12 additions and 10 deletions

View File

@@ -71,12 +71,14 @@ export const PALETTE = {
neutral: 0x808080, // серый для нейтрального мяча neutral: 0x808080, // серый для нейтрального мяча
} as const; } as const;
// AI personality color tints (дифференциация — visual-style.md) // AI personality color tints — PALETTE EXCEPTION group B (см. visual-style.md::AI-личности
// + asset-prompts.md::AI portraits). Single source of truth для UI accents,
// portrait prompts и selector цветов.
export const AI_PERSONALITY_TINTS = { export const AI_PERSONALITY_TINTS = {
defensive: 0x00d0e8, // steel-cyan defensive: 0x00d0e8, // steel-cyan (calm, slightly зеленоватый)
aggressive: 0x00f0ff, // base cyan + magenta corona (применяется отдельно) aggressive: 0xff6090, // warm-magenta (мягкий) + hot #ff006e corona отдельно
trickster: 0x00f0ff, // alternating trickster: 0xa0e0ff, // pale-cyan (playful)
ghost: 0x00f0ff, // semi-transparent (alpha 0.4) ghost: 0xc0f0ff, // ethereal-cyan (semi-transparent feel)
} as const; } as const;
// Bumper points by type (см. data-contracts.md#leaderboard-formula) // Bumper points by type (см. data-contracts.md#leaderboard-formula)

View File

@@ -1,5 +1,5 @@
import * as Phaser from 'phaser'; import * as Phaser from 'phaser';
import { GAME_WIDTH, GAME_HEIGHT, PALETTE } from '../config/defaults'; import { GAME_WIDTH, GAME_HEIGHT, PALETTE, AI_PERSONALITY_TINTS } from '../config/defaults';
import type { import type {
AIDifficulty, AIDifficulty,
AIPersonality, AIPersonality,
@@ -118,10 +118,10 @@ export class MainMenuScene extends Phaser.Scene {
flavour: string; flavour: string;
color: number; color: number;
}> = [ }> = [
{ id: 'defensive', name: 'Бэтти', flavour: 'Защитница — цепкая защита', color: 0x00d0e8 }, { id: 'defensive', name: 'Бэтти', flavour: 'Защитница — цепкая защита', color: AI_PERSONALITY_TINTS.defensive },
{ id: 'aggressive', name: 'Турбо', flavour: 'Атака — активный бустер', color: 0xff6090 }, { id: 'aggressive', name: 'Турбо', flavour: 'Атака — активный бустер', color: AI_PERSONALITY_TINTS.aggressive },
{ id: 'trickster', name: 'Хитрый Хо', flavour: 'Нестандартный setup', color: 0xa0e0ff }, { id: 'trickster', name: 'Хитрый Хо', flavour: 'Нестандартный setup', color: AI_PERSONALITY_TINTS.trickster },
{ id: 'ghost', name: 'Эхо', flavour: 'Финальный босс (без adaptation в MVP)', color: 0xc0f0ff }, { id: 'ghost', name: 'Эхо', flavour: 'Финальный босс (без adaptation в MVP)', color: AI_PERSONALITY_TINTS.ghost },
]; ];
const title = this.add const title = this.add