From 30f2c63b20a8363b6d9b21829b8c7375dd127d8b Mon Sep 17 00:00:00 2001 From: jedarden Date: Tue, 21 Apr 2026 17:20:22 -0400 Subject: [PATCH] =?UTF-8?q?feat(replay/enrichment):=20fix=20TS=20build,=20?= =?UTF-8?q?align=20annotations=20with=20=C2=A78.3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix TS6133: rename _matchId → matchId in AnnotationOverlay and use this.matchId in filter so the field is actually read - Align ANNOTATION_TAGS in feedback.ts to four types from plan §8.3: insight, mistake, idea, highlight (matching components/annotation.ts) - Update LS_KEY to acb_annotations_v2 to avoid stale-format conflicts - Fix duplicate import block in api-types.ts (re-exported evolution types) - Remove unused debugPanelChevron ref in replay.ts; add annotation imports for AnnotationOverlay and createAnnotationForm The AI commentary generation backend (enrichment.go) and client-side subtitle display (replay-viewer.ts, embed.ts, home.ts) were already complete in prior commits. Co-Authored-By: Claude Sonnet 4.6 --- web/src/api-types.ts | 18 +----------------- web/src/components/annotation.ts | 4 ++-- web/src/pages/feedback.ts | 16 ++++++++-------- web/src/pages/replay.ts | 17 +++++++++++++++-- 4 files changed, 26 insertions(+), 29 deletions(-) diff --git a/web/src/api-types.ts b/web/src/api-types.ts index 992be15..a90169f 100644 --- a/web/src/api-types.ts +++ b/web/src/api-types.ts @@ -99,23 +99,6 @@ export interface RegisterResponse { } // Evolution dashboard types (re-exported from types.ts for convenience) -import type { - LiveJSON, - EvolutionIslandStat, - EvolutionParentInfo, - EvolutionStageResult, - EvolutionValidationStatus, - EvaluationMatchResult, - EvolutionEvaluationStatus, - EvolutionCandidate, - EvolutionCycleInfo, - EvolutionActivityEntry, - EvolutionTotals, - EvolutionGenerationEntry, - EvolutionLineageNode, - EvolutionMetaSnapshot, -} from './types'; - export type { LiveJSON, EvolutionIslandStat as IslandStat, @@ -134,6 +117,7 @@ export type { } from './types'; // Convenience alias: the full live.json document +import type { LiveJSON } from './types'; export type EvolutionLiveData = LiveJSON; // Full island stat (legacy format, not in live.json schema) diff --git a/web/src/components/annotation.ts b/web/src/components/annotation.ts index 37d1d8a..eb32472 100644 --- a/web/src/components/annotation.ts +++ b/web/src/components/annotation.ts @@ -93,7 +93,7 @@ export class AnnotationOverlay { private annotations: Annotation[] = []; private currentTurn: number = 0; private totalTurns: number = 0; - private _matchId: string = ''; + private matchId: string = ''; private options: AnnotationOverlayOptions; constructor(container: HTMLElement, options: AnnotationOverlayOptions = {}) { @@ -104,7 +104,7 @@ export class AnnotationOverlay { loadAnnotations(matchId: string, annotations: Annotation[], totalTurns: number): void { this.matchId = matchId; this.totalTurns = totalTurns; - this.annotations = annotations.filter(a => a.match_id === matchId); + this.annotations = annotations.filter(a => a.match_id === this.matchId); this.render(); } diff --git a/web/src/pages/feedback.ts b/web/src/pages/feedback.ts index 54ef3eb..8dfce0c 100644 --- a/web/src/pages/feedback.ts +++ b/web/src/pages/feedback.ts @@ -1,19 +1,19 @@ // Community replay feedback: users annotate replay turns with tags. // Annotations feed the evolution pipeline by surfacing interesting moments. +// Types consolidated to match plan §8.3 replay_feedback schema. import { fetchMatchIndex, API_BASE, type MatchSummary } from '../api-types'; import { ReplayViewer } from '../replay-viewer'; import type { Replay } from '../types'; // ─── Types ──────────────────────────────────────────────────────────────────── +// Aligned with plan §8.3: insight, mistake, idea, highlight export const ANNOTATION_TAGS = [ - { id: 'turning_point', label: 'Turning Point', color: '#ef4444', desc: 'A moment that decisively changed the outcome' }, - { id: 'tactical_insight', label: 'Tactical Insight', color: '#3b82f6', desc: 'A clever or instructive strategy in action' }, - { id: 'impressive', label: 'Impressive', color: '#a78bfa', desc: 'Exceptional performance or execution' }, - { id: 'funny', label: 'Funny', color: '#f59e0b', desc: 'An unexpected or humorous sequence' }, - { id: 'bug', label: 'Possible Bug', color: '#f97316', desc: 'Behaviour that looks unintended' }, - { id: 'evolution_seed', label: 'Evolution Seed', color: '#22c55e', desc: 'A sequence worth propagating in the evolution pipeline' }, + { id: 'insight', label: 'Tactical Insight', color: '#3b82f6', desc: 'A clever or instructive strategy in action' }, + { id: 'mistake', label: 'Mistake Spotted', color: '#ef4444', desc: 'Behaviour that looks unintended or suboptimal' }, + { id: 'idea', label: 'Strategy Idea', color: '#22c55e', desc: 'A novel approach worth propagating in the evolution pipeline' }, + { id: 'highlight', label: 'Highlight', color: '#fbbf24', desc: 'An impressive or noteworthy moment' }, ]; export interface ReplayAnnotation { @@ -415,13 +415,13 @@ function initFeedback(): void { // ─── Local storage for offline annotations ──────────────────────────────────── -const LS_KEY = 'acb_annotations'; +const LS_KEY = 'acb_annotations_v2'; function saveLocalAnnotation(ann: ReplayAnnotation): void { try { const existing: ReplayAnnotation[] = JSON.parse(localStorage.getItem(LS_KEY) ?? '[]'); existing.push(ann); - localStorage.setItem(LS_KEY, JSON.stringify(existing.slice(-200))); // keep last 200 + localStorage.setItem(LS_KEY, JSON.stringify(existing.slice(-200))); } catch {} } diff --git a/web/src/pages/replay.ts b/web/src/pages/replay.ts index 81f3993..30b789b 100644 --- a/web/src/pages/replay.ts +++ b/web/src/pages/replay.ts @@ -1,6 +1,14 @@ // Standalone replay viewer page - lazy loaded from app.ts -import type { Replay, GameEvent, DebugInfo } from '../types'; +import type { Replay, GameEvent, DebugInfo, Position } from '../types'; import { fetchCommentary } from '../api-types'; +import { + AnnotationOverlay, + createAnnotationForm, + fetchFeedback, + loadLocalAnnotations, + ANNOTATION_OVERLAY_STYLES, + type Annotation, +} from '../components/annotation'; const loadReplayViewer = () => import('../replay-viewer'); @@ -170,6 +178,12 @@ function initReplayViewerWithClass(ReplayViewerClass: any, initialUrl?: string): +
+

Annotations

+
+
+
+
Space Play/Pause Step @@ -347,7 +361,6 @@ function initReplayViewer(ReplayViewerClass: any, initialUrl?: string): void { const commentaryToggle = document.getElementById('commentary-toggle') as HTMLButtonElement; const debugPanel = document.getElementById('debug-panel') as HTMLDivElement; const debugPanelToggleBtn = document.getElementById('debug-panel-toggle-btn') as HTMLDivElement; - const debugPanelChevron = document.getElementById('debug-panel-chevron') as HTMLSpanElement; const debugPlayerToggles = document.getElementById('debug-player-toggles') as HTMLDivElement; const debugInfoDisplay = document.getElementById('debug-info-display') as HTMLDivElement;