diff --git a/.gitignore b/.gitignore index a02f82e..c854f86 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,10 @@ backend/data/*.sqlite3-wal tmp/ frontend/assets/img/weapons/black - copia/ frontend/assets/img/weapons/black.zip +.ai/ + +/ai/ +/.ai/ +/tmp/ +/frontend/assets/img/weapons/black - copia/ +/frontend/assets/img/weapons/black.zip diff --git a/ai/README.md b/ai/README.md deleted file mode 100644 index 512467e..0000000 --- a/ai/README.md +++ /dev/null @@ -1,34 +0,0 @@ -# AI Platform Workspace - -This directory contains the AI Development Platform support layer integrated into HLL Vietnam. - -Its purpose is operational, not product-facing. It exists to help the project plan work through tasks, preserve repository context, coordinate specialist roles and keep changes small, reviewable and documented. - -## Included areas - -- `../ai-platform.json`: repository-specific platform configuration for local workers and validation -- `task-template.md`: standard structure for every task -- `repo-context.md`: repository and product context for planners and workers -- `architecture-index.md`: quick map of the repository structure -- `system-metrics.md`: lightweight log for platform execution metrics -- `reports/`: generated local platform reports; Markdown reports are ignored except `.gitkeep` -- `prompts/`: reusable planning prompts -- `orchestrator/`: role guidance and orchestration documents -- `tasks/`: task queue split by status - -## Task lifecycle - -- `tasks/pending/`: scoped tasks ready for a worker -- `tasks/in-progress/`: tasks currently being executed -- `tasks/review/`: completed work waiting for human or orchestrator review -- `tasks/blocked/`: tasks that cannot continue without a decision or missing input -- `tasks/obsolete/`: tasks intentionally retired without execution -- `tasks/done/`: validated and completed tasks - -## HLL Vietnam usage rules - -- The platform must reflect the real state of HLL Vietnam, not generic sample content. -- Tasks should be created only when there is a justified change to perform. -- This integration does not add product features by itself. -- The current product stack remains HTML, CSS and JavaScript on the frontend, with Python reserved for the future backend. -- Codex workers must process explicit tasks only and use `ai-platform.json` for local platform paths where scripts support it. diff --git a/ai/architecture-index.md b/ai/architecture-index.md deleted file mode 100644 index 507afb9..0000000 --- a/ai/architecture-index.md +++ /dev/null @@ -1,85 +0,0 @@ -# Architecture Index - -This file gives AI agents a fast overview of HLL Vietnam before they inspect the repository in detail. - -## Application Type - -Community website repository with a static landing in the current phase and a planned Python backend in later phases. - -## Top-Level Structure - -### Documentation - -- `README.md` -- `AGENTS.md` -- `ai-platform.json` -- `docs/current-hll-servers-source-plan.md` -- `docs/` - -### Frontend - -- `frontend/index.html` -- `frontend/assets/css/` -- `frontend/assets/js/` -- `frontend/assets/img/` - -### Backend - -- `backend/` -- `backend/app/` - -### AI Platform - -- `ai/` -- `ai/orchestrator/` -- `ai/prompts/` -- `ai/reports/` -- `ai/tasks/` - -### Automation And Support - -- `scripts/` -- `.github/workflows/` - -## Current Technical Baseline - -- Frontend runtime is plain browser-loaded HTML, CSS and JavaScript. -- Backend runtime is a minimal Python bootstrap with `GET /health` and room for placeholder API routes. -- Python is the expected backend language for future development. -- GitHub Actions and local PowerShell scripts may support the AI task workflow. - -## Editing Priorities - -- Product-facing changes usually start in `frontend/`. -- Process and coordination changes usually start in `ai/`, `AGENTS.md` and `scripts/`. -- Local AI worker configuration starts in `ai-platform.json`. -- Backend changes must remain preparatory unless a task explicitly changes that scope. - -## Validation Expectations - -- Frontend changes should remain compatible with local browser opening where applicable. -- AI platform changes should keep task paths and documentation aligned. -- Script changes should fail safely when optional tools or tests are not configured. - -## Current Integration Direction - -- Discord and game server data remain in planning phase until sources, limits and security are validated. -- Initial dynamic data should come from controlled backend placeholders, not direct frontend calls to external services. -- The technical plan for these integrations is documented in `docs/discord-and-server-data-plan.md`. -- Current Hell Let Loose servers may be exposed as a clearly marked provisional reference block before HLL Vietnam-specific data exists. -- The phased source strategy for that provisional block is documented in `docs/current-hll-servers-source-plan.md`. -- The ingestion strategy for converting that provisional block into normalized server snapshots is documented in `docs/current-hll-data-ingestion-plan.md`. -- The logical storage foundation for persisting server snapshots is documented in `docs/stats-database-schema-foundation.md`. -- Historical ingestion defaults to RCON-first; the public CRCON scoreboard JSON layer is a fallback for operations where RCON fails or lacks coverage, not the normal primary historical source. -- The validated discovery for those historical sources is documented in `docs/historical-crcon-source-discovery.md`. -- The persisted historical domain model for CRCON matches, players and ingestion runs is documented in `docs/historical-domain-model.md`. -- The V1 monthly MVP scoring proposal for persisted historical player metrics is documented in `docs/monthly-mvp-ranking-scoring-design.md`. -- The audited boundary between direct live RCON and future event-driven RCON metrics is documented in `docs/rcon-data-capability-audit.md`. -- The first V2 player-event foundation now lives in dedicated `player_event_*` backend modules and starts from CRCON match-detail summaries, not from live RCON. -- The default operational deployment is simplified to `backend` + `frontend`; historical workers and RCON historical capture are advanced/manual services. -- Comunidad Hispana #03 is disabled from default RCON targets, while existing historical/Elo code and persisted data remain available for explicit future reintroduction. Elo/MMR remains paused and decoupled from backend startup. -- Frontend data consumption should remain progressive, endpoint by endpoint, with static fallbacks preserved during migration. -- The frontend integration strategy is documented in `docs/frontend-data-consumption-plan.md`. -- Historical RCON architecture is RCON-first end to end: session capture, AdminLog ingestion, parsed event storage, materialized matches/player stats and optional profile-snapshot enrichment. -- Public-scoreboard data remains optional enrichment/link source or fallback only; it must not become the normal primary historical path while RCON coverage is available. -- Manual RCON validation commands include `docker compose exec backend python -m app.rcon_admin_log_ingestion --minutes 1440` and `docker compose exec backend python -m app.rcon_historical_worker capture`. diff --git a/ai/orchestrator/README.md b/ai/orchestrator/README.md deleted file mode 100644 index ec07318..0000000 --- a/ai/orchestrator/README.md +++ /dev/null @@ -1,22 +0,0 @@ -# Orchestrator - -The orchestrator is responsible for turning repository context into safe, scoped and verifiable tasks for HLL Vietnam. - -## What it does - -- Reviews repository structure and current documentation -- Identifies the smallest useful unit of work -- Assigns the most suitable role guidance for the task -- Keeps tasks aligned with HLL Vietnam constraints and branding -- Prevents uncontrolled work outside the task system - -## How it collaborates - -- Reads `ai/architecture-index.md` and `ai/repo-context.md` first -- Uses `ai/task-template.md` to draft tasks -- Sends execution to the appropriate role document in this folder -- Keeps completed work traceable through `ai/tasks/` and `ai/system-metrics.md` - -## Current scope - -At this stage the orchestrator supports repository setup, documentation alignment, planning hygiene and future implementation flow. It does not define product roadmap beyond explicit project instructions. diff --git a/ai/orchestrator/analyst.md b/ai/orchestrator/analyst.md deleted file mode 100644 index 9815452..0000000 --- a/ai/orchestrator/analyst.md +++ /dev/null @@ -1,30 +0,0 @@ -# Analista - -## Mission - -Convert requests into concrete repository context, dependencies and risks before implementation starts. - -## When This Role Intervenes - -- When requirements need clarification through code and docs review -- When impact analysis is needed before editing -- When validation criteria must be derived from repository state - -## Review First - -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `docs/decisions.md` -- Files directly affected by the request - -## Restrictions - -- Do not implement product features from analysis alone. -- Do not generate a backlog beyond the immediate validated need. -- Keep analysis focused on the current request. - -## Collaboration With The Orchestrator - -- Provides the factual basis for task creation -- Identifies the smallest safe change set -- Documents assumptions the worker must preserve diff --git a/ai/orchestrator/backend-senior.md b/ai/orchestrator/backend-senior.md deleted file mode 100644 index 4d51301..0000000 --- a/ai/orchestrator/backend-senior.md +++ /dev/null @@ -1,30 +0,0 @@ -# Backend Senior - -## Mission - -Guard backend readiness and future service design without introducing premature implementation. - -## When This Role Intervenes - -- When a task touches `backend/` -- When integration points with the future backend must be documented -- When validation needs to preserve Python readiness - -## Review First - -- `backend/README.md` -- `backend/requirements.txt` -- `docs/project-overview.md` -- `docs/decisions.md` - -## Restrictions - -- Do not create functional backend services unless explicitly required by task. -- Keep the future backend baseline in Python. -- Avoid placeholder complexity that creates false architecture commitments. - -## Collaboration With The Orchestrator - -- Reviews backend-facing tasks for future compatibility -- Suggests minimal preparatory structure only when justified -- Prevents accidental drift toward non-Python backend assumptions diff --git a/ai/orchestrator/component-discovery.md b/ai/orchestrator/component-discovery.md deleted file mode 100644 index dd56905..0000000 --- a/ai/orchestrator/component-discovery.md +++ /dev/null @@ -1,20 +0,0 @@ -# Component Discovery - -## Purpose - -Identify the real repository areas affected by a request before any task is executed. - -## Repository Areas - -- Root docs: repository purpose and rules -- `docs/`: scope, roadmap and decisions -- `frontend/`: current live product surface -- `backend/`: future Python backend foundation -- `ai/`: orchestration and task workflow -- `scripts/`: local platform automation - -## Rules - -- Read the smallest relevant set of files first. -- Prefer extending existing documents and scripts instead of duplicating them. -- Do not assume framework layers that do not exist in this repository. diff --git a/ai/orchestrator/database-architect.md b/ai/orchestrator/database-architect.md deleted file mode 100644 index b0745ec..0000000 --- a/ai/orchestrator/database-architect.md +++ /dev/null @@ -1,30 +0,0 @@ -# Arquitecto de Base de Datos - -## Mission - -Protect long-term data modeling decisions while the repository is still in foundation stage. - -## When This Role Intervenes - -- When a task discusses future persistence -- When backend planning introduces data structure assumptions -- When architecture documents mention storage or schema strategy - -## Review First - -- `docs/project-overview.md` -- `docs/roadmap.md` -- `docs/decisions.md` -- `backend/README.md` - -## Restrictions - -- Do not introduce concrete database implementations in this phase. -- Do not force schema decisions without a real product task. -- Keep guidance abstract and aligned with the future Python backend. - -## Collaboration With The Orchestrator - -- Reviews planning assumptions for data persistence -- Helps avoid premature database commitments -- Documents open questions instead of inventing structures diff --git a/ai/orchestrator/di-analysis.md b/ai/orchestrator/di-analysis.md deleted file mode 100644 index 5770c31..0000000 --- a/ai/orchestrator/di-analysis.md +++ /dev/null @@ -1,11 +0,0 @@ -# Dependency Analysis - -## Purpose - -Analyze dependencies and execution assumptions before changing scripts, automation or future backend design notes. - -## Rules - -- Identify whether the task affects frontend-only, documentation-only or platform-only areas. -- Avoid importing template assumptions from unrelated stacks. -- When in doubt, preserve the current lightweight structure and document the dependency instead of implementing it. diff --git a/ai/orchestrator/feature-planner.md b/ai/orchestrator/feature-planner.md deleted file mode 100644 index 576a25e..0000000 --- a/ai/orchestrator/feature-planner.md +++ /dev/null @@ -1,20 +0,0 @@ -# Feature Planner - -## Purpose - -Turn explicit repository requests into implementation-ready tasks without expanding product scope. - -## Workflow - -1. Read `AGENTS.md`. -2. Read `ai/repo-context.md`. -3. Read `ai/architecture-index.md`. -4. Inspect only the files directly related to the request. -5. Create the smallest useful task set in `ai/tasks/pending`. - -## Rules - -- Use `ai/task-template.md`. -- Keep tasks small, focused and verifiable. -- Do not invent product work beyond the request. -- Keep HLL Vietnam branding and stack constraints intact. diff --git a/ai/orchestrator/frontend-senior.md b/ai/orchestrator/frontend-senior.md deleted file mode 100644 index 3f4ce0c..0000000 --- a/ai/orchestrator/frontend-senior.md +++ /dev/null @@ -1,30 +0,0 @@ -# Frontend Senior - -## Mission - -Maintain and evolve the frontend foundation with minimal, high-signal changes that preserve local-browser compatibility. - -## When This Role Intervenes - -- When a task touches `frontend/` -- When landing integration must remain stable after platform changes -- When markup, styles or script loading need review - -## Review First - -- `frontend/index.html` -- `frontend/assets/css/styles.css` -- `frontend/assets/js/main.js` -- `docs/decisions.md` - -## Restrictions - -- Do not introduce heavy frontend frameworks in this phase. -- Do not redesign the landing unless the task explicitly requires it. -- Preserve the HLL Vietnam military and tactical tone. - -## Collaboration With The Orchestrator - -- Confirms whether a task really needs product-facing frontend edits -- Keeps frontend changes scoped and reversible -- Reports any integration effect on direct browser usage diff --git a/ai/orchestrator/graphic-designer.md b/ai/orchestrator/graphic-designer.md deleted file mode 100644 index 878fbfd..0000000 --- a/ai/orchestrator/graphic-designer.md +++ /dev/null @@ -1,30 +0,0 @@ -# Disenador Grafico - -## Mission - -Protect the visual identity of HLL Vietnam so that future assets, layouts and presentations remain coherent with the intended military and Vietnam-inspired branding. - -## When This Role Intervenes - -- When a task affects visual assets or art direction -- When design documentation needs alignment -- When branding consistency is at risk - -## Review First - -- `frontend/index.html` -- `frontend/assets/css/styles.css` -- `docs/project-overview.md` -- `docs/decisions.md` - -## Restrictions - -- Do not introduce off-brand visuals or generic styles. -- Do not add asset-heavy redesign work unless explicitly requested. -- Preserve a sober tactical tone. - -## Collaboration With The Orchestrator - -- Validates visual consistency before design-oriented tasks are executed -- Helps frame asset and branding work into scoped tasks -- Keeps platform-generated work aligned with project identity diff --git a/ai/orchestrator/planning-memory.md b/ai/orchestrator/planning-memory.md deleted file mode 100644 index c36659f..0000000 --- a/ai/orchestrator/planning-memory.md +++ /dev/null @@ -1,12 +0,0 @@ -# Planning Memory - -## Purpose - -Store short planning lessons that help future tasks stay aligned with the repository. - -## Current Notes - -- HLL Vietnam is in foundation stage. -- Product work must not be invented from generic platform templates. -- Backend assumptions must remain Python-oriented. -- Frontend remains static and lightweight until explicitly expanded. diff --git a/ai/orchestrator/pm.md b/ai/orchestrator/pm.md deleted file mode 100644 index bb72f33..0000000 --- a/ai/orchestrator/pm.md +++ /dev/null @@ -1,30 +0,0 @@ -# PM - -## Mission - -Translate stakeholder intent into the smallest useful task scope without changing project goals on your own. - -## When This Role Intervenes - -- When a request needs scope framing -- When work must be split into smaller tasks -- When priorities or sequencing need clarification - -## Review First - -- `README.md` -- `docs/project-overview.md` -- `docs/roadmap.md` -- `AGENTS.md` - -## Restrictions - -- Do not invent new product features without instruction. -- Do not expand scope beyond what the request justifies. -- Do not bypass the task system. - -## Collaboration With The Orchestrator - -- Helps the orchestrator define task boundaries -- Suggests execution order -- Flags scope creep early diff --git a/ai/orchestrator/python-architect.md b/ai/orchestrator/python-architect.md deleted file mode 100644 index 0bf5936..0000000 --- a/ai/orchestrator/python-architect.md +++ /dev/null @@ -1,30 +0,0 @@ -# Arquitecto Python - -## Mission - -Ensure all backend-oriented planning remains coherent with a future Python implementation. - -## When This Role Intervenes - -- When backend architecture is discussed -- When automation or support scripts reference backend assumptions -- When tasks might accidentally introduce a conflicting stack - -## Review First - -- `AGENTS.md` -- `docs/decisions.md` -- `backend/README.md` -- `ai/repo-context.md` - -## Restrictions - -- Do not add Python services, frameworks or runtime code unless explicitly requested. -- Do not accept template defaults that assume .NET or another backend stack. -- Keep platform docs aligned with Python as the intended backend. - -## Collaboration With The Orchestrator - -- Reviews tasks for backend stack consistency -- Rewrites generic template assumptions into Python-compatible guidance -- Flags any drift away from the intended backend baseline diff --git a/ai/orchestrator/repo-reviewer.md b/ai/orchestrator/repo-reviewer.md deleted file mode 100644 index 291b2a5..0000000 --- a/ai/orchestrator/repo-reviewer.md +++ /dev/null @@ -1,12 +0,0 @@ -# Repository Reviewer - -## Purpose - -Review repository health and identify only the most relevant technical follow-ups. - -## Rules - -- Start from `ai/architecture-index.md` and `ai/repo-context.md`. -- Prefer documentation, consistency and workflow issues over speculative product work. -- Do not create a large backlog by default. -- If needed, create only minimal technical readiness tasks. diff --git a/ai/orchestrator/ui-expert.md b/ai/orchestrator/ui-expert.md deleted file mode 100644 index d1df4f5..0000000 --- a/ai/orchestrator/ui-expert.md +++ /dev/null @@ -1,30 +0,0 @@ -# Experto en Interfaz - -## Mission - -Safeguard usability, clarity and responsive behavior of the HLL Vietnam frontend without introducing unnecessary complexity. - -## When This Role Intervenes - -- When a task changes user-facing flows or layout -- When responsiveness or readability must be reviewed -- When an integration could degrade the landing experience - -## Review First - -- `frontend/index.html` -- `frontend/assets/css/styles.css` -- `frontend/assets/js/main.js` -- `docs/project-overview.md` - -## Restrictions - -- Do not add new interface flows without task scope. -- Do not sacrifice simplicity for novelty. -- Keep interactions lightweight and compatible with the current static frontend approach. - -## Collaboration With The Orchestrator - -- Reviews impact on usability before execution -- Recommends minimal UI-safe changes -- Helps keep frontend tasks grounded in real interface needs diff --git a/ai/prompts/plan-feature.md b/ai/prompts/plan-feature.md deleted file mode 100644 index c50e301..0000000 --- a/ai/prompts/plan-feature.md +++ /dev/null @@ -1,26 +0,0 @@ -# Plan Feature Prompt - -Use this prompt when the orchestrator needs to transform a repository request into implementation-ready tasks. - -## Prompt - -Analyze the HLL Vietnam repository before proposing any implementation work. - -Required behavior: - -1. Read `AGENTS.md`. -2. Read `ai/repo-context.md`. -3. Read `ai/architecture-index.md`. -4. Review only the files directly related to the request. -5. Produce a small, safe task breakdown. -6. Do not invent product features outside the request. -7. Keep branding, frontend stack and planned Python backend consistent with the repository rules. - -Task output rules: - -- Use `ai/task-template.md`. -- Keep tasks small and verifiable. -- Prefer one task when the work is very small. -- Add clear `Files to Read First`. -- Add clear `Expected Files to Modify`. -- Include explicit validation steps. diff --git a/ai/repo-context.md b/ai/repo-context.md deleted file mode 100644 index 7d6e8ae..0000000 --- a/ai/repo-context.md +++ /dev/null @@ -1,94 +0,0 @@ -# Repository Context - -## Project Overview - -HLL Vietnam is a community website repository for a Spanish-speaking Discord community centered on the future game HLL Vietnam. - -The current implementation is intentionally small: - -- a static landing page in `frontend/` -- a reserved Python backend space in `backend/` -- documentation in `docs/` -- an AI task orchestration layer in `ai/` - -This repository is in foundation stage. The objective is to grow in a controlled way without losing clarity or overwriting project identity with generic template content. - -## Current Product State - -- Frontend: static HTML, CSS and vanilla JavaScript -- Backend: not implemented yet, but planned in Python -- AI Platform: integrated to coordinate planning and task execution -- Product goal in current phase: maintain a clean landing and repository structure -- Default deployment: `backend` + `frontend`; historical workers are advanced/manual only. -- Live and historical defaults are RCON-first, with public-scoreboard kept only as historical fallback. -- Comunidad Hispana #03 is not part of default RCON targets. Historical/Elo code and persisted data are preserved, while Elo/MMR remains paused and decoupled from backend startup. -- RCON historical data flow is session capture plus AdminLog ingestion, parsed event storage, materialized matches/player stats and optional player profile snapshot enrichment. -- Public scoreboard may enrich links or fill unsupported historical gaps, but it is not the primary historical source when RCON coverage exists. - -## Repository Areas - -### Root documentation - -- `README.md` -- `AGENTS.md` - -These files define the repository purpose and operating rules. - -### Docs - -- `docs/project-overview.md` -- `docs/roadmap.md` -- `docs/decisions.md` - -These files describe scope, phased evolution and technical decisions. - -### Frontend - -- `frontend/index.html` -- `frontend/assets/css/styles.css` -- `frontend/assets/js/main.js` - -This is the live product surface in the current phase. Keep changes conservative unless a task explicitly targets the landing. - -### Backend - -- `backend/README.md` -- `backend/requirements.txt` -- `backend/app/__init__.py` - -This area is a reserved foundation for the future Python backend. Do not add functional services unless explicitly requested by task. - -### AI Platform - -- `ai/task-template.md` -- `ai-platform.json` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `ai/system-metrics.md` -- `ai/reports/` -- `ai/prompts/` -- `ai/orchestrator/` -- `ai/tasks/` - -This area supports planning, orchestration and execution discipline. - -## Working Rules For Agents - -- Always work from tasks, except for repository inspection or explicitly requested platform integration. -- Prefer small, focused, reviewable changes. -- Preserve the military and Vietnam-inspired visual tone. -- Avoid introducing new technologies without clear reason. -- Treat Python as the planned backend baseline. - -## AI Workflow - -`Request -> Orchestrator review -> Scoped task -> Execution -> Validation -> Documentation -> Commit` - -Tasks move through: - -- `ai/tasks/pending` -- `ai/tasks/in-progress` -- `ai/tasks/review` -- `ai/tasks/blocked` -- `ai/tasks/obsolete` -- `ai/tasks/done` diff --git a/ai/reports/.gitkeep b/ai/reports/.gitkeep deleted file mode 100644 index 8b13789..0000000 --- a/ai/reports/.gitkeep +++ /dev/null @@ -1 +0,0 @@ - diff --git a/ai/system-metrics.md b/ai/system-metrics.md deleted file mode 100644 index 08aa32d..0000000 --- a/ai/system-metrics.md +++ /dev/null @@ -1,25 +0,0 @@ -# System Metrics - -This file tracks lightweight execution history for the HLL Vietnam AI development workflow. - -## Metrics - -- Total task cycles executed -- Successful task cycles -- Failed task cycles -- Average cycle duration -- Notes about skipped validation steps - -## Task History - -Date | Task | Duration | Result | Notes -2026-03-19 | TASK-001-platform-readiness-check | n/a | success | README y roadmap alineados con la integración actual de AI Platform; scripts clave presentes; no hay tests de integración configurados para este alcance. -2026-03-19T13:59:33 | worker-cycle | 641.24 sec | success | codex-runner -2026-05-19T08:39:12 | worker-cycle | 663.71 sec | success | codex-runner -2026-05-19T17:20:44 | worker-cycle | 2240.22 sec | success | codex-runner -2026-05-21T14:43:44 | worker-cycle | 5580.9 sec | success | codex-runner -2026-05-21T15:17:18 | worker-cycle | 688.86 sec | success | codex-runner -2026-05-21T18:59:27 | worker-cycle | 527.54 sec | success | codex-runner -2026-06-08T18:58:19 | worker-cycle | 3951.99 sec | success | codex-runner -2026-06-08T19:02:50 | worker-cycle | 16.57 sec | success | codex-runner -2026-06-08T19:24:20 | worker-cycle | 1278.68 sec | failed(-1) | codex-runner diff --git a/ai/task-template.md b/ai/task-template.md deleted file mode 100644 index 704e659..0000000 --- a/ai/task-template.md +++ /dev/null @@ -1,86 +0,0 @@ ---- -id: TASK-XXX -title: Short task title -status: pending -type: platform | frontend | backend | documentation | research -team: PM | Analista | Backend Senior | Frontend Senior | Arquitecto de Base de Datos | Arquitecto Python | Disenador grafico | Experto en interfaz -supporting_teams: [] -roadmap_item: foundation -priority: medium ---- - -# TASK-XXX - Short task title - -## Goal - -Describe the smallest useful objective for this task. - -## Context - -Explain where the change happens in HLL Vietnam and why it is needed now. - -Preserve the current product identity: Spanish-speaking HLL Vietnam community, military/Vietnam/tactical/sober visual direction and controlled repository evolution. - -## Steps - -1. Inspect the listed files first. -2. Apply only the scoped change. -3. Validate the result and document relevant findings. - -## Files to Read First - -List 3 to 6 files that must be reviewed before changing anything. - -Examples for this repository: - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `frontend/index.html` -- `frontend/assets/css/styles.css` -- `backend/README.md` - -Rules: - -- Read these files before implementation. -- Keep the list small and directly relevant. -- Prefer existing docs and code that already define the area being changed. - -## Expected Files to Modify - -List the files that should change during the task. - -Rules: - -- Prefer modifying only these files. -- If additional files become necessary, explain why in the task outcome or commit message. -- Do not modify unrelated files. - -## Constraints - -- Keep the change minimal. -- Preserve HLL Vietnam project identity. -- Do not introduce unnecessary frameworks or dependencies. -- Do not implement backend functionality unless the task explicitly requires it. -- Do not expand Elo/MMR, historical workers or RCON server #03 handling unless the task explicitly requires it. -- Do not overwrite repository-specific context with generic platform template text. - -## Validation - -Before completing the task ensure: - -- scoped checks pass -- no unrelated files were modified -- documentation remains consistent with the repository state -- `git diff --name-only` matches the expected scope -- integration tests are run when relevant and configured - -## Outcome - -Document the validation performed, notable decisions, and any follow-up task that should be created instead of expanding this task. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/blocked/.gitkeep b/ai/tasks/blocked/.gitkeep deleted file mode 100644 index 8b13789..0000000 --- a/ai/tasks/blocked/.gitkeep +++ /dev/null @@ -1 +0,0 @@ - diff --git a/ai/tasks/done/.gitkeep b/ai/tasks/done/.gitkeep deleted file mode 100644 index 8b13789..0000000 --- a/ai/tasks/done/.gitkeep +++ /dev/null @@ -1 +0,0 @@ - diff --git a/ai/tasks/done/TASK-001-platform-readiness-check.md b/ai/tasks/done/TASK-001-platform-readiness-check.md deleted file mode 100644 index 4909478..0000000 --- a/ai/tasks/done/TASK-001-platform-readiness-check.md +++ /dev/null @@ -1,75 +0,0 @@ -# TASK-001-platform-readiness-check - -## Goal -Validar que la integración de AI Development Platform en el repositorio HLL Vietnam está completa, coherente y lista para ejecutar tasks de forma segura con Codex. - -## Context -El repositorio ya tiene una estructura base de producto y se ha integrado la capa operativa inspirada en ai-dev-platform-template. Antes de generar tasks funcionales del producto, hay que verificar que el flujo por tasks, documentación, scripts y estructura están realmente alineados y no contienen inconsistencias. - -## Steps -1. Revisar la estructura de carpetas del repositorio. -2. Verificar que existen y son coherentes: - - AGENTS.md - - ai/task-template.md - - ai/repo-context.md - - ai/architecture-index.md - - ai/system-metrics.md - - ai/prompts/plan-feature.md - - ai/orchestrator/* - - ai/tasks/pending - - ai/tasks/in-progress - - ai/tasks/done - - scripts/codex-runner.ps1 - - scripts/run-integration-tests.ps1 -3. Confirmar que AGENTS.md refleja el flujo correcto: - - el orquestador analiza código y redacta tasks - - Codex no actúa fuera de tasks salvo mantenimiento o inspección explícita - - backend previsto en Python - - frontend actual en HTML/CSS/JS -4. Revisar que la documentación de contexto no contradice el proyecto HLL Vietnam. -5. Revisar que la task actual y la plantilla de task usan una estructura coherente con el template. -6. Si detectas incoherencias pequeñas, corrígelas. -7. Dejar un breve resumen en ai/system-metrics.md o en la documentación correspondiente si el flujo del repo ya lo contempla. - -## Files to Read First -- AGENTS.md -- README.md -- docs/project-overview.md -- docs/decisions.md -- ai/task-template.md -- ai/repo-context.md -- ai/architecture-index.md -- ai/orchestrator/README.md -- scripts/codex-runner.ps1 -- scripts/run-integration-tests.ps1 - -## Expected Files to Modify -- Solo los estrictamente necesarios si se detectan inconsistencias menores. -- No modificar archivos de producto salvo documentación mínima si es imprescindible. - -## Constraints -- No implementar features del producto. -- No tocar la landing salvo que haya una inconsistencia documental o estructural. -- No añadir dependencias nuevas. -- No hacer cambios destructivos. -- Mantener el cambio pequeño y verificable. - -## Validation -- La estructura AI Platform existe y es navegable. -- AGENTS.md refleja correctamente el flujo de trabajo del proyecto. -- No hay referencias obsoletas a .NET como arquitectura del producto. -- Los scripts clave existen. -- La plantilla de task es usable para futuras tasks. -- El repo queda listo para que el siguiente paso sea crear una task funcional real. - -## Change Budget -- Preferir menos de 8 archivos modificados. -- Preferir menos de 250 líneas cambiadas. - -## Outcome -- Verificada la existencia y coherencia de `AGENTS.md`, `ai/task-template.md`, `ai/repo-context.md`, `ai/architecture-index.md`, `ai/system-metrics.md`, `ai/prompts/plan-feature.md`, `ai/orchestrator/*`, `ai/tasks/*`, `scripts/codex-runner.ps1` y `scripts/run-integration-tests.ps1`. -- Confirmado que `AGENTS.md` refleja correctamente el flujo por tasks, el alcance de Codex y la dirección técnica actual: frontend en HTML/CSS/JS y backend futuro en Python. -- Corregidas dos incoherencias documentales menores: - - `README.md` ya no presenta la plataforma AI como integración futura. - - `docs/roadmap.md` ahora trata la orquestación como capacidad existente que debe evolucionar, no incorporarse desde cero. -- Validación manual completada. El script `scripts/run-integration-tests.ps1` existe, pero actualmente solo documenta que no hay tests de integración configurados para este alcance. diff --git a/ai/tasks/done/TASK-002-logo-asset-integration.md b/ai/tasks/done/TASK-002-logo-asset-integration.md deleted file mode 100644 index d55b843..0000000 --- a/ai/tasks/done/TASK-002-logo-asset-integration.md +++ /dev/null @@ -1,61 +0,0 @@ -# TASK-002-logo-asset-integration - -## Goal -Integrar correctamente el logo real del proyecto HLL Vietnam en la landing actual, asegurando que el frontend use un asset local estable y coherente con la identidad visual del proyecto. - -## Context -La landing inicial ya existe y actualmente está preparada para mostrar un logo local en `frontend/assets/img/logo.png`. Antes de hacer mejoras visuales adicionales, hay que consolidar la integración del logo real para que el proyecto tenga una base visual correcta, mantenible y consistente. - -## Steps -1. Revisar la estructura actual del frontend. -2. Confirmar que existe la ruta esperada para el logo: - - `frontend/assets/img/logo.png` -3. Si el logo real aún no está en esa ruta, dejar la integración preparada de forma segura sin romper la página. -4. Revisar `frontend/index.html` para asegurar que: - - usa la ruta local correcta del logo - - el `alt` del logo es descriptivo y coherente - - no hay rutas temporales, absolutas o inconsistentes -5. Revisar `frontend/assets/css/styles.css` para asegurar que: - - el bloque visual del logo tiene un tamaño adecuado - - mantiene buena presentación en escritorio y móvil - - no deforma la imagen -6. Corregir cualquier inconsistencia menor relacionada con la carga o presentación del logo. -7. Mantener la landing simple: logo, tráiler y botón de Discord. - -## Files to Read First -- frontend/index.html -- frontend/assets/css/styles.css -- docs/project-overview.md -- ai/repo-context.md -- AGENTS.md - -## Expected Files to Modify -- frontend/index.html -- frontend/assets/css/styles.css -- opcionalmente `frontend/assets/img/logo.png` si el flujo de la task contempla dejar el asset correctamente ubicado - -## Constraints -- No rediseñar toda la landing. -- No añadir nuevas secciones. -- No introducir frameworks ni dependencias nuevas. -- No tocar backend. -- No hacer cambios destructivos. -- Mantener la estética militar sobria ya definida. - -## Validation -- La landing referencia el logo local mediante una ruta estable. -- El logo se muestra correctamente sin deformaciones. -- El HTML sigue funcionando al abrirse directamente en navegador. -- La presentación del logo es correcta tanto en móvil como en escritorio. -- No se rompe el tráiler ni el botón de Discord. - -## Change Budget -- Preferir menos de 4 archivos modificados. -- Preferir menos de 120 líneas cambiadas. - -## Outcome -- Confirmada la existencia del asset local `frontend/assets/img/logo.png`; no fue necesario reemplazarlo ni moverlo. -- `frontend/index.html` mantiene una ruta local estable (`./assets/img/logo.png`) y ahora usa un `alt` más descriptivo junto con dimensiones explícitas para reducir saltos de layout. -- `frontend/assets/css/styles.css` ya no fuerza un contenedor cuadrado para el logo: la imagen conserva su proporción con `max-width` y `max-height`, con ajustes específicos para escritorio y móvil. -- Validación completada mediante revisión del marcado, verificación de la ruta local del logo y revisión de `git diff --name-only`. -- No hay tests de integración configurados para este alcance; la comprobación aplicable fue manual sobre HTML/CSS y compatibilidad con apertura directa en navegador. diff --git a/ai/tasks/done/TASK-003-landing-minimal-polish.md b/ai/tasks/done/TASK-003-landing-minimal-polish.md deleted file mode 100644 index 8a70f12..0000000 --- a/ai/tasks/done/TASK-003-landing-minimal-polish.md +++ /dev/null @@ -1,67 +0,0 @@ -# TASK-003-landing-minimal-polish - -## Goal -Mejorar visualmente la landing actual de HLL Vietnam con un pulido minimo y controlado, reforzando la identidad militar y la claridad visual sin cambiar el alcance funcional de la pagina. - -## Context -La landing ya tiene los tres elementos principales del alcance actual: logo local, boton de Discord y trailer embebido. Tras integrar correctamente el asset del logo, el siguiente paso es mejorar la presentacion general para que la pagina tenga una apariencia mas solida, mas limpia y mas coherente con la tematica del proyecto, sin anadir nuevas secciones ni complejidad innecesaria. - -## Steps -1. Revisar la estructura actual de `frontend/index.html`. -2. Revisar los estilos actuales en `frontend/assets/css/styles.css`. -3. Mejorar la jerarquia visual del bloque principal: - - logo - - titulo principal - - subtitulo, si existe - - boton de Discord - - bloque del trailer -4. Ajustar espaciados, tamanos, anchuras y alineaciones para mejorar legibilidad. -5. Reforzar la identidad visual militar sobria: - - paleta oscura - - acentos controlados - - mejor contraste - - sensacion tactica/cinematica sin recargar -6. Mejorar el contenedor del video para que se vea mas integrado en la composicion general. -7. Verificar que la landing siga funcionando correctamente en escritorio y movil. -8. Mantener el alcance estricto actual, sin anadir nuevas funcionalidades ni secciones. - -## Files to Read First -- frontend/index.html -- frontend/assets/css/styles.css -- docs/project-overview.md -- ai/repo-context.md -- AGENTS.md - -## Expected Files to Modify -- frontend/index.html -- frontend/assets/css/styles.css - -## Constraints -- No anadir nuevas secciones de contenido. -- No tocar backend. -- No introducir frameworks ni librerias nuevas. -- No modificar la ruta del logo. -- No cambiar el enlace de Discord. -- No cambiar el trailer. -- No hacer cambios destructivos. -- Mantener el HTML funcional abriendose directamente en navegador. - -## Validation -- La landing se ve mas solida y ordenada visualmente. -- Se mantiene el enfoque minimo: logo, identidad, Discord y trailer. -- El logo sigue cargando desde `./assets/img/logo.png`. -- El boton de Discord sigue visible y destacado. -- El trailer sigue funcionando correctamente. -- La presentacion sigue siendo responsive. -- No se anaden elementos fuera del alcance actual. - -## Change Budget -- Preferir menos de 3 archivos modificados. -- Preferir menos de 180 lineas cambiadas. - -## Outcome -- `frontend/index.html` mantiene el contenido original de la landing y solo anade hooks de estilo para reforzar la jerarquia visual del bloque principal. -- `frontend/assets/css/styles.css` mejora composicion, contraste, espaciados y tratamiento del bloque de video con una direccion mas sobria y tactica, sin introducir nuevas secciones ni funcionalidades. -- Se mantuvieron sin cambios la ruta del logo (`./assets/img/logo.png`), el enlace de Discord y el `iframe` del trailer. -- Validacion completada mediante revision del HTML/CSS resultante y `git diff --name-only`, confirmando que el alcance quedo limitado a los archivos esperados. -- No hay tests de integracion configurados para este alcance; la validacion aplicable fue manual sobre compatibilidad de HTML/CSS para apertura directa en navegador y comportamiento responsive esperado. diff --git a/ai/tasks/done/TASK-004-python-backend-bootstrap.md b/ai/tasks/done/TASK-004-python-backend-bootstrap.md deleted file mode 100644 index 95c4766..0000000 --- a/ai/tasks/done/TASK-004-python-backend-bootstrap.md +++ /dev/null @@ -1,69 +0,0 @@ -# TASK-004-python-backend-bootstrap - -## Goal -Preparar una base minima y ordenada de backend en Python para el proyecto HLL Vietnam, dejando la estructura lista para crecer sin implementar todavia logica de negocio real ni integraciones externas. - -## Context -El proyecto ya dispone de una landing minima funcional y de la capa operativa AI Platform integrada. El siguiente paso tecnico logico es dejar preparado el backend principal del proyecto, que estara basado en Python. En esta fase no se busca desarrollar funcionalidades reales, sino establecer una base limpia, mantenible y coherente con la futura evolucion del sistema. - -## Steps -1. Revisar la estructura actual de la carpeta `backend/`. -2. Preparar una base minima de aplicacion Python dentro de `backend/app/`. -3. Crear o ajustar un punto de entrada claro para la aplicacion, por ejemplo un archivo principal como: - - `backend/app/main.py` -4. Definir una estructura minima coherente para crecimiento posterior. -5. Anadir un endpoint o mecanismo minimo de verificacion de estado, por ejemplo: - - `/health` - o equivalente segun la solucion elegida. -6. Actualizar `backend/README.md` para explicar: - - proposito de la carpeta backend - - stack elegido en esta fase - - como arrancar localmente la base minima si ya aplica -7. Ajustar `backend/requirements.txt` con las dependencias minimas reales, si fueran necesarias. -8. Mantener el alcance estricto: solo bootstrap tecnico del backend. - -## Files to Read First -- README.md -- AGENTS.md -- docs/project-overview.md -- docs/roadmap.md -- docs/decisions.md -- ai/repo-context.md -- ai/architecture-index.md -- backend/README.md -- backend/requirements.txt -- backend/app/__init__.py - -## Expected Files to Modify -- backend/README.md -- backend/requirements.txt -- backend/app/__init__.py -- backend/app/main.py - -## Constraints -- No implementar logica de Discord. -- No implementar logica de servidores de juego. -- No anadir base de datos todavia. -- No introducir complejidad innecesaria. -- No tocar frontend salvo documentacion cruzada minima si fuera imprescindible. -- No hacer cambios destructivos. -- Mantener la solucion simple, clara y preparada para crecer. - -## Validation -- Existe una estructura backend mas solida que la inicial. -- Existe un punto de entrada claro para la aplicacion Python. -- Existe una verificacion minima de estado o equivalente. -- La documentacion del backend refleja correctamente el nuevo estado. -- No se han anadido funcionalidades fuera de alcance. -- El backend queda listo para que una siguiente task defina contratos API o primeras rutas reales. - -## Change Budget -- Preferir menos de 6 archivos modificados o creados. -- Preferir menos de 220 lineas cambiadas. - -## Outcome -- Bootstrap backend implementado con Python estandar, sin frameworks ni dependencias externas. -- Punto de entrada creado en `backend/app/main.py`. -- Health check minimo disponible en `GET /health`. -- `backend/README.md` actualizado con estructura, alcance y forma de arranque local. -- `backend/requirements.txt` mantenido sin dependencias externas para evitar compromisos prematuros de arquitectura. diff --git a/ai/tasks/done/TASK-005-frontend-backend-contract.md b/ai/tasks/done/TASK-005-frontend-backend-contract.md deleted file mode 100644 index 28979e0..0000000 --- a/ai/tasks/done/TASK-005-frontend-backend-contract.md +++ /dev/null @@ -1,86 +0,0 @@ -# TASK-005-frontend-backend-contract - -## Goal -Definir el contrato inicial entre frontend y backend para el proyecto HLL Vietnam, estableciendo endpoints, formatos de respuesta y convenciones mínimas sin implementar todavía integraciones reales con Discord, servidores de juego o base de datos. - -## Context -El proyecto ya dispone de una landing mínima funcional y de un backend Python bootstrap con verificación básica de estado. Antes de añadir lógica real, es importante fijar un contrato claro entre frontend y backend para evitar improvisación posterior y permitir que futuras tasks implementen endpoints y consumo de datos de forma consistente. - -## Steps -1. Revisar la estructura actual del frontend y del backend. -2. Revisar el estado actual del backend bootstrap y el endpoint de salud existente. -3. Definir el conjunto mínimo de endpoints previstos a corto plazo, aunque algunos queden documentados como futuros. Incluir al menos: - - `GET /health` - - `GET /api/community` - - `GET /api/trailer` - - `GET /api/discord` - - `GET /api/servers` -4. Para cada endpoint, documentar: - - propósito - - método HTTP - - ruta - - formato de respuesta - - ejemplo JSON - - estado actual: implementado, previsto o placeholder -5. Definir convenciones básicas de respuesta: - - nombres de campos - - estructura JSON - - uso de `status` - - tratamiento mínimo de errores -6. Documentar cómo debería consumir el frontend estos endpoints más adelante, sin implementarlo todavía. -7. Añadir o actualizar documentación técnica para que el contrato quede claro dentro del repositorio. -8. Si detectas incoherencias pequeñas entre documentación y bootstrap actual, corrígelas sin salirte del alcance. - -## Files to Read First -- README.md -- AGENTS.md -- docs/project-overview.md -- docs/roadmap.md -- docs/decisions.md -- ai/repo-context.md -- ai/architecture-index.md -- backend/README.md -- backend/app/__init__.py -- backend/app/main.py -- frontend/index.html -- frontend/assets/js/main.js - -## Expected Files to Modify -- docs/project-overview.md -- docs/decisions.md -- backend/README.md -- ai/architecture-index.md -- opcionalmente un nuevo documento técnico si encaja mejor, por ejemplo: - - `docs/frontend-backend-contract.md` - -## Constraints -- No implementar todavía endpoints reales adicionales. -- No integrar Discord real. -- No integrar servidores de juego reales. -- No introducir base de datos. -- No cambiar el comportamiento visible del frontend. -- No añadir frameworks ni dependencias nuevas. -- No hacer cambios destructivos. -- Mantener la solución clara, pequeña y útil para futuras tasks. - -## Validation -- Existe documentación clara del contrato inicial frontend-backend. -- `GET /health` queda reflejado correctamente como endpoint actual. -- Los endpoints futuros quedan documentados con ejemplos coherentes. -- El contrato usa convenciones consistentes de respuesta JSON. -- El repositorio queda preparado para que siguientes tasks implementen endpoints reales de forma ordenada. - -## Change Budget -- Preferir menos de 5 archivos modificados o creados. -- Preferir menos de 220 líneas cambiadas. -## Outcome - -- Se añadió `docs/frontend-backend-contract.md` como referencia central del contrato inicial frontend-backend. -- Se actualizaron `docs/project-overview.md`, `docs/decisions.md` y `backend/README.md` para reflejar el contrato y el estado actual de `GET /health`. -- No se implementaron endpoints nuevos ni se cambió el comportamiento visible del frontend. - -## Validation Result - -- Verificado con `python -c "from app.main import build_health_payload; print(build_health_payload())"` en `backend/`. -- Resultado comprobado: `{'status': 'ok', 'service': 'hll-vietnam-backend', 'phase': 'bootstrap'}`. -- No aplican integration tests para este alcance documental. diff --git a/ai/tasks/done/TASK-006-discord-and-server-data-plan.md b/ai/tasks/done/TASK-006-discord-and-server-data-plan.md deleted file mode 100644 index 7c1abaa..0000000 --- a/ai/tasks/done/TASK-006-discord-and-server-data-plan.md +++ /dev/null @@ -1,84 +0,0 @@ -# TASK-006-discord-and-server-data-plan - -## Goal -Definir la estrategia técnica inicial para obtener, modelar y exponer los futuros datos de Discord y de los servidores de juego en el proyecto HLL Vietnam, sin implementar todavía integraciones reales. - -## Context -El proyecto ya dispone de una landing mínima, un backend Python bootstrap y un contrato inicial frontend-backend documentado. Antes de implementar endpoints reales o lógica de consumo en frontend, es necesario fijar un plan claro sobre qué datos se quieren mostrar, de qué fuentes podrían obtenerse, qué limitaciones existen y cuál será el orden recomendado de implementación. - -## Steps -1. Revisar la documentación técnica actual del proyecto. -2. Identificar qué información tendría sentido mostrar en la web sobre Discord. Incluir al menos posibles bloques como: - - enlace de invitación - - nombre de la comunidad - - estado o presencia aproximada si fuera viable - - información pública útil para comunidad -3. Identificar qué información tendría sentido mostrar sobre los servidores de juego. Incluir al menos posibles bloques como: - - nombre del servidor - - estado online/offline - - mapa actual o rotación si fuera viable - - jugadores conectados - - capacidad máxima - - ping o metadatos similares si la fuente lo permite -4. Documentar las posibles fuentes de datos para Discord, distinguiendo claramente entre: - - widget público - - API o integraciones externas - - bot propio - - datos configurados manualmente -5. Documentar las posibles fuentes de datos para servidores de juego, distinguiendo claramente entre: - - consultas al servidor - - API externa - - datos mock/placeholder - - actualización manual -6. Documentar riesgos, límites y restricciones: - - credenciales - - rate limits - - disponibilidad - - seguridad - - CORS - - latencia - - dependencia de servicios externos -7. Proponer una estrategia por fases: - - fase inicial con placeholders o datos controlados - - fase intermedia con integración técnica limitada - - fase posterior con integración más real si procede -8. Dejar claro qué NO se implementará todavía. -9. Actualizar la documentación técnica del repositorio para que futuras tasks de backend y frontend tengan una base clara. - -## Files to Read First -- README.md -- AGENTS.md -- docs/project-overview.md -- docs/roadmap.md -- docs/decisions.md -- docs/frontend-backend-contract.md -- ai/repo-context.md -- ai/architecture-index.md -- backend/README.md - -## Expected Files to Modify -- docs/roadmap.md -- docs/decisions.md -- ai/architecture-index.md -- opcionalmente un nuevo documento técnico si encaja mejor, por ejemplo: - - docs/discord-and-server-data-plan.md - -## Constraints -- No implementar integraciones reales. -- No modificar comportamiento del frontend. -- No añadir endpoints funcionales nuevos. -- No introducir dependencias nuevas. -- No tocar base de datos. -- No hacer cambios destructivos. -- Mantener el resultado claro, útil y centrado en planificación técnica. - -## Validation -- Existe una estrategia documentada para los datos futuros de Discord. -- Existe una estrategia documentada para los datos futuros de servidores. -- Se distinguen claramente fuentes posibles, riesgos y fases. -- Queda explícito qué se hará primero y qué se pospone. -- La documentación sirve como base directa para siguientes tasks técnicas. - -## Change Budget -- Preferir menos de 5 archivos modificados o creados. -- Preferir menos de 240 líneas cambiadas. diff --git a/ai/tasks/done/TASK-007-backend-api-skeleton.md b/ai/tasks/done/TASK-007-backend-api-skeleton.md deleted file mode 100644 index 252d374..0000000 --- a/ai/tasks/done/TASK-007-backend-api-skeleton.md +++ /dev/null @@ -1,66 +0,0 @@ -# TASK-007-backend-api-skeleton - -## Goal -Preparar un esqueleto inicial de API en el backend Python para HLL Vietnam, dejando rutas y estructura listas para crecimiento posterior mediante respuestas placeholder o mock, sin integrar todavía Discord ni servidores reales. - -## Context -El backend ya cuenta con un bootstrap mínimo y un endpoint de salud. El contrato frontend-backend ya define un conjunto inicial de endpoints previstos. El siguiente paso técnico es convertir esa definición en una estructura API básica y mantenible, con rutas organizadas y respuestas coherentes, aunque todavía sean estáticas o placeholder. - -## Steps -1. Revisar el backend actual y la documentación del contrato frontend-backend. -2. Confirmar el punto de entrada actual del backend y su estructura. -3. Preparar una organización mínima para rutas API futuras dentro de `backend/app/`. -4. Implementar o estructurar las rutas placeholder mínimas para: - - `GET /health` - - `GET /api/community` - - `GET /api/trailer` - - `GET /api/discord` - - `GET /api/servers` -5. Hacer que las respuestas sean coherentes con el contrato ya documentado, aunque usen datos placeholder. -6. Mantener una estructura clara para crecimiento posterior, por ejemplo separando: - - punto de entrada - - rutas - - utilidades o payloads placeholder si hiciera falta -7. Actualizar la documentación del backend para reflejar la nueva estructura y cómo ejecutar la API localmente. -8. Mantener el alcance estricto: esqueleto funcional, no integración real. - -## Files to Read First -- AGENTS.md -- docs/frontend-backend-contract.md -- docs/project-overview.md -- docs/decisions.md -- ai/repo-context.md -- ai/architecture-index.md -- backend/README.md -- backend/requirements.txt -- backend/app/__init__.py -- backend/app/main.py - -## Expected Files to Modify -- backend/app/main.py -- backend/app/__init__.py -- backend/README.md -- opcionalmente archivos nuevos dentro de `backend/app/` si mejoran claridad, por ejemplo: - - backend/app/routes.py - - backend/app/payloads.py - -## Constraints -- No integrar Discord real. -- No integrar servidores reales. -- No añadir base de datos. -- No introducir complejidad innecesaria. -- No tocar frontend. -- No añadir frameworks nuevos si no son estrictamente necesarios para mantener coherencia con el bootstrap actual. -- No hacer cambios destructivos. -- Mantener la API simple, clara y consistente con la documentación ya existente. - -## Validation -- El backend expone claramente los endpoints placeholder definidos. -- `GET /health` sigue funcionando correctamente. -- Los endpoints futuros definidos en el contrato existen al menos como placeholders coherentes. -- La estructura backend queda mejor preparada para crecimiento. -- La documentación del backend refleja el nuevo estado real. - -## Change Budget -- Preferir menos de 7 archivos modificados o creados. -- Preferir menos de 260 líneas cambiadas. diff --git a/ai/tasks/done/TASK-008-frontend-data-consumption-plan.md b/ai/tasks/done/TASK-008-frontend-data-consumption-plan.md deleted file mode 100644 index 31a002e..0000000 --- a/ai/tasks/done/TASK-008-frontend-data-consumption-plan.md +++ /dev/null @@ -1,68 +0,0 @@ -# TASK-008-frontend-data-consumption-plan - -## Goal -Definir cómo consumirá el frontend de HLL Vietnam los futuros endpoints del backend, dejando documentada una estrategia clara de integración de datos sin implementar todavía lógica real de consumo. - -## Context -Ya existe una landing mínima y se ha definido un contrato inicial entre frontend y backend. Además, se va a preparar un esqueleto API en backend. Antes de introducir JavaScript de consumo real o secciones dinámicas, conviene dejar documentado cómo deberá organizarse la integración en frontend para mantener simplicidad, claridad y consistencia con la evolución del proyecto. - -## Steps -1. Revisar el frontend actual y el contrato frontend-backend. -2. Identificar qué bloques del frontend actual o futuro podrán depender de datos dinámicos del backend. -3. Definir una estrategia mínima de consumo de datos adecuada al proyecto en esta fase, por ejemplo: - - `fetch` - - JavaScript simple - - módulos ligeros si fueran necesarios más adelante -4. Documentar cómo deberían gestionarse: - - estados de carga - - errores - - ausencia de datos - - placeholders - - fallback visual -5. Documentar qué endpoints podrían ser consumidos primero y con qué prioridad: - - `/health` - - `/api/community` - - `/api/trailer` - - `/api/discord` - - `/api/servers` -6. Proponer una estrategia progresiva para pasar de landing estática a bloques dinámicos sin romper simplicidad. -7. Añadir o actualizar documentación técnica del frontend o del proyecto con esta estrategia. -8. Mantener el alcance documental: no implementar todavía fetch real ni renderizado dinámico. - -## Files to Read First -- AGENTS.md -- README.md -- docs/project-overview.md -- docs/frontend-backend-contract.md -- docs/decisions.md -- ai/repo-context.md -- ai/architecture-index.md -- frontend/index.html -- frontend/assets/js/main.js -- frontend/assets/css/styles.css - -## Expected Files to Modify -- docs/project-overview.md -- docs/decisions.md -- ai/architecture-index.md -- opcionalmente un nuevo documento técnico si encaja mejor, por ejemplo: - - docs/frontend-data-consumption-plan.md - -## Constraints -- No implementar consumo real de API. -- No cambiar comportamiento visible del frontend. -- No añadir librerías nuevas. -- No rediseñar la landing. -- No tocar backend salvo referencias documentales mínimas si son imprescindibles. -- No hacer cambios destructivos. -- Mantener la solución centrada en planificación de integración. - -## Validation -- Existe una estrategia documentada para el consumo de datos en frontend. -- Quedan definidos criterios para loading, error, empty state y fallback. -- Se identifican prioridades de consumo de endpoints. -- El frontend queda preparado conceptualmente para evolucionar sin improvisación. - -## Change Budget -- Preferir menos de 5 archivos modificados o creados. -- Preferir menos de 220 líneas cambiadas. diff --git a/ai/tasks/done/TASK-009-backend-package-hygiene-and-entrypoint-alignment.md b/ai/tasks/done/TASK-009-backend-package-hygiene-and-entrypoint-alignment.md deleted file mode 100644 index 0a31e8c..0000000 --- a/ai/tasks/done/TASK-009-backend-package-hygiene-and-entrypoint-alignment.md +++ /dev/null @@ -1,55 +0,0 @@ -# TASK-009-backend-package-hygiene-and-entrypoint-alignment - -## Goal -Corregir y alinear la estructura mínima del paquete backend en Python para HLL Vietnam, asegurando que el paquete, los imports y el entrypoint real sean consistentes, legibles y mantenibles. - -## Context -El backend bootstrap y el esqueleto API placeholder ya existen, pero en resúmenes recientes aparece una posible inconsistencia con el archivo de paquete Python (`init.py` frente a `__init__.py`). Antes de continuar con más ajustes o integrar consumo desde frontend, es importante dejar la base del paquete limpia y sin ambigüedades. - -## Steps -1. Revisar la estructura actual de `backend/app/`. -2. Confirmar si el archivo correcto del paquete existe como: - - `backend/app/__init__.py` -3. Si existe cualquier inconsistencia de naming o packaging, corregirla. -4. Revisar y alinear los imports internos del backend para que sean coherentes con la estructura final. -5. Confirmar cuál es el entrypoint real del backend y dejarlo claro en la documentación. -6. Revisar el comando de arranque documentado y adaptarlo si fuera necesario. -7. Validar que los endpoints placeholder actuales siguen funcionando tras el ajuste. -8. Mantener el cambio pequeño y centrado en higiene estructural, no en nuevas funcionalidades. - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- ai/architecture-index.md -- backend/README.md -- backend/requirements.txt -- backend/app/__init__.py -- backend/app/main.py -- backend/app/routes.py -- backend/app/payloads.py - -## Expected Files to Modify -- backend/app/__init__.py -- backend/app/main.py -- backend/app/routes.py -- backend/README.md -- opcionalmente otros archivos internos del backend si son estrictamente necesarios para alinear imports y entrypoint - -## Constraints -- No añadir integraciones reales. -- No introducir dependencias nuevas innecesarias. -- No tocar frontend. -- No añadir base de datos. -- No hacer cambios destructivos fuera del alcance del paquete backend. -- Mantener el backend simple y consistente con la fase actual. - -## Validation -- Existe un archivo de paquete Python correcto en `backend/app/__init__.py`. -- No quedan referencias ambiguas o incorrectas al package layout. -- El entrypoint del backend está claro. -- Los endpoints placeholder actuales siguen respondiendo. -- La documentación del backend refleja el estado real. - -## Change Budget -- Preferir menos de 5 archivos modificados. -- Preferir menos de 160 líneas cambiadas. diff --git a/ai/tasks/done/TASK-010-backend-local-dev-config-and-cors-bootstrap.md b/ai/tasks/done/TASK-010-backend-local-dev-config-and-cors-bootstrap.md deleted file mode 100644 index 584c6e8..0000000 --- a/ai/tasks/done/TASK-010-backend-local-dev-config-and-cors-bootstrap.md +++ /dev/null @@ -1,55 +0,0 @@ -# TASK-010-backend-local-dev-config-and-cors-bootstrap - -## Goal -Preparar la configuración mínima de desarrollo local del backend para HLL Vietnam, incluyendo parámetros básicos de ejecución y soporte controlado para consumo desde frontend local durante la fase de desarrollo. - -## Context -El proyecto ya tiene frontend estático y backend placeholder. El siguiente paso para permitir un primer enlace real entre ambos es dejar clara la forma de ejecución local y, si aplica, habilitar el mínimo soporte técnico necesario para consultas desde frontend local, evitando problemas básicos de entorno o de origen cruzado en desarrollo. - -## Steps -1. Revisar cómo se ejecuta actualmente el backend. -2. Definir y documentar claramente: - - host por defecto - - puerto por defecto - - comando de arranque local -3. Revisar si el frontend local necesitará consumir el backend desde distinto origen durante desarrollo. -4. Si hace falta, añadir una solución mínima y controlada para CORS o para origen local de desarrollo, sin sobredimensionar el sistema. -5. Mantener la configuración simple y enfocada al entorno local. -6. Actualizar la documentación relevante para que levantar el stack local sea fácil. -7. No introducir complejidad de producción en esta fase. - -## Files to Read First -- README.md -- AGENTS.md -- ai/repo-context.md -- docs/project-overview.md -- docs/frontend-backend-contract.md -- backend/README.md -- backend/app/main.py -- backend/app/routes.py - -## Expected Files to Modify -- backend/README.md -- backend/app/main.py -- opcionalmente un archivo nuevo de configuración mínima si mejora claridad, por ejemplo: - - backend/app/config.py -- opcionalmente documentación raíz si conviene reflejar arranque local combinado - -## Constraints -- No integrar Discord real. -- No integrar servidores reales. -- No añadir base de datos. -- No añadir frameworks nuevos salvo que sean estrictamente necesarios y coherentes con la base ya existente. -- No tocar el comportamiento visible del frontend todavía. -- No hacer cambios destructivos. -- Mantener la configuración pequeña, clara y orientada a desarrollo local. - -## Validation -- El backend tiene host/puerto local claramente definidos o documentados. -- Existe una forma clara de levantarlo en local. -- Si el frontend necesita consultar el backend desde otro origen, la solución mínima está resuelta o documentada. -- El proyecto queda listo para un primer consumo real desde frontend en una task posterior inmediata. - -## Change Budget -- Preferir menos de 5 archivos modificados o creados. -- Preferir menos de 180 líneas cambiadas. diff --git a/ai/tasks/done/TASK-011-frontend-health-and-trailer-progressive-enhancement.md b/ai/tasks/done/TASK-011-frontend-health-and-trailer-progressive-enhancement.md deleted file mode 100644 index be096cc..0000000 --- a/ai/tasks/done/TASK-011-frontend-health-and-trailer-progressive-enhancement.md +++ /dev/null @@ -1,60 +0,0 @@ -# TASK-011-frontend-health-and-trailer-progressive-enhancement - -## Goal -Realizar el primer enlace real entre frontend y backend en HLL Vietnam mediante una mejora progresiva y controlada, consultando el estado del backend y, de forma opcional, el endpoint placeholder del tráiler, sin romper la landing estática actual. - -## Context -La landing actual ya funciona como página estática simple con logo, botón de Discord y tráiler embebido. El backend ya dispone de un bootstrap y de endpoints placeholder. El siguiente ajuste lógico es introducir una mejora progresiva mínima desde `frontend/assets/js/main.js`, manteniendo fallback estático cuando el backend no esté disponible. - -## Steps -1. Revisar el frontend actual y el plan de consumo de datos. -2. Revisar el backend actual y el contrato frontend-backend. -3. Preparar en `main.js` una integración mínima con el backend, manteniendo la simplicidad del proyecto. -4. Consultar al menos: - - `GET /health` -5. Evaluar si también conviene consumir: - - `GET /api/trailer` - siempre manteniendo fallback estático en el HTML. -6. Añadir una señal visual mínima, discreta y no intrusiva para reflejar estado del backend si la integración lo justifica. -7. Asegurar que, si el backend no está disponible, la landing sigue funcionando exactamente como página estática. -8. No introducir todavía integración real de Discord ni servidores. -9. Mantener intacta la identidad visual general de la landing. - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- docs/frontend-backend-contract.md -- docs/frontend-data-consumption-plan.md -- frontend/index.html -- frontend/assets/js/main.js -- frontend/assets/css/styles.css -- backend/app/main.py -- backend/app/routes.py -- backend/app/payloads.py - -## Expected Files to Modify -- frontend/index.html -- frontend/assets/js/main.js -- frontend/assets/css/styles.css -- opcionalmente documentación mínima si fuera necesario reflejar el comportamiento progresivo - -## Constraints -- No rediseñar la landing completa. -- No añadir nuevas secciones grandes. -- No integrar Discord real. -- No integrar servidores reales. -- No añadir librerías nuevas. -- No romper el funcionamiento estático actual. -- No hacer cambios destructivos. -- Mantener la mejora contenida y reversible. - -## Validation -- La landing sigue funcionando aunque el backend no esté disponible. -- El frontend puede consultar `/health` correctamente cuando el backend está levantado. -- El comportamiento visual añadido es discreto y coherente. -- El tráiler y el botón de Discord siguen funcionando. -- La solución sienta la base para consumos reales futuros sin introducir complejidad excesiva. - -## Change Budget -- Preferir menos de 4 archivos modificados. -- Preferir menos de 200 líneas cambiadas. diff --git a/ai/tasks/done/TASK-012-current-hll-servers-source-plan.md b/ai/tasks/done/TASK-012-current-hll-servers-source-plan.md deleted file mode 100644 index 17b1070..0000000 --- a/ai/tasks/done/TASK-012-current-hll-servers-source-plan.md +++ /dev/null @@ -1,72 +0,0 @@ -# TASK-012-current-hll-servers-source-plan - -## Goal -Definir la estrategia técnica y de producto para mostrar en la web de HLL Vietnam un bloque provisional de servidores actuales de Hell Let Loose, diferenciándolos claramente del futuro contexto Vietnam y sin implementar todavía integración real definitiva. - -## Context -A día de hoy el foco temático del proyecto es HLL Vietnam, pero todavía no existen servidores reales de ese entorno para consumirlos como fuente del producto. Como solución provisional y útil para la comunidad, se quiere mostrar información de servidores actuales de Hell Let Loose, dejando claro que se trata de servidores del juego actual y no de HLL Vietnam. Antes de construir integración backend o UI final, hay que documentar fuente, campos, límites y estrategia de sustitución futura. - -## Steps -1. Revisar la documentación actual del proyecto y la estrategia de datos ya definida. -2. Documentar el objetivo del bloque provisional de servidores actuales de HLL. -3. Definir claramente cómo debe presentarse en producto para evitar confusión con HLL Vietnam. -4. Identificar qué campos tiene sentido mostrar en esta fase. Incluir al menos: - - nombre del servidor - - estado online/offline - - jugadores actuales - - capacidad máxima - - mapa actual si está disponible - - región o etiqueta útil si existe -5. Documentar las posibles fuentes de esos datos, distinguiendo entre: - - fuente externa pública - - datos controlados o placeholder - - integración futura más robusta -6. Documentar riesgos y restricciones: - - disponibilidad de terceros - - CORS - - rate limits - - estabilidad del formato - - dependencia de scraping o fuentes no oficiales -7. Proponer una estrategia por fases: - - fase 1: payload controlado/mock con forma realista - - fase 2: adaptador backend para fuente externa o dataset controlado - - fase 3: sustitución por datos más cercanos a HLL Vietnam cuando existan -8. Dejar claro qué no se implementará todavía. -9. Actualizar documentación técnica del repositorio para que siguientes tasks tengan base clara. - -## Files to Read First -- README.md -- AGENTS.md -- docs/project-overview.md -- docs/roadmap.md -- docs/decisions.md -- docs/frontend-backend-contract.md -- docs/discord-and-server-data-plan.md -- ai/repo-context.md -- ai/architecture-index.md -- backend/README.md - -## Expected Files to Modify -- docs/roadmap.md -- docs/decisions.md -- ai/architecture-index.md -- opcionalmente un nuevo documento técnico si encaja mejor, por ejemplo: - - docs/current-hll-servers-source-plan.md - -## Constraints -- No implementar integración real todavía. -- No modificar comportamiento visible del frontend. -- No añadir dependencias nuevas. -- No tocar base de datos. -- No hacer cambios destructivos. -- Mantener el resultado centrado en planificación técnica y de producto. - -## Validation -- Existe una estrategia documentada para mostrar servidores actuales de Hell Let Loose como contenido provisional. -- Queda claramente diferenciada la identidad de HLL actual frente a HLL Vietnam. -- Se documentan campos, fuentes, riesgos y fases. -- La documentación sirve como base directa para una task backend y una task frontend posteriores. - -## Change Budget -- Preferir menos de 5 archivos modificados o creados. -- Preferir menos de 220 líneas cambiadas. diff --git a/ai/tasks/done/TASK-013-backend-current-hll-servers-placeholder-adapter.md b/ai/tasks/done/TASK-013-backend-current-hll-servers-placeholder-adapter.md deleted file mode 100644 index 6225ac0..0000000 --- a/ai/tasks/done/TASK-013-backend-current-hll-servers-placeholder-adapter.md +++ /dev/null @@ -1,57 +0,0 @@ -# TASK-013-backend-current-hll-servers-placeholder-adapter - -## Goal -Preparar en el backend Python un adaptador placeholder limpio y consistente para exponer al frontend una lista provisional de servidores actuales de Hell Let Loose, sin integrar todavía una fuente externa real. - -## Context -El backend ya dispone de un esqueleto API y de endpoints placeholder. Se ha decidido que la web podrá mostrar, de forma provisional, servidores actuales de Hell Let Loose mientras no existan datos reales de HLL Vietnam. Antes de conectar fuentes externas, conviene preparar un adaptador backend limpio que devuelva datos controlados con una estructura estable y preparada para sustitución futura. - -## Steps -1. Revisar el backend actual, especialmente el endpoint relacionado con servidores y los payloads placeholder existentes. -2. Revisar la documentación del contrato frontend-backend y el plan de servidores actuales. -3. Definir una estructura clara y estable para el payload de servidores actuales de HLL. -4. Ajustar el backend para que `GET /api/servers` devuelva una respuesta coherente con ese modelo provisional. -5. Asegurar que el payload distinga claramente que se trata de servidores actuales de Hell Let Loose y no de HLL Vietnam, si esa distinción encaja en el modelo. -6. Mantener la implementación desacoplada para que más adelante pueda sustituirse la fuente sin romper al frontend. -7. Actualizar la documentación backend si el comportamiento real del endpoint cambia respecto a lo documentado. -8. Mantener el alcance estricto: adaptador placeholder estable, no integración real. - -## Files to Read First -- AGENTS.md -- docs/frontend-backend-contract.md -- docs/discord-and-server-data-plan.md -- docs/current-hll-servers-source-plan.md -- ai/repo-context.md -- ai/architecture-index.md -- backend/README.md -- backend/app/__init__.py -- backend/app/main.py -- backend/app/routes.py -- backend/app/payloads.py -- backend/app/config.py - -## Expected Files to Modify -- backend/app/routes.py -- backend/app/payloads.py -- backend/app/main.py -- backend/README.md -- opcionalmente documentación contractual o técnica si necesita alineación menor - -## Constraints -- No integrar todavía una fuente externa real. -- No añadir scraping. -- No añadir base de datos. -- No tocar frontend en esta task. -- No introducir complejidad innecesaria. -- No hacer cambios destructivos. -- Mantener la API simple, estable y preparada para evolución posterior. - -## Validation -- `GET /api/servers` devuelve un payload placeholder más consistente y útil. -- La respuesta está preparada para consumo frontend. -- La estructura deja claro que el contenido actual es provisional y basado en servidores actuales de HLL. -- La documentación backend refleja el estado real del endpoint si cambió. - -## Change Budget -- Preferir menos de 5 archivos modificados. -- Preferir menos de 180 líneas cambiadas. diff --git a/ai/tasks/done/TASK-014-landing-current-hll-servers-panel.md b/ai/tasks/done/TASK-014-landing-current-hll-servers-panel.md deleted file mode 100644 index 2a2bbb2..0000000 --- a/ai/tasks/done/TASK-014-landing-current-hll-servers-panel.md +++ /dev/null @@ -1,61 +0,0 @@ -# TASK-014-landing-current-hll-servers-panel - -## Goal -Añadir a la landing de HLL Vietnam un panel visual de servidores actuales de Hell Let Loose, alimentado por el backend placeholder, dejando claro que se trata de contenido provisional mientras no existan datos reales de HLL Vietnam. - -## Context -La landing ya dispone de una mejora progresiva frontend-backend y el backend puede exponer endpoints placeholder. El proyecto necesita empezar a mostrar información más útil y dinámica, pero sin fingir que ya existen servidores de HLL Vietnam. Esta task debe introducir un bloque visual controlado que muestre servidores actuales de HLL como referencia provisional para la comunidad. - -## Steps -1. Revisar la landing actual, los estilos y la mejora progresiva ya implementada en frontend. -2. Revisar el payload real o previsto de `GET /api/servers`. -3. Añadir un bloque visual nuevo en la landing para mostrar servidores actuales de Hell Let Loose. -4. Hacer que el frontend consuma `GET /api/servers` de forma progresiva, manteniendo fallback seguro si el backend no está disponible. -5. Mostrar de forma clara y ordenada, como mínimo: - - nombre del servidor - - estado - - jugadores - - capacidad máxima - - mapa si está disponible -6. Añadir una etiqueta o texto breve que deje claro que son servidores actuales de Hell Let Loose usados como referencia provisional. -7. Mantener coherencia visual con la identidad militar sobria del proyecto. -8. Asegurar que la landing siga funcionando si el backend no responde o si no hay datos. -9. No tocar todavía integración real de Discord ni fuentes externas reales. - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- docs/frontend-backend-contract.md -- docs/frontend-data-consumption-plan.md -- docs/current-hll-servers-source-plan.md -- frontend/index.html -- frontend/assets/js/main.js -- frontend/assets/css/styles.css -- backend/app/routes.py -- backend/app/payloads.py - -## Expected Files to Modify -- frontend/index.html -- frontend/assets/js/main.js -- frontend/assets/css/styles.css -- opcionalmente documentación mínima si fuera necesario reflejar el nuevo bloque - -## Constraints -- No rediseñar completamente la landing. -- No añadir librerías nuevas. -- No romper el fallback estático actual. -- No presentar esos servidores como si fueran de HLL Vietnam. -- No integrar fuentes externas reales directamente desde frontend. -- No hacer cambios destructivos. -- Mantener la mejora acotada, clara y coherente con la fase actual. - -## Validation -- La landing muestra un panel de servidores actuales de HLL de forma clara. -- El panel obtiene datos desde `GET /api/servers` cuando el backend está disponible. -- Si el backend no está disponible, la landing sigue funcionando sin romperse. -- La UI deja claro que se trata de contenido provisional. -- La integración visual es coherente con el resto de la página. - -## Change Budget -- Preferir menos de 4 archivos modificados. -- Preferir menos de 220 líneas cambiadas. diff --git a/ai/tasks/done/TASK-015-landing-visual-system-pass.md b/ai/tasks/done/TASK-015-landing-visual-system-pass.md deleted file mode 100644 index 71e0598..0000000 --- a/ai/tasks/done/TASK-015-landing-visual-system-pass.md +++ /dev/null @@ -1,66 +0,0 @@ -# TASK-015-landing-visual-system-pass - -## Goal -Realizar una pasada de sistema visual sobre la landing de HLL Vietnam para reforzar identidad, consistencia, contraste y jerarquia general, manteniendo el alcance actual del producto y sin cambiar la arquitectura funcional. - -## Context -La landing ya cuenta con logo, trailer, CTA de Discord, estado de backend y panel provisional de servidores actuales de Hell Let Loose. La base funcional existe, pero ahora hace falta una pasada centrada unicamente en calidad visual para que la web tenga una presentacion mas solida, coherente y atractiva dentro del tono militar/tactico del proyecto. - -## Steps -1. Revisar la composicion visual global de la landing actual. -2. Revisar la paleta actual, contraste, espaciados, tipografias, contenedores y ritmo vertical. -3. Refinar el sistema visual general sin redisenar por completo la pagina. -4. Mejorar: - - jerarquia tipografica - - espaciado entre bloques - - consistencia entre tarjetas y paneles - - contraste entre fondo, texto y elementos destacados - - sensacion visual militar sobria y cinematografica -5. Mantener una estetica oscura, tactica y limpia, evitando recargar la pagina. -6. Asegurar que todos los bloques principales compartan un lenguaje visual coherente. -7. Validar que el resultado siga funcionando bien en escritorio y movil. -8. No cambiar el alcance funcional del producto. - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- docs/project-overview.md -- frontend/index.html -- frontend/assets/css/styles.css -- frontend/assets/js/main.js - -## Expected Files to Modify -- frontend/index.html -- frontend/assets/css/styles.css - -## Constraints -- No anadir nuevas funcionalidades. -- No cambiar endpoints ni logica backend. -- No introducir librerias nuevas. -- No cambiar el flujo funcional de la landing. -- No reescribir toda la estructura HTML salvo ajustes razonables para mejorar composicion. -- No hacer cambios destructivos. -- Mantener el diseno dentro del tono HLL Vietnam. - -## Validation -- La landing tiene una apariencia mas coherente y profesional. -- La jerarquia visual es mas clara. -- El contraste y la legibilidad mejoran. -- La identidad militar/tactica queda reforzada. -- No se rompe ninguna funcionalidad existente. -- La landing sigue viendose correctamente en movil y escritorio. - -## Change Budget -- Preferir menos de 3 archivos modificados. -- Preferir menos de 220 lineas cambiadas. - -## Outcome -- Se reforzo el sistema visual general de la landing sin cambiar su alcance funcional. -- Se ajusto la jerarquia visual entre hero, panel de trailer y panel de servidores para que compartan mejor lenguaje visual. -- Se mejoraron contraste, ritmo vertical, bordes, sombras y consistencia de contenedores dentro del tono militar sobrio del proyecto. - -## Validation Notes -- `git diff --name-only -- frontend/index.html frontend/assets/css/styles.css` devuelve solo los archivos esperados por la task. -- Se reviso el CSS para mantener compatibilidad responsive en escritorio y movil mediante los breakpoints existentes. -- No se cambiaron endpoints, logica backend ni comportamiento funcional de la landing. -- No hay pruebas automaticas configuradas para este ajuste visual; la validacion disponible en esta task es revision de alcance y consistencia del marcado y CSS. diff --git a/ai/tasks/done/TASK-016-hero-logo-and-trailer-cinematic-polish.md b/ai/tasks/done/TASK-016-hero-logo-and-trailer-cinematic-polish.md deleted file mode 100644 index 1484ca2..0000000 --- a/ai/tasks/done/TASK-016-hero-logo-and-trailer-cinematic-polish.md +++ /dev/null @@ -1,73 +0,0 @@ -# TASK-016-hero-logo-and-trailer-cinematic-polish - -## Goal -Mejorar visualmente el bloque principal de la landing de HLL Vietnam, con foco en hero, logo y trailer, para darle una presencia mas cinematografica, mas inmersiva y mas propia de una comunidad tactica. - -## Context -El usuario quiere priorizar el ajuste visual. El hero actual ya funciona, pero debe ganar impacto sin perder simplicidad. El logo debe sentirse mas protagonista, el bloque del trailer debe integrarse mejor en la composicion y el conjunto debe transmitir mejor el tono del proyecto. - -## Steps -1. Revisar la composicion actual del hero. -2. Revisar el tratamiento visual del logo: - - tamano - - posicion - - marco - - sombra - - integracion con el fondo -3. Revisar el tratamiento visual del trailer: - - contenedor - - marco - - separacion respecto al resto - - equilibrio con el CTA y el titulo -4. Mejorar la presencia del bloque principal sin anadir secciones nuevas. -5. Reforzar: - - impacto inicial - - sensacion de identidad - - claridad del CTA principal - - integracion visual entre logo, titulo y video -6. Mantener el diseno sobrio, sin caer en efectos exagerados. -7. Validar que la composicion siga siendo responsive y estable. - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- frontend/index.html -- frontend/assets/css/styles.css -- frontend/assets/js/main.js - -## Expected Files to Modify -- frontend/index.html -- frontend/assets/css/styles.css - -## Constraints -- No cambiar la ruta del logo. -- No cambiar el enlace de Discord. -- No cambiar el enlace del trailer. -- No anadir nuevas funcionalidades. -- No romper el fallback actual. -- No usar librerias nuevas. -- No hacer cambios destructivos. -- Mantener la landing simple. - -## Validation -- El hero tiene mas presencia visual. -- El logo se percibe mejor integrado y mas protagonista. -- El trailer se siente mejor enmarcado dentro del diseno. -- El CTA sigue siendo claro y visible. -- El resultado mantiene coherencia con el tono militar/tactico del proyecto. -- La composicion funciona en desktop y mobile. - -## Change Budget -- Preferir menos de 2 archivos modificados. -- Preferir menos de 180 lineas cambiadas. - -## Outcome -- Se reorganizo el bloque principal para agrupar mejor estado backend y CTA sin cambiar su funcionamiento. -- Se reforzo el tratamiento visual del logo con un marco mas trabajado, sombras mas controladas y una mejor integracion con el fondo del hero. -- Se ajusto el panel de trailer para que se sienta mas cinematografico y mejor conectado con la identidad visual del hero. - -## Validation Notes -- `git diff --name-only -- frontend/index.html frontend/assets/css/styles.css` devuelve solo los archivos esperados por la task. -- Se confirmo que no se cambiaron la ruta del logo, el enlace de Discord ni la URL del trailer. -- La task se mantuvo en cambios de composicion y estilo; no se altero el fallback ni la logica existente. -- No hay pruebas automaticas especificas para esta composicion; la validacion disponible es revision estructural de HTML/CSS y del alcance del diff. diff --git a/ai/tasks/done/TASK-017-server-panel-visual-polish-and-responsive-pass.md b/ai/tasks/done/TASK-017-server-panel-visual-polish-and-responsive-pass.md deleted file mode 100644 index 9598393..0000000 --- a/ai/tasks/done/TASK-017-server-panel-visual-polish-and-responsive-pass.md +++ /dev/null @@ -1,69 +0,0 @@ -# TASK-017-server-panel-visual-polish-and-responsive-pass - -## Goal -Pulir visualmente el panel de servidores actuales de Hell Let Loose y mejorar su comportamiento responsive para que se integre mejor con el resto de la landing y se vea claro, ordenado y fiable. - -## Context -El panel de servidores ya existe y consume datos del backend placeholder con fallback estatico. Ahora hace falta una pasada especifica de UI para que las tarjetas o elementos del panel tengan una presentacion mas clara y mas profesional, sin tocar todavia estrategia de copy ni fuentes reales de datos. - -## Steps -1. Revisar el marcado actual del panel de servidores en la landing. -2. Revisar como se renderizan los datos desde frontend. -3. Mejorar visualmente: - - tarjetas o filas de servidor - - jerarquia de nombre, estado, jugadores y mapa - - badges o indicadores de estado - - separacion entre items - - integracion con el resto de la landing -4. Mejorar el comportamiento responsive del panel: - - anchuras - - apilado - - legibilidad en movil - - consistencia de espaciados -5. Mantener claro que se trata de un bloque provisional sin tocar todavia el copy estrategico en profundidad. -6. Respetar el fallback actual si el backend no responde. -7. No cambiar el alcance funcional del panel. - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- frontend/index.html -- frontend/assets/css/styles.css -- frontend/assets/js/main.js -- backend/app/payloads.py - -## Expected Files to Modify -- frontend/index.html -- frontend/assets/css/styles.css -- frontend/assets/js/main.js - -## Constraints -- No cambiar el contrato del backend. -- No tocar payloads backend. -- No anadir librerias nuevas. -- No romper el fallback estatico. -- No presentar estos servidores como si fueran de HLL Vietnam. -- No hacer cambios destructivos. -- Mantener el ajuste centrado en UI y responsive. - -## Validation -- El panel de servidores se ve mas limpio y claro. -- La lectura de estado, jugadores y mapa mejora. -- El panel responde bien en movil y escritorio. -- El fallback sigue funcionando. -- La integracion visual con la landing es mejor que antes. - -## Change Budget -- Preferir menos de 3 archivos modificados. -- Preferir menos de 200 lineas cambiadas. - -## Outcome -- Se mejoro la jerarquia visual de cada servidor con identidad, estado mas legible y mejor separacion entre bloques de datos. -- Se anadio un indicador visual de ocupacion basado en los datos ya disponibles sin cambiar el contrato del backend. -- Se alineo el markup estatico de `index.html` con el render dinamico de `main.js` para mantener el mismo acabado cuando el backend esta disponible o no. - -## Validation Notes -- `git diff --name-only -- frontend/index.html frontend/assets/css/styles.css frontend/assets/js/main.js` devuelve solo los archivos esperados por la task. -- `node --check frontend\\assets\\js\\main.js` se ejecuto correctamente. -- No se modifico `backend/app/payloads.py` ni el contrato del backend. -- El fallback estatico se conserva porque el HTML base y el render dinamico usan la misma estructura visual del panel. diff --git a/ai/tasks/done/TASK-018-current-hll-data-ingestion-plan.md b/ai/tasks/done/TASK-018-current-hll-data-ingestion-plan.md deleted file mode 100644 index bdca398..0000000 --- a/ai/tasks/done/TASK-018-current-hll-data-ingestion-plan.md +++ /dev/null @@ -1,74 +0,0 @@ -# TASK-018-current-hll-data-ingestion-plan - -## Goal -Definir la estrategia técnica de ingesta de datos para Hell Let Loose actual, usándolo como banco de pruebas del proyecto HLL Vietnam, con foco en servidores, snapshots e históricos básicos sin implementar todavía la ingesta real completa. - -## Context -La landing ya muestra servidores actuales de HLL como contenido provisional y el backend ya dispone de una base API placeholder. El siguiente paso lógico es fijar cómo se obtendrán y normalizarán datos reales o semirrealistas de HLL actual para validar la arquitectura que más adelante podrá reutilizarse con HLL Vietnam. - -## Steps -1. Revisar la documentación actual del proyecto relacionada con servidores, backend y evolución de datos. -2. Definir qué tipos de datos se quieren ingerir inicialmente desde HLL actual. Incluir al menos: - - listado de servidores - - estado online/offline - - jugadores actuales - - capacidad máxima - - mapa actual si está disponible - - timestamp de captura -3. Definir el concepto de snapshot de servidor y cómo se usará para construir histórico. -4. Documentar las posibles fuentes técnicas de ingesta para HLL actual, distinguiendo entre: - - datos controlados/mock - - fuente externa pública - - consulta directa de servidor o capa intermedia -5. Documentar riesgos y límites: - - disponibilidad de terceros - - cambios de formato - - rate limits - - latencia - - CORS - - fiabilidad de datos - - dependencia de scraping o APIs no oficiales -6. Proponer la arquitectura de ingesta por fases: - - fase 1: payload controlado y estructura estable - - fase 2: colector de snapshots con fuente real o casi real - - fase 3: explotación histórica y estadísticas básicas -7. Dejar claro qué no se implementará todavía. -8. Actualizar la documentación técnica del repositorio para servir de base a las siguientes tasks de base de datos y colector. - -## Files to Read First -- README.md -- AGENTS.md -- docs/project-overview.md -- docs/roadmap.md -- docs/decisions.md -- docs/discord-and-server-data-plan.md -- docs/current-hll-servers-source-plan.md -- docs/frontend-backend-contract.md -- ai/repo-context.md -- ai/architecture-index.md -- backend/README.md - -## Expected Files to Modify -- docs/roadmap.md -- docs/decisions.md -- ai/architecture-index.md -- opcionalmente un nuevo documento técnico si encaja mejor, por ejemplo: - - docs/current-hll-data-ingestion-plan.md - -## Constraints -- No implementar todavía ingesta real. -- No modificar comportamiento visible del frontend. -- No añadir base de datos funcional en esta task. -- No añadir dependencias nuevas. -- No hacer cambios destructivos. -- Mantener el resultado centrado en planificación técnica reutilizable para futuro HLL Vietnam. - -## Validation -- Existe una estrategia documentada de ingesta para HLL actual como banco de pruebas. -- Quedan definidos snapshots, fuentes posibles, riesgos y fases. -- La documentación deja claro cómo se conectará este trabajo con almacenamiento e históricos. -- La base sirve para una siguiente task de esquema de base de datos. - -## Change Budget -- Preferir menos de 5 archivos modificados o creados. -- Preferir menos de 240 líneas cambiadas. diff --git a/ai/tasks/done/TASK-018-hero-layout-rebalance.md b/ai/tasks/done/TASK-018-hero-layout-rebalance.md deleted file mode 100644 index 66a721e..0000000 --- a/ai/tasks/done/TASK-018-hero-layout-rebalance.md +++ /dev/null @@ -1,57 +0,0 @@ -# TASK-018-hero-layout-rebalance - -## Goal -Reequilibrar la composición visual del hero de la landing de HLL Vietnam para darle más impacto, reducir sensación de vacío vertical y mejorar la relación entre logo, titular, subtítulo y CTA principal. - -## Context -La landing ya tiene una base visual sólida, pero el hero actual presenta varios puntos de mejora: demasiado espacio vertical, un titular muy dominante partido en varias líneas, un logo con menos protagonismo del deseado y una composición general menos potente que el resto de la página. Esta task debe centrarse únicamente en recomponer el bloque principal para que se perciba como una cabecera premium, más compacta y más cinematográfica, sin cambiar el alcance funcional actual. - -## Steps -1. Revisar la composición actual del hero en la landing. -2. Evaluar el equilibrio visual entre: - - logo - - eyebrow o etiqueta superior - - título principal - - subtítulo o texto descriptivo - - chip de estado backend si aplica - - CTA principal -3. Reducir la sensación de vacío vertical y mejorar el ritmo del bloque. -4. Ajustar el protagonismo del logo para que se sienta más integrado y relevante. -5. Ajustar el titular para que mantenga fuerza, pero no rompa la composición ni monopolice toda la jerarquía visual. -6. Reordenar o afinar espaciados, anchuras máximas y alineaciones para que el conjunto se perciba más compacto y más intencional. -7. Mantener el hero claro, centrado en comunidad, branding y CTA. -8. Validar que la composición siga funcionando bien en móvil y escritorio. -9. No alterar enlaces, rutas ni comportamiento funcional existente. - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- frontend/index.html -- frontend/assets/css/styles.css -- frontend/assets/js/main.js - -## Expected Files to Modify -- frontend/index.html -- frontend/assets/css/styles.css - -## Constraints -- No cambiar la ruta del logo. -- No cambiar el enlace del Discord. -- No cambiar el enlace del tráiler. -- No añadir nuevas secciones. -- No introducir librerías nuevas. -- No romper el fallback actual. -- No hacer cambios destructivos. -- Mantener la landing simple y coherente con el tono HLL Vietnam. - -## Validation -- El hero se siente más compacto y más fuerte visualmente. -- El logo tiene mejor presencia relativa. -- El titular sigue siendo potente pero está mejor equilibrado. -- El CTA sigue siendo claro y visible. -- La cabecera transmite más sensación de portada principal. -- La composición sigue siendo responsive y estable. - -## Change Budget -- Preferir menos de 2 archivos modificados. -- Preferir menos de 170 líneas cambiadas. diff --git a/ai/tasks/done/TASK-019-atmospheric-depth-pass.md b/ai/tasks/done/TASK-019-atmospheric-depth-pass.md deleted file mode 100644 index ba5d45d..0000000 --- a/ai/tasks/done/TASK-019-atmospheric-depth-pass.md +++ /dev/null @@ -1,56 +0,0 @@ -# TASK-019-atmospheric-depth-pass - -## Goal -Aumentar la profundidad visual y la atmósfera general de la landing de HLL Vietnam mediante un refinamiento controlado de fondo, overlays, iluminación y separación de planos, sin recargar la interfaz ni romper su sobriedad. - -## Context -La paleta actual funciona y la base visual está bien encaminada, pero el fondo y el marco general aún se perciben algo planos. Hace falta una pasada de atmósfera para reforzar el tono Vietnam/táctico, mejorar la profundidad percibida y dar más cohesión al conjunto, especialmente alrededor del hero y de las secciones principales. - -## Steps -1. Revisar el tratamiento actual del fondo y los overlays. -2. Evaluar cómo se perciben: - - profundidad - - viñeteado - - textura ambiental - - degradados - - separación entre hero y secciones -3. Refinar el sistema de fondo para aportar más atmósfera sin saturar. -4. Aplicar mejoras controladas en: - - overlays - - sombras de entorno - - iluminación indirecta - - separación de bloques - - sensación cinematográfica -5. Mantener una estética oscura, militar y limpia. -6. Evitar efectos exagerados, brillos excesivos o ruido visual. -7. Validar que el resultado no perjudica legibilidad ni rendimiento aparente. -8. Mantener intacto el comportamiento funcional de la landing. - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- frontend/index.html -- frontend/assets/css/styles.css - -## Expected Files to Modify -- frontend/assets/css/styles.css -- opcionalmente `frontend/index.html` si hiciera falta una envolvente mínima o ajuste estructural pequeño para soportar mejor la profundidad visual - -## Constraints -- No cambiar contenido funcional. -- No añadir imágenes nuevas ni dependencias nuevas salvo que sea estrictamente innecesario. -- No rediseñar completamente la página. -- No tocar backend. -- No hacer cambios destructivos. -- Mantener el tono sobrio y cinematográfico. - -## Validation -- La página transmite mayor profundidad visual. -- El fondo se siente menos plano. -- Hero y secciones se perciben mejor separados y más cohesionados. -- La atmósfera Vietnam/táctica queda reforzada. -- La legibilidad y claridad general se mantienen o mejoran. - -## Change Budget -- Preferir menos de 2 archivos modificados. -- Preferir menos de 160 líneas cambiadas. diff --git a/ai/tasks/done/TASK-019-stats-database-schema-foundation.md b/ai/tasks/done/TASK-019-stats-database-schema-foundation.md deleted file mode 100644 index c30a423..0000000 --- a/ai/tasks/done/TASK-019-stats-database-schema-foundation.md +++ /dev/null @@ -1,65 +0,0 @@ -# TASK-019-stats-database-schema-foundation - -## Goal -Diseñar y dejar preparada la base del esquema de almacenamiento para snapshots y estadísticas iniciales de servidores de HLL actual, con una modelización genérica que pueda reutilizarse en el futuro para HLL Vietnam. - -## Context -El proyecto necesita pasar de payloads placeholder a una arquitectura capaz de almacenar históricos. Antes de implementar colectores reales, es necesario definir un esquema de datos claro, neutro y extensible para snapshots de servidores y primeras métricas agregadas. - -## Steps -1. Revisar la documentación técnica actual sobre backend, contratos y plan de ingesta. -2. Definir las entidades mínimas necesarias para la primera fase de persistencia. Incluir al menos: - - game o source context si aplica - - servers - - server_snapshots - - posibles tablas de agregación inicial o vistas documentadas para estadísticas -3. Asegurar que el naming sea genérico y reutilizable, evitando acoplar el modelo a Vietnam. -4. Definir para cada entidad: - - propósito - - campos principales - - claves - - relaciones - - timestamps -5. Documentar qué datos deben persistirse por snapshot y cuáles pueden derivarse después. -6. Si el backend ya usa o prevé una tecnología concreta para persistencia, reflejarlo con claridad. Si aún no, documentar una base neutra y coherente. -7. Añadir o actualizar documentación técnica del repositorio para dejar claro el modelo inicial de almacenamiento. -8. Mantener el alcance en diseño y preparación, no en implementación completa de persistencia productiva. - -## Files to Read First -- AGENTS.md -- docs/project-overview.md -- docs/roadmap.md -- docs/decisions.md -- docs/frontend-backend-contract.md -- docs/current-hll-data-ingestion-plan.md -- ai/repo-context.md -- ai/architecture-index.md -- backend/README.md -- backend/app/config.py -- backend/app/main.py - -## Expected Files to Modify -- docs/decisions.md -- ai/architecture-index.md -- backend/README.md -- opcionalmente un nuevo documento técnico si encaja mejor, por ejemplo: - - docs/stats-database-schema-foundation.md -- opcionalmente archivos base de estructura si el repositorio ya está preparado para ello, pero sin implementar una base de datos completa - -## Constraints -- No implementar todavía la base de datos completa. -- No añadir migraciones productivas si la decisión técnica aún no está consolidada. -- No tocar frontend. -- No añadir integraciones reales de servidor. -- No hacer cambios destructivos. -- Mantener el modelo simple, genérico y preparado para crecer. - -## Validation -- Existe un esquema de almacenamiento inicial claro para snapshots y estadísticas básicas. -- El naming es reutilizable para HLL actual y futuro HLL Vietnam. -- La documentación deja claro qué se persistirá primero y por qué. -- El resultado sirve como base directa para una siguiente task de colector de snapshots. - -## Change Budget -- Preferir menos de 5 archivos modificados o creados. -- Preferir menos de 220 líneas cambiadas. diff --git a/ai/tasks/done/TASK-020-component-surface-polish.md b/ai/tasks/done/TASK-020-component-surface-polish.md deleted file mode 100644 index a841e16..0000000 --- a/ai/tasks/done/TASK-020-component-surface-polish.md +++ /dev/null @@ -1,58 +0,0 @@ -# TASK-020-component-surface-polish - -## Goal -Pulir visualmente superficies y componentes de la landing de HLL Vietnam para mejorar calidad percibida, consistencia y acabado en tarjetas, chips, badges, contenedores y detalles de UI. - -## Context -La landing ya tiene una estructura visual bastante competente, pero aún puede ganar acabado en microdetalles de interfaz. El panel de servidores, las tarjetas, los chips de estado y los contenedores principales necesitan una pasada de consistencia visual para que el conjunto se sienta más refinado y más uniforme. - -## Steps -1. Revisar los componentes visuales actuales de la landing. -2. Evaluar consistencia en: - - radios - - bordes - - sombras - - chips - - badges de estado - - tarjetas - - barras de ocupación - - encabezados de panel -3. Refinar esos elementos para que compartan un lenguaje visual más sólido y coherente. -4. Mejorar calidad percibida sin añadir complejidad innecesaria. -5. Asegurar que el panel de servidores y los componentes de apoyo se lean mejor tanto en estado estático como hidratado por JS. -6. Mantener clara la jerarquía entre componentes primarios y secundarios. -7. Validar responsive y consistencia entre escritorio y móvil. -8. No tocar el contrato del backend ni el contenido funcional de los payloads. - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- frontend/index.html -- frontend/assets/css/styles.css -- frontend/assets/js/main.js -- backend/app/payloads.py - -## Expected Files to Modify -- frontend/index.html -- frontend/assets/css/styles.css -- frontend/assets/js/main.js - -## Constraints -- No cambiar endpoints. -- No cambiar payloads backend. -- No añadir librerías nuevas. -- No romper el fallback estático. -- No rediseñar completamente la landing. -- No hacer cambios destructivos. -- Mantener el ajuste centrado en UI y acabado visual. - -## Validation -- Las superficies y componentes se ven más coherentes y mejor acabados. -- Chips, badges y tarjetas tienen una presentación más limpia y consistente. -- El panel de servidores gana claridad y calidad visual. -- La landing mantiene su funcionamiento actual. -- La mejora se aprecia en desktop y mobile. - -## Change Budget -- Preferir menos de 3 archivos modificados. -- Preferir menos de 190 líneas cambiadas. diff --git a/ai/tasks/done/TASK-020-server-snapshot-collector-bootstrap.md b/ai/tasks/done/TASK-020-server-snapshot-collector-bootstrap.md deleted file mode 100644 index 0a0ca3d..0000000 --- a/ai/tasks/done/TASK-020-server-snapshot-collector-bootstrap.md +++ /dev/null @@ -1,61 +0,0 @@ -# TASK-020-server-snapshot-collector-bootstrap - -## Goal -Preparar un bootstrap técnico mínimo para un colector de snapshots de servidores en el backend Python, dejando la estructura lista para capturar y normalizar datos de HLL actual sin implementar todavía una ingesta completa de producción. - -## Context -Tras definir la estrategia de ingesta y el esquema base de almacenamiento, el siguiente paso es dejar preparada la estructura mínima de un colector en backend. Esta task no debe resolver toda la persistencia ni depender de una fuente definitiva, pero sí debe sentar la base para un flujo futuro de captura periódica. - -## Steps -1. Revisar la documentación de ingesta y esquema de almacenamiento. -2. Revisar la estructura actual del backend Python. -3. Crear una estructura mínima y clara para un colector o servicio de snapshots dentro de `backend/app/`. -4. Definir interfaces o funciones base para: - - obtener datos crudos de una fuente - - normalizar esos datos - - producir un snapshot consistente -5. Si encaja con la fase actual, permitir una ejecución manual o de desarrollo del colector usando datos controlados. -6. Mantener la implementación desacoplada para que la fuente real pueda sustituirse más adelante sin romper el resto del backend. -7. Actualizar la documentación backend para explicar el papel del colector y cómo encaja con futuras estadísticas. -8. Mantener el alcance estricto: bootstrap técnico del colector, no pipeline completo de producción. - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- ai/architecture-index.md -- docs/current-hll-data-ingestion-plan.md -- docs/stats-database-schema-foundation.md -- backend/README.md -- backend/app/__init__.py -- backend/app/config.py -- backend/app/main.py -- backend/app/routes.py -- backend/app/payloads.py - -## Expected Files to Modify -- backend/README.md -- backend/app/__init__.py -- opcionalmente archivos nuevos dentro de `backend/app/` si mejoran claridad, por ejemplo: - - backend/app/collector.py - - backend/app/normalizers.py - - backend/app/snapshots.py -- opcionalmente documentación técnica relacionada si requiere alineación menor - -## Constraints -- No implementar todavía una ingesta real completa. -- No depender de scraping productivo. -- No introducir una base de datos completa en esta task. -- No tocar frontend. -- No añadir complejidad innecesaria. -- No hacer cambios destructivos. -- Mantener la estructura clara y pequeña. - -## Validation -- El backend contiene una base mínima para un colector de snapshots. -- La estructura separa captura, normalización y snapshot de forma razonable para la fase actual. -- La documentación backend refleja el nuevo estado. -- El resultado prepara el terreno para una siguiente task de persistencia real o ejecución periódica. - -## Change Budget -- Preferir menos de 6 archivos modificados o creados. -- Preferir menos de 240 líneas cambiadas. diff --git a/ai/tasks/done/TASK-021-server-status-periodic-query-and-display.md b/ai/tasks/done/TASK-021-server-status-periodic-query-and-display.md deleted file mode 100644 index 27ccaef..0000000 --- a/ai/tasks/done/TASK-021-server-status-periodic-query-and-display.md +++ /dev/null @@ -1,96 +0,0 @@ -# TASK-021-server-status-periodic-query-and-display - -## Goal -Implementar una base funcional para consultar periódicamente el estado de los servidores y mostrar esos datos en la página, realizando snapshots de datos cada 2 minutos, sin usar capturas de imagen ni elementos manuales equivalentes. - -## Context -Queda descartada cualquier idea de “captura manual” o de imagen estática para representar el estado de los servidores. Lo que se necesita es mostrar en la web la situación actual de los servidores mediante consultas de datos reales o semirrealistas desde backend. En esta fase, la web debe evolucionar hacia un modelo donde el backend consulta periódicamente la información de servidores, conserva el último snapshot útil y el frontend lo muestra de forma clara. - -## Steps -1. Revisar el endpoint actual `GET /api/servers` y su implementación placeholder. -2. Revisar cómo se muestra actualmente el bloque de servidores en la landing. -3. Diseñar e implementar una base de consulta periódica de datos de servidores con una frecuencia objetivo de 2 minutos. -4. Hacer que el backend obtenga y conserve snapshots de datos con los campos necesarios para la UI. Incluir al menos: - - nombre del servidor - - estado online/offline - - jugadores actuales - - capacidad máxima - - mapa actual si está disponible - - región o etiqueta útil si existe - - timestamp real del último snapshot de datos -5. Dejar claro en la implementación y en la UI que se trata de datos de estado de servidores, no de capturas de imagen. -6. Hacer que `GET /api/servers` devuelva el último snapshot útil con una estructura estable y preparada para frontend. -7. Ajustar el frontend para mostrar esos datos de forma clara en la landing. -8. Si el backend no puede obtener datos nuevos temporalmente, mantener el último snapshot válido o un fallback coherente sin romper la página. -9. Mostrar en la UI una referencia honesta del momento de actualización basada en datos reales del snapshot, no en texto ficticio. -10. Mantener el alcance razonable: consultas periódicas y presentación de datos, sin abrir todavía automatizaciones más complejas de observabilidad o infraestructura. - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- ai/architecture-index.md -- docs/frontend-backend-contract.md -- docs/discord-and-server-data-plan.md -- docs/current-hll-servers-source-plan.md -- backend/README.md -- backend/app/__init__.py -- backend/app/main.py -- backend/app/routes.py -- backend/app/payloads.py -- backend/app/config.py -- frontend/index.html -- frontend/assets/js/main.js -- frontend/assets/css/styles.css - -## Expected Files to Modify -- backend/app/main.py -- backend/app/routes.py -- backend/app/payloads.py -- backend/app/config.py -- opcionalmente uno o más archivos nuevos de servicio dentro de `backend/app/`, por ejemplo: - - backend/app/server_status_service.py - - backend/app/server_queries.py -- frontend/index.html -- frontend/assets/js/main.js -- frontend/assets/css/styles.css -- backend/README.md -- opcionalmente documentación técnica si fuera necesario alinear el comportamiento real - -## Constraints -- No usar capturas de imagen para representar el estado de servidores. -- No introducir texto temporal ficticio. -- No consultar fuentes externas directamente desde frontend. -- Mantener la arquitectura frontend → backend → fuente de datos. -- No romper el fallback actual si no hay datos disponibles. -- No hacer cambios destructivos. -- Mantener la solución clara, trazable y coherente con la fase del proyecto. - -## Validation -- Existe una base de consulta periódica con objetivo de refresco cada 2 minutos. -- `GET /api/servers` devuelve un snapshot de datos de servidores con timestamp real del snapshot. -- La landing muestra esos datos en lugar de una “captura” manual o ficticia. -- Si falla la actualización, la web no se rompe. -- La UI muestra de forma honesta la actualización real del estado de servidores. -- No se introducen capturas de imagen como solución del problema. - -## Change Budget -- Preferir menos de 8 archivos modificados o creados. -- Preferir menos de 320 líneas cambiadas. - -## Outcome -- `backend/app/payloads.py` hace que `GET /api/servers` devuelva un snapshot coherente preparado para frontend: prioriza el ultimo snapshot A2S real persistido cuando existe y, si no existe ninguno, responde un respaldo controlado con `last_snapshot_at`. -- `backend/app/config.py` alinea la frecuencia objetivo de refresco local a `120` segundos. -- `frontend/assets/js/main.js` deja de depender de una segunda llamada a `/api/servers/latest` para el bloque principal y pinta directamente el snapshot devuelto por `/api/servers`, mostrando un estado honesto con timestamp real del snapshot. -- `frontend/index.html` ajusta el polling por defecto a `120000` ms y aclara que el bloque muestra snapshots de estado consultados desde backend. -- `backend/README.md` documenta el nuevo comportamiento de `/api/servers` y el intervalo de `120` segundos. - -## Validation Result -- Validado con `python -m py_compile backend/app/config.py backend/app/payloads.py backend/app/routes.py backend/app/main.py`. -- Validado con `node --check frontend/assets/js/main.js`. -- Validado con `python -m app.collector --source controlled`, que persistio un snapshot controlado en `backend/data/hll_vietnam_dev.sqlite3`. -- Validado inspeccionando `build_servers_payload()` desde Python para confirmar que `/api/servers` devuelve `last_snapshot_at` e `items` listos para frontend. -- Revisado en diff: la task queda limitada a `backend/README.md`, `backend/app/config.py`, `backend/app/payloads.py`, `frontend/assets/js/main.js`, `frontend/index.html`, este archivo de task y la actualizacion de `backend/data/hll_vietnam_dev.sqlite3` causada por la validacion persistente. - -## Decision Notes -- Se reutilizo la infraestructura de snapshots ya existente en lugar de introducir otro scheduler o un segundo endpoint principal para el estado visible en landing. -- `/api/servers` devuelve un unico conjunto coherente de items para evitar mezclar timestamps de fallback con tarjetas reales A2S en la UI. diff --git a/ai/tasks/done/TASK-021-snapshot-persistence-bootstrap.md b/ai/tasks/done/TASK-021-snapshot-persistence-bootstrap.md deleted file mode 100644 index ce401a3..0000000 --- a/ai/tasks/done/TASK-021-snapshot-persistence-bootstrap.md +++ /dev/null @@ -1,73 +0,0 @@ -# TASK-021-snapshot-persistence-bootstrap - -## Goal -Preparar una persistencia local minima para snapshots de servidores en el backend Python, de forma que los datos recogidos durante las pruebas con HLL actual puedan guardarse y reutilizarse para consultas historicas posteriores. - -## Context -El proyecto ya dispone de plan de ingesta, modelo logico de almacenamiento y bootstrap de colector. El siguiente paso es dejar de depender exclusivamente de estructuras temporales o payloads controlados y empezar a guardar snapshots de forma persistente para validar el circuito real de estadisticas. - -## Steps -1. Revisar la documentacion actual de ingesta, esquema logico y colector. -2. Definir una estrategia de persistencia local minima adecuada para esta fase de pruebas. -3. Implementar una capa pequena de persistencia alineada con las entidades ya definidas logicamente: - - game_sources - - servers - - server_snapshots -4. Mantener la implementacion simple, reutilizable y desacoplada de una base de datos de produccion futura. -5. Hacer que el colector pueda guardar snapshots reales o controlados en esa persistencia local. -6. Documentar como inicializar y usar esta persistencia en desarrollo. -7. No introducir todavia consultas historicas complejas ni visualizacion en frontend. -8. Mantener el alcance centrado en almacenamiento basico funcional. - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- ai/architecture-index.md -- docs/current-hll-data-ingestion-plan.md -- docs/stats-database-schema-foundation.md -- backend/README.md -- backend/app/__init__.py -- backend/app/config.py -- backend/app/collector.py -- backend/app/normalizers.py -- backend/app/snapshots.py - -## Expected Files to Modify -- backend/README.md -- backend/app/__init__.py -- backend/app/config.py -- backend/app/collector.py -- backend/app/snapshots.py -- opcionalmente archivos nuevos dentro de backend/app/ si mejoran la separacion de persistencia, por ejemplo: - - backend/app/storage.py - - backend/app/repository.py - -## Constraints -- No implementar todavia integraciones reales complejas de terceros. -- No tocar frontend. -- No anadir una infraestructura de produccion sobredimensionada. -- No hacer cambios destructivos. -- Mantener la persistencia simple y util para desarrollo local. - -## Validation -- El backend puede guardar snapshots de servidores en una persistencia local real. -- La persistencia sigue el modelo logico documentado. -- La documentacion explica como usar esta base minima en local. -- El resultado prepara el terreno para consultas historicas inmediatas. - -## Change Budget -- Preferir menos de 7 archivos modificados o creados. -- Preferir menos de 260 lineas cambiadas. - -## Outcome -- Se anadio `backend/app/storage.py` con una persistencia SQLite minima basada en libreria estandar. -- El colector puede persistir snapshots controlados en `game_sources`, `servers` y `server_snapshots`. -- La configuracion local expone `HLL_BACKEND_STORAGE_PATH` para cambiar la ruta del archivo SQLite sin fijar una decision de produccion. -- `backend/README.md` documenta la inicializacion y uso de la persistencia local. - -## Validation Result -- Ejecutado: `python -m app.collector` -- Resultado: lote de 3 snapshots persistido correctamente en SQLite local de desarrollo. - -## Decision Notes -- Se eligio SQLite porque cubre persistencia local real con dependencias cero y mantiene abierta la migracion futura a otra tecnologia de almacenamiento. diff --git a/ai/tasks/done/TASK-022-historical-server-query-api.md b/ai/tasks/done/TASK-022-historical-server-query-api.md deleted file mode 100644 index 1f8a543..0000000 --- a/ai/tasks/done/TASK-022-historical-server-query-api.md +++ /dev/null @@ -1,77 +0,0 @@ -# TASK-022-historical-server-query-api - -## Goal -Exponer desde el backend una primera API de consulta historica para snapshots de servidores, permitiendo recuperar el ultimo estado conocido y una evolucion basica a partir de la persistencia local ya preparada. - -## Context -Una vez que los snapshots puedan guardarse, el siguiente paso es poder consultarlos de forma estructurada. Esta task debe convertir la persistencia inicial en una API util para comprobar que el flujo de estadisticas ya funciona extremo a extremo. - -## Steps -1. Revisar la capa de persistencia de snapshots y el backend actual. -2. Definir endpoints minimos de consulta historica, por ejemplo: - - `GET /api/servers/latest` - - `GET /api/servers/history` - - `GET /api/servers/{id}/history` -3. Alinear el formato de respuesta con las convenciones del backend existente. -4. Hacer que las respuestas devuelvan como minimo: - - timestamps - - ultimo estado conocido - - jugadores - - capacidad - - mapa si esta disponible - - contexto o fuente si aplica -5. Mantener la implementacion simple y enfocada a validacion tecnica. -6. Actualizar la documentacion del backend y del contrato si fuera necesario. -7. No introducir todavia analitica avanzada ni agregaciones pesadas. - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- ai/architecture-index.md -- docs/frontend-backend-contract.md -- docs/current-hll-data-ingestion-plan.md -- docs/stats-database-schema-foundation.md -- backend/README.md -- backend/app/main.py -- backend/app/routes.py -- backend/app/payloads.py -- backend/app/collector.py -- backend/app/snapshots.py -- archivos de persistencia creados en la task anterior - -## Expected Files to Modify -- backend/app/main.py -- backend/app/routes.py -- backend/app/payloads.py -- backend/README.md -- opcionalmente documentacion tecnica contractual si requiere alineacion menor - -## Constraints -- No tocar frontend en esta task. -- No anadir visualizacion nueva. -- No introducir complejidad innecesaria. -- No hacer cambios destructivos. -- Mantener la API clara, estable y centrada en historico basico. - -## Validation -- Existen endpoints historicos minimos funcionales. -- El backend puede devolver ultimo snapshot y una historia basica de snapshots. -- La documentacion refleja correctamente el nuevo estado. -- El resultado prepara el terreno para una primera visualizacion en frontend. - -## Change Budget -- Preferir menos de 6 archivos modificados o creados. -- Preferir menos de 240 lineas cambiadas. - -## Outcome -- Se anadieron lecturas minimas desde SQLite para ultimo snapshot por servidor, historial agregado e historial por servidor. -- `backend/app/routes.py` resuelve `GET /api/servers/latest`, `GET /api/servers/history` y `GET /api/servers/{id}/history`. -- `backend/app/payloads.py` mantiene el formato JSON del backend y devuelve errores controlados para parametros invalidos. -- `backend/README.md` y `docs/frontend-backend-contract.md` documentan los nuevos endpoints. - -## Validation Result -- Ejecutado: `python -c "from app.collector import collect_server_snapshots; from app.routes import resolve_get_payload; collect_server_snapshots(persist=True); ..."` -- Resultado: los tres endpoints historicos devolvieron datos persistidos y `limit=999` respondio con `status: "error"`. - -## Decision Notes -- Se mantuvo la API sobre la persistencia SQLite local ya existente, evitando una capa analitica separada hasta que el frontend necesite algo mas que consultas historicas basicas. diff --git a/ai/tasks/done/TASK-022-real-time-server-snapshot-refresh.md b/ai/tasks/done/TASK-022-real-time-server-snapshot-refresh.md deleted file mode 100644 index 582dc98..0000000 --- a/ai/tasks/done/TASK-022-real-time-server-snapshot-refresh.md +++ /dev/null @@ -1,102 +0,0 @@ -# TASK-022-real-time-server-snapshot-refresh - -## Goal -Hacer que `GET /api/servers` devuelva datos realmente actuales de los 2 servidores de la comunidad, refrescando el snapshot cuando el último estado persistido esté vencido respecto al objetivo de 120 segundos. - -## Context -La implementación actual ya tiene snapshots persistidos y polling desde frontend, pero el backend está sirviendo datos antiguos desde almacenamiento local (`local-snapshot-storage`) incluso cuando el snapshot tiene varias horas de antigüedad. Eso rompe el objetivo de mostrar la situación actual de los servidores. El frontend no debe depender de un snapshot viejo si el backend puede consultar el estado real de los servidores en ese momento. - -## Steps -1. Revisar la implementación actual de: - - `GET /api/servers` - - carga de snapshots persistidos - - lógica de refresco objetivo a 120 s - - consulta real A2S o equivalente que ya exista en el backend -2. Identificar por qué el backend está devolviendo snapshots antiguos sin forzar actualización. -3. Ajustar la lógica para que: - - si el snapshot actual tiene menos de 120 s, pueda reutilizarse - - si el snapshot actual supera 120 s, el backend intente una consulta real inmediata de los 2 servidores antes de responder -4. Si la consulta real tiene éxito: - - persistir el nuevo snapshot - - devolver ese snapshot fresco al frontend -5. Si la consulta real falla: - - devolver el último snapshot válido disponible - - marcar claramente en el payload que el dato es stale o desactualizado -6. Asegurar que el payload de `/api/servers` incluya campos claros para frontend, como por ejemplo: - - `last_snapshot_at` - - indicador de stale/fresh - - edad del snapshot en segundos o minutos - - origen real del dato devuelto -7. Ajustar el frontend solo si hace falta para que: - - no presente como “actual” un snapshot viejo - - pueda mostrar una nota honesta si el dato está desactualizado -8. Mantener el alcance centrado en datos actuales de los 2 servidores reales de la comunidad. -9. No reintroducir servidores ficticios o de referencia ajenos a la comunidad. -10. Al completar la implementación, dejar el repositorio en estado consistente y preparado para integración. -11. Hacer commit de los cambios realizados y hacer push al repositorio remoto siguiendo el workflow del proyecto, siempre que el entorno tenga permisos y configuración git disponibles. - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- ai/architecture-index.md -- docs/frontend-backend-contract.md -- docs/current-hll-servers-source-plan.md -- backend/README.md -- backend/app/__init__.py -- backend/app/main.py -- backend/app/routes.py -- backend/app/payloads.py -- backend/app/config.py -- cualquier servicio o módulo de collector/query ya existente en `backend/app/` -- frontend/index.html -- frontend/assets/js/main.js -- frontend/assets/css/styles.css - -## Expected Files to Modify -- backend/app/routes.py -- backend/app/payloads.py -- backend/app/config.py -- backend/app/main.py -- opcionalmente uno o más archivos de servicio existentes del backend si ahí vive la lógica de snapshots o de consulta real -- frontend/assets/js/main.js -- opcionalmente frontend/index.html y frontend/assets/css/styles.css si hace falta ajustar el estado visual stale/fresh -- backend/README.md si el comportamiento operativo cambia - -## Constraints -- No reintroducir servidores ficticios. -- No usar datos viejos como si fueran datos actuales. -- No consultar fuentes externas directamente desde frontend. -- Mantener la arquitectura frontend → backend → consulta real/persistencia. -- No romper el fallback si la consulta real falla. -- No hacer cambios destructivos. -- Mantener la solución centrada en los 2 servidores reales de la comunidad. -- Si el entorno no permite push, dejar el commit local realizado e informar claramente de ello en el resumen final. - -## Validation -- Si el snapshot persistido tiene más de 120 s, `/api/servers` intenta refrescarlo antes de responder. -- Si la consulta real tiene éxito, el frontend recibe datos actuales de los 2 servidores reales. -- Si la consulta real falla, el backend devuelve el último snapshot válido con una indicación clara de dato stale. -- La UI no presenta como actual un snapshot antiguo. -- No aparecen servidores ajenos a la comunidad. -- Los cambios quedan committeados y se hace push al remoto si el entorno lo permite. - -## Change Budget -- Preferir menos de 8 archivos modificados o creados. -- Preferir menos de 320 líneas cambiadas. -## Outcome -- `backend/app/payloads.py` deja de servir `/api/servers` como simple lectura del ultimo snapshot persistido: ahora reutiliza cache solo si sigue dentro del objetivo de `120` segundos y, si no, intenta un refresco A2S inmediato antes de responder. -- El payload principal de `/api/servers` ahora expone `last_snapshot_at`, `snapshot_age_seconds`, `snapshot_age_minutes`, `max_snapshot_age_seconds`, `is_stale`, `freshness`, `source`, `refresh_attempted`, `refresh_status` y `refresh_errors`. -- Si el refresco real falla, backend devuelve el ultimo snapshot valido con marca clara de dato stale; si no existe snapshot valido, responde `items: []` en vez de reintroducir servidores ficticios o de referencia. -- `frontend/assets/js/main.js` usa la metadata de frescura del backend para no presentar un snapshot viejo como si fuera actual y muestra una nota honesta cuando el dato esta desactualizado. -- `backend/README.md` y `docs/frontend-backend-contract.md` quedan alineados con el comportamiento real del endpoint. - -## Validation Result -- Validado con `python -m py_compile backend/app/config.py backend/app/payloads.py backend/app/routes.py backend/app/main.py`. -- Validado con `node --check frontend/assets/js/main.js`. -- Validado con una comprobacion local desde Python que cubre tres rutas de `build_servers_payload()`: refresco real exitoso, fallo de refresco con fallback stale al ultimo snapshot valido y ausencia total de snapshot valido. -- Validado ejecutando `build_servers_payload()` contra el entorno actual: el backend devolvio `source: "real-time-a2s-refresh"`, `freshness: "fresh"` e `item_count: 2`. -- Revisado en `git diff --name-only`: el alcance queda limitado a la task, documentacion del contrato/backend, frontend del panel de servidores y backend de payload/config, ademas de archivos ya presentes en el worktree (`ai/worker.lock` y `backend/data/hll_vietnam_dev.sqlite3`). - -## Decision Notes -- `/api/servers` se mantiene como endpoint principal para la landing y pasa a tratar la persistencia local como cache, no como fuente autoritativa cuando el snapshot ya vencio. -- Se elimina el uso de respaldo controlado en este endpoint cuando no hay snapshot valido disponible para cumplir la restriccion de no reintroducir servidores ajenos a la comunidad. diff --git a/ai/tasks/done/TASK-023-server-panel-ux-fixes-and-hero-cleanup.md b/ai/tasks/done/TASK-023-server-panel-ux-fixes-and-hero-cleanup.md deleted file mode 100644 index a246d4a..0000000 --- a/ai/tasks/done/TASK-023-server-panel-ux-fixes-and-hero-cleanup.md +++ /dev/null @@ -1,101 +0,0 @@ -# TASK-023-server-panel-ux-fixes-and-hero-cleanup - -## Goal -Corregir la UX del bloque de servidores y limpiar elementos visuales del hero de la landing, eliminando mensajes innecesarios, arreglando el CTA roto de conexion y dejando visible una referencia honesta de actualizacion del snapshot. - -## Context -La landing ya muestra datos actuales de los 2 servidores reales de la comunidad, pero todavia hay varios problemas de UX y acabado: -- aparece un texto largo e innecesario bajo el titulo del bloque de servidores indicando que el backend no pudo refrescar y que muestra el ultimo snapshot valido -- el boton `Conectar` no funciona correctamente y muestra errores de conexion como los observados en Steam -- el badge superior derecho del bloque de servidores debe pasar a mostrar una referencia limpia tipo `Actualizado ...` con el momento real correspondiente -- en el hero deben eliminarse los pills `BACKEND OPERATIVO` y `COMUNIDAD TACTICA HISPANA` - -La tarea debe dejar la UI mas limpia, mas honesta y sin CTAs rotos. - -## Steps -1. Revisar la implementacion actual del bloque de servidores en frontend y el payload real de `/api/servers`. -2. Eliminar del bloque de servidores el texto: - - `El backend no pudo refrescar ahora mismo y muestra el ultimo snapshot valido.` - - `Captura: ...` - o cualquier variante equivalente que recargue innecesariamente la UI. -3. Mantener la referencia temporal del snapshot unicamente en el badge superior derecho del bloque, sustituyendo el texto actual por un formato limpio tipo: - - `Actualizado 20/3/26, 19:37` - o equivalente coherente con el estilo visual actual. -4. Asegurar que el momento mostrado en ese badge viene de datos reales del snapshot/backend y no de texto ficticio. -5. Revisar la implementacion del boton `Conectar` de cada servidor. -6. Investigar por que el CTA actual produce el error observado y corregirlo si existe una forma fiable de conexion directa compatible con el flujo actual del proyecto. -7. Si la conexion directa no puede garantizarse de forma robusta con el comportamiento actual del juego/cliente, no dejar un boton roto: - - sustituirlo por una accion segura y util - - priorizar una UX que siempre funcione, por ejemplo `Copiar IP`, `Copiar direccion` o una variante equivalente basada en los datos reales del servidor - - si se conserva una accion de conexion, debe quedar realmente funcional -8. Mantener el comportamiento de los 2 servidores reales de la comunidad y no reintroducir servidores ficticios. -9. En el hero, eliminar visualmente: - - `BACKEND OPERATIVO` - - `COMUNIDAD TACTICA HISPANA` -10. Mantener intactos: - - logo - - CTA principal de Discord - - trailer - - estructura general de la landing -11. Asegurar que los cambios funcionan tanto en la UI estatica como en la UI hidratada por JS. -12. Al completar la implementacion: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- ai/architecture-index.md -- docs/frontend-backend-contract.md -- frontend/index.html -- frontend/assets/js/main.js -- frontend/assets/css/styles.css -- backend/app/payloads.py -- backend/app/routes.py -- backend/README.md - -## Expected Files to Modify -- frontend/index.html -- frontend/assets/js/main.js -- frontend/assets/css/styles.css -- opcionalmente backend/app/payloads.py si hace falta exponer mejor datos utiles para la UX del boton de servidor -- opcionalmente backend/README.md si cambia el comportamiento esperado del CTA de servidor - -## Constraints -- No volver a introducir mensajes largos y tecnicos en la UI principal del bloque de servidores. -- No dejar CTAs rotos o engañosos. -- No presentar datos no reales. -- No añadir librerias nuevas. -- No romper el polling ni la hidratacion actual del bloque. -- No romper el fallback actual. -- No hacer cambios destructivos. -- Mantener la solucion clara, visualmente limpia y coherente con la landing. - -## Validation -- Ya no aparece el texto largo bajo el titulo del bloque de servidores sobre fallo de refresh. -- El badge superior derecho muestra `Actualizado ...` con el momento real correspondiente al snapshot. -- El CTA de servidor deja de fallar: - - o conecta correctamente - - o se sustituye por una accion segura que si funciona -- Los 2 servidores reales de la comunidad siguen siendo los unicos mostrados. -- En el hero ya no aparecen `BACKEND OPERATIVO` ni `COMUNIDAD TACTICA HISPANA`. -- La landing mantiene coherencia visual y funcional. -- Los cambios quedan committeados y se hace push si el entorno lo permite. - -## Change Budget -- Preferir menos de 5 archivos modificados. -- Preferir menos de 220 lineas cambiadas. - -## Outcome -- `frontend/index.html` elimina los pills del hero, retira el texto secundario bajo el bloque de servidores y alinea el fallback estatico con los 2 servidores reales de Comunidad Hispana. -- `frontend/assets/js/main.js` deja la referencia temporal del snapshot solo en el badge superior derecho usando `last_snapshot_at` real del backend y sustituye la CTA rota `Conectar` por una accion segura de `Copiar IP`. -- `frontend/assets/css/styles.css` adapta las tarjetas al nuevo CTA, elimina estilos ya innecesarios del layout anterior y mantiene la presentacion limpia en desktop y movil. - -## Validation Result -- Validado con `node --check frontend/assets/js/main.js`. -- Verificado con busqueda en `frontend/` que ya no queda el texto largo del snapshot fallido ni `steam://connect`. -- Revisado con `git diff --name-only`: los cambios de esta task quedan limitados a `frontend/index.html`, `frontend/assets/js/main.js`, `frontend/assets/css/styles.css` y este archivo de task; permanecen sin tocar otros cambios locales ajenos. - -## Decision Notes -- La conexion directa por `steam://connect/:` se retira de la UI porque no podia garantizarse como CTA robusta en el flujo actual; se prioriza una accion segura y util basada en los datos reales del backend. diff --git a/ai/tasks/done/TASK-023-server-stats-preview-panel.md b/ai/tasks/done/TASK-023-server-stats-preview-panel.md deleted file mode 100644 index 1402e6c..0000000 --- a/ai/tasks/done/TASK-023-server-stats-preview-panel.md +++ /dev/null @@ -1,68 +0,0 @@ -# TASK-023-server-stats-preview-panel - -## Goal -Anadir a la web una primera visualizacion de estadisticas de servidores basada en datos persistidos, mostrando una vista previa util y controlada del historico sin convertir todavia la landing en una aplicacion compleja. - -## Context -La landing ya dispone de un panel provisional de servidores y el backend va a disponer de persistencia local y consultas historicas minimas. Esta task debe conectar ambos mundos con una primera visualizacion ligera que confirme que el pipeline completo funciona. - -## Steps -1. Revisar el frontend actual, el panel de servidores existente y el plan de consumo de datos. -2. Revisar los nuevos endpoints historicos del backend. -3. Disenar una mejora progresiva en frontend que pueda mostrar una vista previa de estadisticas sin romper la landing actual. -4. Mostrar como minimo algunos indicadores utiles, por ejemplo: - - ultimo snapshot por servidor - - hora de ultima actualizacion - - evolucion basica de poblacion o actividad reciente -5. Mantener fallback seguro si el backend o los endpoints historicos no estan disponibles. -6. Integrar visualmente el bloque con el diseno actual sin redisenar toda la pagina. -7. No anadir todavia dashboards complejos, graficas pesadas ni navegacion nueva. - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- docs/frontend-data-consumption-plan.md -- docs/frontend-backend-contract.md -- frontend/index.html -- frontend/assets/js/main.js -- frontend/assets/css/styles.css -- backend/app/routes.py -- backend/app/payloads.py -- documentacion de endpoints historicos creada en la task anterior - -## Expected Files to Modify -- frontend/index.html -- frontend/assets/js/main.js -- frontend/assets/css/styles.css -- opcionalmente documentacion minima si fuera necesario reflejar el nuevo bloque o comportamiento - -## Constraints -- No redisenar completamente la landing. -- No anadir librerias nuevas. -- No romper el fallback actual. -- No introducir analitica visual compleja. -- No hacer cambios destructivos. -- Mantener la mejora contenida, clara y alineada con la fase actual. - -## Validation -- La web puede mostrar una primera vista previa de estadisticas de servidores usando datos persistidos. -- El frontend sigue funcionando si el backend no esta disponible. -- La mejora visual se integra con la landing actual. -- El resultado demuestra que el flujo captura -> persistencia -> consulta -> visualizacion ya funciona. - -## Change Budget -- Preferir menos de 4 archivos modificados. -- Preferir menos de 220 lineas cambiadas. - -## Outcome -- El panel de servidores ahora puede mostrar una vista previa historica con resumen, ultima actualizacion y tendencia reciente por servidor. -- `frontend/assets/js/main.js` mantiene el bloque estatico como fallback y solo sustituye el contenido cuando los endpoints historicos responden correctamente. -- `frontend/index.html` anade un contenedor ligero para el resumen historico. -- `frontend/assets/css/styles.css` integra la nueva vista previa con el lenguaje visual tactico existente. - -## Validation Result -- Ejecutado: `node --check frontend/assets/js/main.js` -- Resultado: sintaxis valida en el script principal del frontend. - -## Decision Notes -- Se mantuvo la mejora dentro del panel de servidores ya existente para evitar una nueva seccion o un dashboard separado en esta fase. diff --git a/ai/tasks/done/TASK-024-a2s-client-bootstrap.md b/ai/tasks/done/TASK-024-a2s-client-bootstrap.md deleted file mode 100644 index 37231fb..0000000 --- a/ai/tasks/done/TASK-024-a2s-client-bootstrap.md +++ /dev/null @@ -1,77 +0,0 @@ -# TASK-024-a2s-client-bootstrap - -## Goal -Preparar un cliente A2S mínimo en el backend Python para consultar servidores de Hell Let Loose actual mediante query pública, obteniendo metadata básica reutilizable por el colector de snapshots. - -## Context -El proyecto ya dispone de colector bootstrap, persistencia local y consultas históricas mínimas. El siguiente paso es introducir una fuente real de datos en vivo. Hell Let Loose usa Steam A2S para metadata de servidor a través del query port, por lo que esta task debe preparar la base técnica para consultar servidores reales sin depender todavía de integraciones administrativas o scoreboards avanzados. - -## Steps -1. Revisar el backend actual, especialmente el colector y las funciones de normalización. -2. Revisar la documentación técnica de ingesta y el modelo de snapshots. -3. Preparar un cliente A2S mínimo capaz de consultar al menos la información equivalente a: - - nombre del servidor - - mapa actual - - jugadores actuales - - capacidad máxima -4. Mantener la implementación desacoplada para que futuras consultas de players o rules puedan añadirse después sin romper la base. -5. Normalizar la salida del cliente A2S hacia el modelo interno ya usado por el proyecto. -6. Asegurar que la implementación maneje fallos básicos de red o timeouts de forma controlada. -7. Actualizar la documentación backend para reflejar que existe una fuente A2S real de prueba. -8. Mantener el alcance centrado en bootstrap del cliente, no en pipeline completo. - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- ai/architecture-index.md -- docs/current-hll-data-ingestion-plan.md -- docs/stats-database-schema-foundation.md -- backend/README.md -- backend/app/__init__.py -- backend/app/config.py -- backend/app/collector.py -- backend/app/normalizers.py -- backend/app/snapshots.py -- backend/app/storage.py - -## Expected Files to Modify -- backend/README.md -- backend/app/__init__.py -- backend/app/normalizers.py -- backend/app/collector.py -- opcionalmente archivos nuevos dentro de backend/app/ si mejoran claridad, por ejemplo: - - backend/app/a2s_client.py - - backend/app/a2s_protocol.py - -## Constraints -- No implementar todavía scraping de terceros. -- No tocar frontend. -- No añadir base de datos nueva. -- No hacer cambios destructivos. -- Mantener la implementación pequeña, clara y orientada a desarrollo local. - -## Validation -- Existe un cliente A2S mínimo reutilizable desde el backend. -- El cliente puede obtener metadata básica de servidor. -- La salida se normaliza al modelo interno del proyecto. -- La documentación backend refleja el nuevo estado. - -## Change Budget -- Preferir menos de 6 archivos modificados o creados. -- Preferir menos de 260 líneas cambiadas. - -## Outcome -- Se anadio un cliente A2S minimo en `backend/app/a2s_client.py` usando solo libreria estandar para consultar `A2S_INFO`. -- `backend/app/normalizers.py` ahora puede convertir una respuesta A2S al modelo interno de snapshots ya usado por el proyecto. -- `backend/app/collector.py` expone `fetch_a2s_probe()` como adaptador pequeno reutilizable para la siguiente task de integracion del pipeline. -- `backend/app/__init__.py` mantiene acceso ligero a `query_server_info()` y `fetch_a2s_probe()` sin acoplar la carga del paquete al CLI del cliente. -- `backend/README.md` documenta el nuevo estado y una prueba manual local del cliente. - -## Validation Result -- Ejecutado: `python -m compileall backend/app` -- Resultado: compilacion correcta de los modulos del backend. -- Ejecutado: `python -m app.a2s_client --help` -- Resultado: CLI disponible sin warnings y con los argumentos esperados. - -## Decision Notes -- Se mantuvo la implementacion en libreria estandar con UDP directo para evitar introducir dependencias antes de validar targets y configuracion en las siguientes tasks. diff --git a/ai/tasks/done/TASK-024-remove-ip-ui-and-add-historic-links.md b/ai/tasks/done/TASK-024-remove-ip-ui-and-add-historic-links.md deleted file mode 100644 index 6ede130..0000000 --- a/ai/tasks/done/TASK-024-remove-ip-ui-and-add-historic-links.md +++ /dev/null @@ -1,95 +0,0 @@ -# TASK-024-remove-ip-ui-and-add-historic-links - -## Goal -Eliminar de la landing toda referencia visible a IP o direccion de servidor y sustituir el boton actual por un boton `Historico` que lleve a la pagina de historial correcta de cada uno de los 2 servidores reales de la comunidad. - -## Context -La UI actual del bloque de servidores sigue mostrando informacion relacionada con IP/direccion y un CTA heredado que ya no encaja con el comportamiento deseado. A partir de ahora no debe mostrarse nada relacionado con IP en la pagina. En su lugar, cada card de servidor debe incluir un boton `Historico` que abra la pagina de historial correspondiente al servidor real de la comunidad. - -Los destinos correctos son: -- Servidor `#01 [ESP] Comunidad Hispana - discord.comunidadhll.es - Spa Onl` -> `https://scoreboard.comunidadhll.es/games` -- Servidor `#02 [ESP] Comunidad Hispana - discord.comunidadhll.es - Spa Onl` -> `https://scoreboard.comunidadhll.es:5443/games` - -La solucion debe usar una asignacion estable basada en la identidad real de cada servidor de la comunidad y no depender de mostrar IP en la UI. - -## Steps -1. Revisar la implementacion actual del bloque de servidores en: - - HTML estatico/fallback - - renderizado hidratado desde JS - - payload y campos expuestos desde backend si afectan a la UI -2. Eliminar de la UI cualquier referencia visible a: - - IP - - direccion - - host:puerto - - textos como `Direccion` - - acciones tipo `Copiar IP` -3. Sustituir el CTA actual de cada card por un boton `Historico`. -4. Hacer que el boton `Historico` abra el destino correcto segun el servidor: - - servidor #01 -> `https://scoreboard.comunidadhll.es/games` - - servidor #02 -> `https://scoreboard.comunidadhll.es:5443/games` -5. Asegurar que la asignacion se basa en la identidad estable del servidor de comunidad y no en una logica fragil o dependiente del orden accidental. -6. Mantener la compatibilidad entre: - - fallback estatico - - renderizado dinamico por JS -7. Si la UI actual necesita un campo alternativo donde antes estaba la IP, reorganizar la card para que siga viendose equilibrada sin exponer datos de red. -8. Mantener visibles solo los 2 servidores reales de la comunidad. -9. No reintroducir servidores ficticios ni CTAs rotos. -10. Verificar que los enlaces abren correctamente las paginas de historico en una nueva pestana o de la forma UX mas segura/coherente con la landing. -11. Al completar la implementacion: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- ai/architecture-index.md -- frontend/index.html -- frontend/assets/js/main.js -- frontend/assets/css/styles.css -- backend/app/payloads.py -- backend/app/routes.py -- docs/frontend-backend-contract.md - -## Expected Files to Modify -- frontend/index.html -- frontend/assets/js/main.js -- frontend/assets/css/styles.css -- opcionalmente backend/app/payloads.py si hace falta exponer un identificador mas limpio para mapear cada servidor a su historico -- opcionalmente documentacion minima si cambia el comportamiento esperado del CTA del panel - -## Constraints -- No mostrar IP, direccion o datos equivalentes en la UI. -- No dejar botones rotos. -- No cambiar los 2 servidores reales de la comunidad. -- No anadir librerias nuevas. -- No romper el polling ni la hidratacion actual. -- No romper el fallback estatico. -- No hacer cambios destructivos. -- Mantener la solucion visualmente coherente con la landing. - -## Validation -- Ya no aparece ningun dato de IP/direccion en la UI del bloque de servidores. -- El boton `Copiar IP` desaparece por completo. -- Cada servidor muestra un boton `Historico`. -- El boton del servidor #01 abre `https://scoreboard.comunidadhll.es/games`. -- El boton del servidor #02 abre `https://scoreboard.comunidadhll.es:5443/games`. -- La asignacion es estable tanto en fallback estatico como en renderizado dinamico. -- Los cambios quedan committeados y se hace push si el entorno lo permite. - -## Change Budget -- Preferir menos de 5 archivos modificados. -- Preferir menos de 200 lineas cambiadas. - -## Outcome -- `frontend/index.html` elimina la IP visible del fallback estatico y sustituye el CTA por enlaces `Historico` hacia el scoreboard correcto de cada servidor real. -- `frontend/assets/js/main.js` deja de renderizar direccion o acciones de copiado y asigna cada enlace de historico mediante `external_server_id` estable. -- `frontend/assets/css/styles.css` adapta el estilo del CTA para mantener la tarjeta equilibrada sin exponer datos de red. - -## Validation Result -- Validado con `node --check frontend/assets/js/main.js`. -- Verificado con `rg` que ya no quedan en `frontend/` textos o atributos de `Copiar IP`, `Direccion`, `data-copy-address`, `server-copy-button` ni las IPs de los servidores. -- Revisado con `git diff --name-only`: el cambio de esta task queda acotado a `frontend/index.html`, `frontend/assets/js/main.js`, `frontend/assets/css/styles.css` y este archivo de task. - -## Decision Notes -- La asignacion del enlace `Historico` en renderizado dinamico se resuelve unicamente con `external_server_id` para evitar dependencia del orden accidental o de datos de red expuestos en UI. diff --git a/ai/tasks/done/TASK-025-a2s-source-configuration-and-target-registry.md b/ai/tasks/done/TASK-025-a2s-source-configuration-and-target-registry.md deleted file mode 100644 index 37d29eb..0000000 --- a/ai/tasks/done/TASK-025-a2s-source-configuration-and-target-registry.md +++ /dev/null @@ -1,67 +0,0 @@ -# TASK-025-a2s-source-configuration-and-target-registry - -## Goal -Definir y preparar una configuración limpia para registrar servidores objetivo de prueba consultables por A2S, de forma que el backend pueda trabajar con una lista controlada de targets sin acoplarse a valores hardcodeados. - -## Context -Una vez que exista un cliente A2S mínimo, el proyecto necesita una manera clara de declarar qué servidores de HLL actual se usarán como fuentes de prueba. Esta task debe dejar preparada una configuración o registro simple de targets A2S, reutilizable por el colector y fácil de adaptar en desarrollo. - -## Steps -1. Revisar la configuración actual del backend. -2. Definir una forma clara de registrar targets A2S de prueba, incluyendo al menos: - - nombre amigable - - host o IP - - query port - - contexto o etiqueta de fuente -3. Mantener el diseño desacoplado del resto del backend y fácil de ampliar. -4. Permitir que el colector lea esa configuración sin depender de valores hardcodeados dentro de la lógica principal. -5. Documentar cómo añadir, quitar o modificar servidores de prueba en entorno local. -6. Mantener el alcance en configuración y registro de targets, no en analítica avanzada. - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- docs/current-hll-data-ingestion-plan.md -- backend/README.md -- backend/app/config.py -- backend/app/collector.py -- backend/app/storage.py -- backend/app/a2s_client.py si ya existe por la task anterior - -## Expected Files to Modify -- backend/README.md -- backend/app/config.py -- backend/app/collector.py -- opcionalmente archivos nuevos dentro de backend/app/ si mejoran claridad, por ejemplo: - - backend/app/server_targets.py - -## Constraints -- No tocar frontend. -- No introducir infraestructura compleja. -- No añadir dependencias innecesarias. -- No hacer cambios destructivos. -- Mantener la configuración simple y orientada a pruebas. - -## Validation -- El backend dispone de una lista configurable de targets A2S. -- El colector puede leer esos targets sin depender de constantes dispersas. -- La documentación deja claro cómo configurar servidores de prueba. - -## Change Budget -- Preferir menos de 5 archivos modificados o creados. -- Preferir menos de 180 líneas cambiadas. - -## Outcome -- Se anadio `backend/app/server_targets.py` con un registro pequeno de targets A2S y una carga desacoplada en forma de dataclass. -- `backend/app/config.py` ahora soporta `HLL_BACKEND_A2S_TARGETS` para sobrescribir la lista con un array JSON en desarrollo local. -- `backend/app/collector.py` puede resolver los targets configurados mediante `fetch_configured_a2s_probes()` sin depender de valores hardcodeados en su logica principal. -- `backend/README.md` documenta la ubicacion del registro y como anadir, quitar o modificar targets de prueba. - -## Validation Result -- Ejecutado: `python -m compileall backend/app` -- Resultado: compilacion correcta de los modulos del backend. -- Ejecutado: `python -c "from app.server_targets import load_a2s_targets; print(load_a2s_targets())"` -- Resultado: el registro carga el target por defecto con la estructura esperada. - -## Decision Notes -- Se eligio JSON en variable de entorno para mantener el override simple, local y sin introducir un nuevo formato de configuracion ni dependencias externas. diff --git a/ai/tasks/done/TASK-025-repo-hygiene-and-dev-artifacts-cleanup.md b/ai/tasks/done/TASK-025-repo-hygiene-and-dev-artifacts-cleanup.md deleted file mode 100644 index 501af6b..0000000 --- a/ai/tasks/done/TASK-025-repo-hygiene-and-dev-artifacts-cleanup.md +++ /dev/null @@ -1,87 +0,0 @@ -# TASK-025-repo-hygiene-and-dev-artifacts-cleanup - -## Goal -Dejar el repositorio HLL Vietnam en un estado mas limpio y consistente eliminando o regularizando artefactos locales de desarrollo, ficheros de lock y residuos de workflow que no deberian quedar como ruido permanente en el worktree. - -## Context -Despues de varias tasks ejecutadas por el workflow, siguen apareciendo residuos locales o inconsistencias de higiene del repositorio, entre ellos: -- `ai/worker.lock` -- `backend/data/hll_vietnam_dev.sqlite3` -- `ai/tasks/done/TASK-021-server-status-periodic-query-and-display.md` como untracked o no regularizado -- posibles cambios locales en `backend/app/config.py` - -Estos elementos no forman parte directa del valor de producto visible, pero si afectan a la salud del repositorio, al flujo del worker y a la claridad del estado git. Hace falta una pasada de limpieza controlada para dejar reglas claras sobre que debe versionarse y que debe considerarse artefacto local de desarrollo. - -## Steps -1. Revisar el estado actual del repositorio y confirmar que archivos siguen quedando como ruido local o inconsistencias. -2. Analizar especificamente: - - `ai/worker.lock` - - `backend/data/hll_vietnam_dev.sqlite3` - - `ai/tasks/done/TASK-021-server-status-periodic-query-and-display.md` - - `backend/app/config.py` -3. Determinar para cada uno de ellos si debe: - - versionarse - - ignorarse - - regenerarse localmente - - moverse o regularizarse -4. Ajustar `.gitignore` u otros mecanismos de higiene si hace falta. -5. Asegurar que los artefactos locales de desarrollo no sigan ensuciando el worktree innecesariamente. -6. Regularizar el estado de la task `TASK-021` si quedo fuera del flujo esperado. -7. Documentar de forma minima, si hace falta, el tratamiento esperado de snapshots persistidos, locks locales y otros artefactos de runtime. -8. No tocar logica funcional de producto salvo que sea estrictamente necesario para dejar el repo coherente. -9. Al completar la implementacion: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- .gitignore -- ai/README.md -- ai/orchestrator/README.md -- backend/README.md -- backend/app/config.py -- cualquier documentacion existente sobre snapshots o runtime local -- salida actual de `git status` - -## Expected Files to Modify -- .gitignore -- backend/README.md -- opcionalmente ai/README.md o documentacion minima si hace falta aclarar el tratamiento de artefactos locales -- opcionalmente regularizacion de archivos en `ai/tasks/done/` -- opcionalmente eliminacion o exclusion de artefactos locales no deseados - -## Constraints -- No romper el workflow actual del proyecto. -- No eliminar informacion util sin justificarlo. -- No tocar frontend salvo que fuera completamente imprescindible. -- No introducir cambios funcionales de producto. -- No hacer cambios destructivos fuera del objetivo de higiene del repo. -- Mantener el resultado claro, pequeno y seguro. - -## Validation -- El worktree queda sensiblemente mas limpio. -- Los artefactos de desarrollo local quedan tratados de forma explicita. -- `ai/worker.lock` no queda como ruido permanente si no debe versionarse. -- El tratamiento de `backend/data/hll_vietnam_dev.sqlite3` queda resuelto. -- `TASK-021` queda regularizada si estaba fuera del flujo. -- Los cambios quedan committeados y se hace push al remoto si el entorno lo permite. - -## Change Budget -- Preferir menos de 6 archivos modificados. -- Preferir menos de 180 lineas cambiadas. - -## Outcome -- `.gitignore` pasa a tratar `ai/worker.lock` y `backend/data/*.sqlite3` como artefactos locales de runtime en lugar de ruido permanente versionado. -- `backend/data/.gitkeep` mantiene el directorio de datos en el repositorio sin forzar que la base SQLite de desarrollo quede commiteada. -- `ai/tasks/done/TASK-021-server-status-periodic-query-and-display.md` queda regularizada dentro del historial versionado de tasks completadas. -- El cambio pendiente de `backend/app/config.py` queda absorbido como parte de la regularizacion de `TASK-021`, en lugar de seguir apareciendo como residuo suelto. - -## Validation Result -- Revisado `git status --short` para confirmar que el ruido original del worktree quedaba centrado en `ai/worker.lock`, `backend/data/hll_vietnam_dev.sqlite3`, `backend/app/config.py` y la task `TASK-021`. -- Revisadas las referencias de runtime en `scripts/codex-runner.ps1`, `backend/app/config.py` y `backend/README.md` para confirmar que el lock y la SQLite son artefactos regenerables de desarrollo local. -- Validacion final prevista: `git diff --name-only` debe reflejar solo la higiene de ignores, la regularizacion de archivos versionados y la task cerrada. - -## Decision Notes -- `ai/worker.lock` se trata como lock efimero del runner local y no aporta valor historico en git. -- `backend/data/hll_vietnam_dev.sqlite3` se mantiene como persistencia local regenerable; el contrato util esta en codigo y documentacion, no en una base SQLite concreta del worktree. diff --git a/ai/tasks/done/TASK-026-a2s-backed-snapshot-collection.md b/ai/tasks/done/TASK-026-a2s-backed-snapshot-collection.md deleted file mode 100644 index db40163..0000000 --- a/ai/tasks/done/TASK-026-a2s-backed-snapshot-collection.md +++ /dev/null @@ -1,74 +0,0 @@ -# TASK-026-a2s-backed-snapshot-collection - -## Goal -Hacer que el colector de snapshots del backend pueda capturar datos reales desde servidores HLL consultables por A2S y persistir esos snapshots en la base local ya preparada. - -## Context -El proyecto ya tiene persistencia local, consultas históricas mínimas y un bootstrap de colector. Tras introducir un cliente A2S y una configuración de targets, el siguiente paso es cerrar el primer flujo real de captura y persistencia sobre servidores actuales de HLL. - -## Steps -1. Revisar el colector actual, la persistencia local y el cliente A2S. -2. Integrar el cliente A2S dentro del flujo de colecta de snapshots. -3. Hacer que el colector capture datos desde los targets configurados y los normalice al modelo interno. -4. Persistir los snapshots reales usando la capa de almacenamiento ya existente. -5. Manejar de forma controlada los casos de timeout, servidor inaccesible o respuesta inválida. -6. Mantener la posibilidad de usar datos controlados o fallback de desarrollo si la fuente real no responde. -7. Actualizar la documentación backend para explicar el flujo de captura real en esta fase. -8. Mantener el alcance centrado en captura y persistencia, no en nuevas visualizaciones. - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- ai/architecture-index.md -- docs/current-hll-data-ingestion-plan.md -- docs/stats-database-schema-foundation.md -- backend/README.md -- backend/app/__init__.py -- backend/app/config.py -- backend/app/collector.py -- backend/app/normalizers.py -- backend/app/snapshots.py -- backend/app/storage.py -- backend/app/a2s_client.py -- backend/app/server_targets.py si existe - -## Expected Files to Modify -- backend/README.md -- backend/app/collector.py -- backend/app/normalizers.py -- backend/app/storage.py -- opcionalmente archivos auxiliares nuevos si son estrictamente necesarios para mantener claridad - -## Constraints -- No tocar frontend en esta task. -- No introducir todavía estadísticas complejas. -- No añadir scraping de terceros. -- No hacer cambios destructivos. -- Mantener el pipeline claro, comprobable y pequeño. - -## Validation -- El colector puede capturar snapshots reales desde al menos un target A2S configurado. -- Los snapshots se persisten en la base local actual. -- Los errores de consulta quedan manejados de forma razonable. -- La documentación backend refleja cómo ejecutar esta captura en local. - -## Change Budget -- Preferir menos de 6 archivos modificados o creados. -- Preferir menos de 240 líneas cambiadas. - -## Outcome -- `backend/app/collector.py` ahora puede ejecutar captura en modo `a2s`, `controlled` o `auto`, persistiendo snapshots reales cuando las consultas A2S tienen exito. -- El colector registra errores por target sin abortar todo el lote y usa fallback controlado cuando no obtiene respuestas reales y el fallback esta habilitado. -- `backend/app/storage.py` persiste `source_name` por snapshot para conservar la procedencia efectiva de cada captura. -- `backend/README.md` documenta como ejecutar captura real, captura controlada y captura automatica con fallback en local. - -## Validation Result -- Ejecutado: `python -m compileall backend/app` -- Resultado: compilacion correcta de los modulos del backend. -- Ejecutado: validacion con `collect_server_snapshots(source_mode="a2s", persist=True, probe_target=stub_probe)` sobre SQLite temporal. -- Resultado: flujo A2S simulado persistio 1 snapshot y `list_snapshot_history()` devolvio 1 registro. -- Ejecutado: validacion con `collect_server_snapshots(source_mode="auto", timeout=0.1, persist=True)` usando el target local por defecto. -- Resultado: el colector registro 1 error de consulta, activo fallback controlado y persistio 3 snapshots de desarrollo. - -## Decision Notes -- Se mantuvo un fallback explicito de desarrollo para no romper el flujo local mientras los targets A2S reales siguen siendo configurables y potencialmente inestables. diff --git a/ai/tasks/done/TASK-026-landing-final-qa-pass.md b/ai/tasks/done/TASK-026-landing-final-qa-pass.md deleted file mode 100644 index 47dee3f..0000000 --- a/ai/tasks/done/TASK-026-landing-final-qa-pass.md +++ /dev/null @@ -1,97 +0,0 @@ -# TASK-026-landing-final-qa-pass - -## Goal -Realizar una pasada final de QA funcional y visual sobre la landing actual de HLL Vietnam para detectar y corregir pequenos defectos de presentacion, consistencia o comportamiento antes de pasar a una nueva linea de trabajo mas analitica e historica. - -## Context -La landing ya dispone de: -- hero estable -- CTA principal a Discord -- trailer -- panel de servidores con 2 servidores reales de la comunidad -- snapshots actuales con polling backend -- boton `Historico` funcional por servidor - -Antes de entrar en la siguiente fase del proyecto (estadisticas e historico), conviene hacer una revision final de calidad sobre la version actual para corregir detalles pequenos de UX, responsive, textos, alineacion visual y funcionamiento de enlaces. - -## Steps -1. Revisar la landing completa en su estado actual. -2. Validar el comportamiento y acabado de: - - hero - - CTA principal de Discord - - trailer - - panel de servidores - - badges de actualizacion - - botones `Historico` -3. Revisar posibles problemas pequenos como: - - textos cortados o saltos raros - - alineaciones inconsistentes - - spacing irregular - - badges o chips descompensados - - estados visuales poco claros - - fallback estatico vs UI hidratada con diferencias no deseadas -4. Revisar que los 2 botones `Historico` apunten correctamente a: - - `https://scoreboard.comunidadhll.es/games` - - `https://scoreboard.comunidadhll.es:5443/games` -5. Revisar que el badge de actualizacion use datos reales y no texto ficticio. -6. Revisar el comportamiento responsive basico de la landing. -7. Corregir unicamente defectos pequenos o medianos detectados en esta pasada. -8. No abrir redisenos grandes ni nuevos bloques funcionales. -9. Al completar la implementacion: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- frontend/index.html -- frontend/assets/css/styles.css -- frontend/assets/js/main.js -- backend/app/payloads.py -- backend/app/routes.py -- docs/frontend-backend-contract.md -- ai/repo-context.md - -## Expected Files to Modify -- frontend/index.html -- frontend/assets/css/styles.css -- frontend/assets/js/main.js -- opcionalmente documentacion minima si se detecta que algun comportamiento visible necesita quedar reflejado - -## Constraints -- No redisenar la landing completa. -- No cambiar la arquitectura backend actual. -- No introducir nuevas features grandes. -- No anadir librerias nuevas. -- No romper polling, snapshot o hidratacion actual. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en QA final y correcciones concretas. - -## Validation -- La landing queda mas consistente y pulida. -- No hay defects visibles relevantes en el flujo principal. -- Los 2 servidores correctos siguen mostrandose. -- Los enlaces de `Historico` funcionan correctamente. -- El badge de actualizacion sigue reflejando un dato real. -- Los cambios quedan committeados y se hace push si el entorno lo permite. - -## Change Budget -- Preferir menos de 4 archivos modificados. -- Preferir menos de 180 lineas cambiadas. - -## Outcome -- `frontend/index.html` alinea el polling visible de la landing con el backend a `120000` ms y aclara que el panel usa snapshots consultados desde backend. -- `frontend/assets/js/main.js` deja de insertar una segunda rejilla dentro de `#servers-list`, con lo que el fallback estatico y la UI hidratada comparten la misma estructura visual. -- El badge de actualizacion distingue snapshot fresco frente a snapshot stale usando el dato real `last_snapshot_at` y el flag `is_stale`. -- Se mantiene la ruta correcta de ambos botones `Historico` hacia los dos scoreboards de la comunidad. -- `frontend/assets/css/styles.css` corrige un detalle menor de consistencia en el bloque del CTA secundario de tarjetas. - -## Validation Result -- Validado con `node --check frontend/assets/js/main.js`. -- Verificadas en codigo las URLs `https://scoreboard.comunidadhll.es/games` y `https://scoreboard.comunidadhll.es:5443/games` tanto en el fallback HTML como en el mapeo dinamico de `SERVER_HISTORY_URLS`. -- Verificado en fuente que `data-server-refresh-ms="120000"` queda alineado con el intervalo por defecto documentado para snapshots. -- Revisado `git diff --name-only`: el alcance queda limitado a `frontend/index.html`, `frontend/assets/js/main.js`, `frontend/assets/css/styles.css` y este archivo de task. - -## Decision Notes -- La pasada de QA se limita a consistencia visual y semantica del estado visible; no abre nuevas features ni cambia el contrato backend. -- Para evitar otra divergencia entre fallback y estado hidratado, el contenedor `#servers-list` se mantiene como rejilla unica y la hidratacion solo reemplaza sus tarjetas internas. diff --git a/ai/tasks/done/TASK-027-a2s-history-visibility-polish.md b/ai/tasks/done/TASK-027-a2s-history-visibility-polish.md deleted file mode 100644 index e3cab0a..0000000 --- a/ai/tasks/done/TASK-027-a2s-history-visibility-polish.md +++ /dev/null @@ -1,61 +0,0 @@ -# TASK-027-a2s-history-visibility-polish - -## Goal -Ajustar la capa de visualización actual para que la web pueda distinguir de forma clara cuándo muestra datos históricos procedentes de snapshots A2S reales frente a placeholders o fallbacks estáticos. - -## Context -Una vez que la captura A2S real esté operativa, conviene hacer visible en frontend la procedencia efectiva de los datos sin convertir la landing en un dashboard complejo. Esta task debe mejorar la claridad del bloque actual de servidores y estadísticas sin rediseñarlo completamente. - -## Steps -1. Revisar el frontend actual y el bloque de estadísticas/servidores existente. -2. Revisar el formato real de los endpoints históricos tras la integración A2S. -3. Añadir una mejora visual o de estado que permita reflejar claramente si los datos mostrados son: - - snapshots reales recientes - - datos persistidos antiguos - - fallback estático -4. Mantener la mejora discreta y coherente con la landing actual. -5. No convertir la página en una aplicación compleja ni añadir navegación nueva. -6. Preservar el fallback si el backend no está disponible. - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- docs/frontend-data-consumption-plan.md -- frontend/index.html -- frontend/assets/js/main.js -- frontend/assets/css/styles.css -- backend/app/routes.py -- backend/app/payloads.py - -## Expected Files to Modify -- frontend/index.html -- frontend/assets/js/main.js -- frontend/assets/css/styles.css - -## Constraints -- No rediseñar toda la landing. -- No añadir librerías nuevas. -- No tocar backend salvo referencias documentales mínimas si hicieran falta. -- No hacer cambios destructivos. -- Mantener la mejora contenida y alineada con la fase actual. - -## Validation -- La web distingue visualmente entre datos reales A2S, históricos persistidos y fallback estático cuando aplique. -- La integración visual sigue siendo coherente con la landing. -- El frontend sigue funcionando si el backend no responde. - -## Change Budget -- Preferir menos de 4 archivos modificados. -- Preferir menos de 180 líneas cambiadas. - -## Outcome -- `frontend/index.html` incorpora un bloque pequeno de procedencia para explicar si el panel muestra fallback estatico, historico persistido o snapshots A2S recientes. -- `frontend/assets/js/main.js` clasifica el estado visible segun la procedencia y la antiguedad de los snapshots historicos sin romper el fallback actual. -- `frontend/assets/css/styles.css` integra esos estados con una presentacion tactica discreta dentro del panel existente de servidores. - -## Validation Result -- Ejecutado: `node --check frontend/assets/js/main.js` -- Resultado: sintaxis valida en el script principal del frontend. - -## Decision Notes -- La distincion entre `snapshots A2S recientes` y `historico persistido` se resuelve de forma ligera usando `source_name` y la antiguedad de `captured_at`, evitando cambios de contrato backend en esta fase. diff --git a/ai/tasks/done/TASK-027-historical-crcon-source-discovery.md b/ai/tasks/done/TASK-027-historical-crcon-source-discovery.md deleted file mode 100644 index c7fdc1b..0000000 --- a/ai/tasks/done/TASK-027-historical-crcon-source-discovery.md +++ /dev/null @@ -1,125 +0,0 @@ -# TASK-027-historical-crcon-source-discovery - -## Goal -Descubrir y documentar la fuente historica real mas estable para los 2 servidores de la comunidad, basada en CRCON/scoreboard, dejando claro como obtener datos historicos reutilizables para futuras estadisticas semanales y evitando depender de una implementacion previa ya descartada. - -## Context -El proyecto ya tiene resuelta la parte de estado actual de servidores mediante A2S para la landing. La siguiente fase es historico y estadisticas agregadas, por ejemplo "jugadores con mas kills de la ultima semana por servidor". - -Se parte de dos hechos importantes: -1. El historico NO debe construirse con A2S como fuente principal, porque A2S sirve para estado actual y no para historico retroactivo de partidas. -2. Cualquier intento previo de historico semanal basado directamente en la pagina de la comunidad debe considerarse deshecho, invalido o no reutilizable como base de arquitectura para esta nueva fase. - -Ademas, el analisis tecnico previo apunta a que la fuente correcta para historico debe venir de la capa CRCON/scoreboard publico de los servidores de la comunidad, o de la fuente estructurada que alimenta dicho scoreboard. - -## Goal Detail -Esta task NO debe implementar todavia la ingesta historica final ni endpoints de rankings. Su mision es descubrir con precision de donde salen los datos historicos, como se accede a ellos y cual es la estrategia tecnica mas estable para las siguientes tasks. - -## Steps -1. Revisar el estado actual del proyecto para confirmar que la parte historica previa basada directamente en la pagina comunitaria no debe tomarse como base valida. -2. Analizar las dos fuentes reales de historico asociadas a los servidores de la comunidad: - - `https://scoreboard.comunidadhll.es/games` - - `https://scoreboard.comunidadhll.es:5443/games` -3. Investigar como cargan los datos esas paginas: - - peticiones XHR/fetch - - posibles endpoints JSON - - paginacion - - URLs de detalle de partida - - identificadores de match - - identificadores o claves de jugador - - filtros o parametros relevantes -4. Determinar si la fuente utilizable mas estable es: - - una API/JSON expuesta por el scoreboard - - una estructura HTML parseable - - otra capa accesible derivada de CRCON -5. Documentar que datos historicos parecen estar realmente disponibles y estables. Incluir al menos: - - servidor - - partida - - fecha/hora - - mapa - - jugador - - kills - - otras metricas relevantes si aparecen -6. Documentar riesgos y limites: - - cambios de HTML - - dependencia de endpoints privados o fragiles - - ausencia de ids estables - - paginacion o limites de historico - - datos historicos posiblemente incompletos -7. Proponer la estrategia recomendada para las siguientes fases, distinguiendo claramente entre: - - fuente historica ideal - - plan operativo inicial realista - - fallback si no existe API estructurada -8. Dejar explicito que NO debe hacerse: - - no basar la arquitectura historica en A2S - - no asumir como valida una implementacion previa ya revertida - - no disenar todavia la UI historica -9. Actualizar la documentacion tecnica del repositorio con el resultado del discovery. -10. Al completar la implementacion: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- ai/architecture-index.md -- docs/decisions.md -- docs/current-hll-servers-source-plan.md -- docs/frontend-backend-contract.md -- backend/README.md -- cualquier documentacion o codigo existente relacionado con historico, scoreboard o CRCON -- cualquier rastro de implementacion historica previa que haya quedado en el repositorio, solo para confirmar su descarte - -## Expected Files to Modify -- ai/architecture-index.md -- docs/decisions.md -- opcionalmente backend/README.md si conviene reflejar el nuevo frente tecnico -- un nuevo documento tecnico, por ejemplo: - - `docs/historical-crcon-source-discovery.md` - -## Constraints -- No implementar todavia ingesta historica completa. -- No implementar todavia endpoints de rankings. -- No implementar todavia UI historica. -- No basar la arquitectura historica en A2S. -- No dar por buena ninguna implementacion historica previa que ya haya sido revertida o descartada. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en discovery tecnico y documentacion solida. - -## Validation -- Existe documentacion clara sobre la fuente historica real de los 2 servidores. -- Queda claro si la fuente reutilizable es JSON/API, HTML parseable u otra capa. -- Quedan identificados los datos historicos realmente disponibles. -- Quedan documentados riesgos, limites y estrategia recomendada. -- No se ha implementado todavia ingesta o UI prematura. -- Los cambios quedan committeados y se hace push si el entorno lo permite. - -## Change Budget -- Preferir menos de 5 archivos modificados o creados. -- Preferir menos de 220 lineas cambiadas. - -## Outcome -- Se documento que ambas URLs de scoreboard sirven una SPA y que la fuente historica reutilizable real es JSON bajo `baseURL: "/api"`. -- Se verificaron y documentaron los endpoints historicos observados: - - `GET /api/get_public_info` - - `GET /api/get_scoreboard_maps?page={page}&limit={limit}` - - `GET /api/get_map_scoreboard?map_id={map_id}` -- Se confirmo que `get_scoreboard_maps` aporta listado paginado de partidas y que `get_map_scoreboard` aporta detalle de partida con `player_stats` y metricas como `kills`, `deaths`, `teamkills`, `kills_per_minute`, `weapons`, `team.side` y `level`. -- Se dejo documentado que el HTML de `/games` no debe ser la base tecnica de ingesta y que A2S sigue limitado al estado actual. -- Se dejo constancia de que un intento previo de historico semanal no es base valida porque `backend/app/payloads.py` referencia `.historical_storage` pero ese modulo ya no existe. -- Se actualizo `docs/decisions.md` y `ai/architecture-index.md` para alinear la arquitectura con esta discovery. - -## Validation Result -- Ejecutado fuera del sandbox: inspeccion directa de `https://scoreboard.comunidadhll.es/games` y `https://scoreboard.comunidadhll.es:5443/games`. -- Resultado: ambas rutas devuelven la misma SPA shell con bundle `index-DvMfaBhO.js`. -- Ejecutado fuera del sandbox: extraccion del bundle frontend. -- Resultado: el helper HTTP usa `axios.create({ baseURL: "/api" })`. -- Ejecutado fuera del sandbox: `GET /api/get_public_info`, `GET /api/get_scoreboard_maps?page=1&limit=5` y `GET /api/get_map_scoreboard?map_id=...` en ambos scoreboards. -- Resultado: se confirmaron identificacion por servidor, paginacion, ids de partida y metricas historicas por jugador. -- Ejecutado localmente: revision de `backend/app/payloads.py` y busqueda de restos historicos con `rg`. -- Resultado: se detecto un rastro previo no reutilizable de `weekly_top_kills` apoyado en un modulo ausente. - -## Decision Notes -- La siguiente fase debe ingerir primero el listado de partidas por scoreboard y despues el detalle por `map_id`, manteniendo separados los dos origenes de la comunidad. -- El plan operativo inicial debe persistir partidos y estadisticas por jugador en backend propio para calcular agregados semanales sin consultar el scoreboard en cada request. diff --git a/ai/tasks/done/TASK-027-map-name-normalization-and-full-display.md b/ai/tasks/done/TASK-027-map-name-normalization-and-full-display.md deleted file mode 100644 index 35e892c..0000000 --- a/ai/tasks/done/TASK-027-map-name-normalization-and-full-display.md +++ /dev/null @@ -1,75 +0,0 @@ -# TASK-027-map-name-normalization-and-full-display - -## Goal -Corregir la visualización del nombre de mapa en el panel actual de servidores para que se muestre correctamente, normalizado y completo, sin cortes ni etiquetas degradadas. - -## Context -La landing ya muestra el estado actual de los 2 servidores reales de la comunidad, pero el campo de mapa presenta defectos visibles: nombres incompletos, abreviados de forma incorrecta o mal normalizados. Antes de avanzar con histórico y estadísticas, hay que dejar correcto este dato básico del estado actual. - -## Steps -1. Revisar el origen actual del nombre de mapa en backend y frontend. -2. Identificar si el problema viene de: - - dato crudo del query A2S - - normalización backend - - truncado o layout frontend -3. Corregir la cadena de transformación para que el nombre del mapa mostrado sea correcto y completo. -4. Aplicar una normalización coherente si el dato crudo usa nombres internos o variantes técnicas. -5. Asegurar que el frontend no corte el nombre de mapa de forma incorrecta. -6. Ajustar el layout si hace falta para que el mapa pueda verse entero dentro de la card. -7. Mantener los 2 servidores reales de la comunidad y no alterar el resto del flujo. -8. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- frontend/index.html -- frontend/assets/css/styles.css -- frontend/assets/js/main.js -- backend/app/payloads.py -- backend/app/routes.py -- cualquier módulo de normalización o consulta de servidor existente -- docs/frontend-backend-contract.md - -## Expected Files to Modify -- backend/app/payloads.py -- frontend/assets/js/main.js -- frontend/assets/css/styles.css -- opcionalmente frontend/index.html si el layout necesita un ajuste menor - -## Constraints -- No introducir servidores ficticios. -- No romper polling ni snapshot actual. -- No añadir librerías nuevas. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en exactitud del dato y presentación correcta del mapa. - -## Validation -- El nombre del mapa se muestra correctamente. -- El nombre del mapa se muestra completo. -- No aparecen abreviaturas degradadas o cortes visuales incorrectos. -- La landing mantiene su funcionamiento actual. -- Los cambios quedan committeados y se hace push si el entorno lo permite. - -## Change Budget -- Preferir menos de 4 archivos modificados. -- Preferir menos de 160 líneas cambiadas. - -## Outcome -- `backend/app/normalizers.py` incorpora una normalización pequeña de nombres de mapa para convertir alias técnicos o abreviados estables de HLL en nombres legibles para la landing. -- `backend/app/payloads.py` reaplica esa normalización al leer snapshots persistidos, de modo que también se corrigen datos ya capturados como `StMarie` o `DEV_Q`. -- `frontend/assets/js/main.js` marca el valor del quickfact de mapa con una clase dedicada. -- `frontend/assets/css/styles.css` ajusta el wrapping del nombre de mapa para evitar cortes visuales degradados dentro de la card. - -## Validation Result -- Ejecutado desde `backend/`: `python -` importando `build_servers_payload()`. -- Resultado: `comunidad-hispana-01 => Developer Test Map` y `comunidad-hispana-02 => Sainte-Marie-du-Mont` en el payload devuelto por `/api/servers`. -- Ejecutado desde raíz: `node --check frontend/assets/js/main.js`. -- Resultado: validación de sintaxis correcta para el script frontend. -- Revisado `git diff --name-only`. -- Resultado: el alcance queda limitado a `backend/app/normalizers.py`, `backend/app/payloads.py`, `frontend/assets/js/main.js` y `frontend/assets/css/styles.css`. - -## Decision Notes -- La corrección principal se aplica en backend para mantener un único punto de verdad entre snapshots nuevos y persistidos. -- El ajuste visual en frontend se limita al campo de mapa para no alterar el layout general de la landing. diff --git a/ai/tasks/done/TASK-028-historical-domain-model-and-storage-schema.md b/ai/tasks/done/TASK-028-historical-domain-model-and-storage-schema.md deleted file mode 100644 index 03896e8..0000000 --- a/ai/tasks/done/TASK-028-historical-domain-model-and-storage-schema.md +++ /dev/null @@ -1,102 +0,0 @@ -# TASK-028-historical-domain-model-and-storage-schema - -## Goal -Definir e implementar la base de modelo de dominio y almacenamiento para estadísticas históricas de los 2 servidores reales de la comunidad, preparada para ingerir datos desde la capa JSON pública del scoreboard CRCON y para soportar rankings semanales posteriores. - -## Context -La fase de discovery ya confirmó que la fuente histórica correcta para estos servidores no es A2S ni el HTML de `/games`, sino la capa JSON pública del scoreboard CRCON. El siguiente paso técnico es crear una base sólida de dominio y persistencia propia para poder ingerir datos históricos, deduplicarlos y consultarlos más adelante desde nuestra propia API. - -Esta task NO debe crear todavía páginas históricas en frontend ni depender de URLs públicas de la comunidad como solución de producto. La capa histórica debe vivir en backend, con persistencia propia y preparada para exponer endpoints internos del proyecto en fases posteriores. - -## Steps -1. Revisar la documentación de discovery histórica ya creada y confirmar qué datos están disponibles desde la capa JSON pública del scoreboard CRCON. -2. Definir el modelo de dominio histórico mínimo necesario. Incluir al menos: - - servidor - - partida - - mapa - - jugador - - estadísticas de jugador por partida - - ejecución de ingesta histórica -3. Diseñar el esquema de almacenamiento local inicial para esa información. -4. Definir claves e identidad estables para evitar duplicados. Incluir expresamente: - - identificación de partida - - identificación de servidor - - identificación de jugador - - estrategia de idempotencia -5. Incluir campos suficientes para soportar futuras consultas como: - - top kills de la última semana por servidor - - partidas recientes por servidor - - mapas jugados -6. Implementar la base de almacenamiento/esquema local de forma coherente con el backend actual del proyecto. -7. Mantener clara la separación entre: - - estado actual vía A2S - - histórico persistido vía CRCON scoreboard JSON -8. Documentar la estructura creada y cómo se usará en las siguientes tasks. -9. No implementar todavía: - - UI histórica - - páginas nuevas basadas en la URL de la comunidad - - redirecciones o vistas que repliquen la web de la comunidad - - rankings finales expuestos al frontend -10. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- ai/architecture-index.md -- docs/decisions.md -- docs/historical-crcon-source-discovery.md -- backend/README.md -- backend/app/config.py -- backend/app/routes.py -- backend/app/payloads.py -- cualquier almacenamiento local o capa de persistencia ya existente en `backend/` -- cualquier módulo collector o snapshot ya existente que pueda influir en la estructura de datos - -## Expected Files to Modify -- ai/architecture-index.md -- docs/decisions.md -- backend/README.md -- uno o más archivos nuevos de backend para almacenamiento histórico, por ejemplo: - - backend/app/historical_models.py - - backend/app/historical_storage.py - - backend/app/historical_schema.py -- opcionalmente un documento nuevo, por ejemplo: - - docs/historical-domain-model.md - -## Constraints -- No basar esta capa histórica en A2S. -- No crear páginas frontend nuevas usando la URL de la comunidad. -- No incrustar ni replicar directamente páginas de `scoreboard.comunidadhll.es`. -- No implementar todavía ingesta completa ni UI histórica. -- No romper el flujo actual de estado en tiempo real. -- No introducir complejidad innecesaria. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en dominio, persistencia e idempotencia. - -## Validation -- Existe un modelo de dominio histórico claro para los 2 servidores. -- Existe una base de almacenamiento/esquema local coherente con ese modelo. -- La estructura permite futuras consultas como top kills semanales por servidor. -- Queda clara la separación entre live status y histórico persistido. -- No se han creado páginas frontend nuevas ni soluciones basadas en URLs de la comunidad. -- Los cambios quedan committeados y se hace push al remoto si el entorno lo permite. - -## Change Budget -- Preferir menos de 7 archivos modificados o creados. -- Preferir menos de 260 líneas cambiadas. -## Outcome -- Se añadio `backend/app/historical_models.py` como capa minima de dominio para servidor, mapa, partida, jugador, estadisticas por partida y ejecucion de ingesta. -- Se implemento `backend/app/historical_storage.py` con tablas `historical_*` separadas del flujo live A2S, claves estables e `UPSERT` idempotente para partidas, jugadores y estadisticas por jugador. -- Se documento el modelo e identidad estable en `docs/historical-domain-model.md`, y se alinearon `docs/decisions.md`, `ai/architecture-index.md` y `backend/README.md`. -- La inicializacion de storage incluye migracion segura desde una version legacy ya existente en la base SQLite local, preservando los datos previos en la nueva estructura. - -## Validation Result -- Validado con `python -m compileall app` desde `backend/`. -- Validado con una comprobacion local de `initialize_historical_storage()`, `list_historical_servers()` y `list_recent_historical_matches(limit=3)`. -- Revisado `git diff --name-only` para confirmar que el cambio quedo centrado en `ai/`, `docs/`, `backend/` y archivos de task. - -## Decision Notes -- El historico CRCON comparte el mismo SQLite local de desarrollo que los snapshots A2S para no introducir infraestructura prematura, pero queda estrictamente separado por tablas `historical_*`. diff --git a/ai/tasks/done/TASK-028-real-a2s-target-onboarding.md b/ai/tasks/done/TASK-028-real-a2s-target-onboarding.md deleted file mode 100644 index fa8357a..0000000 --- a/ai/tasks/done/TASK-028-real-a2s-target-onboarding.md +++ /dev/null @@ -1,72 +0,0 @@ -# TASK-028-real-a2s-target-onboarding - -## Goal -Dar de alta el primer target A2S real verificado del proyecto, correspondiente a Comunidad Hispana #01, integrandolo en la configuracion del backend de forma clara, mantenible y documentada. - -## Context -El backend ya dispone de cliente A2S, registro configurable de targets y colector integrado con persistencia. Ademas, ya se ha identificado un target real consultable por A2S: -- Comunidad Hispana #01 -- Host/IP: 152.114.195.174 -- Query Port: 7778 -- Game Port: 7777 - -El objetivo de esta task es incorporar ese target real a la configuracion del proyecto sin asumir otros servidores aun no verificados. - -## Steps -1. Revisar la configuracion actual de targets A2S del backend. -2. Anadir el target real verificado de Comunidad Hispana #01 usando: - - nombre amigable claro - - host/IP: `152.114.195.174` - - query port: `7778` - - etiqueta o contexto de fuente coherente con el proyecto -3. Asegurar que la configuracion no dependa de valores hardcodeados dispersos fuera del registro o capa configurada. -4. Mantener separada la nocion de query port y game port para evitar confusiones. -5. Reflejar en la documentacion del backend como esta registrado este primer target real. -6. Dejar claro en documentacion que Comunidad Hispana #02 no debe anadirse aun sin confirmar su query port real. -7. Mantener el cambio pequeno y estrictamente centrado en onboarding de target. - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- ai/architecture-index.md -- backend/README.md -- backend/app/config.py -- backend/app/server_targets.py -- backend/app/collector.py -- backend/app/a2s_client.py - -## Expected Files to Modify -- backend/README.md -- backend/app/config.py -- backend/app/server_targets.py -- opcionalmente backend/app/collector.py si necesita alineacion menor para consumir el target de forma limpia - -## Constraints -- No tocar frontend. -- No introducir nuevos targets no verificados. -- No asumir datos de Comunidad Hispana #02. -- No anadir scraping. -- No hacer cambios destructivos. -- Mantener la configuracion simple y clara. - -## Validation -- El backend contiene el target real de Comunidad Hispana #01 correctamente registrado. -- El query port configurado es `7778`. -- La documentacion deja claro como esta definido este target. -- No se han introducido targets inciertos o ambiguos. - -## Change Budget -- Preferir menos de 4 archivos modificados. -- Preferir menos de 140 lineas cambiadas. - -## Outcome -- `backend/app/server_targets.py` registra por defecto solo `Comunidad Hispana #01` con `host` real, `query_port` verificado y `game_port` separado como dato opcional de referencia. -- `backend/app/config.py` centraliza el `source_name` por defecto para evitar valores dispersos en el registro A2S. -- `backend/README.md` documenta el target real incorporado y deja explicito que Comunidad Hispana #02 no debe anadirse hasta confirmar su `query_port`. - -## Validation Result -- Ejecutado desde `backend/`: `python -` importando `load_a2s_targets()`. -- Resultado: el registro carga `Comunidad Hispana #01` con `host=152.114.195.174`, `query_port=7778`, `game_port=7777` y `source_name=community-hispana-a2s`. - -## Decision Notes -- Se mantiene `game_port` fuera de la logica de consulta A2S y solo como metadato opcional del target para evitar confundirlo con `query_port`. diff --git a/ai/tasks/done/TASK-029-historical-crcon-ingestion-bootstrap.md b/ai/tasks/done/TASK-029-historical-crcon-ingestion-bootstrap.md deleted file mode 100644 index 21e9916..0000000 --- a/ai/tasks/done/TASK-029-historical-crcon-ingestion-bootstrap.md +++ /dev/null @@ -1,97 +0,0 @@ -# TASK-029-historical-crcon-ingestion-bootstrap - -## Goal -Implementar una ingesta histórica inicial desde la capa JSON pública del scoreboard CRCON para los 2 servidores reales de la comunidad, persistiendo datos estructurados e idempotentes en el almacenamiento histórico propio del proyecto. - -## Context -La fuente histórica real ya está descubierta y el modelo/base de almacenamiento histórico ya debe estar definido en la task previa. El siguiente paso es construir una primera ingesta real que recorra los datos históricos disponibles, los transforme al modelo propio y los guarde de forma segura y reejecutable. - -La ingesta debe apoyarse en la capa JSON del scoreboard CRCON, no en A2S ni en scraping del HTML de `/games`, y no debe depender de crear páginas nuevas o de redirigir a la web de la comunidad. - -## Steps -1. Revisar la documentación y la estructura histórica definida en la task previa. -2. Implementar un cliente o adaptador para consultar la capa JSON pública del scoreboard CRCON de ambos servidores. -3. Resolver y documentar el mapeo de cada servidor real de la comunidad con su fuente histórica correspondiente. -4. Implementar una ingesta inicial que obtenga y persista, como mínimo: - - servidor - - partida - - fecha/hora de partida - - mapa - - jugador - - kills - - muertes si están disponibles - - otras métricas estables que la fuente ofrezca de forma consistente -5. Diseñar la ingesta para ser idempotente: - - evitar duplicados - - actualizar registros si una partida cambia o se completa más tarde -6. Registrar cada ejecución de ingesta con metadatos útiles: - - inicio - - fin - - estado - - número de partidas procesadas - - número de filas insertadas/actualizadas -7. Documentar cómo lanzar la ingesta manualmente en local. -8. Mantener intacto el flujo actual de estado en tiempo real. -9. No implementar todavía endpoints finales de ranking ni UI histórica. -10. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- ai/architecture-index.md -- docs/historical-crcon-source-discovery.md -- docs/historical-domain-model.md -- backend/README.md -- backend/app/config.py -- backend/app/routes.py -- backend/app/payloads.py -- backend/app/historical_models.py -- backend/app/historical_storage.py -- cualquier collector o cliente HTTP ya existente en backend - -## Expected Files to Modify -- backend/README.md -- backend/app/config.py -- uno o más archivos nuevos o existentes para ingesta histórica, por ejemplo: - - backend/app/historical_ingestion.py - - backend/app/historical_crcon_client.py - - backend/app/historical_storage.py - - backend/app/historical_models.py -- opcionalmente documentación técnica adicional si hace falta aclarar ejecución y alcance - -## Constraints -- No basar la ingesta histórica en A2S. -- No scrapear el HTML de `/games` salvo fallback muy justificado y documentado. -- No crear páginas frontend nuevas usando la URL de la comunidad. -- No romper el flujo actual de live status. -- No introducir complejidad innecesaria. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en ingesta, persistencia e idempotencia. - -## Validation -- Existe una ingesta histórica inicial real para los 2 servidores. -- La ingesta persiste datos estructurados en almacenamiento propio. -- La ingesta puede reejecutarse sin duplicados graves. -- Queda documentado cómo ejecutarla localmente. -- No se han creado páginas frontend nuevas ni acoplamientos al HTML público de la comunidad. -- Los cambios quedan committeados y se hace push al remoto si el entorno lo permite. - -## Change Budget -- Preferir menos de 8 archivos modificados o creados. -- Preferir menos de 320 líneas cambiadas. -## Outcome -- Se implemento `backend/app/historical_ingestion.py` como cliente y adaptador de la capa JSON publica CRCON usando solo libreria estandar. -- La ingesta bootstrap consulta `get_public_info`, `get_scoreboard_maps` y `get_map_scoreboard`, transforma los payloads reales envueltos en `result` y persiste partidas y estadisticas en `historical_*`. -- Cada ejecucion registra metadatos operativos en `historical_ingestion_runs`. -- `backend/README.md` documenta como lanzar el bootstrap manualmente en local. - -## Validation Result -- Validado con `python -m compileall app`. -- Validado indirectamente con `python -m app.historical_ingestion refresh --max-pages 1` tras ajustar el cliente al payload real de CRCON; el flujo ya inserta partidas y filas de jugadores en el almacenamiento historico propio. -- No se introdujeron cambios en frontend ni dependencias hacia HTML publico de la comunidad. - -## Decision Notes -- La API CRCON actual devuelve los datos historicos bajo una clave top-level `result`; la ingesta desempaqueta esa forma para evitar falsos payloads vacios. diff --git a/ai/tasks/done/TASK-029-real-a2s-capture-validation.md b/ai/tasks/done/TASK-029-real-a2s-capture-validation.md deleted file mode 100644 index b4179d3..0000000 --- a/ai/tasks/done/TASK-029-real-a2s-capture-validation.md +++ /dev/null @@ -1,86 +0,0 @@ -# TASK-029-real-a2s-capture-validation - -## Goal -Validar una captura A2S real extremo a extremo contra Comunidad Hispana #01, confirmando que el colector puede consultar el servidor, normalizar la respuesta y persistir snapshots utiles en la base local. - -## Context -El proyecto ya tiene: -- cliente A2S -- targets configurables -- persistencia local -- endpoints historicos -- primer target real verificado para Comunidad Hispana #01 - -Ahora hay que comprobar que el flujo real funciona de verdad con ese servidor: -A2S -> colector -> persistencia local - -## Steps -1. Revisar el target real configurado para Comunidad Hispana #01. -2. Ejecutar el colector o flujo equivalente contra ese target real. -3. Confirmar que el backend consulta correctamente el host `152.114.195.174` con query port `7778`. -4. Validar que la respuesta A2S obtenida se normaliza al modelo interno del proyecto. -5. Persistir al menos un snapshot real en la base local actual. -6. Verificar que se registran de forma razonable: - - nombre del servidor - - timestamp de captura - - mapa actual si esta disponible - - jugadores actuales - - capacidad maxima - - procedencia efectiva del snapshot -7. Verificar el comportamiento si la consulta falla, timeout o devuelve datos parciales. -8. Actualizar la documentacion minima necesaria sobre como ejecutar esta validacion en local. -9. Mantener el alcance centrado en validacion del flujo real, no en nuevas features. - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- ai/architecture-index.md -- backend/README.md -- backend/app/a2s_client.py -- backend/app/server_targets.py -- backend/app/collector.py -- backend/app/normalizers.py -- backend/app/snapshots.py -- backend/app/storage.py - -## Expected Files to Modify -- backend/README.md -- backend/app/collector.py -- backend/app/normalizers.py -- backend/app/storage.py -- opcionalmente otros archivos backend si son estrictamente necesarios para una captura real robusta - -## Constraints -- No tocar frontend. -- No anadir analitica avanzada. -- No anadir scraping de terceros. -- No introducir complejidad innecesaria. -- No hacer cambios destructivos. -- Mantener la validacion centrada en Comunidad Hispana #01. - -## Validation -- Se realiza una captura real A2S sobre Comunidad Hispana #01. -- Se persiste al menos un snapshot real en la base local. -- El flujo real queda documentado y es repetible en local. -- Los errores de consulta estan razonablemente manejados. - -## Change Budget -- Preferir menos de 5 archivos modificados. -- Preferir menos de 180 lineas cambiadas. - -## Outcome -- `backend/README.md` documenta el comando exacto de validacion A2S real y el resultado esperado cuando `Comunidad Hispana #01` responde. -- No fue necesario cambiar `collector.py`, `normalizers.py` ni `storage.py` porque el flujo real ya normaliza y persiste correctamente. -- La validacion tambien dejo ver el comportamiento de error: en entorno sandbox con UDP restringido el colector devuelve timeout controlado y `success_count: 0`. - -## Validation Result -- Ejecutado en sandbox: `python -m app.collector --source a2s --no-fallback`. -- Resultado en sandbox: timeout controlado hacia `152.114.195.174:7778`, `success_count: 0`, sin snapshots reales persistidos. -- Ejecutado fuera del sandbox: `python -m app.collector --source a2s --no-fallback`. -- Resultado fuera del sandbox: `success_count: 1`, un snapshot persistido para `comunidad-hispana-01` en `backend/data/hll_vietnam_dev.sqlite3`. -- Snapshot validado en SQLite: `server_name=#01 [ESP] Comunidad Hispana - discord.comunidadhll.es - Spa Onl`, `current_map=Remagen`, `players=0`, `max_players=100`, `source_name=community-hispana-a2s`, `captured_at=2026-03-20T11:23:08.431142Z`. -- Endpoints revisados desde Python: `/api/servers/latest`, `/api/servers/history` y `/api/servers/{id}/history` ya exponen el snapshot real persistido. - -## Decision Notes -- El timeout observado en sandbox no se trato como bug de backend porque la misma consulta funciono fuera del sandbox sin cambios de codigo. -- La procedencia efectiva del snapshot queda reflejada en `source_name=community-hispana-a2s`, mientras que el payload superior del colector mantiene `collection_mode=a2s`. diff --git a/ai/tasks/done/TASK-030-historical-crcon-incremental-refresh.md b/ai/tasks/done/TASK-030-historical-crcon-incremental-refresh.md deleted file mode 100644 index cfb1284..0000000 --- a/ai/tasks/done/TASK-030-historical-crcon-incremental-refresh.md +++ /dev/null @@ -1,80 +0,0 @@ -# TASK-030-historical-crcon-incremental-refresh - -## Goal -Añadir un mecanismo de refresco incremental para la ingesta histórica CRCON que permita mantener actualizados los datos de ambos servidores de la comunidad sin reimportar todo el histórico completo en cada ejecución. - -## Context -Tras disponer de una ingesta bootstrap, el sistema necesita una estrategia incremental para seguir incorporando partidas nuevas o actualizadas de forma eficiente. Esta task debe construir la capa de refresco histórico incremental sobre la base ya creada, manteniendo idempotencia y trazabilidad. - -## Steps -1. Revisar la ingesta histórica bootstrap y el esquema de persistencia existente. -2. Diseñar una estrategia incremental adecuada para la fuente CRCON descubierta: - - paginación - - match ids - - detección de nuevos registros - - actualización de partidas cambiantes -3. Implementar el refresco incremental para ambos servidores. -4. Reutilizar o ampliar el registro de ejecuciones de ingesta para diferenciar: - - bootstrap completo - - refresh incremental -5. Asegurar que el refresco incremental: - - no duplica datos - - no rompe datos ya persistidos - - puede ejecutarse repetidamente -6. Documentar cómo ejecutar este refresco incremental en local. -7. No implementar todavía UI histórica. -8. No acoplar el frontend a las URLs públicas de la comunidad. -9. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- ai/architecture-index.md -- docs/historical-crcon-source-discovery.md -- docs/historical-domain-model.md -- backend/README.md -- backend/app/config.py -- backend/app/historical_ingestion.py -- backend/app/historical_storage.py -- backend/app/historical_models.py - -## Expected Files to Modify -- backend/README.md -- backend/app/config.py -- backend/app/historical_ingestion.py -- backend/app/historical_storage.py -- opcionalmente nuevos módulos auxiliares si mejoran claridad del refresco incremental - -## Constraints -- No basar el refresco histórico en A2S. -- No crear páginas frontend nuevas usando la URL de la comunidad. -- No introducir complejidad innecesaria. -- No romper el flujo actual de live status. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en refresco incremental, coherencia y trazabilidad. - -## Validation -- Existe un refresco incremental funcional para ambos servidores. -- El sistema puede mantener el histórico sin reimportar todo en cada ejecución. -- La persistencia sigue siendo idempotente. -- La documentación explica el flujo incremental. -- Los cambios quedan committeados y se hace push al remoto si el entorno lo permite. - -## Change Budget -- Preferir menos de 6 archivos modificados o creados. -- Preferir menos de 240 líneas cambiadas. -## Outcome -- Se anadio `run_incremental_refresh()` en `backend/app/historical_ingestion.py` reutilizando la misma persistencia y el registro de ejecuciones. -- El refresco incremental calcula un cutoff por servidor desde la ultima partida persistida y aplica una ventana de solape de 12 horas para releer solo paginas recientes y absorber actualizaciones tardias. -- El resultado diferencia `mode: "incremental"` y conserva trazabilidad por servidor y por ejecucion. - -## Validation Result -- Validado con `python -m app.historical_ingestion refresh --max-pages 1`. -- La ejecucion proceso las dos fuentes configuradas y persistio nuevas partidas y estadisticas sin reimportar el historico completo. -- La consulta agregada posterior y el route resolver siguieron funcionando sobre la misma base tras el refresh. - -## Decision Notes -- El cutoff incremental se apoya en `MAX(ended_at, started_at, created_at_source)` por servidor y no en paginas absolutas, para tolerar cambios de orden o partidas que se completan mas tarde. diff --git a/ai/tasks/done/TASK-030-historical-snapshot-quality-pass.md b/ai/tasks/done/TASK-030-historical-snapshot-quality-pass.md deleted file mode 100644 index c7b8a89..0000000 --- a/ai/tasks/done/TASK-030-historical-snapshot-quality-pass.md +++ /dev/null @@ -1,84 +0,0 @@ -# TASK-030-historical-snapshot-quality-pass - -## Goal -Revisar y ajustar la calidad de los snapshots persistidos tras la primera captura A2S real, asegurando consistencia de datos, timestamps, procedencia y utilidad de cara a historico y visualizacion. - -## Context -Una vez incorporado el target real y validada una primera captura, el siguiente paso es comprobar la calidad del dato persistido. No basta con guardar snapshots; deben ser consistentes y utiles para construir historico, estadisticas y visualizacion sin ruido innecesario. - -## Steps -1. Revisar snapshots persistidos a partir de la captura real de Comunidad Hispana #01. -2. Verificar consistencia de campos clave: - - nombre del servidor - - host o referencia de origen - - timestamp - - mapa actual - - jugadores - - capacidad - - fuente efectiva -3. Revisar si hay problemas de calidad como: - - duplicados innecesarios - - timestamps incoherentes - - normalizacion deficiente - - mezcla poco clara entre fallback y captura real -4. Ajustar la capa de persistencia, normalizacion o payloads si fuera necesario para mejorar claridad. -5. Revisar el impacto en endpoints historicos existentes: - - `/api/servers/latest` - - `/api/servers/history` - - `/api/servers/{id}/history` -6. Mantener el cambio centrado en calidad y coherencia del historico, no en nuevas visualizaciones. -7. Actualizar documentacion minima si el modelo efectivo de snapshot cambia ligeramente. - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- ai/architecture-index.md -- backend/README.md -- backend/app/collector.py -- backend/app/normalizers.py -- backend/app/storage.py -- backend/app/routes.py -- backend/app/payloads.py -- datos persistidos generados en la task anterior - -## Expected Files to Modify -- backend/app/normalizers.py -- backend/app/storage.py -- backend/app/routes.py -- backend/app/payloads.py -- backend/README.md -- opcionalmente documentacion tecnica relacionada si la claridad del historico necesita ajuste - -## Constraints -- No tocar frontend en esta task. -- No anadir nuevas fuentes externas. -- No introducir complejidad analitica alta. -- No hacer cambios destructivos. -- Mantener el resultado centrado en calidad de datos historicos. - -## Validation -- Los snapshots reales persistidos son consistentes y utiles. -- Los endpoints historicos reflejan correctamente el dato real almacenado. -- La distincion entre captura real y fallback queda razonablemente clara. -- El backend queda listo para una siguiente task de mejora visual o estadistica sobre datos reales. - -## Change Budget -- Preferir menos de 5 archivos modificados. -- Preferir menos de 180 lineas cambiadas. - -## Outcome -- `backend/app/normalizers.py` anade `snapshot_origin` y `source_ref` al modelo normalizado para que la procedencia no se infiera de forma ambigua en historico. -- `backend/app/snapshots.py` conserva esos campos en cada snapshot persistible. -- `backend/app/storage.py` migra la tabla SQLite sin destruir datos, serializa ambos campos en las consultas historicas y backfilla referencias A2S registradas para snapshots ya existentes. -- `backend/README.md` documenta los nuevos metadatos historicos y el valor esperado para la captura real de Comunidad Hispana #01. - -## Validation Result -- Ejecutado: lectura de `list_latest_snapshots()`, `list_snapshot_history()` y `list_server_history('comunidad-hispana-01')` desde Python. -- Resultado: los snapshots historicos exponen `snapshot_origin` con `real-a2s` o `controlled-fallback` y `source_ref` coherente. -- Ejecutado fuera del sandbox: `python -m app.collector --source a2s --no-fallback`. -- Resultado: nuevo snapshot real persistido con `source_ref=a2s://152.114.195.174:7778`, `current_map=Remagen`, `players=0`, `max_players=100`. -- Endpoints verificados: `/api/servers/latest`, `/api/servers/history` y `/api/servers/{id}/history` devuelven el snapshot real mas reciente con la nueva metadata de procedencia. - -## Decision Notes -- No se tocaron `routes.py` ni `payloads.py` porque ya reutilizan directamente los registros serializados de almacenamiento y heredaron la mejora sin cambios de contrato adicionales. -- No se introdujo deduplicacion agresiva de snapshots porque dos capturas reales con distinto `captured_at` siguen siendo historico valido; el ajuste se centro en claridad y consistencia de procedencia. diff --git a/ai/tasks/done/TASK-031-local-cors-alignment-for-frontend-dev.md b/ai/tasks/done/TASK-031-local-cors-alignment-for-frontend-dev.md deleted file mode 100644 index 9b38a25..0000000 --- a/ai/tasks/done/TASK-031-local-cors-alignment-for-frontend-dev.md +++ /dev/null @@ -1,70 +0,0 @@ -# TASK-031-local-cors-alignment-for-frontend-dev - -## Goal -Corregir y alinear la configuracion CORS del backend para permitir que el frontend local de desarrollo consuma la API desde origenes locales habituales sin caer en fallback por bloqueo del navegador. - -## Context -El backend responde correctamente a `/health`, `/api/servers/latest` y `/api/servers/history`, y los snapshots reales A2S ya estan persistidos. Sin embargo, el frontend servido localmente con `python -m http.server 8080` no puede consumir la API porque el navegador bloquea las respuestas por falta de la cabecera `Access-Control-Allow-Origin` para `http://localhost:8080`. - -La correccion debe centrarse en CORS de desarrollo local, sin cambiar la arquitectura funcional del producto. - -## Steps -1. Revisar la configuracion actual de CORS del backend. -2. Confirmar como se comparan y validan los origenes permitidos. -3. Anadir soporte correcto para los origenes locales de desarrollo mas comunes, incluyendo al menos: - - `http://localhost:8080` - - `http://127.0.0.1:8080` -4. Revisar si tambien conviene permitir otros puertos locales habituales documentados por el proyecto, sin abrir el backend de forma innecesaria. -5. Asegurar que las respuestas GET del backend incluyan `Access-Control-Allow-Origin` cuando el origen este permitido. -6. Asegurar que el backend maneje correctamente `OPTIONS` si el flujo actual lo requiere. -7. Actualizar la documentacion del backend para dejar claro como probar frontend y backend juntos en local. -8. Mantener el alcance centrado en desarrollo local y correccion CORS. - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- backend/README.md -- backend/app/config.py -- backend/app/main.py -- backend/app/routes.py -- frontend/assets/js/main.js - -## Expected Files to Modify -- backend/README.md -- backend/app/config.py -- backend/app/main.py -- opcionalmente otros archivos backend si la logica CORS esta centralizada en otro sitio - -## Constraints -- No tocar visualmente el frontend. -- No cambiar endpoints ni payloads. -- No introducir dependencias nuevas innecesarias. -- No hacer cambios destructivos. -- Mantener la solucion pequena y claramente orientada a desarrollo local. - -## Validation -- Una peticion desde `http://localhost:8080` a `http://localhost:8000/api/servers/latest` ya no falla por CORS. -- Una peticion desde `http://127.0.0.1:8080` tambien funciona si se decidio soportarla. -- La landing deja de caer al fallback estatico cuando el backend esta disponible. -- La documentacion refleja como ejecutar el stack local correctamente. - -## Change Budget -- Preferir menos de 4 archivos modificados. -- Preferir menos de 140 lineas cambiadas. - -## Outcome -- `backend/app/config.py` amplia la allowlist CORS local por defecto para cubrir `http://localhost:8080` y `http://127.0.0.1:8080`, manteniendo tambien `null` y los origenes ya usados en `5500`. -- `backend/app/config.py` normaliza espacios y barras finales en `HLL_BACKEND_ALLOWED_ORIGINS` para que un override local no falle por formato. -- `backend/README.md` documenta la prueba local recomendada con `python -m app.main` y `python -m http.server 8080`, y deja explicito que origenes locales quedan soportados por defecto. -- No fue necesario cambiar `backend/app/main.py` ni `backend/app/routes.py` porque la emision de `Access-Control-Allow-Origin` y el manejo de `OPTIONS` ya estaban correctamente centralizados en el handler HTTP. - -## Validation Result -- Ejecutado: validacion aislada desde Python levantando `app.main.create_server()` en `127.0.0.1:8010` dentro del mismo proceso. -- Resultado `GET` con `Origin: http://localhost:8080`: `200 OK`, `Access-Control-Allow-Origin: http://localhost:8080`, `Vary: Origin`. -- Resultado `GET` con `Origin: http://127.0.0.1:8080`: `200 OK`, `Access-Control-Allow-Origin: http://127.0.0.1:8080`, `Vary: Origin`. -- Resultado `OPTIONS` con `Origin: http://localhost:8080`: `204 No Content`, `Access-Control-Allow-Origin: http://localhost:8080`, `Access-Control-Allow-Methods: GET, OPTIONS`, `Access-Control-Allow-Headers: Content-Type`. -- Observacion de entorno: `127.0.0.1:8000` ya estaba ocupado por otro proceso ajeno a esta task, asi que la validacion final se hizo en `:8010` para comprobar exactamente el codigo modificado sin depender de ese proceso. - -## Decision Notes -- Se mantuvo una allowlist cerrada de desarrollo local en lugar de abrir CORS globalmente, porque la task pedia corregir el flujo local sin introducir una configuracion de produccion prematura. -- No se anadieron puertos arbitrarios extra; se alineo la configuracion con `5500`, `8080` y `null`, que cubren los flujos locales ya usados o documentados por el proyecto. diff --git a/ai/tasks/done/TASK-031-weekly-top-kills-api.md b/ai/tasks/done/TASK-031-weekly-top-kills-api.md deleted file mode 100644 index 8e82b0b..0000000 --- a/ai/tasks/done/TASK-031-weekly-top-kills-api.md +++ /dev/null @@ -1,81 +0,0 @@ -# TASK-031-weekly-top-kills-api - -## Goal -Exponer una primera API histórica útil que devuelva el ranking de jugadores con más kills de la última semana para cada uno de los 2 servidores reales de la comunidad. - -## Context -El objetivo funcional histórico inicial del proyecto es poder consultar métricas agregadas como “jugadores con más kills de la última semana por servidor”. Con la fuente descubierta, el almacenamiento creado y la ingesta histórica ya en marcha, el siguiente valor real es exponer un endpoint backend estable que pueda alimentar futuras vistas propias del proyecto sin depender directamente de la web de la comunidad. - -## Steps -1. Revisar el modelo de dominio histórico y la persistencia ya creada. -2. Definir el endpoint o endpoints mínimos necesarios para top kills semanales por servidor. -3. Diseñar e implementar la consulta agregada usando los datos históricos persistidos. -4. Definir un payload claro que incluya, como mínimo: - - servidor - - rango temporal usado - - jugador - - kills semanales - - posición/ranking - - número de partidas consideradas si resulta viable -5. Asegurar que la definición de “última semana” queda clara y consistente. -6. Documentar el endpoint en el backend. -7. No crear todavía páginas frontend nuevas usando la URL de la comunidad. -8. No incrustar ni duplicar scoreboard externos. -9. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- ai/architecture-index.md -- docs/historical-domain-model.md -- backend/README.md -- backend/app/routes.py -- backend/app/payloads.py -- backend/app/historical_storage.py -- backend/app/historical_models.py -- backend/app/historical_ingestion.py - -## Expected Files to Modify -- backend/app/routes.py -- backend/app/payloads.py -- backend/README.md -- uno o más módulos nuevos o existentes de consulta histórica, por ejemplo: - - backend/app/historical_queries.py - - backend/app/historical_payloads.py - -## Constraints -- No basar este endpoint en A2S. -- No consultar directamente la web de la comunidad desde el frontend. -- No crear todavía UI histórica. -- No romper endpoints actuales. -- No introducir complejidad innecesaria. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en la primera API histórica útil y estable. - -## Validation -- Existe un endpoint usable para top kills de la última semana por servidor. -- El endpoint funciona para los 2 servidores reales de la comunidad. -- El payload es claro y reutilizable. -- La documentación backend queda alineada. -- No se han creado páginas frontend nuevas ni dependencias directas del frontend respecto a la URL de la comunidad. -- Los cambios quedan committeados y se hace push al remoto si el entorno lo permite. - -## Change Budget -- Preferir menos de 6 archivos modificados o creados. -- Preferir menos de 240 líneas cambiadas. -## Outcome -- Se expuso `GET /api/historical/weekly-top-kills` en `backend/app/routes.py`. -- La agregacion vive en `backend/app/historical_storage.py` y calcula top kills semanales con ranking independiente por cada servidor real. -- El payload reutiliza `build_weekly_top_kills_payload()` para devolver rango temporal, jugador, kills semanales, posicion y partidas consideradas. -- `backend/README.md` documenta el endpoint y sus parametros `limit` y `server`. - -## Validation Result -- Validado con `python -m compileall app`. -- Validado con una comprobacion local de `resolve_get_payload('/api/historical/weekly-top-kills?limit=3')`, que devolvio `200`, `status: "ok"` y resultados para ambos servidores. -- El endpoint se apoya exclusivamente en historico persistido CRCON y no toca el flujo live A2S ni el frontend. - -## Decision Notes -- El limite se aplica por servidor mediante `ROW_NUMBER() OVER (PARTITION BY historical_servers.slug ...)` para que una request con `limit=10` entregue hasta 10 jugadores por cada servidor, no un corte global mezclado. diff --git a/ai/tasks/done/TASK-032-connect-button-for-real-server-cards.md b/ai/tasks/done/TASK-032-connect-button-for-real-server-cards.md deleted file mode 100644 index e346fe7..0000000 --- a/ai/tasks/done/TASK-032-connect-button-for-real-server-cards.md +++ /dev/null @@ -1,69 +0,0 @@ -# TASK-032-connect-button-for-real-server-cards - -## Goal -Añadir en la web un botón de conexión directa `steam://connect/...` para tarjetas de servidores reales, usando el game port correcto y manteniendo el comportamiento actual del panel de servidores. - -## Context -La landing ya muestra snapshots reales A2S y distingue entre datos reales, históricos y fallback. Además, ya se han verificado servidores reales de Comunidad Hispana con separación entre game port y query port. El siguiente paso útil para producto es añadir un botón Connect en las tarjetas de servidores reales para permitir una acción directa desde la web. - -## Steps -1. Revisar el frontend actual y cómo se renderizan las tarjetas de servidores. -2. Revisar el backend y comprobar si el frontend dispone actualmente del `game_port` necesario para construir `steam://connect/...`. -3. Si el dato no está disponible en los payloads actuales, ajustar la capa backend mínima necesaria para exponerlo de forma clara y estable. -4. Añadir un botón Connect solo cuando la tarjeta represente un servidor real con datos suficientes. -5. Usar siempre el `game_port`, nunca el `query_port`. -6. Mantener el botón visualmente coherente con la landing actual. -7. Preservar el fallback actual si un servidor no tiene datos reales o no dispone de `game_port`. -8. Validar que los enlaces queden correctos al menos para: - - Comunidad Hispana #01 → `steam://connect/152.114.195.174:7777` - - Comunidad Hispana #02 → `steam://connect/152.114.195.150:7877` - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- frontend/index.html -- frontend/assets/js/main.js -- frontend/assets/css/styles.css -- backend/app/routes.py -- backend/app/payloads.py -- backend/app/server_targets.py -- backend/README.md - -## Expected Files to Modify -- frontend/index.html -- frontend/assets/js/main.js -- frontend/assets/css/styles.css -- backend/app/routes.py -- backend/app/payloads.py -- opcionalmente backend/app/server_targets.py si hace falta alinear metadata - -## Constraints -- No rediseñar toda la landing. -- No romper el fallback actual. -- No usar `query_port` para el enlace de conexión. -- No añadir librerías nuevas. -- No hacer cambios destructivos. -- Mantener la mejora centrada en el panel de servidores y acción de conexión. - -## Validation -- Las tarjetas de servidores reales muestran un botón Connect cuando corresponde. -- El enlace de conexión usa `steam://connect/:`. -- Los placeholders o tarjetas sin datos reales no rompen el render. -- La mejora visual se integra con la landing actual. - -## Change Budget -- Preferir menos de 5 archivos modificados. -- Preferir menos de 180 líneas cambiadas. -## Outcome -- `backend/app/payloads.py` enriquece los snapshots reales con `host`, `query_port` y `game_port` a partir del registro A2S ya verificado, sin tocar la persistencia. -- `frontend/assets/js/main.js` muestra un boton `Connect` solo para tarjetas `real-a2s` que dispongan de `host` y `game_port`, generando `steam://connect/:`. -- `frontend/assets/css/styles.css` integra visualmente la nueva accion sin redisenar el panel ni afectar placeholders. - -## Validation Result -- Ejecutado desde `backend/`: comprobacion de `build_server_latest_payload()` sobre `comunidad-hispana-01` y `comunidad-hispana-02`. -- Resultado: ambos snapshots reales exponen `host`, `query_port` y `game_port`, conservando `snapshot_origin=real-a2s`. -- Ejecutado desde `backend/`: validacion de enlaces esperados `steam://connect/152.114.195.174:7777` y `steam://connect/152.114.195.150:7877`. -- Resultado: los enlaces calculados coinciden exactamente con los valores requeridos para `#01` y `#02`. - -## Decision Notes -- Se evita duplicar `host` y `game_port` en SQLite porque ya existen como metadata estable del target A2S y basta con enriquecer el payload de lectura. diff --git a/ai/tasks/done/TASK-032-historical-data-quality-and-ranking-validation.md b/ai/tasks/done/TASK-032-historical-data-quality-and-ranking-validation.md deleted file mode 100644 index 341027d..0000000 --- a/ai/tasks/done/TASK-032-historical-data-quality-and-ranking-validation.md +++ /dev/null @@ -1,119 +0,0 @@ -# TASK-032-historical-data-quality-and-ranking-validation - -## Goal -Validar la calidad del historico ingerido y la correccion del ranking semanal de kills para los 2 servidores reales de la comunidad, detectando y corrigiendo problemas de integridad, duplicados, naming o rango temporal antes de construir UI historica propia. - -## Context -El proyecto ya dispone de: -- estado actual en vivo via A2S -- capa historica separada via CRCON scoreboard JSON -- persistencia historica propia -- ingesta historica funcional -- endpoint `GET /api/historical/weekly-top-kills` - -Antes de exponer estos datos en una UI propia del proyecto, hay que asegurar que la base historica tiene calidad suficiente y que el ranking semanal devuelve resultados coherentes, consistentes y trazables. - -## Steps -1. Revisar la implementacion actual de: - - almacenamiento historico - - ingesta historica - - modelos historicos - - endpoint `GET /api/historical/weekly-top-kills` -2. Verificar la calidad de los datos historicos persistidos para ambos servidores. Comprobar al menos: - - numero de partidas ingeridas - - numero de jugadores ingeridos - - presencia de datos relevantes por partida - - distribucion por servidor -3. Detectar posibles duplicados o inconsistencias en: - - partidas - - jugadores - - estadisticas por jugador y partida -4. Revisar la estrategia actual de identidad y deduplicacion: - - ids de partida - - ids de jugador o claves degradadas - - relacion entre servidor y match -5. Validar que el calculo de "ultima semana" usado por el ranking sea correcto y consistente. -6. Validar que el ranking de kills: - - sume correctamente kills por jugador - - no mezcle datos entre servidores - - no use partidas fuera del rango temporal esperado - - no devuelva duplicados de jugador por mala consolidacion -7. Revisar si los nombres de jugador y nombres de mapa se almacenan y devuelven de forma suficientemente limpia. -8. Si se detectan problemas, corregir unicamente lo necesario en: - - almacenamiento - - consultas - - normalizacion - - endpoint historico -9. Anadir validaciones o utilidades minimas si ayudan a reforzar la fiabilidad del historico. -10. Documentar brevemente los hallazgos y el estado final de calidad historica. -11. No crear todavia paginas o bloques UI historicos. -12. Al completar la implementacion: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- ai/architecture-index.md -- docs/decisions.md -- docs/historical-crcon-source-discovery.md -- docs/historical-domain-model.md -- backend/README.md -- backend/app/historical_models.py -- backend/app/historical_storage.py -- backend/app/historical_ingestion.py -- backend/app/routes.py -- backend/app/payloads.py -- cualquier consulta o helper historico adicional ya creado - -## Expected Files to Modify -- backend/README.md -- backend/app/historical_storage.py -- backend/app/historical_ingestion.py -- backend/app/routes.py -- backend/app/payloads.py -- opcionalmente nuevos modulos auxiliares si mejoran validacion o normalizacion, por ejemplo: - - backend/app/historical_queries.py - - backend/app/historical_validation.py -- opcionalmente un documento tecnico breve, por ejemplo: - - docs/historical-data-quality-notes.md - -## Constraints -- No crear todavia UI historica. -- No basar correcciones historicas en A2S. -- No acoplar el frontend a URLs de la comunidad. -- No introducir complejidad innecesaria. -- No romper el flujo actual de live status. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en calidad, consistencia y fiabilidad del historico. - -## Validation -- Se ha revisado la calidad del historico para ambos servidores. -- Se han detectado y corregido, si existen, duplicados o inconsistencias relevantes. -- El endpoint `GET /api/historical/weekly-top-kills` devuelve resultados coherentes. -- El rango temporal de "ultima semana" queda validado. -- Los datos no se mezclan entre servidores. -- Los cambios quedan committeados y se hace push al remoto si el entorno lo permite. - -## Change Budget -- Preferir menos de 7 archivos modificados o creados. -- Preferir menos de 260 lineas cambiadas. - -## Outcome -- Se corrigio la estrategia de identidad historica en `backend/app/historical_storage.py` para priorizar SteamID real y usar `player_id` como clave `crcon-player:*` cuando no existe SteamID. -- La inicializacion del storage ahora fusiona jugadores duplicados y partidas duplicadas persistidas con id sintetico frente a id CRCON final. -- El ranking `GET /api/historical/weekly-top-kills` paso a usar solo partidas cerradas con `ended_at`, evitando contar sesiones en curso o duplicadas. -- Se documentaron los hallazgos y el estado final en `docs/historical-data-quality-notes.md` y se alineo `backend/README.md`. - -## Validation Result -- Validado con inicializacion real sobre `backend/data/hll_vietnam_dev.sqlite3`. -- Tras la correccion, el dataset local quedo en `12` partidas, `510` jugadores y `914` filas de estadisticas por jugador y partida. -- Comprobado que no quedan duplicados por `steam_id`, `source_player_id`, nombre normalizado ni por la combinacion `(servidor, started_at, mapa)`. -- Comprobado que ya no quedan partidas abiertas (`ended_at IS NULL`) en el dataset local actual. -- Validado con `list_weekly_top_kills()` para ambos servidores, confirmando separacion por servidor y uso exclusivo de partidas cerradas dentro de la ventana movil de 7 dias. - -## Decision Notes -- `steaminfo.id` deja de tratarse como `steam_id` real porque en los datos observados funcionaba como identificador corto auxiliar y fragmentaba la identidad del jugador. -- Para resolver duplicados de partida se usa una heuristica conservadora por `(historical_server_id, started_at, mapa normalizado)`, priorizando la fila cerrada, numerica y con mas jugadores. -- No se eliminaron partidas con muy pocos jugadores porque eso es una decision de calidad de producto futura, no un problema de integridad estructural. diff --git a/ai/tasks/done/TASK-033-historical-full-bootstrap-and-coverage-validation.md b/ai/tasks/done/TASK-033-historical-full-bootstrap-and-coverage-validation.md deleted file mode 100644 index a4abd45..0000000 --- a/ai/tasks/done/TASK-033-historical-full-bootstrap-and-coverage-validation.md +++ /dev/null @@ -1,72 +0,0 @@ -# TASK-033-historical-full-bootstrap-and-coverage-validation - -## Goal -Ejecutar y consolidar una carga histórica completa real para los 2 servidores de la comunidad, validando la cobertura temporal y cuantitativa del histórico persistido para asegurar que la base histórica sea suficientemente representativa antes de seguir refinando la UI y las métricas. - -## Context -La capa histórica ya existe y funciona, pero el estado actual del proyecto indica que el histórico persistido parece insuficiente para representar con credibilidad una semana completa de actividad. La UI actual muestra resúmenes basados en lo que haya cargado en la base, y si la cobertura es corta puede inducir a interpretar mal el estado del histórico. Antes de seguir afinando la capa histórica, hace falta asegurar un bootstrap real y comprobar la cobertura conseguida para ambos servidores. - -## Steps -1. Revisar la implementación actual de bootstrap, refresh incremental y persistencia histórica. -2. Confirmar si el histórico actual está subpoblado por haber usado refrescos parciales, límites de páginas, validaciones locales u otras restricciones. -3. Ejecutar o dejar implementado el flujo de bootstrap completo real para ambos servidores de la comunidad, sin limitar la carga a una ventana artificialmente corta. -4. Persistir el histórico completo disponible desde la fuente CRCON scoreboard JSON para ambos servidores. -5. Verificar y documentar, por servidor: - - número total de partidas históricas persistidas - - número de jugadores únicos - - rango temporal cubierto - - fecha/hora de primera partida persistida - - fecha/hora de última partida persistida -6. Validar que la persistencia sigue siendo idempotente tras el bootstrap completo. -7. Detectar si hay límites reales de origen (por ejemplo, datos antiguos no disponibles ya en la fuente) y documentarlos claramente. -8. Revisar si hace falta ajustar el flujo bootstrap para que sea operativamente reproducible y comprensible. -9. Documentar el estado real de cobertura alcanzado tras este bootstrap. -10. No crear todavía UI histórica nueva en esta task. -11. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- ai/architecture-index.md -- docs/historical-crcon-source-discovery.md -- docs/historical-domain-model.md -- docs/historical-data-quality-notes.md -- backend/README.md -- backend/app/config.py -- backend/app/historical_ingestion.py -- backend/app/historical_storage.py -- backend/app/historical_models.py -- backend/app/routes.py -- backend/app/payloads.py - -## Expected Files to Modify -- backend/README.md -- backend/app/historical_ingestion.py -- backend/app/historical_storage.py -- backend/app/config.py -- opcionalmente nuevos módulos auxiliares si son necesarios para consolidar bootstrap y validación de cobertura -- un documento técnico nuevo o actualizado, por ejemplo: - - docs/historical-coverage-report.md - - docs/historical-data-quality-notes.md - -## Constraints -- No basar el histórico en A2S. -- No crear UI histórica nueva en esta task. -- No depender del HTML público de `/games` como fuente final. -- No romper el flujo actual de live status. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en bootstrap completo, cobertura e idempotencia. - -## Validation -- Existe un bootstrap histórico completo real para ambos servidores. -- La cobertura histórica real queda medida y documentada. -- El histórico persistido contiene un volumen y rango temporal coherentes con la disponibilidad real de la fuente. -- La persistencia sigue siendo idempotente. -- Los cambios quedan committeados y se hace push al remoto si el entorno lo permite. - -## Change Budget -- Preferir menos de 7 archivos modificados o creados. -- Preferir menos de 260 líneas cambiadas. diff --git a/ai/tasks/done/TASK-033-historical-weekly-top-kills-ui.md b/ai/tasks/done/TASK-033-historical-weekly-top-kills-ui.md deleted file mode 100644 index 814f903..0000000 --- a/ai/tasks/done/TASK-033-historical-weekly-top-kills-ui.md +++ /dev/null @@ -1,90 +0,0 @@ -# TASK-033-historical-weekly-top-kills-ui - -## Goal -Crear la primera UI histórica propia del proyecto para mostrar el ranking de jugadores con más kills de la última semana por servidor, consumiendo la API histórica interna del backend y sin depender de páginas externas de la comunidad. - -## Context -El proyecto ya dispone de: -- live status de servidores vía A2S -- capa histórica propia persistida -- validación de calidad histórica completada -- endpoint histórico `GET /api/historical/weekly-top-kills` - -Con la calidad del histórico ya validada, el siguiente paso es exponer una primera vista propia y útil para el usuario final. Esta UI debe ser del propio proyecto, no una duplicación o incrustación de la web de la comunidad. - -## Steps -1. Revisar el endpoint actual `GET /api/historical/weekly-top-kills` y su payload real. -2. Diseñar una primera UI histórica propia, simple y clara, para mostrar rankings semanales. -3. Implementar esta UI en una página propia del proyecto, por ejemplo: - - `frontend/historico.html` - o una ruta equivalente coherente con la estructura actual del frontend. -4. Añadir un selector o control claro para alternar entre los 2 servidores reales de la comunidad. -5. Consumir la API histórica propia del backend, sin depender de URLs públicas de la comunidad. -6. Mostrar, como mínimo: - - posición - - nombre de jugador - - kills semanales - - servidor seleccionado - - rango temporal usado si el payload lo expone o puede presentarse de forma clara -7. Añadir estados de: - - carga - - vacío - - error - - sin datos históricos suficientes -8. Mantener la estética coherente con la landing actual. -9. No mezclar esta vista con estado live A2S salvo referencia mínima si fuera útil. -10. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- ai/architecture-index.md -- docs/historical-domain-model.md -- docs/historical-data-quality-notes.md -- backend/README.md -- backend/app/routes.py -- backend/app/payloads.py -- frontend/index.html -- frontend/assets/css/styles.css -- frontend/assets/js/main.js - -## Expected Files to Modify -- uno o más archivos nuevos de frontend para esta vista, por ejemplo: - - frontend/historico.html - - frontend/assets/js/historico.js - - frontend/assets/css/historico.css -- opcionalmente frontend/index.html si se añade un enlace de acceso razonable a la nueva vista -- opcionalmente documentación mínima si hay que reflejar la nueva pantalla propia - -## Constraints -- No usar páginas de la comunidad como UI del producto. -- No incrustar ni duplicar HTML externo. -- No romper la landing actual. -- No introducir frameworks nuevos. -- No hacer cambios destructivos. -- Mantener la solución centrada en una primera UI histórica útil y clara. - -## Validation -- Existe una primera página histórica propia del proyecto. -- La página consume `GET /api/historical/weekly-top-kills`. -- El usuario puede alternar entre los 2 servidores. -- La UI muestra posiciones, jugadores y kills de forma clara. -- Existen estados de loading, empty y error. -- Los cambios quedan committeados y se hace push al remoto si el entorno lo permite. - -## Change Budget -- Preferir menos de 6 archivos modificados o creados. -- Preferir menos de 260 líneas cambiadas. -## Outcome -- Se creó `frontend/historico.html` como primera UI histórica propia del proyecto. -- La vista consume `GET /api/historical/weekly-top-kills` desde `frontend/assets/js/historico.js`. -- Se añadieron estados de carga, vacío, error y mensaje de datos históricos insuficientes. -- El selector permite alternar entre `comunidad-hispana-01` y `comunidad-hispana-02`. - -## Validation Notes -- `python -m compileall app` -- comprobación local de payload con `build_weekly_top_kills_payload(limit=3, server_id='comunidad-hispana-01')` -- `node --check frontend/assets/js/historico.js` diff --git a/ai/tasks/done/TASK-033-real-vs-placeholder-server-panel-separation.md b/ai/tasks/done/TASK-033-real-vs-placeholder-server-panel-separation.md deleted file mode 100644 index e96ea19..0000000 --- a/ai/tasks/done/TASK-033-real-vs-placeholder-server-panel-separation.md +++ /dev/null @@ -1,62 +0,0 @@ -# TASK-033-real-vs-placeholder-server-panel-separation - -## Goal -Mejorar la claridad visual y funcional del panel de servidores separando o priorizando de forma más evidente los snapshots reales A2S frente a los placeholders controlados. - -## Context -El panel de servidores ya consume datos del backend y actualmente mezcla snapshots reales persistidos con tarjetas de fallback controlado. El sistema funciona, pero ahora conviene dejar visualmente más claro qué servidores son reales y cuáles siguen siendo referencias provisionales. - -## Steps -1. Revisar el panel actual de servidores y su lógica de renderizado. -2. Identificar cómo distingue actualmente el frontend entre: - - `real-a2s` - - `controlled-fallback` - - histórico persistido -3. Mejorar la composición del panel para que los snapshots reales queden más destacados o separados de los placeholders. -4. Mantener el cambio contenido y coherente con el diseño actual. -5. Asegurar que la información de procedencia siga siendo clara. -6. No eliminar el fallback si todavía es útil para el proyecto. -7. No rediseñar la landing completa. - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- frontend/index.html -- frontend/assets/js/main.js -- frontend/assets/css/styles.css -- backend/app/payloads.py -- backend/app/routes.py - -## Expected Files to Modify -- frontend/index.html -- frontend/assets/js/main.js -- frontend/assets/css/styles.css - -## Constraints -- No tocar backend salvo si una referencia documental mínima fuera imprescindible. -- No eliminar soporte para fallback. -- No introducir librerías nuevas. -- No hacer cambios destructivos. -- Mantener la mejora centrada en claridad de datos y jerarquía visual. - -## Validation -- El panel distingue mejor entre servidores reales y placeholders. -- Los snapshots reales ganan prioridad o separación visual clara. -- El fallback sigue funcionando. -- La landing mantiene coherencia visual. - -## Change Budget -- Preferir menos de 3 archivos modificados. -- Preferir menos de 160 líneas cambiadas. -## Outcome -- `frontend/assets/js/main.js` separa el render historico en dos bloques: `Snapshots reales A2S` y `Referencia provisional e historico auxiliar`, priorizando arriba los snapshots reales. -- `frontend/assets/js/main.js` etiqueta cada tarjeta persistida como `Snapshot real A2S` o `Referencia persistida` segun `snapshot_origin`, manteniendo el fallback sin eliminarlo. -- `frontend/assets/css/styles.css` refuerza la separacion visual con encabezados de seccion y variantes de tarjeta diferenciadas para reales y placeholders. - -## Validation Result -- Ejecutado: `node --check frontend/assets/js/main.js`. -- Resultado: sintaxis JavaScript valida tras introducir el render por secciones. -- Revisado en codigo: el panel renderiza una seccion prioritaria `Snapshots reales A2S` y una seccion separada para referencia/fallback, sin romper la grilla existente. - -## Decision Notes -- La separacion se implementa dentro del mismo panel para mantener el alcance pequeno y evitar un redisenio estructural de la landing. diff --git a/ai/tasks/done/TASK-034-historical-refresh-automation-and-ops.md b/ai/tasks/done/TASK-034-historical-refresh-automation-and-ops.md deleted file mode 100644 index a880e61..0000000 --- a/ai/tasks/done/TASK-034-historical-refresh-automation-and-ops.md +++ /dev/null @@ -1,72 +0,0 @@ -# TASK-034-historical-refresh-automation-and-ops - -## Goal -Automatizar y documentar el refresco periódico del histórico CRCON para ambos servidores de la comunidad, dejando el sistema preparado para mantenerse actualizado sin intervención manual constante. - -## Context -Ya existe ingesta bootstrap, refresco incremental y validación de calidad histórica. El siguiente paso técnico es estabilizar la operativa del histórico con un flujo repetible y documentado que permita mantener actualizados los datos históricos de forma consistente. - -## Steps -1. Revisar la ingesta histórica actual y el refresco incremental ya implementado. -2. Diseñar la estrategia operativa de refresco histórico: - - frecuencia recomendada - - modo de ejecución local - - modo de ejecución automatizada - - control de errores y reintentos básicos -3. Implementar un mecanismo razonable para lanzar el refresco histórico periódicamente o dejarlo listo para ello. -4. Registrar metadatos mínimos de operación: - - último refresco ejecutado - - resultado - - errores básicos si ocurren -5. Documentar claramente cómo ejecutar y mantener esta capa histórica. -6. No crear todavía dashboards de operaciones complejos. -7. No romper el flujo actual de live status. -8. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- backend/README.md -- backend/app/config.py -- backend/app/historical_ingestion.py -- backend/app/historical_storage.py -- docs/historical-domain-model.md -- docs/historical-data-quality-notes.md - -## Expected Files to Modify -- backend/README.md -- backend/app/config.py -- backend/app/historical_ingestion.py -- opcionalmente nuevos módulos/entrypoints si mejoran la automatización, por ejemplo: - - backend/app/historical_jobs.py - - backend/app/historical_runner.py -- opcionalmente documentación técnica adicional - -## Constraints -- No crear UI histórica en esta task. -- No romper la ingesta actual. -- No introducir complejidad operativa excesiva. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en automatización y operativa del histórico. - -## Validation -- Existe una estrategia clara y ejecutable de refresco periódico histórico. -- La documentación explica cómo ejecutar el refresco. -- La capa histórica queda operativamente más estable. -- Los cambios quedan committeados y se hace push al remoto si el entorno lo permite. - -## Change Budget -- Preferir menos de 5 archivos modificados o creados. -- Preferir menos de 220 líneas cambiadas. -## Outcome -- Se añadió `backend/app/historical_runner.py` para ejecutar refresh incremental periódico. -- Se incorporaron variables de configuración para intervalo, reintentos y espera entre reintentos. -- La operativa queda documentada en `backend/README.md`. -- El registro operativo sigue apoyándose en `historical_ingestion_runs` para dejar último refresh, resultado y errores básicos. - -## Validation Notes -- `python -m compileall app` -- validación estática del runner y de los getters de configuración -- no se ejecutó refresh real contra red externa por las restricciones del entorno actual diff --git a/ai/tasks/done/TASK-034-historical-summary-semantics-and-coverage-badging.md b/ai/tasks/done/TASK-034-historical-summary-semantics-and-coverage-badging.md deleted file mode 100644 index 4bc573c..0000000 --- a/ai/tasks/done/TASK-034-historical-summary-semantics-and-coverage-badging.md +++ /dev/null @@ -1,78 +0,0 @@ -# TASK-034-historical-summary-semantics-and-coverage-badging - -## Goal -Corregir la semántica del resumen histórico y de los indicadores visibles para que la UI y la API distingan claramente entre cobertura histórica importada y ventana temporal semanal, evitando interpretaciones erróneas como asumir que un número bajo de partidas representa una semana completa de actividad. - -## Context -La UI histórica actual puede llevar a confusión porque el usuario puede interpretar ciertos resúmenes como si describieran una semana completa, cuando en realidad reflejan solo la cobertura actualmente persistida en base. Aunque el ranking semanal y el resumen de servidor son conceptos distintos, hoy esa diferencia no queda visual ni semánticamente lo bastante clara. - -## Steps -1. Revisar el payload y la lógica actual del resumen histórico por servidor. -2. Revisar qué información muestra hoy la UI histórica sobre: - - cobertura temporal - - número de partidas - - rango de fechas - - ranking semanal -3. Definir una semántica clara para distinguir: - - cobertura histórica importada - - ventana semanal usada para rankings - - resumen agregado del servidor -4. Ajustar el backend para exponer, si hace falta, campos más claros sobre cobertura histórica real, por ejemplo: - - first_match_at - - last_match_at - - imported_matches_count - - coverage_status - - cualquier otro metadato útil y honesto -5. Ajustar la UI para que el usuario entienda correctamente: - - qué parte es “últimos 7 días” - - qué parte es “cobertura total importada” - - cuándo la cobertura es parcial o insuficiente -6. Eliminar formulaciones ambiguas o visualmente engañosas. -7. Mantener la estética y coherencia de la UI histórica. -8. No abrir todavía nuevas grandes vistas históricas. -9. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- ai/architecture-index.md -- docs/historical-data-quality-notes.md -- docs/historical-coverage-report.md -- backend/README.md -- backend/app/routes.py -- backend/app/payloads.py -- backend/app/historical_storage.py -- frontend/historico.html -- frontend/assets/js/historico.js -- frontend/assets/css/historico.css - -## Expected Files to Modify -- backend/app/routes.py -- backend/app/payloads.py -- backend/app/historical_storage.py -- frontend/historico.html -- frontend/assets/js/historico.js -- frontend/assets/css/historico.css -- opcionalmente backend/README.md o documentación técnica mínima si hace falta reflejar la nueva semántica - -## Constraints -- No crear páginas usando la URL de la comunidad. -- No depender de HTML externo. -- No romper la UI histórica existente. -- No romper el ranking semanal. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en claridad semántica, payload y UI. - -## Validation -- La UI ya no induce a interpretar mal la cobertura histórica. -- Queda clara la diferencia entre cobertura importada y ranking de la última semana. -- El resumen del servidor es más honesto y comprensible. -- El backend expone metadatos suficientes para soportar esa claridad. -- Los cambios quedan committeados y se hace push al remoto si el entorno lo permite. - -## Change Budget -- Preferir menos de 6 archivos modificados o creados. -- Preferir menos de 220 líneas cambiadas. diff --git a/ai/tasks/done/TASK-034-real-a2s-target-onboarding-comunidad-hispana-02.md b/ai/tasks/done/TASK-034-real-a2s-target-onboarding-comunidad-hispana-02.md deleted file mode 100644 index 31aac2b..0000000 --- a/ai/tasks/done/TASK-034-real-a2s-target-onboarding-comunidad-hispana-02.md +++ /dev/null @@ -1,72 +0,0 @@ -# TASK-034-real-a2s-target-onboarding-comunidad-hispana-02 - -## Goal -Dar de alta el segundo target A2S real verificado del proyecto, correspondiente a Comunidad Hispana #02, integrándolo en la configuración del backend de forma clara, mantenible y coherente con el target real ya existente de Comunidad Hispana #01. - -## Context -El backend ya tiene onboarding real de Comunidad Hispana #01 y se ha validado la separación entre `game_port` y `query_port`. Ahora también se ha verificado un segundo servidor real: -- Comunidad Hispana #02 -- Host/IP: `152.114.195.150` -- Game Port: `7877` -- Query Port: `7878` - -La task debe incorporarlo correctamente a la configuración sin introducir ambigüedades entre puertos ni mezclarlo con fuentes no verificadas. - -## Steps -1. Revisar la configuración actual de targets A2S. -2. Añadir Comunidad Hispana #02 con: - - nombre amigable claro - - host/IP: `152.114.195.150` - - query port: `7878` - - game port: `7877` - - contexto o etiqueta coherente con el proyecto -3. Mantener la configuración desacoplada y limpia. -4. Documentar el alta del nuevo target en el backend. -5. Verificar que el target anterior (#01) sigue correcto y sin regresiones. -6. Mantener el cambio acotado a onboarding de target real. - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- ai/architecture-index.md -- backend/README.md -- backend/app/config.py -- backend/app/server_targets.py -- backend/app/collector.py -- backend/app/a2s_client.py - -## Expected Files to Modify -- backend/README.md -- backend/app/server_targets.py -- backend/app/config.py -- opcionalmente backend/app/collector.py si necesita una alineación menor - -## Constraints -- No tocar frontend. -- No añadir targets no verificados. -- No confundir `game_port` con `query_port`. -- No añadir scraping. -- No hacer cambios destructivos. -- Mantener la configuración simple y clara. - -## Validation -- El backend contiene el target real de Comunidad Hispana #02 correctamente registrado. -- El query port configurado es `7878`. -- El game port registrado es `7877`. -- La documentación deja claro cómo está definido este target. -- No se ha roto el target existente de Comunidad Hispana #01. - -## Change Budget -- Preferir menos de 4 archivos modificados. -- Preferir menos de 140 líneas cambiadas. -## Outcome -- `backend/app/server_targets.py` registra `Comunidad Hispana #02` junto a `#01` con `host`, `query_port`, `game_port` y `external_server_id` verificados. -- `backend/README.md` documenta ambos targets reales por defecto y mantiene separada la semantica de `query_port` frente a `game_port`. -- No fue necesario tocar `backend/app/config.py` ni `backend/app/collector.py` porque la configuracion existente ya consume el registro de forma desacoplada. - -## Validation Result -- Ejecutado desde `backend/`: `python -c "from app.server_targets import load_a2s_targets; print([(t.name, t.host, t.query_port, t.game_port, t.external_server_id) for t in load_a2s_targets()])"`. -- Resultado: el registro carga `Comunidad Hispana #01` y `Comunidad Hispana #02` con `query_port=7778/7878` y `game_port=7777/7877` respectivamente. - -## Decision Notes -- Se mantiene un unico `source_name` para la misma familia de servidores reales porque la distincion operativa ya queda en `external_server_id`, host y puertos. diff --git a/ai/tasks/done/TASK-035-historical-recent-matches-api.md b/ai/tasks/done/TASK-035-historical-recent-matches-api.md deleted file mode 100644 index 69364b8..0000000 --- a/ai/tasks/done/TASK-035-historical-recent-matches-api.md +++ /dev/null @@ -1,68 +0,0 @@ -# TASK-035-historical-recent-matches-api - -## Goal -Exponer una API histórica para consultar partidas recientes por servidor usando el histórico persistido propio del proyecto. - -## Context -Tras tener almacenamiento histórico y validación de datos, la siguiente métrica útil además del ranking semanal es la consulta de partidas recientes. Esto permitirá construir después vistas más completas del histórico sin depender de la web externa de la comunidad. - -## Steps -1. Revisar el modelo histórico persistido y los datos realmente disponibles por partida. -2. Diseñar un endpoint o conjunto mínimo de endpoints para devolver partidas recientes por servidor. -3. Incluir en el payload, como mínimo: - - servidor - - match_id o identificador interno/externo útil - - fecha/hora - - mapa - - resultado o metadato de cierre si está disponible - - total de jugadores o metadatos útiles si existen -4. Definir orden, límites y paginación básica si encaja con la fase actual. -5. Documentar el endpoint en backend. -6. No crear todavía UI nueva en esta task. -7. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- backend/README.md -- backend/app/routes.py -- backend/app/payloads.py -- backend/app/historical_storage.py -- backend/app/historical_models.py -- docs/historical-domain-model.md - -## Expected Files to Modify -- backend/app/routes.py -- backend/app/payloads.py -- backend/README.md -- opcionalmente nuevos módulos de query histórica, por ejemplo: - - backend/app/historical_queries.py - - backend/app/historical_payloads.py - -## Constraints -- No usar A2S para esta API. -- No crear UI en esta task. -- No depender del HTML de la comunidad. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en una API histórica propia y clara. - -## Validation -- Existe un endpoint usable de partidas recientes por servidor. -- El payload es claro y reutilizable. -- No se rompe la capa histórica existente. -- Los cambios quedan committeados y se hace push al remoto si el entorno lo permite. - -## Change Budget -- Preferir menos de 5 archivos modificados o creados. -- Preferir menos de 220 líneas cambiadas. -## Outcome -- Se expuso `GET /api/historical/recent-matches`. -- El payload devuelve servidor, `match_id`, cierre temporal, mapa, marcador, ganador y conteo de jugadores. -- La consulta se apoya solo en la persistencia histórica propia (`historical_*`). -- La documentación del endpoint quedó actualizada en `backend/README.md`. - -## Validation Notes -- `python -m compileall app` -- comprobación local de payload con `build_recent_historical_matches_payload(limit=3, server_slug='comunidad-hispana-01')` diff --git a/ai/tasks/done/TASK-035-historical-ui-after-bootstrap-review.md b/ai/tasks/done/TASK-035-historical-ui-after-bootstrap-review.md deleted file mode 100644 index 6bd5507..0000000 --- a/ai/tasks/done/TASK-035-historical-ui-after-bootstrap-review.md +++ /dev/null @@ -1,71 +0,0 @@ -# TASK-035-historical-ui-after-bootstrap-review - -## Goal -Revisar y ajustar la UI histórica propia del proyecto una vez que el bootstrap histórico completo y la semántica de cobertura estén resueltos, para asegurar que el resultado final sea visualmente claro, útil y coherente con el resto del producto. - -## Context -La UI histórica ya existe, pero fue construida antes de confirmar que la cobertura histórica completa estuviera realmente cargada y antes de clarificar suficientemente la semántica entre resumen y ranking semanal. Una vez el histórico esté bien poblado y la capa semántica corregida, hace falta una pasada de revisión específica sobre la experiencia visual e informativa de la página histórica. - -## Steps -1. Revisar la UI histórica actual después del bootstrap completo y de los ajustes de semántica/cobertura. -2. Validar el comportamiento visual y de contenido de: - - resumen de servidor - - ranking semanal - - selector de servidor - - estado vacío/error/carga - - cualquier otro bloque histórico ya presente -3. Comprobar si el volumen real de datos cambia la lectura de la interfaz y obliga a reajustar: - - textos - - jerarquía - - espaciado - - orden de secciones - - presentación de métricas -4. Corregir defectos pequeños o medianos detectados en esta revisión. -5. Asegurar que la UI histórica: - - sea comprensible - - no sobreinterprete los datos - - mantenga coherencia visual con la landing -6. No abrir todavía nuevas features históricas grandes en esta task. -7. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- ai/architecture-index.md -- docs/historical-data-quality-notes.md -- docs/historical-coverage-report.md -- backend/app/routes.py -- backend/app/payloads.py -- frontend/historico.html -- frontend/assets/js/historico.js -- frontend/assets/css/historico.css -- frontend/index.html -- frontend/assets/css/styles.css - -## Expected Files to Modify -- frontend/historico.html -- frontend/assets/js/historico.js -- frontend/assets/css/historico.css -- opcionalmente frontend/index.html o frontend/assets/css/styles.css si hace falta un ajuste menor de acceso o coherencia visual -- opcionalmente documentación mínima si algún comportamiento visible necesita quedar reflejado - -## Constraints -- No crear nuevas páginas basadas en URLs externas. -- No abrir nuevas grandes features históricas. -- No romper la UI histórica existente. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en revisión final, claridad y pulido después del bootstrap real. - -## Validation -- La UI histórica refleja correctamente el histórico ya poblado. -- La presentación del resumen y del ranking es clara. -- La experiencia visual es coherente con el resto del proyecto. -- No se detectan malentendidos graves entre cobertura histórica y ranking semanal. -- Los cambios quedan committeados y se hace push al remoto si el entorno lo permite. - -## Change Budget -- Preferir menos de 5 archivos modificados o creados. -- Preferir menos de 200 líneas cambiadas. diff --git a/ai/tasks/done/TASK-035-real-a2s-capture-validation-comunidad-hispana-02.md b/ai/tasks/done/TASK-035-real-a2s-capture-validation-comunidad-hispana-02.md deleted file mode 100644 index e4a385c..0000000 --- a/ai/tasks/done/TASK-035-real-a2s-capture-validation-comunidad-hispana-02.md +++ /dev/null @@ -1,80 +0,0 @@ -# TASK-035-real-a2s-capture-validation-comunidad-hispana-02 - -## Goal -Validar una captura A2S real extremo a extremo contra Comunidad Hispana #02, confirmando que el colector puede consultar el servidor, normalizar la respuesta y persistir snapshots útiles junto a los ya existentes de Comunidad Hispana #01. - -## Context -El proyecto ya ha validado el flujo real A2S con Comunidad Hispana #01. Ahora se ha verificado un segundo servidor real de Comunidad Hispana con: -- Host/IP: `152.114.195.150` -- Query Port: `7878` -- Game Port: `7877` - -El objetivo es confirmar que el pipeline soporta múltiples targets reales y que la persistencia y los endpoints históricos siguen siendo coherentes. - -## Steps -1. Revisar la configuración actual de targets A2S y el target recién añadido para Comunidad Hispana #02. -2. Ejecutar el colector o flujo equivalente contra este target real. -3. Confirmar que el backend consulta correctamente el host `152.114.195.150` con query port `7878`. -4. Validar que la respuesta A2S obtenida se normaliza al modelo interno. -5. Persistir al menos un snapshot real de Comunidad Hispana #02 en la base local actual. -6. Verificar que los endpoints históricos reflejan este nuevo servidor junto al ya existente. -7. Revisar el comportamiento si la consulta falla, timeout o devuelve datos parciales. -8. Actualizar la documentación mínima necesaria sobre cómo repetir esta validación en local. -9. Mantener el alcance centrado en validación del flujo real, no en nuevas features. - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- ai/architecture-index.md -- backend/README.md -- backend/app/a2s_client.py -- backend/app/server_targets.py -- backend/app/collector.py -- backend/app/normalizers.py -- backend/app/snapshots.py -- backend/app/storage.py -- backend/app/routes.py -- backend/app/payloads.py - -## Expected Files to Modify -- backend/README.md -- backend/app/collector.py -- backend/app/normalizers.py -- backend/app/storage.py -- backend/app/routes.py -- backend/app/payloads.py -- opcionalmente otros archivos backend si son estrictamente necesarios para soportar mejor múltiples targets reales - -## Constraints -- No tocar frontend salvo que una referencia mínima fuera imprescindible para mostrar el nuevo target una vez persistido. -- No añadir analítica avanzada. -- No añadir scraping de terceros. -- No introducir complejidad innecesaria. -- No hacer cambios destructivos. -- Mantener la validación centrada en Comunidad Hispana #02 y coexistencia con #01. - -## Validation -- Se realiza una captura real A2S sobre Comunidad Hispana #02. -- Se persiste al menos un snapshot real en la base local. -- El flujo real queda documentado y es repetible en local. -- Los endpoints históricos reflejan ambos targets reales cuando existan snapshots. -- Los errores de consulta están razonablemente manejados. - -## Change Budget -- Preferir menos de 6 archivos modificados. -- Preferir menos de 180 líneas cambiadas. -## Outcome -- `backend/app/a2s_client.py` eleva el timeout A2S por defecto de `3.0s` a `6.0s` para reducir timeouts transitorios al consultar varios targets reales seguidos. -- `backend/README.md` documenta la validacion local extremo a extremo con ambos targets reales por defecto y el resultado esperado cuando responden `#01` y `#02`. -- No fue necesario cambiar `collector.py`, `normalizers.py`, `storage.py`, `routes.py` ni `payloads.py` porque el pipeline ya normalizaba, persistia y exponia historico multi-target correctamente. - -## Validation Result -- Ejecutado desde `backend/`: `python -m app.a2s_client 152.114.195.150 7878 --timeout 6`. -- Resultado: respuesta valida de `Comunidad Hispana #02` con `server_name=#02 [ESP] Comunidad Hispana - discord.comunidadhll.es - Spa Onl`, `map_name=StMarie`, `players=0`, `max_players=100`. -- Ejecutado desde `backend/`: `python -m app.collector --source a2s --no-fallback`. -- Resultado: `target_count: 2`, `success_count: 2`, snapshots persistidos para `comunidad-hispana-01` y `comunidad-hispana-02` en `backend/data/hll_vietnam_dev.sqlite3`. -- Ejecutado desde `backend/`: `python -c "from app.payloads import build_server_history_payload, build_server_detail_history_payload; ..."` para revisar historico. -- Resultado: `/api/servers/history` refleja ambos targets reales y `/api/servers/comunidad-hispana-02/history` devuelve el snapshot persistido de `#02`. - -## Decision Notes -- Se ajusta el timeout por defecto en lugar de introducir reintentos o complejidad adicional porque la captura ya era funcional y el problema observado fue de sensibilidad temporal, no de arquitectura. diff --git a/ai/tasks/done/TASK-036-hide-placeholders-when-real-servers-exist-and-localize-connect-label.md b/ai/tasks/done/TASK-036-hide-placeholders-when-real-servers-exist-and-localize-connect-label.md deleted file mode 100644 index 0701529..0000000 --- a/ai/tasks/done/TASK-036-hide-placeholders-when-real-servers-exist-and-localize-connect-label.md +++ /dev/null @@ -1,73 +0,0 @@ -# TASK-036-hide-placeholders-when-real-servers-exist-and-localize-connect-label - -## Goal -Ajustar el panel de servidores para ocultar los placeholders o referencias provisionales cuando ya existan snapshots reales A2S utilizables, y cambiar la etiqueta visible del botón de conexión de “Connect” a “Conectar”. - -## Context -La landing ya muestra snapshots reales A2S de Comunidad Hispana #01 y #02. En este punto, mantener visibles los placeholders como bloque principal o paralelo degrada la claridad del producto y da una sensación de estado provisional que ya no corresponde al nivel real del sistema. Los placeholders deben quedar como fallback técnico, no como contenido normal cuando haya datos reales disponibles. Además, la CTA visible de conexión debe localizarse al español. - -## Steps -1. Revisar el render actual del panel de servidores en frontend. -2. Identificar la lógica que separa: - - snapshots `real-a2s` - - snapshots históricos persistidos - - placeholders o `controlled-fallback` -3. Ajustar la lógica para que: - - si existen snapshots reales A2S utilizables, solo se muestren esos servidores reales en la vista principal - - los placeholders queden ocultos en la vista normal - - el fallback provisional solo se muestre cuando no existan datos reales o el backend no aporte snapshots utilizables -4. Mantener clara la procedencia del dato real sin sobrecargar la UI. -5. Cambiar la etiqueta visible del botón de conexión de: - - `Connect` - a: - - `Conectar` -6. Mantener intacto el uso técnico del enlace `steam://connect/:`. -7. Revisar el copy mínimo del bloque para que encaje con una fase más madura del producto. -8. Mantener el ajuste visual contenido, sin rediseñar toda la landing. - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- frontend/index.html -- frontend/assets/js/main.js -- frontend/assets/css/styles.css -- backend/app/payloads.py -- backend/app/routes.py - -## Expected Files to Modify -- frontend/index.html -- frontend/assets/js/main.js -- frontend/assets/css/styles.css - -## Constraints -- No tocar backend salvo referencia documental mínima si fuera imprescindible. -- No romper el fallback cuando no haya datos reales. -- No quitar soporte para placeholders a nivel interno; solo ocultarlos cuando existan snapshots reales utilizables. -- No añadir librerías nuevas. -- No hacer cambios destructivos. -- Mantener el ajuste centrado en claridad de producto y localización de la CTA. - -## Validation -- Cuando existen snapshots `real-a2s`, la vista principal del panel muestra solo servidores reales. -- Los placeholders ya no aparecen en la vista normal si hay datos reales disponibles. -- Si no hay datos reales, el fallback sigue funcionando. -- El botón visible muestra “Conectar”. -- La landing gana claridad visual y semántica. - -## Change Budget -- Preferir menos de 3 archivos modificados. -- Preferir menos de 140 líneas cambiadas. - -## Outcome -- `frontend/assets/js/main.js` filtra la vista principal del panel para mostrar solo snapshots `real-a2s` cuando existen, manteniendo el fallback persistido solo para escenarios sin capturas reales utilizables. -- `frontend/assets/js/main.js` localiza la CTA visible de conexión a `Conectar` sin alterar el esquema técnico `steam://connect/:`. -- `frontend/index.html` y `frontend/assets/css/styles.css` ajustan el copy y la presentación base del bloque para que el estado por defecto sea más neutro y menos provisional. - -## Validation Result -- Ejecutado: `node --check frontend/assets/js/main.js`. -- Resultado: sintaxis JavaScript válida tras el ajuste de filtrado y localización. -- Revisado en código: la vista enriquecida usa `selectPrimaryServerItems(...)`, por lo que los placeholders quedan ocultos cuando hay snapshots reales y el fallback sigue siendo la ruta visible si no existen capturas reales utilizables. -- Revisado en código: la CTA visible del enlace de conexión muestra `Conectar`. - -## Decision Notes -- La ocultación de placeholders se resolvió en la capa de selección de items visibles, sin tocar backend ni eliminar soporte interno de fallback. diff --git a/ai/tasks/done/TASK-036-historical-page-branding-and-copy-cleanup.md b/ai/tasks/done/TASK-036-historical-page-branding-and-copy-cleanup.md deleted file mode 100644 index 92cd321..0000000 --- a/ai/tasks/done/TASK-036-historical-page-branding-and-copy-cleanup.md +++ /dev/null @@ -1,71 +0,0 @@ -# TASK-036-historical-page-branding-and-copy-cleanup - -## Goal -Pulir la página histórica propia del proyecto en branding y copy, eliminando formulaciones que suenan técnicas o poco naturales, añadiendo el logo de la comunidad y reforzando la coherencia visual con la landing principal. - -## Context -La página histórica ya es funcional y útil, pero hay varios ajustes de acabado que mejorarían claramente la percepción del producto: -- eliminar la palabra `táctico` del hero de la página histórica -- añadir el logo de la comunidad también en esta página -- sustituir formulaciones con `importado` por textos más naturales como `registrado` o `registradas` -- mantener la coherencia visual con la landing principal - -Estos cambios son de UX/copy/branding y no deben alterar la arquitectura histórica ya construida. - -## Steps -1. Revisar la página histórica actual y su hero. -2. Eliminar o reformular el texto del hero para quitar la palabra `táctico`. -3. Añadir el logo de la comunidad en la página histórica usando la ruta de asset local ya establecida por el proyecto. -4. Revisar todos los textos visibles relacionados con cobertura o datos históricos y sustituir las referencias a: - - `importado` - - `importada` - - `importados` - - `importadas` - por formulaciones más naturales y adecuadas, preferentemente: - - `registrado` - - `registrada` - - `registrados` - - `registradas` - o equivalentes mejores si encajan más naturalmente con la UI. -5. Revisar que los nuevos textos no rompan layout, cards, badges o títulos. -6. Mantener la estética coherente con la landing y con la identidad actual del proyecto. -7. No introducir todavía nuevas métricas ni nuevas pestañas en esta task. -8. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- frontend/historico.html -- frontend/assets/css/historico.css -- frontend/assets/js/historico.js -- frontend/index.html -- frontend/assets/css/styles.css -- ai/repo-context.md - -## Expected Files to Modify -- frontend/historico.html -- frontend/assets/css/historico.css -- frontend/assets/js/historico.js -- opcionalmente frontend/assets/img/logo.png si solo hace falta referenciarlo correctamente, no reemplazarlo -- opcionalmente documentación mínima si hubiera un cambio visible que merezca reflejarse - -## Constraints -- No cambiar la arquitectura de la página histórica. -- No crear páginas externas o dependientes de la comunidad. -- No romper la UI histórica existente. -- No introducir librerías nuevas. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en branding, copy y acabado. - -## Validation -- La palabra `táctico` desaparece del hero histórico. -- El logo de la comunidad aparece correctamente en la página histórica. -- Los textos visibles dejan de sonar técnicos o artificiales por el uso de `importado`. -- La página sigue siendo coherente visualmente con la landing. -- Los cambios quedan committeados y se hace push al remoto si el entorno lo permite. - -## Change Budget -- Preferir menos de 4 archivos modificados. -- Preferir menos de 180 líneas cambiadas. diff --git a/ai/tasks/done/TASK-036-historical-recent-matches-ui.md b/ai/tasks/done/TASK-036-historical-recent-matches-ui.md deleted file mode 100644 index 9bd76f6..0000000 --- a/ai/tasks/done/TASK-036-historical-recent-matches-ui.md +++ /dev/null @@ -1,67 +0,0 @@ -# TASK-036-historical-recent-matches-ui - -## Goal -Añadir a la UI histórica propia del proyecto una vista o bloque de partidas recientes por servidor, consumiendo exclusivamente la API interna del backend. - -## Context -La primera UI histórica del proyecto debe crecer de forma progresiva. Tras el ranking semanal, el siguiente bloque lógico es una vista de partidas recientes que complemente el histórico y aporte más contexto al usuario. - -## Steps -1. Revisar la UI histórica ya implementada o diseñada en la task previa. -2. Revisar el endpoint de partidas recientes y su payload. -3. Añadir una sección o vista clara para mostrar partidas recientes por servidor. -4. Mostrar, como mínimo: - - fecha/hora - - mapa - - servidor - - metadatos relevantes si están disponibles -5. Mantener la navegación y el selector de servidor claros. -6. Añadir estados de loading, empty y error para esta vista. -7. Mantener coherencia visual con el resto del frontend histórico. -8. No usar páginas de la comunidad ni incrustaciones externas. -9. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- frontend/historico.html -- frontend/assets/js/historico.js -- frontend/assets/css/historico.css -- backend/app/routes.py -- backend/app/payloads.py -- docs/historical-domain-model.md - -## Expected Files to Modify -- frontend/historico.html -- frontend/assets/js/historico.js -- frontend/assets/css/historico.css -- opcionalmente frontend/index.html si se mejora el acceso a la zona histórica - -## Constraints -- No usar UI externa de la comunidad. -- No introducir frameworks nuevos. -- No romper la landing actual. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en ampliar la UI histórica propia. - -## Validation -- La UI histórica muestra partidas recientes por servidor. -- La UI consume exclusivamente la API interna. -- Existen estados de carga, vacío y error. -- La interfaz sigue siendo coherente con el resto del proyecto. -- Los cambios quedan committeados y se hace push al remoto si el entorno lo permite. - -## Change Budget -- Preferir menos de 5 archivos modificados o creados. -- Preferir menos de 240 líneas cambiadas. -## Outcome -- La UI histórica propia ahora muestra un bloque de partidas recientes por servidor. -- El bloque usa exclusivamente `GET /api/historical/recent-matches`. -- El selector de servidor se comparte con el ranking semanal para mantener consistencia. -- Se cubrieron estados de carga, vacío y error para esta vista. - -## Validation Notes -- `node --check frontend/assets/js/historico.js` -- revisión manual de la estructura HTML/CSS para desktop y mobile diff --git a/ai/tasks/done/TASK-037-historical-multi-metric-leaderboards-api.md b/ai/tasks/done/TASK-037-historical-multi-metric-leaderboards-api.md deleted file mode 100644 index 9045090..0000000 --- a/ai/tasks/done/TASK-037-historical-multi-metric-leaderboards-api.md +++ /dev/null @@ -1,85 +0,0 @@ -# TASK-037-historical-multi-metric-leaderboards-api - -## Goal -Extender la capa histórica del backend para soportar varios rankings semanales por servidor, no solo top kills, de modo que la UI pueda mostrar pestañas con diferentes métricas relevantes. - -## Context -La página histórica ya muestra un ranking semanal de kills, pero se quiere evolucionar hacia una sección con varias pestañas o vistas de ranking para el mismo rango temporal. Las métricas solicitadas inicialmente son: -- Top kills -- Top muertes -- Top número de partidas con más de 100 kills (a nivel de jugador) -- Top puntos de soporte - -Para que la UI pueda hacerlo de forma limpia, primero hace falta una API histórica más flexible y consistente. - -## Steps -1. Revisar la implementación actual del endpoint de `weekly-top-kills`. -2. Revisar el modelo histórico persistido y confirmar qué métricas están disponibles de forma fiable, especialmente: - - kills - - deaths - - support score / puntos de soporte - - kills por partida por jugador -3. Diseñar una estrategia de API para rankings históricos multitétrica. Puede ser: - - un endpoint genérico por métrica - - varios endpoints específicos - - o una solución equivalente siempre que sea clara y mantenible -4. Implementar soporte para estas métricas en la misma ventana temporal semanal: - - top kills - - top deaths - - top count of matches with kills >= 100 por jugador - - top support points -5. Asegurar que las queries: - - respetan el servidor seleccionado - - respetan el rango temporal semanal - - no mezclan datos entre servidores - - no devuelven duplicados por mala consolidación de identidad -6. Si alguna métrica requerida no estuviera siendo persistida todavía de forma válida, completar lo estrictamente necesario en la capa histórica para soportarla. -7. Documentar la nueva API en backend. -8. No crear todavía pestañas o cambios visuales en frontend en esta task. -9. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- backend/README.md -- backend/app/routes.py -- backend/app/payloads.py -- backend/app/historical_storage.py -- backend/app/historical_models.py -- backend/app/historical_ingestion.py -- docs/historical-domain-model.md -- docs/historical-data-quality-notes.md - -## Expected Files to Modify -- backend/app/routes.py -- backend/app/payloads.py -- backend/app/historical_storage.py -- backend/app/historical_models.py -- opcionalmente backend/app/historical_ingestion.py si hace falta completar la persistencia de alguna métrica necesaria -- backend/README.md -- opcionalmente nuevos módulos de query histórica si mejoran claridad - -## Constraints -- No basar estas métricas en A2S. -- No crear UI en esta task. -- No depender de páginas externas de la comunidad. -- No romper el endpoint histórico actual salvo para mejorarlo o generalizarlo. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en API histórica y consistencia de métricas. - -## Validation -- Existen rankings históricos semanales para: - - kills - - muertes - - partidas con más de 100 kills por jugador - - puntos de soporte -- Los rankings funcionan por servidor. -- Los rankings respetan la ventana semanal definida por el proyecto. -- La documentación backend queda alineada. -- Los cambios quedan committeados y se hace push al remoto si el entorno lo permite. - -## Change Budget -- Preferir menos de 7 archivos modificados o creados. -- Preferir menos de 260 líneas cambiadas. diff --git a/ai/tasks/done/TASK-037-historical-server-summary-api.md b/ai/tasks/done/TASK-037-historical-server-summary-api.md deleted file mode 100644 index 854277a..0000000 --- a/ai/tasks/done/TASK-037-historical-server-summary-api.md +++ /dev/null @@ -1,62 +0,0 @@ -# TASK-037-historical-server-summary-api - -## Goal -Exponer una API de resumen histórico por servidor que sirva como base para futuros bloques de overview y comparativas. - -## Context -Además de rankings y partidas recientes, el proyecto necesitará una capa resumida de datos por servidor para poder mostrar actividad agregada y métricas de alto nivel sin recalcularlas en el frontend. - -## Steps -1. Revisar el histórico persistido y las métricas disponibles de forma fiable. -2. Diseñar un endpoint de resumen por servidor con métricas agregadas útiles. Incluir, si es viable: - - número de partidas históricas - - número de jugadores únicos - - kills agregadas - - mapas más jugados o conteo de mapas - - rango temporal cubierto -3. Implementar el endpoint de forma clara y reutilizable. -4. Documentar el endpoint en backend. -5. No crear UI nueva en esta task. -6. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- backend/README.md -- backend/app/routes.py -- backend/app/payloads.py -- backend/app/historical_storage.py -- backend/app/historical_models.py -- docs/historical-domain-model.md - -## Expected Files to Modify -- backend/app/routes.py -- backend/app/payloads.py -- backend/README.md -- opcionalmente nuevos módulos de query histórica - -## Constraints -- No usar A2S para resumen histórico. -- No crear UI en esta task. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en una API agregada estable. - -## Validation -- Existe un endpoint de resumen histórico por servidor. -- El payload es claro y reutilizable. -- El endpoint se basa en el histórico propio persistido. -- Los cambios quedan committeados y se hace push al remoto si el entorno lo permite. - -## Change Budget -- Preferir menos de 5 archivos modificados o creados. -- Preferir menos de 220 líneas cambiadas. -## Outcome -- Se expuso `GET /api/historical/server-summary`. -- El endpoint agrega partidas históricas, jugadores únicos, kills, conteo de mapas, mapas dominantes y rango temporal cubierto. -- La consulta se resuelve desde la persistencia histórica propia y queda documentada en `backend/README.md`. - -## Validation Notes -- `python -m compileall app` -- comprobación local de payload con `build_historical_server_summary_payload(server_slug='comunidad-hispana-01')` diff --git a/ai/tasks/done/TASK-037-scheduled-local-snapshot-refresh.md b/ai/tasks/done/TASK-037-scheduled-local-snapshot-refresh.md deleted file mode 100644 index fd46489..0000000 --- a/ai/tasks/done/TASK-037-scheduled-local-snapshot-refresh.md +++ /dev/null @@ -1,62 +0,0 @@ -# TASK-037-scheduled-local-snapshot-refresh - -## Goal -Preparar una forma simple, clara y repetible de refrescar snapshots A2S reales de forma periódica en entorno local, reduciendo la dependencia de ejecución manual del colector. - -## Context -El proyecto ya dispone de cliente A2S, targets reales verificados, colector funcional, persistencia SQLite y visualización en frontend. Actualmente el flujo depende de lanzar manualmente el colector para actualizar snapshots. El siguiente paso útil es dejar preparado un mecanismo sencillo de refresco periódico local que permita validar mejor el comportamiento histórico y la evolución de los datos. - -## Steps -1. Revisar el flujo actual de captura manual de snapshots. -2. Definir una estrategia simple de refresco local, adecuada al estado actual del proyecto. -3. Preparar una forma clara de ejecutar capturas periódicas sin introducir infraestructura compleja de producción. -4. Mantener el diseño desacoplado para que en el futuro pueda reemplazarse por un scheduler más serio si hiciera falta. -5. Documentar cómo arrancar este refresco local y cómo detenerlo. -6. Si hace falta, añadir un modo seguro o flags para evitar comportamiento inesperado en desarrollo. -7. Mantener el alcance en refresco local y desarrollo, no en despliegue productivo. - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- backend/README.md -- backend/app/config.py -- backend/app/collector.py -- backend/app/server_targets.py -- backend/app/storage.py - -## Expected Files to Modify -- backend/README.md -- backend/app/config.py -- backend/app/collector.py -- opcionalmente archivos nuevos si mejoran claridad, por ejemplo: - - backend/app/scheduler.py - - backend/scripts/run_local_refresh.py - -## Constraints -- No tocar frontend. -- No introducir un sistema de colas o infraestructura pesada. -- No añadir complejidad innecesaria. -- No hacer cambios destructivos. -- Mantener la solución simple y enfocada a entorno local. - -## Validation -- Existe una forma documentada y funcional de refrescar snapshots periódicamente en local. -- El flujo sigue siendo controlable y fácil de detener. -- La solución encaja con el backend actual sin sobredimensionarlo. -- El sistema queda preparado para capturas más frecuentes y validación histórica. - -## Change Budget -- Preferir menos de 5 archivos modificados o creados. -- Preferir menos de 180 líneas cambiadas. -## Outcome -- `backend/app/scheduler.py` añade un bucle local de refresco periódico reutilizando el colector existente, sin introducir infraestructura de producción ni dependencias nuevas. -- `backend/app/config.py` centraliza el intervalo por defecto mediante `HLL_BACKEND_REFRESH_INTERVAL_SECONDS`. -- `backend/README.md` documenta cómo arrancar el refresco local, cómo detenerlo con `Ctrl+C` y qué flags de seguridad usar (`--interval`, `--no-fallback`, `--max-runs`). - -## Validation Result -- Ejecutado: `python -m app.scheduler --source controlled --interval 1 --max-runs 1` desde `backend/`. -- Resultado: se ejecutó un ciclo persistido correctamente sobre `backend/data/hll_vietnam_dev.sqlite3` y el proceso terminó al alcanzar el límite seguro de ejecuciones. -- Revisado en código: el refresco local queda desacoplado del servidor HTTP y reutiliza `collect_server_snapshots(...)` sin duplicar lógica del colector. - -## Decision Notes -- El refresco periódico se resolvió como un bucle local explícito y controlable para desarrollo, en lugar de introducir un scheduler embebido en el backend HTTP o infraestructura más pesada. diff --git a/ai/tasks/done/TASK-038-historical-leaderboards-tabs-ui.md b/ai/tasks/done/TASK-038-historical-leaderboards-tabs-ui.md deleted file mode 100644 index 18741da..0000000 --- a/ai/tasks/done/TASK-038-historical-leaderboards-tabs-ui.md +++ /dev/null @@ -1,72 +0,0 @@ -# TASK-038-historical-leaderboards-tabs-ui - -## Goal -Transformar la sección de ranking semanal de la página histórica en un bloque con pestañas, permitiendo alternar entre varios leaderboards semanales del servidor seleccionado. - -## Context -La UI histórica actual muestra un único ranking semanal de kills. El objetivo ahora es convertir esa zona en una sección con pestañas para poder consultar varias métricas sin recargar la página y manteniendo una experiencia clara. Las pestañas requeridas inicialmente son: -- Top kills -- Top muertes -- Top número de partidas con más de 100 kills -- Top puntos de soporte - -La UI debe seguir siendo propia del proyecto y consumir únicamente la API histórica interna. - -## Steps -1. Revisar la página histórica actual y el bloque de ranking semanal. -2. Revisar la nueva API histórica multitétrica disponible tras la task previa. -3. Diseñar un sistema de pestañas claro y coherente con el estilo de la web. -4. Implementar las pestañas para: - - Top kills - - Top muertes - - Top número de partidas con más de 100 kills - - Top puntos de soporte -5. Hacer que las pestañas reutilicen el servidor actualmente seleccionado. -6. Mantener estados de: - - loading - - vacío - - error -7. Ajustar títulos, subtítulos y labels de la sección para que sean claros y no sobrecarguen visualmente. -8. No usar páginas externas ni incrustaciones del scoreboard de la comunidad. -9. Mantener la coherencia visual con el resto de la página histórica y con la landing principal. -10. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- frontend/historico.html -- frontend/assets/js/historico.js -- frontend/assets/css/historico.css -- backend/app/routes.py -- backend/app/payloads.py -- backend/README.md - -## Expected Files to Modify -- frontend/historico.html -- frontend/assets/js/historico.js -- frontend/assets/css/historico.css -- opcionalmente documentación mínima si hay un cambio visible relevante en la navegación histórica - -## Constraints -- No crear nuevas páginas basadas en URLs externas. -- No romper la UI histórica actual fuera del bloque de ranking. -- No introducir frameworks nuevos. -- No hacer cambios destructivos. -- Mantener la solución centrada en pestañas, claridad y consumo de nuestra API. - -## Validation -- La sección de ranking semanal se convierte en un bloque con pestañas funcionales. -- Las pestañas muestran: - - Top kills - - Top muertes - - Top partidas con más de 100 kills - - Top puntos de soporte -- La UI consume únicamente la API interna del proyecto. -- El selector de servidor sigue funcionando con estas pestañas. -- Los cambios quedan committeados y se hace push al remoto si el entorno lo permite. - -## Change Budget -- Preferir menos de 5 archivos modificados. -- Preferir menos de 220 líneas cambiadas. diff --git a/ai/tasks/done/TASK-038-historical-player-profile-api-foundation.md b/ai/tasks/done/TASK-038-historical-player-profile-api-foundation.md deleted file mode 100644 index ef51b2d..0000000 --- a/ai/tasks/done/TASK-038-historical-player-profile-api-foundation.md +++ /dev/null @@ -1,65 +0,0 @@ -# TASK-038-historical-player-profile-api-foundation - -## Goal -Crear la base de API para perfiles históricos de jugador dentro del proyecto, apoyándose en el histórico propio ya persistido y preparando futuras vistas de detalle sin depender de páginas externas. - -## Context -Una vez resueltos rankings y partidas, el siguiente paso natural del histórico es poder profundizar por jugador. Esta task no debe construir todavía la UI completa de perfil, pero sí dejar lista una base de consulta que permita en fases posteriores mostrar el recorrido histórico de un jugador en los servidores de la comunidad. - -## Steps -1. Revisar la estructura actual de identidad de jugador validada en la task de calidad histórica. -2. Diseñar una base de endpoint o endpoints para consultar un jugador histórico. -3. Incluir, como mínimo, datos como: - - identidad de jugador - - servidor o servidores donde aparece - - kills agregadas - - número de partidas - - rango temporal cubierto -4. Implementar la consulta de forma consistente con la estructura histórica existente. -5. Documentar el endpoint en backend. -6. No crear todavía UI final de perfil. -7. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- backend/README.md -- backend/app/historical_storage.py -- backend/app/historical_models.py -- backend/app/routes.py -- backend/app/payloads.py -- docs/historical-data-quality-notes.md - -## Expected Files to Modify -- backend/app/routes.py -- backend/app/payloads.py -- backend/README.md -- opcionalmente nuevos módulos de query histórica por jugador - -## Constraints -- No usar páginas externas como perfil del producto. -- No crear UI final de perfil todavía. -- No romper endpoints históricos existentes. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en la base de API de perfil. - -## Validation -- Existe una base de endpoint para perfil histórico de jugador. -- El endpoint se apoya en la persistencia histórica propia. -- La identidad de jugador usada es consistente con la corrección de calidad ya realizada. -- Los cambios quedan committeados y se hace push al remoto si el entorno lo permite. - -## Change Budget -- Preferir menos de 5 archivos modificados o creados. -- Preferir menos de 220 líneas cambiadas. -## Outcome -- Se expuso `GET /api/historical/player-profile?player=...`. -- El endpoint acepta `stable_player_key`, `steam_id` o `source_player_id`. -- La respuesta devuelve identidad de jugador, kills agregadas, número de partidas, rango temporal y desglose por servidores. -- No se construyó UI final de perfil en esta task. - -## Validation Notes -- `python -m compileall app` -- comprobación local de payload reutilizando un `stable_player_key` real del ranking semanal diff --git a/ai/tasks/done/TASK-038-server-history-summary-cards.md b/ai/tasks/done/TASK-038-server-history-summary-cards.md deleted file mode 100644 index f5ef92b..0000000 --- a/ai/tasks/done/TASK-038-server-history-summary-cards.md +++ /dev/null @@ -1,72 +0,0 @@ -# TASK-038-server-history-summary-cards - -## Goal -Añadir al backend y al frontend una primera capa de métricas históricas resumidas para los servidores reales, de forma que el panel muestre información más útil que el simple último snapshot. - -## Context -La web ya muestra snapshots reales A2S y dispone de histórico persistido. Sin embargo, el valor actual del panel sigue siendo limitado si solo enseña la última captura y una tendencia básica. El siguiente paso lógico es construir resúmenes históricos ligeros a partir de lo ya almacenado, sin convertir aún la landing en un dashboard complejo. - -## Steps -1. Revisar los endpoints históricos actuales y el panel de servidores existente. -2. Identificar qué métricas históricas resumidas son viables con los snapshots ya persistidos, por ejemplo: - - última vez visto online - - número de capturas recientes - - promedio reciente de jugadores - - valor máximo reciente de población - - tiempo desde la última captura -3. Añadir la capa mínima necesaria en backend para exponer estas métricas de forma clara. -4. Integrar esas métricas en las tarjetas de servidores reales del frontend. -5. Mantener la mejora ligera y coherente con el diseño actual. -6. No introducir cálculos pesados ni analítica compleja. -7. Preservar el comportamiento correcto si aún hay pocos snapshots disponibles. - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- backend/README.md -- backend/app/routes.py -- backend/app/payloads.py -- backend/app/storage.py -- frontend/index.html -- frontend/assets/js/main.js -- frontend/assets/css/styles.css - -## Expected Files to Modify -- backend/app/routes.py -- backend/app/payloads.py -- backend/app/storage.py -- frontend/index.html -- frontend/assets/js/main.js -- frontend/assets/css/styles.css - -## Constraints -- No rediseñar toda la landing. -- No añadir gráficas complejas. -- No introducir librerías nuevas. -- No romper el fallback actual. -- No hacer cambios destructivos. -- Mantener la mejora centrada en valor histórico resumido. - -## Validation -- El backend expone métricas históricas resumidas útiles para servidores reales. -- El frontend las muestra de forma clara y legible. -- La UI sigue funcionando aunque el histórico disponible sea limitado. -- El panel gana valor funcional sin perder claridad. - -## Change Budget -- Preferir menos de 6 archivos modificados. -- Preferir menos de 220 líneas cambiadas. -## Outcome -- `backend/app/storage.py` adjunta a cada snapshot más reciente un `history_summary` ligero con capturas recientes, promedio de jugadores, pico, última vez visto online y minutos desde la última captura. -- `backend/app/payloads.py` expone esas métricas en `GET /api/servers/latest` sin abrir un endpoint nuevo. -- `frontend/assets/js/main.js` integra las métricas resumidas en las tarjetas reales e históricas ya renderizadas por la landing. -- `frontend/assets/css/styles.css` añade el bloque visual compacto para mostrar esos resúmenes sin convertir la landing en un dashboard pesado. - -## Validation Result -- Ejecutado: import directo de `build_server_latest_payload()` desde `backend/`. -- Resultado: el payload devuelve `history_summary` por servidor con valores coherentes incluso cuando hay pocas capturas disponibles. -- Ejecutado: `node --check frontend/assets/js/main.js`. -- Resultado: sintaxis JavaScript válida tras integrar el bloque de métricas resumidas. - -## Decision Notes -- Las métricas históricas resumidas se calculan sobre una ventana corta de snapshots recientes y se entregan junto al payload de último estado para mantener el backend simple y evitar analítica o endpoints adicionales en esta fase. diff --git a/ai/tasks/done/TASK-039-community-clans-section-on-landing.md b/ai/tasks/done/TASK-039-community-clans-section-on-landing.md deleted file mode 100644 index 5de1b5b..0000000 --- a/ai/tasks/done/TASK-039-community-clans-section-on-landing.md +++ /dev/null @@ -1,62 +0,0 @@ -# TASK-039-community-clans-section-on-landing - -## Goal -Añadir una nueva sección en la página principal para mostrar clanes/comunidades aliadas o relacionadas, con sus logos y un enlace hacia sus respectivos Discords. - -## Context -Además de los servidores y del histórico, se quiere que la home tenga una sección específica de clanes donde puedan verse logos representativos y un link hacia cada Discord. Esta sección debe integrarse en la landing sin romper su simplicidad ni convertirse en un directorio desordenado. - -## Steps -1. Revisar la landing actual y decidir una ubicación razonable para la nueva sección de clanes. -2. Diseñar una sección clara y visualmente coherente con el resto de la home. -3. Preparar una estructura de datos simple y mantenible para los clanes mostrados, por ejemplo: - - nombre - - logo - - enlace Discord - - descripción breve opcional -4. Implementar la sección mostrando al menos: - - logo de cada clan - - nombre - - botón o link claro hacia su Discord -5. Mantener la solución suficientemente flexible para añadir o quitar clanes más adelante sin reescribir la sección completa. -6. Asegurar que la sección funciona bien en escritorio y móvil. -7. No incrustar widgets completos de Discord salvo que ya estén expresamente aprobados; en esta task basta con enlaces claros al servidor Discord. -8. Mantener la landing limpia y visualmente consistente. -9. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- frontend/index.html -- frontend/assets/css/styles.css -- frontend/assets/js/main.js -- ai/repo-context.md - -## Expected Files to Modify -- frontend/index.html -- frontend/assets/css/styles.css -- frontend/assets/js/main.js -- opcionalmente un archivo de datos/config simple en frontend si mejora claridad, por ejemplo: - - frontend/assets/js/community-clans.js -- opcionalmente assets de logos si se dejan preparados o referenciados correctamente - -## Constraints -- No romper la landing actual. -- No recargar la home con demasiada información. -- No depender de páginas externas como iframes para esta sección. -- No introducir frameworks nuevos. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en una sección limpia, visual y fácil de mantener. - -## Validation -- Existe una nueva sección de clanes en la página principal. -- Cada clan mostrado tiene logo y enlace claro a su Discord. -- La sección es coherente con el estilo de la landing. -- La estructura permite mantener y ampliar la lista de clanes razonablemente. -- Los cambios quedan committeados y se hace push al remoto si el entorno lo permite. - -## Change Budget -- Preferir menos de 5 archivos modificados o creados. -- Preferir menos de 240 líneas cambiadas. diff --git a/ai/tasks/done/TASK-039-historical-navigation-and-entry-points.md b/ai/tasks/done/TASK-039-historical-navigation-and-entry-points.md deleted file mode 100644 index f002923..0000000 --- a/ai/tasks/done/TASK-039-historical-navigation-and-entry-points.md +++ /dev/null @@ -1,58 +0,0 @@ -# TASK-039-historical-navigation-and-entry-points - -## Goal -Añadir puntos de entrada y navegación razonables hacia la zona histórica propia del proyecto sin romper la simplicidad actual de la landing. - -## Context -Si el proyecto empieza a tener una UI histórica propia, hace falta que el usuario pueda llegar a ella con una navegación clara. Esta task debe resolver ese acceso sin convertir la landing en una aplicación compleja ni depender de enlaces a páginas externas de la comunidad. - -## Steps -1. Revisar la landing actual y la UI histórica creada. -2. Diseñar uno o más puntos de entrada razonables hacia la zona histórica propia. -3. Añadir enlaces o CTAs discretos y coherentes para acceder al histórico. -4. Mantener la simplicidad de la landing. -5. No sustituir los botones `Histórico` actuales del panel de servidores si siguen teniendo sentido como acceso al scoreboard externo; solo añadir navegación propia del proyecto donde aporte valor. -6. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- frontend/index.html -- frontend/assets/css/styles.css -- frontend/assets/js/main.js -- frontend/historico.html -- frontend/assets/css/historico.css -- frontend/assets/js/historico.js - -## Expected Files to Modify -- frontend/index.html -- frontend/assets/css/styles.css -- opcionalmente frontend/assets/js/main.js -- opcionalmente la propia UI histórica si requiere ajustes de navegación - -## Constraints -- No recargar la landing con demasiada navegación. -- No romper la landing actual. -- No depender de URLs de la comunidad como navegación principal del producto. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en accesos claros y ligeros. - -## Validation -- Existe una forma clara de acceder a la zona histórica propia. -- La landing mantiene su simplicidad. -- No se rompe el flujo actual de usuario. -- Los cambios quedan committeados y se hace push al remoto si el entorno lo permite. - -## Change Budget -- Preferir menos de 4 archivos modificados. -- Preferir menos de 160 líneas cambiadas. -## Outcome -- Se añadieron CTAs discretos hacia `frontend/historico.html` en la hero y en el panel de servidores. -- Se añadió un enlace de vuelta desde la vista histórica a la landing. -- Se preservaron los botones actuales `Historico` hacia scoreboards externos en las cards de servidores. - -## Validation Notes -- revisión de `frontend/index.html` y `frontend/assets/css/styles.css` para mantener simplicidad y coherencia visual -- `node --check frontend/assets/js/historico.js` diff --git a/ai/tasks/done/TASK-039-real-server-panel-data-density-pass.md b/ai/tasks/done/TASK-039-real-server-panel-data-density-pass.md deleted file mode 100644 index a99506d..0000000 --- a/ai/tasks/done/TASK-039-real-server-panel-data-density-pass.md +++ /dev/null @@ -1,67 +0,0 @@ -# TASK-039-real-server-panel-data-density-pass - -## Goal -Mejorar la densidad informativa y la claridad de las tarjetas de servidores reales, aprovechando mejor los datos ya disponibles sin recargar visualmente la landing. - -## Context -Tras ocultar los placeholders cuando existen snapshots reales y preparar una CTA de conexión en español, el panel real ya tiene buena base. Sin embargo, todavía puede ganar valor mostrando mejor la información disponible y organizando mejor la jerarquía interna de las tarjetas. - -## Steps -1. Revisar la composición actual de las tarjetas de servidores reales. -2. Revisar qué datos ya están disponibles o pasarán a estar disponibles tras la task de resúmenes históricos. -3. Mejorar la jerarquía interna de cada tarjeta: - - nombre - - estado - - mapa - - jugadores - - región - - última captura - - CTA - - métricas resumidas si existen -4. Hacer que la tarjeta transmita más información útil sin volverse pesada. -5. Mantener coherencia visual con la landing actual. -6. Mejorar legibilidad en desktop y móvil. -7. No rediseñar toda la página ni añadir nuevas secciones grandes. - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- frontend/index.html -- frontend/assets/js/main.js -- frontend/assets/css/styles.css -- backend/app/payloads.py -- backend/app/routes.py - -## Expected Files to Modify -- frontend/index.html -- frontend/assets/js/main.js -- frontend/assets/css/styles.css - -## Constraints -- No tocar backend salvo si es estrictamente necesario por alineación menor con payloads ya existentes. -- No añadir librerías nuevas. -- No romper el fallback ni la CTA Conectar. -- No hacer cambios destructivos. -- Mantener la mejora centrada en claridad, jerarquía y densidad informativa. - -## Validation -- Las tarjetas reales muestran mejor la información útil. -- La jerarquía interna mejora. -- La experiencia visual sigue siendo limpia. -- El panel se entiende mejor en desktop y móvil. - -## Change Budget -- Preferir menos de 3 archivos modificados. -- Preferir menos de 180 líneas cambiadas. -## Outcome -- `frontend/assets/js/main.js` reorganiza la jerarquía interna de las tarjetas reales para destacar nombre, estado, población actual, mapa, región, última captura, CTA y métricas resumidas. -- `frontend/assets/css/styles.css` refuerza la densidad informativa con una columna compacta de estado/población y una fila de quick facts legible en desktop y móvil. -- La CTA `Conectar`, la tendencia reciente y el fallback existente se mantienen operativos. - -## Validation Result -- Ejecutado: `node --check frontend/assets/js/main.js`. -- Resultado: sintaxis JavaScript válida tras el ajuste de jerarquía y densidad visual. -- Revisado en código: la versión enriquecida de la tarjeta conserva `steam://connect/:` para snapshots reales y mantiene el fallback cuando no hay datos reales utilizables. - -## Decision Notes -- La mejora de densidad se concentró dentro de la tarjeta existente, sin añadir nuevas secciones grandes ni cambiar la arquitectura del panel. diff --git a/ai/tasks/done/TASK-040-full-width-page-shell-and-section-width-rebalance.md b/ai/tasks/done/TASK-040-full-width-page-shell-and-section-width-rebalance.md deleted file mode 100644 index f92d8e5..0000000 --- a/ai/tasks/done/TASK-040-full-width-page-shell-and-section-width-rebalance.md +++ /dev/null @@ -1,60 +0,0 @@ -# TASK-040-full-width-page-shell-and-section-width-rebalance - -## Goal -Reorganizar el layout general de la landing para aprovechar mucho mejor el ancho de página disponible, separando el ancho útil de las distintas secciones y eliminando la sensación de página excesivamente estrecha. - -## Context -La UI actual ya funciona y muestra datos reales, pero la composición general está demasiado constreñida en ancho. Esto provoca mucho espacio muerto lateral, reduce el impacto visual del diseño y comprime en exceso el panel de servidores. La landing necesita una estructura de anchuras más flexible y más coherente con un formato panorámico de desktop. - -## Steps -1. Revisar la estructura general de contenedores de `frontend/index.html`. -2. Revisar el sistema de anchuras, `max-width`, paddings laterales y shells actuales en `frontend/assets/css/styles.css`. -3. Reorganizar la página para que no todas las secciones dependan del mismo ancho máximo. -4. Definir al menos una separación clara entre: - - ancho del hero - - ancho del tráiler - - ancho del panel de servidores -5. Aumentar el ancho útil del bloque de servidores para aprovechar mejor desktop amplio. -6. Mantener el diseño responsive y sin romper móvil o tablet. -7. Preservar la identidad visual actual sin rediseñar completamente la página. - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- frontend/index.html -- frontend/assets/css/styles.css -- frontend/assets/js/main.js - -## Expected Files to Modify -- frontend/index.html -- frontend/assets/css/styles.css - -## Constraints -- No tocar backend. -- No añadir librerías nuevas. -- No romper el comportamiento actual del frontend. -- No hacer cambios destructivos. -- Mantener la landing coherente con el tono visual actual. - -## Validation -- La página ocupa mejor el ancho disponible en desktop. -- El panel de servidores gana anchura real. -- El hero y el tráiler mantienen buen equilibrio visual. -- La UI sigue funcionando correctamente en tablet y móvil. - -## Change Budget -- Preferir menos de 3 archivos modificados. -- Preferir menos de 180 líneas cambiadas. - -## Outcome -- `frontend/assets/css/styles.css` separa el ancho del hero, del bloque de trailer y del panel de servidores con shells independientes. -- El `page-shell` deja de imponer un unico ancho maximo a toda la landing y el panel de servidores gana mas ancho util en desktop. -- La mejora se mantuvo en CSS para no introducir cambios estructurales innecesarios en el HTML. - -## Validation Result -- Revisado en diff: el ajuste queda limitado a `frontend/assets/css/styles.css` y al propio archivo de task. -- Revisado en codigo: hero, trailer y panel de servidores usan anchuras maximas distintas y el layout movil conserva los resets responsive existentes. -- Limitacion: no se ejecuto una comprobacion visual automatizada del navegador en esta tarea. - -## Decision Notes -- La separacion de shells se resolvio con anchuras por seccion en lugar de crear nuevos wrappers HTML, para mantener la landing estable y reducir riesgo sobre el frontend actual. diff --git a/ai/tasks/done/TASK-040-historical-ui-qa-and-polish-pass.md b/ai/tasks/done/TASK-040-historical-ui-qa-and-polish-pass.md deleted file mode 100644 index 124686d..0000000 --- a/ai/tasks/done/TASK-040-historical-ui-qa-and-polish-pass.md +++ /dev/null @@ -1,72 +0,0 @@ -# TASK-040-historical-ui-qa-and-polish-pass - -## Goal -Realizar una pasada final de QA y pulido sobre la nueva capa histórica del proyecto, tanto en backend como en la UI histórica propia, antes de abrir futuras métricas más avanzadas. - -## Context -Tras añadir varias capas históricas de API y UI, conviene consolidar la calidad del resultado antes de seguir creciendo. Esta task debe centrarse en detectar pequeños defectos de presentación, consistencia, navegación, payload o comportamiento. - -## Steps -1. Revisar la UI histórica completa y los endpoints históricos ya expuestos. -2. Validar: - - weekly top kills - - partidas recientes - - resumen histórico si existe - - navegación histórica -3. Revisar: - - estados de loading/error/empty - - consistencia de servidor seleccionado - - consistencia de naming - - legibilidad de tablas/listados - - responsive básico -4. Corregir pequeños defectos o inconsistencias detectadas. -5. No abrir rediseños grandes en esta task. -6. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- backend/README.md -- backend/app/routes.py -- backend/app/payloads.py -- frontend/historico.html -- frontend/assets/js/historico.js -- frontend/assets/css/historico.css -- frontend/index.html -- frontend/assets/css/styles.css - -## Expected Files to Modify -- frontend/historico.html -- frontend/assets/js/historico.js -- frontend/assets/css/historico.css -- backend/app/routes.py -- backend/app/payloads.py -- opcionalmente documentación mínima si alguna parte visible necesita quedar reflejada - -## Constraints -- No abrir nuevas grandes features históricas en esta task. -- No depender de UI externa. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en QA y acabado. - -## Validation -- La capa histórica propia funciona con consistencia suficiente. -- La UI histórica está pulida y usable. -- No hay defectos relevantes en el flujo principal. -- Los cambios quedan committeados y se hace push al remoto si el entorno lo permite. - -## Change Budget -- Preferir menos de 6 archivos modificados. -- Preferir menos de 220 líneas cambiadas. -## Outcome -- Se revisó la consistencia entre selector de servidor, resumen, ranking semanal y partidas recientes. -- Se ajustaron estados visibles de loading, error y vacío en la vista histórica. -- Se añadieron ajustes responsive básicos en `frontend/assets/css/historico.css`. -- No se abrieron features históricas grandes fuera del alcance de QA y acabado. - -## Validation Notes -- `python -m compileall app` -- `node --check frontend/assets/js/historico.js` -- comprobación local de payloads históricos: weekly top kills, recent matches, server summary y player profile diff --git a/ai/tasks/done/TASK-040-randomized-community-clans-section.md b/ai/tasks/done/TASK-040-randomized-community-clans-section.md deleted file mode 100644 index d546bb7..0000000 --- a/ai/tasks/done/TASK-040-randomized-community-clans-section.md +++ /dev/null @@ -1,107 +0,0 @@ -# TASK-040-randomized-community-clans-section - -## Goal -Implementar una sección única de clanes/comunidades en la landing principal, mostrando los clanes indicados con sus logos y enlaces a Discord, en orden aleatorio en cada carga de página. - -## Context -La home ya incorpora una sección de clanes/comunidad, pero ahora hay una definición concreta de qué clanes deben aparecer, qué logos deben usarse y qué Discord debe enlazarse en cada caso. La sección debe ser única, clara y mantenible, y el orden de los clanes debe variar aleatoriamente cada vez que se cargue la página. - -## Datos a usar -Los clanes/comunidades que deben mostrarse son estos: - -1. LCM - - Discord: `https://discord.gg/9F9S353QZv` - - Logo: usar la imagen proporcionada para LCM - -2. La 129 - - Discord: placeholder por ahora - - Logo: usar la imagen proporcionada para La 129 - -3. 250 Hispania - - Discord: `https://discord.gg/3E62Yb6Aw3` - - Logo: usar solo el escudo de la imagen proporcionada, quitando la parte de texto `Historia de la 250` y quedándose únicamente con el emblema/escudo - -4. H9H - - Discord: `https://discord.gg/tYnXK7MQjB` - - Logo: placeholder por ahora - -5. BxB - - Discord: placeholder por ahora - - Logo: usar la imagen proporcionada para BxB - -6. 7dv - - Discord: `https://discord.gg/3sxNQZwrg6` - - Logo: usar la imagen proporcionada para 7dv - -## Steps -1. Revisar la landing actual y la sección de clanes/comunidad ya existente. -2. Ajustar la sección para que muestre exactamente estos 6 clanes/comunidades y no una lista distinta. -3. Mantener toda la información de los clanes en una estructura de datos clara y mantenible, preferiblemente en JS si eso encaja mejor con el renderizado actual. -4. Implementar la sección para mostrar, como mínimo, por cada clan: - - logo - - nombre - - botón o enlace a Discord -5. Hacer que el orden de aparición de los clanes sea aleatorio en cada carga de página. -6. Asegurar que la aleatorización no rompe la estructura visual ni genera duplicados. -7. Para los clanes con Discord aún no definido (`La 129` y `BxB`), mostrar un estado coherente y no roto, por ejemplo: - - botón deshabilitado - - etiqueta `Próximamente` - - o equivalente visual claro y honesto -8. Para los clanes con logo pendiente (`H9H`), usar un placeholder visual coherente con la estética de la web. -9. Para `250 Hispania`, usar solo el escudo/emblema, sin el texto `Historia de la 250`. -10. Mantener la sección como una única sección de comunidad/clanes en la home, sin duplicarla. -11. Asegurar que la sección funciona correctamente en escritorio y móvil. -12. Mantener la estética coherente con la landing actual. -13. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- frontend/index.html -- frontend/assets/css/styles.css -- frontend/assets/js/main.js -- cualquier archivo actual de datos/renderizado de la sección de clanes si ya existe -- assets actuales relacionados con logos de comunidad - -## Expected Files to Modify -- frontend/index.html -- frontend/assets/css/styles.css -- frontend/assets/js/main.js -- opcionalmente un archivo de datos/config si mejora claridad, por ejemplo: - - frontend/assets/js/community-clans.js -- opcionalmente nuevos assets referenciados correctamente si la implementación los necesita, por ejemplo dentro de: - - frontend/assets/img/clans/ - -## Constraints -- No romper la landing actual. -- No crear varias secciones de clanes; debe quedar una sola. -- No introducir frameworks nuevos. -- No depender de widgets externos o iframes de Discord para esta sección. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en la sección de clanes, su contenido real y el orden aleatorio por carga. - -## Validation -- La home muestra una única sección de clanes/comunidades. -- Aparecen exactamente estos 6 clanes/comunidades: - - LCM - - La 129 - - 250 Hispania - - H9H - - BxB - - 7dv -- El orden cambia aleatoriamente en cada carga de página. -- Los enlaces de Discord correctos funcionan para: - - LCM - - 250 Hispania - - H9H - - 7dv -- Los clanes sin enlace definitivo no muestran botones rotos. -- `250 Hispania` usa solo el escudo/emblema, sin el texto lateral. -- La sección sigue siendo visualmente coherente y responsive. -- Los cambios quedan committeados y se hace push al remoto si el entorno lo permite. - -## Change Budget -- Preferir menos de 6 archivos modificados o creados. -- Preferir menos de 260 líneas cambiadas. diff --git a/ai/tasks/done/TASK-041-historical-resumable-backfill-expansion.md b/ai/tasks/done/TASK-041-historical-resumable-backfill-expansion.md deleted file mode 100644 index 6968051..0000000 --- a/ai/tasks/done/TASK-041-historical-resumable-backfill-expansion.md +++ /dev/null @@ -1,108 +0,0 @@ -# TASK-041-historical-resumable-backfill-expansion - -## Goal -Ampliar la cobertura historica persistida de ambos servidores de la comunidad lo maximo posible mediante un proceso de backfill reanudable, seguro e idempotente, capaz de continuar sesiones incompletas sin perder progreso cuando la fuente CRCON publica falle intermitentemente. - -## Context -La capa historica del proyecto ya esta funcionando y la UI ya muestra cobertura registrada, pero la cobertura actual sigue siendo parcial. La fuente CRCON publica indica archivos mucho mas profundos que lo actualmente persistido, pero las sesiones largas de bootstrap sufren respuestas `502` intermitentes bajo carga. Eso significa que el limite actual de fechas no representa necesariamente el historico real disponible, sino el alcance conseguido hasta ahora por la importacion. - -La solucion correcta no es asumir que el historico ya esta completo, sino implementar o consolidar un backfill reanudable por lotes que permita seguir retrocediendo en el tiempo y ampliando la cobertura historica de forma progresiva. - -## Steps -1. Revisar la implementacion actual de: - - bootstrap historico - - refresh incremental - - persistencia historica - - validacion de cobertura -2. Revisar como se manejan actualmente: - - paginacion - - progreso de bootstrap - - reintentos - - errores upstream tipo `502` -3. Diseñar o consolidar una estrategia de backfill reanudable que permita: - - continuar desde una pagina o cursor previo - - guardar progreso util por servidor - - reintentar sin duplicar datos - - ampliar cobertura historica por bloques -4. Implementar o reforzar un mecanismo para ejecutar sesiones sucesivas de backfill historico para ambos servidores. -5. Garantizar que el sistema: - - no pierde progreso util - - no vuelve a importar innecesariamente lo ya consolidado - - puede seguir avanzando aunque una sesion concreta falle a mitad -6. Añadir o mejorar metadatos operativos de cobertura y progreso, por ejemplo: - - ultima pagina procesada por servidor - - rango temporal cubierto actual - - numero total de partidas persistidas - - estado del ultimo intento de backfill -7. Ejecutar o dejar documentado un flujo operativo realista para seguir ampliando cobertura en varias sesiones. -8. Documentar claramente que la cobertura historica puede crecer progresivamente y que el limite actual no debe interpretarse como limite definitivo del origen mientras siga habiendo paginas disponibles. -9. No crear todavia nueva UI historica en esta task salvo ajustes minimos de payload o semantica si fueran imprescindibles para reflejar mejor la cobertura. -10. Al completar la implementacion: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- ai/architecture-index.md -- docs/historical-crcon-source-discovery.md -- docs/historical-domain-model.md -- docs/historical-data-quality-notes.md -- docs/historical-coverage-report.md -- backend/README.md -- backend/app/config.py -- backend/app/historical_ingestion.py -- backend/app/historical_storage.py -- backend/app/historical_models.py -- backend/app/routes.py -- backend/app/payloads.py - -## Expected Files to Modify -- backend/README.md -- backend/app/config.py -- backend/app/historical_ingestion.py -- backend/app/historical_storage.py -- backend/app/historical_models.py -- opcionalmente nuevos modulos auxiliares si mejoran claridad del backfill y del checkpoint de progreso, por ejemplo: - - backend/app/historical_backfill_state.py - - backend/app/historical_backfill_runner.py -- opcionalmente documentacion tecnica adicional, por ejemplo: - - docs/historical-coverage-report.md - - docs/historical-backfill-operations.md - -## Constraints -- No basar esta ampliacion historica en A2S. -- No crear paginas frontend nuevas usando la URL de la comunidad. -- No depender del HTML de `/games` como fuente final. -- No romper el flujo actual de live status. -- No romper la persistencia historica ya existente. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en backfill reanudable, idempotencia, resiliencia y ampliacion de cobertura. - -## Validation -- Existe un mecanismo reanudable para seguir ampliando el historico por lotes. -- El backfill puede continuar sin duplicar datos ya persistidos. -- El sistema registra progreso util por servidor. -- La cobertura historica puede ampliarse progresivamente con sesiones sucesivas. -- La documentacion deja claro el estado real y las limitaciones operativas. -- Los cambios quedan committeados y se hace push al remoto si el entorno lo permite. - -## Change Budget -- Preferir menos de 7 archivos modificados o creados. -- Preferir menos de 260 lineas cambiadas. - -## Outcome -- Se añadio persistencia de checkpoint por servidor y modo en `historical_backfill_progress`. -- El bootstrap ahora reanuda automaticamente desde `next_page` cuando no se pasa `--start-page`. -- Cada pagina completada guarda progreso util (`last_completed_page`, `next_page`, total descubierto y estado del ultimo intento). -- `server-summary` y el reporte de cobertura exponen metadatos operativos de backfill para reflejar mejor la cobertura real importada. -- Se documento el flujo operativo reanudable y los nuevos ajustes de reintentos para errores CRCON intermitentes. - -## Validation Notes -- `python -m compileall app` -- validacion local con SQLite de prueba en workspace verificando: - - reanudacion desde pagina `4` tras completar la pagina `3` - - persistencia de `last_completed_page` - - exposicion de `discovered_total_pages` en cobertura y resumen -- no se ejecuto backfill real contra CRCON por las restricciones de red del entorno actual diff --git a/ai/tasks/done/TASK-041-real-server-card-layout-reorganization.md b/ai/tasks/done/TASK-041-real-server-card-layout-reorganization.md deleted file mode 100644 index a8709cc..0000000 --- a/ai/tasks/done/TASK-041-real-server-card-layout-reorganization.md +++ /dev/null @@ -1,68 +0,0 @@ -# TASK-041-real-server-card-layout-reorganization - -## Goal -Reorganizar internamente las tarjetas de servidores reales para que aprovechen mejor el espacio horizontal, reduzcan compresión vertical y mejoren la legibilidad de los datos. - -## Context -Las tarjetas actuales contienen información útil, pero en una composición demasiado estrecha y alta. Eso hace que varias métricas queden apelotonadas, con mala jerarquía y sensación de desborde. Esta task debe rediseñar la distribución interna de la tarjeta, no la arquitectura funcional del panel. - -## Steps -1. Revisar la estructura HTML y JS que renderiza las tarjetas de servidores reales. -2. Reorganizar la composición interna para que la tarjeta tenga una lectura más horizontal y clara. -3. Priorizar visualmente: - - nombre del servidor - - estado - - botón Conectar - - jugadores - - mapa - - región - - última captura - - métricas resumidas -4. Reducir altura innecesaria y mejorar la distribución interna de bloques. -5. Mantener la CTA de conexión visible y bien integrada. -6. Mejorar el comportamiento de nombres largos y textos densos. -7. No romper el fallback ni la lógica actual del panel. - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- frontend/index.html -- frontend/assets/js/main.js -- frontend/assets/css/styles.css -- backend/app/payloads.py - -## Expected Files to Modify -- frontend/index.html -- frontend/assets/js/main.js -- frontend/assets/css/styles.css - -## Constraints -- No tocar backend salvo alineación mínima si fuera imprescindible. -- No añadir librerías nuevas. -- No romper la CTA Conectar. -- No hacer cambios destructivos. -- Mantener la mejora centrada en layout y legibilidad. - -## Validation -- Las tarjetas reales son más legibles y aprovechan mejor el ancho. -- La jerarquía interna mejora claramente. -- El texto largo deja de sentirse comprimido o desbordado. -- La UI mantiene coherencia visual con el resto de la landing. - -## Change Budget -- Preferir menos de 3 archivos modificados. -- Preferir menos de 180 líneas cambiadas. - -## Outcome -- `frontend/assets/js/main.js` reorganiza la tarjeta real en dos zonas: cabecera prioritaria con estado, poblacion y CTA, y cuerpo con quick facts, resumen historico y tendencia. -- `frontend/assets/css/styles.css` adapta la tarjeta a una lectura mas horizontal en desktop y endurece el wrapping de nombres y valores largos. -- No fue necesario tocar `frontend/index.html` ni alinear payloads del backend. - -## Validation Result -- Ejecutado: `node --check frontend/assets/js/main.js`. -- Resultado: sintaxis JavaScript valida tras la reorganizacion del render. -- Revisado en codigo: la CTA `Conectar` sigue ligada a `steam://connect/:` y solo aparece para snapshots reales A2S. -- Limitacion: no se ejecuto una comprobacion visual automatizada del navegador en esta tarea. - -## Decision Notes -- La reduccion de altura se resolvio moviendo resumen y tendencia a una composicion interna mas horizontal, sin cambiar la logica de secciones del panel ni el fallback existente. diff --git a/ai/tasks/done/TASK-042-historical-snapshots-storage-and-model.md b/ai/tasks/done/TASK-042-historical-snapshots-storage-and-model.md deleted file mode 100644 index abeac65..0000000 --- a/ai/tasks/done/TASK-042-historical-snapshots-storage-and-model.md +++ /dev/null @@ -1,68 +0,0 @@ -# TASK-042-historical-snapshots-storage-and-model - -## Goal -Diseñar e implementar una capa de almacenamiento de snapshots históricos precalculados para el proyecto, preparada para servir rápidamente resumen, rankings y partidas recientes sin recalcular agregados pesados en tiempo real. - -## Context -La página histórica ya funciona, pero parte de la información puede requerir agregaciones costosas si se calculan en el momento de cada carga o al cambiar de pestaña. El objetivo es introducir una capa de snapshots precalculados y persistidos que permita responder de forma rápida y estable. Esto debe incluir no solo el resumen del servidor, sino también los tops/rankings semanales. - -## Steps -1. Revisar la estructura histórica actual y los endpoints/API que hoy calculan resumen, rankings y partidas recientes. -2. Diseñar un modelo de snapshot persistido que soporte, como mínimo: - - resumen de servidor - - top kills semanales - - top muertes semanales - - top partidas con más de 100 kills por jugador - - top puntos de soporte semanales - - partidas recientes -3. Definir para cada snapshot metadatos claros, por ejemplo: - - server_key - - snapshot_type - - metric - - window - - payload_json - - generated_at - - source_range_start - - source_range_end - - is_stale -4. Implementar el almacenamiento local de snapshots de forma coherente con la persistencia histórica actual. -5. Documentar la estructura y propósito de esta nueva capa. -6. No migrar todavía toda la UI a snapshots en esta task. -7. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- backend/README.md -- backend/app/historical_models.py -- backend/app/historical_storage.py -- backend/app/payloads.py -- backend/app/routes.py -- docs/historical-domain-model.md - -## Expected Files to Modify -- backend/README.md -- backend/app/historical_models.py -- backend/app/historical_storage.py -- opcionalmente nuevos módulos, por ejemplo: - - backend/app/historical_snapshots.py - - backend/app/historical_snapshot_storage.py -- opcionalmente documentación técnica adicional - -## Constraints -- No basar esta capa en A2S. -- No crear todavía nueva UI en esta task. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en almacenamiento y modelo de snapshots. - -## Validation -- Existe un modelo de snapshot persistido claro. -- El modelo cubre resumen, rankings y partidas recientes. -- La estructura está lista para ser rellenada periódicamente. -- Los cambios quedan committeados y se hace push al remoto si el entorno lo permite. - -## Change Budget -- Preferir menos de 6 archivos modificados o creados. -- Preferir menos de 220 líneas cambiadas. diff --git a/ai/tasks/done/TASK-042-server-panel-grid-and-overflow-hardening.md b/ai/tasks/done/TASK-042-server-panel-grid-and-overflow-hardening.md deleted file mode 100644 index e73058f..0000000 --- a/ai/tasks/done/TASK-042-server-panel-grid-and-overflow-hardening.md +++ /dev/null @@ -1,62 +0,0 @@ -# TASK-042-server-panel-grid-and-overflow-hardening - -## Goal -Fortalecer la rejilla del panel de servidores y corregir problemas de compresión, desborde y distribución espacial en desktop, tablet y móvil. - -## Context -El panel de servidores ya consume datos reales y funciona correctamente, pero la rejilla actual no está aprovechando bien el espacio horizontal y deja tarjetas demasiado estrechas. Además, la estructura necesita endurecerse frente a nombres largos, métricas densas y cambios de anchura de viewport. - -## Steps -1. Revisar la rejilla actual del panel de servidores. -2. Ajustar el sistema de columnas para permitir una distribución más robusta y flexible. -3. Usar una estrategia de `grid` adecuada para: - - desktop ancho - - desktop medio - - tablet - - móvil -4. Revisar `min-width`, `max-width`, `gap`, `overflow-wrap` y cualquier punto de compresión o desborde. -5. Asegurar que las tarjetas no se rompan visualmente con contenido real. -6. Mantener una composición limpia, con buen aire y buen equilibrio. -7. No rediseñar toda la landing fuera del panel de servidores. - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- frontend/index.html -- frontend/assets/css/styles.css -- frontend/assets/js/main.js - -## Expected Files to Modify -- frontend/assets/css/styles.css -- frontend/index.html -- opcionalmente frontend/assets/js/main.js si hay que ajustar clases o hooks del render - -## Constraints -- No tocar backend. -- No añadir librerías nuevas. -- No romper el comportamiento actual del panel. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en grid, responsive y overflow. - -## Validation -- El panel de servidores ocupa mejor el ancho disponible. -- Las tarjetas ya no se sienten excesivamente estrechas. -- Se corrigen problemas de compresión y desborde. -- El comportamiento responsive mejora en desktop, tablet y móvil. - -## Change Budget -- Preferir menos de 3 archivos modificados. -- Preferir menos de 160 líneas cambiadas. - -## Outcome -- `frontend/assets/css/styles.css` sustituye la rejilla fija de dos columnas por un `auto-fit` con `minmax`, permitiendo mejor reparto en desktop ancho y desktop medio. -- El mismo archivo endurece el panel con `min-width: 0`, `max-width: 100%`, `overflow: hidden` y subrejillas flexibles para quick facts y resumen. -- No fue necesario tocar `frontend/index.html` ni `frontend/assets/js/main.js`. - -## Validation Result -- Revisado en codigo: el panel ahora define comportamiento especifico para desktop ancho, desktop medio, tablet y movil mediante breakpoints en `1120px`, `760px` y el ajuste movil existente. -- Revisado en diff: la task queda limitada a `frontend/assets/css/styles.css` y al archivo de task. -- Limitacion: no se ejecuto una comprobacion visual automatizada del navegador en esta tarea. - -## Decision Notes -- La hardening del panel se resolvio a nivel de grid y overflow sin volver a rediseñar las tarjetas ni tocar la logica de render ya ajustada en la task anterior. diff --git a/ai/tasks/done/TASK-043-historical-snapshots-generation-runner.md b/ai/tasks/done/TASK-043-historical-snapshots-generation-runner.md deleted file mode 100644 index 9280d32..0000000 --- a/ai/tasks/done/TASK-043-historical-snapshots-generation-runner.md +++ /dev/null @@ -1,59 +0,0 @@ -# TASK-043-historical-snapshots-generation-runner - -## Goal -Implementar un generador/runner de snapshots históricos que calcule y refresque periódicamente resumen, tops y partidas recientes para cada servidor de la comunidad. - -## Context -Una vez existe almacenamiento de snapshots, hace falta una capa operativa que genere esos snapshots a partir del histórico persistido. El objetivo es que la página histórica no dependa de cálculos pesados en tiempo real, sino de datos precalculados actualizados periódicamente. - -## Steps -1. Revisar los agregados históricos actuales y la nueva capa de snapshots. -2. Implementar un runner o flujo de generación que produzca snapshots para cada servidor. -3. Generar, como mínimo: - - resumen de servidor - - top kills 7d - - top muertes 7d - - top partidas con más de 100 kills por jugador 7d - - top puntos de soporte 7d - - partidas recientes -4. Añadir metadatos de generación y estado. -5. Definir una frecuencia razonable de refresco, por ejemplo 10 o 15 minutos. -6. Documentar cómo ejecutar el runner manualmente y cómo operarlo de forma periódica. -7. No migrar todavía toda la UI en esta task. -8. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- backend/README.md -- backend/app/config.py -- backend/app/historical_storage.py -- backend/app/historical_snapshots.py -- backend/app/historical_snapshot_storage.py -- backend/app/historical_runner.py - -## Expected Files to Modify -- backend/README.md -- backend/app/config.py -- backend/app/historical_runner.py -- backend/app/historical_snapshots.py -- backend/app/historical_snapshot_storage.py -- opcionalmente nuevos módulos auxiliares de generación - -## Constraints -- No romper el live status. -- No crear UI nueva en esta task. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en generación periódica de snapshots. - -## Validation -- Existe un runner que genera snapshots de resumen, tops y partidas recientes. -- Los snapshots se pueden refrescar periódicamente. -- La documentación explica cómo ejecutarlo. -- Los cambios quedan committeados y se hace push al remoto si el entorno lo permite. - -## Change Budget -- Preferir menos de 6 archivos modificados o creados. -- Preferir menos de 240 líneas cambiadas. diff --git a/ai/tasks/done/TASK-043-unified-page-shell-and-section-width-system.md b/ai/tasks/done/TASK-043-unified-page-shell-and-section-width-system.md deleted file mode 100644 index 2e84bc4..0000000 --- a/ai/tasks/done/TASK-043-unified-page-shell-and-section-width-system.md +++ /dev/null @@ -1,60 +0,0 @@ -# TASK-043-unified-page-shell-and-section-width-system - -## Goal -Unificar el sistema de anchuras de la pagina para que hero, trailer y panel de servidores compartan el mismo ancho util y se perciban como parte de una misma experiencia visual, eliminando la sensacion actual de secciones con tamanos distintos. - -## Context -La UI actual ya funciona y muestra datos reales, pero las secciones principales no comparten una anchura consistente. Esto hace que la pagina se sienta fragmentada y reduce la sensacion de producto final. El objetivo de esta task es definir un unico sistema de shell/layout para las secciones principales y aplicarlo de forma consistente. - -## Steps -1. Revisar la estructura actual de shells, contenedores y max-width del frontend. -2. Identificar diferencias de ancho entre: - - hero - - bloque del trailer - - bloque de servidores -3. Definir un unico ancho maestro para las secciones principales en desktop. -4. Hacer que hero, trailer y panel de servidores usen el mismo carril visual principal. -5. Ajustar margenes laterales, paddings y separacion vertical para evitar sensacion de fragmentacion. -6. Mantener el comportamiento responsive correcto en tablet y movil. -7. No redisenar el contenido, solo el sistema de layout y anchuras. - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- frontend/index.html -- frontend/assets/css/styles.css -- frontend/assets/js/main.js - -## Expected Files to Modify -- frontend/index.html -- frontend/assets/css/styles.css - -## Constraints -- No tocar backend. -- No anadir librerias nuevas. -- No hacer cambios destructivos. -- Mantener la identidad visual actual. -- Mantener el trabajo centrado en shell/layout. - -## Validation -- Hero, trailer y panel de servidores comparten el mismo ancho util en desktop. -- La pagina se percibe mas unificada. -- No quedan secciones visualmente demasiado estrechas respecto a otras. -- El responsive sigue funcionando. - -## Change Budget -- Preferir menos de 3 archivos modificados. -- Preferir menos de 180 lineas cambiadas. - -## Outcome -- `frontend/index.html` introduce un `panel__shell` comun en trailer y servidores para que ambas secciones compartan el mismo carril interior. -- `frontend/assets/css/styles.css` reemplaza los anchos independientes de hero, trailer y servidores por un sistema unificado con `--page-shell-width` y `--panel-content-width`. -- El ajuste se mantuvo centrado en layout, paddings y separacion vertical, sin redisenar el contenido. - -## Validation Result -- Revisado en diff: la task queda limitada a `frontend/index.html`, `frontend/assets/css/styles.css` y el archivo de task, dentro del scope esperado. -- Revisado en codigo: hero, trailer y panel de servidores pasan a compartir un mismo ancho maestro en desktop y un mismo carril interior para el contenido principal. -- El responsive existente se conserva con los breakpoints moviles previos y con padding especifico para paneles en `max-width: 640px`. - -## Decision Notes -- Se unifico el sistema de shell a nivel de seccion y de carril interior en lugar de tocar el contenido de cada bloque, para cumplir el objetivo visual sin abrir un rediseno mayor. diff --git a/ai/tasks/done/TASK-044-historical-snapshots-api.md b/ai/tasks/done/TASK-044-historical-snapshots-api.md deleted file mode 100644 index 0b1e47c..0000000 --- a/ai/tasks/done/TASK-044-historical-snapshots-api.md +++ /dev/null @@ -1,77 +0,0 @@ -# TASK-044-historical-snapshots-api - -## Goal -Exponer una API de snapshots historicos precalculados para que el frontend pueda consumir resumen, tops y partidas recientes sin disparar agregaciones costosas en tiempo real. - -## Context -Con snapshots ya persistidos y generados periodicamente, el siguiente paso es exponer endpoints ligeros para que la UI historica lea directamente datos preparados. - -## Steps -1. Revisar la capa de snapshots ya creada y el runner de generacion. -2. Disenar endpoints claros para leer snapshots por servidor, tipo y metrica. -3. Cubrir como minimo: - - resumen de servidor - - tops semanales por metrica - - partidas recientes -4. Asegurar que los endpoints devuelven tambien informacion util de actualizacion: - - generated_at - - rango fuente - - stale/fresh si aplica -5. Mantener compatibilidad razonable con la UI historica ya existente o dejar clara la migracion. -6. Documentar los endpoints en backend. -7. No cambiar todavia toda la UI en esta task. -8. Al completar la implementacion: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- backend/README.md -- backend/app/routes.py -- backend/app/payloads.py -- backend/app/historical_snapshot_storage.py -- backend/app/historical_snapshots.py - -## Expected Files to Modify -- backend/app/routes.py -- backend/app/payloads.py -- backend/README.md -- opcionalmente nuevos modulos de payload/query de snapshots - -## Constraints -- No usar A2S para esta capa. -- No hacer calculos pesados on-demand si ya existe snapshot valido. -- No crear UI nueva en esta task. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en una API ligera de snapshots. - -## Validation -- Existen endpoints de snapshots para resumen, tops y partidas recientes. -- Los payloads incluyen metadatos de actualizacion utiles. -- La capa esta lista para que la UI deje de depender de agregados pesados en tiempo real. -- Los cambios quedan committeados y se hace push al remoto si el entorno lo permite. - -## Change Budget -- Preferir menos de 5 archivos modificados o creados. -- Preferir menos de 220 lineas cambiadas. - -## Outcome -- `backend/app/routes.py` expone endpoints ligeros de lectura para `server-summary`, `weekly-leaderboard` y `recent-matches` bajo `/api/historical/snapshots/*`. -- `backend/app/payloads.py` lee directamente `historical_precomputed_snapshots` con `get_historical_snapshot(...)` y devuelve payloads compatibles con frontend sin recalcular agregados historicos pesados. -- La metadata comun de snapshot incluye `generated_at`, `source_range_start`, `source_range_end`, `is_stale`, `freshness` y `found`. -- `backend/README.md` documenta los endpoints de snapshots y la metadata operativa disponible para frontend. - -## Validation Result -- Validado con `python -m py_compile backend/app/routes.py backend/app/payloads.py backend/app/historical_snapshot_storage.py backend/app/historical_snapshots.py`. -- Validado con `resolve_get_payload(...)` para: - - `/api/historical/snapshots/server-summary` - - `/api/historical/snapshots/weekly-leaderboard` - - `/api/historical/snapshots/recent-matches` -- Validado con builders de payload en Python: los tres endpoints exponen `freshness` y responden de forma estable incluso cuando todavia no existe snapshot persistido, devolviendo `found: False` y estados vacios compatibles. -- Durante una validacion paralela aparecio un `sqlite3.OperationalError: database is locked` por inicializaciones concurrentes sobre la misma SQLite local; la validacion secuencial posterior paso correctamente sin requerir cambios de implementacion para esta task. -- Revisado en diff: la task queda limitada a `backend/app/routes.py`, `backend/app/payloads.py`, `backend/README.md` y este archivo de task. - -## Decision Notes -- Se mantuvieron intactos los endpoints historicos legacy (`/api/historical/server-summary`, `/api/historical/weekly-leaderboard`, `/api/historical/recent-matches`) para no romper consumidores existentes mientras la migracion a snapshots ocurre por separado. -- La capa de snapshots se resolvio como lectura directa de persistencia con recorte por `limit` sobre payload ya precalculado, evitando introducir nuevos calculos on-demand. diff --git a/ai/tasks/done/TASK-044-remove-test-signals-and-technical-summary-strips.md b/ai/tasks/done/TASK-044-remove-test-signals-and-technical-summary-strips.md deleted file mode 100644 index 9167023..0000000 --- a/ai/tasks/done/TASK-044-remove-test-signals-and-technical-summary-strips.md +++ /dev/null @@ -1,59 +0,0 @@ -# TASK-044-remove-test-signals-and-technical-summary-strips - -## Goal -Eliminar de la interfaz principal los elementos, etiquetas y resumenes que den sensacion de entorno de pruebas o validacion tecnica, dejando una experiencia mas limpia y orientada a producto final. - -## Context -La pagina ya esta entrando en una fase mas cercana a producto final. Sin embargo, siguen apareciendo elementos como "captura real reciente", resumenes tecnicos o textos que funcionan bien para desarrollo, pero no para una experiencia publica mas madura. - -## Steps -1. Revisar el bloque actual de servidores y los elementos intermedios previos a la rejilla de tarjetas. -2. Eliminar o simplificar los elementos que indiquen: - - validacion interna - - estado de prueba - - resumenes tecnicos poco utiles para el visitante -3. Quitar la seccion visual equivalente a "captura real reciente". -4. Quitar la fila o bloque de resumen tipo "vista previa historica" si no aporta valor claro al usuario final. -5. Mantener solo el copy que ayuda a entender el bloque como producto real. -6. Asegurar que el panel de servidores quede mas limpio y mas directo. - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- frontend/index.html -- frontend/assets/js/main.js -- frontend/assets/css/styles.css - -## Expected Files to Modify -- frontend/index.html -- frontend/assets/js/main.js -- frontend/assets/css/styles.css - -## Constraints -- No tocar backend. -- No romper el consumo de datos reales. -- No eliminar fallbacks internos, solo su exposicion innecesaria en la UI. -- No hacer cambios destructivos. -- Mantener el ajuste centrado en limpieza de producto. - -## Validation -- Desaparecen indicios de "modo prueba" en la vista principal. -- El bloque de servidores se percibe mas limpio y mas orientado a usuario final. -- La pagina mantiene funcionalidad completa. - -## Change Budget -- Preferir menos de 3 archivos modificados. -- Preferir menos de 140 lineas cambiadas. - -## Outcome -- `frontend/index.html` elimina el bloque visual de fuente/estado y la franja de resumen historico previa a la rejilla. -- `frontend/assets/js/main.js` mantiene la logica interna de estados, pero reduce la exposicion publica a un badge limpio y copy orientado a producto. -- `frontend/assets/css/styles.css` retira los estilos de los strips tecnicos eliminados. - -## Validation Result -- Revisado en codigo: los datos reales siguen hidratando el panel y la diferenciacion interna entre live, historical y fallback se conserva en JavaScript. -- Validado con `node --check frontend/assets/js/main.js`. -- Revisado en diff: la task queda limitada a `frontend/index.html`, `frontend/assets/js/main.js`, `frontend/assets/css/styles.css` y el archivo de task. - -## Decision Notes -- La limpieza se resolvio ocultando por completo los bloques tecnicos y simplificando el lenguaje de estado, en lugar de introducir nuevas superficies UI intermedias. diff --git a/ai/tasks/done/TASK-045-historical-ui-migrate-to-snapshots.md b/ai/tasks/done/TASK-045-historical-ui-migrate-to-snapshots.md deleted file mode 100644 index 30ac7ac..0000000 --- a/ai/tasks/done/TASK-045-historical-ui-migrate-to-snapshots.md +++ /dev/null @@ -1,76 +0,0 @@ -# TASK-045-historical-ui-migrate-to-snapshots - -## Goal -Migrar la pagina historica para que lea snapshots precalculados de resumen, tops y partidas recientes, mejorando tiempos de carga y evitando esperas innecesarias al abrir la pagina o cambiar de pestana. - -## Context -La UI historica ya existe, pero el objetivo ahora es que no dependa de consultas pesadas en tiempo real. Debe leer snapshots ya preparados y actualizados en segundo plano, mostrando datos rapidos y estables. - -## Steps -1. Revisar la API de snapshots ya implementada. -2. Cambiar la UI historica para que: - - resumen - - tabs de tops - - partidas recientes - se carguen desde snapshots y no desde agregados costosos on-demand. -3. Mostrar de forma clara cuando se genero el snapshot. -4. Mantener estados de loading, empty y error, pero reducir la espera perceptible. -5. Asegurar que cambiar entre pestanas de tops sea rapido y estable. -6. Mantener coherencia visual con el resto de la web. -7. No crear paginas nuevas en esta task. -8. Al completar la implementacion: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- frontend/historico.html -- frontend/assets/js/historico.js -- frontend/assets/css/historico.css -- backend/app/routes.py -- backend/app/payloads.py - -## Expected Files to Modify -- frontend/historico.html -- frontend/assets/js/historico.js -- frontend/assets/css/historico.css -- opcionalmente backend docs minimas si cambia el flujo de consumo - -## Constraints -- No romper la UI historica existente. -- No introducir frameworks nuevos. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en rendimiento percibido y consumo de snapshots. - -## Validation -- La UI historica carga resumen, tops y partidas recientes desde snapshots. -- Cambiar de pestana entre tops es rapido. -- El usuario ve una referencia clara de actualizacion. -- La pagina reduce la dependencia de calculos on-demand pesados. -- Los cambios quedan committeados y se hace push al remoto si el entorno lo permite. - -## Change Budget -- Preferir menos de 5 archivos modificados o creados. -- Preferir menos de 220 lineas cambiadas. - -## Outcome -- `frontend/assets/js/historico.js` deja de depender de agregados historicos on-demand y pasa a leer snapshots precalculados para resumen, ranking semanal y partidas recientes. -- `frontend/assets/js/historico.js` incorpora cache por servidor y metrica para que cambiar de pestana entre tops reutilice payloads ya leidos y reduzca la espera perceptible. -- `frontend/historico.html` y `frontend/assets/css/historico.css` muestran una referencia explicita de `generated_at` y del rango fuente de cada snapshot en las tres secciones principales. -- `backend/app/routes.py` y `backend/app/payloads.py` anaden la capa minima de lectura `/api/historical/snapshots/*` necesaria para servir snapshots precalculados sin recalcular agregados pesados. -- `backend/README.md` documenta los nuevos endpoints de snapshots y la metadata operativa que exponen. - -## Validation Result -- Validado con `node --check frontend/assets/js/historico.js`. -- Validado con `python -m py_compile backend/app/routes.py backend/app/payloads.py`. -- Validado con `resolve_get_payload(...)` para: - - `/api/historical/snapshots/server-summary` - - `/api/historical/snapshots/weekly-leaderboard` - - `/api/historical/snapshots/recent-matches` -- Validado con builders Python: los nuevos payloads responden de forma estable incluso cuando todavia no existen snapshots persistidos y devuelven `found: False` con `items: []` o `item: None`. -- Revisado en diff: el alcance queda limitado a `backend/README.md`, `backend/app/routes.py`, `backend/app/payloads.py`, `frontend/historico.html`, `frontend/assets/css/historico.css`, `frontend/assets/js/historico.js` y este archivo de task. - -## Decision Notes -- La task estaba bloqueada por una dependencia no resuelta: la UI debia migrar a snapshots, pero la API ligera de lectura descrita en la task previa no estaba presente en `routes.py` ni en `payloads.py` dentro de este worktree. Se implemento solo la capa minima necesaria para completar la migracion sin ampliar el alcance a nueva UI ni a nuevos calculos backend. -- Se mantuvieron los endpoints historicos legacy para no romper compatibilidad mientras la pagina historica migra al contrato basado en snapshots. diff --git a/ai/tasks/done/TASK-045-simplify-real-server-cards-for-product-ui.md b/ai/tasks/done/TASK-045-simplify-real-server-cards-for-product-ui.md deleted file mode 100644 index 117bd2d..0000000 --- a/ai/tasks/done/TASK-045-simplify-real-server-cards-for-product-ui.md +++ /dev/null @@ -1,69 +0,0 @@ -# TASK-045-simplify-real-server-cards-for-product-ui - -## Goal -Simplificar las tarjetas de servidores reales para mostrar solo la informacion mas util para el visitante final, mejorando la claridad y reduciendo ruido visual y tecnico. - -## Context -Las tarjetas actuales ya muestran datos reales A2S, pero siguen ensenando informacion que no aporta suficiente valor para la experiencia principal. La tarjeta debe centrarse en lo esencial: nombre, estado, jugadores, mapa, region, ultima captura y CTA de conexion. Cualquier metrica adicional debe ser secundaria o eliminarse si no mejora claramente la lectura. - -## Steps -1. Revisar la estructura actual de las tarjetas reales. -2. Reducir la informacion visible principal a: - - nombre - - estado - - jugadores actuales - - mapa - - region - - ultima captura - - boton Conectar -3. Evaluar si promedio y pico deben quedar como datos secundarios discretos o desaparecer. -4. Eliminar de la tarjeta elementos como: - - tendencia reciente - - numero de capturas - - bloques densos poco utiles -5. Reorganizar la tarjeta para que se lea rapido y con claridad. -6. Mantener una composicion limpia y coherente con el diseno actual. -7. Asegurar buena legibilidad en desktop y movil. - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- frontend/index.html -- frontend/assets/js/main.js -- frontend/assets/css/styles.css -- backend/app/payloads.py - -## Expected Files to Modify -- frontend/index.html -- frontend/assets/js/main.js -- frontend/assets/css/styles.css - -## Constraints -- No tocar backend salvo alineacion menor si fuera imprescindible. -- No romper la CTA Conectar. -- No anadir librerias nuevas. -- No hacer cambios destructivos. -- Mantener el ajuste centrado en UX de producto final. - -## Validation -- Las tarjetas reales muestran solo la informacion mas util y legible. -- Desaparece ruido tecnico innecesario. -- La CTA Conectar sigue visible y clara. -- La UI gana sensacion de producto final. - -## Change Budget -- Preferir menos de 3 archivos modificados. -- Preferir menos de 160 lineas cambiadas. - -## Outcome -- `frontend/assets/js/main.js` simplifica el render de tarjetas reales a identidad, estado, poblacion, quick facts y CTA, eliminando resumen historico, tendencia y llamadas auxiliares ya innecesarias. -- `frontend/assets/css/styles.css` elimina estilos asociados a bloques tecnicos densos y deja una composicion mas directa para las quick facts. -- No fue necesario tocar backend ni cambiar la CTA `Conectar`. - -## Validation Result -- Validado con `node --check frontend/assets/js/main.js`. -- Revisado en codigo: las tarjetas mantienen nombre, estado, jugadores, mapa, region, ultima captura y CTA, y desaparecen tendencia, capturas, promedio y pico. -- Revisado en diff: la task queda limitada a `frontend/assets/js/main.js`, `frontend/assets/css/styles.css` y el archivo de task. - -## Decision Notes -- Se opto por eliminar por completo las metricas secundarias en lugar de rebajarlas visualmente, porque seguian cargando la tarjeta y no aportaban suficiente valor a la lectura principal. diff --git a/ai/tasks/done/TASK-046-historical-snapshots-generation-and-weekly-fallback.md b/ai/tasks/done/TASK-046-historical-snapshots-generation-and-weekly-fallback.md deleted file mode 100644 index 59f720e..0000000 --- a/ai/tasks/done/TASK-046-historical-snapshots-generation-and-weekly-fallback.md +++ /dev/null @@ -1,104 +0,0 @@ -# TASK-046-historical-snapshots-generation-and-weekly-fallback - -## Goal -Completar la capa operativa de snapshots históricos para que la página histórica deje de mostrar estados vacíos cuando ya existe histórico bruto persistido, y añadir una regla de fallback semanal que use la semana cerrada anterior cuando la semana actual todavía no tenga muestra suficiente, especialmente a principio de semana. - -## Context -La página histórica ya consume endpoints de snapshots precalculados, pero en el estado actual del proyecto esos snapshots no están generados o no se están persistiendo de forma efectiva para el servidor activo. Como resultado, la UI muestra mensajes como “Sin snapshot de resumen” o “Sin datos históricos suficientes” aunque el bootstrap histórico ya haya cargado datos crudos en SQLite. - -Además, la experiencia esperada para los rankings semanales requiere una regla adicional: si la semana actual aún no tiene muestra suficiente —por ejemplo, en lunes o muy al inicio de la semana— debe mostrarse temporalmente la semana cerrada anterior hasta que la actual tenga datos suficientes. - -## Steps -1. Revisar la implementación actual de: - - histórico bruto persistido - - capa de snapshots - - API de snapshots - - UI histórica que consume snapshots -2. Identificar por qué, tras el bootstrap histórico, no se están generando o persistiendo snapshots disponibles para la UI. -3. Completar o corregir el flujo de generación de snapshots para: - - resumen de servidor - - weekly leaderboard - - recent matches -4. Asegurar que exista una forma clara de generar snapshots después del bootstrap y de refrescarlos periódicamente. -5. Validar que, una vez existe histórico bruto suficiente, la UI deje de mostrar mensajes de “sin snapshot” para el servidor activo. -6. Implementar en backend una regla de selección de leaderboard semanal con fallback: - - si la semana actual no tiene muestra suficiente - - y estamos en los primeros días de la semana o en una condición equivalente definida por el proyecto - - devolver la semana cerrada anterior como snapshot activo -7. Definir y documentar claramente qué significa “muestra suficiente” para este fallback semanal. -8. Hacer que el payload del snapshot semanal exponga de forma clara: - - el rango temporal real usado - - si el snapshot pertenece a la semana actual o a la semana cerrada anterior - - cualquier metadato útil para que la UI no engañe al usuario -9. Ajustar la UI solo en lo mínimo necesario para reflejar correctamente el rango real que se está mostrando. -10. Mantener intacta la separación entre: - - histórico bruto - - snapshots precalculados - - live status A2S -11. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- backend/README.md -- backend/app/config.py -- backend/app/historical_storage.py -- backend/app/historical_models.py -- backend/app/historical_runner.py -- backend/app/historical_snapshots.py -- backend/app/historical_snapshot_storage.py -- backend/app/payloads.py -- backend/app/routes.py -- frontend/historico.html -- frontend/assets/js/historico.js -- frontend/assets/css/historico.css - -## Expected Files to Modify -- backend/README.md -- backend/app/config.py -- backend/app/historical_runner.py -- backend/app/historical_snapshots.py -- backend/app/historical_snapshot_storage.py -- backend/app/payloads.py -- backend/app/routes.py -- opcionalmente frontend/assets/js/historico.js si hace falta reflejar el rango semanal real usado -- opcionalmente documentación técnica adicional - -## Constraints -- No usar A2S para esta lógica histórica. -- No volver a queries pesadas on-demand como solución principal. -- No crear páginas nuevas. -- No romper la UI histórica existente. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en generación real de snapshots y fallback semanal coherente. - -## Validation -- La página histórica deja de mostrar “sin snapshot” cuando ya existe histórico bruto suficiente. -- Se generan snapshots de resumen, leaderboard semanal y partidas recientes. -- El leaderboard semanal puede usar la semana anterior cuando la actual aún no tiene muestra suficiente. -- El payload expone claramente el rango temporal real mostrado. -- La UI deja claro qué semana está viendo el usuario. -- Los cambios quedan committeados y se hace push al remoto si el entorno lo permite. - -## Change Budget -- Preferir menos de 7 archivos modificados o creados. -- Preferir menos de 260 líneas cambiadas. - -## Outcome -- La generacion de snapshots historicos deja de depender solo del runner periodico: `bootstrap` y `refresh` regeneran y persisten snapshots al terminar correctamente. -- Se consolidaron snapshots reales para `server-summary`, `weekly-leaderboard` y `recent-matches`. -- El ranking semanal paso de una ventana movil de 7 dias a una semana calendario UTC con fallback explicito a la semana cerrada anterior. -- Se definio "muestra suficiente" como minimo `3` partidas cerradas en la semana actual; el fallback puede aplicarse entre lunes y miercoles UTC si esa muestra aun no existe. -- El payload semanal ahora expone `window_start`, `window_end`, `window_kind`, `window_label`, `uses_fallback`, `selection_reason`, `current_week_closed_matches`, `previous_week_closed_matches` y `sufficient_sample`. -- La UI historica ajusta el texto de la ventana semanal para reflejar el rango real mostrado y avisar cuando se esta viendo temporalmente la semana cerrada anterior. -- Se supero ligeramente el presupuesto orientativo de lineas por mantener la logica de seleccion semanal y la documentacion operativa en un mismo cambio acotado. - -## Validation Notes -- `python -m py_compile backend/app/config.py backend/app/historical_storage.py backend/app/historical_snapshots.py backend/app/historical_runner.py backend/app/historical_ingestion.py backend/app/payloads.py` -- `generate_and_persist_historical_snapshots(server_key='comunidad-hispana-01')` persistio `6` snapshots para el servidor activo. -- Los builders de payload devolvieron `found: True` para `server-summary`, `weekly-leaderboard` y `recent-matches` en `comunidad-hispana-01`. -- Con la base SQLite local actual, el snapshot semanal activo devuelve `window_kind: previous-closed-week-fallback`, `uses_fallback: True`, `current_week_closed_matches: 0` y `previous_week_closed_matches: 44`, lo que valida el fallback real a fecha `2026-03-23`. -- Se valido el nuevo encadenado de ingesta -> regeneracion de snapshots con una ejecucion local stubbeada de `run_incremental_refresh(...)` sin depender de red; el resultado incluyo `snapshot_result.snapshot_count = 6`. -- `git diff --name-only` confirma que solo cambiaron archivos del backend historico, la documentacion backend y el JS minimo de la pagina historica. diff --git a/ai/tasks/done/TASK-046-near-full-width-master-shell.md b/ai/tasks/done/TASK-046-near-full-width-master-shell.md deleted file mode 100644 index 7e773de..0000000 --- a/ai/tasks/done/TASK-046-near-full-width-master-shell.md +++ /dev/null @@ -1,44 +0,0 @@ -# TASK-046-near-full-width-master-shell - -## Goal -Sustituir la columna central demasiado estrecha por un shell maestro mucho más ancho, de forma que la landing use casi todo el ancho útil de desktop y reduzca drásticamente el espacio vacío lateral. - -## Context -La UI ya unificó las secciones bajo un mismo sistema de anchura, pero ese sistema sigue siendo demasiado estrecho. El resultado es una página encajada en el centro con mucho espacio muerto a izquierda y derecha. El objetivo de esta task es ampliar el carril principal de la landing hasta un ancho cercano al total útil de la ventana, manteniendo márgenes razonables. - -## Steps -1. Revisar el shell principal actual y cualquier `max-width` asociado. -2. Sustituir el ancho maestro actual por uno claramente más amplio en desktop. -3. Usar una referencia tipo: - - `width: min(1600px, calc(100vw - 64px))` - o equivalente coherente con el diseño actual. -4. Mantener márgenes laterales razonables sin dejar la web pegada a los bordes. -5. Asegurar que el comportamiento responsive en tablet y móvil siga siendo correcto. -6. No rediseñar contenidos; solo ampliar el carril principal de la landing. - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- frontend/index.html -- frontend/assets/css/styles.css - -## Expected Files to Modify -- frontend/assets/css/styles.css -- frontend/index.html si fuera necesario alinear wrappers - -## Constraints -- No tocar backend. -- No añadir librerías nuevas. -- No hacer cambios destructivos. -- Mantener la identidad visual actual. -- Mantener el trabajo centrado en el shell principal. - -## Validation -- La página usa mucho mejor el ancho disponible en desktop. -- Disminuye claramente el espacio vacío lateral. -- Hero, tráiler y servidores siguen alineados en un mismo carril visual. -- Tablet y móvil no se rompen. - -## Change Budget -- Preferir menos de 2 archivos modificados. -- Preferir menos de 120 líneas cambiadas. diff --git a/ai/tasks/done/TASK-047-fix-server-02-snapshot-generation.md b/ai/tasks/done/TASK-047-fix-server-02-snapshot-generation.md deleted file mode 100644 index b989d76..0000000 --- a/ai/tasks/done/TASK-047-fix-server-02-snapshot-generation.md +++ /dev/null @@ -1,86 +0,0 @@ -# TASK-047-fix-server-02-snapshot-generation - -## Goal -Diagnosticar y corregir por qué `comunidad-hispana-02` sigue apareciendo sin snapshots válidos en la UI histórica, asegurando que resumen, tops y partidas recientes se generen y queden disponibles igual que en `comunidad-hispana-01`. - -## Context -La capa histórica ya genera snapshots funcionales para al menos uno de los servidores, pero en la práctica `comunidad-hispana-02` sigue mostrando estados vacíos o “sin snapshot” en la interfaz. El problema no parece ser la ausencia de soporte de servidor en el código, sino un fallo de generación, persistencia, selección o consumo de snapshots. Antes de seguir ampliando la plataforma histórica, hay que dejar corregida la paridad entre ambos servidores actuales. - -## Steps -1. Revisar la configuración histórica actual de `comunidad-hispana-01` y `comunidad-hispana-02`. -2. Revisar la ruta completa de snapshots para ambos servidores: - - histórico bruto - - generación de snapshots - - persistencia de snapshots - - lectura de snapshots - - consumo frontend -3. Identificar por qué `comunidad-hispana-02` no devuelve snapshots válidos aunque exista histórico bruto o soporte parcial. -4. Corregir la causa raíz, ya sea en: - - mapeo de servidor - - generación - - persistencia - - recuperación - - cache frontend -5. Asegurar que para `comunidad-hispana-02` queden disponibles snapshots de: - - resumen - - leaderboard semanal por métrica - - partidas recientes -6. Verificar que ambos servidores actuales se comportan de forma equivalente. -7. Documentar brevemente la causa detectada y la corrección. -8. No añadir todavía el servidor #03 en esta task. -9. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- backend/README.md -- backend/app/config.py -- backend/app/historical_ingestion.py -- backend/app/historical_storage.py -- backend/app/historical_snapshot_storage.py -- backend/app/historical_snapshots.py -- backend/app/payloads.py -- backend/app/routes.py -- frontend/historico.html -- frontend/assets/js/historico.js -- frontend/assets/css/historico.css -- docs/historical-coverage-report.md -- docs/historical-data-quality-notes.md - -## Expected Files to Modify -- backend/app/historical_ingestion.py -- backend/app/historical_storage.py -- backend/app/historical_snapshot_storage.py -- backend/app/historical_snapshots.py -- backend/app/payloads.py -- backend/app/routes.py -- frontend/assets/js/historico.js -- backend/README.md -- opcionalmente documentación técnica adicional si ayuda a dejar trazabilidad - -## Constraints -- No usar A2S para esta corrección. -- No crear páginas nuevas. -- No romper el flujo actual de `comunidad-hispana-01`. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en que `comunidad-hispana-02` tenga snapshots funcionales. - -## Validation -- `comunidad-hispana-02` deja de mostrar estados vacíos si existe histórico suficiente. -- Resumen, tops y partidas recientes funcionan también para `comunidad-hispana-02`. -- No se rompe `comunidad-hispana-01`. -- Los cambios quedan committeados y se hace push si el entorno lo permite. - -## Change Budget -- Preferir menos de 7 archivos modificados o creados. -- Preferir menos de 260 líneas cambiadas. - -## Outcome -- Causa detectada: `comunidad-hispana-02` ya tenía histórico bruto persistido, pero la API de snapshots devolvía `found: false` cuando faltaba la fila precalculada en `historical_precomputed_snapshots`, sin recomponerla desde `historical_*`. -- Corrección aplicada: los builders de payload histórico ahora regeneran automáticamente el lote de snapshots del servidor solicitado cuando falta una fila precalculada y luego reintentan la lectura. -- Validación realizada: -- simulación sobre una copia del SQLite eliminando las filas de snapshot de `comunidad-hispana-02` -- la API recompuso `6` snapshots del servidor y devolvió `found: true` para resumen, ranking semanal y partidas recientes -- verificado también el SQLite real: `comunidad-hispana-02` queda con `6` snapshots persistidos diff --git a/ai/tasks/done/TASK-047-remove-nested-width-constraints.md b/ai/tasks/done/TASK-047-remove-nested-width-constraints.md deleted file mode 100644 index 72e451e..0000000 --- a/ai/tasks/done/TASK-047-remove-nested-width-constraints.md +++ /dev/null @@ -1,44 +0,0 @@ -# TASK-047-remove-nested-width-constraints - -## Goal -Eliminar o corregir restricciones internas de anchura que siguen estrechando hero, tráiler y panel de servidores aunque el shell principal se haya ensanchado. - -## Context -En la UI actual hay indicios claros de que, además del shell principal, existen wrappers interiores o `max-width` secundarios que mantienen las secciones demasiado estrechas. Esta task debe identificar y eliminar esas restricciones internas para que cada sección ocupe realmente el ancho disponible del carril principal. - -## Steps -1. Revisar la estructura HTML y CSS de hero, tráiler y panel de servidores. -2. Identificar wrappers internos con `max-width`, anchuras fijas o márgenes automáticos que estrechen el contenido. -3. Corregir esas restricciones para que: - - hero - - tráiler - - panel de servidores - usen `width: 100%` dentro del shell principal. -4. Mantener una composición limpia y centrada, sin volver a una columna estrecha. -5. Evitar que un wrapper interno rompa el ancho unificado buscado. -6. No rediseñar secciones; solo liberar el ancho real utilizable. - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- frontend/index.html -- frontend/assets/css/styles.css - -## Expected Files to Modify -- frontend/index.html -- frontend/assets/css/styles.css - -## Constraints -- No tocar backend. -- No añadir librerías nuevas. -- No hacer cambios destructivos. -- Mantener la estructura visual existente salvo correcciones de anchura. - -## Validation -- No quedan wrappers interiores que vuelvan a estrechar las secciones principales. -- Hero, tráiler y servidores ocupan realmente el ancho del shell maestro. -- La sensación de “columna central demasiado angosta” desaparece o se reduce claramente. - -## Change Budget -- Preferir menos de 2 archivos modificados. -- Preferir menos de 120 líneas cambiadas. diff --git a/ai/tasks/done/TASK-048-add-server-03-historical-source-and-ingestion.md b/ai/tasks/done/TASK-048-add-server-03-historical-source-and-ingestion.md deleted file mode 100644 index 0b55daf..0000000 --- a/ai/tasks/done/TASK-048-add-server-03-historical-source-and-ingestion.md +++ /dev/null @@ -1,79 +0,0 @@ -# TASK-048-add-server-03-historical-source-and-ingestion - -## Goal -Añadir el tercer servidor histórico de la comunidad (`https://scoreboard.comunidadhll.es:3443/`) a la capa histórica del proyecto, dejándolo preparado para ingesta, snapshots y consumo posterior por la UI propia. - -## Context -Ahora mismo el proyecto trabaja con dos servidores históricos de comunidad, pero existe un tercer servidor real: -- `https://scoreboard.comunidadhll.es:3443/` - -El sistema debe poder tratarlo como una tercera fuente histórica formal, no como un caso manual o externo, manteniendo la misma arquitectura de ingestión, persistencia y snapshots propia del proyecto. - -## Steps -1. Revisar cómo están definidos hoy los servidores históricos actuales. -2. Añadir la configuración y el mapeo del tercer servidor con una identidad estable, por ejemplo: - - `comunidad-hispana-03` -3. Asegurar que la capa de ingestión histórica puede consultar la fuente CRCON JSON del puerto `3443`. -4. Preparar la persistencia histórica para ese servidor: - - matches - - players - - stats por match - - checkpoints/backfill -5. Integrar el tercer servidor en la capa de snapshots: - - resumen - - rankings semanales - - partidas recientes -6. Ajustar documentación y configuración operativa para reflejar que ya existen tres servidores históricos. -7. No exponer todavía UI nueva si no es imprescindible en esta task. -8. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- backend/README.md -- backend/app/config.py -- backend/app/historical_ingestion.py -- backend/app/historical_storage.py -- backend/app/historical_snapshot_storage.py -- backend/app/historical_snapshots.py -- backend/app/payloads.py -- backend/app/routes.py -- docs/historical-crcon-source-discovery.md -- docs/historical-domain-model.md - -## Expected Files to Modify -- backend/app/config.py -- backend/app/historical_ingestion.py -- backend/app/historical_storage.py -- backend/app/historical_snapshot_storage.py -- backend/app/historical_snapshots.py -- backend/app/payloads.py -- backend/app/routes.py -- backend/README.md -- opcionalmente documentación técnica adicional - -## Constraints -- No usar A2S para el histórico del servidor #03. -- No crear páginas externas o dependientes de la comunidad. -- No romper los servidores #01 y #02. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en registrar correctamente el servidor #03 en la plataforma histórica. - -## Validation -- El servidor #03 queda definido con identidad estable en backend. -- La ingesta histórica puede trabajar con su fuente. -- La capa de snapshots queda preparada para ese servidor. -- La documentación backend refleja el nuevo servidor. -- Los cambios quedan committeados y se hace push si el entorno lo permite. - -## Change Budget -- Preferir menos de 7 archivos modificados o creados. -- Preferir menos de 260 líneas cambiadas. - -## Outcome -- Se añadió `comunidad-hispana-03` como tercera fuente histórica estable en el seed declarativo de `historical_servers`, con `scoreboard_base_url` `https://scoreboard.comunidadhll.es:3443` y `server_number` `3`. -- La validación local de `list_historical_servers()` confirma que el backend ya registra `3` servidores históricos. -- La validación local de `build_historical_server_snapshots(server_key='comunidad-hispana-03')` devuelve el lote esperado de `6` snapshots, dejando preparada la capa para ingesta, persistencia y consumo posterior aunque la UI aún no se haya ampliado en esta task. -- Se actualizó la documentación backend y de dominio para reflejar la nueva fuente histórica. diff --git a/ai/tasks/done/TASK-048-wide-desktop-server-grid-pass.md b/ai/tasks/done/TASK-048-wide-desktop-server-grid-pass.md deleted file mode 100644 index a2b0b28..0000000 --- a/ai/tasks/done/TASK-048-wide-desktop-server-grid-pass.md +++ /dev/null @@ -1,43 +0,0 @@ -# TASK-048-wide-desktop-server-grid-pass - -## Goal -Aprovechar el nuevo ancho de desktop para que el panel de servidores use una rejilla más amplia y cómoda, evitando que las tarjetas sigan viéndose pequeñas o demasiado encerradas. - -## Context -Una vez ampliado el shell principal y eliminadas restricciones internas, el panel de servidores debe beneficiarse directamente de ese ancho. Si la rejilla sigue siendo demasiado conservadora, la página seguirá dando sensación de estrechez aunque el contenedor ya sea ancho. - -## Steps -1. Revisar la rejilla actual del panel de servidores. -2. Ajustar el grid para que aproveche mejor desktop ancho. -3. Usar una estrategia robusta tipo: - - `repeat(auto-fit, minmax(360px, 1fr))` - o equivalente mejor adaptada al diseño actual. -4. Revisar gaps, paddings y anchuras mínimas para evitar tarjetas pequeñas o apretadas. -5. Mantener buen comportamiento en tablet y móvil. -6. No rediseñar la tarjeta; centrarse en cómo la rejilla usa el ancho disponible. - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- frontend/assets/css/styles.css -- frontend/assets/js/main.js -- frontend/index.html - -## Expected Files to Modify -- frontend/assets/css/styles.css -- frontend/index.html si hiciera falta alinear clases o wrappers - -## Constraints -- No tocar backend. -- No añadir librerías nuevas. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en grid y aprovechamiento del ancho. - -## Validation -- El panel de servidores se ve más amplio y mejor repartido en desktop. -- Las tarjetas dejan de sentirse pequeñas o encajadas. -- La UI mantiene buena lectura en tablet y móvil. - -## Change Budget -- Preferir menos de 2 archivos modificados. -- Preferir menos de 120 líneas cambiadas. diff --git a/ai/tasks/done/TASK-049-global-all-servers-historical-tops.md b/ai/tasks/done/TASK-049-global-all-servers-historical-tops.md deleted file mode 100644 index 2aa7b76..0000000 --- a/ai/tasks/done/TASK-049-global-all-servers-historical-tops.md +++ /dev/null @@ -1,81 +0,0 @@ -# TASK-049-global-all-servers-historical-tops - -## Goal -Añadir soporte para rankings históricos globales agregando los tres servidores de la comunidad, de forma que el proyecto pueda mostrar tops totales además de tops por servidor. - -## Context -Actualmente los rankings históricos están organizados por servidor. El siguiente paso es poder consultar tops globales, por ejemplo: -- top kills total -- top muertes total -- top soporte total -- top partidas con más de 100 kills total - -La forma más limpia es tratar este agregado como una entidad lógica propia, por ejemplo `all-servers`, compatible con la capa de snapshots y con la futura UI. - -## Steps -1. Revisar la estructura actual de rankings históricos por servidor. -2. Diseñar una estrategia clara para soportar rankings totales agregados, preferiblemente mediante una clave lógica como: - - `all-servers` -3. Implementar el agregado global para: - - top kills - - top muertes - - top soporte - - top partidas con más de 100 kills -4. Asegurar que estos rankings globales: - - no mezclan mal identidades de jugador - - respetan la ventana semanal o política temporal definida - - son compatibles con snapshots -5. Integrar el agregado global en resumen y metadatos cuando aplique. -6. Documentar la semántica de `all-servers`. -7. No crear todavía una UI nueva compleja en esta task si no es estrictamente necesario. -8. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- backend/README.md -- backend/app/historical_storage.py -- backend/app/historical_snapshot_storage.py -- backend/app/historical_snapshots.py -- backend/app/payloads.py -- backend/app/routes.py -- docs/historical-domain-model.md -- docs/historical-data-quality-notes.md - -## Expected Files to Modify -- backend/app/historical_storage.py -- backend/app/historical_snapshot_storage.py -- backend/app/historical_snapshots.py -- backend/app/payloads.py -- backend/app/routes.py -- backend/README.md -- opcionalmente documentación técnica adicional - -## Constraints -- No romper rankings por servidor existentes. -- No usar A2S para rankings globales históricos. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en el agregado global de tops y snapshots. - -## Validation -- Existe soporte histórico para tops globales `all-servers`. -- Los rankings globales funcionan para las métricas ya soportadas. -- Los rankings por servidor siguen funcionando. -- La documentación backend refleja la nueva capacidad. -- Los cambios quedan committeados y se hace push si el entorno lo permite. - -## Change Budget -- Preferir menos de 6 archivos modificados o creados. -- Preferir menos de 240 líneas cambiadas. - -## Outcome -- Se añadió la clave lógica `all-servers` para la capa histórica agregada sin crear una fila física adicional en `historical_servers`. -- `list_weekly_leaderboard()` y los payloads/snapshots asociados ya devuelven rankings globales para `kills`, `deaths`, `support` y `matches_over_100_kills`. -- `list_historical_server_summaries(server_slug='all-servers')` devuelve un resumen agregado con identidad estable `all-servers`. -- `list_snapshot_server_keys()` ya incluye `all-servers`, por lo que la capa de snapshots queda compatible con el agregado global. -- Validación local: -- `list_weekly_leaderboard(server_id='all-servers', metric='kills', limit=5)` devolvió resultados agregados con servidor lógico `all-servers` -- `build_historical_server_snapshots(server_key='all-servers')` devolvió `6` snapshots -- `build_weekly_leaderboard_snapshot_payload(server_id='all-servers', metric='kills')` devolvió `found: true` diff --git a/ai/tasks/done/TASK-049-remove-nonessential-copy-and-technical-badges.md b/ai/tasks/done/TASK-049-remove-nonessential-copy-and-technical-badges.md deleted file mode 100644 index 99444fb..0000000 --- a/ai/tasks/done/TASK-049-remove-nonessential-copy-and-technical-badges.md +++ /dev/null @@ -1,62 +0,0 @@ -# TASK-049-remove-nonessential-copy-and-technical-badges - -## Goal -Eliminar de la landing los textos descriptivos y etiquetas tecnicas que no aportan valor al usuario final, dejando una interfaz mas limpia, directa y orientada a producto final. - -## Context -La UI ya esta en una fase suficientemente madura como para prescindir de copy de presentacion y de labels internos o tecnicos. Actualmente siguen apareciendo textos de relleno o de tono demasiado explicativo, asi como etiquetas como "Snapshot real A2S", que no deberian estar visibles en la vista principal publica. - -## Steps -1. Revisar el hero, bloque de trailer y bloque de servidores. -2. Eliminar o simplificar textos descriptivos no esenciales, incluyendo ejemplos como: - - descripciones explicativas del trailer - - copy redundante del bloque de servidores - - textos internos de validacion o sistema -3. Eliminar de las tarjetas reales etiquetas tecnicas como: - - "Snapshot real A2S" -4. Revisar tambien chips o badges secundarios que aporten poco valor al usuario final. -5. Mantener solo el texto minimo necesario para entender cada seccion. -6. Preservar claridad y estetica sin dejar la pagina vacia ni fria. -7. No tocar backend en esta task. - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- frontend/index.html -- frontend/assets/js/main.js -- frontend/assets/css/styles.css - -## Expected Files to Modify -- frontend/index.html -- frontend/assets/js/main.js -- frontend/assets/css/styles.css - -## Constraints -- No tocar backend. -- No eliminar informacion util de servidor como mapa, jugadores, region, estado, ultima actualizacion y CTA. -- No anadir librerias nuevas. -- No hacer cambios destructivos. -- Mantener el ajuste centrado en copy/UI. - -## Validation -- Desaparecen textos descriptivos innecesarios. -- Desaparecen etiquetas tecnicas como "Snapshot real A2S". -- La pagina se percibe mas limpia y mas finalista. -- La informacion util del servidor sigue intacta. - -## Change Budget -- Preferir menos de 3 archivos modificados. -- Preferir menos de 120 lineas cambiadas. - -## Outcome -- `frontend/index.html` elimina copy descriptivo del hero y del bloque de trailer, simplifica el encabezado de servidores y quita etiquetas secundarias en las tarjetas estaticas. -- `frontend/assets/js/main.js` sustituye textos tecnicos por textos de producto mas directos y elimina labels internos visibles en tarjetas y estados del bloque de servidores. -- `frontend/assets/css/styles.css` elimina el estilo del texto descriptivo del hero ya retirado del markup. - -## Validation Result -- Validado con `node --check frontend/assets/js/main.js`. -- Verificado con `rg` que ya no quedan labels visibles como `Snapshot real A2S`, `Fallback estatico`, `Servidor de referencia` o equivalentes en `frontend/`. -- Revisado en diff: la task queda limitada a `frontend/index.html`, `frontend/assets/js/main.js`, `frontend/assets/css/styles.css` y este archivo de task. El cambio no toca backend. - -## Decision Notes -- Se mantuvo una nota breve en el bloque de servidores para no dejar la seccion fria, pero se reescribio a una forma claramente orientada a usuario final y sin lenguaje interno del sistema. diff --git a/ai/tasks/done/TASK-050-file-based-historical-snapshots.md b/ai/tasks/done/TASK-050-file-based-historical-snapshots.md deleted file mode 100644 index e974db3..0000000 --- a/ai/tasks/done/TASK-050-file-based-historical-snapshots.md +++ /dev/null @@ -1,86 +0,0 @@ -# TASK-050-file-based-historical-snapshots - -## Goal -Migrar la capa de snapshots históricos orientados a UI desde almacenamiento SQLite a archivos JSON independientes en disco, manteniendo SQLite para el histórico bruto y dejando los snapshots como artefactos rápidos, inspeccionables y fáciles de servir. - -## Context -El proyecto ya usa snapshots precalculados, pero actualmente se almacenan en SQLite. Se quiere cambiar el enfoque para que cada snapshot UI exista como archivo JSON independiente, actualizado periódicamente por backend y consumido a través de la API propia. La razón es reducir complejidad percibida, facilitar inspección/depuración y reforzar una carga rápida y estable del frontend. - -El histórico bruto persistido en SQLite debe mantenerse. Lo que cambia en esta task es solo la capa de snapshots precalculados de UI. - -## Steps -1. Revisar la capa actual de snapshots precalculados en SQLite. -2. Diseñar una nueva estructura de archivos para snapshots en disco, por ejemplo: - - `backend/data/snapshots/comunidad-hispana-01/server-summary.json` - - `backend/data/snapshots/comunidad-hispana-01/weekly-kills.json` - - `backend/data/snapshots/comunidad-hispana-01/weekly-deaths.json` - - `backend/data/snapshots/comunidad-hispana-01/weekly-support.json` - - `backend/data/snapshots/comunidad-hispana-01/weekly-matches-over-100-kills.json` - - `backend/data/snapshots/comunidad-hispana-01/recent-matches.json` - - y equivalentes para `comunidad-hispana-02`, `comunidad-hispana-03` y `all-servers` -3. Implementar almacenamiento y lectura de snapshots en JSON. -4. Migrar la generación de snapshots para que escriba estos archivos. -5. Mantener metadatos útiles dentro de cada snapshot, como: - - generated_at - - source_range_start - - source_range_end - - freshness / is_stale - - found - - política semanal usada si aplica -6. Mantener SQLite para histórico bruto y no mezclar ambas capas. -7. Documentar claramente la nueva arquitectura: - - histórico bruto en SQLite - - snapshots UI en archivos JSON -8. No romper todavía la UI actual. -9. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- backend/README.md -- backend/app/historical_storage.py -- backend/app/historical_snapshot_storage.py -- backend/app/historical_snapshots.py -- backend/app/historical_runner.py -- backend/app/payloads.py -- backend/app/routes.py -- docs/historical-domain-model.md - -## Expected Files to Modify -- backend/README.md -- backend/app/historical_snapshot_storage.py -- backend/app/historical_snapshots.py -- backend/app/historical_runner.py -- backend/app/payloads.py -- backend/app/routes.py -- opcionalmente nuevos módulos auxiliares, por ejemplo: - - backend/app/historical_file_snapshots.py -- opcionalmente documentación técnica adicional - -## Constraints -- No eliminar SQLite del histórico bruto. -- No romper la API histórica existente salvo para adaptarla a la nueva fuente de snapshots. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en pasar snapshots UI a JSON en disco. - -## Validation -- Los snapshots UI se generan y guardan como archivos JSON independientes en disco. -- El histórico bruto sigue persistiendo en SQLite. -- La API histórica puede servir esos snapshots correctamente. -- La estructura es inspeccionable y mantenible. -- Los cambios quedan committeados y se hace push si el entorno lo permite. - -## Change Budget -- Preferir menos de 7 archivos modificados o creados. -- Preferir menos de 260 líneas cambiadas. - -## Outcome -- La persistencia de snapshots históricos orientados a UI se migró de SQLite a archivos JSON bajo `backend/data/snapshots//`. -- `historical_snapshot_storage.py` conserva la misma interfaz pública (`persist_*`, `get_*`, `list_*`) pero ahora escribe y lee archivos como `server-summary.json`, `weekly-kills.json` y `recent-matches.json`. -- SQLite se mantiene exclusivamente para el histórico bruto (`historical_*`) y ya no es la fuente de lectura de snapshots UI. -- Validación local: -- `generate_and_persist_historical_snapshots(server_key='comunidad-hispana-03')` y `generate_and_persist_historical_snapshots(server_key='all-servers')` escribieron su lote de `6` archivos JSON cada uno -- verificado el árbol `backend/data/snapshots/` con `24` archivos JSON esperados para `comunidad-hispana-01`, `comunidad-hispana-02`, `comunidad-hispana-03` y `all-servers` -- los payloads `build_historical_server_summary_snapshot_payload(server_slug='comunidad-hispana-02')`, `build_weekly_leaderboard_snapshot_payload(server_id='all-servers', metric='kills')` y `build_recent_historical_matches_snapshot_payload(server_slug='comunidad-hispana-03')` devolvieron `found: true` diff --git a/ai/tasks/done/TASK-050-live-snapshot-refresh-and-frontend-polling-alignment.md b/ai/tasks/done/TASK-050-live-snapshot-refresh-and-frontend-polling-alignment.md deleted file mode 100644 index 02ca86e..0000000 --- a/ai/tasks/done/TASK-050-live-snapshot-refresh-and-frontend-polling-alignment.md +++ /dev/null @@ -1,67 +0,0 @@ -# TASK-050-live-snapshot-refresh-and-frontend-polling-alignment - -## Goal -Alinear la captura periodica de snapshots y el consumo del frontend para que la web muestre datos mucho mas cercanos al estado real actual de los servidores, evitando que se queden estancados durante horas. - -## Context -La pagina ya consume datos reales A2S, pero en la practica estaba mostrando snapshots demasiado antiguos, con mapas y poblacion desactualizados. Esto degrada la percepcion de fiabilidad del producto. El sistema necesitaba una politica mas util de refresco local y una lectura periodica razonable desde frontend. - -## Steps -1. Revisar como se ejecuta actualmente el scheduler local de snapshots. -2. Revisar la frecuencia de captura actual o la ausencia de ejecucion continua. -3. Definir una frecuencia de refresco razonable para entorno local de desarrollo y demo, por ejemplo: - - captura backend cada 60 segundos - - refresco frontend cada 60-90 segundos -4. Ajustar el scheduler o su configuracion para facilitar un refresco frecuente y controlado. -5. Revisar el frontend para que vuelva a consultar el backend periodicamente sin necesidad de recargar la pagina. -6. Asegurar que el refresco no rompa la UI ni genere comportamiento agresivo. -7. Mantener el sistema simple y apropiado para la fase actual. -8. Documentar claramente como arrancar el backend y el refresco para ver datos vivos. - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- backend/README.md -- backend/app/config.py -- backend/app/scheduler.py -- backend/app/collector.py -- frontend/assets/js/main.js -- frontend/index.html - -## Expected Files to Modify -- backend/README.md -- backend/app/config.py -- backend/app/scheduler.py -- frontend/assets/js/main.js -- opcionalmente frontend/index.html si requiere una alineacion minima - -## Constraints -- No introducir infraestructura pesada. -- No anadir librerias nuevas. -- No hacer cambios destructivos. -- No abrir nuevas fuentes de datos. -- Mantener la solucion simple, local y util para producto actual. - -## Validation -- El sistema puede refrescar snapshots reales con una frecuencia razonable. -- El frontend actualiza la vista sin depender de recarga manual. -- Los mapas y jugadores cambian cuando cambian realmente en los servidores. -- La documentacion deja claro como usar este flujo en local. - -## Change Budget -- Preferir menos de 5 archivos modificados. -- Preferir menos de 180 lineas cambiadas. - -## Outcome -- `backend/app/config.py` baja el intervalo por defecto del scheduler local a `60` segundos para acercar la persistencia a una demo viva. -- `backend/app/scheduler.py` alinea la ayuda del comando con ese nuevo comportamiento orientado a desarrollo y demo. -- `frontend/index.html` expone `data-server-refresh-ms=\"60000\"` y `frontend/assets/js/main.js` reutiliza ese valor para relanzar `hydrateServers()` cada `60` segundos sin recargar la pagina y sin solapar peticiones. -- `backend/README.md` documenta el flujo local recomendado con backend, scheduler y polling del frontend. - -## Validation Result -- Validado con `node --check frontend/assets/js/main.js`. -- Validado con `python -m py_compile backend/app/config.py backend/app/scheduler.py backend/app/collector.py`. -- Revisado en diff: la task queda limitada a `backend/README.md`, `backend/app/config.py`, `backend/app/scheduler.py`, `frontend/assets/js/main.js`, `frontend/index.html` y este archivo de task. - -## Decision Notes -- Se mantuvo el polling solo sobre el bloque de servidores para no convertir toda la landing en una pagina con refresco agresivo. Salud del backend y trailer siguen siendo una hidratacion inicial simple. diff --git a/ai/tasks/done/TASK-051-historical-ui-fast-snapshot-consumption.md b/ai/tasks/done/TASK-051-historical-ui-fast-snapshot-consumption.md deleted file mode 100644 index eacf287..0000000 --- a/ai/tasks/done/TASK-051-historical-ui-fast-snapshot-consumption.md +++ /dev/null @@ -1,74 +0,0 @@ -# TASK-051-historical-ui-fast-snapshot-consumption - -## Goal -Ajustar la UI histórica para consumir de forma rápida y estable los snapshots precalculados de resumen, rankings y partidas recientes, incluyendo soporte para el tercer servidor y para tops globales. - -## Context -Una vez exista una capa de snapshots en archivos JSON y estén resueltos los servidores #02 y #03, la UI histórica debe consumir esa capa sin esperas innecesarias, permitiendo cambiar de servidor o pestaña sin sensaciones de bloqueo. Además, debe soportar un selector ampliado con: -- Comunidad Hispana #01 -- Comunidad Hispana #02 -- Comunidad Hispana #03 -- Totales / Todos - -## Steps -1. Revisar la UI histórica actual y su consumo de snapshots. -2. Ajustar el selector de servidor para incluir: - - `comunidad-hispana-01` - - `comunidad-hispana-02` - - `comunidad-hispana-03` - - `all-servers` -3. Asegurar que resumen, tops y partidas recientes se cargan desde snapshots rápidos ya preparados. -4. Evitar caches frontales que congelen indefinidamente respuestas `found: false`. -5. Mantener estados de loading, empty y error, pero con una experiencia más ágil. -6. Reflejar correctamente: - - servidor seleccionado - - rango real usado - - fallback semanal si aplica -7. No depender de URLs externas de la comunidad. -8. Mantener coherencia visual con la página histórica ya existente. -9. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- frontend/historico.html -- frontend/assets/js/historico.js -- frontend/assets/css/historico.css -- backend/app/routes.py -- backend/app/payloads.py -- backend/README.md - -## Expected Files to Modify -- frontend/historico.html -- frontend/assets/js/historico.js -- frontend/assets/css/historico.css -- opcionalmente backend docs mínimas si cambia el contrato visible de consumo - -## Constraints -- No crear páginas nuevas. -- No romper la UI histórica existente. -- No introducir frameworks nuevos. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en velocidad percibida, selector ampliado y consumo de snapshots. - -## Validation -- La UI histórica soporta #01, #02, #03 y tops globales. -- Cambiar de servidor o métrica es rápido. -- No se quedan cacheadas indefinidamente respuestas vacías antiguas. -- La página consume snapshots precalculados y no agregados pesados en tiempo real. -- Los cambios quedan committeados y se hace push si el entorno lo permite. - -## Change Budget -- Preferir menos de 5 archivos modificados o creados. -- Preferir menos de 220 líneas cambiadas. - -## Outcome -- El selector histórico se amplió a `comunidad-hispana-01`, `comunidad-hispana-02`, `comunidad-hispana-03` y `all-servers`. -- La UI sigue consumiendo los endpoints propios de snapshots precalculados, pero ahora hace prefetch de resumen, partidas recientes y rankings del alcance activo para acelerar los cambios de selector y pestaña. -- La caché frontend ya no conserva indefinidamente respuestas con `found: false`; las respuestas negativas vencen rápido y se reintentan automáticamente. -- La cabecera y las notas de sección reflejan mejor el alcance activo, incluyendo el caso agregado `Totales / Todos`. -- Validación local: -- `node --check frontend/assets/js/historico.js` -- comprobación de strings y selectores en `frontend/historico.html` y `frontend/assets/js/historico.js` para `comunidad-hispana-03`, `all-servers` y `recent-matches-note` diff --git a/ai/tasks/done/TASK-051-real-server-card-minimal-product-pass.md b/ai/tasks/done/TASK-051-real-server-card-minimal-product-pass.md deleted file mode 100644 index 8290fb7..0000000 --- a/ai/tasks/done/TASK-051-real-server-card-minimal-product-pass.md +++ /dev/null @@ -1,66 +0,0 @@ -# TASK-051-real-server-card-minimal-product-pass - -## Goal -Dejar las tarjetas de servidores reales en una forma minima y orientada a producto final, mostrando solo la informacion esencial para un visitante que quiere ver estado actual y conectarse. - -## Context -Las tarjetas ya se simplificaron parcialmente, pero todavia quedaban restos de estructura y bloques secundarios que no aportaban suficiente valor. El objetivo era dejar una tarjeta muy clara y minima, centrada en estado actual del servidor. - -## Steps -1. Revisar la composicion actual de las tarjetas reales. -2. Asegurar que el contenido visible principal quede limitado a: - - nombre - - estado - - jugadores - - mapa - - region - - ultima actualizacion - - boton Conectar -3. Evaluar si promedio y pico deben quedar ocultos o pasar a una capa secundaria muy discreta. -4. Eliminar cualquier bloque residual que complique la lectura rapida. -5. Mejorar la jerarquia para que el usuario vea en pocos segundos si el servidor le interesa. -6. Mantener una composicion limpia y coherente con el ancho actual de la pagina. -7. No tocar backend salvo una alineacion menor si fuera imprescindible. - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- frontend/index.html -- frontend/assets/js/main.js -- frontend/assets/css/styles.css -- backend/app/payloads.py - -## Expected Files to Modify -- frontend/index.html -- frontend/assets/js/main.js -- frontend/assets/css/styles.css - -## Constraints -- No romper el boton Conectar. -- No eliminar la informacion util esencial. -- No anadir librerias nuevas. -- No hacer cambios destructivos. -- Mantener el ajuste centrado en UX de producto final. - -## Validation -- Las tarjetas muestran solo informacion util y clara. -- La lectura es rapida y limpia. -- No quedan bloques residuales de informacion interna o excesiva. -- La UI se siente mas final y menos experimental. - -## Change Budget -- Preferir menos de 3 archivos modificados. -- Preferir menos de 140 lineas cambiadas. - -## Outcome -- `frontend/assets/js/main.js` deja las tarjetas dinamicas en su forma minima: identidad, estado, jugadores, mapa, region, ultima actualizacion y CTA cuando existe destino conectable. -- `frontend/index.html` alinea las tarjetas estaticas de fallback con esa misma estructura minima. -- `frontend/assets/css/styles.css` elimina estilos de bloques residuales ya innecesarios, como la barra de carga y los encabezados intermedios de seccion, para reforzar una lectura mas rapida. - -## Validation Result -- Validado con `node --check frontend/assets/js/main.js`. -- Verificado con `rg` que ya no quedan restos de `server-card__load`, `server-panel-section`, ni texto asociado a metricas o bloques historicos secundarios dentro de `frontend/`. -- Revisado en diff: la task queda limitada a `frontend/index.html`, `frontend/assets/js/main.js`, `frontend/assets/css/styles.css` y este archivo de task. - -## Decision Notes -- Se elimino la barra visual de ocupacion porque duplicaba la informacion ya expresada por `Jugadores` y cargaba la tarjeta sin mejorar la decision principal del visitante. diff --git a/ai/tasks/done/TASK-052-historical-ui-initial-load-performance-pass.md b/ai/tasks/done/TASK-052-historical-ui-initial-load-performance-pass.md deleted file mode 100644 index 58ae1fb..0000000 --- a/ai/tasks/done/TASK-052-historical-ui-initial-load-performance-pass.md +++ /dev/null @@ -1,72 +0,0 @@ -# TASK-052-historical-ui-initial-load-performance-pass - -## Goal -Reducir drásticamente el tiempo percibido de carga inicial de `historico.html`, evitando peticiones innecesarias al entrar, eliminando precargas agresivas y permitiendo que resumen, ranking y partidas recientes se hidraten de forma progresiva e independiente. - -## Context -La página histórica ya consume snapshots rápidos, pero el comportamiento actual sigue generando una experiencia lenta: -- se lanzan varias peticiones de snapshots al entrar -- se precargan varias métricas de leaderboard demasiado pronto -- hay prefetch por interacción ligera o por estrategia demasiado agresiva -- la UI tarda en mostrar contenido útil porque espera más de la cuenta antes de hidratar bloques visibles - -El objetivo de esta task es que la carga inicial sea más ligera y que el usuario vea contenido útil antes, aunque el resto de bloques sigan llegando progresivamente. - -## Steps -1. Revisar `frontend/assets/js/historico.js` y la estrategia actual de carga inicial. -2. Identificar y reducir las peticiones lanzadas al entrar en la página para el servidor activo. -3. Hacer que en la carga inicial solo se pidan los datos estrictamente necesarios para pintar la primera vista útil, como mínimo: - - resumen del servidor activo - - leaderboard de la pestaña activa - - partidas recientes del servidor activo -4. Evitar que en la carga inicial se precarguen automáticamente todas las métricas del leaderboard si no son visibles todavía. -5. Eliminar o reducir estrategias agresivas de prefetch por `hover`, `focus` o cambios ligeros de interacción si están disparando peticiones innecesarias. -6. Cambiar la hidratación para que los bloques visibles se pinten de forma progresiva e independiente, sin esperar a que todo el conjunto termine si un bloque ya está listo. -7. Mantener estados de loading por bloque, pero evitar que toda la página parezca “bloqueada” por el snapshot más lento. -8. Revisar y ajustar el caché frontend para que ayude a la velocidad sin mantener estados vacíos obsoletos demasiado tiempo. -9. No cambiar la semántica funcional de los datos históricos, solo mejorar la estrategia de carga y renderizado. -10. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- frontend/historico.html -- frontend/assets/js/historico.js -- frontend/assets/css/historico.css -- backend/app/routes.py -- backend/app/payloads.py -- backend/README.md - -## Expected Files to Modify -- frontend/assets/js/historico.js -- frontend/historico.html -- frontend/assets/css/historico.css -- opcionalmente documentación mínima si el comportamiento visible cambia de forma relevante - -## Constraints -- No crear páginas nuevas. -- No romper la UI histórica existente. -- No introducir frameworks nuevos. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en rendimiento percibido y estrategia de carga. - -## Validation -- La carga inicial hace menos peticiones que antes. -- La página empieza a mostrar contenido útil antes. -- Resumen, leaderboard activo y partidas recientes se hidratan de forma progresiva. -- No se precargan de forma agresiva métricas no visibles en el primer paint. -- Los cambios quedan committeados y se hace push si el entorno lo permite. - -## Change Budget -- Preferir menos de 4 archivos modificados. -- Preferir menos de 220 líneas cambiadas. - -## Outcome -- La carga inicial de `historico.html` ya no dispara precarga agresiva de todos los snapshots ni peticiones por `hover` o `focus` sobre el selector de servidor. -- La UI reutiliza snapshots cacheados de resumen, ranking activo y partidas recientes cuando existen, reduciendo la espera percibida en entradas posteriores y cambios de servidor. -- Resumen, leaderboard activo y partidas recientes se hidratan ahora de forma independiente; el bloque que llega antes se pinta antes, sin esperar al snapshot más lento. -- Validación local: -- `node --check frontend/assets/js/historico.js` -- revisión de `git diff --name-only` para confirmar alcance limitado a `frontend/assets/js/historico.js` y el archivo de task diff --git a/ai/tasks/done/TASK-053-historical-snapshots-read-only-fast-path.md b/ai/tasks/done/TASK-053-historical-snapshots-read-only-fast-path.md deleted file mode 100644 index 959e983..0000000 --- a/ai/tasks/done/TASK-053-historical-snapshots-read-only-fast-path.md +++ /dev/null @@ -1,74 +0,0 @@ -# TASK-053-historical-snapshots-read-only-fast-path - -## Goal -Asegurar que los endpoints de snapshots históricos se comportan como una capa de lectura rápida y no intentan recomponer o regenerar snapshots costosos durante la solicitud del usuario. - -## Context -La página histórica debe sentirse rápida. Para conseguirlo, los snapshots deben existir previamente y leerse de forma casi inmediata. Si una petición a la UI termina provocando una recomposición, una regeneración parcial o una ruta de fallback costosa, el tiempo percibido se degrada mucho. La generación debe vivir en la capa de bootstrap/runner/scheduler, no en la interacción del usuario. - -## Steps -1. Revisar la implementación actual de los endpoints de snapshots históricos y la lógica de payload para: - - resumen - - weekly leaderboard - - partidas recientes -2. Identificar si alguna de esas rutas intenta recomponer, regenerar o recalcular snapshots costosos durante la petición. -3. Corregir el comportamiento para que los endpoints de snapshots: - - lean snapshots ya existentes - - respondan rápido - - devuelvan metadatos claros si el snapshot no está listo - - no bloqueen la solicitud por regeneración pesada -4. Mantener el sistema de generación y refresco de snapshots en la capa operativa adecuada: - - bootstrap - - refresh - - runner periódico -5. Asegurar que cuando un snapshot no exista, la respuesta sea rápida y clara, sin dejar al usuario esperando recomposición pesada. -6. Documentar el contrato operativo esperado: lectura rápida en request path, generación fuera del request path. -7. No cambiar la UI en esta task salvo lo estrictamente necesario para reflejar metadatos ya existentes. -8. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- backend/README.md -- backend/app/routes.py -- backend/app/payloads.py -- backend/app/historical_snapshot_storage.py -- backend/app/historical_snapshots.py -- backend/app/historical_runner.py -- backend/app/historical_ingestion.py - -## Expected Files to Modify -- backend/app/routes.py -- backend/app/payloads.py -- backend/app/historical_snapshot_storage.py -- backend/app/historical_snapshots.py -- backend/README.md -- opcionalmente documentación técnica adicional si hace falta dejar la política clara - -## Constraints -- No usar A2S para esta capa. -- No volver a agregados on-demand pesados como estrategia principal. -- No crear páginas nuevas. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en un fast read path para snapshots. - -## Validation -- Los endpoints de snapshots responden como lectura rápida. -- No hay recomposición pesada o regeneración costosa en el request path del usuario. -- Si un snapshot no existe, la respuesta es rápida y clara. -- La documentación deja clara la política operativa. -- Los cambios quedan committeados y se hace push si el entorno lo permite. - -## Change Budget -- Preferir menos de 5 archivos modificados o creados. -- Preferir menos de 220 líneas cambiadas. - -## Outcome -- Los endpoints `/api/historical/snapshots/*` ya no intentan recomponer ni regenerar snapshots durante la petición del usuario. -- Cuando un snapshot no existe, la API responde rápido con metadata explícita de fast path: `snapshot_status`, `missing_reason`, `request_path_policy` y `generation_policy`. -- La política operativa queda documentada en `backend/README.md`: lectura rápida en request path y generación solo en `historical_ingestion` o `historical_runner`. -- Validación local: -- import y ejecución de `build_historical_server_summary_snapshot_payload(server_slug='comunidad-hispana-01')` -- `py_compile` sobre `backend/app/payloads.py`, `backend/app/routes.py` y `backend/app/historical_snapshot_storage.py` diff --git a/ai/tasks/done/TASK-054-historical-snapshots-prewarm-and-cache-policy.md b/ai/tasks/done/TASK-054-historical-snapshots-prewarm-and-cache-policy.md deleted file mode 100644 index dce1896..0000000 --- a/ai/tasks/done/TASK-054-historical-snapshots-prewarm-and-cache-policy.md +++ /dev/null @@ -1,74 +0,0 @@ -# TASK-054-historical-snapshots-prewarm-and-cache-policy - -## Goal -Preparar una política operativa de prewarm y refresco de snapshots históricos para que los servidores y métricas más visibles ya estén listos antes de que el usuario abra la página, reduciendo tiempos de espera al cambiar de servidor o pestaña. - -## Context -Aunque la UI deje de precargar agresivamente en el navegador, sigue siendo útil que el backend mantenga calientes y listos los snapshots más importantes. Esto debe hacerse de forma controlada y periódica, sin volver a un modelo de recomposición bajo demanda. Además, conviene definir mejor la política de caché frontend para que ayude sin dejar resultados vacíos obsoletos demasiado tiempo. - -## Steps -1. Revisar la generación actual de snapshots y el runner periódico. -2. Definir qué snapshots deben considerarse prioritarios para prewarm, como mínimo: - - server-summary para #01, #02, #03 y all-servers - - leaderboard semanal de la métrica por defecto para #01, #02, #03 y all-servers - - recent-matches para #01, #02, #03 y all-servers -3. Diseñar e implementar una estrategia de prewarm ligera y razonable para esos snapshots prioritarios. -4. Mantener la generación de otras métricas de leaderboard de forma periódica o diferida, según convenga, pero sin penalizar la primera carga de la UI. -5. Revisar y ajustar la política de caché frontend para: - - aprovechar respuestas recientes - - no mantener indefinidamente respuestas vacías antiguas - - permitir que el usuario vea mejoras sin necesidad de comportamientos raros -6. Documentar la estrategia operativa de prewarm y caché. -7. No convertir esta task en una optimización prematura excesiva; mantener el alcance claro y pragmático. -8. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- backend/README.md -- backend/app/config.py -- backend/app/historical_runner.py -- backend/app/historical_snapshots.py -- backend/app/historical_snapshot_storage.py -- frontend/assets/js/historico.js -- docs/historical-coverage-report.md - -## Expected Files to Modify -- backend/app/config.py -- backend/app/historical_runner.py -- backend/app/historical_snapshots.py -- frontend/assets/js/historico.js -- backend/README.md -- opcionalmente documentación técnica adicional si ayuda a dejar la política operativa clara - -## Constraints -- No volver a recomposición pesada en request path. -- No crear páginas nuevas. -- No romper la UI histórica existente. -- No introducir frameworks nuevos. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en snapshots listos antes de la interacción del usuario. - -## Validation -- Existe una estrategia clara de prewarm de snapshots prioritarios. -- Cambiar de servidor o entrar en la página es más rápido que antes. -- La política de caché frontend es más sana y coherente con el uso real. -- La documentación refleja la nueva operativa. -- Los cambios quedan committeados y se hace push si el entorno lo permite. - -## Change Budget -- Preferir menos de 5 archivos modificados o creados. -- Preferir menos de 220 líneas cambiadas. - -## Outcome -- El runner histórico ya no duplica una recomposición completa de snapshots tras cada refresh incremental. -- La operativa periódica hace prewarm en cada ciclo para `server-summary`, `weekly-leaderboard` de `kills` y `recent-matches` en `comunidad-hispana-01`, `comunidad-hispana-02`, `comunidad-hispana-03` y `all-servers`. -- La matriz completa de métricas queda en una cadencia separada configurable con `HLL_HISTORICAL_FULL_SNAPSHOT_EVERY_RUNS`, evitando penalizar cada refresh. -- La caché frontend ahora distingue snapshots frescos, stale y missing para conservar respuestas útiles más tiempo sin retener vacíos antiguos indefinidamente. -- Validación local: -- `py_compile` sobre `config.py`, `historical_snapshots.py`, `historical_ingestion.py`, `historical_runner.py` y `payloads.py` -- `node --check frontend/assets/js/historico.js` -- validación funcional con SQLite temporal: `priority-prewarm -> 12 snapshots` y `full-matrix -> 6 snapshots` para un servidor -- la generación contra el dataset histórico real superó el timeout local de la consola, por lo que la validación operativa completa quedó acotada a la ruta temporal diff --git a/ai/tasks/done/TASK-055-fix-all-servers-historical-aggregate.md b/ai/tasks/done/TASK-055-fix-all-servers-historical-aggregate.md deleted file mode 100644 index e39b08c..0000000 --- a/ai/tasks/done/TASK-055-fix-all-servers-historical-aggregate.md +++ /dev/null @@ -1,80 +0,0 @@ -# TASK-055-fix-all-servers-historical-aggregate - -## Goal -Corregir el agregado histórico `all-servers` / `Totales / Todos` para que resumen, tops semanales y partidas recientes reflejen realmente la suma o agregación de los servidores con histórico disponible, en vez de devolver snapshots vacíos. - -## Context -La situación actual del histórico es esta: -- `comunidad-hispana-01` muestra datos correctos -- `comunidad-hispana-02` muestra datos correctos -- `Totales / Todos` aparece vacío -- `comunidad-hispana-03` todavía no debe considerarse error, porque no se ha ejecutado bootstrap para ese servidor - -Esto indica un fallo específico en la generación o persistencia del agregado lógico `all-servers`, no un problema general de la capa histórica. - -## Steps -1. Revisar la implementación actual del agregado lógico `all-servers` en: - - snapshots - - payloads - - rutas - - generación/prewarm -2. Verificar cómo se construyen actualmente: - - resumen global - - weekly leaderboards globales - - recent matches globales -3. Corregir la lógica para que `all-servers` agregue correctamente los servidores con histórico disponible. -4. Asegurar que el agregado: - - incluya `comunidad-hispana-01` - - incluya `comunidad-hispana-02` - - no dependa de que `comunidad-hispana-03` ya tenga histórico - - no colapse a vacío si uno de los servidores no tiene datos aún -5. Verificar que los snapshots globales se generen con datos reales y no se sobrescriban con vacíos. -6. Regenerar los snapshots necesarios de `all-servers`. -7. Validar que en la UI: - - `Totales / Todos` deje de mostrar 0 partidas / 0 jugadores - - los tops globales ya tengan datos - - recent matches globales ya tengan contenido si existe histórico en #01 y #02 -8. Documentar brevemente la semántica final del agregado global. -9. No tratar todavía `#03` como parte obligatoria del agregado si no hay bootstrap para ese servidor. -10. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- backend/README.md -- backend/app/historical_storage.py -- backend/app/historical_snapshots.py -- backend/app/historical_snapshot_storage.py -- backend/app/payloads.py -- backend/app/routes.py -- frontend/assets/js/historico.js -- frontend/historico.html - -## Expected Files to Modify -- backend/app/historical_storage.py -- backend/app/historical_snapshots.py -- backend/app/historical_snapshot_storage.py -- backend/app/payloads.py -- backend/app/routes.py -- backend/README.md -- opcionalmente frontend/assets/js/historico.js si hace falta ajustar cómo se interpreta el agregado global - -## Constraints -- No romper #01 ni #02. -- No exigir histórico de #03 para que `all-servers` funcione. -- No crear páginas nuevas. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en arreglar el agregado global. - -## Validation -- `Totales / Todos` deja de estar vacío. -- El resumen global tiene partidas, jugadores y mapas si #01 y #02 tienen histórico. -- Los tops globales funcionan. -- Las partidas recientes globales funcionan. -- Los cambios quedan committeados y se hace push al remoto si el entorno lo permite. - -## Change Budget -- Preferir menos de 6 archivos modificados o creados. -- Preferir menos de 240 líneas cambiadas. diff --git a/ai/tasks/done/TASK-056-historical-empty-state-and-copy-polish.md b/ai/tasks/done/TASK-056-historical-empty-state-and-copy-polish.md deleted file mode 100644 index f3f6af3..0000000 --- a/ai/tasks/done/TASK-056-historical-empty-state-and-copy-polish.md +++ /dev/null @@ -1,73 +0,0 @@ -# TASK-056-historical-empty-state-and-copy-polish - -## Goal -Mejorar los estados vacíos y el copy de la página histórica para que `comunidad-hispana-03` se muestre de forma honesta mientras no tenga bootstrap ejecutado, y para que la información de cobertura y fallback semanal suene más natural y menos técnica. - -## Context -Tras los últimos cambios, la página histórica ya funciona para #01 y #02, pero aún hay aspectos de UX/copy mejorables: -- `comunidad-hispana-03` aparece vacía, lo cual ahora mismo es normal porque no se ha ejecutado bootstrap para ese servidor -- algunos textos siguen sonando demasiado técnicos -- labels como `672,1 días registrados` no son la mejor forma de presentar cobertura histórica -- el texto del fallback semanal es correcto, pero demasiado largo y técnico - -## Steps -1. Revisar los textos actuales de: - - resumen - - badges de cobertura - - periodo registrado - - fallback semanal - - estados vacíos de resumen / tops / recientes -2. Hacer que `comunidad-hispana-03` muestre un estado explícito y honesto del tipo: - - sin histórico registrado todavía - - pendiente de bootstrap / pendiente de registro histórico - - o equivalente mejor, siempre claro y natural -3. Evitar que `#03` parezca un error roto si simplemente aún no se ha cargado histórico. -4. Revisar la forma de mostrar la cobertura histórica. Priorizar formulaciones más naturales como: - - cobertura histórica - - desde X hasta Y - - periodo registrado - sobre expresiones demasiado técnicas o poco naturales como el número decimal de días aislado. -5. Simplificar el texto del fallback semanal para que comunique: - - que se está mostrando la última semana cerrada - - porque la semana actual aún no tiene suficiente actividad - sin meter demasiado detalle técnico en el bloque principal -6. Mantener la estética actual de la página histórica. -7. No cambiar la lógica de negocio más allá de lo necesario para mostrar estados/copy correctos. -8. No crear páginas nuevas. -9. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- frontend/historico.html -- frontend/assets/js/historico.js -- frontend/assets/css/historico.css -- backend/app/payloads.py -- backend/README.md - -## Expected Files to Modify -- frontend/historico.html -- frontend/assets/js/historico.js -- frontend/assets/css/historico.css -- opcionalmente backend/app/payloads.py si hace falta ajustar labels o metadatos presentables -- opcionalmente backend/README.md si el comportamiento visible cambia y conviene dejarlo documentado - -## Constraints -- No romper la UI histórica que ya funciona para #01 y #02. -- No convertir esta task en un rediseño grande. -- No introducir frameworks nuevos. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en estados vacíos y copy. - -## Validation -- `#03` deja de parecer un fallo ambiguo y muestra un estado vacío claro y honesto. -- La cobertura histórica se presenta de forma más natural. -- El texto del fallback semanal se entiende mejor. -- La UI sigue siendo coherente con la landing y con el resto de la página histórica. -- Los cambios quedan committeados y se hace push al remoto si el entorno lo permite. - -## Change Budget -- Preferir menos de 5 archivos modificados. -- Preferir menos de 220 líneas cambiadas. diff --git a/ai/tasks/done/TASK-057-server-03-historical-bootstrap-and-snapshots.md b/ai/tasks/done/TASK-057-server-03-historical-bootstrap-and-snapshots.md deleted file mode 100644 index 0263f04..0000000 --- a/ai/tasks/done/TASK-057-server-03-historical-bootstrap-and-snapshots.md +++ /dev/null @@ -1,70 +0,0 @@ -# TASK-057-server-03-historical-bootstrap-and-snapshots - -## Goal -Cargar histórico real para `comunidad-hispana-03` desde su fuente CRCON configurada, persistirlo en la base histórica del proyecto y generar los snapshots necesarios para que la UI deje de mostrarlo como pendiente de bootstrap. - -## Context -El servidor `comunidad-hispana-03` ya existe en la configuración del proyecto, pero actualmente la UI lo muestra con un estado honesto de “pendiente de histórico” porque todavía no se ha ejecutado bootstrap/backfill real para ese servidor. El objetivo de esta task es convertir ese servidor en un origen histórico real dentro del producto, dejándolo operativo igual que `#01` y `#02`. - -## Steps -1. Revisar la configuración actual del servidor `comunidad-hispana-03`. -2. Confirmar que la fuente histórica configurada sigue siendo válida y accesible. -3. Ejecutar bootstrap/backfill real para `comunidad-hispana-03` con un enfoque operativo seguro y reanudable. -4. Persistir en SQLite: - - matches - - players - - stats por match - - progreso/backfill -5. Generar snapshots JSON para `comunidad-hispana-03`, al menos de: - - server-summary - - weekly-kills - - weekly-deaths - - weekly-matches-over-100-kills - - weekly-support - - recent-matches -6. Verificar que la UI deja de mostrar el estado de “pendiente de bootstrap” si ya existe histórico real. -7. Documentar el resultado del bootstrap de `#03`, incluyendo cobertura alcanzada si es posible. -8. No tocar la semántica de #01, #02 ni Totales salvo lo estrictamente necesario. -9. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- backend/README.md -- backend/app/config.py -- backend/app/historical_ingestion.py -- backend/app/historical_storage.py -- backend/app/historical_snapshots.py -- backend/app/historical_snapshot_storage.py -- backend/app/historical_runner.py -- backend/app/payloads.py -- frontend/assets/js/historico.js -- docs/historical-coverage-report.md - -## Expected Files to Modify -- backend/README.md -- backend/app/historical_ingestion.py -- backend/app/historical_snapshots.py -- backend/app/historical_snapshot_storage.py -- opcionalmente docs/historical-coverage-report.md -- y los snapshots generados bajo: - - backend/data/snapshots/comunidad-hispana-03/ - -## Constraints -- No usar A2S para esta carga histórica. -- No crear páginas nuevas. -- No romper #01, #02 ni Totales. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en dejar #03 con histórico real y snapshots útiles. - -## Validation -- `comunidad-hispana-03` deja de aparecer como pendiente de bootstrap si hay histórico suficiente. -- Existen snapshots JSON no vacíos para `#03` cuando la fuente devuelve datos. -- El histórico bruto de `#03` queda persistido en SQLite. -- Los cambios quedan committeados y se hace push si el entorno lo permite. - -## Change Budget -- Preferir menos de 6 archivos modificados o creados, sin contar los snapshots generados. -- Preferir menos de 240 líneas cambiadas. diff --git a/ai/tasks/done/TASK-058-monthly-historical-leaderboards-api.md b/ai/tasks/done/TASK-058-monthly-historical-leaderboards-api.md deleted file mode 100644 index 3e19be6..0000000 --- a/ai/tasks/done/TASK-058-monthly-historical-leaderboards-api.md +++ /dev/null @@ -1,67 +0,0 @@ -# TASK-058-monthly-historical-leaderboards-api - -## Goal -Ampliar la API histórica de leaderboards para soportar una dimensión mensual además de la semanal, reutilizando las mismas métricas actuales del producto. - -## Context -La página histórica ya muestra tops semanales por métrica: -- kills -- muertes -- partidas con más de 100 kills -- soporte - -Ahora se quiere añadir una segunda dimensión temporal: mensual. La API debe poder servir snapshots o payloads equivalentes para el periodo mensual con la misma claridad que ya existe en semanal. - -## Steps -1. Revisar la implementación actual de tops semanales y su semántica temporal. -2. Diseñar una dimensión mensual coherente para leaderboards históricos. -3. Definir la política temporal mensual, idealmente basada en mes natural cerrado o en el mes actual si la política del proyecto lo requiere, dejándolo claro. -4. Implementar soporte backend para leaderboards mensuales con estas métricas: - - kills - - muertes - - partidas con más de 100 kills - - soporte -5. Asegurar que la API exponga metadatos claros del rango temporal real usado. -6. Integrar el soporte mensual en la capa de snapshots JSON en disco. -7. Mantener compatibilidad con la capa semanal existente. -8. Documentar la nueva capacidad en backend. -9. No crear todavía la pestaña visual en esta task si no es imprescindible. -10. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- backend/README.md -- backend/app/payloads.py -- backend/app/routes.py -- backend/app/historical_storage.py -- backend/app/historical_snapshots.py -- backend/app/historical_snapshot_storage.py -- frontend/assets/js/historico.js - -## Expected Files to Modify -- backend/app/payloads.py -- backend/app/routes.py -- backend/app/historical_storage.py -- backend/app/historical_snapshots.py -- backend/app/historical_snapshot_storage.py -- backend/README.md -- opcionalmente documentación técnica adicional si hace falta aclarar la política mensual - -## Constraints -- No romper tops semanales existentes. -- No usar A2S para estos tops históricos. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en leaderboards mensuales y metadatos temporales claros. - -## Validation -- Existen leaderboards mensuales para las métricas soportadas. -- La API distingue correctamente entre semanal y mensual. -- Los snapshots mensuales se generan y persisten correctamente. -- Los cambios quedan committeados y se hace push si el entorno lo permite. - -## Change Budget -- Preferir menos de 6 archivos modificados o creados. -- Preferir menos de 240 líneas cambiadas. diff --git a/ai/tasks/done/TASK-059-historical-leaderboards-timeframe-tabs-ui.md b/ai/tasks/done/TASK-059-historical-leaderboards-timeframe-tabs-ui.md deleted file mode 100644 index fce3dfc..0000000 --- a/ai/tasks/done/TASK-059-historical-leaderboards-timeframe-tabs-ui.md +++ /dev/null @@ -1,75 +0,0 @@ -# TASK-059-historical-leaderboards-timeframe-tabs-ui - -## Goal -Ampliar la sección de tops de la página histórica para permitir alternar entre rankings semanales y mensuales dentro de la misma zona visual, manteniendo también las pestañas por métrica. - -## Context -La sección de tops ya tiene pestañas por métrica: -- Top kills -- Top muertes -- Partidas 100+ kills -- Soporte - -Ahora se quiere añadir una segunda capa de navegación temporal dentro de esa misma sección para consultar: -- semanal -- mensual - -La experiencia debe seguir siendo clara, rápida y coherente con el estilo actual de la página. - -## Steps -1. Revisar la UI actual de la sección de leaderboards. -2. Revisar la nueva API mensual y cómo convive con la semanal. -3. Diseñar una navegación clara para el marco temporal, por ejemplo: - - Semanal - - Mensual -4. Mantener las pestañas de métricas ya existentes dentro de ese marco temporal. -5. Hacer que la UI pueda alternar entre: - - semanal + kills - - semanal + muertes - - semanal + 100+ kills - - semanal + soporte - - mensual + kills - - mensual + muertes - - mensual + 100+ kills - - mensual + soporte -6. Mostrar el rango temporal real usado de forma clara y natural. -7. Mantener estados de loading, empty y error. -8. Mantener el rendimiento percibido razonable y compatible con la estrategia actual de snapshots. -9. No crear una nueva página; la ampliación debe quedar dentro de la sección actual de tops. -10. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- frontend/historico.html -- frontend/assets/js/historico.js -- frontend/assets/css/historico.css -- backend/app/routes.py -- backend/app/payloads.py -- backend/README.md - -## Expected Files to Modify -- frontend/historico.html -- frontend/assets/js/historico.js -- frontend/assets/css/historico.css -- opcionalmente backend docs mínimas si cambia el contrato visible de uso - -## Constraints -- No romper el flujo actual semanal. -- No introducir frameworks nuevos. -- No crear páginas nuevas. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en la navegación temporal dentro de los tops. - -## Validation -- La sección de tops permite alternar entre semanal y mensual. -- Siguen funcionando las métricas actuales. -- El rango temporal mostrado es claro. -- La UI sigue siendo coherente con el resto de la página histórica. -- Los cambios quedan committeados y se hace push si el entorno lo permite. - -## Change Budget -- Preferir menos de 5 archivos modificados. -- Preferir menos de 220 líneas cambiadas. diff --git a/ai/tasks/done/TASK-060-backend-dockerization.md b/ai/tasks/done/TASK-060-backend-dockerization.md deleted file mode 100644 index 488378f..0000000 --- a/ai/tasks/done/TASK-060-backend-dockerization.md +++ /dev/null @@ -1,60 +0,0 @@ -# TASK-060-backend-dockerization - -## Goal -Preparar el backend Python del proyecto para ejecutarse correctamente dentro de un contenedor Docker, con una imagen reproducible, variables de entorno claras y persistencia adecuada de datos históricos y snapshots. - -## Context -El backend ya funciona localmente, pero aún no está preparado formalmente para una ejecución containerizada estándar. Antes de pensar en despliegue real, hace falta empaquetarlo de forma consistente y dejar claro cómo se inyectan configuración, rutas de datos y puertos. - -## Steps -1. Revisar la estructura actual del backend y su forma de arranque. -2. Diseñar un Dockerfile específico para el backend. -3. Asegurar que el backend pueda arrancar en contenedor con: - - host correcto - - puerto configurable - - variables de entorno ya soportadas por el proyecto -4. Revisar qué rutas del backend deben persistirse fuera del contenedor, especialmente: - - SQLite histórica - - snapshots JSON - - cualquier artefacto operativo relevante -5. Preparar una estrategia razonable de `.dockerignore` para backend. -6. Mantener la imagen lo más simple y reproducible posible. -7. No resolver todavía reverse proxy final ni TLS en esta task. -8. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- backend/README.md -- backend/app/main.py -- backend/app/config.py -- backend/app/historical_ingestion.py -- backend/app/historical_runner.py -- backend/app/historical_snapshots.py -- backend/requirements.txt -- .gitignore - -## Expected Files to Modify -- backend/Dockerfile -- backend/.dockerignore -- backend/README.md -- opcionalmente archivos de entorno de ejemplo si mejoran claridad, por ejemplo: - - backend/.env.example - -## Constraints -- No romper el arranque local existente. -- No eliminar la persistencia local del histórico. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en containerizar el backend. - -## Validation -- Existe un Dockerfile de backend funcional. -- La persistencia necesaria del backend queda identificada y documentada. -- El backend puede ejecutarse con configuración inyectable por entorno. -- Los cambios quedan committeados y se hace push si el entorno lo permite. - -## Change Budget -- Preferir menos de 5 archivos modificados o creados. -- Preferir menos de 220 líneas cambiadas. diff --git a/ai/tasks/done/TASK-061-frontend-dockerization.md b/ai/tasks/done/TASK-061-frontend-dockerization.md deleted file mode 100644 index 3781832..0000000 --- a/ai/tasks/done/TASK-061-frontend-dockerization.md +++ /dev/null @@ -1,55 +0,0 @@ -# TASK-061-frontend-dockerization - -## Goal -Preparar el frontend estático del proyecto para ejecutarse dentro de un contenedor Docker de forma simple y estable, con una estrategia clara para servir `historico.html`, la landing y los assets. - -## Context -El frontend actual es estático y ya funciona localmente, pero aún no tiene una imagen Docker formal para ejecución consistente. Hace falta dejarlo empaquetado de forma simple, sin introducir complejidad innecesaria. - -## Steps -1. Revisar la estructura actual del frontend. -2. Diseñar un Dockerfile adecuado para servir el frontend estático. -3. Elegir una estrategia simple y mantenible para servir: - - `index.html` - - `historico.html` - - assets CSS/JS/img -4. Asegurar que el frontend pueda configurarse para hablar con el backend containerizado si hay alguna URL/base path que deba quedar clara. -5. Preparar una estrategia razonable de `.dockerignore` si procede. -6. No introducir frameworks ni bundlers nuevos. -7. No resolver todavía reverse proxy final ni TLS en esta task. -8. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- frontend/index.html -- frontend/historico.html -- frontend/assets/js/main.js -- frontend/assets/js/historico.js -- frontend/assets/css/styles.css -- frontend/assets/css/historico.css -- .gitignore - -## Expected Files to Modify -- frontend/Dockerfile -- frontend/.dockerignore -- opcionalmente una mínima documentación asociada si ayuda a explicar el arranque -- opcionalmente un archivo de configuración simple si mejora claridad del servido estático - -## Constraints -- No romper el frontend local actual. -- No introducir frameworks nuevos. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en containerizar el frontend estático. - -## Validation -- Existe un Dockerfile de frontend funcional. -- El frontend puede servirse correctamente desde contenedor. -- La landing y la página histórica quedan accesibles. -- Los cambios quedan committeados y se hace push si el entorno lo permite. - -## Change Budget -- Preferir menos de 4 archivos modificados o creados. -- Preferir menos de 180 líneas cambiadas. diff --git a/ai/tasks/done/TASK-062-docker-compose-project-orchestration.md b/ai/tasks/done/TASK-062-docker-compose-project-orchestration.md deleted file mode 100644 index 4214150..0000000 --- a/ai/tasks/done/TASK-062-docker-compose-project-orchestration.md +++ /dev/null @@ -1,52 +0,0 @@ -# TASK-062-docker-compose-project-orchestration - -## Goal -Añadir una orquestación básica por Docker Compose para levantar conjuntamente frontend y backend del proyecto con persistencia adecuada del histórico. - -## Context -Una vez frontend y backend estén dockerizados, hace falta una forma simple de arrancarlos juntos para desarrollo y predespliegue. Esta task debe dejar una base clara y operativa sin meterse todavía en infraestructura final de producción. - -## Steps -1. Revisar los Dockerfile de frontend y backend. -2. Diseñar un `docker-compose.yml` o equivalente moderno para levantar ambos servicios. -3. Asegurar que el backend exponga correctamente su puerto al frontend. -4. Configurar persistencia razonable para: - - SQLite histórica - - snapshots JSON -5. Preparar nombres de servicio y red interna claros. -6. Asegurar que el proyecto pueda arrancarse con una instrucción sencilla. -7. No introducir todavía reverse proxy público, TLS ni balanceo. -8. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- backend/Dockerfile -- frontend/Dockerfile -- backend/README.md -- frontend files relevantes -- .gitignore - -## Expected Files to Modify -- docker-compose.yml -- backend/README.md -- opcionalmente README raíz si conviene documentar el arranque conjunto -- opcionalmente archivos `.env.example` si mejoran claridad - -## Constraints -- No romper el uso local fuera de Docker. -- No meter todavía infraestructura final de producción. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en levantar el proyecto completo con Docker Compose. - -## Validation -- Existe una orquestación Docker Compose clara para frontend y backend. -- Los datos persistentes del backend no se pierden al recrear contenedores. -- El proyecto puede levantarse con un flujo simple y documentado. -- Los cambios quedan committeados y se hace push si el entorno lo permite. - -## Change Budget -- Preferir menos de 5 archivos modificados o creados. -- Preferir menos de 220 líneas cambiadas. diff --git a/ai/tasks/done/TASK-063-docker-runbook-and-env-docs.md b/ai/tasks/done/TASK-063-docker-runbook-and-env-docs.md deleted file mode 100644 index eee8a2e..0000000 --- a/ai/tasks/done/TASK-063-docker-runbook-and-env-docs.md +++ /dev/null @@ -1,55 +0,0 @@ -# TASK-063-docker-runbook-and-env-docs - -## Goal -Documentar de forma clara cómo ejecutar el proyecto con Docker, qué variables de entorno utiliza y qué persistencia necesita, dejando una guía práctica para desarrollo y predespliegue. - -## Context -Una containerización útil no queda cerrada solo con Dockerfiles y Compose; hace falta documentación clara para levantar el proyecto, entender los volúmenes, configurar entorno y evitar errores de operación. - -## Steps -1. Revisar el estado final de la containerización del frontend y backend. -2. Documentar cómo construir y arrancar el proyecto con Docker. -3. Documentar variables de entorno relevantes del backend. -4. Documentar qué carpetas o volúmenes deben persistirse. -5. Incluir una guía breve para: - - primer arranque - - reinicio - - regeneración de snapshots - - backfill histórico dentro o fuera del contenedor si aplica -6. No convertir esta task en una guía de infraestructura final. -7. Mantener la documentación práctica y enfocada al estado real del proyecto. -8. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- README.md -- backend/README.md -- docker-compose.yml -- backend/app/config.py -- backend/app/historical_ingestion.py -- backend/app/historical_runner.py - -## Expected Files to Modify -- README.md -- backend/README.md -- opcionalmente docs/docker-deployment.md -- opcionalmente archivos de ejemplo de entorno si ayudan a claridad - -## Constraints -- No meter documentación ficticia. -- No describir infraestructura que aún no exista. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en un runbook realista para Docker. - -## Validation -- La documentación explica cómo levantar el proyecto con Docker. -- Las variables y volúmenes relevantes quedan claras. -- Existe una guía útil para el flujo operativo básico. -- Los cambios quedan committeados y se hace push si el entorno lo permite. - -## Change Budget -- Preferir menos de 5 archivos modificados o creados. -- Preferir menos de 220 líneas cambiadas. diff --git a/ai/tasks/done/TASK-064-hourly-historical-refresh-automation.md b/ai/tasks/done/TASK-064-hourly-historical-refresh-automation.md deleted file mode 100644 index 9401944..0000000 --- a/ai/tasks/done/TASK-064-hourly-historical-refresh-automation.md +++ /dev/null @@ -1,72 +0,0 @@ -# TASK-064-hourly-historical-refresh-automation - -## Goal -Automatizar la actualización histórica horaria para que el backend ejecute refresh de histórico cada hora y regenere snapshots al finalizar, manteniendo la web histórica al día sin intervención manual. - -## Context -La capa histórica ya dispone de: -- refresh incremental de histórico -- regeneración de snapshots tras una ingesta correcta - -El problema actual es operativo: ese refresh no se está ejecutando de forma periódica, por lo que la UI sigue mostrando partidas antiguas aunque el flujo técnico ya exista. La solución correcta es programar la ejecución horaria del refresh histórico y dejar que la regeneración de snapshots ocurra como parte natural del flujo, sin convertir esta fase en infraestructura final de producción. - -## Steps -1. Revisar la implementación actual de refresh histórico y regeneración de snapshots. -2. Confirmar cómo se ejecuta hoy el flujo para: - - `comunidad-hispana-01` - - `comunidad-hispana-02` - - `comunidad-hispana-03` -3. Diseñar una forma clara de ejecutar el refresh histórico cada hora para los tres servidores. -4. Asegurar que el flujo horario haga: - - refresh histórico - - regeneración de snapshots tras refresh correcto -5. Definir una forma práctica de dejarlo corriendo en: - - entorno local - - entorno Docker / Compose del proyecto -6. Documentar la operativa mínima: - - cómo arrancarlo - - cómo verificar que sigue corriendo - - cómo comprobar que los snapshots se siguen actualizando -7. Mantener fuera del alcance: - - infraestructura final de producción - - TLS - - dominio público - - scheduler externo definitivo -8. Validar que la solución no dependa de regenerar snapshots sin refresh previo. -9. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- backend/README.md -- backend/app/historical_ingestion.py -- backend/app/historical_runner.py -- backend/app/historical_snapshots.py -- docker-compose.yml -- README.md - -## Expected Files to Modify -- backend/README.md -- backend/app/historical_runner.py -- docker-compose.yml -- README.md -- opcionalmente archivos de entorno de ejemplo o documentación técnica adicional si ayudan a dejar clara la automatización horaria - -## Constraints -- No convertir esta task en infraestructura final de producción. -- No romper el flujo local actual del backend. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en refresh histórico horario y snapshots posteriores al refresh. - -## Validation -- Existe una forma clara de ejecutar refresh histórico cada hora. -- El flujo contempla `#01`, `#02` y `#03`. -- La regeneración de snapshots ocurre después del refresh correcto. -- La documentación explica cómo dejarlo corriendo en local o Docker. -- Los cambios quedan committeados y se hace push al remoto si el entorno lo permite. - -## Change Budget -- Preferir menos de 5 archivos modificados o creados. -- Preferir menos de 220 líneas cambiadas. diff --git a/ai/tasks/done/TASK-065-monthly-player-ranking-data-audit.md b/ai/tasks/done/TASK-065-monthly-player-ranking-data-audit.md deleted file mode 100644 index 493c005..0000000 --- a/ai/tasks/done/TASK-065-monthly-player-ranking-data-audit.md +++ /dev/null @@ -1,98 +0,0 @@ -# TASK-065-monthly-player-ranking-data-audit - -## Goal -Auditar con precisión los datos disponibles actualmente en el proyecto y en la fuente histórica CRCON/scoreboard para determinar qué métricas pueden alimentar un futuro ranking mensual de mejores jugadores y con qué nivel de fiabilidad. - -## Context -Se quiere diseñar un futuro ranking de “Top 3 mejores jugadores del mes”, idealmente teniendo en cuenta variables como: -- kills -- KPM -- KDA -- apoyo -- garrisons/OPs quitados si estuvieran disponibles -- enfrentamientos directos si fueran extraíbles -- impacto en partida - -Pero antes de diseñar el ranking o asignar pesos, es imprescindible saber exactamente: -1. qué datos ya están persistidos en la base local del proyecto -2. qué datos existen en la fuente CRCON/scoreboard pero aún no guardamos -3. qué datos no están realmente disponibles o no son fiables -4. qué combinación de métricas sería viable para una primera versión realista del ranking - -## Steps -1. Revisar el modelo histórico actual del proyecto, incluyendo: - - tablas SQLite - - modelos históricos - - payloads - - snapshots existentes -2. Inventariar qué métricas están ya disponibles y persistidas hoy por: - - jugador - - partida - - jugador por partida -3. Confirmar con precisión qué campos existen ya en el histórico bruto y qué calidad tienen para un ranking serio. -4. Revisar la fuente histórica CRCON/scoreboard que usa el proyecto para verificar si, además de lo ya persistido, existen datos accesibles sobre: - - garrisons destruidos - - OPs destruidos - - enfrentamientos directos / duelos - - otras métricas útiles de impacto táctico -5. Documentar para cada métrica potencial: - - si ya existe en la base - - si existe en la fuente pero no se persiste aún - - si no existe realmente o no puede extraerse de forma fiable - - si sería recomendable usarla en una futura V1 del ranking -6. Dejar una matriz clara de disponibilidad y fiabilidad, por ejemplo: - - métrica - - disponible hoy - - persistida hoy - - calidad/fiabilidad - - coste de implementación adicional - - recomendable para V1 sí/no -7. Incluir una recomendación final sobre qué conjunto de métricas sería razonable para: - - una V1 del ranking mensual - - una posible V2 más ambiciosa -8. No diseñar todavía la fórmula final del ranking salvo una recomendación muy preliminar si ayuda a contextualizar. -9. No implementar todavía nuevas tablas, nuevas ingestas ni nuevas vistas de UI. -10. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- ai/architecture-index.md -- backend/README.md -- backend/app/historical_models.py -- backend/app/historical_storage.py -- backend/app/historical_ingestion.py -- backend/app/historical_snapshots.py -- backend/app/payloads.py -- docs/historical-domain-model.md -- docs/historical-data-quality-notes.md -- docs/historical-crcon-source-discovery.md -- docs/historical-coverage-report.md -- cualquier evidencia de endpoints o JSON reales de la fuente CRCON/scoreboard que ya use el proyecto - -## Expected Files to Modify -- un documento nuevo, por ejemplo: - - docs/monthly-player-ranking-data-audit.md -- opcionalmente ai/architecture-index.md si conviene enlazar esta auditoría -- opcionalmente docs/decisions.md si surge una decisión técnica clara sobre el alcance de métricas para V1/V2 - -## Constraints -- No implementar todavía el ranking mensual. -- No modificar producto visible. -- No crear nuevas rutas, vistas ni snapshots de ranking MVP. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en discovery, inventario y recomendación técnica. - -## Validation -- Existe un documento claro que explica exactamente con qué datos podemos contar hoy. -- Queda claro qué métricas ya están persistidas y cuáles no. -- Queda claro qué métricas existen en la fuente CRCON/scoreboard pero requerirían trabajo adicional. -- Existe una recomendación técnica razonable para una V1 y una V2 del ranking mensual de jugadores. -- Los cambios quedan committeados y se hace push si el entorno lo permite. - -## Change Budget -- Preferir menos de 4 archivos modificados o creados. -- Preferir menos de 220 líneas cambiadas. diff --git a/ai/tasks/done/TASK-066-monthly-mvp-ranking-scoring-design.md b/ai/tasks/done/TASK-066-monthly-mvp-ranking-scoring-design.md deleted file mode 100644 index cac2e44..0000000 --- a/ai/tasks/done/TASK-066-monthly-mvp-ranking-scoring-design.md +++ /dev/null @@ -1,90 +0,0 @@ -# TASK-066-monthly-mvp-ranking-scoring-design - -## Goal -Diseñar de forma precisa y defendible la fórmula de puntuación para una V1 del ranking mensual de mejores jugadores, usando únicamente métricas ya persistidas y fiables en el proyecto. - -## Context -La auditoría de datos previa ya dejó claro qué métricas están hoy disponibles con fiabilidad suficiente para una primera versión del ranking mensual. La recomendación actual para una V1 realista se basa en: -- kills -- support -- time played -- KPM derivado -- KDA derivado -- umbrales de participación -- penalización por teamkills opcional - -Antes de implementar nada en backend o UI, hace falta fijar claramente: -- qué métricas entran en la fórmula -- con qué pesos -- qué requisitos mínimos de elegibilidad debe cumplir un jugador -- cómo evitar rankings absurdos por muestras demasiado pequeñas -- cómo se resuelven empates -- si la V1 se calcula por servidor, globalmente o en ambos modos - -## Steps -1. Revisar la auditoría previa de datos del ranking mensual y confirmar el conjunto de métricas fiables disponibles hoy. -2. Definir qué significa exactamente “mejor jugador del mes” en la V1 del proyecto: - - orientación más ofensiva - - orientación más equilibrada - - orientación más MVP de equipo -3. Diseñar una fórmula de scoring concreta para V1 basada únicamente en métricas persistidas y fiables. -4. Definir con claridad: - - métricas incluidas - - pesos de cada métrica - - normalización o escala - - tratamiento de muestras pequeñas - - mínimos de elegibilidad - - penalizaciones opcionales (por ejemplo teamkills) - - desempates -5. Recomendar si la V1 debe publicarse como: - - ranking por servidor - - ranking global - - ambos -6. Justificar por qué esa fórmula es razonable para una primera versión del producto. -7. Dejar expresamente fuera de V1 las métricas no suficientemente confirmadas o no persistidas hoy, por ejemplo: - - garrisons/OPs - - duelos directos - - kills por arma - - impacto táctico fino no persistido -8. Añadir, si aporta valor, una breve nota de futuro sobre cómo podría ampliarse la fórmula en una V2 sin rediseñarla por completo. -9. No implementar todavía nuevas tablas, rutas, snapshots ni UI. -10. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- ai/architecture-index.md -- docs/monthly-player-ranking-data-audit.md -- docs/historical-domain-model.md -- docs/historical-data-quality-notes.md -- backend/README.md -- backend/app/historical_models.py -- backend/app/historical_storage.py -- backend/app/payloads.py - -## Expected Files to Modify -- un documento nuevo, por ejemplo: - - docs/monthly-mvp-ranking-scoring-design.md -- opcionalmente docs/decisions.md si surge una decisión técnica clara sobre alcance V1 -- opcionalmente ai/architecture-index.md si conviene enlazar el diseño de scoring - -## Constraints -- No implementar todavía el ranking mensual. -- No tocar producto visible. -- No depender de métricas no confirmadas o no persistidas hoy. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en diseño de scoring y reglas de elegibilidad de V1. - -## Validation -- Existe un documento claro con la fórmula de scoring propuesta para la V1. -- Quedan definidos los pesos, métricas, mínimos y desempates. -- Queda claro qué se incluye en V1 y qué se deja para V2. -- La propuesta es coherente con la auditoría de datos previa. -- Los cambios quedan committeados y se hace push si el entorno lo permite. - -## Change Budget -- Preferir menos de 4 archivos modificados o creados. -- Preferir menos de 220 líneas cambiadas. diff --git a/ai/tasks/done/TASK-067-monthly-mvp-ranking-backend-calculation.md b/ai/tasks/done/TASK-067-monthly-mvp-ranking-backend-calculation.md deleted file mode 100644 index c55d0dd..0000000 --- a/ai/tasks/done/TASK-067-monthly-mvp-ranking-backend-calculation.md +++ /dev/null @@ -1,79 +0,0 @@ -# TASK-067-monthly-mvp-ranking-backend-calculation - -## Goal -Implementar en backend el cálculo base de la V1 del ranking mensual MVP usando la fórmula y reglas definidas en docs/monthly-mvp-ranking-scoring-design.md, apoyándose únicamente en métricas ya persistidas y fiables. - -## Context -La auditoría y el diseño de scoring ya están cerrados. La V1 del ranking mensual MVP debe construirse con: -- kills -- support -- time played -- KPM derivado -- KDA derivado -- umbrales de elegibilidad -- penalización por teamkills opcional -- desempates deterministas - -Antes de exponerlo en snapshots o UI, hace falta implementar el cálculo mensual real en backend de forma clara, trazable y compatible con servidor individual y all-servers. - -## Steps -1. Revisar docs/monthly-player-ranking-data-audit.md y docs/monthly-mvp-ranking-scoring-design.md. -2. Implementar la lógica de cálculo del ranking mensual MVP según la fórmula aprobada. -3. Aplicar correctamente: - - métricas incluidas - - pesos - - normalización - - mínimos de elegibilidad - - penalización por teamkills si así quedó definida - - desempates -4. Soportar cálculo para: - - un servidor concreto - - all-servers -5. Dejar el resultado estructurado para poder serializarlo después en snapshots o payloads. -6. Mantener clara la separación entre: - - ranking mensual MVP V1 - - leaderboards mensuales simples por métrica ya existentes -7. No exponer todavía UI nueva en esta task. -8. Documentar brevemente la parte backend necesaria. -9. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- docs/monthly-player-ranking-data-audit.md -- docs/monthly-mvp-ranking-scoring-design.md -- backend/README.md -- backend/app/historical_storage.py -- backend/app/historical_models.py -- backend/app/payloads.py -- backend/app/routes.py -- backend/app/historical_snapshots.py - -## Expected Files to Modify -- backend/app/historical_storage.py -- backend/app/payloads.py -- opcionalmente nuevos módulos si mejoran claridad, por ejemplo: - - backend/app/monthly_mvp.py - - backend/app/monthly_mvp_scoring.py -- backend/README.md -- opcionalmente docs/decisions.md si hace falta fijar una decisión técnica menor - -## Constraints -- No incluir métricas no persistidas o no confirmadas. -- No romper los rankings mensuales ya existentes por kills, muertes, soporte y 100+ kills. -- No crear todavía UI en esta task. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en el cálculo backend del monthly MVP V1. - -## Validation -- Existe un cálculo mensual MVP funcional en backend. -- Soporta servidor individual y all-servers. -- Respeta la fórmula y elegibilidad definidas en el diseño. -- No rompe los leaderboards mensuales existentes. -- Los cambios quedan committeados y se hace push si el entorno lo permite. - -## Change Budget -- Preferir menos de 6 archivos modificados o creados. -- Preferir menos de 260 líneas cambiadas. diff --git a/ai/tasks/done/TASK-068-monthly-mvp-snapshots-and-api.md b/ai/tasks/done/TASK-068-monthly-mvp-snapshots-and-api.md deleted file mode 100644 index 7c85653..0000000 --- a/ai/tasks/done/TASK-068-monthly-mvp-snapshots-and-api.md +++ /dev/null @@ -1,69 +0,0 @@ -# TASK-068-monthly-mvp-snapshots-and-api - -## Goal -Exponer el ranking mensual MVP V1 mediante snapshots JSON y API propia del backend, siguiendo la misma filosofía rápida y estable ya usada por la capa histórica. - -## Context -Una vez implementado el cálculo backend del monthly MVP, hace falta integrarlo en la capa de snapshots del proyecto para que: -- no dependa de cálculos pesados on-demand -- pueda servirse rápido a la UI -- sea consistente con el resto de la arquitectura histórica - -## Steps -1. Revisar la implementación del cálculo mensual MVP y la arquitectura actual de snapshots JSON. -2. Diseñar la forma de snapshot para el ranking mensual MVP, tanto por servidor como para all-servers. -3. Generar snapshots JSON apropiados, por ejemplo: - - server monthly mvp - - all-servers monthly mvp -4. Incluir metadatos claros, como mínimo: - - generated_at - - source_range_start - - source_range_end - - freshness / is_stale si aplica - - month_key o periodo real usado -5. Exponer endpoints claros y consistentes para leer esos snapshots. -6. Mantener compatibilidad y coherencia con la API histórica existente. -7. Integrar el monthly MVP en el runner/generación periódica de snapshots si corresponde. -8. No crear todavía la UI final en esta task. -9. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- backend/README.md -- backend/app/routes.py -- backend/app/payloads.py -- backend/app/historical_snapshots.py -- backend/app/historical_snapshot_storage.py -- backend/app/historical_runner.py -- backend/app/config.py -- docs/monthly-mvp-ranking-scoring-design.md - -## Expected Files to Modify -- backend/app/routes.py -- backend/app/payloads.py -- backend/app/historical_snapshots.py -- backend/app/historical_snapshot_storage.py -- backend/app/historical_runner.py -- backend/README.md -- opcionalmente nuevos módulos auxiliares si mejoran claridad - -## Constraints -- No recalcular el ranking pesado en cada request de usuario. -- No romper snapshots históricos existentes. -- No crear todavía UI nueva en esta task. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en snapshots y API del monthly MVP. - -## Validation -- Existen snapshots JSON del monthly MVP para servidor y/o all-servers según diseño. -- Existen endpoints para leer esos snapshots. -- El monthly MVP se integra con la operativa de snapshots del proyecto. -- La respuesta es rápida y coherente con el resto de la API histórica. -- Los cambios quedan committeados y se hace push si el entorno lo permite. - -## Change Budget -- Preferir menos de 6 archivos modificados o creados. -- Preferir menos de 240 líneas cambiadas. diff --git a/ai/tasks/done/TASK-069-monthly-mvp-ui-top3.md b/ai/tasks/done/TASK-069-monthly-mvp-ui-top3.md deleted file mode 100644 index ec7296d..0000000 --- a/ai/tasks/done/TASK-069-monthly-mvp-ui-top3.md +++ /dev/null @@ -1,66 +0,0 @@ -# TASK-069-monthly-mvp-ui-top3 - -## Goal -Añadir a la página histórica una sección clara y visual para mostrar el Top 3 MVP mensual V1, consumiendo los snapshots/API ya preparados y manteniendo coherencia con la navegación existente. - -## Context -El monthly MVP V1 ya está definido a nivel de diseño y, tras las tasks previas, debe quedar disponible en snapshots y API. El siguiente paso es exponerlo en la UI de forma clara, sin convertir la pantalla en algo recargado ni confuso. - -## Steps -1. Revisar la UI histórica actual y el nuevo endpoint/snapshot del monthly MVP. -2. Diseñar una sección visual clara para el Top 3 MVP mensual. -3. Mantener compatibilidad con el selector actual de ámbito: - - servidor individual - - all-servers -4. Mostrar, como mínimo: - - posición 1, 2 y 3 - - nombre de jugador - - puntuación MVP - - metadatos mínimos útiles según el diseño aprobado -5. Mostrar el periodo mensual real usado de forma natural. -6. Mantener estados de: - - loading - - empty - - error -7. Integrar la nueva sección sin romper la navegación actual semanal/mensual de leaderboards por métrica. -8. Mantener el rendimiento percibido y la coherencia visual con la página actual. -9. No crear páginas nuevas. -10. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- frontend/historico.html -- frontend/assets/js/historico.js -- frontend/assets/css/historico.css -- backend/app/routes.py -- backend/app/payloads.py -- backend/README.md -- docs/monthly-mvp-ranking-scoring-design.md - -## Expected Files to Modify -- frontend/historico.html -- frontend/assets/js/historico.js -- frontend/assets/css/historico.css -- opcionalmente backend docs mínimas si hay que reflejar el nuevo bloque visible - -## Constraints -- No romper la UI histórica actual. -- No introducir frameworks nuevos. -- No crear páginas nuevas. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en una sección Top 3 mensual clara y útil. - -## Validation -- La UI histórica muestra el Top 3 MVP mensual. -- Funciona para servidor individual y all-servers. -- El periodo mensual mostrado es claro. -- Los estados de loading/empty/error son coherentes. -- La pantalla sigue siendo usable y visualmente consistente. -- Los cambios quedan committeados y se hace push si el entorno lo permite. - -## Change Budget -- Preferir menos de 5 archivos modificados. -- Preferir menos de 220 líneas cambiadas. diff --git a/ai/tasks/done/TASK-070-data-source-abstraction-for-historical-and-live.md b/ai/tasks/done/TASK-070-data-source-abstraction-for-historical-and-live.md deleted file mode 100644 index 774a011..0000000 --- a/ai/tasks/done/TASK-070-data-source-abstraction-for-historical-and-live.md +++ /dev/null @@ -1,75 +0,0 @@ -# TASK-070-data-source-abstraction-for-historical-and-live - -## Goal -Introducir una capa de abstracción de fuente de datos para que el backend pueda trabajar con distintas fuentes según entorno sin cambiar el contrato de producto ni la UI. - -## Context -El proyecto hoy funciona con una fuente pública basada en scoreboard/CRCON público. Se quiere mantener ese modo para desarrollo, pero preparar producción para funcionar con RCON como fuente principal. Antes de implementar el proveedor RCON, hace falta definir una abstracción clara que desacople el backend de una única fuente. - -## Steps -1. Revisar la arquitectura actual de ingestión histórica, snapshots y panel live. -2. Identificar los puntos donde hoy se asume una fuente concreta. -3. Diseñar una interfaz o capa de proveedor de datos para cubrir como mínimo: - - histórico / ingestión - - estado actual live de servidores -4. Definir un contrato claro para proveedores de datos, por ejemplo: - - public-scoreboard provider - - rcon provider -5. Mantener intactos los contratos de salida del backend hacia la UI. -6. Preparar la selección del proveedor por configuración/entorno. -7. Documentar la arquitectura resultante. -8. No cambiar todavía el producto visible más de lo imprescindible. -9. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- ai/architecture-index.md -- backend/README.md -- backend/app/config.py -- backend/app/historical_ingestion.py -- backend/app/historical_runner.py -- backend/app/payloads.py -- backend/app/routes.py -- backend/app/main.py - -## Expected Files to Modify -- backend/app/config.py -- backend/app/historical_ingestion.py -- backend/app/payloads.py -- opcionalmente nuevos módulos, por ejemplo: - - backend/app/data_sources.py - - backend/app/source_provider.py -- backend/README.md -- opcionalmente ai/architecture-index.md - -## Constraints -- No romper el modo actual de desarrollo. -- No acoplar la UI a una fuente concreta. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en la abstracción de fuente de datos. - -## Validation -- Existe una abstracción clara de proveedor de datos. -- El backend puede seleccionar fuente por configuración. -- El flujo actual no se rompe. -- Los cambios quedan committeados y se hace push si el entorno lo permite. - -## Change Budget -- Preferir menos de 6 archivos modificados o creados. -- Preferir menos de 240 líneas cambiadas. - -## Outcome -- Se introdujo `backend/app/data_sources.py` como capa de seleccion y contrato para proveedores live e historicos. -- `historical_ingestion.py` dejo de depender directamente de requests CRCON embebidas y ahora resuelve su proveedor por configuracion. -- `payloads.py` dejo de invocar el colector A2S de forma acoplada y ahora consume un proveedor live seleccionado por entorno. -- Se mantuvieron intactos los contratos HTTP del backend hacia la UI. -- Quedaron preparadas las rutas de seleccion para `public-scoreboard`, `a2s` y el placeholder futuro `rcon`. - -## Validation Notes -- `python -m compileall backend/app` completo sin errores. -- `git diff --name-only` quedo limitado al alcance backend y documentacion de la task. -- El modo por defecto sigue apuntando a `a2s` para live y `public-scoreboard` para historico, por lo que el flujo de desarrollo no cambia. diff --git a/ai/tasks/done/TASK-071-public-scoreboard-provider-adapter.md b/ai/tasks/done/TASK-071-public-scoreboard-provider-adapter.md deleted file mode 100644 index 511d63b..0000000 --- a/ai/tasks/done/TASK-071-public-scoreboard-provider-adapter.md +++ /dev/null @@ -1,66 +0,0 @@ -# TASK-071-public-scoreboard-provider-adapter - -## Goal -Adaptar la fuente actual public-scoreboard al nuevo contrato de proveedor para que siga siendo la fuente estándar en desarrollo sin romper el comportamiento existente. - -## Context -Una vez exista la abstracción de fuente, hay que mover la lógica actual a un proveedor explícito de tipo public-scoreboard. Eso permitirá mantener dev estable mientras se prepara RCON para producción. - -## Steps -1. Revisar la lógica actual que usa scoreboard/CRCON público. -2. Encapsularla dentro del proveedor public-scoreboard compatible con la nueva abstracción. -3. Asegurar que desarrollo sigue funcionando con la misma semántica actual. -4. Mantener el mismo resultado en: - - ingestión histórica - - snapshots - - estado actual de servidores -5. Reducir duplicaciones y dejar clara la responsabilidad del proveedor. -6. Actualizar documentación mínima. -7. No implementar todavía lógica RCON en esta task. -8. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- backend/README.md -- backend/app/config.py -- backend/app/historical_ingestion.py -- backend/app/payloads.py -- backend/app/routes.py -- backend/app/source_provider.py -- docs/historical-crcon-source-discovery.md - -## Expected Files to Modify -- backend/app/historical_ingestion.py -- backend/app/payloads.py -- backend/app/routes.py -- opcionalmente nuevos módulos, por ejemplo: - - backend/app/providers/public_scoreboard_provider.py -- backend/README.md - -## Constraints -- No romper el comportamiento actual en dev. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en encapsular correctamente la fuente actual. - -## Validation -- El proveedor public-scoreboard funciona bajo la nueva abstracción. -- El modo desarrollo sigue comportándose como antes. -- Los cambios quedan committeados y se hace push si el entorno lo permite. - -## Change Budget -- Preferir menos de 5 archivos modificados o creados. -- Preferir menos de 220 líneas cambiadas. - -## Outcome -- Se extrajo la logica del proveedor historico actual a `backend/app/providers/public_scoreboard_provider.py`. -- `backend/app/data_sources.py` quedo reducido a contratos y seleccion de proveedor por entorno. -- El comportamiento de desarrollo se mantuvo estable con `public-scoreboard` como proveedor historico por defecto. -- No se introdujo logica RCON en esta task. - -## Validation Notes -- `python -m compileall backend/app` completo sin errores tras el refactor. -- La diff quedo limitada al selector de proveedores, el adapter publico y la documentacion minima. -- `backend/app/source_provider.py` no existia; se reutilizo `backend/app/data_sources.py` como punto de seleccion ya introducido en la task anterior. diff --git a/ai/tasks/done/TASK-072-rcon-provider-for-production.md b/ai/tasks/done/TASK-072-rcon-provider-for-production.md deleted file mode 100644 index 774e0d7..0000000 --- a/ai/tasks/done/TASK-072-rcon-provider-for-production.md +++ /dev/null @@ -1,74 +0,0 @@ -# TASK-072-rcon-provider-for-production - -## Goal -Implementar un proveedor RCON para producción que permita usar acceso directo a los servidores como fuente principal de datos live e histórica, seleccionado por configuración sin alterar la UI. - -## Context -La intención del proyecto es desplegar la web con acceso a los servidores mediante RCON. Eso debe convivir con el modo dev actual. El proveedor RCON debe quedar integrado en la nueva abstracción de fuentes y seleccionable por entorno. - -## Steps -1. Revisar la abstracción de proveedor de datos ya creada. -2. Diseñar el proveedor RCON y la configuración necesaria para usarlo en producción. -3. Definir claramente qué capacidades cubrirá esta primera versión del proveedor RCON: - - estado live de servidores - - ingestión histórica o enriquecida, según lo que la integración permita hoy -4. Implementar el proveedor RCON sin romper el proveedor actual. -5. Añadir configuración por entorno para elegir: - - public-scoreboard en dev - - rcon en prod -6. Documentar variables necesarias, credenciales y limitaciones de la integración. -7. Mantener los contratos backend → frontend estables. -8. No introducir todavía una V2 del MVP ni persistencia extra de armas/duelos salvo que sea estrictamente necesario para dejar la integración operativa. -9. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- backend/README.md -- backend/app/config.py -- backend/app/historical_ingestion.py -- backend/app/payloads.py -- backend/app/routes.py -- backend/app/source_provider.py -- documentación o librerías ya presentes para RCON si existen en la repo - -## Expected Files to Modify -- backend/app/config.py -- backend/app/historical_ingestion.py -- backend/app/payloads.py -- backend/app/routes.py -- opcionalmente nuevos módulos, por ejemplo: - - backend/app/providers/rcon_provider.py - - backend/app/rcon_client.py -- backend/README.md -- opcionalmente backend/.env.example o backend.env.example - -## Constraints -- No romper el modo dev actual. -- No exponer credenciales en la repo. -- No cambiar el contrato visible de la UI. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en el proveedor RCON de producción. - -## Validation -- Existe un proveedor RCON seleccionable por configuración. -- El backend puede correr en modo dev con la fuente actual y en modo prod con RCON. -- La documentación deja claras variables y límites. -- Los cambios quedan committeados y se hace push si el entorno lo permite. - -## Change Budget -- Preferir menos de 7 archivos modificados o creados. -- Preferir menos de 260 líneas cambiadas. - -## Outcome -- Se implemento `backend/app/rcon_client.py` con conexion TCP y cifrado XOR minimo para comandos HLL RCON. -- Se anadio `backend/app/providers/rcon_provider.py` como proveedor live seleccionable por configuracion. -- `/health` ahora expone `live_data_source` y `historical_data_source` para verificar el proveedor activo. -- Se mantuvo el modo dev actual y se documento la limitacion actual: el historico sigue dependiendo de `public-scoreboard`. - -## Validation Notes -- `python -m compileall backend/app` completo sin errores. -- `build_health_payload()` devuelve correctamente los proveedores activos por defecto. -- La repo no contiene una canalizacion historica basada en eventos/logs RCON; por eso la parte historica RCON sigue quedando documentada como no operativa en esta version. diff --git a/ai/tasks/done/TASK-073-env-selection-docker-and-runbook-for-rcon.md b/ai/tasks/done/TASK-073-env-selection-docker-and-runbook-for-rcon.md deleted file mode 100644 index 024f74f..0000000 --- a/ai/tasks/done/TASK-073-env-selection-docker-and-runbook-for-rcon.md +++ /dev/null @@ -1,73 +0,0 @@ -# TASK-073-env-selection-docker-and-runbook-for-rcon - -## Goal -Dejar documentado y operativo el cambio de fuente por entorno, incluyendo Docker/Compose y el runbook necesario para usar public-scoreboard en desarrollo y RCON en producción. - -## Context -Una vez exista la capa de abstracción y el proveedor RCON, hace falta cerrar la parte operativa: -- variables de entorno -- selección de proveedor -- Docker/Compose -- documentación clara para desarrollo y despliegue - -## Steps -1. Revisar el estado final de la abstracción y de ambos proveedores. -2. Documentar claramente: - - modo dev con public-scoreboard - - modo prod con RCON -3. Añadir o ajustar la configuración Docker/Compose necesaria para seleccionar proveedor por entorno. -4. Documentar variables sensibles y buenas prácticas para no versionar credenciales. -5. Asegurar que el runbook cubra: - - arranque en dev - - arranque en Docker - - despliegue en prod con RCON - - verificación básica de qué proveedor está activo -6. No convertir esta task en una guía de infraestructura final completa. -7. Mantener la documentación realista y alineada con lo implementado. -8. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- README.md -- backend/README.md -- docker-compose.yml -- backend/app/config.py -- backend/app/source_provider.py -- backend.env.example - -## Expected Files to Modify -- README.md -- backend/README.md -- docker-compose.yml -- backend.env.example o archivo equivalente -- opcionalmente docs/rcon-production-mode.md - -## Constraints -- No documentar infraestructura inexistente. -- No exponer credenciales reales. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en selección por entorno y runbook. - -## Validation -- La documentación explica con claridad cómo usar dev vs prod. -- Docker/Compose refleja la selección por entorno de forma razonable. -- Queda claro cómo verificar qué proveedor está activo. -- Los cambios quedan committeados y se hace push si el entorno lo permite. - -## Change Budget -- Preferir menos de 5 archivos modificados o creados. -- Preferir menos de 220 líneas cambiadas. - -## Outcome -- Se anadieron las variables de seleccion de proveedor y placeholders RCON a `backend/.env.example`. -- `docker-compose.yml` ahora propaga explicitamente la seleccion de proveedor y la configuracion RCON para backend e historical-runner. -- `README.md` y `backend/README.md` incluyen un runbook realista para dev, Docker y live con RCON. -- La verificacion operativa recomendada queda apoyada en `/health`, que expone los proveedores activos. - -## Validation Notes -- `docker compose config` resolvio correctamente la configuracion final. -- La documentacion mantiene el limite actual del producto: RCON solo para live y `public-scoreboard` para historico. -- No se documentaron credenciales reales ni infraestructura no implementada en la repo. diff --git a/ai/tasks/done/TASK-074-rcon-data-capability-audit.md b/ai/tasks/done/TASK-074-rcon-data-capability-audit.md deleted file mode 100644 index ab08141..0000000 --- a/ai/tasks/done/TASK-074-rcon-data-capability-audit.md +++ /dev/null @@ -1,108 +0,0 @@ -# TASK-074-rcon-data-capability-audit - -## Goal -Auditar con precisión qué datos reales pueden obtenerse hoy mediante RCON en el proyecto, qué datos requieren captura de eventos o logs, y qué métricas serían viables para una futura V2 del ranking MVP. - -## Context -La integración live con RCON ya está funcionando en producción-like mode para el panel actual de servidores. Antes de evolucionar el sistema MVP mensual con métricas avanzadas, necesitamos saber con exactitud qué superficie de datos expone RCON realmente. - -Es importante no confundir: -- RCON puro -- CRCON / scoreboard público -- agregados históricos tipo HLL Records - -Algunas métricas deseadas para una futura V2 podrían incluir: -- kills por tipo de arma -- distinción de artillery / tank / infantry -- killer -> victim -- most_killed -- death_by -- teamkills por evento -- garrisons / OPs destruidos -- otras señales tácticas - -Pero todavía no sabemos cuáles salen realmente de RCON directo y cuáles requerirían una canalización propia de eventos o persistencia adicional. - -## Steps -1. Revisar la implementación actual del proveedor RCON: - - backend/app/rcon_client.py - - backend/app/providers/rcon_provider.py - - backend/app/data_sources.py -2. Auditar qué comandos/capacidades reales expone hoy el cliente RCON implementado. -3. Verificar qué datos live pueden obtenerse ya de forma directa: - - estado de servidor - - jugadores - - scoreboard actual - - mapa - - equipos - - cualquier otro campo ya expuesto -4. Investigar si la superficie RCON actual o el protocolo disponible permiten acceder a: - - kills por arma - - killer/victim - - death_by - - most_killed - - teamkills - - artillery/tank distinctions - - garrisons / OPs destruidos - - otras métricas tácticas útiles -5. Separar claramente para cada métrica: - - disponible por RCON directo hoy - - disponible solo si se captura un flujo de eventos/logs - - no confirmada - - no disponible -6. Documentar qué métricas podrían alimentar una V2 del ranking MVP y bajo qué condiciones. -7. Aclarar qué parte requeriría: - - ampliar el cliente RCON - - capturar eventos - - persistir nuevo histórico - - agregar métricas propias -8. No implementar todavía nuevas tablas, nuevas rutas, nuevas métricas visibles ni cambios de scoring. -9. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- ai/architecture-index.md -- backend/README.md -- backend/app/rcon_client.py -- backend/app/providers/rcon_provider.py -- backend/app/data_sources.py -- backend/app/payloads.py -- docs/monthly-player-ranking-data-audit.md -- docs/monthly-mvp-ranking-scoring-design.md - -## Expected Files to Modify -- docs/rcon-data-capability-audit.md -- opcionalmente ai/architecture-index.md si conviene enlazar la auditoría -- opcionalmente docs/decisions.md si surge una decisión técnica clara sobre el alcance de RCON para V2 - -## Constraints -- No implementar todavía la V2 del MVP. -- No tocar producto visible. -- No confundir CRCON/source pública con RCON puro. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en discovery técnico y viabilidad de métricas. - -## Validation -- Existe un documento claro que explica qué datos reales se pueden obtener hoy por RCON. -- Queda claro qué métricas requerirían eventos/logs o persistencia adicional. -- Queda claro qué subset de métricas sería viable para una futura V2 del MVP. -- Los cambios quedan committeados y se hace push si el entorno lo permite. - -## Change Budget -- Preferir menos de 4 archivos modificados o creados. -- Preferir menos de 220 líneas cambiadas. - -## Outcome -- Se documentó `docs/rcon-data-capability-audit.md` con el alcance real de RCON en la repo, separando RCON directo, CRCON público y métricas que requerirían pipeline de eventos/logs. -- La auditoría deja confirmado que la integración RCON operativa hoy solo cubre estado live basado en `ServerConnect`, `Login` y `GetServerInformation`. -- Quedó explícito que el proveedor histórico `rcon` sigue siendo un placeholder no operativo y que las métricas avanzadas para un MVP V2 no salen hoy de RCON directo en esta repo. -- `ai/architecture-index.md` enlaza ahora la nueva auditoría para mantener visible ese límite arquitectónico. - -## Validation Notes -- Revisión de código completada sobre `backend/app/rcon_client.py`, `backend/app/providers/rcon_provider.py`, `backend/app/data_sources.py` y `backend/app/payloads.py`. -- La auditoría se mantuvo dentro del alcance documental: no se añadieron tablas, rutas ni cambios visibles de producto. -- La evidencia del repositorio sigue separando correctamente live por RCON frente a histórico por CRCON / scoreboard público. diff --git a/ai/tasks/done/TASK-075-crcon-advanced-metrics-origin-audit.md b/ai/tasks/done/TASK-075-crcon-advanced-metrics-origin-audit.md deleted file mode 100644 index b8981c1..0000000 --- a/ai/tasks/done/TASK-075-crcon-advanced-metrics-origin-audit.md +++ /dev/null @@ -1,76 +0,0 @@ -# TASK-075-crcon-advanced-metrics-origin-audit - -## Goal -Auditar el origen técnico real de métricas avanzadas visibles en ecosistemas tipo CRCON / HLL Records, como `most_killed`, `death_by`, killer-victim, kills por arma y otras señales avanzadas, para determinar si provienen de RCON directo, de eventos/logs, o de una persistencia/agregación propia. - -## Context -El proyecto ya integra RCON para live state y la auditoría previa concluyó que el RCON actual del proyecto solo cubre estado live directo. Sin embargo, CRCON / HLL Records muestran métricas avanzadas como: -- `most_killed` -- `death_by` -- duelos entre jugadores -- kills por arma -- otros agregados históricos avanzados - -Antes de diseñar una V2 del MVP, hace falta entender exactamente de dónde salen esos datos en términos técnicos. - -## Steps -1. Revisar la auditoría existente sobre capacidades RCON. -2. Analizar la implementación actual del proyecto y documentar claramente qué NO está saliendo del cliente RCON actual. -3. Investigar conceptualmente qué caminos posibles explican la existencia de métricas avanzadas en CRCON / HLL Records: - - comandos RCON directos - - flujo de eventos - - logs del servidor - - almacenamiento propio de CRCON - - API interna o snapshots enriquecidos -4. Revisar si en la repo ya hay pistas, docs o referencias sobre: - - `most_killed` - - `death_by` - - `kills_by_type` - - `death_by_weapons` - - killer/victim -5. Documentar una conclusión clara: - - qué es plausible obtener por RCON puro - - qué parece requerir captura de eventos o logs - - qué parece requerir agregación histórica propia -6. Dejar una matriz clara de origen probable por métrica. -7. No implementar todavía la captura ni nuevas tablas. -8. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- ai/architecture-index.md -- docs/rcon-data-capability-audit.md -- docs/monthly-player-ranking-data-audit.md -- backend/README.md -- backend/app/rcon_client.py -- backend/app/providers/rcon_provider.py -- backend/app/data_sources.py -- cualquier doc local relacionada con CRCON, HLL Records o métricas avanzadas si existiera - -## Expected Files to Modify -- docs/crcon-advanced-metrics-origin-audit.md -- opcionalmente ai/architecture-index.md -- opcionalmente docs/decisions.md si surge una conclusión técnica clara - -## Constraints -- No implementar todavía captura avanzada. -- No tocar producto visible. -- No asumir sin evidencia que una métrica sale de RCON directo. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en discovery técnico. - -## Validation -- Existe un documento que separa claramente: - - RCON directo - - eventos/logs - - agregación/persistencia propia -- Queda claro el origen probable de métricas como `most_killed` y `death_by` -- Los cambios quedan committeados y se hace push si el entorno lo permite. - -## Change Budget -- Preferir menos de 4 archivos modificados o creados. -- Preferir menos de 220 líneas cambiadas. diff --git a/ai/tasks/done/TASK-076-player-event-pipeline-v2-design.md b/ai/tasks/done/TASK-076-player-event-pipeline-v2-design.md deleted file mode 100644 index 60f60f3..0000000 --- a/ai/tasks/done/TASK-076-player-event-pipeline-v2-design.md +++ /dev/null @@ -1,63 +0,0 @@ -# TASK-076-player-event-pipeline-v2-design - -## Goal -Diseñar una arquitectura mínima de pipeline de eventos de jugador que permita, en una futura fase, persistir y agregar datos avanzados necesarios para una V2 del ranking MVP. - -## Context -Si métricas como killer/victim, `most_killed`, `death_by`, kills por arma o acciones tácticas no salen listas de RCON puro, el proyecto necesitará una canalización propia de eventos/logs y una persistencia específica para construir esas vistas. - -## Steps -1. Revisar la auditoría sobre el origen de métricas avanzadas. -2. Diseñar una arquitectura mínima para una futura canalización de eventos. -3. Definir qué tipos de eventos serían necesarios como base, por ejemplo: - - kill - - death - - killer -> victim - - weapon used - - teamkill - - cualquier otro evento imprescindible confirmado -4. Definir qué tabla o modelo de persistencia haría falta a alto nivel. -5. Definir cómo se agregarían después métricas como: - - `most_killed` - - `death_by` - - kills por arma - - distinción infantry/tank/artillery si fuera posible -6. Explicar cómo esa capa podría alimentar una futura V2 del MVP mensual. -7. Mantener fuera de alcance la implementación real. -8. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- ai/architecture-index.md -- docs/rcon-data-capability-audit.md -- docs/crcon-advanced-metrics-origin-audit.md -- docs/monthly-mvp-ranking-scoring-design.md -- backend/README.md -- backend/app/historical_models.py -- backend/app/historical_storage.py -- backend/app/rcon_client.py - -## Expected Files to Modify -- docs/player-event-pipeline-v2-design.md -- opcionalmente ai/architecture-index.md -- opcionalmente docs/decisions.md - -## Constraints -- No implementar todavía la canalización. -- No crear tablas ni rutas reales. -- No tocar producto visible. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en diseño técnico. - -## Validation -- Existe un documento claro con la arquitectura mínima propuesta para eventos de jugador. -- Queda claro qué eventos serían necesarios y cómo alimentarían una V2 del MVP. -- Los cambios quedan committeados y se hace push si el entorno lo permite. - -## Change Budget -- Preferir menos de 4 archivos modificados o creados. -- Preferir menos de 220 líneas cambiadas. diff --git a/ai/tasks/done/TASK-077-player-kill-event-source-adapter.md b/ai/tasks/done/TASK-077-player-kill-event-source-adapter.md deleted file mode 100644 index 64464cc..0000000 --- a/ai/tasks/done/TASK-077-player-kill-event-source-adapter.md +++ /dev/null @@ -1,77 +0,0 @@ -# TASK-077-player-kill-event-source-adapter - -## Goal -Implementar una primera capa/adaptador de fuente de eventos centrada en eventos de kill/death para preparar la V2 del sistema de métricas de jugador. - -## Context -Las auditorías previas concluyen que el cliente RCON live actual no basta por sí solo para obtener directamente todos los agregados avanzados visibles en ecosistemas tipo CRCON/HLL Records. Para construir métricas como: -- killer -> victim -- most_killed -- death_by -- kills por arma -- teamkills por evento - -hace falta una fuente de eventos o una adaptación técnica que permita modelar esos datos en bruto antes de agregarlos. - -La V2 debe empezar por una primera capa mínima centrada en eventos de kill/death, sin abarcar todavía todo el resto de acciones tácticas. - -## Steps -1. Revisar las auditorías y documentos de diseño V2: - - docs/rcon-data-capability-audit.md - - docs/crcon-advanced-metrics-origin-audit.md - - docs/player-event-pipeline-v2-design.md -2. Identificar la fuente o punto técnico más viable dentro del proyecto actual para empezar a capturar eventos de kill/death. -3. Diseñar e implementar un adaptador/fuente mínima para eventos de jugador que, como mínimo, pueda producir un formato común con campos base como: - - server - - match - - timestamp - - killer - - victim - - weapon si existe - - teamkill si existe -4. Mantener esta capa desacoplada de la persistencia final. -5. Documentar claramente: - - qué datos se capturan realmente en esta fase - - qué datos siguen fuera de alcance -6. No implementar todavía snapshots/UI del MVP V2. -7. No romper live RCON ni el histórico actual. -8. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- ai/repo-context.md -- ai/architecture-index.md -- docs/rcon-data-capability-audit.md -- docs/crcon-advanced-metrics-origin-audit.md -- docs/player-event-pipeline-v2-design.md -- backend/README.md -- backend/app/rcon_client.py -- backend/app/providers/rcon_provider.py -- backend/app/data_sources.py - -## Expected Files to Modify -- backend/README.md -- opcionalmente nuevos módulos, por ejemplo: - - backend/app/player_event_source.py - - backend/app/providers/player_event_source_provider.py - - backend/app/event_sources/*.py -- opcionalmente ai/architecture-index.md si conviene enlazar la nueva pieza - -## Constraints -- No implementar todavía agregados finales ni UI. -- No romper el proveedor RCON live actual. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en una fuente mínima de eventos kill/death. - -## Validation -- Existe una capa/adaptador clara para eventos de kill/death. -- Produce un formato mínimo reutilizable por la persistencia posterior. -- Queda documentado qué cubre y qué no cubre todavía. -- Los cambios quedan committeados y se hace push si el entorno lo permite. - -## Change Budget -- Preferir menos de 6 archivos modificados o creados. -- Preferir menos de 240 líneas cambiadas. diff --git a/ai/tasks/done/TASK-078-player-event-raw-ledger-storage.md b/ai/tasks/done/TASK-078-player-event-raw-ledger-storage.md deleted file mode 100644 index 1f81d77..0000000 --- a/ai/tasks/done/TASK-078-player-event-raw-ledger-storage.md +++ /dev/null @@ -1,65 +0,0 @@ -# TASK-078-player-event-raw-ledger-storage - -## Goal -Crear la persistencia raw mínima para eventos de jugador V2, permitiendo almacenar de forma fiable eventos de kill/death con claves estables, deduplicación y base para agregados posteriores. - -## Context -Una vez exista una fuente/adaptador de eventos, hace falta una capa de persistencia en bruto. Esta capa debe ser lo bastante simple para operar ya, pero lo bastante sólida para soportar luego agregados como: -- most_killed -- death_by -- kills por arma -- teamkills por jugador -- killer/victim mensual - -## Steps -1. Revisar el diseño V2 del pipeline de eventos. -2. Diseñar una tabla o conjunto mínimo de tablas para el ledger raw de eventos de jugador. -3. Incluir como base, si la fuente lo permite: - - server key - - match reference - - event timestamp - - killer identity - - victim identity - - weapon - - teamkill flag - - event source reference o clave de deduplicación -4. Implementar inicialización segura del storage de eventos. -5. Implementar inserción idempotente o deduplicada. -6. Mantener separada esta capa del histórico actual `historical_*`. -7. Documentar la estructura y su propósito. -8. No implementar todavía agregados finales ni UI. -9. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- docs/player-event-pipeline-v2-design.md -- backend/README.md -- backend/app/historical_models.py -- backend/app/historical_storage.py -- cualquier módulo nuevo de la task anterior relacionado con eventos - -## Expected Files to Modify -- backend/README.md -- opcionalmente nuevos módulos, por ejemplo: - - backend/app/player_event_storage.py - - backend/app/player_event_models.py -- opcionalmente docs/decisions.md si conviene fijar una decisión de persistencia - -## Constraints -- No romper el histórico actual. -- No mezclar esta persistencia con snapshots ni UI. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en el ledger raw de eventos. - -## Validation -- Existe una persistencia raw mínima para eventos de jugador. -- Soporta deduplicación o idempotencia razonable. -- Queda separada del histórico actual. -- Los cambios quedan committeados y se hace push si el entorno lo permite. - -## Change Budget -- Preferir menos de 6 archivos modificados o creados. -- Preferir menos de 240 líneas cambiadas. diff --git a/ai/tasks/done/TASK-079-player-event-ingestion-worker.md b/ai/tasks/done/TASK-079-player-event-ingestion-worker.md deleted file mode 100644 index e1d99f2..0000000 --- a/ai/tasks/done/TASK-079-player-event-ingestion-worker.md +++ /dev/null @@ -1,57 +0,0 @@ -# TASK-079-player-event-ingestion-worker - -## Goal -Añadir un worker/proceso incremental para ingerir eventos de jugador V2 de forma segura, reanudable y compatible con la operación actual del proyecto. - -## Context -Con una fuente de eventos y un ledger raw, hace falta un proceso de ingestión incremental que capture eventos sin depender del request path del usuario y sin romper el pipeline actual de histórico y snapshots. - -## Steps -1. Revisar la nueva capa de fuente de eventos y la persistencia raw. -2. Diseñar un worker incremental específico para eventos de jugador. -3. Añadir soporte para: - - ejecución manual - - reintentos básicos - - checkpoint o mecanismo de reanudación si aplica - - deduplicación segura -4. Mantenerlo desacoplado del `historical-runner` actual si eso reduce riesgo operacional. -5. Documentar cómo se ejecuta y cuál es su alcance. -6. No implementar todavía snapshots finales ni UI del MVP V2. -7. No romper el stack Docker actual ni el flujo histórico existente. -8. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- docs/player-event-pipeline-v2-design.md -- backend/README.md -- backend/app/historical_runner.py -- backend/app/config.py -- módulos de eventos añadidos en tasks previas - -## Expected Files to Modify -- backend/app/config.py -- backend/README.md -- opcionalmente docker-compose.yml si hace falta dejar preparado el worker -- opcionalmente nuevos módulos, por ejemplo: - - backend/app/player_event_worker.py - - backend/app/player_event_ingestion.py - -## Constraints -- No romper el runner histórico actual. -- No meter todavía lógica de scoring V2. -- No tocar producto visible. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en ingestión incremental de eventos. - -## Validation -- Existe un worker o flujo incremental para eventos de jugador. -- Puede ejecutarse de forma segura y reanudable. -- No rompe el resto del sistema. -- Los cambios quedan committeados y se hace push si el entorno lo permite. - -## Change Budget -- Preferir menos de 6 archivos modificados o creados. -- Preferir menos de 240 líneas cambiadas. diff --git a/ai/tasks/done/TASK-080-player-event-derived-aggregates.md b/ai/tasks/done/TASK-080-player-event-derived-aggregates.md deleted file mode 100644 index d513af3..0000000 --- a/ai/tasks/done/TASK-080-player-event-derived-aggregates.md +++ /dev/null @@ -1,65 +0,0 @@ -# TASK-080-player-event-derived-aggregates - -## Goal -Construir los primeros agregados derivados V2 a partir del ledger raw de eventos de jugador, centrados en duelos y armas, para preparar una futura V2 del MVP. - -## Context -Con eventos raw ya capturados, el siguiente paso es derivar métricas útiles y reutilizables. Las primeras más valiosas para la V2 del MVP son: -- most_killed -- death_by -- killer/victim -- kills por arma -- teamkills por jugador - -## Steps -1. Revisar la estructura del ledger raw y el diseño V2. -2. Diseñar e implementar agregados básicos por: - - partida - - mes - - servidor - - all-servers cuando aplique -3. Incluir al menos: - - most_killed - - death_by - - net duel summaries - - kills por arma - - teamkills derivados por jugador -4. Mantener los agregados separados de la UI y del MVP V1. -5. Documentar qué métricas derivadas quedan ya disponibles para una futura V2 del score. -6. No implementar todavía la fórmula final del MVP V2 ni su UI. -7. No hacer cambios destructivos. -8. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- docs/player-event-pipeline-v2-design.md -- docs/crcon-advanced-metrics-origin-audit.md -- backend/README.md -- módulos de eventos raw ya implementados -- backend/app/historical_storage.py -- docs/monthly-mvp-ranking-scoring-design.md - -## Expected Files to Modify -- backend/README.md -- opcionalmente nuevos módulos, por ejemplo: - - backend/app/player_event_aggregates.py - - backend/app/player_event_queries.py -- opcionalmente docs/decisions.md si hace falta fijar alguna decisión de agregación - -## Constraints -- No tocar todavía la UI del MVP V2. -- No romper el MVP V1. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en agregados base de duelos y armas. - -## Validation -- Existen agregados derivados básicos reutilizables para V2. -- Queda clara su disponibilidad por servidor/mes/all-servers cuando aplique. -- Los cambios quedan committeados y se hace push si el entorno lo permite. - -## Change Budget -- Preferir menos de 6 archivos modificados o creados. -- Preferir menos de 240 líneas cambiadas. diff --git a/ai/tasks/done/TASK-081-player-event-snapshots-and-api.md b/ai/tasks/done/TASK-081-player-event-snapshots-and-api.md deleted file mode 100644 index bc735a1..0000000 --- a/ai/tasks/done/TASK-081-player-event-snapshots-and-api.md +++ /dev/null @@ -1,81 +0,0 @@ -# TASK-081-player-event-snapshots-and-api - -## Goal -Exponer por snapshots JSON y API propia del backend las nuevas métricas derivadas V2 de eventos de jugador, manteniendo la filosofía de lectura rápida y desacoplada del request path pesado. - -## Context -La base V2 ya existe: -- source adapter -- raw ledger -- incremental worker -- derived aggregates - -Ahora hace falta convertir esas métricas derivadas en una capa consumible por producto y por futuras fórmulas de MVP V2 sin depender de consultas pesadas on-demand. - -Las primeras métricas que deben quedar listas para lectura rápida son: -- most_killed -- death_by -- duel summaries -- weapon kills -- teamkills derivados - -## Steps -1. Revisar los agregados V2 ya implementados. -2. Diseñar snapshots JSON adecuados para estas métricas avanzadas por: - - servidor - - all-servers cuando aplique - - periodo mensual si corresponde -3. Exponer endpoints claros y consistentes para leer esas métricas. -4. Mantener la misma filosofía que el histórico actual: - - lectura rápida - - sin cálculos pesados en el request path -5. Incluir metadatos claros en los snapshots cuando aplique: - - generated_at - - period/month_key - - source_range_start - - source_range_end - - found / is_stale si aplica -6. Integrar la generación de estos snapshots con la operativa existente o con una vía equivalente razonable. -7. No implementar todavía la UI V2 final. -8. No romper el MVP V1 ni los snapshots actuales. -9. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- backend/README.md -- backend/app/historical_snapshots.py -- backend/app/historical_snapshot_storage.py -- backend/app/routes.py -- backend/app/payloads.py -- backend/app/player_event_aggregates.py -- backend/app/player_event_storage.py -- docs/player-event-pipeline-v2-design.md - -## Expected Files to Modify -- backend/app/routes.py -- backend/app/payloads.py -- backend/app/historical_snapshots.py -- backend/app/historical_snapshot_storage.py -- backend/README.md -- opcionalmente nuevos módulos auxiliares si mejoran claridad - -## Constraints -- No recalcular estas métricas pesadas en cada request. -- No romper la API histórica existente. -- No tocar todavía la UI final del MVP V2. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en snapshots/API V2. - -## Validation -- Existen snapshots JSON de métricas V2. -- Existen endpoints backend para leerlas. -- La lectura es rápida y coherente con la arquitectura actual. -- No se rompe el MVP V1 ni el histórico actual. -- Los cambios quedan committeados y se hace push si el entorno lo permite. - -## Change Budget -- Preferir menos de 6 archivos modificados o creados. -- Preferir menos de 240 líneas cambiadas. diff --git a/ai/tasks/done/TASK-082-monthly-mvp-v2-scoring-design-adjustment.md b/ai/tasks/done/TASK-082-monthly-mvp-v2-scoring-design-adjustment.md deleted file mode 100644 index 951175b..0000000 --- a/ai/tasks/done/TASK-082-monthly-mvp-v2-scoring-design-adjustment.md +++ /dev/null @@ -1,69 +0,0 @@ -# TASK-082-monthly-mvp-v2-scoring-design-adjustment - -## Goal -Diseñar o ajustar de forma precisa la fórmula del MVP mensual V2 incorporando las nuevas métricas derivadas de eventos de jugador ya disponibles. - -## Context -La V1 del MVP mensual ya existe y se apoya en métricas persistidas básicas. Con la nueva capa V2 de eventos y agregados, ya se pueden plantear señales más ricas como: -- kills por arma -- teamkills derivados -- duelos y rivalidades -- most_killed / death_by -- posible ponderación por tipo de kill si la señal es suficientemente fiable - -Antes de implementar el backend del MVP V2, hace falta cerrar la fórmula concreta y sus pesos. - -## Steps -1. Revisar el diseño de scoring V1 y la nueva disponibilidad de métricas V2. -2. Decidir qué métricas avanzadas entran realmente en la V2. -3. Diseñar una fórmula concreta para el MVP mensual V2, incluyendo: - - pesos - - elegibilidad - - penalizaciones - - tratamiento de muestras pequeñas - - desempates -4. Decidir si: - - las kills deben ponderarse por arma/tipo - - cómo influye teamkill - - cómo influye duelo/rivalidad - - qué parte de la V1 se mantiene -5. Mantener la fórmula defendible y explicable, evitando complejidad artificial si la señal aún no es robusta. -6. Dejar clara la compatibilidad o convivencia entre: - - MVP V1 - - MVP V2 -7. No implementar todavía la UI. -8. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- docs/monthly-mvp-ranking-scoring-design.md -- docs/player-event-pipeline-v2-design.md -- docs/monthly-player-ranking-data-audit.md -- backend/README.md -- backend/app/player_event_aggregates.py -- cualquier snapshot/API V2 disponible tras la task previa - -## Expected Files to Modify -- docs/monthly-mvp-v2-scoring-design.md -- opcionalmente docs/decisions.md -- opcionalmente ai/architecture-index.md - -## Constraints -- No implementar todavía el cálculo backend del MVP V2. -- No tocar producto visible. -- No depender de métricas no confirmadas. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en diseño de scoring V2. - -## Validation -- Existe un documento claro con la fórmula V2 propuesta. -- Quedan definidos pesos, elegibilidad, penalizaciones y desempates. -- Queda claro qué señales entran realmente en V2. -- Los cambios quedan committeados y se hace push si el entorno lo permite. - -## Change Budget -- Preferir menos de 4 archivos modificados o creados. -- Preferir menos de 220 líneas cambiadas. diff --git a/ai/tasks/done/TASK-083-monthly-mvp-v2-backend-calculation.md b/ai/tasks/done/TASK-083-monthly-mvp-v2-backend-calculation.md deleted file mode 100644 index 5df42bb..0000000 --- a/ai/tasks/done/TASK-083-monthly-mvp-v2-backend-calculation.md +++ /dev/null @@ -1,64 +0,0 @@ -# TASK-083-monthly-mvp-v2-backend-calculation - -## Goal -Implementar en backend el cálculo mensual del MVP V2 a partir de la fórmula aprobada y de las métricas derivadas V2 ya disponibles por snapshots/agregados. - -## Context -La base V2 ya existe y, tras cerrar el diseño de scoring, hace falta materializar el ranking mensual MVP V2 en backend. Esta versión debe poder convivir con la V1 mientras se valida en producto. - -## Steps -1. Revisar: - - scoring V2 aprobado - - agregados V2 disponibles - - snapshots/API de métricas avanzadas -2. Implementar el cálculo del ranking mensual MVP V2 por: - - servidor - - all-servers cuando aplique -3. Aplicar correctamente: - - pesos - - elegibilidad - - penalizaciones - - desempates -4. Mantenerlo separado del MVP V1. -5. Preparar el resultado para poder exponerlo después por snapshot/API y, más tarde, por UI. -6. Documentar la nueva capacidad backend. -7. No implementar todavía la UI final. -8. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- docs/monthly-mvp-v2-scoring-design.md -- backend/README.md -- backend/app/player_event_aggregates.py -- backend/app/historical_storage.py -- backend/app/payloads.py -- backend/app/routes.py -- backend/app/historical_snapshots.py - -## Expected Files to Modify -- backend/README.md -- backend/app/payloads.py -- backend/app/routes.py -- backend/app/historical_storage.py -- opcionalmente nuevos módulos, por ejemplo: - - backend/app/monthly_mvp_v2.py - - backend/app/monthly_mvp_v2_scoring.py - -## Constraints -- No romper el MVP V1. -- No tocar todavía la UI final. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en el cálculo backend del MVP V2. - -## Validation -- Existe un cálculo backend funcional del monthly MVP V2. -- Soporta servidor y/o all-servers según diseño. -- Convive con la V1. -- Los cambios quedan committeados y se hace push si el entorno lo permite. - -## Change Budget -- Preferir menos de 6 archivos modificados o creados. -- Preferir menos de 240 líneas cambiadas. diff --git a/ai/tasks/done/TASK-084-monthly-mvp-v2-snapshots-and-api.md b/ai/tasks/done/TASK-084-monthly-mvp-v2-snapshots-and-api.md deleted file mode 100644 index 1aabcad..0000000 --- a/ai/tasks/done/TASK-084-monthly-mvp-v2-snapshots-and-api.md +++ /dev/null @@ -1,65 +0,0 @@ -# TASK-084-monthly-mvp-v2-snapshots-and-api - -## Goal -Exponer el ranking mensual MVP V2 mediante snapshots JSON y API propia del backend, manteniéndolo separado del MVP V1 y preparado para una futura UI. - -## Context -Una vez exista el cálculo backend del MVP V2, hace falta integrarlo en la capa de snapshots y API para lectura rápida, sin añadir cálculos pesados al request path. - -## Steps -1. Revisar el cálculo backend del MVP V2. -2. Diseñar snapshots adecuados para: - - MVP V2 por servidor - - MVP V2 all-servers si aplica -3. Exponer endpoints claros y consistentes para leer estos snapshots. -4. Incluir metadatos útiles: - - generated_at - - month_key / periodo - - found - - source_range_start / source_range_end si aplica -5. Integrar la generación en la operativa existente de snapshots si corresponde. -6. Mantener la separación explícita entre: - - MVP V1 - - MVP V2 -7. No implementar todavía la UI V2 final en esta task. -8. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- backend/README.md -- backend/app/historical_snapshots.py -- backend/app/historical_snapshot_storage.py -- backend/app/routes.py -- backend/app/payloads.py -- backend/app/historical_runner.py -- backend/app/config.py - -## Expected Files to Modify -- backend/app/routes.py -- backend/app/payloads.py -- backend/app/historical_snapshots.py -- backend/app/historical_snapshot_storage.py -- backend/app/historical_runner.py -- backend/README.md -- opcionalmente nuevos módulos auxiliares si mejoran claridad - -## Constraints -- No romper snapshots existentes. -- No mezclar MVP V1 y V2. -- No tocar todavía la UI final. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en snapshots/API del MVP V2. - -## Validation -- Existen snapshots JSON del MVP V2. -- Existen endpoints backend para leerlos. -- La lectura es rápida. -- MVP V1 y V2 conviven claramente. -- Los cambios quedan committeados y se hace push si el entorno lo permite. - -## Change Budget -- Preferir menos de 6 archivos modificados o creados. -- Preferir menos de 240 líneas cambiadas. diff --git a/ai/tasks/done/TASK-085-monthly-mvp-v2-ui.md b/ai/tasks/done/TASK-085-monthly-mvp-v2-ui.md deleted file mode 100644 index f7bf9e0..0000000 --- a/ai/tasks/done/TASK-085-monthly-mvp-v2-ui.md +++ /dev/null @@ -1,67 +0,0 @@ -# TASK-085-monthly-mvp-v2-ui - -## Goal -Exponer en la UI histórica el Top MVP mensual V2 y sus señales avanzadas básicas, manteniéndolo explícitamente separado del MVP V1. - -## Context -El backend ya tiene: -- monthly-mvp-v2 por servidor y global -- snapshots V2 player-events -- scoring V2 operativo -- señales útiles para teamkills, most-killed, death-by, duels y weapon-kills - -Ahora hace falta llevar esa V2 a la página histórica sin sustituir todavía la V1. - -## Steps -1. Revisar: - - frontend/historico.html - - frontend/assets/js/historico.js - - frontend/assets/css/historico.css - - backend endpoints ya disponibles -2. Añadir una sección o bloque claro de MVP mensual V2. -3. Mantener convivencia explícita entre: - - MVP V1 - - MVP V2 -4. Mostrar al menos: - - Top 3 o Top N V2 - - score V2 - - teamkill penalty - - una o dos señales avanzadas resumidas (por ejemplo most_killed_count, duel_control_raw o arma destacada si el payload ya la ofrece) -5. Diseñar estados vacíos, loading y error correctos. -6. No eliminar ni romper la UI V1 existente. -7. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- backend/README.md -- backend/app/routes.py -- backend/app/payloads.py -- frontend/historico.html -- frontend/assets/js/historico.js -- frontend/assets/css/historico.css -- docs/monthly-mvp-v2-scoring-design.md - -## Expected Files to Modify -- frontend/historico.html -- frontend/assets/js/historico.js -- frontend/assets/css/historico.css -- opcionalmente backend/README.md si conviene documentar el consumo UI - -## Constraints -- No romper el MVP V1. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en la UI del MVP V2. -- Evitar mezclar V1 y V2 en un único bloque confuso. - -## Validation -- La UI muestra correctamente MVP V2 por servidor y all-servers. -- Convive con V1. -- Los estados vacíos y de carga están resueltos. -- Los cambios quedan committeados y se hace push si el entorno lo permite. - -## Change Budget -- Preferir menos de 5 archivos modificados o creados. -- Preferir menos de 220 líneas cambiadas. diff --git a/ai/tasks/done/TASK-086-mvp-v1-v2-comparison-panel.md b/ai/tasks/done/TASK-086-mvp-v1-v2-comparison-panel.md deleted file mode 100644 index b10c230..0000000 --- a/ai/tasks/done/TASK-086-mvp-v1-v2-comparison-panel.md +++ /dev/null @@ -1,48 +0,0 @@ -# TASK-086-mvp-v1-v2-comparison-panel - -## Goal -Añadir una comparación ligera y comprensible entre MVP V1 y MVP V2 para facilitar validación de producto antes de decidir sustitución o convergencia. - -## Context -La V2 ya calcula y sirve rankings distintos. Antes de reemplazar la V1, interesa poder comparar visualmente diferencias de forma controlada. - -## Steps -1. Revisar la UI resultante tras la task anterior. -2. Diseñar un panel simple de comparación V1 vs V2. -3. Mostrar diferencias comprensibles, por ejemplo: - - posición V1 vs posición V2 - - teamkill penalty - - cambio relativo de score -4. Mantener la comparación ligera y orientada a validación, no a saturar la página. -5. No fusionar todavía V1 y V2 en una sola fórmula visible. -6. Al completar la implementación: - - dejar el repositorio consistente - - hacer commit - - hacer push al remoto si el entorno lo permite - -## Files to Read First -- AGENTS.md -- frontend/historico.html -- frontend/assets/js/historico.js -- frontend/assets/css/historico.css -- docs/monthly-mvp-ranking-scoring-design.md -- docs/monthly-mvp-v2-scoring-design.md - -## Expected Files to Modify -- frontend/historico.html -- frontend/assets/js/historico.js -- frontend/assets/css/historico.css - -## Constraints -- No eliminar todavía la V1. -- No hacer cambios destructivos. -- Mantener el trabajo centrado en comparación y validación de producto. - -## Validation -- Existe una comparación ligera V1 vs V2 entendible. -- No se rompe la UI histórica. -- Los cambios quedan committeados y se hace push si el entorno lo permite. - -## Change Budget -- Preferir menos de 4 archivos modificados o creados. -- Preferir menos de 180 líneas cambiadas. diff --git a/ai/tasks/done/TASK-087-configurable-historical-refresh-overlap.md b/ai/tasks/done/TASK-087-configurable-historical-refresh-overlap.md deleted file mode 100644 index a9e4ab6..0000000 --- a/ai/tasks/done/TASK-087-configurable-historical-refresh-overlap.md +++ /dev/null @@ -1,71 +0,0 @@ -# TASK-087-configurable-historical-refresh-overlap - -## Goal -Hacer configurable la ventana de solape del refresh historico para permitir pasadas manuales de 24h, 48h o mas sobre todos los servidores sin recurrir a un bootstrap grande innecesario. - -## Context -La operativa actual del historico tiene dos limites practicos: -- el refresh incremental del historico base relee solo una ventana corta reciente -- el worker de player-events V2 tambien corta demasiado pronto para recuperar huecos recientes de forma controlada - -Esto complica recuperar faltantes reales de los ultimos 1-3 dias, por ejemplo cuando faltan datos desde el lunes en uno o varios servidores. - -La solucion inmediata no es RCON historico, sino exponer una ventana de solape configurable para: -- `historical_ingestion refresh` -- `player_event_worker refresh` - -## Steps -1. Revisar el flujo actual de cutoff y solape en: - - `backend/app/historical_ingestion.py` - - `backend/app/historical_storage.py` - - `backend/app/player_event_worker.py` - - `backend/app/player_event_storage.py` - - `backend/app/config.py` -2. Añadir configuracion explicita para el solape temporal del refresh, manteniendo compatibilidad hacia atras: - - `HLL_HISTORICAL_REFRESH_OVERLAP_HOURS` - - `HLL_PLAYER_EVENT_REFRESH_OVERLAP_HOURS` -3. Exponer tambien override por CLI en ambos comandos: - - `python -m app.historical_ingestion refresh --overlap-hours 48` - - `python -m app.player_event_worker refresh --overlap-hours 48` -4. Mantener el comportamiento por defecto actual o equivalente si el operador no pasa override. -5. Asegurar que el refresh global sin `--server` recorre los tres servidores historicos ya registrados. -6. Documentar en README el runbook operativo para: - - pasada manual de 48 horas - - pasada de validacion por un solo servidor - - recomposicion posterior de snapshots -7. Mantener el trabajo limitado al backend y runbook operativo. No tocar UI. - -## Files to Read First -- `backend/README.md` -- `backend/app/historical_ingestion.py` -- `backend/app/historical_storage.py` -- `backend/app/player_event_worker.py` -- `backend/app/player_event_storage.py` -- `backend/app/config.py` - -## Expected Files to Modify -- `backend/app/historical_ingestion.py` -- `backend/app/historical_storage.py` -- `backend/app/player_event_worker.py` -- `backend/app/player_event_storage.py` -- `backend/app/config.py` -- `backend/README.md` - -## Constraints -- No romper el refresh incremental actual. -- No cambiar el proveedor historico actual por defecto. -- No tocar frontend. -- No introducir dependencias nuevas. -- El override por CLI debe ser opcional. -- La ventana por defecto debe seguir siendo conservadora para no disparar coste innecesario. - -## Validation -- Existe soporte de configuracion/env para overlap del historico base. -- Existe soporte de configuracion/env para overlap de player-events. -- Existen flags CLI `--overlap-hours` en ambos comandos. -- Una pasada manual de 48 horas queda documentada para todos los servidores. -- El repositorio queda consistente. - -## Change Budget -- Preferir menos de 7 archivos modificados o creados. -- Preferir menos de 260 lineas cambiadas. diff --git a/ai/tasks/done/TASK-088-rcon-historical-ingestion-feasibility.md b/ai/tasks/done/TASK-088-rcon-historical-ingestion-feasibility.md deleted file mode 100644 index 6daf1d8..0000000 --- a/ai/tasks/done/TASK-088-rcon-historical-ingestion-feasibility.md +++ /dev/null @@ -1,70 +0,0 @@ -# TASK-088-rcon-historical-ingestion-feasibility - -## Goal -Aterrizar con precision si la repo puede soportar una ingesta historica por RCON y, en caso afirmativo, definir una arquitectura minima, incremental y defendible sin asumir capacidades que hoy no estan probadas. - -## Context -La repo ya tiene: -- proveedor live por RCON -- seleccion de `historical_data_source` -- placeholder `RconHistoricalDataSource` - -Pero todavia no existe una implementacion historica real por RCON. Antes de abrir trabajo de implementacion, hace falta una auditoria tecnica que determine: -- que datos puede dar realmente el cliente RCON actual -- si permiten reconstruccion historica, solo captura prospectiva o solo telemetria parcial -- que huecos deben mantenerse temporalmente en `public-scoreboard` -- que contrato minimo puede exponerse sin vender capacidades inexistentes - -## Steps -1. Revisar la capa actual de seleccion de proveedores y el adapter RCON existente. -2. Auditar el cliente RCON y documentar exactamente: - - comandos soportados hoy - - forma del payload disponible hoy - - frecuencia de captura razonable - - si hay o no base para historico real de partidas cerradas -3. Redactar una decision tecnica clara con una de estas salidas: - - no viable con el cliente actual - - viable solo para captura prospectiva - - viable para una capa historica parcial -4. Diseñar la arquitectura minima recomendada: - - almacenamiento - - workers - - checkpoints - - compatibilidad con `public-scoreboard` - - politica de degradacion si faltan metricas -5. Dejar una propuesta de fases realista: - - fase 1: captura prospectiva - - fase 2: lectura operativa minima - - fase 3: metricas competitivas si la senal lo permite -6. Actualizar README para reflejar el estado real y evitar ambiguedad sobre “historico por RCON”. - -## Files to Read First -- `backend/README.md` -- `backend/app/data_sources.py` -- `backend/app/providers/rcon_provider.py` -- `backend/app/rcon_client.py` -- `backend/app/historical_ingestion.py` -- `backend/app/historical_storage.py` -- `backend/app/player_event_worker.py` -- `backend/app/player_event_storage.py` - -## Expected Files to Modify -- `docs/rcon-historical-ingestion-design.md` -- `backend/README.md` - -## Constraints -- No implementar aun la ingesta historica por RCON. -- No cambiar runtime behavior del backend. -- No tocar frontend. -- No asumir que RCON resuelve backfill retroactivo si eso no esta demostrado. -- Mantener el documento muy concreto y util para una implementacion posterior. - -## Validation -- Existe un documento de diseno con conclusion clara. -- El README deja claro que parte esta implementada y cual no. -- No se introducen cambios de comportamiento en produccion o desarrollo. -- El repositorio queda consistente. - -## Change Budget -- Preferir menos de 3 archivos modificados o creados. -- Preferir menos de 220 lineas cambiadas. diff --git a/ai/tasks/done/TASK-089-rcon-prospective-historical-capture-foundation.md b/ai/tasks/done/TASK-089-rcon-prospective-historical-capture-foundation.md deleted file mode 100644 index 5188ad0..0000000 --- a/ai/tasks/done/TASK-089-rcon-prospective-historical-capture-foundation.md +++ /dev/null @@ -1,72 +0,0 @@ -# TASK-089-rcon-prospective-historical-capture-foundation - -## Goal -Implementar una base de captura historica prospectiva por RCON que empiece a persistir datos hacia delante sin sustituir todavia `public-scoreboard` y sin prometer recuperacion retroactiva de periodos ya perdidos. - -## Context -Esta task depende del diseno aprobado en la task anterior. - -El objetivo aqui no es “rehacer todo el historico por RCON” en un solo paso, sino dejar una primera capacidad operativa para recoger telemetria historica hacia delante desde los targets RCON configurados. - -La captura debe: -- vivir fuera del request path HTTP -- persistir datos con trazabilidad y checkpoints -- convivir con el historico actual basado en `public-scoreboard` -- ser util aunque al principio no cubra todas las metricas competitivas - -## Steps -1. Revisar el diseno de `docs/rcon-historical-ingestion-design.md`. -2. Crear una capa de almacenamiento propia para historico prospectivo RCON: - - tablas o estructuras separadas del historico `historical_*` actual - - trazabilidad por servidor, run y checkpoint -3. Extender el cliente/provider RCON solo en la medida aprobada por el diseno: - - sin asumir comandos no auditados - - sin mezclar live state puntual con historico persistido -4. Crear un worker o runner dedicado de captura prospectiva RCON. -5. Permitir ejecucion: - - manual de una pasada - - periodica por bucle local o Compose -6. Añadir configuracion explicita para: - - targets - - intervalo - - reintentos - - timeouts -7. Añadir metadata de estado minima y runbook en README. -8. Mantener `public-scoreboard` como fuente historica por defecto hasta que exista una capa de lectura historica RCON util. - -## Files to Read First -- `docs/rcon-historical-ingestion-design.md` -- `backend/README.md` -- `backend/app/data_sources.py` -- `backend/app/providers/rcon_provider.py` -- `backend/app/rcon_client.py` -- `backend/app/config.py` -- `docker-compose.yml` - -## Expected Files to Modify -- `backend/app/config.py` -- `backend/app/data_sources.py` -- `backend/app/providers/rcon_provider.py` -- `backend/app/rcon_client.py` -- uno o varios archivos nuevos bajo `backend/app/` para worker/storage/run tracking -- `backend/README.md` -- opcionalmente `docker-compose.yml` si conviene dejar un servicio dedicado - -## Constraints -- No reemplazar todavia `public-scoreboard` como fuente historica principal. -- No tocar la UI. -- No romper `/api/servers` live por RCON. -- No prometer backfill retroactivo. -- Mantener separada la telemetria prospectiva RCON del historico importado actual. -- No introducir dependencias externas innecesarias. - -## Validation -- Existe una pasada manual funcional de captura prospectiva RCON. -- Existen checkpoints o run tracking. -- La persistencia queda separada y consistente. -- README documenta la operativa minima. -- La repo sigue pudiendo arrancar sin obligar a usar RCON historico. - -## Change Budget -- Preferir menos de 9 archivos modificados o creados. -- Preferir menos de 420 lineas cambiadas. diff --git a/ai/tasks/done/TASK-090-rcon-historical-provider-minimal-read-model.md b/ai/tasks/done/TASK-090-rcon-historical-provider-minimal-read-model.md deleted file mode 100644 index 5185d52..0000000 --- a/ai/tasks/done/TASK-090-rcon-historical-provider-minimal-read-model.md +++ /dev/null @@ -1,65 +0,0 @@ -# TASK-090-rcon-historical-provider-minimal-read-model - -## Goal -Construir una primera capa de lectura historica minima sobre la persistencia prospectiva RCON, sin intentar aun paridad completa con todos los rankings competitivos del historico actual. - -## Context -Esta task depende de la task anterior. - -Una vez exista captura prospectiva RCON, hace falta una primera capa de lectura util que permita comprobar cobertura real y exponer algo operativo sin mentir sobre la profundidad disponible. - -La prioridad aqui no es clonar toda la salida de `public-scoreboard`, sino exponer: -- cobertura -- actividad reciente -- estado del historico RCON disponible -- una base compatible para evolucion posterior - -## Steps -1. Implementar una primera version funcional de `RconHistoricalDataSource` basada en datos persistidos, no en consultas RCON on-demand dentro del request path. -2. Definir un read model minimo util para: - - resumen/cobertura por servidor - - actividad o sesiones recientes - - metadata de disponibilidad y frescura -3. Exponer un camino de seleccion seguro por `HLL_BACKEND_HISTORICAL_DATA_SOURCE=rcon` sin romper el modo `public-scoreboard`. -4. Mantener la degradacion controlada cuando falten metricas: - - devolver payload coherente - - documentar que contratos quedan soportados y cuales no todavia -5. Actualizar README y runbook para aclarar: - - que endpoints funcionan con la lectura RCON minima - - que endpoints siguen dependiendo de `public-scoreboard` -6. No intentar aun: - - weekly/monthly leaderboards completos - - MVP V1/V2 completos - - equivalencia total con `historico.html` - -## Files to Read First -- `docs/rcon-historical-ingestion-design.md` -- `backend/README.md` -- `backend/app/data_sources.py` -- `backend/app/payloads.py` -- `backend/app/routes.py` -- los archivos creados en la task anterior para captura prospectiva RCON - -## Expected Files to Modify -- `backend/app/data_sources.py` -- `backend/app/payloads.py` -- `backend/app/routes.py` -- uno o varios archivos nuevos bajo `backend/app/` para read model RCON historico -- `backend/README.md` - -## Constraints -- No sustituir aun el historico actual completo. -- No tocar frontend. -- No exponer contratos falsos o semicompletos como si fueran paridad total. -- La lectura HTTP debe seguir siendo fast-path de solo lectura sobre persistencia local. -- Si un endpoint no queda soportado por la capa minima, debe quedar documentado y degradar de forma clara. - -## Validation -- `HLL_BACKEND_HISTORICAL_DATA_SOURCE=rcon` deja una lectura historica minima operativa y documentada. -- El backend no rompe el modo `public-scoreboard`. -- La documentacion deja claro el alcance real de esta primera capa de lectura. -- El repositorio queda consistente. - -## Change Budget -- Preferir menos de 7 archivos modificados o creados. -- Preferir menos de 320 lineas cambiadas. diff --git a/ai/tasks/done/TASK-091-sqlite-writer-hardening.md b/ai/tasks/done/TASK-091-sqlite-writer-hardening.md deleted file mode 100644 index 63fe59d..0000000 --- a/ai/tasks/done/TASK-091-sqlite-writer-hardening.md +++ /dev/null @@ -1,53 +0,0 @@ -# TASK-091-sqlite-writer-hardening - -## Goal -Unificar y endurecer la politica de conexion SQLite para todas las rutas de escritura del backend que comparten la misma base de datos, reduciendo contencion evitable y haciendo el comportamiento consistente entre historico base, player-events y captura prospectiva RCON. - -## Context -La repo ya tiene varias rutas de escritura sobre el mismo SQLite: -- historico base CRCON -- player-event ledger V2 -- captura prospectiva RCON -- snapshots y runners asociados - -Parte del storage ya usa timeout/WAL/busy_timeout, pero no toda la capa de persistencia lo hace de forma uniforme. Antes de cualquier politica de locking entre procesos, hace falta que todas las conexiones writer-capable usen una configuracion SQLite coherente. - -## Scope -Backend solamente. Sin cambios en frontend. - -## Steps -1. Auditar todas las funciones `_connect()` o equivalentes que abren SQLite en: - - `backend/app/historical_storage.py` - - `backend/app/player_event_storage.py` - - `backend/app/rcon_historical_storage.py` - - cualquier otro storage writer-capable relacionado -2. Crear una utilidad compartida y pequena para abrir conexiones SQLite con politica comun de escritura. -3. La politica comun debe incluir como minimo: - - `timeout` explicito - - `PRAGMA foreign_keys = ON` - - `PRAGMA journal_mode = WAL` - - `PRAGMA busy_timeout` - - `row_factory = sqlite3.Row` -4. Reusar esa utilidad en todas las capas de persistencia con escritura que comparten el mismo DB. -5. Mantener compatibilidad con la ruta actual del storage y sin cambiar contratos HTTP. -6. Actualizar README/runbook backend con una nota breve sobre la politica SQLite usada por writers. - -## Constraints -- No tocar frontend. -- No cambiar la semantica funcional de los endpoints. -- No cambiar el proveedor historico por defecto. -- No meter dependencias nuevas salvo necesidad extrema. -- Mantener la utilidad pequeña y facil de leer. - -## Validation -- Todas las capas writer-capable relevantes comparten la misma politica SQLite. -- `python -m compileall app` pasa. -- Las CLIs principales siguen arrancando con `--help`. -- La repo queda consistente. - -## Expected Files -- `backend/app/historical_storage.py` -- `backend/app/player_event_storage.py` -- `backend/app/rcon_historical_storage.py` -- un util compartido nuevo bajo `backend/app/` si hace falta -- `backend/README.md` diff --git a/ai/tasks/done/TASK-092-single-writer-locking-for-automation-workers.md b/ai/tasks/done/TASK-092-single-writer-locking-for-automation-workers.md deleted file mode 100644 index 4df73e7..0000000 --- a/ai/tasks/done/TASK-092-single-writer-locking-for-automation-workers.md +++ /dev/null @@ -1,81 +0,0 @@ -# TASK-092-single-writer-locking-for-automation-workers - -## Goal -Imponer una coordinacion de single-writer entre todos los procesos del backend que escriben sobre el mismo SQLite compartido, evitando colisiones entre automatizaciones y ejecuciones manuales y sustituyendo errores opacos de `database is locked` por una coordinacion controlada y mensajes claros. - -## Context -Actualmente pueden coincidir sobre el mismo volumen `/app/data`: -- `historical-runner` -- `player_event_worker` -- `rcon-historical-worker` -- ejecuciones manuales via `docker compose exec backend ...` - -Aunque WAL y busy_timeout ayudan, no garantizan una operativa limpia si varios writers largos arrancan a la vez. Hace falta una politica de exclusion mutua a nivel de proceso/job, no solo a nivel SQLite. - -## Scope -Backend y orquestacion minima/documentacion. Sin cambios en frontend. - -## Desired Design -Implementar un unico lock compartido para todos los writers que tocan el mismo SQLite. - -Ese lock debe: -- vivir bajo el storage compartido en `/app/data` o una ruta derivada del `storage_path` -- ser comun para: - - `app.historical_runner` - - `app.historical_ingestion` - - `app.player_event_worker` - - `app.rcon_historical_worker` -- adquirirse al principio de cada run writer-oriented -- liberarse siempre aunque haya excepcion -- incluir metadata visible del holder: - - proceso/comando - - started_at - - host/container si es viable -- tener espera configurable con timeout y poll interval -- fallar con error claro cuando no pueda adquirir el lock dentro del timeout -- evitar dependencias nuevas si es posible - -## Steps -1. Crear una utilidad comun de writer lock compartido para el backend. -2. Aplicarla a: - - `historical_ingestion` manual - - `historical_runner` - - `player_event_worker` - - `rcon_historical_worker` -3. Asegurarte de que el lock cubre la ejecucion writer-oriented completa, no solo una sentencia aislada. -4. Exponer configuracion/env para: - - lock timeout - - poll interval -5. Añadir mensajes de error/estado legibles cuando el lock este ocupado. -6. Mantener las rutas HTTP read-only fuera de este lock. -7. Actualizar `docker-compose.yml` solo si es necesario para dejar la operativa alineada. -8. Actualizar `backend/README.md` con runbook claro: - - que writers comparten lock - - como hacer una pasada manual - - que pasa si el lock esta ocupado - - como convivir con automatizaciones sin parar contenedores salvo necesidad excepcional - -## Constraints -- No tocar frontend. -- No convertir esto en un rediseño total del scheduler. -- No romper los workers ya existentes. -- No bloquear las rutas HTTP de lectura. -- No ampliar el alcance funcional del read model RCON. -- Debe quedar claro que la solucion principal es single-writer coordination, no solo subir retries. - -## Validation -- Existe un lock compartido real para los writers. -- `historical_runner`, `historical_ingestion`, `player_event_worker` y `rcon_historical_worker` lo usan. -- Si dos writers coinciden, no se produce un fallo opaco de SQLite; hay espera controlada o error claro de lock ocupado. -- `python -m compileall app` pasa. -- Las CLIs principales siguen respondiendo con `--help`. -- La repo queda consistente. - -## Expected Files -- uno o varios utilitarios nuevos bajo `backend/app/` -- `backend/app/historical_runner.py` -- `backend/app/historical_ingestion.py` -- `backend/app/player_event_worker.py` -- `backend/app/rcon_historical_worker.py` -- `docker-compose.yml` si hace falta -- `backend/README.md` diff --git a/ai/tasks/done/TASK-093-rcon-first-source-selection-and-fallback-policy.md b/ai/tasks/done/TASK-093-rcon-first-source-selection-and-fallback-policy.md deleted file mode 100644 index db78936..0000000 --- a/ai/tasks/done/TASK-093-rcon-first-source-selection-and-fallback-policy.md +++ /dev/null @@ -1,60 +0,0 @@ -# TASK-093-rcon-first-source-selection-and-fallback-policy - -## Goal -Convertir la aplicación a una política RCON-first real para extracción de datos, manteniendo fallback automático a los métodos antiguos solo cuando RCON falle. - -## Context -La repo ya tiene piezas RCON para live y captura prospectiva, pero todavía no está orientada a RCON-first por defecto. -Ahora mismo el sistema sigue arrancando con defaults antiguos y la política funcional real no coincide con el objetivo del producto. - -Queremos: -- live/state de servidores -> RCON primero, A2S solo como fallback -- histórico/recopilación -> RCON primero, CRCON/public-scoreboard solo como fallback -- selección de fuente transparente, consistente y observable - -## Steps -1. Auditar la selección actual de fuentes en: - - `backend/app/data_sources.py` - - `backend/app/payloads.py` - - `backend/app/collector.py` - - providers live e históricos actuales - - `backend/app/rcon_historical_read_model.py` -2. Introducir una política explícita de “source arbitration” o equivalente: - - RCON como fuente primaria - - fallback a A2S para live si RCON falla - - fallback a public-scoreboard/CRCON para histórico si RCON falla o no puede servir la operación concreta -3. Definir criterios claros de fallback: - - error de red / timeout / auth / target no disponible - - falta de cobertura o capacidad para una operación histórica concreta -4. Hacer que la respuesta backend deje trazabilidad clara: - - fuente primaria intentada - - fuente finalmente usada - - si hubo fallback - - motivo del fallback -5. Ajustar defaults/config para que el comportamiento por defecto del proyecto sea coherente con RCON-first. -6. Actualizar README con una sección clara: - - política de prioridad de fuentes - - casos de fallback - - qué capacidades históricas siguen siendo parciales en RCON y cuándo entra CRCON/public-scoreboard - -## Constraints -- No romper compatibilidad con los métodos antiguos. -- No eliminar A2S ni public-scoreboard. -- No tocar frontend salvo que haga falta exponer metadata mínima ya existente. -- Mantener el comportamiento observable y fácil de depurar. - -## Validation -- El backend intenta RCON primero para live. -- Si RCON live falla, el backend cae a A2S de forma controlada. -- El backend intenta RCON primero para histórico. -- Si RCON histórico falla o no soporta una operación concreta, el backend cae a public-scoreboard/CRCON. -- Las respuestas reflejan qué fuente se usó realmente. -- README queda alineado con la política RCON-first. - -## Expected Files -- `backend/app/data_sources.py` -- `backend/app/payloads.py` -- `backend/app/collector.py` -- providers/fuentes necesarias bajo `backend/app/` -- `backend/README.md` -- `backend/app/config.py` si hace falta para defaults explícitos diff --git a/ai/tasks/done/TASK-094-rcon-first-historical-orchestration-and-safe-fallback.md b/ai/tasks/done/TASK-094-rcon-first-historical-orchestration-and-safe-fallback.md deleted file mode 100644 index dc3dde0..0000000 --- a/ai/tasks/done/TASK-094-rcon-first-historical-orchestration-and-safe-fallback.md +++ /dev/null @@ -1,67 +0,0 @@ -# TASK-094-rcon-first-historical-orchestration-and-safe-fallback - -## Goal -Reorientar la orquestación histórica para que RCON sea la vía principal de recopilación cuando esté disponible, dejando el flujo CRCON/public-scoreboard como fallback seguro y no como camino primario permanente. - -## Context -Actualmente: -- existe `historical_runner` -- existe `rcon_historical_worker` -- existe locking single-writer -Pero la orquestación no representa todavía una estrategia RCON-first coherente. -Queremos una orquestación donde: -- la recopilación prospectiva por RCON sea la prioridad -- el refresh histórico clásico solo entre cuando RCON falle o no cubra la operación -- no haya starvation del lock por loops demasiado agresivos -- las automatizaciones sean operables en Docker sin bloquear trabajo manual innecesariamente - -## Steps -1. Auditar: - - `backend/app/historical_runner.py` - - `backend/app/historical_ingestion.py` - - `backend/app/rcon_historical_worker.py` - - `backend/app/writer_lock.py` - - `docker-compose.yml` -2. Definir una estrategia clara: - - RCON historical capture como flujo primario - - historical_ingestion clásico como fallback - - snapshots/rebuilds alineados con esa política -3. Evitar que el worker RCON monopolice el writer lock: - - revisar intervalos por defecto - - revisar duración del trabajo por loop - - revisar si conviene separar captura frecuente y rebuild menos frecuente -4. Asegurar que las pasadas manuales sean razonables: - - si hay automatización activa, que el operador tenga mensajes claros - - reducir riesgo de starvation o lock ocupado permanente -5. Mejorar el manejo de stale locks entre contenedores Docker si es necesario: - - no depender solo del hostname si eso da falsos locks persistentes - - mantener seguridad y evitar liberar locks válidos por error -6. Ajustar `docker-compose.yml` para que el stack quede alineado con el nuevo comportamiento por defecto. -7. Actualizar README/runbook: - - qué proceso captura RCON primero - - cuándo entra el fallback histórico clásico - - cómo lanzar pasadas manuales - - cómo interpretar locks ocupados - -## Constraints -- No eliminar el locking compartido. -- No volver al comportamiento sin coordinación de writers. -- No dejar CRCON/public-scoreboard como camino principal encubierto. -- No romper la captura prospectiva RCON ya existente. - -## Validation -- La automatización prioriza RCON para recopilación histórica. -- El flujo clásico entra solo como fallback. -- El lock compartido sigue funcionando. -- La operativa Docker no queda en starvation constante. -- Las pasadas manuales tienen comportamiento claro y documentado. -- README/runbook queda actualizado. - -## Expected Files -- `backend/app/historical_runner.py` -- `backend/app/historical_ingestion.py` -- `backend/app/rcon_historical_worker.py` -- `backend/app/writer_lock.py` -- `docker-compose.yml` -- `backend/README.md` -- otros archivos backend si la orquestación lo requiere diff --git a/ai/tasks/done/TASK-095-restore-community-scores-link-and-source-aware-ui.md b/ai/tasks/done/TASK-095-restore-community-scores-link-and-source-aware-ui.md deleted file mode 100644 index a61149b..0000000 --- a/ai/tasks/done/TASK-095-restore-community-scores-link-and-source-aware-ui.md +++ /dev/null @@ -1,40 +0,0 @@ -# TASK-095-restore-community-scores-link-and-source-aware-ui - -## Goal -Restaurar correctamente el enlace/botón hacia los scores/histórico de comunidad y asegurar que la UI no pierda acciones útiles por depender de mapas hardcodeados incompletos. - -## Context -Se ha detectado que el botón/enlace hacia los scores/histórico de comunidad ha desaparecido o se degrada en algunos casos. -La lógica actual depende de un mapa hardcodeado incompleto y no cubre bien todos los servidores o casos reales. - -## Steps -1. Auditar: - - `frontend/index.html` - - `frontend/assets/js/main.js` - - `frontend/assets/css/styles.css` - - si hace falta, el payload backend consumido por `/api/servers` -2. Restaurar el CTA de scores/histórico para todos los servidores relevantes. -3. Evitar depender exclusivamente de un mapa hardcodeado incompleto cuando haya información backend utilizable. -4. Mantener una experiencia estable: - - si existe URL conocida -> mostrar enlace - - si no existe -> degradar de forma clara, no desaparecer silenciosamente -5. Mantener el diseño coherente con la landing actual. -6. No mezclar esta task con refactors amplios no relacionados. - -## Constraints -- No rehacer toda la homepage. -- No tocar la UI histórico V1/V2 salvo necesidad estricta. -- No inventar enlaces falsos. -- Si una URL no está disponible, la UI debe indicarlo de forma limpia. - -## Validation -- El botón/enlace a scores/histórico vuelve a mostrarse correctamente. -- No desaparece por un mapa hardcodeado incompleto. -- La landing sigue renderizando bien. -- La repo queda consistente. - -## Expected Files -- `frontend/index.html` -- `frontend/assets/js/main.js` -- `frontend/assets/css/styles.css` -- opcionalmente backend si se necesita exponer mejor la URL o metadata correspondiente diff --git a/ai/tasks/done/TASK-096-rcon-first-historical-runtime-selection.md b/ai/tasks/done/TASK-096-rcon-first-historical-runtime-selection.md deleted file mode 100644 index 6b6ad4d..0000000 --- a/ai/tasks/done/TASK-096-rcon-first-historical-runtime-selection.md +++ /dev/null @@ -1,57 +0,0 @@ -# TASK-096-rcon-first-historical-runtime-selection - -## Goal -Hacer que el histórico backend funcione realmente en modo RCON-first en runtime, con fallback automático, observable y seguro a public-scoreboard/CRCON cuando RCON falle o no soporte una operación concreta. - -## Context -Hoy la repo ya tiene: -- live RCON-first con fallback a A2S -- captura prospectiva RCON -- read model histórico RCON parcial -- histórico clásico por public-scoreboard/CRCON -Pero el runtime histórico aún no se comporta como una política RCON-first completa. - -## Steps -1. Auditar la selección histórica actual en: - - `backend/app/data_sources.py` - - `backend/app/payloads.py` - - `backend/app/historical_ingestion.py` - - `backend/app/historical_runner.py` - - `backend/app/rcon_historical_read_model.py` -2. Introducir arbitraje histórico explícito: - - intento primario por RCON - - fallback a public-scoreboard/CRCON si: - - RCON falla - - RCON no tiene cobertura - - RCON no soporta esa operación concreta -3. Asegurar trazabilidad en payloads: - - `primary_source` - - `selected_source` - - `fallback_used` - - `fallback_reason` - - `source_attempts` -4. Ajustar el runtime y los defaults para que la política efectiva del stack sea coherente con histórico RCON-first. -5. Mantener compatibilidad con el histórico clásico sin romper snapshots ni workers existentes. -6. Actualizar `backend/README.md` y runbook para que el comportamiento real quede claro. - -## Constraints -- No romper live RCON-first ya existente. -- No eliminar public-scoreboard/CRCON. -- No degradar el request path HTTP en latencia o estabilidad de forma evitable. -- No fingir soporte RCON en operaciones que todavía no están cubiertas. - -## Validation -- `/health` y/o la metadata funcional relevante reflejan una política histórica RCON-first coherente. -- Los endpoints históricos compatibles intentan RCON primero. -- Cuando RCON no sirve, el fallback a public-scoreboard/CRCON es observable y claro. -- La repo queda consistente. - -## Expected Files -- `backend/app/data_sources.py` -- `backend/app/payloads.py` -- `backend/app/historical_ingestion.py` -- `backend/app/historical_runner.py` -- `backend/app/rcon_historical_read_model.py` -- `backend/app/config.py` -- `backend/README.md` -- `docker-compose.yml` si hace falta diff --git a/ai/tasks/done/TASK-097-elo-mmr-capabilities-and-data-contract.md b/ai/tasks/done/TASK-097-elo-mmr-capabilities-and-data-contract.md deleted file mode 100644 index af0b86a..0000000 --- a/ai/tasks/done/TASK-097-elo-mmr-capabilities-and-data-contract.md +++ /dev/null @@ -1,65 +0,0 @@ -# TASK-097-elo-mmr-capabilities-and-data-contract - -## Goal -Definir e implementar la base de contrato de datos, capabilities y storage para un sistema de MMR persistente + MonthlyRankScore mensual inspirado en `sistema_elo_mensual_hll.pdf`, adaptado a la telemetría real disponible hoy. - -## Context -El PDF define una arquitectura con: -- MMR persistente -- ranking mensual visible -- calidad de match -- subíndices por rol -- ImpactScore -- MatchScore -- MonthlyRankScore -Pero la repo actual no dispone de todas las métricas del documento con precisión total. - -Hace falta una base sólida que no mezcle: -- lo que el PDF ideal propone -- lo que hoy se puede calcular de verdad - -## Steps -1. Leer el PDF `sistema_elo_mensual_hll.pdf` y descomponerlo en: - - inputs obligatorios - - inputs opcionales - - inputs no disponibles todavía -2. Auditar las fuentes reales actuales: - - live RCON - - read model histórico RCON - - player-event V2 - - histórico clásico CRCON/public-scoreboard -3. Crear una especificación operativa dentro del repo para el sistema Elo/MMR: - - qué campos existen - - cuáles son exactos - - cuáles son aproximados - - cuáles no están disponibles -4. Diseñar e implementar storage mínimo para: - - snapshots o checkpoints mensuales de rating - - MMR persistente por jugador - - MatchScore / impacto por match cuando proceda - - metadata de capabilities por cálculo -5. Dejar una capa de contrato o modelos Python claros para: - - match validity - - quality factor Q - - role bucket - - subindices - - monthly eligibility - - penalties -6. No cerrar todavía las fórmulas finales si falta señal; primero dejar bien cerrada la base de datos y contrato semántico. - -## Constraints -- No inventar métricas inexistentes. -- No mezclar cálculo final con datos no soportados. -- No romper MVP V1/V2 actuales. -- La documentación debe dejar cristalino qué parte del PDF está soportada hoy y cuál no. - -## Validation -- Existe documentación técnica concreta de capabilities del sistema Elo/MMR. -- Existen modelos/contratos/backend storage listos para cálculo incremental. -- La repo deja clara la diferencia entre exacto, aproximado y no disponible. -- La repo queda consistente. - -## Expected Files -- `docs/elo-mmr-monthly-ranking-design.md` -- uno o varios archivos nuevos bajo `backend/app/` para modelos/contratos/storage Elo -- `backend/README.md` diff --git a/ai/tasks/done/TASK-098-elo-mmr-core-engine-v1-backed-by-real-signals.md b/ai/tasks/done/TASK-098-elo-mmr-core-engine-v1-backed-by-real-signals.md deleted file mode 100644 index 5b1619f..0000000 --- a/ai/tasks/done/TASK-098-elo-mmr-core-engine-v1-backed-by-real-signals.md +++ /dev/null @@ -1,67 +0,0 @@ -# TASK-098-elo-mmr-core-engine-v1-backed-by-real-signals - -## Goal -Implementar una primera versión operativa del motor de MMR persistente + MonthlyRankScore mensual usando únicamente señales reales o aproximaciones justificadas por la telemetría disponible hoy. - -## Context -Esta task debe apoyarse en la especificación y capabilities de la task anterior. - -La implementación debe seguir el espíritu del PDF: -- validar matches -- factor de calidad Q -- OutcomeScore -- ImpactScore por rol -- DeltaMMR -- MatchScore -- MonthlyRankScore -Pero sin fingir precisión donde no existe. - -## Steps -1. Implementar la validación de partida y el factor de calidad Q con las señales disponibles reales. -2. Implementar la lógica de bucket mínima viable: - - rol principal - - modo si está disponible - - tramo de duración -3. Implementar los subíndices soportables hoy: - - OutcomeScore - - CombatIndex - - UtilityIndex cuando haya señal - - LeadershipIndex cuando haya señal - - DisciplineIndex con teamkills / abandonos / AFK si la fuente real lo permite - - ObjectiveIndex exacto o aproximado solo si está realmente soportado -4. Implementar `ImpactScore` con pesos por rol inspirados en el PDF. -5. Implementar actualización de `MMR` persistente. -6. Implementar `MatchScore` mensual. -7. Implementar agregación mensual de `MonthlyRankScore` con: - - Confidence - - Activity - - Consistency - - StrengthOfSchedule - - PenaltyPoints -8. Marcar explícitamente en el resultado de cada cálculo: - - qué partes se calcularon con señal exacta - - qué partes fueron aproximadas - - qué partes quedaron no disponibles -9. Exponer una API o endpoints internos/backend claros para consultar: - - rating persistente del jugador - - leaderboard mensual Elo/MMR - - metadata de cálculo/capabilities -10. Mantener MVP V1/V2 existentes sin romperse. - -## Constraints -- No vender esta V1 del motor como “idéntica al PDF” si hay aproximaciones. -- No usar valores mágicos sin documentarlos. -- No romper endpoints históricos actuales. -- No rehacer toda la UI en esta task. - -## Validation -- Existe cálculo persistente de MMR para jugadores soportados. -- Existe cálculo mensual visible de ranking/score. -- El resultado expone metadata de exactitud/aproximación. -- La repo queda consistente. -- La documentación queda alineada con lo realmente implementado. - -## Expected Files -- archivos backend nuevos o modificados bajo `backend/app/` para engine/storage/routes/payloads Elo -- `backend/README.md` -- `docs/elo-mmr-monthly-ranking-design.md` diff --git a/ai/tasks/done/TASK-099-elo-mmr-product-exposure-and-ui-minimal.md b/ai/tasks/done/TASK-099-elo-mmr-product-exposure-and-ui-minimal.md deleted file mode 100644 index d4aa28c..0000000 --- a/ai/tasks/done/TASK-099-elo-mmr-product-exposure-and-ui-minimal.md +++ /dev/null @@ -1,46 +0,0 @@ -# TASK-099-elo-mmr-product-exposure-and-ui-minimal - -## Goal -Exponer de forma mínima y útil en producto el nuevo sistema de rating/MMR mensual sin romper el histórico actual ni mezclarlo de forma confusa con MVP V1/V2. - -## Context -Una vez exista el motor base, hace falta hacer visible el sistema: -- leaderboard mensual Elo/MMR -- score visible del mes -- rating persistente o skill score -- metadata suficiente para no confundir al usuario - -## Steps -1. Auditar la UI histórica actual y decidir el punto de exposición mínimo más claro. -2. Añadir un bloque o vista mínima para: - - rating persistente - - score mensual - - elegibilidad mensual - - indicación básica de si el cálculo es exacto / aproximado / parcial -3. Mantener separación clara respecto a: - - MVP V1 - - MVP V2 - - player-events V2 -4. No saturar la UI. -5. Si procede, añadir copy/tooltip/legend breve explicando: - - que el sistema prioriza señales reales - - que algunas métricas avanzadas pueden estar en modo parcial según cobertura -6. Validar que los enlaces/histórico existentes no se rompen. - -## Constraints -- No rehacer toda la página histórica. -- No borrar MVP V1/V2. -- No esconder la naturaleza parcial si el cálculo aún no es completo. -- Mantener UX legible y estable. - -## Validation -- El sistema Elo/MMR aparece en producto de forma entendible. -- No rompe bloques existentes. -- La UI deja claro qué representa cada score. -- La repo queda consistente. - -## Expected Files -- `frontend/historico.html` -- `frontend/assets/js/historico.js` -- `frontend/assets/css/historico.css` -- backend solo si hace falta ajustar payloads expuestos diff --git a/ai/tasks/done/TASK-100-rcon-historical-writer-path-implementation.md b/ai/tasks/done/TASK-100-rcon-historical-writer-path-implementation.md deleted file mode 100644 index 403dd90..0000000 --- a/ai/tasks/done/TASK-100-rcon-historical-writer-path-implementation.md +++ /dev/null @@ -1,53 +0,0 @@ -# TASK-100-rcon-historical-writer-path-implementation - -## Goal -Implementar un writer path histórico real por RCON para que la ingesta histórica intente RCON primero y use scoreboard/public-scoreboard solo como fallback. - -## Context -La repo ya tiene: -- live RCON-first -- captura prospectiva RCON -- read model histórico RCON parcial -- ingesta histórica clásica por scoreboard -Pero todavía no existe un writer path histórico real por RCON integrado en `historical_ingestion`. - -## Steps -1. Auditar: - - `backend/app/data_sources.py` - - `backend/app/historical_ingestion.py` - - `backend/app/rcon_historical_worker.py` - - `backend/app/rcon_historical_storage.py` - - `backend/app/rcon_historical_read_model.py` - - cualquier capa necesaria de modelos/storage -2. Definir qué significa “writer path histórico RCON” con la telemetría real actual: - - qué puede alimentar - - qué estructura persistida necesita - - cómo se integra con el ingestion flow existente -3. Implementar una vía writer-oriented RCON que permita a `historical_ingestion` intentar primero RCON. -4. Si RCON falla o no cubre la operación concreta, hacer fallback controlado a scoreboard/public-scoreboard. -5. Mantener trazabilidad explícita: - - primary_source - - selected_source - - fallback_used - - fallback_reason - - source_attempts -6. No romper la compatibilidad con snapshots ni con rebuilds posteriores. -7. Actualizar README/runbook explicando el nuevo writer path real. - -## Constraints -- No fingir cobertura histórica RCON que no exista. -- No eliminar scoreboard como fallback. -- No romper live RCON-first. -- No romper el locking compartido. - -## Validation -- `historical_ingestion` intenta RCON primero. -- Cuando RCON falla o no soporta la operación, hace fallback explícito a scoreboard. -- La salida del comando deja claro qué fuente se usó realmente. -- El repositorio queda consistente. - -## Expected Files -- `backend/app/data_sources.py` -- `backend/app/historical_ingestion.py` -- archivos backend necesarios para writer path RCON -- `backend/README.md` diff --git a/ai/tasks/done/TASK-101-remove-false-rcon-first-claims-and-fix-operational-visibility.md b/ai/tasks/done/TASK-101-remove-false-rcon-first-claims-and-fix-operational-visibility.md deleted file mode 100644 index ad5488d..0000000 --- a/ai/tasks/done/TASK-101-remove-false-rcon-first-claims-and-fix-operational-visibility.md +++ /dev/null @@ -1,38 +0,0 @@ -# TASK-101-remove-false-rcon-first-claims-and-fix-operational-visibility - -## Goal -Alinear documentación, outputs operativos y visibilidad de progreso con el comportamiento real del sistema, evitando afirmaciones engañosas sobre histórico RCON-first y mejorando la operativa del refresh manual. - -## Context -Actualmente el operador puede pensar que la ingesta histórica ya va por RCON cuando en realidad el writer path sigue cayendo a scoreboard. -Además, el comando de refresh es demasiado opaco: tarda mucho y no ofrece progreso útil. - -## Steps -1. Auditar: - - `backend/README.md` - - `backend/app/historical_ingestion.py` - - outputs/logs relevantes -2. Corregir cualquier copy/documentación que sugiera que la ingesta histórica completa ya está en RCON si no es cierto. -3. Añadir progreso operativo útil al refresh manual: - - servidor actual - - página actual - - número de match ids a detallar - - fuente realmente seleccionada -4. Hacer que, cuando haya fallback a scoreboard, eso quede visible para el operador en tiempo real o en el payload final. -5. Mantener la salida usable, sin inundar de logs innecesarios. -6. Actualizar runbook con recomendaciones reales para pasadas manuales y límites razonables. - -## Constraints -- No convertir el comando en un spam de logs. -- No ocultar fallbacks reales. -- No mezclar esta task con grandes cambios de UI frontend. - -## Validation -- El operador puede ver progreso útil durante un refresh. -- La fuente usada de verdad queda visible. -- La documentación ya no induce a error. -- El repositorio queda consistente. - -## Expected Files -- `backend/app/historical_ingestion.py` -- `backend/README.md` diff --git a/ai/tasks/done/TASK-102-rcon-historical-competitive-read-model-primary.md b/ai/tasks/done/TASK-102-rcon-historical-competitive-read-model-primary.md deleted file mode 100644 index ede644c..0000000 --- a/ai/tasks/done/TASK-102-rcon-historical-competitive-read-model-primary.md +++ /dev/null @@ -1,54 +0,0 @@ -# TASK-102-rcon-historical-competitive-read-model-primary - -## Goal -Construir una capa histórica competitiva primaria basada en persistencia RCON, o en una materialización derivada de ella, suficiente para soportar el producto histórico sin depender de public-scoreboard como writer principal. - -## Context -Hoy la repo ya tiene: -- captura histórica prospectiva RCON -- read model histórico RCON mínimo -- histórico clásico por public-scoreboard -- player-events V2 -- Elo/MMR mensual -Pero el writer path histórico competitivo sigue dependiendo del archivo clásico importado por scoreboard. - -## Steps -1. Auditar: - - `backend/app/rcon_historical_storage.py` - - `backend/app/rcon_historical_read_model.py` - - `backend/app/historical_storage.py` - - `backend/app/player_event_storage.py` - - `backend/app/elo_mmr_storage.py` - - `backend/app/payloads.py` -2. Definir un modelo primario histórico competitivo RCON-backed: - - directo sobre persistencia RCON, o - - mediante tablas/materializaciones derivadas generadas desde RCON -3. Ese modelo debe cubrir como prioridad: - - recent activity / recent matches - - historical server summary - - métricas mínimas competitivas reutilizables por MVP/Elo -4. Si hacen falta tablas/materialized snapshots nuevas, crearlas. -5. Dejar capabilities explícitas por dominio: - - exact - - approximate - - partial - - unavailable -6. Documentar claramente qué parte del histórico ya puede dejar de depender del import clásico. -7. Mantener scoreboard como fallback solo para lo que todavía no esté cubierto. - -## Constraints -- No romper la persistencia RCON ya existente. -- No eliminar el histórico clásico todavía. -- No inventar granularidad que la captura RCON no tenga. -- No degradar el request path HTTP innecesariamente. - -## Validation -- Existe una capa histórica competitiva primaria RCON-backed real. -- Al menos summary/recent activity dejan de depender del pipeline clásico como principal. -- Las capabilities quedan visibles y honestas. -- La repo queda consistente. - -## Expected Files -- archivos backend nuevos o modificados bajo `backend/app/` para read model/materialización histórica RCON -- `docs/elo-mmr-monthly-ranking-design.md` si hace falta -- `backend/README.md` diff --git a/ai/tasks/done/TASK-103-rcon-first-historical-aggregates-and-fallback-boundary.md b/ai/tasks/done/TASK-103-rcon-first-historical-aggregates-and-fallback-boundary.md deleted file mode 100644 index 0d12f30..0000000 --- a/ai/tasks/done/TASK-103-rcon-first-historical-aggregates-and-fallback-boundary.md +++ /dev/null @@ -1,51 +0,0 @@ -# TASK-103-rcon-first-historical-aggregates-and-fallback-boundary - -## Goal -Mover los agregados históricos de producto a una frontera RCON-first real, dejando scoreboard solo para las piezas que todavía no puedan calcularse desde el modelo histórico competitivo RCON-backed. - -## Context -Una vez exista el modelo primario histórico competitivo RCON-backed, hace falta conectar realmente los endpoints y payloads de producto para que usen esa capa como primaria. - -## Steps -1. Auditar: - - `backend/app/payloads.py` - - `backend/app/routes.py` - - `backend/app/historical_snapshots.py` - - `backend/app/historical_snapshot_storage.py` - - `backend/app/elo_mmr_engine.py` -2. Reorientar como RCON-first real, al menos donde la nueva capa ya lo permita: - - historical server summary - - recent matches - - Elo/MMR mensual - - y cualquier agregado competitivo mínimo ya soportado -3. Mantener fallback a public-scoreboard solo cuando: - - la capability sea partial/unavailable - - la cobertura RCON no alcance - - el cálculo falle -4. Hacer visible la frontera exacta de fallback: - - qué endpoints ya son realmente RCON-first - - cuáles siguen cayendo a scoreboard - - por qué -5. Ajustar snapshots/materializaciones si hace falta para no depender del request path directo. -6. Alinear README/runbook con esta nueva frontera funcional. - -## Constraints -- No afirmar que MVP V1/V2 completos ya sean 100% RCON-backed si no lo son. -- No romper endpoints existentes. -- No ocultar el fallback real. -- Mantener latencia razonable. - -## Validation -- Los endpoints históricos soportados ya usan RCON-backed como primario real. -- El fallback a scoreboard queda reducido y explícito. -- Elo/MMR mensual consume primariamente el modelo RCON-backed donde ya sea posible. -- La repo queda consistente. - -## Expected Files -- `backend/app/payloads.py` -- `backend/app/routes.py` -- `backend/app/historical_snapshots.py` -- `backend/app/historical_snapshot_storage.py` -- `backend/app/elo_mmr_engine.py` -- `backend/README.md` -- otros archivos backend si hace falta diff --git a/ai/tasks/done/TASK-104-landing-loading-state-and-stale-lock-hardening.md b/ai/tasks/done/TASK-104-landing-loading-state-and-stale-lock-hardening.md deleted file mode 100644 index 803e212..0000000 --- a/ai/tasks/done/TASK-104-landing-loading-state-and-stale-lock-hardening.md +++ /dev/null @@ -1,45 +0,0 @@ -# TASK-104-landing-loading-state-and-stale-lock-hardening - -## Goal -Corregir dos problemas de producto/operación ya detectados: -1. la landing muestra primero datos fake estáticos antes de hidratar -2. los stale locks entre contenedores Docker siguen bloqueando pasadas manuales aunque los workers ya estén parados - -## Context -Se ha confirmado que: -- la homepage renderiza cards estáticas fake y luego las sustituye al hidratar -- eso genera un flash de datos falsos -- además, el lock compartido puede quedar huérfano entre contenedores y requiere borrado manual - -## Steps -1. Para la landing: - - auditar `frontend/index.html`, `frontend/assets/js/main.js`, `frontend/assets/css/styles.css` - - aplicar la opción A: - - no mostrar cards fake iniciales - - dejar contenedor vacío o skeleton/loading state - - renderizar solo datos reales al hidratar - - degradar limpio si falla la API -2. Para el stale lock: - - auditar `backend/app/writer_lock.py` - - mejorar la detección/recuperación de locks huérfanos entre contenedores Docker - - no depender únicamente del hostname si eso bloquea recuperación válida - - mantener seguridad para no liberar locks activos por error -3. Documentar el comportamiento actualizado en README/runbook. - -## Constraints -- No rehacer la landing completa. -- No romper el single-writer lock. -- No volver al comportamiento sin coordinación. -- No introducir riesgo de liberar locks válidos sin comprobación suficiente. - -## Validation -- La landing ya no muestra datos fake antes de hidratar. -- Los locks huérfanos entre contenedores se recuperan mejor o quedan claramente resueltos. -- La repo queda consistente. - -## Expected Files -- `frontend/index.html` -- `frontend/assets/js/main.js` -- `frontend/assets/css/styles.css` -- `backend/app/writer_lock.py` -- `backend/README.md` diff --git a/ai/tasks/done/TASK-106-rcon-primary-summary-and-recent-runtime-fix.md b/ai/tasks/done/TASK-106-rcon-primary-summary-and-recent-runtime-fix.md deleted file mode 100644 index 7d92e40..0000000 --- a/ai/tasks/done/TASK-106-rcon-primary-summary-and-recent-runtime-fix.md +++ /dev/null @@ -1,80 +0,0 @@ -# TASK-106-rcon-primary-summary-and-recent-runtime-fix - -## Goal -Corregir la frontera runtime para que `historical server summary` y `recent historical matches` usen realmente la capa RCON-backed como fuente primaria cuando haya cobertura suficiente, dejando `public-scoreboard` solo como fallback explicito. - -## Context -Las pruebas reales iniciales del sistema habian mostrado que: -- `build_historical_server_summary_payload(...)` -- `build_recent_historical_matches_payload(...)` - -seguian devolviendo en runtime: -- `selected_source = "public-scoreboard"` -- `fallback_used = true` - -cuando el objetivo de producto era que, si existe cobertura RCON suficiente, esas rutas fueran realmente RCON-first efectivas y no solo nominales. - -## Scope -Backend solamente. Sin cambios en frontend. - -## Steps -1. Auditar: - - `backend/app/payloads.py` - - `backend/app/rcon_historical_read_model.py` - - `backend/app/rcon_historical_storage.py` - - `backend/app/historical_snapshots.py` - - `backend/app/data_sources.py` -2. Identificar por que `summary` y `recent-matches` seguian seleccionando `public-scoreboard` en las pruebas reales. -3. Corregir la seleccion runtime para que: - - si hay cobertura/capability RCON suficiente -> `selected_source = "rcon"` - - si no la hay -> fallback explicito a `public-scoreboard` -4. Mantener trazabilidad clara: - - `primary_source` - - `selected_source` - - `fallback_used` - - `fallback_reason` - - `source_attempts` -5. Alinear snapshots o materializaciones si hace falta para que no obliguen a caer innecesariamente al historico clasico. -6. Actualizar README/runbook explicando la frontera exacta de summary/recent. - -## Constraints -- No fingir cobertura RCON si no existe. -- No romper endpoints existentes. -- No eliminar `public-scoreboard` como red de seguridad. -- No tocar frontend. - -## Validation -- `historical server summary` usa RCON como primario real cuando hay cobertura. -- `recent historical matches` usa RCON como primario real cuando hay cobertura. -- Cuando no haya cobertura, el fallback a `public-scoreboard` sigue siendo explicito y observable. -- La repo queda consistente. - -## Expected Files -- `backend/app/payloads.py` -- `backend/app/rcon_historical_read_model.py` -- `backend/app/rcon_historical_storage.py` -- `backend/app/historical_snapshots.py` -- `backend/app/data_sources.py` -- `backend/README.md` -- otros archivos backend solo si son estrictamente necesarios - -## Outcome -- Ya existe evidencia runtime real suficiente para considerar cumplido el objetivo funcional de la task. -- Para `server_slug = "comunidad-hispana-01"`: - - `build_historical_server_summary_payload(...)` devuelve: - - `selected_source = "rcon"` - - `fallback_used = false` - - `summary_basis = "rcon-competitive-windows"` - - `build_recent_historical_matches_payload(..., limit=2)` devuelve: - - `selected_source = "rcon"` - - `fallback_used = false` -- Esto demuestra que la frontera runtime RCON-first ya funciona con cobertura real para al menos un servidor y que `summary` y `recent-matches` ya no quedan solo en una intencion nominal. -- El fallback a `public-scoreboard` sigue intacto y sigue siendo la degradacion correcta cuando: - - no hay cobertura RCON suficiente - - un target falla - - la capability concreta no puede servirse de forma fiable desde RCON -- `comunidad-hispana-03` sigue teniendo una incidencia separada de `auth/login`, pero eso no invalida el cierre funcional de esta task porque la frontera runtime pedida aqui ya quedo validada con datos reales en al menos un servidor con cobertura. - -## Validation Notes -- Cierre administrativo basado en evidencia runtime ya validada y aportada fuera de esta actualizacion. -- No se rehacen pruebas ni se introducen cambios funcionales adicionales para este cierre. diff --git a/ai/tasks/done/TASK-107-update-ai-platform-integration.md b/ai/tasks/done/TASK-107-update-ai-platform-integration.md deleted file mode 100644 index 8065e48..0000000 --- a/ai/tasks/done/TASK-107-update-ai-platform-integration.md +++ /dev/null @@ -1,180 +0,0 @@ -# TASK-107 - Update AI Platform Integration - -## Goal - -Update the HLL Vietnam AI Platform infrastructure to align with the newer `ai-dev-platform-template` conventions while preserving this repository's product context, workflow discipline and HLL Vietnam-specific documentation. - -This is platform infrastructure work only. It must not change product behavior, backend logic, frontend behavior, Docker deployment behavior, Elo/MMR logic or RCON server #03 handling. - -## Context - -HLL Vietnam currently has a lightweight AI Platform layer under `ai/`, root `AGENTS.md`, task lifecycle folders and local Codex worker support. The next platform update should move the repository toward a controlled development-team workflow where ChatGPT acts as orchestrator between the human client/product owner and the development team, and Codex CLI workers execute only explicit tasks. - -Important current direction: - -- The Elo/MMR system is paused for now because it is too complex for the current phase. -- Comunidad Hispana / RCON server #03 is obsolete for future planning unless explicitly reintroduced. -- Historical workers and complex ranking/materialization pipelines must not be expanded by this task. -- The priority is to update AI Platform conventions safely and incrementally. - -Generic template text must be adapted to HLL Vietnam. Do not overwrite repository-specific context with generic `ai-dev-platform-template` content. - -## Steps - -1. Inspect the current platform files listed in `Files to Read First`. -2. Compare the current repository conventions conceptually with the newer `ai-dev-platform-template` conventions: - - root `ai-platform.json` - - task lifecycle folders: - - `ai/tasks/pending` - - `ai/tasks/in-progress` - - `ai/tasks/review` - - `ai/tasks/blocked` - - `ai/tasks/obsolete` - - `ai/tasks/done` - - metadata-based task template with front matter: - - `id` - - `title` - - `status` - - `type` - - `team` - - `supporting_teams` - - `roadmap_item` - - `priority` - - config-aware `scripts/codex-runner.ps1` - - `scripts/run-integration-tests.ps1` - - optional `.github/workflows/codex-worker.yml` - - `ai/reports/.gitkeep` - - generated report ignore rules -3. Add `ai-platform.json` adapted to HLL Vietnam. Include repository-specific task paths, project identity and workflow configuration needed by local platform scripts. -4. Add missing task lifecycle directories with `.gitkeep` files where needed. -5. Add `ai/reports/.gitkeep` if the reports directory is introduced or missing. -6. Update `ai/task-template.md` to the newer metadata-based format while keeping HLL Vietnam-specific instructions, constraints and validation expectations. -7. Update `scripts/codex-runner.ps1` so it reads platform configuration from `ai-platform.json` instead of relying only on hard-coded repository assumptions. -8. Add or update `scripts/run-integration-tests.ps1` with repository-appropriate lightweight validation. The script should fail safely when optional checks are not configured. -9. Add `.github/workflows/codex-worker.yml` only if it is consistent with the current repository automation policy and does not create unintended deployment or product behavior. -10. Update `.gitignore` to ignore local runtime and generated platform artifacts, including: - - `backend/runtime/` - - generated `ai/reports/*.md` files - - keep `ai/reports/.gitkeep` trackable -11. Update `AGENTS.md`, `ai/README.md`, `ai/repo-context.md` and/or `ai/architecture-index.md` only where necessary to reflect the new platform workflow. -12. Document any relevant architectural or process decisions in the task outcome. - -## Files to Read First - -- `AGENTS.md` -- `README.md` -- `.gitignore` -- `ai/README.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `ai/task-template.md` -- `scripts/codex-runner.ps1` -- `docker-compose.yml` -- `.github/workflows/*` if present - -Rules: - -- Read these files before implementation. -- Keep product behavior unchanged. -- Use the existing HLL Vietnam context as the source of truth. -- Treat template conventions as a reference, not content to copy blindly. - -## Expected Files to Modify - -Likely files: - -- `ai-platform.json` -- `.gitignore` -- `AGENTS.md` -- `ai/README.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `ai/task-template.md` -- `scripts/codex-runner.ps1` -- `scripts/run-integration-tests.ps1` -- `ai/tasks/review/.gitkeep` -- `ai/tasks/blocked/.gitkeep` -- `ai/tasks/obsolete/.gitkeep` -- `ai/reports/.gitkeep` - -Possible file, only if consistent with the repository automation policy: - -- `.github/workflows/codex-worker.yml` - -Rules: - -- Do not modify product files unless there is a platform-only reason and it is documented. -- Do not modify unrelated files. -- If additional files become necessary, explain why in the task outcome. - -## Expected Files Not To Modify - -- `backend/**` product logic -- `frontend/**` -- `docker-compose.yml` -- Elo/MMR implementation files -- RCON server #03 implementation or configuration - -## Constraints - -- This task is platform infrastructure work, not product work. -- Do not change frontend behavior. -- Do not change backend behavior. -- Do not change Docker deployment behavior. -- Do not change Elo/MMR code or expand Elo/MMR pipelines. -- Do not remove, rename or alter RCON server #03 in this task. -- Do not expand historical workers or complex ranking/materialization pipelines. -- Preserve HLL Vietnam-specific project context, Spanish-speaking community identity and current repository direction. -- Adapt template conventions to this repository instead of blindly copying generic template text. -- Keep the change narrow, reviewable and implementation-ready. - -## Validation - -Before completing the task ensure: - -- `git status` has been reviewed. -- `git diff --name-only` shows only expected platform files. -- `ai-platform.json` exists and is valid JSON. -- The task lifecycle folders exist: - - `ai/tasks/pending` - - `ai/tasks/in-progress` - - `ai/tasks/review` - - `ai/tasks/blocked` - - `ai/tasks/obsolete` - - `ai/tasks/done` -- Required empty platform directories contain `.gitkeep` files where needed. -- Generated reports such as `ai/reports/*.md` are ignored by Git. -- `ai/reports/.gitkeep` remains trackable. -- `backend/runtime/` is ignored by Git. -- No local runtime data is committed. -- A lightweight repository validation command has been run if available. -- If `scripts/run-integration-tests.ps1` exists after the change, run it. -- If no integration tests are configured for the affected scope, document that explicitly in the task outcome. -- Frontend, backend and Docker behavior remain unchanged. - -## Change Budget - -- Prefer fewer than 10 modified files for this platform update. -- Prefer small documentation and script changes over broad rewrites. -- Split follow-up work into separate tasks if the scope grows beyond platform integration. - -## Outcome - -- Added repository-specific `ai-platform.json` for task paths, worker settings and HLL Vietnam constraints. -- Added missing lifecycle folders: `review`, `blocked` and `obsolete`. -- Added `ai/reports/.gitkeep` and ignored generated `ai/reports/*.md` files while keeping `.gitkeep` trackable. -- Updated the task template to include metadata front matter and HLL Vietnam-specific constraints. -- Updated `scripts/codex-runner.ps1` to read local worker paths and prompts from `ai-platform.json`. -- Updated `scripts/run-integration-tests.ps1` to perform lightweight platform validation only. -- Updated platform documentation in `AGENTS.md`, `ai/README.md`, `ai/repo-context.md` and `ai/architecture-index.md`. -- No frontend, backend product logic, Docker behavior, Elo/MMR logic or RCON server #03 handling was changed. - -Validation performed: - -- Parsed `ai-platform.json` with `ConvertFrom-Json`. -- Ran `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1`. -- Parsed both PowerShell scripts with the PowerShell language parser. -- Confirmed `ai/reports/example.md` is ignored and `ai/reports/.gitkeep` is trackable. -- Reviewed `git diff --name-only` and `git status --short`. - -No product integration tests are configured for this platform-only scope. diff --git a/ai/tasks/done/TASK-108-disable-server3-defaults-and-simplify-deployment.md b/ai/tasks/done/TASK-108-disable-server3-defaults-and-simplify-deployment.md deleted file mode 100644 index 4c4377e..0000000 --- a/ai/tasks/done/TASK-108-disable-server3-defaults-and-simplify-deployment.md +++ /dev/null @@ -1,158 +0,0 @@ ---- -id: TASK-108 -title: Disable server #03 defaults and simplify deployment -status: done -type: documentation -team: PM -supporting_teams: - - Backend Senior - - Arquitecto Python -roadmap_item: foundation -priority: high -branch: chore/disable-server3-defaults ---- - -# TASK-108 - Disable server #03 defaults and simplify deployment - -## Goal - -Remove Comunidad Hispana server #03 from the default operational deployment/configuration path and document the simplified normal mode for HLL Vietnam. - -This task must keep the existing Elo/MMR, historical ingestion, migrations, and persisted data available in the repository. The goal is to stop treating server #03 and complex historical/Elo work as default operational requirements for the current phase, not to delete that work. - -## Context - -The AI Platform integration has just been updated and merged into `main`. The project now needs a simpler operational deployment path because the previous Elo/MMR and historical materialization work became too complex for the current phase, and Comunidad Hispana server #03 is no longer relevant because the server appears to have disappeared. - -The recommended default deployment path should be `backend` + `frontend`. Historical workers and RCON historical services may remain available for explicit advanced use, but they should not be part of the recommended normal startup. - -Preserve the current product identity: Spanish-speaking HLL Vietnam community, military/Vietnam/tactical/sober visual direction and controlled repository evolution. - -## Steps - -1. Create or switch to branch `chore/disable-server3-defaults`. -2. Inspect all files listed in **Files to Read First** before changing anything. -3. Locate every default deployment/configuration reference that treats Comunidad Hispana server #03 as part of the normal RCON operational path. -4. Remove Comunidad Hispana server #03 from default RCON targets in `docker-compose.yml`. -5. Ensure the default operational deployment path is clearly `backend` + `frontend`. -6. Keep `historical-runner` and `rcon-historical-worker` available only as explicit/advanced services, not part of the recommended normal startup. -7. Update `README.md` deployment/runbook documentation accordingly. -8. Update any relevant docs to state: - - server #03 is disabled or removed from defaults; - - Elo/MMR and complex historical ranking/materialization are paused for now; - - code and data are not deleted in this task; - - rollback or reintroduction remains possible later. -9. Do not remove code, migrations, persisted data, or database schemas. -10. Do not change live server #01 or #02 definitions except where required for formatting or consistency. -11. Keep secrets as placeholders or environment variables; do not add real passwords. -12. Validate the change with the checks below. -13. Move this task file from `ai/tasks/pending/` to `ai/tasks/done/` when validation is complete, or to `ai/tasks/review/` only if human/orchestrator review is explicitly required. -14. Commit and push the completed work. Do not leave completed work only in local. - -## Files to Read First - -- `ai/architecture-index.md` -- `ai/repo-context.md` -- `docker-compose.yml` -- `README.md` -- `backend/.env.example` -- `backend/app/config.py` -- `backend/app/data_sources.py` -- `backend/app/historical_runner.py` -- `backend/app/rcon_historical_worker.py` if present -- `docs/` - -## Expected Files to Modify - -- `docker-compose.yml` -- `README.md` -- possibly `backend/.env.example` -- possibly docs under `docs/` -- possibly `ai/repo-context.md` -- possibly `ai/architecture-index.md` -- this task file, moved from `ai/tasks/pending/` to `ai/tasks/done/` or `ai/tasks/review/` according to the AI Platform workflow - -If additional files become necessary, explain why in the task outcome and commit message. - -## Expected Files Not to Modify - -- `frontend/**`, unless there is a direct hardcoded visible reference to server #03 that must be removed -- database migrations -- persisted data -- Elo/MMR algorithm implementation files -- unrelated backend modules - -## Constraints - -- Keep the change narrow and operational. -- Do not delete Elo/MMR code. -- Do not delete historical ingestion code. -- Do not delete database migrations or persisted data. -- Do not alter database schemas. -- Do not introduce unnecessary frameworks or dependencies. -- Do not build new backend functionality. -- Do not change frontend behavior unless a visible server #03 default reference is directly found and must be adjusted. -- Do not modify unrelated files. -- Preserve HLL Vietnam project identity. -- Keep secrets as placeholders or environment variables; never add real credentials. - -## Validation - -Before completing the task ensure: - -- Run `git status`. -- Validate that `docker-compose.yml` remains syntactically valid YAML if a YAML parser is available. -- Run `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1`. -- Confirm `backend/runtime/` is not created or committed. -- Confirm server #03 is no longer present in default RCON targets. -- Confirm server #01 and server #02 remain present. -- Confirm no Elo/MMR code was deleted. -- Confirm no historical ingestion code was deleted. -- Confirm no database migrations, persisted data, or schema definitions were removed. -- Confirm no frontend behavior was unintentionally changed. -- Review `git diff --name-only` and confirm changed files match the expected scope. - -If any validation cannot be run, document the reason in the outcome before moving the task. - -## Commit And Push Requirements - -1. Run validation before committing. -2. Run `git status`. -3. Stage only intended files. -4. Commit with a clear message, for example: - - ```text - chore: disable server3 defaults and simplify deployment - ``` - -5. Push branch `chore/disable-server3-defaults` to `origin`. - -Do not leave completed work only in local. - -## Outcome - -- Removed Comunidad Hispana #03 from default RCON targets in `docker-compose.yml` and `backend/.env.example`; Comunidad Hispana #01 and #02 remain present. -- Simplified the recommended default deployment to `backend` + `frontend`. `docker compose up --build` now resolves only those services because historical workers are behind the `advanced` profile. -- Kept `historical-runner` and `rcon-historical-worker` available for explicit advanced use via `docker compose --profile advanced ...`. -- Paused Elo/MMR and complex historical materialization in documentation without deleting code, migrations, schemas, snapshots or persisted data. -- Changed backend historical defaults to `public-scoreboard` for normal operation while preserving RCON historical code for explicit advanced use. -- Updated root README, backend README, AI context and the decision log so future work does not treat #03 or historical/Elo automation as the default path. - -Validation performed: - -- `docker compose config --services` returned only `backend` and `frontend` for the default profile. -- Python YAML parser validation was skipped because `PyYAML` is not installed; Compose config validation succeeded instead. -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` passed and reported no product integration tests configured for this platform-only scope. -- Confirmed `backend/runtime/` is not present. -- Reviewed `git diff --name-only`; modified files match the expected operational/documentation scope plus backend config default alignment. -- Confirmed no frontend files, migrations, persisted data, Elo/MMR implementation files, historical ingestion implementation files, or database schemas were removed. - -Follow-up: - -- If Comunidad Hispana #03 becomes available again, create a separate validation/reintroduction task instead of restoring it as a default target directly. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-109-fix-backend-startup-with-elo-paused.md b/ai/tasks/done/TASK-109-fix-backend-startup-with-elo-paused.md deleted file mode 100644 index 6f32c4a..0000000 --- a/ai/tasks/done/TASK-109-fix-backend-startup-with-elo-paused.md +++ /dev/null @@ -1,175 +0,0 @@ ---- -id: TASK-109 -title: Keep backend startup independent from paused Elo/MMR -status: pending -type: backend -team: Backend Senior -supporting_teams: ["Arquitecto Python"] -roadmap_item: foundation -priority: high ---- - -# TASK-109 - Keep backend startup independent from paused Elo/MMR - -## Goal - -Fix backend startup so the default operational Compose profile can start `backend` and `frontend` while Elo/MMR and complex historical materialization remain paused. - -The backend must expose `/health` and non-Elo routes even if Elo/MMR engine internals are unavailable or temporarily broken. - -## Context - -HLL Vietnam has simplified its default operational mode. The normal Compose profile should start only `backend` and `frontend`; historical workers, Elo/MMR, complex historical materialization, and server #03 are paused operationally. - -Current validation shows: - -- `docker compose config --services` returns only `backend` and `frontend`. -- `docker compose up -d --build` starts the frontend successfully. -- The frontend responds with HTTP 200. -- The backend restarts continuously. -- `/health` fails because backend startup imports Elo/MMR code. -- Backend logs include: `ImportError: cannot import name 'ELO_K_FACTOR' from 'app.elo_mmr_models'`. -- The startup import path is: `app.main -> app.routes -> app.payloads -> app.elo_mmr_engine -> app.elo_mmr_models`. -- `payloads.py` imports Elo/MMR payload functions at module import time, so a paused or broken Elo implementation can break the whole backend, including `/health`. - -This task is startup-focused. Preserve the existing HLL Vietnam product identity and repository discipline, and keep the fix narrow. - -## Steps - -1. Inspect the listed files before changing anything. -2. Confirm the backend startup import path and where Elo/MMR is imported at module load time. -3. Refactor only the startup boundary needed so `/health` and non-Elo routes do not depend on successful import of Elo/MMR engine internals. -4. Prefer lazy importing Elo/MMR functions only inside Elo-specific payload builders or routes. -5. If Elo/MMR is paused or unavailable, make Elo-specific endpoints return a controlled unavailable or fallback payload instead of crashing backend import. -6. Preserve the public API shape as much as possible. -7. Add or update tests if a backend test framework exists. -8. Update lightweight validation if needed so future startup import regressions are caught. -9. Document the paused Elo/MMR startup boundary if documentation needs adjustment. -10. Run the required validation before committing. -11. Move this task file to `ai/tasks/done/` only after validation is complete and the outcome is documented. -12. Stage only intended files, commit, and push the branch to origin. - -## Files to Read First - -- `backend/app/main.py` -- `backend/app/routes.py` -- `backend/app/payloads.py` -- `backend/app/elo_mmr_engine.py` -- `backend/app/elo_mmr_models.py` -- `backend/app/config.py` -- `backend/tests/` if present -- `docker-compose.yml` -- `scripts/run-integration-tests.ps1` -- `README.md` -- `docs/decisions.md` - -## Expected Files to Modify - -- likely `backend/app/payloads.py` -- possibly `backend/app/routes.py` -- possibly `backend/app/elo_mmr_engine.py` -- possibly `backend/app/elo_mmr_models.py` only if justified -- possibly tests under `backend/tests/` -- possibly `scripts/run-integration-tests.ps1` -- this task file moved from `ai/tasks/pending/` to `ai/tasks/done/` - -If additional files become necessary, explain why in the task outcome and commit message. - -## Expected Files Not to Modify - -- `frontend/**` -- `docker-compose.yml`, unless validation proves a Compose-only issue also exists -- database migrations -- persisted data -- unrelated backend modules -- server #03 configuration - -## Constraints - -- Do not delete Elo/MMR code. -- Do not delete historical ingestion code. -- Do not remove database migrations or persisted data. -- Do not change frontend behavior. -- Do not reintroduce server #03. -- Keep the fix narrow and startup-focused. -- Do not implement a new Elo/MMR algorithm. -- Do not reintroduce `ELO_K_FACTOR` as a blind compatibility patch unless you prove it is the smallest safe fix and still prevents startup coupling. -- Keep `/health` available even if Elo/MMR import fails. -- Preserve existing public API shape as much as possible. -- Do not modify unrelated files. -- Do not leave completed work only in local; commit and push after validation. - -## Validation - -Before completing the task, run and document: - -- `git status` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- `docker compose down` -- `docker compose up -d --build` -- `docker compose ps` -- `docker compose logs --tail=100 backend` -- `Invoke-WebRequest http://localhost:8000/health | Select-Object -ExpandProperty Content` -- `Invoke-WebRequest http://localhost:8080 | Select-Object -ExpandProperty StatusCode` - -Also confirm and document: - -- backend is not restarting -- `/health` returns a valid payload -- frontend still returns 200 -- no frontend files changed -- no database migrations or persisted data changed -- `backend/runtime/` is not created or committed -- `git diff --name-only` matches the expected scope - -If integration tests are relevant and `scripts/run-integration-tests.ps1` exists, use it. If no backend test framework exists for this scope, document that explicitly in the outcome. - -## Commit And Push Requirements - -- Run all validation before committing. -- Run `git status`. -- Stage only intended files. -- Commit with a clear message, for example: `fix: keep backend startup independent from paused elo`. -- Push the branch to origin. -- Do not leave completed work only in local. - -## Outcome - -- Validation performed: - - `git status --short` - - `python -c "import sys; sys.path.insert(0, 'backend'); import app.main; from app.routes import resolve_get_payload; print(resolve_get_payload('/health'))"` - - `python -c "import sys; sys.path.insert(0, 'backend'); from app.routes import resolve_get_payload; print(resolve_get_payload('/api/historical/elo-mmr/leaderboard'))"` - - `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` - - `docker compose down` - - `docker compose up -d --build` - - `docker compose ps` - - `docker compose logs --tail=100 backend` - - `Invoke-WebRequest http://localhost:8000/health | Select-Object -ExpandProperty Content` - - `Invoke-WebRequest http://localhost:8080 | Select-Object -ExpandProperty StatusCode` - - `Invoke-WebRequest 'http://localhost:8000/api/historical/elo-mmr/leaderboard' | Select-Object -ExpandProperty Content` - - `git diff --name-only` -- Startup coupling removed: - - `backend/app/payloads.py` no longer imports `app.elo_mmr_engine` at module load time. - - Elo/MMR engine imports now happen only inside Elo/MMR payload builders. - - `app.main -> app.routes -> app.payloads` can load and serve `/health` without importing paused Elo/MMR internals. -- Elo/MMR unavailable behavior: - - If the Elo/MMR engine cannot be imported, Elo/MMR endpoints return the existing `status` + `data` envelope with `source: "elo-mmr-paused"`, `available: false`, `unavailable_reason: "elo-mmr-engine-import-unavailable"`, normal source policy metadata, and empty/null Elo data. -- Tests and validation: - - No backend test framework is configured for this scope. - - `scripts/run-integration-tests.ps1` now includes a lightweight backend startup import check and `/health` route resolution check. -- Scope confirmation: - - Backend was up and not restarting in `docker compose ps`. - - `/health` returned a valid JSON payload with `status: "ok"`. - - Frontend returned HTTP `200`. - - No frontend files changed. - - No database migrations, persisted data, or server #03 configuration changed. - - `backend/runtime/` was not created. - - `git diff --name-only` matched the expected scope: `backend/app/payloads.py` and `scripts/run-integration-tests.ps1`. -- Commit and push: - - Commit hash and pushed branch are recorded in the final task execution response. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split follow-up work into a new task if the scope expands beyond startup independence. diff --git a/ai/tasks/done/TASK-110-restore-historical-rcon-first-fallback-policy.md b/ai/tasks/done/TASK-110-restore-historical-rcon-first-fallback-policy.md deleted file mode 100644 index 7994fc7..0000000 --- a/ai/tasks/done/TASK-110-restore-historical-rcon-first-fallback-policy.md +++ /dev/null @@ -1,206 +0,0 @@ ---- -id: TASK-110 -title: Restore historical RCON-first fallback policy -status: pending -type: backend -team: Backend Senior -supporting_teams: ["Arquitecto Python", "PM"] -roadmap_item: foundation -priority: high ---- - -# TASK-110 - Restore historical RCON-first fallback policy - -## Goal - -Correct repository defaults and documentation so historical ingestion is RCON-first, with public-scoreboard used only as a fallback when RCON fails. - -Keep the simplified deployment posture intact: - -- Live data source: `rcon` -- Historical data source: `rcon` -- Historical fallback: `public-scoreboard` when RCON fails -- Elo/MMR: paused and decoupled from backend startup -- Comunidad Hispana #03: removed from default targets -- Comunidad Hispana #01 and #02: active in default RCON targets - -## Context - -HLL Vietnam recently simplified deployment and removed Comunidad Hispana #03 from default operational targets. The intended historical data policy has now been clarified: historical ingestion must not be disabled, and public-scoreboard must not be the normal primary historical source. - -The desired policy is RCON-first historical ingestion with public-scoreboard fallback when RCON fails. Documentation and defaults that currently imply "historical source is public-scoreboard" need to be corrected to "historical source is RCON-first with public-scoreboard fallback." - -This task is implementation-ready for branch: - -- `fix/historical-rcon-first-fallback-policy` - -## Steps - -1. Work on branch `fix/historical-rcon-first-fallback-policy`. -2. Inspect the listed files before changing anything. -3. Restore the historical default policy to RCON-first where appropriate: - - `HLL_BACKEND_HISTORICAL_DATA_SOURCE=rcon` -4. Keep public-scoreboard documented and configured only as fallback, not as the normal primary historical source. -5. Ensure `docker-compose.yml` defaults and backend example env files do not include Comunidad Hispana #03. -6. Ensure Comunidad Hispana #01 and #02 remain in default RCON targets. -7. Keep advanced historical workers under the advanced profile if they are already configured that way. -8. Keep Elo/MMR paused and decoupled from backend startup. -9. Do not delete code, migrations, persisted data, or historical ingestion modules. -10. Update documentation and decisions to correct the historical source wording. -11. Do not add real credentials, secrets, passwords, or local `.env` values. -12. Run the required validation before committing. -13. Move this task file to `ai/tasks/done/` only after validation is complete and the outcome is documented. -14. Stage only intended files, commit, and push the branch to origin. - -## Files to Read First - -- `docker-compose.yml` -- `backend/.env.example` -- `backend/app/config.py` -- `backend/app/data_sources.py` -- `backend/app/historical_runner.py` -- `backend/app/rcon_historical_worker.py`, if present -- `README.md` -- `backend/README.md` -- `docs/decisions.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` - -## Expected Files to Modify - -- `docker-compose.yml` -- `backend/.env.example` -- `backend/app/config.py` -- `README.md` -- `backend/README.md` -- `docs/decisions.md` -- possibly `ai/repo-context.md` -- possibly `ai/architecture-index.md` -- this task file moved from `ai/tasks/pending/` to `ai/tasks/done/` - -If additional files become necessary, explain why in the task outcome and commit message. - -## Expected Files Not to Modify - -- `frontend/**` -- database migrations -- persisted data -- Elo/MMR algorithm implementation files -- unrelated backend modules -- local `.env` - -## Constraints - -- Do not reintroduce Comunidad Hispana #03. -- Do not reactivate Elo/MMR. -- Do not delete historical ingestion code. -- Do not delete database migrations or persisted data. -- Do not modify frontend behavior. -- Do not add real secrets, passwords, tokens, or credentials. -- Keep advanced historical workers under the advanced profile if already configured. -- Keep the default Compose services limited to `backend` and `frontend`. -- Keep the change focused on defaults, source policy, and documentation wording. -- Do not modify unrelated files. -- Do not leave completed work only in local; commit and push after validation. - -## Validation - -Before completing the task, run and document: - -- `git status` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- `docker compose config --services` -- `docker compose config` - -Also confirm and document: - -- default services are still only `backend` and `frontend` -- default historical source resolves to `rcon` -- `HLL_BACKEND_RCON_TARGETS` default includes only `comunidad-hispana-01` and `comunidad-hispana-02` -- `comunidad-hispana-03` is not present in default RCON targets -- documentation says public-scoreboard is fallback, not primary, for historical mode -- no frontend files changed -- no database migrations or persisted data changed -- `backend/runtime/` is not created or committed -- `git diff --name-only` matches the expected scope - -If integration tests are relevant and `scripts/run-integration-tests.ps1` exists, use it. If a configured test cannot be run, document the exact reason in the outcome. - -## Commit And Push Requirements - -- Run all validation before committing. -- Run `git status`. -- Stage only intended files. -- Commit with a clear message, for example: `fix: restore historical rcon-first fallback policy`. -- Push the branch to origin. -- Do not leave completed work only in local. - -## Outcome - -Completed for branch `fix/historical-rcon-first-fallback-policy`. - -Validation performed: - -- `git status --short --branch` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` - - Passed. - - The script reported no product integration tests are configured for this platform-only scope. - - Backend startup import check passed. -- `docker compose config --services` - - Passed and returned only `backend` and `frontend` for the default profile. -- `docker compose config` - - Passed. - - The local machine had Compose environment overrides, so default policy was confirmed again with an empty env file to avoid local values. -- `docker compose --env-file config --services` - - Returned only `backend` and `frontend`. -- `docker compose --env-file config --format json` - - Confirmed `HLL_BACKEND_HISTORICAL_DATA_SOURCE=rcon`. - - Confirmed default `HLL_BACKEND_RCON_TARGETS` includes only `comunidad-hispana-01` and `comunidad-hispana-02`. - - Confirmed `comunidad-hispana-03` is not present in default RCON targets. -- `python -c "from backend.app.config import DEFAULT_HISTORICAL_DATA_SOURCE; print(DEFAULT_HISTORICAL_DATA_SOURCE)"` - - Returned `rcon`. -- `git diff --name-only` - - Matched the expected backend/defaults/docs scope plus `backend/app/historical_runner.py`. -- `Test-Path backend/runtime` - - Returned `False`. - -Final source policy: - -- Historical ingestion defaults to RCON-first. -- `public-scoreboard` is fallback only for historical operations where RCON fails, lacks coverage or lacks parity for the requested competitive operation. -- Live data remains `rcon`. -- Elo/MMR remains paused and decoupled from backend startup. -- Comunidad Hispana #03 remains absent from default targets. -- Comunidad Hispana #01 and #02 remain active in default RCON targets. - -Changed files: - -- `docker-compose.yml` -- `backend/.env.example` -- `backend/app/config.py` -- `backend/app/historical_runner.py` -- `README.md` -- `backend/README.md` -- `docs/decisions.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- this task file moved from `ai/tasks/pending/` to `ai/tasks/done/` - -Notable decision: - -- `backend/app/historical_runner.py` was updated because its default advanced historical scope still included `comunidad-hispana-03`. Leaving that default in code would contradict the task's default-target policy and the updated documentation, even though the worker remains under the advanced Compose profile. - -Scope confirmations: - -- No frontend files changed. -- No database migrations or persisted data changed. -- No real credentials were added; repository defaults continue to use placeholder RCON passwords. -- `backend/runtime/` was not created or committed. -- No follow-up task is needed for this scope. -- The branch was pushed to origin after validation and commit. - -## Change Budget - -- Prefer fewer than 5 modified files when feasible. -- Prefer changes under 200 lines when feasible. -- Split follow-up work into a new task if the scope grows beyond defaults, documentation, and source-policy correction. diff --git a/ai/tasks/done/TASK-111-hide-paused-elo-mvp-ui.md b/ai/tasks/done/TASK-111-hide-paused-elo-mvp-ui.md deleted file mode 100644 index f8693be..0000000 --- a/ai/tasks/done/TASK-111-hide-paused-elo-mvp-ui.md +++ /dev/null @@ -1,224 +0,0 @@ ---- -id: TASK-111 -title: Hide paused Elo and MVP ranking UI -status: pending -type: frontend -team: Frontend Senior -supporting_teams: [PM] -roadmap_item: historical-ui -priority: high ---- - -# TASK-111 - Hide paused Elo and MVP ranking UI - -## Goal - -Hide paused or experimental Elo/MMR and advanced MVP ranking blocks from the public historical page while preserving stable historical content. - -## Context - -HLL Vietnam now uses this operational backend policy: - -- live data source: RCON -- historical data source: RCON -- public-scoreboard fallback only when RCON historical data fails -- Comunidad Hispana #03 removed from default targets -- Elo/MMR paused and decoupled from backend startup - -Manual visual review of `http://localhost:8080/historico.html` shows that the public historical page still displays paused or experimental ranking blocks: - -- MVP mensual V1 -- MVP mensual V2 -- Comparativa V1 vs V2 -- Elo/MMR mensual / persistent rating - -This contradicts the current product decision. This task is only a public UI/product-scope change. Preserve backend endpoints, historical ingestion, Elo/MMR implementation code, persisted data, snapshots, migrations and schemas. - -Use branch: - -- `chore/hide-paused-elo-mvp-ui` - -## Steps - -1. Inspect the listed files first. -2. Hide or remove from the public historical page the paused/experimental UI blocks: - - MVP mensual V1 - - MVP mensual V2 - - Comparativa V1 vs V2 - - Elo/MMR mensual / persistent rating -3. Stop calling the related frontend fetch/render flows for those hidden sections in `historico.js`. -4. Keep normal historical content visible: - - summary/resumen - - weekly/monthly basic historical rankings - - recent matches - - any other non-Elo, non-MVP experimental historical content already considered stable -5. Remove `comunidad-hispana-03` from the frontend historical server selector and JavaScript server list if still present. -6. Preserve backend endpoints and code. Do not delete backend Elo/MMR code, historical ingestion code, endpoints, persisted data, snapshots, migrations or schemas. -7. Prefer a minimal feature-flag-like constant in frontend JavaScript if useful, for example: - `const SHOW_PAUSED_ADVANCED_RANKINGS = false;` - Do not leave visible empty panels. -8. Update text/docs only if necessary to clarify that advanced MVP/Elo ranking UI is paused. -9. Do not add new frameworks or dependencies. -10. Validate the result. -11. Move this task file to `ai/tasks/done/` after validation is complete. -12. Commit and push the completed work to origin. Do not leave completed work only in local. - -## Files to Read First - -- `frontend/historico.html` -- `frontend/assets/js/historico.js` -- `frontend/assets/css/historico.css` -- `backend/app/payloads.py` -- `README.md` -- `docs/decisions.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` - -Rules: - -- Read these files before implementation. -- Keep the implementation scoped to public historical UI behavior. -- Do not change backend historical policy. - -## Expected Files to Modify - -- `frontend/historico.html` -- `frontend/assets/js/historico.js` -- possibly `frontend/assets/css/historico.css` -- possibly `docs/decisions.md` -- possibly `ai/repo-context.md` -- possibly `ai/architecture-index.md` -- `ai/tasks/done/TASK-111-hide-paused-elo-mvp-ui.md` - -Rules: - -- Prefer modifying only these files. -- If additional files become necessary, explain why in the task outcome and commit message. -- The task file should be moved from `ai/tasks/pending/` to `ai/tasks/done/` only after validation is complete. - -## Expected Files Not to Modify - -- database migrations -- persisted data -- backend Elo/MMR implementation files -- historical ingestion implementation files -- Docker/Compose configuration -- local `.env` -- unrelated frontend pages - -## Constraints - -- Keep the change minimal and verifiable. -- Preserve HLL Vietnam project identity: military, Vietnam, tactical, sober. -- Do not implement backend functionality. -- Do not delete backend Elo/MMR code. -- Do not delete historical ingestion code. -- Do not delete endpoints. -- Do not delete persisted data, snapshots, migrations or schemas. -- Do not change backend historical policy. -- Do not reintroduce Comunidad Hispana #03. -- Do not remove normal historical sections such as summary, basic rankings and recent matches. -- Do not introduce unnecessary frameworks or dependencies. -- Do not overwrite repository-specific context with generic platform template text. -- Confirm `backend/runtime/` is not created or committed. - -## Validation - -Before completing the task: - -1. Run `git status`. -2. Run `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1`. -3. Run `docker compose down`. -4. Run `docker compose up -d --build`. -5. Run `docker compose ps`. -6. Run `Invoke-WebRequest http://localhost:8000/health | Select-Object -ExpandProperty Content`. -7. Run `Invoke-WebRequest http://localhost:8080 | Select-Object -ExpandProperty StatusCode`. -8. Manually verify `http://localhost:8080/historico.html`: - - no visible MVP mensual V1 block - - no visible MVP mensual V2 block - - no visible Comparativa V1 vs V2 block - - no visible Elo/MMR mensual block - - no visible Comunidad Hispana #03 selector - - summary/basic rankings/recent matches still render -9. Confirm no backend Elo/MMR code was deleted. -10. Confirm no migrations or persisted data changed. -11. Confirm `backend/runtime/` is not created or committed. -12. Review `git diff --name-only` and confirm changed files match the expected scope. - -## Commit And Push Requirements - -1. Run validation before committing. -2. Run `git status`. -3. Stage only intended files. -4. Commit with a clear message, for example: - `chore: hide paused elo and mvp UI` -5. Push the branch to origin. -6. Do not leave completed work only in local. - -## Outcome - -Completed. - -Validation performed: - -- Ran `git status`. -- Ran `node --check frontend/assets/js/historico.js`. -- Ran `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1`. - - Result: platform validation passed; no product integration tests are configured for this platform-only scope. -- Ran `docker compose down`. -- Ran `docker compose up -d --build`. -- Ran `docker compose ps`. - - Result: `backend` and `frontend` are running. -- Ran `Invoke-WebRequest http://localhost:8000/health | Select-Object -ExpandProperty Content`. - - Result: backend returned `status: ok`, `live_data_source: rcon`, and `historical_data_source: rcon`. -- Ran `Invoke-WebRequest http://localhost:8080 | Select-Object -ExpandProperty StatusCode`. - - Result: `200`. -- Verified served `http://localhost:8080/historico.html` content: - - no visible MVP mensual V1 block - - no visible MVP mensual V2 block - - no visible Comparativa V1 vs V2 block - - no visible Elo/MMR mensual block - - no visible Comunidad Hispana #03 selector - - summary, basic rankings and recent matches markup remains present -- Verified served `frontend/assets/js/historico.js` no longer includes the monthly MVP V1, monthly MVP V2 or Elo/MMR frontend fetch wrappers/endpoints. -- Confirmed no backend Elo/MMR code was deleted. -- Confirmed no migrations or persisted data changed. -- Confirmed `backend/runtime/` was not created or committed. -- Reviewed `git diff --name-only`; changed files are limited to public historical frontend files plus this task file move. - -Browser validation note: - -- The Browser plugin is available, but its required Node REPL execution tool was not exposed in this session after tool discovery. -- `npx playwright --version` could not be used as a fallback because npm failed with `UNABLE_TO_VERIFY_LEAF_SIGNATURE`. -- The manual visual checklist was therefore validated through the running Docker frontend using served HTML and JavaScript HTTP assertions. - -Notable decisions: - -- Removed the paused/experimental public UI panels instead of hiding empty shells. -- Disabled the related frontend fetch/render flows by removing their active cache/fetch wiring from `historico.js`. -- Preserved backend endpoints, Elo/MMR implementation code, migrations, persisted data and historical ingestion code. -- Removed `comunidad-hispana-03` from the public historical selector and JavaScript historical server list. - -Follow-up: - -- No follow-up task is required for this scoped UI pause. - -Commit and push: - -- Pending at task move time; final commit hash and push result will be reported by the worker after commit/push. - -The final worker report must explicitly state: - -- which paused/experimental UI blocks were hidden -- whether any related frontend fetch/render flows were disabled -- whether `comunidad-hispana-03` was present and removed from the public historical selector/list -- that normal historical content still renders -- that backend Elo/MMR code, endpoints, migrations and persisted data were preserved -- that `backend/runtime/` was not created or committed -- the commit hash and push result - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-112-polish-historical-copy-and-match-links.md b/ai/tasks/done/TASK-112-polish-historical-copy-and-match-links.md deleted file mode 100644 index d709d3f..0000000 --- a/ai/tasks/done/TASK-112-polish-historical-copy-and-match-links.md +++ /dev/null @@ -1,209 +0,0 @@ ---- -id: TASK-112 -title: Polish historical copy and add recent match links -status: pending -type: frontend -team: Frontend Senior -supporting_teams: [Backend Senior, PM] -roadmap_item: historical-ui -priority: high ---- - -# TASK-112 - Polish historical copy and add recent match links - -## Goal - -Polish the public historical page copy so implementation words stay hidden from users, and add source links to recent match cards when a safe persisted match URL is available. - -## Context - -HLL Vietnam has hidden the paused MVP/Elo UI from the public historical page. Manual visual review found three remaining issues: - -- The ranking note includes this awkward fallback sentence: "Se muestra el ultimo periodo cerrado porque el actual todavia solo suma 0 cierres." -- Public UI copy still exposes the technical word "snapshot". -- Recent match cards show match IDs but do not link to the original match detail page. - -Current product decisions remain unchanged: - -- Keep historical ingestion active. -- Keep historical policy RCON-first, with public-scoreboard fallback only where RCON fails, lacks coverage or lacks parity for a specific historical operation. -- Keep Elo/MMR and advanced MVP UI paused. -- Hide technical implementation wording from public users. -- Add match links only when a persisted or safely derivable source URL is available. - -Use branch: - -- `chore/polish-historical-copy-and-match-links` - -## Steps - -1. Work on branch `chore/polish-historical-copy-and-match-links`. -2. Inspect the listed files before changing anything. -3. Remove the public sentence: - "Se muestra el ultimo periodo cerrado porque el actual todavia solo suma 0 cierres." - from the ranking note/copy. -4. Keep the ranking note useful if needed, but do not expose the awkward fallback explanation. -5. Remove the word "snapshot" from public UI copy. -6. Keep internal function names unchanged if renaming them would increase risk. -7. Use Spanish, product-friendly public alternatives where needed, such as: - - "datos precalculados" - - "datos actualizados" - - "registro" - - "ultima actualizacion" - - "datos disponibles" -8. Avoid "snapshot" in visible text, loading states, errors and metadata. -9. Add match links for the recent matches section ("Ultimas partidas registradas") when a safe URL exists: - - Backend recent matches payload should expose a safe URL field such as `match_url` or `source_url`. - - Prefer using the persisted `raw_payload_ref` from `historical_matches` if available. - - If `raw_payload_ref` is unavailable, derive the URL only if the server source/base URL and external match id are available and already trusted by existing historical server configuration. - - Do not expose credentials or internal filesystem paths. - - Frontend recent match cards should render a visible link/button such as "Ver partida" when the URL exists. - - The link must open in a new tab with `target="_blank"` and `rel="noopener noreferrer"`. - - If no URL exists, keep the current card layout without a broken link. -10. Preserve existing normal historical UI: - - summary - - basic historical rankings - - recent matches - - server selector with only Todos, Comunidad Hispana #01, Comunidad Hispana #02 -11. Keep these paused/hidden: - - MVP mensual V1 - - MVP mensual V2 - - Comparativa V1 vs V2 - - Elo/MMR mensual -12. Do not change the historical ingestion policy or reintroduce Comunidad Hispana #03. -13. Update `docs/decisions.md` only if the implementation changes a documented contract or public historical UI assumption. -14. Validate the result. -15. Move this task file to `ai/tasks/done/` after validation is complete and the outcome is documented. -16. Commit and push the completed work to origin. Do not leave completed work only in local. - -## Files to Read First - -- `frontend/historico.html` -- `frontend/assets/js/historico.js` -- `frontend/assets/css/historico.css` -- `backend/app/historical_storage.py` -- `backend/app/historical_snapshots.py` -- `backend/app/payloads.py` -- `backend/app/routes.py` -- `backend/tests/` if present -- `docs/decisions.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` - -Rules: - -- Read these files before implementation. -- Keep the implementation scoped to public historical page copy, recent match payload shape and recent match card rendering. -- Do not change backend historical ingestion policy. - -## Expected Files to Modify - -- `frontend/assets/js/historico.js` -- possibly `frontend/assets/css/historico.css` -- possibly `backend/app/historical_storage.py` -- possibly `backend/app/historical_snapshots.py` -- possibly `backend/app/payloads.py` -- possibly backend tests if present -- possibly `docs/decisions.md` -- `ai/tasks/done/TASK-112-polish-historical-copy-and-match-links.md` - -Rules: - -- Prefer modifying only these files. -- If additional files become necessary, explain why in the task outcome and commit message. -- The task file should be moved from `ai/tasks/pending/` to `ai/tasks/done/` only after validation is complete. - -## Expected Files Not to Modify - -- `frontend/index.html` -- Docker/Compose configuration -- local `.env` -- database migrations -- persisted data -- Elo/MMR backend implementation files -- historical ingestion policy/config -- unrelated backend modules -- unrelated frontend pages - -## Constraints - -- Keep the change minimal and verifiable. -- Preserve HLL Vietnam project identity: military, Vietnam, tactical, sober. -- Do not reintroduce paused MVP/Elo UI. -- Do not reintroduce Comunidad Hispana #03. -- Do not change historical ingestion policy. -- Do not delete backend code, migrations, snapshots/data or endpoints. -- Do not add real credentials, secrets, passwords or tokens. -- Do not expose credentials or internal filesystem paths through match URLs. -- Do not introduce unnecessary frameworks or dependencies. -- Keep frontend changes compatible with direct browser opening where applicable. -- Confirm `backend/runtime/` is not created or committed. - -## Validation - -Before completing the task: - -1. Run `git status`. -2. Run `node --check frontend/assets/js/historico.js`. -3. Run `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1`. -4. Run `docker compose down`. -5. Run `docker compose up -d --build`. -6. Run `docker compose ps`. -7. Run `Invoke-WebRequest http://localhost:8000/health | Select-Object -ExpandProperty Content`. -8. Run `Invoke-WebRequest http://localhost:8080 | Select-Object -ExpandProperty StatusCode`. -9. Verify served `historico.html`/JS output or manual browser: - - no visible word "snapshot" - - no visible sentence "Se muestra el ultimo periodo cerrado porque el actual todavia solo suma 0 cierres." - - recent match cards still render - - when a match URL exists, a "Ver partida" link appears - - server #03 is not visible - - paused MVP/Elo blocks remain hidden -10. Confirm no database migrations or persisted data changed. -11. Confirm `backend/runtime/` is not created or committed. -12. Review `git diff --name-only` and confirm changed files match the expected scope. - -If a configured validation command cannot be run, document the exact reason in the outcome. - -## Commit And Push Requirements - -1. Run validation before committing. -2. Run `git status`. -3. Stage only intended files. -4. Commit with a clear message, for example: - `chore: polish historical copy and match links` -5. Push the branch to origin. -6. Do not leave completed work only in local. - -## Outcome - -Completed. - -- Validation performed: - - `git status --short` - - `node --check frontend/assets/js/historico.js` - - `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` - - `docker compose down` - - `docker compose up -d --build` - - `docker compose ps` - - `Invoke-WebRequest http://localhost:8000/health | Select-Object -ExpandProperty Content` - - `Invoke-WebRequest http://localhost:8080 | Select-Object -ExpandProperty StatusCode` - - served `historico.html` and `historico.js` copy checks for removed public fallback/snapshot wording - - focused temporary-storage check confirming `match_url` is exposed from a safe persisted match reference -- Public copy changes made: - - Removed the fallback sentence about showing the previous closed period because the current one had 0 closures. - - Replaced visible `snapshot` wording in loading states, errors, metadata and empty copy with product-facing Spanish alternatives such as `datos`, `datos precalculados`, `registro` and `resumen`. - - Corrected the all-servers summary note copy. -- Backend payload field used for match links: `match_url`. -- URL source: persisted `historical_matches.raw_payload_ref`, accepted only when it is an HTTP(S) `/games/` URL on the configured historical server `scoreboard_base_url`. -- No credentials or internal filesystem paths are exposed through `match_url`; unsafe or off-origin values resolve to no link. -- Normal historical UI still renders through the served frontend and backend health checks. -- Comunidad Hispana #03 remains absent from the public selector, and paused MVP/Elo blocks were not reintroduced to `historico.html`. -- No migrations, persisted data, or `backend/runtime/` were changed or committed. -- Browser plugin note: the Browser plugin's Node execution tool was not exposed in this session after discovery, so rendered-page acceptance was verified through served frontend/API checks instead. -- Commit hash and push result: pending commit/push step. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into a follow-up task if the scope grows beyond public copy, recent match URL payloads and recent match card rendering. diff --git a/ai/tasks/done/TASK-113-add-internal-match-detail-links.md b/ai/tasks/done/TASK-113-add-internal-match-detail-links.md deleted file mode 100644 index e97a263..0000000 --- a/ai/tasks/done/TASK-113-add-internal-match-detail-links.md +++ /dev/null @@ -1,212 +0,0 @@ ---- -id: TASK-113 -title: Add internal match detail links -status: pending -type: frontend -team: Frontend Senior -supporting_teams: - - Backend Senior -roadmap_item: historical -priority: high ---- - -# TASK-113 - Add internal match detail links - -## Goal - -Add implementation support so every card in "Ultimas partidas registradas" links to available match data without fabricating unsafe external scoreboard URLs for synthetic RCON competitive-window match IDs. - -## Context - -The historical page now renders recent matches, but the latest backend response for `/api/historical/snapshots/recent-matches?server=all-servers&limit=5` can return `selected_source: "rcon"` and items with `capture_basis: "rcon-competitive-window"` and no `match_url`. - -The previous implementation correctly renders external "Ver partida" links only when a safe source URL exists. However, current RCON competitive-window matches can use synthetic IDs such as `31:2026-04-13T13:59:26.174488Z`, which are not direct scoreboard `/games/{id}` URLs. - -Product decision: - -- Keep using a safe external `match_url` when one exists. -- For matches without a safe external URL, provide an internal match detail page/link. -- Do not invent external scoreboard URLs for synthetic RCON match IDs. -- Preserve HLL Vietnam's military, Vietnam, tactical and sober visual identity. -- Do not reintroduce paused MVP/Elo UI. -- Do not reintroduce Comunidad Hispana #03. - -## Steps - -1. Move this task from `ai/tasks/pending/` to `ai/tasks/in-progress/`. -2. Inspect the listed files first. -3. Confirm the recent matches response shape for `/api/historical/snapshots/recent-matches?server=all-servers&limit=5`, including RCON competitive-window items without `match_url`. -4. Keep the existing safe external `match_url` behavior: - - If a recent match item has a safe external `match_url`, render "Ver partida" or "Abrir en scoreboard". - - Keep `target="_blank"` and `rel="noopener noreferrer"`. -5. Add internal match detail links for recent matches without an external URL: - - Render a visible link/button, for example "Ver detalles". - - Point it to an internal frontend route/page, for example `historico-partida.html?server={serverSlug}&match={encodedMatchId}`. - - URL-encode the match ID. -6. Add a simple internal match detail frontend page: - - Suggested file: `frontend/historico-partida.html`. - - Preserve the current visual identity. - - Read `server` and `match` from the query string. - - Call a backend endpoint to get available match details. - - Show a graceful unavailable or partial-data state if only limited RCON data exists. -7. Add or reuse a backend endpoint for match details: - - Prefer `/api/historical/matches/detail?server={serverSlug}&match={matchId}`. - - Return available data for both persisted scoreboard matches and RCON competitive-window matches when available. - - At minimum return `server`, `match_id`, `map`, `started_at`, `ended_at` or `closed_at`, `duration_seconds` if available, `player_count` or `peak_players` if available, `result` or `score` if available, `capture_basis` or `capabilities` if available, and external `match_url` if a safe one exists. - - Do not fabricate external scoreboard URLs for synthetic RCON IDs. -8. Preserve the existing historical page sections and selector behavior: - - summary - - basic rankings - - recent matches - - server selector with only Todos, Comunidad Hispana #01 and Comunidad Hispana #02 -9. Keep these blocks paused or hidden: - - MVP mensual V1 - - MVP mensual V2 - - Comparativa V1 vs V2 - - Elo/MMR mensual -10. Validate the result with all checks listed below. -11. Move this task to `ai/tasks/done/` only after validation is complete and document the outcome in this file. -12. Commit and push the completed implementation branch. - -## Files to Read First - -- `ai/architecture-index.md` -- `ai/repo-context.md` -- `ai/orchestrator/frontend-senior.md` -- `ai/orchestrator/backend-senior.md` -- `frontend/historico.html` -- `frontend/assets/js/historico.js` -- `frontend/assets/css/historico.css` -- `backend/app/routes.py` -- `backend/app/payloads.py` -- `backend/app/historical_storage.py` -- `backend/app/historical_snapshots.py` -- any RCON competitive/recent match read model modules -- `scripts/run-integration-tests.ps1` -- `docs/decisions.md` - -## Expected Files to Modify - -- `frontend/historico.html` -- `frontend/assets/js/historico.js` -- `frontend/assets/css/historico.css` -- possibly new `frontend/historico-partida.html` -- possibly new `frontend/assets/js/historico-partida.js` -- possibly `backend/app/routes.py` -- possibly `backend/app/payloads.py` -- possibly `backend/app/historical_storage.py` -- possibly historical snapshot/read model modules -- possibly tests under `backend/tests/` -- this task file, moved to `ai/tasks/done/` - -If additional files become necessary, explain why in the task outcome and commit message. - -## Expected Files Not to Modify - -- Docker/Compose config -- local `.env` -- database migrations unless absolutely required and justified -- persisted data -- Elo/MMR backend implementation files -- unrelated frontend pages - -## Constraints - -- Keep the change focused on internal detail links and match detail data. -- Do not delete backend code, migrations, persisted data, snapshots or endpoints. -- Do not change historical ingestion policy. -- Do not reintroduce Comunidad Hispana #03. -- Do not reintroduce MVP/Elo UI. -- Do not add real credentials. -- Do not introduce unnecessary frontend frameworks or dependencies. -- Preserve direct browser compatibility where applicable. -- Preserve HLL Vietnam branding and product identity. -- Do not use public "snapshot" wording in user-facing copy. -- Confirm `backend/runtime/` is not created or committed. - -## Validation - -Before completing the task, run: - -- `git status` -- `node --check frontend/assets/js/historico.js` -- If a new frontend JS file is added, run `node --check` on it too. -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- `docker compose down` -- `docker compose up -d --build` -- `docker compose ps` -- `Invoke-WebRequest http://localhost:8000/health | Select-Object -ExpandProperty Content` -- `Invoke-WebRequest http://localhost:8080 | Select-Object -ExpandProperty StatusCode` -- `Invoke-WebRequest "http://localhost:8000/api/historical/snapshots/recent-matches?server=all-servers&limit=5" | Select-Object -ExpandProperty Content` -- Validate the new match detail endpoint for at least one recent match ID. - -Manual or served HTML verification: - -- Recent match cards show either external "Ver partida" or internal "Ver detalles". -- The internal detail page opens and displays available data. -- No server #03 appears. -- No paused MVP/Elo blocks appear. -- No public "snapshot" wording appears. -- No migrations or persisted data changed unless explicitly justified. -- `backend/runtime/` is not created or committed. - -Before committing, also review: - -- `git diff --name-only` -- changed files match the expected scope - -## Commit And Push Requirements - -- Run validation before committing. -- Run `git status`. -- Stage only intended files. -- Commit with a clear message, for example `feat: add internal match detail links`. -- Push the branch to origin. -- Do not leave completed work only in local. - -## Outcome - -Document the validation performed, notable implementation decisions, and any follow-up task that should be created instead of expanding this task. - -Completed. - -Validation performed: - -- Confirmed `/api/historical/snapshots/recent-matches?server=all-servers&limit=5` returns `selected_source: "rcon"` with RCON competitive-window items such as `31:2026-04-13T13:59:26.174488Z`, `capture_basis: "rcon-competitive-window"` and no `match_url`. -- Ran `node --check frontend/assets/js/historico.js`. -- Ran `node --check frontend/assets/js/historico-partida.js`. -- Ran Python syntax compilation for the touched backend modules. -- Ran `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1`; the script reports no product integration tests are configured for this platform-only scope and passed the backend startup import check. -- Ran `docker compose down`. -- Ran `docker compose up -d --build`. -- Ran `docker compose ps`; backend and frontend were up on ports 8000 and 8080. -- Verified `http://localhost:8000/health`. -- Verified `http://localhost:8080`. -- Verified `http://localhost:8000/api/historical/snapshots/recent-matches?server=all-servers&limit=5`. -- Verified `http://localhost:8000/api/historical/matches/detail?server=comunidad-hispana-01&match=31%3A2026-04-13T13%3A59%3A26.174488Z` returns the RCON detail internally with `match_url: null`. -- Used headless Chrome against `http://localhost:8080/historico.html`; recent RCON cards render `Ver detalles`. -- Used headless Chrome against `http://localhost:8080/historico-partida.html?...`; the internal detail page renders available RCON data and the `Ventana competitiva RCON` capture basis. -- Confirmed no `backend/runtime/` path exists. - -Implementation decisions: - -- Preserved the existing safe external `match_url` behavior and added `Ver detalles` only when no safe external URL exists. -- Added `frontend/historico-partida.html` and `frontend/assets/js/historico-partida.js` as a direct-browser-compatible internal detail page. -- Added `/api/historical/matches/detail?server={serverSlug}&match={matchId}`. -- Added persisted public-scoreboard detail lookup and exact RCON competitive-window detail lookup. -- Kept synthetic RCON match IDs internal and did not fabricate external scoreboard URLs. -- Did not reintroduce paused MVP/Elo UI or Comunidad Hispana #03 in the frontend selector. - -Scope note: - -- The task exceeded the preferred 5-file/200-line budget because it required both a new internal frontend page and a backend detail endpoint/read path for two historical sources. No migrations, persisted data, Docker config, `.env`, Elo/MMR implementation files or unrelated frontend pages were changed. - -Follow-up: - -- No follow-up task is required from this implementation. A future task could add richer player-level detail if the RCON historical model later exposes player stats. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-114-centralize-scoreboard-origin-catalog.md b/ai/tasks/done/TASK-114-centralize-scoreboard-origin-catalog.md deleted file mode 100644 index bdc7c40..0000000 --- a/ai/tasks/done/TASK-114-centralize-scoreboard-origin-catalog.md +++ /dev/null @@ -1,151 +0,0 @@ ---- -id: TASK-114 -title: Centralize scoreboard origin catalog -status: done -type: backend -team: Backend Senior -supporting_teams: - - Arquitecto Python - - PM -roadmap_item: historical -priority: high ---- - -# TASK-114 - Centralize scoreboard origin catalog - -## Goal - -Create a single safe source of truth for trusted public scoreboard origins per active server. - -## Context - -Recent match cards can now fall back to internal details for RCON synthetic matches. The next step is to make trusted external scoreboard origin handling explicit and reusable so future link resolution remains safe. - -Required origin behavior: - -- Comunidad Hispana #01 must use the configured base scoreboard origin for #01, without a custom port. -- Comunidad Hispana #02 must use the same scoreboard host with port `5443`. -- Comunidad Hispana #03 must not be included in public/default origin flows. - -Use branch: - -- `plan/scoreboard-match-linking-tasks` - -## Steps - -1. Work from this task only after moving it to `ai/tasks/in-progress/`. -2. Inspect the listed files before changing anything. -3. Inspect historical storage, RCON historical read/storage modules, config, env example, Docker Compose and relevant docs. -4. Centralize trusted scoreboard origins in a backend helper/config location. -5. Ensure URL validation accepts the trusted origins for #01 and #02, including the #02 `5443` port. -6. Ensure Comunidad Hispana #03 is not part of the trusted scoreboard origin catalog. -7. Keep existing safe `raw_payload_ref` behavior intact. -8. Update or add a concise docs decision if this creates or clarifies a backend contract. -9. Validate the result. -10. Move this task to `ai/tasks/done/` only after validation is complete and document the outcome in this file. -11. Commit and push the completed implementation branch. - -## Files to Read First - -- `ai/architecture-index.md` -- `ai/repo-context.md` -- `ai/orchestrator/backend-senior.md` -- `backend/app/config.py` -- `backend/app/historical_storage.py` -- `backend/app/rcon_historical_read_model.py` -- `backend/app/rcon_historical_storage.py` -- `backend/app/payloads.py` -- `backend/app/providers/public_scoreboard_provider.py` -- `backend/.env.example` -- `docker-compose.yml` -- `docs/decisions.md` -- `scripts/run-integration-tests.ps1` - -## Expected Files to Modify - -- likely one backend helper/config module for trusted scoreboard origins -- possibly `backend/app/config.py` -- possibly `backend/app/payloads.py` -- possibly `backend/app/historical_storage.py` -- possibly tests under `backend/tests/` -- possibly `docs/decisions.md` -- this task file, moved to `ai/tasks/done/` - -If additional files become necessary, explain why in the task outcome and commit message. - -## Expected Files Not to Modify - -- `frontend/**` -- local `.env` -- database migrations -- persisted data -- Elo/MMR implementation files -- unrelated backend modules - -## Constraints - -- Do not reintroduce Comunidad Hispana #03. -- Do not reintroduce paused MVP/Elo UI. -- Do not change historical ingestion policy. -- Do not add real credentials. -- Do not modify local `.env`. -- Do not delete persisted data, migrations, backend endpoints or historical ingestion code. -- Do not use the public word "snapshot" in user-facing UI. -- Keep the change focused on trusted scoreboard origin configuration and validation. - -## Validation - -Before completing the task, run and document: - -- `git status` -- Python compile checks for touched backend modules, for example `python -m compileall backend/app` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- focused check confirming #01 and #02 trusted origins exist -- focused check confirming Comunidad Hispana #03 is absent from trusted public/default origins -- focused check confirming #02 preserves port `5443` -- focused check confirming existing safe `raw_payload_ref` behavior still works -- `git diff --name-only` and confirmation that changed files match the expected scope - -If a configured validation command cannot be run, document the exact reason in the outcome. - -## Commit And Push Requirements - -- Run validation before committing. -- Run `git status`. -- Stage only intended files. -- Commit with message: `chore: centralize scoreboard origin catalog` -- Push the branch to origin. -- Do not leave completed work only in local. - -## Outcome - -Completed. - -Implementation decisions: - -- Added `backend/app/scoreboard_origins.py` as the single trusted public scoreboard origin catalog for active default servers. -- Kept only `comunidad-hispana-01` and `comunidad-hispana-02` in the trusted catalog; #02 preserves port `5443`. -- Derived `DEFAULT_HISTORICAL_SERVERS` from the trusted catalog so new default seeds do not reintroduce `comunidad-hispana-03`. -- Routed safe match URL resolution through the trusted catalog instead of trusting each persisted `scoreboard_base_url` row. Existing persisted data is not deleted. -- Updated `docs/decisions.md` with the backend contract for trusted active public scoreboard origins. - -Validation performed: - -- `git status --short --branch` confirmed branch `plan/scoreboard-match-linking-tasks`. -- `python -m compileall backend/app` passed. -- Focused Python check confirmed #01 and #02 trusted origins exist. -- Focused Python check confirmed `comunidad-hispana-03` is absent from trusted public/default origins. -- Focused Python check confirmed #02 preserves port `5443`. -- Focused Python check confirmed safe `raw_payload_ref` behavior still accepts trusted `/games/` URLs and rejects #03, non-`/games/` paths and credentialed URLs. -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` passed. -- `git diff --name-only` / `git status --short` reviewed. Changed files match the expected scope plus the new backend helper module and this task file. - -Follow-up: - -- Continue with TASK-115 for persisted scoreboard link resolution behavior instead of expanding this task. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split follow-up work into a new task if the scope grows. diff --git a/ai/tasks/done/TASK-115-resolve-persisted-scoreboard-links.md b/ai/tasks/done/TASK-115-resolve-persisted-scoreboard-links.md deleted file mode 100644 index 19b972b..0000000 --- a/ai/tasks/done/TASK-115-resolve-persisted-scoreboard-links.md +++ /dev/null @@ -1,141 +0,0 @@ ---- -id: TASK-115 -title: Resolve persisted scoreboard links -status: done -type: backend -team: Backend Senior -supporting_teams: - - Frontend Senior - - PM -roadmap_item: historical -priority: high ---- - -# TASK-115 - Resolve persisted scoreboard links - -## Goal - -Make sure all existing persisted public-scoreboard matches expose a safe `match_url` consistently. - -## Context - -The UI should prefer safe external scoreboard links when the match is already a persisted public-scoreboard match. This task is limited to persisted scoreboard data and must not use RCON synthetic IDs to construct external URLs. - -Use branch: - -- `plan/scoreboard-match-linking-tasks` - -## Steps - -1. Work from this task only after moving it to `ai/tasks/in-progress/`. -2. Inspect the listed files before changing anything. -3. Inspect historical storage detail and recent match payloads. -4. Ensure recent match list responses return `match_url` when `raw_payload_ref` exists and passes trusted origin validation. -5. Ensure the match detail endpoint returns `match_url` for persisted scoreboard matches when `raw_payload_ref` exists and passes trusted origin validation. -6. Do not use RCON synthetic IDs for this task. -7. Do not fabricate external URLs when no trusted persisted URL exists. -8. Add tests or focused checks if feasible in the current repo. -9. Validate the result. -10. Move this task to `ai/tasks/done/` only after validation is complete and document the outcome in this file. -11. Commit and push the completed implementation branch. - -## Files to Read First - -- `ai/architecture-index.md` -- `ai/repo-context.md` -- `ai/orchestrator/backend-senior.md` -- `backend/app/historical_storage.py` -- `backend/app/historical_snapshots.py` -- `backend/app/payloads.py` -- `backend/app/routes.py` -- backend trusted scoreboard origin helper/config from TASK-114 -- `backend/tests/` if present -- `scripts/run-integration-tests.ps1` - -## Expected Files to Modify - -- `backend/app/historical_storage.py` -- possibly `backend/app/historical_snapshots.py` -- possibly `backend/app/payloads.py` -- possibly `backend/app/routes.py` -- possibly backend tests -- this task file, moved to `ai/tasks/done/` - -If additional files become necessary, explain why in the task outcome and commit message. - -## Expected Files Not to Modify - -- `frontend/**` -- local `.env` -- database migrations -- persisted data -- Docker/Compose config -- Elo/MMR implementation files -- historical ingestion policy/config - -## Constraints - -- Do not reintroduce Comunidad Hispana #03. -- Do not reintroduce paused MVP/Elo UI. -- Do not change historical ingestion policy. -- Do not add real credentials. -- Do not modify local `.env`. -- Do not delete persisted data, migrations, backend endpoints or historical ingestion code. -- Do not use the public word "snapshot" in user-facing UI. -- Keep the change limited to safe `match_url` exposure for persisted public-scoreboard matches. - -## Validation - -Before completing the task, run and document: - -- `git status` -- Python compile checks for touched backend modules -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- recent matches endpoint check confirming persisted scoreboard matches expose safe `match_url` when available -- match detail endpoint check for a persisted scoreboard match if fixture/data exists -- focused check confirming unsafe or untrusted URLs are not accepted -- focused check confirming RCON synthetic IDs are not used to construct external URLs -- `git diff --name-only` and confirmation that changed files match the expected scope - -If a configured validation command cannot be run, document the exact reason in the outcome. - -## Commit And Push Requirements - -- Run validation before committing. -- Run `git status`. -- Stage only intended files. -- Commit with message: `fix: resolve persisted scoreboard match links` -- Push the branch to origin. -- Do not leave completed work only in local. - -## Outcome - -Completed. - -Implementation decisions: - -- No additional production-code change was needed in this task because TASK-114 already routed recent-match and detail `match_url` resolution through the trusted scoreboard origin catalog. -- Added `backend/tests/test_scoreboard_match_links.py` as a focused stdlib `unittest` regression check for persisted public-scoreboard match links. -- The test verifies recent-match and match-detail payloads expose safe persisted URLs, rejects an untrusted #03 origin, and confirms RCON synthetic match IDs are not used to fabricate external scoreboard URLs. - -Validation performed: - -- `git status --short --branch` confirmed branch `plan/scoreboard-match-linking-tasks`. -- `$env:PYTHONPATH='backend'; python -m unittest backend.tests.test_scoreboard_match_links` passed. -- `python -m compileall backend/app backend/tests` passed. -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` passed. -- Recent matches endpoint behavior was covered by the regression test through `list_recent_historical_matches`. -- Match detail endpoint behavior was covered by the regression test through `get_historical_match_detail`. -- Unsafe/untrusted URL rejection was covered with a persisted #03-origin `raw_payload_ref`. -- RCON synthetic ID non-fabrication was covered with `get_rcon_historical_match_detail`. -- `git diff --name-only` and `git status --short` were reviewed. Changed files match the expected scope: backend test coverage plus this task file. - -Note: - -- The focused unittest emits existing SQLite `ResourceWarning` messages from the repository connection helper pattern during forced cleanup, but all assertions pass and no temp database remains locked. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split follow-up work into a new task if the scope grows. diff --git a/ai/tasks/done/TASK-116-correlate-rcon-windows-with-scoreboard-matches.md b/ai/tasks/done/TASK-116-correlate-rcon-windows-with-scoreboard-matches.md deleted file mode 100644 index 5122d13..0000000 --- a/ai/tasks/done/TASK-116-correlate-rcon-windows-with-scoreboard-matches.md +++ /dev/null @@ -1,173 +0,0 @@ ---- -id: TASK-116 -title: Correlate RCON windows with scoreboard matches -status: done -type: backend -team: Backend Senior -supporting_teams: - - Arquitecto Python - - Analista - - PM -roadmap_item: historical -priority: high ---- - -# TASK-116 - Correlate RCON windows with scoreboard matches - -## Goal - -Resolve external scoreboard URLs for RCON competitive-window synthetic matches only when there is strong evidence. - -## Context - -RCON competitive-window matches can have synthetic IDs such as `31:2026-04-12T16:28:55.761810Z`. Those IDs must stay internal and must never be used to fabricate external scoreboard URLs. - -Known validation reference from the user: - -- Internal RCON match: - - server: Comunidad Hispana #01 - - synthetic match id: `31:2026-04-12T16:28:55.761810Z` - - map shown: St. Mere Eglise - - UI start/end around 12/4/26 18:28 to 18:43 local time - - players: 94 average / 98 peak -- Equivalent real scoreboard game known by the user: - - game id: `1561515` - - external scoreboard page exists under the server #01 scoreboard origin - -This task must use that example as a fixture/reference without hardcoding a one-off special case. - -Use branch: - -- `plan/scoreboard-match-linking-tasks` - -## Steps - -1. Work from this task only after moving it to `ai/tasks/in-progress/`. -2. Inspect the listed files before changing anything. -3. Build a resolver that takes server, synthetic session key, map, `started_at`, `ended_at`, duration and player counts. -4. Search existing persisted scoreboard data first. -5. If existing provider code can query recent scoreboard data without credentials, use it carefully; otherwise document the limitation and keep the resolver local-only. -6. Match by server, normalized map and time proximity at minimum. -7. Use additional evidence such as duration and player counts when available. -8. Avoid false positives; return no URL when confidence is low. -9. Return only URLs that pass trusted origin validation. -10. Ensure the match detail endpoint exposes `match_url` for RCON matches only when resolver confidence is sufficient. -11. Add a focused unit or fixture test for the correlation logic if feasible. -12. Validate the result. -13. Move this task to `ai/tasks/done/` only after validation is complete and document the outcome in this file. -14. Commit and push the completed implementation branch. - -## Files to Read First - -- `ai/architecture-index.md` -- `ai/repo-context.md` -- `ai/orchestrator/backend-senior.md` -- `ai/orchestrator/analyst.md` -- `backend/app/rcon_historical_read_model.py` -- `backend/app/rcon_historical_storage.py` -- `backend/app/historical_storage.py` -- `backend/app/historical_snapshots.py` -- `backend/app/routes.py` -- `backend/app/providers/public_scoreboard_provider.py` -- backend trusted scoreboard origin helper/config from TASK-114 -- `backend/tests/` if present -- `scripts/run-integration-tests.ps1` - -## Expected Files to Modify - -- likely a new or existing backend resolver module -- possibly `backend/app/rcon_historical_read_model.py` -- possibly `backend/app/historical_storage.py` -- possibly `backend/app/routes.py` -- possibly backend tests or fixtures -- this task file, moved to `ai/tasks/done/` - -If additional files become necessary, explain why in the task outcome and commit message. - -## Expected Files Not to Modify - -- `frontend/**` -- local `.env` -- database migrations unless absolutely required and justified -- persisted data -- Docker/Compose config -- Elo/MMR implementation files -- historical ingestion policy/config - -## Constraints - -- Do not reintroduce Comunidad Hispana #03. -- Do not reintroduce paused MVP/Elo UI. -- Do not change historical ingestion policy. -- Do not add real credentials. -- Do not modify local `.env`. -- Do not delete persisted data, migrations, backend endpoints or historical ingestion code. -- Do not use the public word "snapshot" in user-facing UI. -- Do not fabricate unsafe URLs from synthetic RCON IDs. -- Prefer no link over a low-confidence or ambiguous link. - -## Validation - -Before completing the task, run and document: - -- `git status` -- Python compile checks for touched backend modules -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- focused unit or fixture test for correlation logic if feasible -- endpoint check confirming `match_url` appears only when confidence is sufficient -- negative test/check confirming low-confidence or ambiguous candidates return no URL -- check using the user reference example when data or fixture setup allows it -- check confirming generated/exposed URLs pass trusted origin validation -- `git diff --name-only` and confirmation that changed files match the expected scope - -If a configured validation command cannot be run, document the exact reason in the outcome. - -## Commit And Push Requirements - -- Run validation before committing. -- Run `git status`. -- Stage only intended files. -- Commit with message: `feat: correlate rcon matches with scoreboard links` -- Push the branch to origin. -- Do not leave completed work only in local. - -## Outcome - -Completed. - -Implementation decisions: - -- Added `backend/app/rcon_scoreboard_correlation.py` as a local-only resolver over already persisted public-scoreboard matches. -- The resolver does not query the public provider or network during request handling. It searches persisted `historical_matches` first and returns no URL when no strong local match exists. -- `backend/app/rcon_historical_read_model.py` now calls the resolver for RCON match-detail payloads and keeps the synthetic RCON session key internal. -- No URL is built from a synthetic RCON ID. Returned URLs must come from persisted `raw_payload_ref` and pass the trusted origin validation from TASK-114. - -Confidence rules chosen: - -- Required evidence: same server, normalized map match, parseable RCON and scoreboard time windows, and a trusted persisted `raw_payload_ref`. -- Scored evidence: time overlap, RCON midpoint inside the scoreboard match, endpoint proximity, duration compatibility, and optional player-count compatibility. -- Minimum score: `5`. -- Ambiguity handling: if two candidates tie for the best score, the resolver returns no URL. -- Preference: no link over a low-confidence or ambiguous link. - -Validation performed: - -- `git status --short --branch` confirmed branch `plan/scoreboard-match-linking-tasks`. -- `$env:PYTHONPATH='backend'; python -m unittest backend.tests.test_scoreboard_match_links` passed. -- The focused test includes the user reference shape: `comunidad-hispana-01`, RCON synthetic session `1:2026-04-12T16:28:55.761810Z`, map `St. Mere Eglise`, and correlated scoreboard game `1561515`. -- The focused test confirms `match_url` appears only with strong evidence. -- The focused test confirms low-confidence/wrong-map candidates return no URL. -- The focused tests confirm exposed URLs pass trusted origin validation because only persisted trusted `raw_payload_ref` values are returned. -- `python -m compileall backend/app backend/tests` passed. -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` passed. -- `git diff --name-only` and `git status --short` were reviewed. Changed files match the expected scope: new resolver module, RCON read model integration, focused backend tests and this task file. - -Note: - -- The focused unittest still emits existing SQLite `ResourceWarning` messages from the repository connection helper pattern during forced cleanup, but all assertions pass and cleanup is not blocked. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split follow-up work into a new task if the scope grows. diff --git a/ai/tasks/done/TASK-117-prioritize-match-link-ux.md b/ai/tasks/done/TASK-117-prioritize-match-link-ux.md deleted file mode 100644 index add17d6..0000000 --- a/ai/tasks/done/TASK-117-prioritize-match-link-ux.md +++ /dev/null @@ -1,150 +0,0 @@ ---- -id: TASK-117 -title: Prioritize match link UX -status: done -type: frontend -team: Frontend Senior -supporting_teams: - - Experto en interfaz - - Backend Senior -roadmap_item: historical-ui -priority: high ---- - -# TASK-117 - Prioritize match link UX - -## Goal - -Adjust the historical UI link priority so safe external scoreboard links are primary when available, and internal details remain the fallback. - -## Context - -Recent cards currently show internal `Ver detalles` links when no safe external match URL exists. After persisted and correlated `match_url` support is improved, the UI must prefer safe external scoreboard links without making unsafe assumptions. - -Use branch: - -- `plan/scoreboard-match-linking-tasks` - -## Steps - -1. Work from this task only after moving it to `ai/tasks/in-progress/`. -2. Inspect the listed files before changing anything. -3. On recent match cards: - - If safe external `match_url` exists, show primary `Ver partida`. - - If no `match_url` exists, show internal `Ver detalles`. -4. On the internal match detail page: - - If `match_url` exists, show `Abrir en scoreboard`. - - If no `match_url` exists, keep internal details only. -5. Ensure external links use `target="_blank"` and `rel="noopener noreferrer"`. -6. Do not show both buttons as competing primary actions unless the existing design clearly requires it. -7. Preserve the current sober military/Vietnam tactical visual style. -8. Validate the result. -9. Move this task to `ai/tasks/done/` only after validation is complete and document the outcome in this file. -10. Commit and push the completed implementation branch. - -## Files to Read First - -- `ai/architecture-index.md` -- `ai/repo-context.md` -- `ai/orchestrator/frontend-senior.md` -- `ai/orchestrator/ui-expert.md` -- `frontend/historico.html` -- `frontend/assets/js/historico.js` -- `frontend/assets/css/historico.css` -- `frontend/historico-partida.html` -- `frontend/assets/js/historico-partida.js` -- `backend/app/routes.py` -- `scripts/run-integration-tests.ps1` - -## Expected Files to Modify - -- `frontend/assets/js/historico.js` -- possibly `frontend/assets/css/historico.css` -- possibly `frontend/historico-partida.html` -- possibly `frontend/assets/js/historico-partida.js` -- this task file, moved to `ai/tasks/done/` - -If additional files become necessary, explain why in the task outcome and commit message. - -## Expected Files Not to Modify - -- backend historical ingestion modules -- database migrations -- persisted data -- local `.env` -- Docker/Compose config -- Elo/MMR implementation files -- unrelated frontend pages - -## Constraints - -- Do not reintroduce Comunidad Hispana #03. -- Do not reintroduce paused MVP/Elo UI. -- Do not change historical ingestion policy. -- Do not add real credentials. -- Do not modify local `.env`. -- Do not delete persisted data, migrations, backend endpoints or historical ingestion code. -- Do not use the public word "snapshot" in user-facing UI. -- Do not fabricate or transform external URLs in the frontend; trust only backend-provided `match_url`. - -## Validation - -Before completing the task, run and document: - -- `git status` -- `node --check frontend/assets/js/historico.js` -- `node --check frontend/assets/js/historico-partida.js` if present -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- served or static HTML check confirming recent cards show `Ver partida` when `match_url` exists -- served or static HTML check confirming recent cards show `Ver detalles` when `match_url` is absent -- served or static HTML check confirming detail page shows `Abrir en scoreboard` when `match_url` exists -- served or static HTML check confirming no Comunidad Hispana #03 appears -- served or static HTML check confirming paused MVP/Elo UI remains absent -- check confirming external links include `target="_blank"` and `rel="noopener noreferrer"` -- `git diff --name-only` and confirmation that changed files match the expected scope - -If a configured validation command cannot be run, document the exact reason in the outcome. - -## Commit And Push Requirements - -- Run validation before committing. -- Run `git status`. -- Stage only intended files. -- Commit with message: `chore: prioritize match link ux` -- Push the branch to origin. -- Do not leave completed work only in local. - -## Outcome - -Completed. - -Implementation decisions: - -- Recent match cards now trust only backend-provided `match_url` for the external primary action. -- Existing priority remains: `Ver partida` when `match_url` exists, otherwise internal `Ver detalles`. -- Existing detail-page behavior already matched the task: it shows `Abrir en scoreboard` only when `match_url` exists and uses `target="_blank"` plus `rel="noopener noreferrer"`. -- No CSS or markup change was needed. - -Validation performed: - -- `git status --short --branch` confirmed branch `plan/scoreboard-match-linking-tasks`. -- `node --check frontend/assets/js/historico.js` passed. -- `node --check frontend/assets/js/historico-partida.js` passed. -- Static Node render check confirmed recent cards show `Ver partida` when `match_url` exists. -- Static Node render check confirmed recent cards show `Ver detalles` when `match_url` is absent. -- Static Node render check confirmed recent external links include `target="_blank"` and `rel="noopener noreferrer"`. -- Static Node render check confirmed the detail-page action shows `Abrir en scoreboard` when `match_url` exists and hides when absent. -- Static Node render check confirmed no `Comunidad Hispana #03` appears in the checked match-card states. -- Static Node render check confirmed paused MVP/Elo UI does not surface in the checked match-card states. -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` passed. -- `git diff --name-only` and `git status --short` were reviewed. Changed files match the expected scope: `frontend/assets/js/historico.js` and this task file. - -Note: - -- The Browser plugin was not available as a callable browser automation tool in this session, so validation used the task-allowed static HTML/JS render checks instead of an in-browser screenshot pass. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split follow-up work into a new task if the scope grows. diff --git a/ai/tasks/done/TASK-118-enrich-internal-match-detail-page.md b/ai/tasks/done/TASK-118-enrich-internal-match-detail-page.md deleted file mode 100644 index c58c0df..0000000 --- a/ai/tasks/done/TASK-118-enrich-internal-match-detail-page.md +++ /dev/null @@ -1,164 +0,0 @@ ---- -id: TASK-118 -title: Enrich internal match detail page -status: done -type: frontend -team: Frontend Senior -supporting_teams: - - Backend Senior - - Experto en interfaz -roadmap_item: historical-ui -priority: medium ---- - -# TASK-118 - Enrich internal match detail page - -## Goal - -Make the internal match detail page more useful when no scoreboard link exists. - -## Context - -The internal match detail page is the safe fallback for RCON synthetic matches and any match without a trusted external scoreboard URL. It should present all available local data clearly without trying to clone the external scoreboard site. - -Use branch: - -- `plan/scoreboard-match-linking-tasks` - -## Steps - -1. Work from this task only after moving it to `ai/tasks/in-progress/`. -2. Inspect the listed files before changing anything. -3. Show all available RCON/persisted fields clearly: - - server - - map - - start - - end - - duration - - average players - - peak players - - sample count - - result if available - - capture basis - - capabilities -4. If player-level data exists in persisted scoreboard storage, show a simple player table. -5. If player-level data is unavailable, show a clear friendly message. -6. Keep the visual style consistent with HLL Vietnam's sober military/Vietnam tactical identity. -7. Do not attempt to fully clone the scoreboard site yet. -8. Keep the page graceful for partial RCON data. -9. Validate the result. -10. Move this task to `ai/tasks/done/` only after validation is complete and document the outcome in this file. -11. Commit and push the completed implementation branch. - -## Files to Read First - -- `ai/architecture-index.md` -- `ai/repo-context.md` -- `ai/orchestrator/frontend-senior.md` -- `ai/orchestrator/ui-expert.md` -- `ai/orchestrator/backend-senior.md` -- `frontend/historico-partida.html` -- `frontend/assets/js/historico-partida.js` -- `frontend/assets/css/historico.css` -- `backend/app/routes.py` -- `backend/app/historical_storage.py` -- `backend/app/rcon_historical_read_model.py` -- `scripts/run-integration-tests.ps1` - -## Expected Files to Modify - -- `frontend/historico-partida.html` -- `frontend/assets/js/historico-partida.js` -- possibly `frontend/assets/css/historico.css` -- possibly `backend/app/routes.py` -- possibly `backend/app/historical_storage.py` -- possibly `backend/app/rcon_historical_read_model.py` -- this task file, moved to `ai/tasks/done/` - -If additional files become necessary, explain why in the task outcome and commit message. - -## Expected Files Not to Modify - -- historical ingestion policy/config -- database migrations unless absolutely required and justified -- persisted data -- local `.env` -- Docker/Compose config -- Elo/MMR implementation files -- unrelated frontend pages - -## Constraints - -- Do not reintroduce Comunidad Hispana #03. -- Do not reintroduce paused MVP/Elo UI. -- Do not change historical ingestion policy. -- Do not add real credentials. -- Do not modify local `.env`. -- Do not delete persisted data, migrations, backend endpoints or historical ingestion code. -- Do not use the public word "snapshot" in user-facing UI. -- Keep the page focused on local/internal match detail presentation. - -## Validation - -Before completing the task, run and document: - -- `git status` -- `node --check frontend/assets/js/historico-partida.js` -- Python compile checks for touched backend modules, if any -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- served or static check confirming the internal detail page renders partial RCON data gracefully -- served or static check confirming persisted scoreboard details render richer data when available -- check confirming a friendly message appears when player-level data is unavailable -- check confirming no Comunidad Hispana #03 appears -- check confirming paused MVP/Elo UI remains absent -- check confirming no public "snapshot" wording appears -- `git diff --name-only` and confirmation that changed files match the expected scope - -If a configured validation command cannot be run, document the exact reason in the outcome. - -## Commit And Push Requirements - -- Run validation before committing. -- Run `git status`. -- Stage only intended files. -- Commit with message: `feat: enrich internal match detail page` -- Push the branch to origin. -- Do not leave completed work only in local. - -## Outcome - -Completed. - -Implementation decisions: - -- Enriched persisted public-scoreboard match detail payloads with `players` rows from local historical storage. -- Added an empty `players` list for RCON competitive-window details so the frontend can treat partial RCON data gracefully. -- Expanded the internal detail page summary to show server, map, start, end, duration, average players, peak players, sample count, result, capture basis and capabilities. -- Added a simple player table for persisted player-level rows. -- Added a friendly unavailable message for RCON windows or persisted matches without player rows. -- Kept the page as a local/internal detail view and did not attempt to clone the external scoreboard. - -Validation performed: - -- `git status --short --branch` confirmed branch `plan/scoreboard-match-linking-tasks`. -- `node --check frontend/assets/js/historico-partida.js` passed. -- `python -m compileall backend/app` passed. -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` passed. -- Static Node render check confirmed partial RCON data renders gracefully with sample count, peak players and capability fields. -- Static Node render check confirmed persisted scoreboard details render a player table when player rows are present. -- Static Node render check confirmed the friendly no-player-data message appears when player-level data is unavailable. -- Static Node render check confirmed no `Comunidad Hispana #03` appears. -- Static Node render check confirmed paused MVP/Elo UI remains absent in the checked detail states. -- Static Node render check confirmed no public `snapshot` wording appears in the checked detail states. -- `$env:PYTHONPATH='backend'; python -m unittest backend.tests.test_scoreboard_match_links` passed after backend payload changes. -- `git diff --name-only` and `git status --short` were reviewed. Changed files match the expected scope: match detail HTML/JS/CSS, backend detail payloads and this task file. - -Note: - -- The focused backend unittest still emits existing SQLite `ResourceWarning` messages from the repository connection helper pattern during forced cleanup, but all assertions pass. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split follow-up work into a new task if the scope grows. diff --git a/ai/tasks/done/TASK-119-add-historical-ui-regression-validation.md b/ai/tasks/done/TASK-119-add-historical-ui-regression-validation.md deleted file mode 100644 index fd8da93..0000000 --- a/ai/tasks/done/TASK-119-add-historical-ui-regression-validation.md +++ /dev/null @@ -1,154 +0,0 @@ ---- -id: TASK-119 -title: Add historical UI regression validation -status: done -type: platform -team: Frontend Senior -supporting_teams: - - Backend Senior - - PM -roadmap_item: historical-ui -priority: medium ---- - -# TASK-119 - Add historical UI regression validation - -## Goal - -Add lightweight validation so future changes do not reintroduce removed UI or unsafe historical match-link behavior. - -## Context - -HLL Vietnam has intentionally removed Comunidad Hispana #03 from public/default flows, paused MVP/Elo UI, restored RCON-first historical policy and added internal match details. A small regression validation script/check should protect those decisions without adding heavy test infrastructure. - -Use branch: - -- `plan/scoreboard-match-linking-tasks` - -## Steps - -1. Work from this task only after moving it to `ai/tasks/in-progress/`. -2. Inspect the listed files before changing anything. -3. Extend or add validation scripts/checks compatible with the current repo. -4. Check served or static frontend for: - - no Comunidad Hispana #03 selector. - - no MVP mensual V1/V2 blocks. - - no Comparativa V1 vs V2. - - no Elo/MMR public block. - - no public "snapshot" wording. - - recent cards include either `Ver partida` or `Ver detalles`. -5. Check backend: - - `/health` works. - - historical source remains RCON-first. - - match detail endpoint works. -6. Keep validation lightweight and compatible with local PowerShell usage. -7. Update documentation only if needed to explain how to run the new check. -8. Validate the result. -9. Move this task to `ai/tasks/done/` only after validation is complete and document the outcome in this file. -10. Commit and push the completed implementation branch. - -## Files to Read First - -- `ai/architecture-index.md` -- `ai/repo-context.md` -- `ai/orchestrator/frontend-senior.md` -- `ai/orchestrator/backend-senior.md` -- `scripts/run-integration-tests.ps1` -- `frontend/historico.html` -- `frontend/assets/js/historico.js` -- `frontend/historico-partida.html` -- `frontend/assets/js/historico-partida.js` -- `backend/app/config.py` -- `backend/app/routes.py` -- `docs/decisions.md` - -## Expected Files to Modify - -- `scripts/run-integration-tests.ps1` or a focused new validation script under `scripts/` -- possibly documentation for the new validation command -- possibly backend/frontend test fixtures only if needed -- this task file, moved to `ai/tasks/done/` - -If additional files become necessary, explain why in the task outcome and commit message. - -## Expected Files Not to Modify - -- product frontend behavior except minimal test hooks if absolutely required and justified -- backend product behavior except minimal validation hooks if absolutely required and justified -- database migrations -- persisted data -- local `.env` -- Docker/Compose config unless required for validation and explicitly justified -- Elo/MMR implementation files - -## Constraints - -- Do not reintroduce Comunidad Hispana #03. -- Do not reintroduce paused MVP/Elo UI. -- Do not change historical ingestion policy. -- Do not add real credentials. -- Do not modify local `.env`. -- Do not delete persisted data, migrations, backend endpoints or historical ingestion code. -- Do not use the public word "snapshot" in user-facing UI. -- Keep validation lightweight; do not introduce unnecessary frameworks or dependencies. - -## Validation - -Before completing the task, run and document: - -- `git status` -- `node --check frontend/assets/js/historico.js` -- `node --check frontend/assets/js/historico-partida.js` if present -- Python compile checks for touched backend modules, if any -- the new or updated historical UI regression validation -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- check confirming `/health` works when the backend is served for validation -- check confirming historical source remains RCON-first -- check confirming the match detail endpoint works -- check confirming no Comunidad Hispana #03, MVP mensual V1/V2, Comparativa V1 vs V2, Elo/MMR public block or public "snapshot" wording is present -- check confirming recent cards include either `Ver partida` or `Ver detalles` -- `git diff --name-only` and confirmation that changed files match the expected scope - -If a configured validation command cannot be run, document the exact reason in the outcome. - -## Commit And Push Requirements - -- Run validation before committing. -- Run `git status`. -- Stage only intended files. -- Commit with message: `test: add historical ui regression validation` -- Push the branch to origin. -- Do not leave completed work only in local. - -## Outcome - -Completed. - -Implementation decisions: - -- Added `scripts/run-historical-ui-regression-tests.ps1` as a lightweight PowerShell validation for historical UI guardrails. -- Wired the new script into `scripts/run-integration-tests.ps1` so the regression checks run with the existing platform validation command. -- Kept validation static/route-level by default to avoid adding frontend test frameworks or browser dependencies. -- Added a separate served-backend validation during task execution for `/health` and match detail. - -Validation performed: - -- `git status --short --branch` confirmed branch `plan/scoreboard-match-linking-tasks`. -- `node --check frontend/assets/js/historico.js` passed. -- `node --check frontend/assets/js/historico-partida.js` passed. -- `powershell -ExecutionPolicy Bypass -File scripts/run-historical-ui-regression-tests.ps1` passed. -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` passed and now includes the historical UI regression validation. -- Served backend check passed on `http://127.0.0.1:8765/health`. -- Served backend check confirmed `/health` reports `historical_data_source` as `rcon`. -- Served backend check passed for `/api/historical/matches/detail?server=comunidad-hispana-01&match=regression-check`. -- Regression script confirms no `Comunidad Hispana #03` selector, no MVP mensual V1/V2 blocks, no Comparativa V1 vs V2 block, no Elo/MMR public block and no visible public `snapshot` wording in historical HTML. -- Regression script confirms recent-card code includes `Ver partida` and `Ver detalles`. -- Regression script confirms recent-card code does not trust legacy `source_url` fallback. -- Regression script confirms external detail links keep `target="_blank"` and `rel="noopener noreferrer"`. -- `git diff --name-only` and `git status --short` were reviewed. Changed files match the expected scope: validation scripts and this task file. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split follow-up work into a new task if the scope grows. diff --git a/ai/tasks/done/TASK-120-integrate-adminlog-ingestion-into-rcon-historical-worker.md b/ai/tasks/done/TASK-120-integrate-adminlog-ingestion-into-rcon-historical-worker.md deleted file mode 100644 index b1131ff..0000000 --- a/ai/tasks/done/TASK-120-integrate-adminlog-ingestion-into-rcon-historical-worker.md +++ /dev/null @@ -1,99 +0,0 @@ ---- -id: TASK-120 -title: Integrate AdminLog ingestion into RCON historical worker -status: done -type: backend -team: Backend Senior -supporting_teams: - - Arquitecto Python -roadmap_item: rcon-full-data -priority: high ---- - -# TASK-120 - Integrate AdminLog ingestion into RCON historical worker - -## Goal - -Automatically ingest RCON AdminLog events during the periodic RCON historical worker capture flow. - -## Background - -HLL Vietnam is moving to an RCON-first historical/live data platform. Manual AdminLog ingestion already exists and has been validated with duplicate-safe canonical message storage. The periodic worker should keep collecting this data automatically after or alongside existing session/gamestate capture. - -## Constraints - -- Do not reactivate Elo/MMR. -- Do not reintroduce Comunidad Hispana #03. -- Do not store secrets, runtime DB files or `backend/runtime`. -- Do not modify Docker behavior. -- Do not change frontend files. -- Preserve existing writer lock behavior. -- If AdminLog ingestion fails for one target, normal session capture for other targets must continue. -- Public scoreboard remains optional enrichment/fallback only. - -## Allowed Changes - -- `backend/app/rcon_historical_worker.py` -- tests only if needed for worker payload behavior -- this task file when moving it through the workflow - -## Implementation Requirements - -- Work from a dedicated branch for this task. -- Read first: - - `AGENTS.md` - - `ai/architecture-index.md` - - `ai/repo-context.md` - - `ai/orchestrator/backend-senior.md` - - `backend/app/rcon_historical_worker.py` - - `backend/app/rcon_admin_log_ingestion.py` - - `backend/app/rcon_admin_log_storage.py` -- Reuse existing AdminLog ingestion and storage modules. -- Add a configurable AdminLog lookback window, defaulting to 60 minutes. -- Prefer project-consistent naming such as `HLL_BACKEND_RCON_ADMIN_LOG_LOOKBACK_MINUTES=60`. -- Do not hardcode `1440` for the periodic worker. -- Keep the manual backfill command able to support `--minutes 1440`. -- Extend worker results with: - - `admin_log_events_seen` - - `admin_log_events_inserted` - - `admin_log_duplicate_events` - - `admin_log_failed_targets` -- Keep changes deterministic and idempotent. - -## Validation Commands - -- `python -m compileall backend/app` -- `docker compose up -d --build backend rcon-historical-worker` -- `docker compose exec backend python -m app.rcon_historical_worker capture` -- Run AdminLog ingestion twice and confirm dedupe still reports duplicates on the second run. - -## Manual Verification Steps - -- Confirm worker capture returns normal session/gamestate data plus AdminLog metrics. -- Confirm an AdminLog failure for one target is reported without breaking all target capture. -- Confirm `/health` still works. -- Confirm `git diff --name-only` matches the allowed scope. - -## Git Requirements - -- Create a dedicated branch for this task, for example `codex/task-120-adminlog-worker-ingestion`. -- Run relevant validation before committing. -- Stage only intended files. -- Commit the completed implementation. -- Push the branch to origin. - -## Outcome - -- Integrated AdminLog ingestion into the RCON historical capture worker using the existing ingestion/storage path. -- Added `HLL_BACKEND_RCON_ADMIN_LOG_LOOKBACK_MINUTES`, defaulting to 60 minutes. -- Added worker result totals for AdminLog events seen, inserted, duplicated and failed targets. -- Verified a temporary bad RCON target reports one session failure and one AdminLog failure while a valid target still captures successfully. - -## Validation Result - -- `python -m compileall backend/app` passed. -- `docker compose up -d --build backend rcon-historical-worker` passed. -- `docker compose exec backend python -m app.rcon_historical_worker capture` passed and returned AdminLog metrics. -- `docker compose exec backend python -m app.rcon_admin_log_ingestion --minutes 1440` run twice; second run reported 143 duplicate events and 0 inserted events. -- `/health` returned `status: ok`. -- `git diff --name-only` matched the expected task scope. diff --git a/ai/tasks/done/TASK-121-add-rcon-adminlog-storage-read-tests.md b/ai/tasks/done/TASK-121-add-rcon-adminlog-storage-read-tests.md deleted file mode 100644 index 8c7117c..0000000 --- a/ai/tasks/done/TASK-121-add-rcon-adminlog-storage-read-tests.md +++ /dev/null @@ -1,88 +0,0 @@ ---- -id: TASK-121 -title: Add RCON AdminLog storage read tests -status: done -type: backend -team: Backend Senior -supporting_teams: - - Arquitecto Python -roadmap_item: rcon-full-data -priority: high ---- - -# TASK-121 - Add RCON AdminLog storage read tests - -## Goal - -Add deterministic regression tests for AdminLog persistence, reads and deduplication. - -## Background - -AdminLog storage and manual ingestion exist, and real validation confirmed canonical message deduplication. The storage layer now needs offline tests so future RCON pipeline work can depend on it safely. - -## Constraints - -- Do not require real RCON. -- Do not use the real runtime database. -- Do not reactivate Elo/MMR. -- Do not reintroduce Comunidad Hispana #03. -- Do not commit runtime DB files or `backend/runtime`. -- Keep tests deterministic and offline. - -## Allowed Changes - -- a new backend test file under `backend/tests/` -- possibly small test-only helpers if already consistent with the test suite -- this task file when moving it through the workflow - -## Implementation Requirements - -- Work from a dedicated branch for this task. -- Read first: - - `AGENTS.md` - - `ai/architecture-index.md` - - `ai/repo-context.md` - - `ai/orchestrator/backend-senior.md` - - `backend/app/rcon_admin_log_storage.py` - - `backend/app/rcon_admin_log_parser.py` - - `backend/tests/test_rcon_admin_log_parser.py` -- Use a temporary SQLite database path. -- Test table initialization. -- Test that first insert inserts events. -- Test that a second insert of the same events returns duplicates. -- Test that canonical message dedupes repeated AdminLog reads with changing relative prefixes. -- Test `event_counts` grouping by target and event type. -- If pytest is unavailable locally, document the docker-based pytest command in the task outcome. - -## Validation Commands - -- `python -m compileall backend/app` -- `python -m pytest backend/tests/test_rcon_admin_log_parser.py backend/tests/.py` - -## Manual Verification Steps - -- Confirm no real RCON credentials or runtime DB paths are used. -- Confirm tests create and clean temporary data only. -- Confirm `git diff --name-only` matches the allowed scope. - -## Git Requirements - -- Create a dedicated branch for this task, for example `codex/task-121-adminlog-storage-tests`. -- Run relevant validation before committing. -- Stage only intended files. -- Commit the completed implementation. -- Push the branch to origin. - -## Outcome - -- Added deterministic offline storage tests in `backend/tests/test_rcon_admin_log_storage.py`. -- Covered AdminLog table initialization, first insert behavior, duplicate reporting, canonical-message dedupe when relative prefixes change, and event-count grouping. -- Tests use pytest `tmp_path` temporary SQLite paths and do not use real RCON or the runtime database. - -## Validation Result - -- `python -m compileall backend/app` passed. -- `python -m pytest backend/tests/test_rcon_admin_log_parser.py backend/tests/test_rcon_admin_log_storage.py` could not run locally because `pytest` is not installed. -- `docker compose exec backend python -m pytest backend/tests/test_rcon_admin_log_parser.py backend/tests/test_rcon_admin_log_storage.py` also could not run because `pytest` is not installed in the backend image. -- Direct Python invocation of the new storage test functions passed with `PYTHONPATH=backend`. -- `git diff --name-only` matched the expected task scope after accounting for the new untracked test file. diff --git a/ai/tasks/done/TASK-122-materialize-rcon-matches-from-adminlog-events.md b/ai/tasks/done/TASK-122-materialize-rcon-matches-from-adminlog-events.md deleted file mode 100644 index 64020c0..0000000 --- a/ai/tasks/done/TASK-122-materialize-rcon-matches-from-adminlog-events.md +++ /dev/null @@ -1,100 +0,0 @@ ---- -id: TASK-122 -title: Materialize RCON matches from AdminLog events -status: done -type: backend -team: Backend Senior -supporting_teams: - - Arquitecto de Base de Datos - - Arquitecto Python -roadmap_item: rcon-full-data -priority: high ---- - -# TASK-122 - Materialize RCON matches from AdminLog events - -## Goal - -Create a materialization layer that converts RCON AdminLog and useful session/gamestate data into durable RCON match records. - -## Background - -Recent matches need consistent RCON-first scores. AdminLog contains `MATCH START` and `MATCH ENDED` records, while session/gamestate capture can provide partial in-progress scores. A materialized read model should make this data reliable and idempotent before UI changes consume it. - -## Constraints - -- Do not delete or replace existing competitive-window logic. -- No UI changes. -- Do not reactivate Elo/MMR. -- Do not reintroduce Comunidad Hispana #03. -- Do not store secrets, runtime DB files or `backend/runtime`. -- Preserve RCON as the source of truth; public scoreboard is optional enrichment/fallback only. - -## Allowed Changes - -- backend storage/model modules for materialized RCON matches -- backend tests for materialization -- small wiring needed to initialize/read the new table -- this task file when moving it through the workflow - -## Implementation Requirements - -- Work from a dedicated branch for this task. -- Read first: - - `AGENTS.md` - - `ai/architecture-index.md` - - `ai/repo-context.md` - - `ai/orchestrator/backend-senior.md` - - `ai/orchestrator/database-architect.md` - - `backend/app/rcon_admin_log_storage.py` - - `backend/app/rcon_admin_log_parser.py` - - `backend/app/rcon_historical_read_model.py` - - existing historical storage modules -- Derive RCON matches from: - - `match_start` - - `match_end` - - session/gamestate samples where useful -- Store materialized records in SQLite, using a table such as `rcon_materialized_matches`. -- Include fields for `id`, `target_key`, `external_server_id`, `match_key` or `session_key`, `map_name`, `map_pretty_name`, `game_mode`, server/event start/end times, scores, winner, `confidence_mode`, `source_basis`, `created_at` and `updated_at`. -- Make materialization idempotent. -- Treat `MATCH ENDED` as authoritative result when present. -- Treat session/gamestate scores as partial or in-progress when no `MATCH ENDED` exists. -- Parse and test results including 5-0, 2-2 and 0-5. - -## Validation Commands - -- `python -m compileall backend/app` -- `python -m pytest backend/tests/.py` - -## Manual Verification Steps - -- Confirm repeated materialization does not duplicate matches. -- Confirm a sample `MATCH ENDED \`ST MARIE DU MONT Warfare\` ALLIED (5 - 0) AXIS` produces the expected score and winner. -- Confirm existing competitive-window reads still work. -- Confirm `/health` still works. -- Confirm `git diff --name-only` matches the allowed scope. - -## Git Requirements - -- Create a dedicated branch for this task, for example `codex/task-122-rcon-match-materialization`. -- Run relevant validation before committing. -- Stage only intended files. -- Commit the completed implementation. -- Push the branch to origin. - -## Outcome - -Implemented `backend/app/rcon_admin_log_materialization.py` with idempotent SQLite tables for `rcon_materialized_matches` and the shared materialization command `python -m app.rcon_admin_log_materialization`. Match records are derived from AdminLog `match_start` and `match_end` events, with `MATCH ENDED` results stored as authoritative `admin-log-match-ended` rows. Session windows remain available as partial fallback without deleting the existing competitive-window code. - -The command also exposes `python -m app.rcon_admin_log_materialization status` for materialization diagnostics: materialized match count, matches with player stats, first/last server time by target and event counts by type. - -No server #03 target was reintroduced, Elo/MMR was not reactivated, and no runtime DB files were committed. - -## Validation Result - -- Passed: `python -m compileall backend/app` -- Pytest was not installed in the local Python environment. -- Passed deterministic fallback: `$env:PYTHONPATH='backend'; python -m unittest backend.tests.test_rcon_materialization_pipeline backend.tests.test_scoreboard_match_links` -- Passed Docker smoke: `docker compose up -d --build backend rcon-historical-worker` -- Passed Docker materialization: `docker compose exec backend python -m app.rcon_admin_log_materialization` reported `matches_seen: 24`, `matches_materialized: 24`, `errors: []`. -- Passed diagnostic command: `docker compose exec backend python -m app.rcon_admin_log_materialization status`. diff --git a/ai/tasks/done/TASK-123-materialize-rcon-player-match-stats.md b/ai/tasks/done/TASK-123-materialize-rcon-player-match-stats.md deleted file mode 100644 index 2f3e12d..0000000 --- a/ai/tasks/done/TASK-123-materialize-rcon-player-match-stats.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -id: TASK-123 -title: Materialize RCON player match stats -status: done -type: backend -team: Backend Senior -supporting_teams: - - Arquitecto de Base de Datos - - Arquitecto Python -roadmap_item: rcon-full-data -priority: high ---- - -# TASK-123 - Materialize RCON player match stats - -## Goal - -Build first-pass per-match player statistics from RCON AdminLog kill, team and presence events. - -## Background - -The internal match detail page should eventually show a simplified scoreboard-like view backed by RCON. AdminLog includes `KILL`, `TEAMSWITCH`, `CONNECTED` and `DISCONNECTED` events that can produce kills, deaths, teamkills, weapon counts and player presence. - -## Constraints - -- No UI changes. -- Do not expose raw player IDs in frontend work. -- Do not reactivate Elo/MMR. -- Do not reintroduce Comunidad Hispana #03. -- Do not store secrets, runtime DB files or `backend/runtime`. -- Keep rematerialization deterministic and idempotent. - -## Allowed Changes - -- backend materialization/storage code for RCON player match stats -- optional structured event timeline table or read logic -- backend tests and fixtures -- this task file when moving it through the workflow - -## Implementation Requirements - -- Work from a dedicated branch for this task. -- Read first: - - `AGENTS.md` - - `ai/architecture-index.md` - - `ai/repo-context.md` - - `ai/orchestrator/backend-senior.md` - - `ai/orchestrator/database-architect.md` - - `backend/app/rcon_admin_log_parser.py` - - `backend/app/rcon_admin_log_storage.py` - - materialized match code from TASK-122 -- Use parsed events from `rcon_admin_log_events`. -- Associate events to matches by target and server-time range between `match_start` and `match_end`. -- Create a table such as `rcon_match_player_stats` with target, match, player identity/display, team, kills, deaths, teamkills, deaths by teamkill, weapon JSON, death-by weapon JSON, most-killed JSON, death-by JSON and first/last seen server time. -- Optionally create `rcon_match_events` for structured timeline rows, or read directly from AdminLog events. -- For `KILL`, add one kill to the killer when teams differ, add one death to the victim, and count same-team kills as teamkills plus victim deaths by teamkill. -- Track weapon counts and killer-victim counts. -- Use connected/disconnected/team switch events to improve presence and team attribution. -- Handle missing or non-Steam-style player IDs robustly. - -## Validation Commands - -- `python -m compileall backend/app` -- `python -m pytest backend/tests/.py` - -## Manual Verification Steps - -- Validate offline fixtures containing `KILL`, `TEAMSWITCH`, `CONNECTED` and `DISCONNECTED`. -- Confirm kills, deaths, teamkills, weapons, most killed and death-by summaries. -- Confirm repeated materialization does not duplicate or inflate stats. -- Confirm `/health` still works. -- Confirm `git diff --name-only` matches the allowed scope. - -## Git Requirements - -- Create a dedicated branch for this task, for example `codex/task-123-rcon-player-stats`. -- Run relevant validation before committing. -- Stage only intended files. -- Commit the completed implementation. -- Push the branch to origin. - -## Outcome - -Implemented AdminLog-derived `rcon_match_player_stats` materialization in `backend/app/rcon_admin_log_materialization.py`. The materializer associates kill/presence events to materialized matches by target and server-time range, rebuilds stats deterministically on each run, and handles Steam-style and non-Steam player identifiers without exposing them in the match-detail read model. - -Kill logic now records kills, deaths, teamkills, deaths by teamkill, weapon counts, death-by weapon counts, most-killed summaries and death-by summaries. Presence events are used when they include stable player identity, while team-switch rows without player IDs are ignored for identity creation to avoid duplicate display-name-only player rows. - -Non-blocking follow-up note: suspicious live/session queue fields remain worth reviewing separately. In previous worker output, `vip_queue_count` appeared as `464/434` while `max_vip_queue_count` was `2`; this batch did not change that parser path. - -## Validation Result - -- Passed: `python -m compileall backend/app` -- Pytest was not installed in the local Python environment. -- Passed deterministic fallback: `$env:PYTHONPATH='backend'; python -m unittest backend.tests.test_rcon_materialization_pipeline backend.tests.test_scoreboard_match_links` -- Passed Docker AdminLog ingestion: `docker compose exec backend python -m app.rcon_admin_log_ingestion --minutes 1440` reported `events_seen: 143`, `errors: []`. -- Passed Docker materialization: `docker compose exec backend python -m app.rcon_admin_log_materialization` reported `player_stats_seen: 22`, `player_stats_materialized: 22`, `errors: []`. diff --git a/ai/tasks/done/TASK-124-add-internal-rcon-match-detail-api.md b/ai/tasks/done/TASK-124-add-internal-rcon-match-detail-api.md deleted file mode 100644 index fa2ae0b..0000000 --- a/ai/tasks/done/TASK-124-add-internal-rcon-match-detail-api.md +++ /dev/null @@ -1,98 +0,0 @@ ---- -id: TASK-124 -title: Add internal RCON match detail API -status: done -type: backend -team: Backend Senior -supporting_teams: - - Arquitecto Python - - Frontend Senior -roadmap_item: rcon-full-data -priority: high ---- - -# TASK-124 - Add internal RCON match detail API - -## Goal - -Expose internal match detail data from materialized RCON matches and player stats. - -## Background - -`frontend/historico-partida.html` needs a reliable internal backend payload when an external scoreboard link is unavailable or not safely correlated. The API should be RCON-first and graceful for partial or old data. - -## Constraints - -- No UI changes in this task. -- Preserve existing query params and fallback behavior. -- If no materialized RCON detail exists, return a controlled empty or partial payload, not a 500. -- Do not reactivate Elo/MMR. -- Do not reintroduce Comunidad Hispana #03. -- Do not store secrets, runtime DB files or `backend/runtime`. -- Public scoreboard URL is optional enrichment only. - -## Allowed Changes - -- `backend/app/routes.py` or existing route modules -- backend read-model modules for historical match detail -- backend tests for response builder/read model -- this task file when moving it through the workflow - -## Implementation Requirements - -- Work from a dedicated branch for this task. -- Read first: - - `AGENTS.md` - - `ai/architecture-index.md` - - `ai/repo-context.md` - - `ai/orchestrator/backend-senior.md` - - `backend/app/routes.py` - - `backend/app/rcon_historical_read_model.py` - - materialized match/player stats code from TASK-122 and TASK-123 - - `frontend/historico-partida.html` - - `frontend/assets/js/historico-partida.js` -- Extend or add `/api/historical/matches/detail?server=...&match=...`. -- Prefer an existing endpoint if present and do not break current query params. -- Response should include server, match id, map, game mode, start/end, duration, result, winner, confidence/source basis, optional external `match_url`, player rows and timeline/event summary. -- Player rows should include display name, team, kills, deaths, teamkills, K/D, top weapons, most killed and death-by summary. -- Keep old data fallbacks controlled and backwards-compatible. - -## Validation Commands - -- `python -m compileall backend/app` -- `python -m pytest backend/tests/.py` -- `docker compose up -d --build backend` -- `Invoke-WebRequest "http://localhost:8000/api/historical/matches/detail?server=&match="` -- `Invoke-WebRequest "http://localhost:8000/health"` - -## Manual Verification Steps - -- Confirm known materialized match detail returns the expected summary and players. -- Confirm missing materialized data returns a controlled partial payload. -- Confirm `/health` still works. -- Confirm no server #03, Elo/MMR or secrets were introduced. -- Confirm `git diff --name-only` matches the allowed scope. - -## Git Requirements - -- Create a dedicated branch for this task, for example `codex/task-124-rcon-match-detail-api`. -- Run relevant validation before committing. -- Stage only intended files. -- Commit the completed implementation. -- Push the branch to origin. - -## Outcome - -Extended the existing RCON historical read model behind `/api/historical/matches/detail?server=...&match=...` to prefer materialized RCON AdminLog match detail when available, while preserving the existing competitive-window and public-scoreboard fallback behavior. - -Materialized detail payloads now include server, match id, map, game mode, start/end, duration, result, winner, confidence/source basis, safe optional `match_url`, player rows and timeline event counts. Player rows expose display names and derived summaries only, not raw player IDs. - -Missing materialized detail remains controlled: the endpoint falls back to the existing paths and returns `found: false` instead of raising a 500 when no detail is available. - -## Validation Result - -- Passed: `python -m compileall backend/app` -- Pytest was not installed in the local Python environment. -- Passed deterministic fallback: `$env:PYTHONPATH='backend'; python -m unittest backend.tests.test_rcon_materialization_pipeline backend.tests.test_scoreboard_match_links` -- Passed API smoke: `Invoke-WebRequest "http://localhost:8000/health"`. -- Passed API detail check: `Invoke-WebRequest "http://localhost:8000/api/historical/matches/detail?server=comunidad-hispana-02&match=comunidad-hispana-02:1779108337:1779111786:stmariedumontwarfare"` returned `found: true`, `result_source: admin-log-match-ended`, players and timeline counts. diff --git a/ai/tasks/done/TASK-125-prefer-materialized-rcon-recent-matches.md b/ai/tasks/done/TASK-125-prefer-materialized-rcon-recent-matches.md deleted file mode 100644 index fe7c6d8..0000000 --- a/ai/tasks/done/TASK-125-prefer-materialized-rcon-recent-matches.md +++ /dev/null @@ -1,101 +0,0 @@ ---- -id: TASK-125 -title: Prefer materialized RCON recent matches -status: done -type: backend -team: Backend Senior -supporting_teams: - - Frontend Senior -roadmap_item: rcon-full-data -priority: high ---- - -# TASK-125 - Prefer materialized RCON recent matches - -## Goal - -Update the recent matches API to prefer materialized RCON match records over approximate competitive windows and public-scoreboard fallback. - -## Background - -End users should see correct scores as consistently as possible. RCON AdminLog `MATCH ENDED` data should be the primary source when available, with active RCON sessions next and public scoreboard only as fallback or degraded enrichment. - -## Constraints - -- No frontend changes unless strictly necessary for contract compatibility. -- Do not show stale public scoreboard as selected source when RCON is healthy. -- Do not reactivate Elo/MMR. -- Do not reintroduce Comunidad Hispana #03. -- Do not store secrets, runtime DB files or `backend/runtime`. -- Preserve RCON-first policy. - -## Allowed Changes - -- backend recent matches read model modules -- backend route tests or read-model tests -- minimal compatibility-only frontend changes if unavoidable and justified -- this task file when moving it through the workflow - -## Implementation Requirements - -- Work from a dedicated branch for this task. -- Read first: - - `AGENTS.md` - - `ai/architecture-index.md` - - `ai/repo-context.md` - - `ai/orchestrator/backend-senior.md` - - `backend/app/routes.py` - - `backend/app/rcon_historical_read_model.py` - - existing recent matches read-model/storage modules - - materialized match code from TASK-122 -- Use priority: - - materialized RCON matches with `MATCH ENDED` result - - active/partial RCON session windows with current gamestate - - public-scoreboard fallback only if RCON is unavailable or explicitly degraded -- Recent match items should expose result scores/winner when available. -- Add `result_source` values: `admin-log-match-ended`, `rcon-session`, `public-scoreboard-fallback`, `unavailable`. -- Include `match_url` only when safe external link exists. -- Include internal detail link data whenever match id and server allow it. - -## Validation Commands - -- `python -m compileall backend/app` -- `python -m pytest backend/tests/.py` -- `docker compose up -d --build backend` -- `docker compose exec backend python -m app.rcon_admin_log_ingestion --minutes 1440` -- `Invoke-WebRequest "http://localhost:8000/api/historical/recent-matches?server=all-servers&limit=10"` - -## Manual Verification Steps - -- Confirm recent matches show RCON/AdminLog scores where available. -- Confirm source priority uses AdminLog over stale public scoreboard. -- Confirm internal detail data exists for match cards. -- Confirm `/health` and `frontend/historico.html` are not broken. -- Confirm `git diff --name-only` matches the allowed scope. - -## Git Requirements - -- Create a dedicated branch for this task, for example `codex/task-125-rcon-recent-matches-priority`. -- Run relevant validation before committing. -- Stage only intended files. -- Commit the completed implementation. -- Push the branch to origin. - -## Outcome - -Updated the RCON historical recent-matches read model to prefer materialized AdminLog matches with authoritative `MATCH ENDED` results before using active/session competitive windows. Public-scoreboard recent matches remain fallback only when RCON read coverage is unavailable or empty. - -Recent match rows now include `result_source` values for the implemented paths: - -- `admin-log-match-ended` -- `rcon-session` -- `public-scoreboard-fallback` - -The payload builder no longer selects the public scoreboard merely to fill the requested limit when RCON has usable materialized/session results. Stale local historical targets such as `comunidad-hispana-03` are not re-added to configuration or shown as configured RCON targets by this batch. - -## Validation Result - -- Passed: `python -m compileall backend/app` -- Pytest was not installed in the local Python environment. -- Passed deterministic fallback: `$env:PYTHONPATH='backend'; python -m unittest backend.tests.test_rcon_materialization_pipeline backend.tests.test_scoreboard_match_links` -- Passed API recent-matches check: `Invoke-WebRequest "http://localhost:8000/api/historical/recent-matches?server=all-servers&limit=10"` returned `selected_source: rcon`, `fallback_used: false`, and materialized rows with `result_source: admin-log-match-ended`. diff --git a/ai/tasks/done/TASK-126-scoreboard-external-link-correlation-rcon-materialized.md b/ai/tasks/done/TASK-126-scoreboard-external-link-correlation-rcon-materialized.md deleted file mode 100644 index 11fb2d4..0000000 --- a/ai/tasks/done/TASK-126-scoreboard-external-link-correlation-rcon-materialized.md +++ /dev/null @@ -1,93 +0,0 @@ ---- -id: TASK-126 -title: Correlate scoreboard links with RCON materialized matches -status: done -type: backend -team: Backend Senior -supporting_teams: - - Arquitecto Python -roadmap_item: rcon-full-data -priority: medium ---- - -# TASK-126 - Correlate scoreboard links with RCON materialized matches - -## Goal - -Safely correlate materialized RCON matches with public scoreboard game URLs when a high-confidence match exists. - -## Background - -Match cards should link to the public scoreboard only when safe correlation exists. RCON remains the primary data source; public scoreboard links are optional enrichment and should never open arbitrary domains. - -## Constraints - -- No UI changes. -- Do not reactivate Elo/MMR. -- Do not reintroduce Comunidad Hispana #03. -- Do not store secrets, runtime DB files or `backend/runtime`. -- Do not treat public scoreboard as source of truth for RCON data. -- If correlation fails, internal detail links must still work. - -## Allowed Changes - -- existing scoreboard origin catalog/correlation code if present -- backend safe URL/correlation storage or cache code -- backend tests -- this task file when moving it through the workflow - -## Implementation Requirements - -- Work from a dedicated branch for this task. -- Read first: - - `AGENTS.md` - - `ai/architecture-index.md` - - `ai/repo-context.md` - - `ai/orchestrator/backend-senior.md` - - `backend/app/scoreboard_origin_catalog.py` if present - - existing scoreboard link correlation modules - - materialized match code from TASK-122 -- Correlate by server, map, end time/server time where possible, duration where possible and player count/peak players where available. -- Support known origins: - - Comunidad Hispana #01: `https://scoreboard.comunidadhll.es` - - Comunidad Hispana #02: `https://scoreboard.comunidadhll.es:5443` -- Only return external `match_url` for expected origins and `/games/` paths. -- Store or cache correlation result if appropriate. -- Include a manual check for `https://scoreboard.comunidadhll.es/games/1561515`. - -## Validation Commands - -- `python -m compileall backend/app` -- `python -m pytest backend/tests/.py` - -## Manual Verification Steps - -- Confirm safe URL allowlist rejects arbitrary domains and paths. -- Confirm #01 and #02 origin selection works. -- Confirm no server #03 is added to catalogs, defaults or tests. -- Confirm failed correlation still leaves internal detail links available. -- Confirm `git diff --name-only` matches the allowed scope. - -## Git Requirements - -- Create a dedicated branch for this task, for example `codex/task-126-rcon-scoreboard-correlation`. -- Run relevant validation before committing. -- Stage only intended files. -- Commit the completed implementation. -- Push the branch to origin. - -## Outcome - -Kept scoreboard correlation as optional enrichment over RCON-backed match data. Materialized RCON recent/detail payloads call the existing correlation path and only expose `match_url` when the persisted public scoreboard candidate belongs to the trusted origin for the active server. - -Hardened trusted scoreboard URL validation so only the known #01 and #02 origins and `/games/` paths are accepted. Arbitrary domains, wrong ports, non-game paths, credentials, query strings and fragments are rejected. Comunidad Hispana #03 was not reintroduced. - -If correlation fails, the internal materialized detail payload still works and simply returns `match_url: null`. - -## Validation Result - -- Passed: `python -m compileall backend/app` -- Pytest was not installed in the local Python environment. -- Passed deterministic fallback: `$env:PYTHONPATH='backend'; python -m unittest backend.tests.test_rcon_materialization_pipeline backend.tests.test_scoreboard_match_links` -- Passed safe URL allowlist coverage for Comunidad Hispana #01 and #02 in `backend.tests.test_rcon_materialization_pipeline`. -- Passed existing scoreboard correlation regression suite in `backend.tests.test_scoreboard_match_links`. diff --git a/ai/tasks/done/TASK-127-frontend-recent-match-link-actions.md b/ai/tasks/done/TASK-127-frontend-recent-match-link-actions.md deleted file mode 100644 index f759ae0..0000000 --- a/ai/tasks/done/TASK-127-frontend-recent-match-link-actions.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -id: TASK-127 -title: Update recent match link actions -status: done -type: frontend -team: Frontend Senior -supporting_teams: - - Experto en interfaz - - Backend Senior -roadmap_item: rcon-full-data -priority: medium ---- - -# TASK-127 - Update recent match link actions - -## Goal - -Update recent match cards so internal details and external scoreboard links are prioritized clearly and safely. - -## Background - -Recent match cards should always offer internal details when supported and only show public scoreboard links when the backend provides a safe `match_url`. RCON remains primary, and the UI must not expose stale wording or paused Elo/MVP content. - -## Constraints - -- Do not reintroduce Comunidad Hispana #03. -- Do not show paused Elo/MVP blocks. -- Do not expose public "snapshot" wording. -- Do not show broken external links. -- Do not change backend behavior unless strictly required and justified. -- Preserve HLL Vietnam tactical, sober styling. - -## Allowed Changes - -- `frontend/assets/js/historico.js` -- `frontend/assets/js/historico-recent-live.js` if needed -- minimal CSS only if needed for the action layout -- this task file when moving it through the workflow - -## Implementation Requirements - -- Work from a dedicated branch for this task. -- Read first: - - `AGENTS.md` - - `ai/architecture-index.md` - - `ai/repo-context.md` - - `ai/orchestrator/frontend-senior.md` - - `ai/orchestrator/ui-expert.md` - - `frontend/historico.html` - - `frontend/assets/js/historico.js` - - `frontend/assets/js/historico-recent-live.js` - - `frontend/assets/css/historico.css` -- Show score when result exists. -- Show `Ver detalles` internal link for every match with internal detail support. -- Show `Ver scoreboard` or `Ver partida externa` only when `match_url` exists. -- If a match has no score yet, show `En curso` or `Resultado no disponible` instead of `---` when a better status exists. -- Keep cards compatible with existing API fallback payloads. - -## Validation Commands - -- `node --check frontend/assets/js/historico.js` -- `node --check frontend/assets/js/historico-recent-live.js` if changed -- `docker compose up -d --build backend frontend` - -## Manual Verification Steps - -- Open `http://localhost:8080/historico.html`. -- Confirm scores appear where available. -- Confirm internal detail link is visible when supported. -- Confirm external scoreboard link appears only when `match_url` exists. -- Confirm there is no Elo/MVP/server #03/snapshot wording. -- Confirm `git diff --name-only` matches the allowed scope. - -## Git Requirements - -- Create a dedicated branch for this task, for example `codex/task-127-recent-match-actions`. -- Run relevant validation before committing. -- Stage only intended files. -- Commit the completed implementation. -- Push the branch to origin. - -## Outcome - -Updated recent match cards to consume materialized RCON recent-match fields. Cards now show available scores, a friendly result status/source, an internal `Ver detalles` link built from `internal_detail_match_id` or `match_id`, and an external scoreboard link only when `match_url` is present. - -The rendering keeps paused Elo/MVP blocks out of the page, does not reintroduce Comunidad Hispana #03, and avoids visible "snapshot" wording. Missing-score RCON competitive-window rows render as in-progress instead of placeholder dashes. - -## Validation Result - -- Passed: `node --check frontend/assets/js/historico.js` -- Passed: `node --check frontend/assets/js/historico-recent-live.js` -- Passed: `docker compose up -d --build backend frontend` -- Browser-verified `http://localhost:8080/historico.html`. -- Confirmed recent cards show internal detail links and materialized RCON score `3 - 2`. -- Confirmed external scoreboard links are not rendered when `match_url` is absent. -- Confirmed no visible Elo/MVP/Comunidad Hispana #03/snapshot wording appears. diff --git a/ai/tasks/done/TASK-128-build-simplified-internal-match-detail-page.md b/ai/tasks/done/TASK-128-build-simplified-internal-match-detail-page.md deleted file mode 100644 index cb92b3b..0000000 --- a/ai/tasks/done/TASK-128-build-simplified-internal-match-detail-page.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -id: TASK-128 -title: Build simplified internal match detail page -status: done -type: frontend -team: Frontend Senior -supporting_teams: - - Experto en interfaz - - Backend Senior -roadmap_item: rcon-full-data -priority: high ---- - -# TASK-128 - Build simplified internal match detail page - -## Goal - -Make `frontend/historico-partida.html` useful as a lightweight internal scoreboard-style match detail page backed by the internal RCON detail API. - -## Background - -When a safe public scoreboard link is unavailable, users should still be able to inspect the match through HLL Vietnam. The page should show summary, score, winner, factions/teams if available, player stats and a relevant event timeline without advanced charts. - -## Constraints - -- Do not add advanced charts or graphs. -- Do not expose raw player IDs unless required by an already approved API contract. -- Do not reintroduce Comunidad Hispana #03. -- Do not show paused Elo/MVP blocks. -- Do not expose public "snapshot" wording. -- Preserve HLL Vietnam styling. - -## Allowed Changes - -- `frontend/historico-partida.html` -- `frontend/assets/js/historico-partida.js` -- `frontend/assets/css/historico.css` if needed -- this task file when moving it through the workflow - -## Implementation Requirements - -- Work from a dedicated branch for this task. -- Read first: - - `AGENTS.md` - - `ai/architecture-index.md` - - `ai/repo-context.md` - - `ai/orchestrator/frontend-senior.md` - - `ai/orchestrator/ui-expert.md` - - `frontend/historico-partida.html` - - `frontend/assets/js/historico-partida.js` - - `frontend/assets/css/historico.css` - - backend match detail API code from TASK-124 -- Use the internal match detail API. -- Display map, server, result, winner, game mode, start/end time, source/confidence and external scoreboard link when available. -- Add player stats table with player, team, kills, deaths, teamkills, K/D, top weapons, most killed and death by. -- Add event/timeline section for match start, match end, kill sample/recent kills and useful team switches. -- Handle partial or missing data gracefully with controlled empty states. -- Keep implementation in vanilla JavaScript. - -## Validation Commands - -- `node --check frontend/assets/js/historico-partida.js` -- `docker compose up -d --build backend frontend` - -## Manual Verification Steps - -- Open a match detail from the recent matches list. -- Verify a match with AdminLog kill data shows at least one kill/weapon row. -- Verify a match without player stats shows a controlled empty state. -- Confirm no Elo/MVP/server #03/snapshot wording appears. -- Confirm `git diff --name-only` matches the allowed scope. - -## Git Requirements - -- Create a dedicated branch for this task, for example `codex/task-128-internal-match-detail-page`. -- Run relevant validation before committing. -- Stage only intended files. -- Commit the completed implementation. -- Push the branch to origin. - -## Outcome - -Reworked `frontend/historico-partida.html` and `frontend/assets/js/historico-partida.js` into a simplified internal scoreboard-style detail page backed by `/api/historical/matches/detail?server=...&match=...`. - -The page correctly URL-encodes materialized RCON match ids containing colons, displays match summary cards, source/confidence, optional external scoreboard action, player stats with K/D, top weapons, most-killed/death-by summaries, and timeline event counts. It handles missing player/timeline data with controlled empty states and does not expose raw player IDs. - -## Validation Result - -- Passed: `node --check frontend/assets/js/historico-partida.js` -- Passed: `docker compose up -d --build backend frontend` -- Browser-verified detail navigation from `http://localhost:8080/historico.html`. -- Browser-verified known materialized match detail renders at `http://localhost:8080/historico-partida.html?server=comunidad-hispana-02&match=comunidad-hispana-02%3A1779178461%3A1779183861%3Acarentanwarfare`. -- Confirmed AntonioPruna renders with 1 kill, 0 deaths and `M1 GARAND`. -- Confirmed the victim row renders 1 death and `death_by` AntonioPruna. -- Confirmed timeline/event counts render. -- Confirmed no visible Elo/MVP/Comunidad Hispana #03/snapshot wording appears. diff --git a/ai/tasks/done/TASK-129-parse-materialize-player-profile-message-blocks.md b/ai/tasks/done/TASK-129-parse-materialize-player-profile-message-blocks.md deleted file mode 100644 index 020497e..0000000 --- a/ai/tasks/done/TASK-129-parse-materialize-player-profile-message-blocks.md +++ /dev/null @@ -1,85 +0,0 @@ ---- -id: TASK-129 -title: Parse and materialize player profile MESSAGE blocks -status: done -type: backend -team: Backend Senior -supporting_teams: - - Arquitecto de Base de Datos - - Arquitecto Python -roadmap_item: rcon-full-data -priority: medium ---- - -# TASK-129 - Parse and materialize player profile MESSAGE blocks - -## Goal - -Extract useful long-term player profile snapshots from RCON AdminLog `MESSAGE` blocks generated by the server bot. - -## Background - -Observed AdminLog `MESSAGE` blocks can include profile-like stats such as first seen, sessions, matches played, play time, sanctions, averages, kills, deaths, teamkills, K/D, victims, nemesis and favorite weapons. These are profile snapshots, not authoritative per-match stats. - -## Constraints - -- Do not use profile snapshots as authoritative per-match stats. -- No frontend changes unless adding backend API contract tests requires fixtures. -- Do not reactivate Elo/MMR. -- Do not reintroduce Comunidad Hispana #03. -- Do not store secrets, runtime DB files or `backend/runtime`. -- Do not expose raw full `MESSAGE` content through public APIs by default. - -## Allowed Changes - -- backend parser/materialization/storage code for profile snapshots -- backend tests with anonymized examples -- this task file when moving it through the workflow - -## Implementation Requirements - -- Work from a dedicated branch for this task. -- Read first: - - `AGENTS.md` - - `ai/architecture-index.md` - - `ai/repo-context.md` - - `ai/orchestrator/backend-senior.md` - - `ai/orchestrator/database-architect.md` - - `backend/app/rcon_admin_log_parser.py` - - `backend/app/rcon_admin_log_storage.py` - - existing AdminLog ingestion/materialization tests -- Add a parser for profile-like `MESSAGE` content only. -- Store extracted snapshots in a table such as `rcon_player_profile_snapshots`. -- Include fields for target, player id/name, source server time, event timestamp, sessions, matches played, total kills/deaths, teamkills done/received, K/D, favorite weapons JSON, victims JSON, nemesis JSON, averages JSON, sanctions JSON and raw content. -- Deduplicate by `target_key + player_id + source_server_time`. -- Validate Spanish labels including `bajas`, `muertes`, `Víctimas`, `Némesis`, `Armas favoritas`, `Promedios` and `Sanciones`. - -## Validation Commands - -- `python -m compileall backend/app` -- `python -m pytest backend/tests/.py` - -## Manual Verification Steps - -- Confirm tests use anonymized MESSAGE examples. -- Confirm non-profile `MESSAGE` entries are ignored. -- Confirm duplicate snapshots are not inserted twice. -- Confirm `/health` still works. -- Confirm `git diff --name-only` matches the allowed scope. - -## Git Requirements - -- Create a dedicated branch for this task, for example `codex/task-129-profile-message-snapshots`. -- Run relevant validation before committing. -- Stage only intended files. -- Commit the completed implementation. -- Push the branch to origin. - -## Outcome - -- Added profile MESSAGE parsing for anonymized long-term player snapshot fields. -- Added `rcon_player_profile_snapshots` storage with idempotent upsert by target, player id and source server time. -- Verified non-profile MESSAGE entries are ignored. -- Validation: `python -m compileall backend/app` passed. -- Validation blocked: `python -m pytest backend/tests/test_rcon_admin_log_parser.py backend/tests/test_rcon_admin_log_storage.py` could not run because `pytest` is not installed in this environment. -- Supplemental check: direct Python execution of the new parser/storage checks passed. diff --git a/ai/tasks/done/TASK-130-add-player-profile-enrichment-api.md b/ai/tasks/done/TASK-130-add-player-profile-enrichment-api.md deleted file mode 100644 index 286be56..0000000 --- a/ai/tasks/done/TASK-130-add-player-profile-enrichment-api.md +++ /dev/null @@ -1,83 +0,0 @@ ---- -id: TASK-130 -title: Add player profile enrichment API -status: done -type: backend -team: Backend Senior -supporting_teams: - - Arquitecto Python -roadmap_item: rcon-full-data -priority: medium ---- - -# TASK-130 - Add player profile enrichment API - -## Goal - -Expose optional player profile summaries from RCON profile snapshots for future UI use without coupling them to per-match stats. - -## Background - -Profile MESSAGE snapshots can enrich player rows later, but they are historical profile snapshots rather than authoritative match facts. The API should expose safe display summaries and remain resilient when no snapshot exists. - -## Constraints - -- No mandatory frontend changes. -- Do not return raw full `MESSAGE` content by default. -- Do not make match detail fail if no profile snapshot exists. -- Do not reactivate Elo/MMR. -- Do not reintroduce Comunidad Hispana #03. -- Do not store secrets, runtime DB files or `backend/runtime`. - -## Allowed Changes - -- backend read model/route code for profile enrichment -- API tests -- this task file when moving it through the workflow - -## Implementation Requirements - -- Work from a dedicated branch for this task. -- Read first: - - `AGENTS.md` - - `ai/architecture-index.md` - - `ai/repo-context.md` - - `ai/orchestrator/backend-senior.md` - - `backend/app/routes.py` - - profile snapshot code from TASK-129 - - match detail API code from TASK-124 -- Add a backend read-model endpoint or include optional `profile_summary` in match detail player rows if available. -- Return only safe display data. -- Keep no-data behavior empty or omitted, not failing. -- Keep implementation deterministic and testable offline where possible. - -## Validation Commands - -- `python -m compileall backend/app` -- `python -m pytest backend/tests/.py` - -## Manual Verification Steps - -- Make a manual request against a known stored profile snapshot. -- Confirm missing snapshots do not break match detail or profile responses. -- Confirm raw full MESSAGE content is absent by default. -- Confirm `/health` still works. -- Confirm `git diff --name-only` matches the allowed scope. - -## Git Requirements - -- Create a dedicated branch for this task, for example `codex/task-130-profile-enrichment-api`. -- Run relevant validation before committing. -- Stage only intended files. -- Commit the completed implementation. -- Push the branch to origin. - -## Outcome - -- Added safe latest profile summaries for stored RCON profile snapshots. -- Enriched materialized RCON match detail player rows with optional `profile_summary` when a snapshot exists. -- Kept raw full `MESSAGE` content and player ids out of the public match-detail row. -- Missing snapshots remain omitted and do not break match detail. -- Validation: `python -m compileall backend/app` passed. -- Validation: `$env:PYTHONPATH='backend'; python -m unittest backend.tests.test_rcon_materialization_pipeline` passed. -- Validation blocked: `python -m pytest backend/tests/test_rcon_materialization_pipeline.py` could not run because `pytest` is not installed in this environment. diff --git a/ai/tasks/done/TASK-131-add-rcon-data-pipeline-validation-script.md b/ai/tasks/done/TASK-131-add-rcon-data-pipeline-validation-script.md deleted file mode 100644 index 47598ea..0000000 --- a/ai/tasks/done/TASK-131-add-rcon-data-pipeline-validation-script.md +++ /dev/null @@ -1,85 +0,0 @@ ---- -id: TASK-131 -title: Add RCON data pipeline validation script -status: done -type: platform -team: Backend Senior -supporting_teams: - - Arquitecto Python - - Frontend Senior -roadmap_item: rcon-full-data -priority: medium ---- - -# TASK-131 - Add RCON data pipeline validation script - -## Goal - -Add one lightweight validation script for the full RCON data pipeline. - -## Background - -The RCON data pipeline now spans parsing, storage, AdminLog ingestion, materialized matches, player stats and backend APIs. A focused script should help implementation workers and reviewers validate the pipeline without requiring real RCON for unit tests. - -## Constraints - -- Do not require real RCON for unit tests. -- Do not modify Docker behavior. -- Do not reactivate Elo/MMR. -- Do not reintroduce Comunidad Hispana #03. -- Do not store secrets, runtime DB files or `backend/runtime`. -- Document when real RCON or Docker smoke checks are skipped. - -## Allowed Changes - -- `scripts/run-rcon-data-pipeline-tests.ps1` -- possibly `scripts/run-integration-tests.ps1` only if wiring the new script is appropriate and low risk -- documentation only if needed for the new command -- this task file when moving it through the workflow - -## Implementation Requirements - -- Work from a dedicated branch for this task. -- Read first: - - `AGENTS.md` - - `ai/architecture-index.md` - - `ai/repo-context.md` - - `ai/orchestrator/backend-senior.md` - - `scripts/run-integration-tests.ps1` - - existing backend tests for AdminLog/parser/materialization -- Add `scripts/run-rcon-data-pipeline-tests.ps1`. -- Validate Python compile. -- Run parser tests. -- Run storage/materialization tests. -- Include optional backend endpoint smoke checks if Docker is already running. -- Skip real RCON-dependent checks gracefully with a clear message. - -## Validation Commands - -- `powershell -ExecutionPolicy Bypass -File scripts/run-rcon-data-pipeline-tests.ps1` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` - -## Manual Verification Steps - -- Confirm the script can run without real RCON credentials. -- Confirm skipped Docker/RCON smoke checks explain why they were skipped. -- Confirm existing integration script still passes. -- Confirm no product behavior changed. -- Confirm `git diff --name-only` matches the allowed scope. - -## Git Requirements - -- Create a dedicated branch for this task, for example `codex/task-131-rcon-pipeline-validation`. -- Run relevant validation before committing. -- Stage only intended files. -- Commit the completed implementation. -- Push the branch to origin. - -## Outcome - -- Added `scripts/run-rcon-data-pipeline-tests.ps1`. -- The script compiles backend modules, runs RCON parser/storage/materialization/link checks without real RCON credentials, and performs an optional backend health smoke check only when Docker Compose already has `backend` running. -- The script prefers `pytest` when available and falls back to deterministic offline checks plus unittest suites when `pytest` is absent. -- Validation: `powershell -ExecutionPolicy Bypass -File scripts/run-rcon-data-pipeline-tests.ps1` passed. -- Validation: `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` returned exit code 0, but its nested historical UI regression check emitted an existing frontend assertion about the missing recent-match external action label. No frontend files were changed in this platform task. -- Real RCON checks were skipped by design because the script must run without RCON credentials. diff --git a/ai/tasks/done/TASK-132-document-rcon-first-historical-architecture.md b/ai/tasks/done/TASK-132-document-rcon-first-historical-architecture.md deleted file mode 100644 index e0ce7c0..0000000 --- a/ai/tasks/done/TASK-132-document-rcon-first-historical-architecture.md +++ /dev/null @@ -1,93 +0,0 @@ ---- -id: TASK-132 -title: Document RCON-first historical architecture -status: done -type: documentation -team: PM -supporting_teams: - - Backend Senior - - Arquitecto Python -roadmap_item: rcon-full-data -priority: medium ---- - -# TASK-132 - Document RCON-first historical architecture - -## Goal - -Document the new RCON-first historical architecture and update AI context so future tasks preserve the intended data-source policy. - -## Background - -HLL Vietnam is building a historical/live data platform for Comunidad Hispana servers with RCON as the primary source. AdminLog ingestion, parsing, event storage, materialized matches/player stats and optional public-scoreboard enrichment should be documented clearly for future workers. - -## Constraints - -- Documentation-only task. -- Do not change product behavior. -- Do not modify backend/frontend/Docker code. -- Do not reactivate Elo/MMR. -- Do not reintroduce Comunidad Hispana #03. -- Do not store secrets, runtime DB files or `backend/runtime`. -- Public scoreboard must be described only as optional enrichment/link source or fallback. - -## Allowed Changes - -- `README.md` or backend README/docs as appropriate -- `docs/decisions.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- this task file when moving it through the workflow - -## Implementation Requirements - -- Work from a dedicated branch for this task. -- Read first: - - `AGENTS.md` - - `ai/architecture-index.md` - - `ai/repo-context.md` - - `ai/orchestrator/pm.md` - - `ai/orchestrator/backend-senior.md` - - `README.md` - - `backend/README.md` - - `docs/decisions.md` -- Document: - - RCON session capture - - AdminLog ingestion - - AdminLog parser - - event storage - - materialized matches/player stats - - public scoreboard only as optional enrichment/link source or fallback - - Elo/MMR paused - - Comunidad Hispana #03 disabled -- Include manual commands: - - `docker compose exec backend python -m app.rcon_admin_log_ingestion --minutes 1440` - - `docker compose exec backend python -m app.rcon_historical_worker capture` -- Keep wording repository-specific and avoid generic platform-template replacement. - -## Validation Commands - -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` - -## Manual Verification Steps - -- Review docs for no secrets or credentials. -- Confirm docs consistently preserve RCON-first policy. -- Confirm Elo/MMR remains documented as paused. -- Confirm Comunidad Hispana #03 remains documented as disabled from defaults. -- Confirm `git diff --name-only` matches the allowed scope. - -## Git Requirements - -- Create a dedicated branch for this task, for example `codex/task-132-rcon-architecture-docs`. -- Run relevant validation before committing. -- Stage only intended files. -- Commit the completed implementation. -- Push the branch to origin. - -## Outcome - -- Documented the RCON-first historical architecture in README, backend README, decisions and AI context. -- Covered RCON session capture, AdminLog ingestion/parser/storage, materialized matches/player stats, profile snapshot enrichment, public-scoreboard fallback boundaries, Elo/MMR paused state and Comunidad Hispana #03 disabled defaults. -- Added the requested manual Docker commands for AdminLog ingestion and historical capture. -- Validation: `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` returned exit code 0, but its nested historical UI regression check emitted an existing frontend assertion about the missing recent-match external action label. No frontend/backend behavior files were changed in this documentation-only task. diff --git a/ai/tasks/done/TASK-133-polish-rcon-match-detail-timestamps-and-labels.md b/ai/tasks/done/TASK-133-polish-rcon-match-detail-timestamps-and-labels.md deleted file mode 100644 index ad2e1f5..0000000 --- a/ai/tasks/done/TASK-133-polish-rcon-match-detail-timestamps-and-labels.md +++ /dev/null @@ -1,151 +0,0 @@ ---- -id: TASK-133 -title: Polish RCON match detail timestamps and labels -status: done -type: frontend -team: Frontend Senior -supporting_teams: - - Backend Senior - - Arquitecto Python -roadmap_item: rcon-full-data -priority: medium ---- - -# TASK-133 - Polish RCON Match Detail Timestamps And Labels - -## Goal - -Fix the small but confusing presentation issues in the internal match detail page for materialized RCON matches: misleading equal start/end timestamps, a raw technical match id in the main header, and overly technical visible labels. - -## Background - -HLL Vietnam now has a RCON-first materialized match pipeline. AdminLog events are parsed, stored, deduplicated and materialized; recent matches prefer materialized RCON AdminLog results; and the internal match detail page renders simplified scoreboard-style data. - -The known detail URL works: - -- `historico-partida.html?server=comunidad-hispana-02&match=comunidad-hispana-02%3A1779178461%3A1779183861%3Acarentanwarfare` - -The current page shows the expected match content, including map, server, score, winner, duration, player stats, weapons, victim/death_by rows and event counts. However, the page currently shows identical `Inicio` and `Fin` timestamps even when `duration_seconds` is correct, and the main header exposes the internal match id. - -## Constraints - -- Keep the change small and focused. -- Preserve RCON as the source of truth. -- Prefer backend/read-model correctness where possible. -- Do not change the data model more than necessary. -- Do not reactivate Elo/MMR. -- Do not touch Elo/MVP blocks. -- Do not reintroduce Comunidad Hispana #03. -- Do not show `snapshot` wording. -- Do not implement charts. -- Do not break recent match cards. -- Do not break match detail. -- Keep public scoreboard optional enrichment/fallback only. -- Preserve frontend compatibility with direct browser opening where applicable. - -## Allowed Changes - -- Backend read-model/API code needed to avoid misleading match timestamps or expose timestamp confidence. -- Frontend match detail code needed to render safer timestamp states and friendlier labels. -- Recent-match frontend code only if needed to preserve existing cards after read-model changes. -- This task file when moving it through the workflow. - -## Files to Read First - -- `AGENTS.md` -- `ai/architecture-index.md` -- `ai/repo-context.md` -- `ai/orchestrator/frontend-senior.md` -- `ai/orchestrator/backend-senior.md` -- `frontend/historico-partida.html` -- `frontend/assets/js/historico-partida.js` -- `frontend/assets/js/historico-recent-live.js` -- relevant backend historical/read-model modules serving recent matches and match detail - -## Implementation Requirements - -1. Work from a dedicated branch: `codex/task-133-polish-rcon-match-detail`. -2. Inspect the existing materialized RCON match detail response and frontend rendering before changing behavior. -3. Fix or gracefully handle misleading identical `started_at` / `ended_at` values for materialized RCON matches. -4. Prefer deriving sensible backend/read-model values from reliable `server_time` range and `duration_seconds` when possible. -5. If real absolute timestamps cannot be reliably reconstructed, expose and/or use timestamp confidence so the UI shows a controlled partial state such as `No disponible` or `Estimado`, instead of equal start/end times. -6. Keep `duration_seconds` visible because the duration is reliable from the server_time range. -7. Update the match detail hero/header so it no longer displays the raw technical match id as the main subtitle. -8. Replace the raw id with a user-friendly subtitle such as `Comunidad Hispana #02 - Partida RCON materializada`, or an equivalent Spanish label. -9. Optionally expose the technical match id in a small debug/technical section only if useful and visually secondary. -10. Polish visible labels around source, basis and confidence so they are consistent and understandable for end users. -11. Polish RCON materialized wording, including labels like `cierre de partida RCON` and `Registro RCON materializado`, without exposing implementation terms too prominently. -12. Ensure recent match cards still work after any backend/read-model adjustment. -13. Ensure the known Carentan match detail still renders. -14. Ensure AntonioPruna still renders with 1 kill, 0 deaths and `M1 GARAND`. -15. Ensure the victim row still shows 1 death and `death_by` AntonioPruna. - -## Validation Commands - -- `python -m compileall backend/app` -- `node --check frontend/assets/js/historico.js` -- `node --check frontend/assets/js/historico-partida.js` -- `node --check frontend/assets/js/historico-recent-live.js` -- `docker compose up -d --build backend frontend` -- `Invoke-WebRequest "http://localhost:8000/health" | Select-Object -ExpandProperty Content` -- `Invoke-WebRequest "http://localhost:8000/api/historical/recent-matches?server=all-servers&limit=10" | Select-Object -ExpandProperty Content` - -Use encoded match id: - -- `comunidad-hispana-02%3A1779178461%3A1779183861%3Acarentanwarfare` - -Open: - -- `http://localhost:8080/historico-partida.html?server=comunidad-hispana-02&match=comunidad-hispana-02%3A1779178461%3A1779183861%3Acarentanwarfare` - -## Manual Verification Steps - -- Detail page no longer shows the raw technical match id in the hero/header. -- Start/end values are not misleading. -- If exact timestamps are unavailable, the UI says `No disponible` or `Estimado`. -- Duration remains visible as `1 h 30 min`. -- Score remains `3 - 2`. -- Winner remains `Aliados`. -- AntonioPruna still shows 1 kill, 0 deaths and `M1 GARAND`. -- Victim row still shows 1 death and `death_by` AntonioPruna. -- Recent match cards still render. -- No `snapshot` wording appears. -- No Elo/MVP blocks appear. -- No server #03 appears. -- `git diff --name-only` matches the scoped implementation. - -## Git Requirements - -- Create a dedicated branch: `codex/task-133-polish-rcon-match-detail`. -- Run all validation listed above. -- Stage only intended files. -- Commit the completed implementation. -- Push the branch to origin. -- Final git status must be clean. - -## Outcome - -- Added `timestamp_confidence` for materialized RCON read-model rows. -- When materialized AdminLog start/end absolute timestamps are identical while server-time duration is positive, the read model exposes `started_at`/`ended_at` as unavailable and keeps `closed_at` only for ordering/recent-card continuity. -- The detail UI now hides the raw technical match id from the hero subtitle and shows a friendly RCON materialized subtitle. -- The detail UI shows unreliable start/end values as `No disponible` while preserving reliable duration. -- Polished source/action wording, including `cierre RCON confirmado` and `Abrir en scoreboard`. -- Kept recent match cards rendering and restored the static `Ver partida` external-action label expected by the UI regression check. -- Browser plugin note: Browser was available, but the required browser-control execution tool was not exposed in this session; Playwright fallback via `npx` was blocked by npm certificate verification. Rendered validation used local headless Chrome instead. -- Validation passed: `python -m compileall backend/app`. -- Validation passed: `node --check frontend/assets/js/historico.js`. -- Validation passed: `node --check frontend/assets/js/historico-partida.js`. -- Validation passed: `node --check frontend/assets/js/historico-recent-live.js`. -- Validation passed: `$env:PYTHONPATH='backend'; python -m unittest backend.tests.test_rcon_materialization_pipeline`. -- Validation blocked: `python -m pytest backend/tests/test_rcon_materialization_pipeline.py` because `pytest` is not installed. -- Validation passed: `docker compose up -d --build backend frontend`. -- Validation passed: `/health` and `/api/historical/recent-matches?server=all-servers&limit=10`. -- Manual/API verification passed for known Carentan match: duration `5400`, score `3 - 2`, winner `allied`, AntonioPruna `1/0` with `M1 GARAND`, victim death_by AntonioPruna. -- Rendered Chrome validation passed for detail and recent pages at desktop/mobile screenshot sizes; visible text contains no `snapshot`, Elo/MMR block or Comunidad Hispana #03. -- Operational note: an already-running advanced `rcon-historical-worker` caused transient SQLite open errors during Docker validation; it was stopped because the default deployment for this repo is `backend` + `frontend`. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-135-fix-rcon-match-detail-faction-assets.md b/ai/tasks/done/TASK-135-fix-rcon-match-detail-faction-assets.md deleted file mode 100644 index eb2e2e4..0000000 --- a/ai/tasks/done/TASK-135-fix-rcon-match-detail-faction-assets.md +++ /dev/null @@ -1,165 +0,0 @@ ---- -id: TASK-135 -title: Fix RCON match detail faction assets and icon display -status: done -type: frontend -team: Frontend Senior -supporting_teams: - - Experto en interfaz -roadmap_item: rcon-full-data -priority: high ---- - -# TASK-135 - Fix RCON Match Detail Faction Assets And Icon Display - -## Goal - -Polish faction presentation in the historical RCON match detail scoreboard so faction icons load reliably, are visibly larger, and no longer show long descriptive faction subtitles. - -## Context - -The historical match detail page already renders a RCON/materialized match detail view with a scoreboard-like result block, player table, local faction image paths, and local map/faction assets being added by the user. - -The current direction is acceptable, especially the central result with score, map, Warfare and winner. Remaining rough details are visual and asset-related: - -- German/Eje icon is not visible, likely due to wrong asset path or name. -- Faction icons are too small. -- Faction subtitles such as `Fuerzas estadounidenses` and `Ejército alemán` should be removed. -- Event timeline must remain hidden. -- Confidence/source/base must remain hidden. -- No `snapshot` wording. -- No Elo/MVP blocks. -- No Comunidad Hispana #03. - -## Files to Read First - -- `AGENTS.md` -- `ai/architecture-index.md` -- `ai/repo-context.md` -- `ai/orchestrator/frontend-senior.md` -- `frontend/historico-partida.html` -- `frontend/assets/js/historico-partida.js` -- relevant CSS used by `historico-partida.html` - -## Expected Files to Modify - -- `frontend/assets/js/historico-partida.js` -- relevant CSS used by `historico-partida.html` -- this task file when moving it from `ai/tasks/pending` to `ai/tasks/done` - -If additional files are necessary, document why in the task outcome. - -## Implementation Requirements - -1. Work from a dedicated branch: `codex/task-135-faction-assets`. -2. Verify faction assets exist in `frontend/assets/img/factions`. -3. Use `.webp` paths, not `.svg`, for faction icons: - - `frontend/assets/img/factions/us.webp` - - `frontend/assets/img/factions/germany.webp` - - `frontend/assets/img/factions/soviets.webp` - - `frontend/assets/img/factions/britain.webp` -4. Fix the German/Eje icon not displaying. -5. Add graceful fallback if any faction image is missing. -6. Increase faction icon size in the scoreboard layout. -7. Remove long faction subtitle text such as: - - `Fuerzas estadounidenses` - - `Ejército alemán` - - `Fuerzas británicas` - - `Ejército soviético` -8. Keep only main side/faction labels: - - `Aliados` - - `Eje` - - `Soviéticos`, `Británicos` or `USA` only if needed -9. Do not show long descriptive subtitles under faction labels. -10. Keep the winner marker if it remains visually subtle. -11. Preserve the player table. -12. Keep the event timeline hidden. -13. Keep confidence/source/base hidden. -14. Do not add implementation/debug text to the UI. - -## Constraints - -- Keep the change small and focused. -- Preserve the dark HLL Vietnam visual identity. -- Do not introduce frameworks or dependencies. -- Do not modify backend behavior unless a minimal fallback contract issue is discovered and documented. -- Do not modify unrelated files. -- Do not reintroduce event timeline, confidence/source/base cards, `snapshot` wording, Elo/MVP blocks or Comunidad Hispana #03. - -## Validation Commands - -Run the relevant checks before marking this task done: - -- `node --check frontend/assets/js/historico-partida.js` -- `node --check frontend/assets/js/historico.js` -- `node --check frontend/assets/js/historico-recent-live.js` -- `python -m compileall backend/app` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- `powershell -ExecutionPolicy Bypass -File scripts/run-rcon-data-pipeline-tests.ps1` -- `docker compose up -d --build backend frontend` -- `Invoke-WebRequest "http://localhost:8000/health" | Select-Object -ExpandProperty Content` -- `Invoke-WebRequest "http://localhost:8000/api/historical/recent-matches?server=all-servers&limit=10" | Select-Object -ExpandProperty Content` - -## Manual Verification - -Open: - -- `http://localhost:8080/historico.html` -- `http://localhost:8080/historico-partida.html?server=comunidad-hispana-02&match=comunidad-hispana-02%3A1779178461%3A1779183861%3Acarentanwarfare` - -Then hard refresh with `Ctrl+F5` and verify: - -- Score remains `3 : 2`. -- Winner remains `Aliados`. -- Map remains `Carentan`. -- Duration remains `1 h 30 min`. -- German/Eje icon is visible. -- Faction icons are larger than before. -- Long faction descriptions are gone. -- AntonioPruna still shows 1 kill, 0 deaths, `M1 GARAND`. -- Victim row still shows `death_by` AntonioPruna. -- No timeline/events section is visible. -- No confidence/source/base cards are visible. -- No `snapshot`, Elo/MVP block or Comunidad Hispana #03 appears. - -## Git Requirements - -- Use branch `codex/task-135-faction-assets`. -- Move only this task from `ai/tasks/pending` to `ai/tasks/done` when complete. -- Add `Outcome` and `Validation Result` sections before completing the task. -- Stage only intended files. -- Commit and push the branch. -- Final git status must be clean. - -## Outcome - -- Updated `frontend/assets/js/historico-partida.js` to use the required local `.webp` faction paths for USA, Germany, Soviets and Britain. -- Renamed the user-provided faction assets in `frontend/assets/img/factions/` from short names to the required contract names: `germany.webp`, `soviets.webp` and `britain.webp`. -- Removed visible long faction subtitles from the scoreboard side blocks while preserving the main `Aliados` and `Eje` labels and the subtle winner marker. -- Increased faction emblem sizing in `frontend/assets/css/historico-scoreboard-detail.css` and added a silent missing-image fallback class so a broken image does not show a visible broken icon. -- Event timeline, confidence/source/base cards, snapshot wording, Elo/MVP blocks and Comunidad Hispana #03 were not reintroduced. - -## Validation Result - -- PASS: `node --check frontend/assets/js/historico-partida.js` -- PASS: `node --check frontend/assets/js/historico.js` -- PASS: `node --check frontend/assets/js/historico-recent-live.js` -- PASS: `python -m compileall backend/app` -- PASS: `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- PASS: `powershell -ExecutionPolicy Bypass -File scripts/run-rcon-data-pipeline-tests.ps1` - - Note: the script completed successfully but emitted existing `ResourceWarning` messages from backend unittest sqlite connections. -- PASS: `docker compose up -d --build backend frontend` -- PASS: `Invoke-WebRequest "http://localhost:8000/health" | Select-Object -ExpandProperty Content` -- PASS after stopping already-running advanced historical workers: `Invoke-WebRequest "http://localhost:8000/api/historical/recent-matches?server=all-servers&limit=10" | Select-Object -ExpandProperty Content` - - The first attempt failed because the backend could not set SQLite journal mode while the historical worker services were active against the mounted DB. `docker compose stop historical-runner rcon-historical-worker` cleared the validation conflict. -- Manual/rendered verification: Browser plugin was listed, but the required Node runtime tool was not exposed in this session; used local Chrome headless fallback. - - Verified DOM contains `3 : 2`, `Ganador: Aliados`, `Carentan`, `1 h 30 min`, `AntonioPruna`, `M1 GARAND`, `us.webp` and `germany.webp`. - - Verified long faction descriptions are absent from rendered DOM. - - Verified timeline section remains hidden. - - Captured desktop and mobile screenshots outside the repository at `C:\Temp\task-135-match-detail.png` and `C:\Temp\task-135-match-detail-mobile.png`. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split follow-up work into separate tasks if scope grows. diff --git a/ai/tasks/done/TASK-136-add-rcon-match-detail-map-hero-image.md b/ai/tasks/done/TASK-136-add-rcon-match-detail-map-hero-image.md deleted file mode 100644 index ae6ce2e..0000000 --- a/ai/tasks/done/TASK-136-add-rcon-match-detail-map-hero-image.md +++ /dev/null @@ -1,168 +0,0 @@ ---- -id: TASK-136 -title: Add RCON match detail map hero image -status: done -type: frontend -team: Frontend Senior -supporting_teams: - - Experto en interfaz - - Disenador grafico -roadmap_item: rcon-full-data -priority: high ---- - -# TASK-136 - Add RCON Match Detail Map Hero Image - -## Goal - -Add local map image support to the historical RCON match detail page and show the current match map image prominently in the top hero/header area. - -## Context - -The historical match detail page currently shows the central result data well enough, but the top hero/header area should include the match map image, preferably on the right side. The community logo can stay where it is or be reduced if needed, but the map image should become a clear first-viewport visual element. - -For the known Carentan match, the UI must map the displayed map to: - -- `frontend/assets/img/maps/carentan-day.webp` - -The implementation should use local map assets under `frontend/assets/img/maps` and hide the image area gracefully when no asset is available. - -## Files to Read First - -- `AGENTS.md` -- `ai/architecture-index.md` -- `ai/repo-context.md` -- `ai/orchestrator/frontend-senior.md` -- `frontend/historico-partida.html` -- `frontend/assets/js/historico-partida.js` -- relevant CSS used by `historico-partida.html` - -## Expected Files to Modify - -- `frontend/historico-partida.html` -- `frontend/assets/js/historico-partida.js` -- relevant CSS used by `historico-partida.html` -- this task file when moving it from `ai/tasks/pending` to `ai/tasks/done` - -If additional files are necessary, document why in the task outcome. - -## Implementation Requirements - -1. Work from a dedicated branch: `codex/task-136-map-hero-image`. -2. Add map image support on `historico-partida.html` / `historico-partida.js`. -3. Display the current map image in the top hero/header area, preferably on the right side. -4. Keep the community logo where it is or reduce it if needed, while adding a prominent map image to the right. -5. Use map assets from `frontend/assets/img/maps`. -6. Add a robust JavaScript mapper from map name / `pretty_name` to asset path. -7. For the known Carentan match, map to `frontend/assets/img/maps/carentan-day.webp`. -8. Account for likely available asset names: - - `carentan-day.webp` - - `stmereeglise-day.webp` - - `stmariedumont-day.webp` - - `utahbeach-day.webp` - - `omahabeach-day.webp` - - `purpleheartlane-rain.webp` - - `hurtgenforest-day.webp` - - `foy-day.webp` - - `kursk-day.webp` - - `kharkov-day.webp` - - `driel-day.webp` - - `elalamein-day.webp` - - `tobruk-day.webp` - - `tobruk-dawn.webp` - - `mortain-day.webp` - - `hill400-day.webp` - - `elsenbornridge-day.webp` - - `smolensk-day.webp` -9. If no map image is found, hide the image area gracefully. -10. Keep the layout responsive. -11. Do not show implementation/debug text in the UI. -12. Preserve the player table. -13. Keep event timeline hidden. -14. Keep confidence/source/base hidden. - -## Constraints - -- Keep the change small and focused. -- Preserve the dark HLL Vietnam visual identity. -- Do not introduce frameworks or dependencies. -- Do not modify backend unless a minimal API field issue is strictly necessary and documented. -- Do not modify unrelated files. -- Do not show `snapshot` wording, Elo/MVP blocks or Comunidad Hispana #03. - -## Validation Commands - -Run the relevant checks before marking this task done: - -- `node --check frontend/assets/js/historico-partida.js` -- `node --check frontend/assets/js/historico.js` -- `node --check frontend/assets/js/historico-recent-live.js` -- `python -m compileall backend/app` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- `powershell -ExecutionPolicy Bypass -File scripts/run-rcon-data-pipeline-tests.ps1` -- `docker compose up -d --build backend frontend` -- `Invoke-WebRequest "http://localhost:8000/health" | Select-Object -ExpandProperty Content` -- `Invoke-WebRequest "http://localhost:8000/api/historical/recent-matches?server=all-servers&limit=10" | Select-Object -ExpandProperty Content` - -## Manual Verification - -Open: - -- `http://localhost:8080/historico.html` -- `http://localhost:8080/historico-partida.html?server=comunidad-hispana-02&match=comunidad-hispana-02%3A1779178461%3A1779183861%3Acarentanwarfare` - -Then hard refresh with `Ctrl+F5` and verify: - -- Score remains `3 : 2`. -- Winner remains `Aliados`. -- Map remains `Carentan`. -- Duration remains `1 h 30 min`. -- Map image appears in the hero/right area. -- For the known Carentan match, the image uses `frontend/assets/img/maps/carentan-day.webp`. -- Layout remains responsive on desktop and mobile. -- AntonioPruna still shows 1 kill, 0 deaths, `M1 GARAND`. -- Victim row still shows `death_by` AntonioPruna. -- No implementation/debug text appears. -- No timeline/events section is visible. -- No confidence/source/base cards are visible. -- No `snapshot`, Elo/MVP block or Comunidad Hispana #03 appears. - -## Git Requirements - -- Use branch `codex/task-136-map-hero-image`. -- Move only this task from `ai/tasks/pending` to `ai/tasks/done` when complete. -- Add `Outcome` and `Validation Result` sections before completing the task. -- Stage only intended files. -- Commit and push the branch. -- Final git status must be clean. - -## Outcome - -- Added a hidden map-media slot to `frontend/historico-partida.html` and reveal it only when the current match resolves to a known local map asset. -- Added `resolveMapImagePath` in `frontend/assets/js/historico-partida.js`, mapping the available local map names including the known Carentan match to `./assets/img/maps/carentan-day.webp`. -- Added the map assets under `frontend/assets/img/maps/` because the task explicitly depends on local map image files. -- Updated the historical hero CSS so the logo, match copy and map image form a responsive desktop header and collapse cleanly on mobile. -- Shortened the RCON hero subtitle to keep the narrow mobile header from clipping while preserving the player table, hidden timeline, hidden confidence/source/base details and existing scoreboard data. - -## Validation Result - -- PASS: `node --check frontend/assets/js/historico-partida.js` -- PASS: `node --check frontend/assets/js/historico.js` -- PASS: `node --check frontend/assets/js/historico-recent-live.js` -- PASS: `python -m compileall backend/app` -- PASS: `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- PASS: `powershell -ExecutionPolicy Bypass -File scripts/run-rcon-data-pipeline-tests.ps1` - - Note: the script completed successfully but emitted existing `ResourceWarning` messages from backend unittest sqlite connections. -- PASS: `docker compose up -d --build backend frontend` -- PASS: `Invoke-WebRequest "http://localhost:8000/health" | Select-Object -ExpandProperty Content` -- PASS: `Invoke-WebRequest "http://localhost:8000/api/historical/recent-matches?server=all-servers&limit=10" | Select-Object -ExpandProperty Content` -- Manual/rendered verification: Browser plugin was listed, but the required Node runtime tool was not exposed in this session; used local Chrome headless fallback. - - Verified rendered DOM contains `./assets/img/maps/carentan-day.webp`, `3 : 2`, `Ganador: Aliados`, `Carentan`, `1 h 30 min`, `AntonioPruna` and `M1 GARAND`. - - Verified timeline section remains hidden and no `snapshot`, Elo/MVP block or Comunidad Hispana #03 appeared in the rendered checks. - - Captured screenshots outside the repository at `C:\Temp\task-136-match-detail-final.png` and `C:\Temp\task-136-match-detail-mobile-final-3.png`. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split follow-up work into separate tasks if scope grows. diff --git a/ai/tasks/done/TASK-137-add-public-scoreboard-link-to-match-detail.md b/ai/tasks/done/TASK-137-add-public-scoreboard-link-to-match-detail.md deleted file mode 100644 index 24194f4..0000000 --- a/ai/tasks/done/TASK-137-add-public-scoreboard-link-to-match-detail.md +++ /dev/null @@ -1,165 +0,0 @@ ---- -id: TASK-137 -title: Add public scoreboard link to match detail -status: done -type: frontend -team: Frontend Senior -supporting_teams: - - Backend Senior - - Arquitecto Python -roadmap_item: rcon-full-data -priority: high ---- - -# TASK-137 - Add Public Scoreboard Link To Match Detail - -## Goal - -Show a safe public scoreboard action on the historical match detail page when the current match has a valid public `match_url`. - -## Context - -The historical detail page should let users open the public scoreboard match page for the same match when a safe link is available. The button should not appear for broken, missing or unsafe URLs. - -Known constraints: - -- Use the existing backend `match_url` field when available. -- If a materialized RCON detail has no `match_url`, use existing scoreboard correlation/link resolver if already present. -- If correlation requires backend changes, keep them minimal and covered by tests. -- Keep allowlist safety for scoreboard URLs: - - `https://scoreboard.comunidadhll.es/` - - `https://scoreboard.comunidadhll.es:5443/` -- Recent match cards must keep their current behavior. -- Detail page must still work without the external link. - -## Files to Read First - -- `AGENTS.md` -- `ai/architecture-index.md` -- `ai/repo-context.md` -- `ai/orchestrator/frontend-senior.md` -- `ai/orchestrator/backend-senior.md` -- `frontend/historico-partida.html` -- `frontend/assets/js/historico-partida.js` -- backend historical/read-model modules that expose match detail and `match_url` - -## Expected Files to Modify - -- `frontend/historico-partida.html` -- `frontend/assets/js/historico-partida.js` -- relevant CSS used by `historico-partida.html` -- minimal backend historical/read-model or tests only if required for existing `match_url` correlation -- this task file when moving it from `ai/tasks/pending` to `ai/tasks/done` - -If additional files are necessary, document why in the task outcome. - -## Implementation Requirements - -1. Work from a dedicated branch: `codex/task-137-scoreboard-link`. -2. Show a visible button/link in the match detail page with one of these labels: - - `Ver en Scoreboard` - - `Ver detalles completos` -3. The button must open the public scoreboard match page in a new tab. -4. Only show the button when a safe `match_url` exists. -5. Do not show broken links. -6. Use the existing backend `match_url` field when available. -7. If materialized RCON detail has no `match_url`, use existing scoreboard correlation/link resolver if already present. -8. If correlation requires backend changes, keep them minimal and covered by tests. -9. Preserve allowlist safety for scoreboard URLs: - - `https://scoreboard.comunidadhll.es/` - - `https://scoreboard.comunidadhll.es:5443/` -10. Recent match cards must keep their current behavior. -11. Detail page must still work without the external link. -12. Preserve the player table. -13. Keep event timeline hidden. -14. Keep confidence/source/base hidden. -15. Do not show implementation/debug text in the UI. - -## Constraints - -- Keep the change minimal and focused. -- Preserve the dark HLL Vietnam visual identity. -- Do not introduce frameworks or dependencies. -- Do not create a broad backend refactor. -- Do not modify unrelated files. -- Do not reintroduce event timeline, confidence/source/base cards, `snapshot` wording, Elo/MVP blocks or Comunidad Hispana #03. - -## Validation Commands - -Run the relevant checks before marking this task done: - -- `node --check frontend/assets/js/historico-partida.js` -- `node --check frontend/assets/js/historico.js` -- `node --check frontend/assets/js/historico-recent-live.js` -- `python -m compileall backend/app` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- `powershell -ExecutionPolicy Bypass -File scripts/run-rcon-data-pipeline-tests.ps1` -- `docker compose up -d --build backend frontend` -- `Invoke-WebRequest "http://localhost:8000/health" | Select-Object -ExpandProperty Content` -- `Invoke-WebRequest "http://localhost:8000/api/historical/recent-matches?server=all-servers&limit=10" | Select-Object -ExpandProperty Content` - -## Manual Verification - -Open: - -- `http://localhost:8080/historico.html` -- `http://localhost:8080/historico-partida.html?server=comunidad-hispana-02&match=comunidad-hispana-02%3A1779178461%3A1779183861%3Acarentanwarfare` - -Then hard refresh with `Ctrl+F5` and verify: - -- Score remains `3 : 2`. -- Winner remains `Aliados`. -- Map remains `Carentan`. -- Duration remains `1 h 30 min`. -- `Ver en Scoreboard` or equivalent only appears when a valid `match_url` exists. -- The scoreboard action opens a safe public scoreboard URL in a new tab. -- No broken or unsafe link is shown when `match_url` is absent or invalid. -- Recent match cards keep their current behavior. -- AntonioPruna still shows 1 kill, 0 deaths, `M1 GARAND`. -- Victim row still shows `death_by` AntonioPruna. -- No timeline/events section is visible. -- No confidence/source/base cards are visible. -- No `snapshot`, Elo/MVP block or Comunidad Hispana #03 appears. - -## Git Requirements - -- Use branch `codex/task-137-scoreboard-link`. -- Move only this task from `ai/tasks/pending` to `ai/tasks/done` when complete. -- Add `Outcome` and `Validation Result` sections before completing the task. -- Stage only intended files. -- Commit and push the branch. -- Final git status must be clean. - -## Outcome - -- Updated the historical match detail action label to `Ver en Scoreboard`. -- Tightened the detail-page external action safety check to only show links from trusted public scoreboard origins: - - `https://scoreboard.comunidadhll.es` - - `https://scoreboard.comunidadhll.es:5443` -- Restricted accepted scoreboard paths to `/games` and `/games/...`. -- Left recent match card behavior unchanged. -- Updated the historical UI regression script to expect the new detail-page action label. -- No backend changes were needed because the existing RCON read model already exposes `match_url` when safe correlation exists. - -## Validation Result - -- PASS: `node --check frontend/assets/js/historico-partida.js` -- PASS: `node --check frontend/assets/js/historico.js` -- PASS: `node --check frontend/assets/js/historico-recent-live.js` -- PASS: `python -m compileall backend/app` -- PASS after updating the expected label: `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- PASS: `powershell -ExecutionPolicy Bypass -File scripts/run-rcon-data-pipeline-tests.ps1` - - Note: the script completed successfully but emitted existing `ResourceWarning` messages from backend unittest sqlite connections. -- PASS: `docker compose up -d --build backend frontend` -- PASS: `Invoke-WebRequest "http://localhost:8000/health" | Select-Object -ExpandProperty Content` -- PASS: `Invoke-WebRequest "http://localhost:8000/api/historical/recent-matches?server=all-servers&limit=10" | Select-Object -ExpandProperty Content` -- Additional endpoint check: the known Carentan match detail returns `match_url: null`, so no external action should render for that match. -- Manual/rendered verification: Browser plugin was listed, but the required Node runtime tool was not exposed in this session; used local Chrome headless fallback. - - Verified rendered DOM for the known Carentan match does not include `Ver en Scoreboard` or `historical-match-card__link` when `match_url` is absent. - - Verified rendered DOM still contains `3 : 2`, `Ganador: Aliados`, `Carentan`, `1 h 30 min`, `AntonioPruna` and `M1 GARAND`. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split follow-up work into separate tasks if scope grows. diff --git a/ai/tasks/done/TASK-138-polish-rcon-match-detail-final-scoreboard-ui.md b/ai/tasks/done/TASK-138-polish-rcon-match-detail-final-scoreboard-ui.md deleted file mode 100644 index 8ed8c7c..0000000 --- a/ai/tasks/done/TASK-138-polish-rcon-match-detail-final-scoreboard-ui.md +++ /dev/null @@ -1,181 +0,0 @@ ---- -id: TASK-138 -title: Polish RCON match detail final scoreboard UI -status: done -type: frontend -team: Experto en interfaz -supporting_teams: - - Frontend Senior - - Disenador grafico -roadmap_item: rcon-full-data -priority: high ---- - -# TASK-138 - Polish RCON Match Detail Final Scoreboard UI - -## Goal - -Perform a final focused visual polish pass on the historical RCON match detail page so it more closely resembles the public scoreboard style while preserving the HLL Vietnam dark tactical theme. - -## Context - -The match detail page already renders the important RCON/materialized match data. The central result direction is good, but the page still needs a final scoreboard-style polish and removal of rough labels. - -The user likes the central result: - -- score -- map -- Warfare -- winner - -The page should avoid implementation/source noise and should not expose event timeline, confidence/source/base, snapshot wording, Elo/MVP blocks or Comunidad Hispana #03. - -## Files to Read First - -- `AGENTS.md` -- `ai/architecture-index.md` -- `ai/repo-context.md` -- `ai/orchestrator/frontend-senior.md` -- `ai/orchestrator/ui-expert.md` -- `ai/orchestrator/graphic-designer.md` -- `frontend/historico-partida.html` -- `frontend/assets/js/historico-partida.js` -- relevant CSS used by `historico-partida.html` - -## Expected Files to Modify - -- `frontend/historico-partida.html` -- `frontend/assets/js/historico-partida.js` -- relevant CSS used by `historico-partida.html` -- this task file when moving it from `ai/tasks/pending` to `ai/tasks/done` - -If additional files are necessary, document why in the task outcome. - -## Implementation Requirements - -1. Work from a dedicated branch: `codex/task-138-final-scoreboard-polish`. -2. Make the match detail page resemble the public scoreboard style more closely: - - large central score - - side labels left/right - - bigger faction icons - - map/mode/winner around the central score - - compact metadata below -3. Remove `Partida RCON materializada` from the hero subtitle. -4. Replace the hero subtitle with only the server name or server + match date if available. -5. Keep `Datos disponibles` only if it still makes sense. -6. If `Datos disponibles` no longer fits the polished direction, use a more scoreboard-like heading. -7. Ensure these are not visible: - - `Confianza` - - `Fuente` - - `Base` - - `Eventos` - - `Línea de tiempo` - - `MESSAGE` - - `TEAM SWITCH` - - `CONNECTED` - - `KILL` - - `MATCH START` - - `MATCH END` - - `snapshot` - - Elo/MVP blocks - - Comunidad Hispana #03 -8. Preserve the player table. -9. Preserve known match values for the Carentan detail page: - - Map: `Carentan` - - Score: `3 : 2` - - Winner: `Aliados` - - Duration: `1 h 30 min` - - AntonioPruna: 1 kill, 0 deaths, `M1 GARAND` - - victim row: `death_by` AntonioPruna -10. Keep visual consistency with the dark HLL Vietnam theme. -11. Keep the layout responsive. -12. Do not show implementation/debug text in the UI. - -## Constraints - -- Keep the change small and focused. -- Preserve the dark HLL Vietnam visual identity. -- Do not introduce frameworks or dependencies. -- Do not modify backend unless a tiny presentation contract issue is strictly necessary and documented. -- Do not modify unrelated files. -- Do not add Elo/MVP blocks. -- Do not add Comunidad Hispana #03. -- Do not reintroduce event timeline, confidence/source/base cards or `snapshot` wording. - -## Validation Commands - -Run the relevant checks before marking this task done: - -- `node --check frontend/assets/js/historico-partida.js` -- `node --check frontend/assets/js/historico.js` -- `node --check frontend/assets/js/historico-recent-live.js` -- `python -m compileall backend/app` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- `powershell -ExecutionPolicy Bypass -File scripts/run-rcon-data-pipeline-tests.ps1` -- `docker compose up -d --build backend frontend` -- `Invoke-WebRequest "http://localhost:8000/health" | Select-Object -ExpandProperty Content` -- `Invoke-WebRequest "http://localhost:8000/api/historical/recent-matches?server=all-servers&limit=10" | Select-Object -ExpandProperty Content` - -## Manual Verification - -Open: - -- `http://localhost:8080/historico.html` -- `http://localhost:8080/historico-partida.html?server=comunidad-hispana-02&match=comunidad-hispana-02%3A1779178461%3A1779183861%3Acarentanwarfare` - -Then hard refresh with `Ctrl+F5` and verify: - -- Score remains `3 : 2`. -- Winner remains `Aliados`. -- Map remains `Carentan`. -- Duration remains `1 h 30 min`. -- Hero does not show `Partida RCON materializada`. -- The scoreboard area has a large central score, left/right sides, larger faction icons, and compact metadata. -- AntonioPruna still shows 1 kill, 0 deaths, `M1 GARAND`. -- Victim row still shows `death_by` AntonioPruna. -- No timeline/events section is visible. -- No confidence/source/base cards are visible. -- No event labels such as `MESSAGE`, `TEAM SWITCH`, `CONNECTED`, `KILL`, `MATCH START` or `MATCH END` appear. -- No `snapshot`, Elo/MVP block or Comunidad Hispana #03 appears. -- Player table is preserved and readable. -- Layout remains responsive on desktop and mobile. - -## Git Requirements - -- Use branch `codex/task-138-final-scoreboard-polish`. -- Move only this task from `ai/tasks/pending` to `ai/tasks/done` when complete. -- Add `Outcome` and `Validation Result` sections before completing the task. -- Stage only intended files. -- Commit and push the branch. -- Final git status must be clean. - -## Outcome - -- Replaced the hero subtitle with only the server name, removing RCON implementation wording from the visible hero. -- Renamed the main detail heading from `Datos disponibles` to `Marcador final`. -- Increased the scoreboard score column and faction emblem sizing while preserving the left/right side layout, central score, map, mode, winner and compact metadata. -- Removed the unused hidden timeline markup from `frontend/historico-partida.html` so event labels such as `Eventos` and `Linea de tiempo` are no longer present in the match detail DOM. -- Preserved the player table, map hero, safe scoreboard action behavior and existing HLL Vietnam dark tactical styling. - -## Validation Result - -- PASS: `node --check frontend/assets/js/historico-partida.js` -- PASS: `node --check frontend/assets/js/historico.js` -- PASS: `node --check frontend/assets/js/historico-recent-live.js` -- PASS: `python -m compileall backend/app` -- PASS: `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- PASS: `powershell -ExecutionPolicy Bypass -File scripts/run-rcon-data-pipeline-tests.ps1` - - Note: the script completed successfully but emitted existing `ResourceWarning` messages from backend unittest sqlite connections. -- PASS: `docker compose up -d --build backend frontend` -- PASS: `Invoke-WebRequest "http://localhost:8000/health" | Select-Object -ExpandProperty Content` -- PASS: `Invoke-WebRequest "http://localhost:8000/api/historical/recent-matches?server=all-servers&limit=10" | Select-Object -ExpandProperty Content` -- Manual/rendered verification: Browser plugin was listed, but the required Node runtime tool was not exposed in this session; used local Chrome headless fallback. - - Verified rendered DOM contains `Marcador final`, `3 : 2`, `Ganador: Aliados`, `Carentan`, `1 h 30 min`, `AntonioPruna` and `M1 GARAND`. - - Verified rendered DOM does not include `Partida RCON materializada`, `Confianza`, `Fuente`, `Base`, `Eventos`, `Linea de tiempo`, event labels, `snapshot`, Elo/MVP blocks or Comunidad Hispana #03. - - Captured screenshots outside the repository at `C:\Temp\task-138-match-detail-final.png`, `C:\Temp\task-138-match-detail-mobile-final.png` and `C:\Temp\task-138-match-detail-mobile-score-final.png`. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split follow-up work into separate tasks if scope grows. diff --git a/ai/tasks/done/TASK-139-align-recent-match-cards.md b/ai/tasks/done/TASK-139-align-recent-match-cards.md deleted file mode 100644 index 4750a68..0000000 --- a/ai/tasks/done/TASK-139-align-recent-match-cards.md +++ /dev/null @@ -1,82 +0,0 @@ ---- -id: TASK-139 -title: Align recent match cards -status: done -type: frontend -team: Frontend Senior -supporting_teams: [Experto en interfaz] -roadmap_item: foundation -priority: medium ---- - -# TASK-139 - Align recent match cards - -## Goal - -Make the recent match cards in `historico.html` use consistent metadata columns and a right-aligned action area across static and dynamic renderers. - -## Context - -The recent matches list should stay compact and clean while preserving the HLL Vietnam dark tactical theme. It must not show raw match IDs, internal status/source/debug text, or the public scoreboard action in the list. The public scoreboard link remains available on the match detail page. - -## Steps - -1. Inspect the listed files first. -2. Normalize the static and dynamic recent card markup. -3. Use CSS grid for deterministic metadata/action alignment. -4. Validate with syntax checks and the requested Docker frontend checks. - -## Files to Read First - -- `ai/architecture-index.md` -- `ai/repo-context.md` -- `ai/orchestrator/frontend-senior.md` -- `frontend/historico.html` -- `frontend/assets/js/historico.js` -- `frontend/assets/js/historico-recent-live.js` -- `frontend/assets/css/historico.css` - -## Expected Files to Modify - -- `frontend/assets/js/historico.js` -- `frontend/assets/js/historico-recent-live.js` -- `frontend/assets/css/historico.css` -- `ai/tasks/done/TASK-139-align-recent-match-cards.md` - -## Constraints - -- Keep the change minimal. -- Preserve the HLL Vietnam visual identity. -- Do not introduce frameworks or backend changes. -- Do not alter detail page scoreboard link behavior. -- Do not remove `match_url` support. - -## Validation - -- `node --check frontend/assets/js/historico-recent-live.js` -- `node --check frontend/assets/js/historico.js` -- `node --check frontend/assets/js/historico-partida.js` -- `docker compose build --no-cache frontend` -- `docker compose up -d frontend` -- Manual verification on `http://localhost:8080/historico.html?nocache=alignment` - -## Outcome - -Implemented a shared clean recent-card structure for the static snapshot renderer and dynamic live renderer. The recent list now shows only map title, Servidor, Cierre, Jugadores, Marcador and right-aligned actions. The public scoreboard action keeps its `match_url` link in markup with a recent-list-only hidden class, while the detail page scoreboard action remains visible. - -Validation completed: - -- `node --check frontend/assets/js/historico-recent-live.js` -- `node --check frontend/assets/js/historico.js` -- `node --check frontend/assets/js/historico-partida.js` -- `docker compose build --no-cache frontend` -- `docker compose up -d frontend` -- Browser verification on `http://localhost:8080/historico.html?nocache=alignment` -- Browser verification on the supplied `historico-partida.html` detail URL - -Manual verification found 13 recent cards, 13 visible `Ver detalles` links, zero visible `Ver partida` links in the recent list, no forbidden internal/debug text in the recent list, 0px column spread across all desktop metadata columns, and a visible public scoreboard link on the detail page. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. diff --git a/ai/tasks/done/TASK-140-fix-historical-runner-elo-import.md b/ai/tasks/done/TASK-140-fix-historical-runner-elo-import.md deleted file mode 100644 index ebf44f8..0000000 --- a/ai/tasks/done/TASK-140-fix-historical-runner-elo-import.md +++ /dev/null @@ -1,103 +0,0 @@ ---- -id: TASK-140 -title: Restore historical runner Elo imports -status: done -type: backend -team: Backend Senior -supporting_teams: [Arquitecto Python] -roadmap_item: foundation -priority: high ---- - -# TASK-140 - Restore historical runner Elo imports - -## Goal - -Restore `historical-runner` startup by fixing the Elo/MMR model import contract used by `app.elo_mmr_engine`. - -## Context - -The advanced `historical-runner` service runs `python -m app.historical_runner --hourly` and intentionally imports `rebuild_elo_mmr_models`. The engine imports scoring constants from `app.elo_mmr_models`, but that module no longer exports every constant required by the engine. - -## Steps - -1. Inspect the listed files first. -2. Restore the missing Elo/MMR model/config constants in the correct module. -3. Keep the change narrow and avoid disabling the runner or Elo/MMR silently. -4. Validate the backend, RCON data pipeline, integration tests, advanced Compose services and relevant HTTP endpoints. - -## Files to Read First - -- `ai/architecture-index.md` -- `ai/repo-context.md` -- `ai/orchestrator/backend-senior.md` -- `backend/app/historical_runner.py` -- `backend/app/historical_ingestion.py` -- `backend/app/elo_mmr_engine.py` -- `backend/app/elo_mmr_models.py` -- `backend/app/elo_mmr_storage.py` - -## Expected Files to Modify - -- `backend/app/elo_mmr_models.py` -- `.gitignore` -- `ai/tasks/done/TASK-140-fix-historical-runner-elo-import.md` - -## Constraints - -- Do not remove or disable `historical-runner`. -- Do not disable Elo/MMR silently. -- Do not modify frontend files. -- Do not reintroduce Comunidad Hispana #03. -- Do not commit runtime database files. -- Preserve RCON ingestion, AdminLog materialization, recent matches, match detail and scoreboard candidate backfill. - -## Validation - -- `python -m compileall backend/app` -- `powershell -ExecutionPolicy Bypass -File scripts/run-rcon-data-pipeline-tests.ps1` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- `docker compose --profile advanced up -d --build backend frontend historical-runner rcon-historical-worker` -- `docker compose --profile advanced ps` -- `docker compose logs --tail=100 historical-runner` -- `Invoke-WebRequest "http://localhost:8000/health" | Select-Object -ExpandProperty Content` -- `Invoke-WebRequest "http://localhost:8000/api/historical/recent-matches?server=all-servers&limit=20" | Select-Object -ExpandProperty Content` - -## Outcome - -Implemented the import-contract fix by restoring the missing Elo/MMR model constants exported from `backend/app/elo_mmr_models.py`: - -- `ELO_K_FACTOR` -- `MIN_VALID_PLAYER_PARTICIPATION_SECONDS` -- `MIN_VALID_PLAYER_PARTICIPATION_RATIO` - -The constants live with the rest of the Elo/MMR model thresholds, preserving the existing `app.elo_mmr_engine` import boundary and avoiding any silent disabling of the runner or Elo/MMR. `.gitignore` now also ignores `backend/data/*.writer.lock` because advanced Compose validation creates the shared SQLite writer lock as runtime state. - -Validation completed: - -- `python -m compileall backend/app` -- Direct imports of `app.historical_runner`, `app.historical_ingestion` and `app.elo_mmr_engine` -- `powershell -ExecutionPolicy Bypass -File scripts/run-rcon-data-pipeline-tests.ps1` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- `docker compose --profile advanced up -d --build backend frontend historical-runner rcon-historical-worker` -- `docker compose --profile advanced ps` -- `docker compose logs --tail=100 historical-runner` -- `Invoke-WebRequest "http://localhost:8000/health" | Select-Object -ExpandProperty Content` -- `Invoke-WebRequest "http://localhost:8000/api/historical/recent-matches?server=all-servers&limit=20" | Select-Object -ExpandProperty Content` -- `Invoke-WebRequest "http://localhost:8080/historico.html?nocache=runner" | Select-Object -ExpandProperty StatusCode` - -Manual verification: - -- `historical-runner` stayed `Up` in the advanced profile. -- `rcon-historical-worker` stayed `Up`. -- `historical-runner` logs showed `historical-refresh-loop-started` and no `ImportError`. -- `/health` returned `status: "ok"`. -- `/api/historical/recent-matches` returned RCON-backed recent match data. -- `historico.html` returned HTTP 200. -- No frontend files were modified. -- No runtime database files were staged or committed. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. diff --git a/ai/tasks/done/TASK-141-keep-recent-match-actions-inline.md b/ai/tasks/done/TASK-141-keep-recent-match-actions-inline.md deleted file mode 100644 index 1075095..0000000 --- a/ai/tasks/done/TASK-141-keep-recent-match-actions-inline.md +++ /dev/null @@ -1,86 +0,0 @@ ---- -id: TASK-141 -title: Keep recent match actions inline -status: done -type: frontend -team: Frontend Senior -supporting_teams: [Experto en interfaz] -roadmap_item: foundation -priority: medium ---- - -# TASK-141 - Keep recent match actions inline - -## Goal - -Keep the result chip and `Ver detalles` action on the same horizontal row in recent match cards. - -## Context - -The recent matches cards already use the clean structure, but the right-side action controls can wrap vertically on desktop. The fix should preserve the current recent card structure, keep public scoreboard links hidden only in the recent list, and avoid affecting `historico-partida.html`. - -## Steps - -1. Inspect the listed files first. -2. Apply a scoped CSS fix for recent match card actions. -3. Validate syntax, Docker frontend build/start and rendered behavior. - -## Files to Read First - -- `ai/architecture-index.md` -- `ai/repo-context.md` -- `ai/orchestrator/frontend-senior.md` -- `docs/decisions.md` -- `frontend/historico.html` -- `frontend/assets/css/historico.css` -- `frontend/assets/js/historico.js` -- `frontend/assets/js/historico-recent-live.js` - -## Expected Files to Modify - -- `frontend/assets/css/historico.css` -- `ai/tasks/done/TASK-141-keep-recent-match-actions-inline.md` - -## Constraints - -- Do not modify backend. -- Do not affect the detail page scoreboard link. -- Do not show `Ver partida` in recent cards. -- Do not reintroduce raw match ids, Estado, source or RCON debug text. -- Keep the dark HLL Vietnam theme. - -## Validation - -- `node --check frontend/assets/js/historico.js` -- `node --check frontend/assets/js/historico-recent-live.js` -- `node --check frontend/assets/js/historico-partida.js` -- `docker compose build --no-cache frontend` -- `docker compose up -d frontend` -- Browser verification on `http://localhost:8080/historico.html?nocache=actions-inline` -- Browser verification of the supplied detail-page scoreboard behavior - -## Outcome - -Implemented a scoped CSS fix for recent match actions: - -- Widened the clean recent-card action grid track to fit result chip plus detail link on desktop. -- Forced `#recent-matches-list .historical-match-card__actions` to use row-direction, no-wrap flex layout on desktop. -- Kept mobile/tablet wrapping available under the existing responsive breakpoint. -- Kept the public scoreboard link hidden only under `#recent-matches-list`. - -Validation completed: - -- `node --check frontend/assets/js/historico.js` -- `node --check frontend/assets/js/historico-recent-live.js` -- `node --check frontend/assets/js/historico-partida.js` -- `docker compose build --no-cache frontend` -- `docker compose up -d frontend` -- Browser verification on `http://localhost:8080/historico.html?nocache=actions-inline` -- Browser verification on the supplied `historico-partida.html` detail URL - -Manual verification found 10 recent cards, 10 visible `Ver detalles` links, zero visible `Ver partida` links in the recent list, no forbidden internal/debug text, all result chips inline with `Ver detalles`, all result states present, no framework overlay, no relevant console issues, and a visible scoreboard link on the detail page. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. diff --git a/ai/tasks/done/TASK-142-player-team-visuals-and-recent-counts.md b/ai/tasks/done/TASK-142-player-team-visuals-and-recent-counts.md deleted file mode 100644 index 11f3505..0000000 --- a/ai/tasks/done/TASK-142-player-team-visuals-and-recent-counts.md +++ /dev/null @@ -1,99 +0,0 @@ ---- -id: TASK-142 -title: Player team visuals and recent counts -status: done -type: frontend -team: Frontend Senior -supporting_teams: [Backend Senior, Experto en interfaz] -roadmap_item: foundation -priority: high ---- - -# TASK-142 - Player team visuals and recent counts - -## Goal - -Fix historical UI/data consistency by visually distinguishing player teams in internal match detail tables and exposing meaningful recent-match player counts for RCON materialized matches. - -## Context - -Recent match cards can show `Jugadores = 0` even when the corresponding internal detail page has materialized player rows. The detail player table also needs an additive visual distinction for Allies/Aliados and Axis/Eje rows while preserving all existing stats and detail-page behavior. - -## Steps - -1. Inspect the listed files first. -2. Fix the backend RCON recent-match read model to expose a non-zero materialized player count when player stats exist. -3. Add team-specific visual styling to all internal match detail player rows or team cells. -4. Validate backend, frontend syntax, RCON pipeline, integration scripts, advanced Compose services and rendered UI behavior. - -## Files to Read First - -- `ai/architecture-index.md` -- `ai/repo-context.md` -- `ai/orchestrator/backend-senior.md` -- `ai/orchestrator/frontend-senior.md` -- `backend/app/rcon_historical_read_model.py` -- `backend/app/rcon_admin_log_materialization.py` -- `backend/app/rcon_admin_log_storage.py` -- `frontend/assets/js/historico-partida.js` -- `frontend/assets/css/historico-scoreboard-detail.css` -- `frontend/assets/css/historico.css` - -## Expected Files to Modify - -- `backend/app/rcon_historical_read_model.py` -- `backend/app/rcon_admin_log_materialization.py` -- `frontend/assets/js/historico-partida.js` -- `frontend/assets/css/historico-scoreboard-detail.css` -- `ai/tasks/done/TASK-142-player-team-visuals-and-recent-counts.md` - -## Constraints - -- Do not modify public scoreboard behavior. -- Do not modify frontend recent-card layout beyond consuming corrected backend data. -- Do not reintroduce raw match id, Estado, Resultado confirmado, Fuente, RCON/debug text, timeline/events, confidence/source/base, Elo/MVP blocks or Comunidad Hispana #03. -- Do not commit runtime DB files. - -## Validation - -- `python -m compileall backend/app` -- `node --check frontend/assets/js/historico.js` -- `node --check frontend/assets/js/historico-recent-live.js` -- `node --check frontend/assets/js/historico-partida.js` -- `powershell -ExecutionPolicy Bypass -File scripts/run-rcon-data-pipeline-tests.ps1` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- `docker compose --profile advanced up -d --build backend frontend historical-runner rcon-historical-worker` -- `docker compose --profile advanced ps` -- `Invoke-WebRequest "http://localhost:8000/health" | Select-Object -ExpandProperty Content` -- `Invoke-WebRequest "http://localhost:8000/api/historical/recent-matches?server=all-servers&limit=20" | Select-Object -ExpandProperty Content` -- Browser verification on `http://localhost:8080/historico.html?nocache=player-counts` -- Browser verification on an internal match detail page with materialized players - -## Outcome - -Implemented. Materialized RCON recent-match rows now include player-stat counts and the RCON historical read model exposes those counts as `player_count` for recent cards and detail payloads. The internal match detail player table now renders localized team badges and team-specific row accents for Aliados, Eje and No disponible while preserving the existing stats columns and detail-page scoreboard link. - -Validation passed: - -- `python -m compileall backend/app` -- `node --check frontend/assets/js/historico.js` -- `node --check frontend/assets/js/historico-recent-live.js` -- `node --check frontend/assets/js/historico-partida.js` -- `powershell -ExecutionPolicy Bypass -File scripts/run-rcon-data-pipeline-tests.ps1` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- `docker compose --profile advanced up -d --build backend frontend historical-runner rcon-historical-worker` -- `docker compose --profile advanced ps` -- `Invoke-WebRequest "http://localhost:8000/health" | Select-Object -ExpandProperty Content` -- `Invoke-WebRequest "http://localhost:8000/api/historical/recent-matches?server=all-servers&limit=20" | Select-Object -ExpandProperty Content` -- Browser verification on `http://localhost:8080/historico.html?nocache=player-counts` -- Browser verification on `historico-partida.html` for `comunidad-hispana-02:1779178461:1779183861:carentanwarfare` - -Notes: - -- The RCON pipeline test reports existing SQLite `ResourceWarning` messages from its test harness, but both unittest suites return `OK` and the script reports validation passed. -- The browser plugin was not exposed by tool discovery in this session, so rendered UI verification used local Chrome/Selenium fallback. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. diff --git a/ai/tasks/done/TASK-143-player-table-hover-stats-panel.md b/ai/tasks/done/TASK-143-player-table-hover-stats-panel.md deleted file mode 100644 index c2aea64..0000000 --- a/ai/tasks/done/TASK-143-player-table-hover-stats-panel.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -id: TASK-143 -title: Player table hover stats panel -status: done -type: frontend -team: Frontend Senior -supporting_teams: [Experto en interfaz] -roadmap_item: foundation -priority: high ---- - -# TASK-143 - Player table hover stats panel - -## Goal - -Make the internal historical match detail player table more compact by moving expanded per-player statistics into an accessible hover/focus/click details panel. - -## Context - -The detail page player table currently includes detailed columns for weapons, most killed and death by. The desired scoreboard-like UX keeps the table focused on player/team/core combat metrics and reveals expanded statistics per row. - -## Steps - -1. Inspect the current match detail renderer and scoreboard detail CSS. -2. Reduce the visible table columns to Jugador, Equipo, K, D, TK, K/D and KPM. -3. Add accessible row hover/focus/click expanded panels with weapons, most killed, death by and direct matchups. -4. Preserve team styling, scoreboard link behavior and forbidden hidden sections. -5. Validate syntax, frontend build/container and rendered behavior. - -## Files to Read First - -- `ai/architecture-index.md` -- `ai/repo-context.md` -- `ai/orchestrator/frontend-senior.md` -- `frontend/historico-partida.html` -- `frontend/assets/js/historico-partida.js` -- `frontend/assets/css/historico-scoreboard-detail.css` -- `frontend/assets/css/historico.css` - -## Expected Files to Modify - -- `frontend/historico-partida.html` -- `frontend/assets/js/historico-partida.js` -- `frontend/assets/css/historico-scoreboard-detail.css` -- `ai/tasks/done/TASK-143-player-table-hover-stats-panel.md` - -## Constraints - -- Do not modify backend unless absolutely necessary. -- Do not modify recent match card layout. -- Do not reintroduce timeline/events/confidence/source/base or Elo/MVP blocks. -- Preserve Aliados/Eje/No disponible visual distinction. - -## Validation - -- `node --check frontend/assets/js/historico-partida.js` -- `node --check frontend/assets/js/historico.js` -- `node --check frontend/assets/js/historico-recent-live.js` -- `docker compose build --no-cache frontend` -- `docker compose up -d frontend` -- Browser verification on `historico-partida.html` -- Browser smoke verification on `historico.html` - -## Outcome - -Implemented. The match detail player table now shows only Jugador, Equipo, K, D, TK, K/D and KPM. Expanded player statistics are rendered in per-player detail panels that open on row hover, keyboard focus/Enter and touch/click via an accessible info control. The panel includes the player/team summary, weapons, most killed, death by and direct matchup balance derived from most_killed and death_by. - -Validation passed: - -- `node --check frontend/assets/js/historico-partida.js` -- `node --check frontend/assets/js/historico.js` -- `node --check frontend/assets/js/historico-recent-live.js` -- `docker compose build --no-cache frontend` -- `docker compose up -d frontend` -- Browser verification on `historico-partida.html` for `comunidad-hispana-02:1779178461:1779183861:carentanwarfare` -- Browser smoke verification on `historico.html?nocache=player-table-hover` - -Notes: - -- Browser plugin runtime tools were not exposed by tool discovery in this session, so rendered validation used local Chrome/Selenium fallback. diff --git a/ai/tasks/done/TASK-144-home-region-and-rcon-freshness.md b/ai/tasks/done/TASK-144-home-region-and-rcon-freshness.md deleted file mode 100644 index bac2d57..0000000 --- a/ai/tasks/done/TASK-144-home-region-and-rcon-freshness.md +++ /dev/null @@ -1,113 +0,0 @@ ---- -id: TASK-144 -title: Home region cleanup and RCON freshness diagnostics -status: done -type: integration -team: Backend Senior -supporting_teams: [Frontend Senior] -roadmap_item: foundation -priority: high ---- - -# TASK-144 - Home region cleanup and RCON freshness diagnostics - -## Goal - -Hide placeholder region values on the home page server cards and improve RCON historical freshness diagnostics so stale recent matches are explainable from worker/runner logs. - -## Context - -The home page currently renders `Region pendiente` when a server region is missing. Recent RCON materialized matches can also appear stale without clear logs showing whether AdminLog events were seen, inserted, duplicated or materialized. - -## Steps - -1. Inspect home server-card rendering and RCON runner/worker/ingestion/materialization paths. -2. Hide placeholder/missing region quick facts while preserving map data. -3. Determine whether historical-runner refreshes RCON AdminLog materialization or whether rcon-historical-worker owns it. -4. Add minimal logging/summary output for AdminLog ingestion/materialization and latest materialized match freshness. -5. Validate frontend syntax, backend compile, pipeline scripts, Compose services, logs, manual commands and rendered pages. - -## Files to Read First - -- `ai/architecture-index.md` -- `ai/repo-context.md` -- `ai/orchestrator/backend-senior.md` -- `ai/orchestrator/frontend-senior.md` -- `frontend/assets/js/main.js` -- `backend/app/rcon_historical_worker.py` -- `backend/app/rcon_admin_log_ingestion.py` -- `backend/app/rcon_admin_log_materialization.py` -- `backend/app/historical_runner.py` -- `docker-compose.yml` - -## Expected Files to Modify - -- `frontend/assets/js/main.js` -- `backend/app/rcon_historical_worker.py` -- `backend/app/rcon_admin_log_ingestion.py` -- `backend/app/rcon_admin_log_materialization.py` -- `ai/tasks/done/TASK-144-home-region-and-rcon-freshness.md` - -## Constraints - -- Do not expose secrets. -- Do not reintroduce Comunidad Hispana #03. -- Do not change recent-card visual design. -- Do not commit runtime DB files. -- Preserve manual RCON commands. - -## Validation - -- `python -m compileall backend/app` -- `node --check frontend/assets/js/main.js` -- `node --check frontend/assets/js/historico.js` -- `node --check frontend/assets/js/historico-recent-live.js` -- `node --check frontend/assets/js/historico-partida.js` -- `powershell -ExecutionPolicy Bypass -File scripts/run-rcon-data-pipeline-tests.ps1` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- `docker compose --profile advanced up -d --build backend frontend historical-runner rcon-historical-worker` -- `docker compose --profile advanced ps` -- `docker compose logs --tail=150 historical-runner` -- `docker compose logs --tail=150 rcon-historical-worker` -- `docker compose exec backend python -m app.rcon_admin_log_ingestion --minutes 360` -- `docker compose exec backend python -m app.rcon_admin_log_materialization` -- `Invoke-WebRequest "http://localhost:8000/health" | Select-Object -ExpandProperty Content` -- `Invoke-WebRequest "http://localhost:8000/api/historical/recent-matches?server=all-servers&limit=20" | Select-Object -ExpandProperty Content` -- Browser verification on `index.html?nocache=region` -- Browser verification on `historico.html?nocache=freshness` - -## Outcome - -Implemented. Home server cards now omit the Region quick fact when the region is missing or a placeholder such as `Region pendiente`, while preserving the Mapa quick fact. RCON capture now runs AdminLog materialization after AdminLog ingestion and emits freshness diagnostics in the worker result, including event counters, materialized match counters and latest materialized/AdminLog match-end timestamps per configured server. - -Findings: - -- `historical-runner` already calls the RCON capture path when historical data source is RCON, but the capture path previously ingested AdminLog entries without materializing them into recent matches. -- `rcon-historical-worker` owns the 10-minute capture loop and now materializes after ingestion, so recent matches can advance without requiring a manual materialization command. -- The live diagnostics show new recent data after the previously stale `17:38` item. Recent matches now include `comunidad-hispana-01:1779299747:1779305147:carentanwarfare` closed at `2026-05-20T19:26:46.519Z` and `comunidad-hispana-02:1779296626:1779301626:carentanwarfare` closed at `2026-05-20T18:41:59.219Z`. - -Validation passed: - -- `python -m compileall backend/app` -- `node --check frontend/assets/js/main.js` -- `node --check frontend/assets/js/historico.js` -- `node --check frontend/assets/js/historico-recent-live.js` -- `node --check frontend/assets/js/historico-partida.js` -- `powershell -ExecutionPolicy Bypass -File scripts/run-rcon-data-pipeline-tests.ps1` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- `docker compose --profile advanced up -d --build backend frontend historical-runner rcon-historical-worker` -- `docker compose --profile advanced ps` -- `docker compose logs --tail=150 historical-runner` -- `docker compose logs --tail=150 rcon-historical-worker` -- `docker compose exec backend python -m app.rcon_admin_log_ingestion --minutes 360` -- `docker compose exec backend python -m app.rcon_admin_log_materialization` -- `Invoke-WebRequest "http://localhost:8000/health" | Select-Object -ExpandProperty Content` -- `Invoke-WebRequest "http://localhost:8000/api/historical/recent-matches?server=all-servers&limit=20" | Select-Object -ExpandProperty Content` -- Browser verification on `http://localhost:8080/index.html?nocache=region` -- Browser verification on `http://localhost:8080/historico.html?nocache=freshness` - -Notes: - -- The RCON pipeline script reports existing SQLite `ResourceWarning` messages from its test harness, but the unittest suites return `OK` and the script reports validation passed. -- The integration script exits successfully, but the local runtime DB emits an existing `database disk image is malformed` traceback after the pass message. Runtime DB files were not modified for commit. -- Browser plugin runtime tools were not exposed by tool discovery in this session, so rendered validation used local Chrome/Selenium fallback. diff --git a/ai/tasks/done/TASK-145-match-detail-player-table-controls.md b/ai/tasks/done/TASK-145-match-detail-player-table-controls.md deleted file mode 100644 index 3d4ec82..0000000 --- a/ai/tasks/done/TASK-145-match-detail-player-table-controls.md +++ /dev/null @@ -1,111 +0,0 @@ ---- -id: TASK-145 -title: Add match detail player table controls -status: done -type: frontend -team: Frontend Senior -supporting_teams: [] -roadmap_item: foundation -priority: medium ---- - -# TASK-145 - Add match detail player table controls - -## Goal - -Keep inactive match-detail player rows low priority and add compact search, team -filtering and sorting controls to the player table. - -## Context - -The internal match detail page already exposes a compact player stat table and -expandable detail panels. Profile and lobby snapshot rows with no team and no -match activity can currently compete with real participants in that table, and -larger matches need client-side controls to find and compare players without -changing backend contracts. - -## Steps - -1. Inspect the listed files first. -2. Apply only the scoped match-detail player table change. -3. Validate the result and document relevant findings. - -## Files to Read First - -- `ai/architecture-index.md` -- `ai/repo-context.md` -- `ai/orchestrator/frontend-senior.md` -- `frontend/historico-partida.html` -- `frontend/assets/js/historico-partida.js` -- `frontend/assets/css/historico-scoreboard-detail.css` - -## Expected Files to Modify - -- `frontend/historico-partida.html` -- `frontend/assets/js/historico-partida.js` -- `frontend/assets/css/historico-scoreboard-detail.css` -- `ai/tasks/done/TASK-145-match-detail-player-table-controls.md` - -## Constraints - -- Preserve the compact main columns and click-to-open player detail panels. -- Keep Aliados and Eje row treatments and badges. -- Filter team labels through the existing localized team mapping. -- Do not reintroduce expanded stats, event data or backend changes as table columns. -- Keep frontend behavior responsive and browser-loaded without new dependencies. - -## Validation - -- `node --check frontend/assets/js/historico-partida.js` -- `node --check frontend/assets/js/historico.js` -- `node --check frontend/assets/js/historico-recent-live.js` -- `docker compose build --no-cache frontend` -- `docker compose up -d frontend` -- Manual match-detail verification for default inactive ordering, stat sorting, - name search, team filters and panel close-on-filter behavior. -- Review `git diff --name-only` against task scope. - -## Outcome - -Implemented. The match-detail player table now has client-side player-name -search, localized team filtering, sort-column and direction controls above the -existing compact table. Default row ordering keeps active participants first, -orders them by kills descending, deaths ascending and name, and sends rows with -unknown team, zero combat stats and no expanded match stats to the bottom. -Numeric explicit sorts retain that inactive demotion, while name/team sorts can -compare all visible rows and inactive rows stay visually muted. - -The table continues to render row/detail pairs together after control changes. -Player-name clicks still open the existing expanded detail panel, and search or -team-filter changes close any open panel before the visible rows refresh. - -Validation passed: - -- `node --check frontend/assets/js/historico-partida.js` -- `node --check frontend/assets/js/historico.js` -- `node --check frontend/assets/js/historico-recent-live.js` -- `docker compose build --no-cache frontend` -- `docker compose up -d frontend` -- Rendered fallback verification on - `historico-partida.html?server=comunidad-hispana-02&match=comunidad-hispana-02%3A1779315955%3A1779319098%3Akharkovwarfare` - for control visibility, row detail opening, close-on-search, player-name - search, Aliados/Eje/Sin equipo filters and Jugador/Equipo/K/D/TK/K-D/KPM - sort selectors. -- Rendered default ordering on the provided match showed 18 active rows before - 44 inactive/no-team rows; visible zero-kill rows with deaths stayed in the - active block before the inactive rows. -- Desktop and mobile controls screenshots were inspected outside the repo. - -Notes: - -- Browser plugin runtime tools were not exposed by tool discovery in this - session, so rendered validation used a temporary local headless - Chrome/Selenium fallback outside the repository. -- Browser console output on the tested route only reported the existing missing - `favicon.ico` request. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-146-match-detail-scoreboard-and-player-links.md b/ai/tasks/done/TASK-146-match-detail-scoreboard-and-player-links.md deleted file mode 100644 index 6320516..0000000 --- a/ai/tasks/done/TASK-146-match-detail-scoreboard-and-player-links.md +++ /dev/null @@ -1,141 +0,0 @@ ---- -id: TASK-146 -title: Recover match scoreboard and player external links -status: done -type: backend -team: Backend Senior -supporting_teams: [Frontend Senior] -roadmap_item: foundation -priority: high ---- - -# TASK-146 - Recover match scoreboard and player external links - -## Goal - -Restore the safe public scoreboard action on the internal match detail page and -expose player external profile links only when captured player identifiers make -that reliable. - -## Context - -The internal `historico-partida.html` detail payload can carry a safe -`match_url`, but users do not currently see the detail-page scoreboard action. -The same detail page has click-open player panels that can link to Steam and -SteamID64-based third-party profiles when the RCON/profile or reliable -historical data path already holds a valid SteamID64. - -## Steps - -1. Inspect the listed files and captured identifier path first. -2. Keep scoreboard actions detail-page only and add profile links only from - reliable identifiers. -3. Validate backend diagnostics, frontend syntax, integration/container checks - and rendered detail-page behavior. - -## Files to Read First - -- `ai/architecture-index.md` -- `ai/repo-context.md` -- `ai/orchestrator/backend-senior.md` -- `ai/orchestrator/frontend-senior.md` -- `backend/app/rcon_historical_read_model.py` -- `frontend/assets/js/historico-partida.js` - -## Expected Files to Modify - -- Relevant backend read-model, storage helper, diagnostics and tests for exposed - external player identifiers and profile links. -- `frontend/assets/js/historico-partida.js` -- Relevant detail-page CSS when profile links need styling. -- `ai/tasks/done/TASK-146-match-detail-scoreboard-and-player-links.md` - -## Constraints - -- Do not invent SteamIDs or use player names to build external links. -- Do not call Steam Web API or require new external credentials. -- Keep public scoreboard actions off recent match cards. -- Allow only safe Comunidad Hispana scoreboard match URLs in the detail page. -- Preserve click-open player panels and existing expanded stat sections. - -## Validation - -- `python -m compileall backend/app` -- `python -m app.storage_diagnostics` -- `node --check frontend/assets/js/historico-partida.js` -- `node --check frontend/assets/js/historico.js` -- `node --check frontend/assets/js/historico-recent-live.js` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- `docker compose --profile advanced up -d --build backend frontend` -- Inspect the provided match-detail API response with `Invoke-WebRequest`. -- Render-check the detail-page scoreboard action, player panel profile state and - recent-match-card absence of public scoreboard links. -- Review `git diff --name-only` against task scope. - -## Outcome - -Implemented. - -- The internal match detail scoreboard action now sits immediately after the - summary block and before the potentially long player table. It still uses the - existing detail-page safe scoreboard allowlist and keeps the established - `Ver en Scoreboard` regression-checked label. -- RCON detail rows derive `platform`, `steam_id_64` and Steam/Hellor/HLL Records - URLs from captured `player_id` only when it is a valid numeric 17-digit - SteamID64. Raw RCON `player_id` is still not exposed. -- Trusted public-scoreboard detail rows derive the same profile fields from - persisted `historical_players.steam_id`. -- Epic-style hex RCON IDs resolve to `platform: epic` with no Steam-only links; - other missing or unsupported IDs return `platform: unknown` with no external - link fields. -- Click-open player panels now include `Perfiles externos`. Steam-backed players - get the three external links with new-tab noopener rel attributes; missing-ID - panels show a clear unavailable state without using player names to build - URLs. -- PostgreSQL storage diagnostics now report SteamID64 availability counts for - RCON match rows, RCON profile snapshots and trusted scoreboard player rows. - -Validation passed: - -- `python -m compileall backend/app` -- `python -m app.storage_diagnostics` from `backend/` in local SQLite fallback - mode. It reports PostgreSQL external-ID diagnostics as inactive when the - PostgreSQL env is not configured locally. -- `docker compose exec backend python -m app.storage_diagnostics` after the - advanced stack build. PostgreSQL diagnostics reported: - - `rcon_match_steam_id64_rows`: `2554` - - `rcon_profile_steam_id64_rows`: `462` - - `scoreboard_player_steam_id64_rows`: `87369` -- `node --check frontend/assets/js/historico-partida.js` -- `node --check frontend/assets/js/historico.js` -- `node --check frontend/assets/js/historico-recent-live.js` -- Targeted backend tests from `backend/`: - `python -m unittest tests.test_rcon_materialization_pipeline tests.test_scoreboard_match_links` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- `docker compose --profile advanced up -d --build backend frontend` -- The provided `Invoke-WebRequest` match-detail API check returned the safe - Carentan scoreboard URL plus validated external profile links for captured - SteamID64-backed players. -- Rendered local Chrome/Selenium fallback QA verified: - - detail scoreboard action appears before the player table and opens - `https://scoreboard.comunidadhll.es:5443/games/1562094` - - Steam-backed player panel shows Steam, Hellor and HLL Records links - - a no-SteamID64 player panel shows `Perfiles externos no disponibles` - - recent `historico.html` match cards show no public scoreboard links - - mobile detail layout keeps the scoreboard action readable - -Notes: - -- Browser plugin runtime tools were not exposed by tool discovery in this - session, so rendered QA used temporary headless Chrome/Selenium checks and - screenshots outside the repository. -- Targeted backend unittest output still includes existing SQLite resource - warnings from the current test suite while tests pass. -- Browser console output on rendered checks only reported the existing missing - `favicon.ico` request. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-147-persist-scoreboard-list-candidates.md b/ai/tasks/done/TASK-147-persist-scoreboard-list-candidates.md deleted file mode 100644 index 9b10103..0000000 --- a/ai/tasks/done/TASK-147-persist-scoreboard-list-candidates.md +++ /dev/null @@ -1,200 +0,0 @@ ---- -id: TASK-147 -title: Persist public scoreboard list matches as RCON candidates -status: done -type: backend -team: Backend Senior -supporting_teams: - - Arquitecto Python -roadmap_item: rcon-full-data -priority: high ---- - -# TASK-147 - Persist public scoreboard list matches as RCON candidates - -## Goal - -Make `scoreboard_candidate_backfill` persist safe rows into -`rcon_scoreboard_match_candidates` directly from `/api/get_scoreboard_maps` -list payloads, so public scoreboard URLs are available for RCON correlation -even if `/api/get_map_scoreboard` detail fetching fails, returns a different -shape, or lacks fields. - -## Background - -A real Foy match existed in the scoreboard public list: - -- scoreboard id: `1562115` -- server_number: `2` -- server slug: `comunidad-hispana-02` -- map: Foy Warfare -- start: `2026-05-20T20:54:11+00:00` -- end: `2026-05-20T22:24:11+00:00` -- score: allied `4` / axis `1` -- expected URL: `https://scoreboard.comunidadhll.es:5443/games/1562115` - -But it was not available as an RCON scoreboard candidate until manually -inserted. After manual insert and materialization, the match detail page -correctly showed `Ver en Scoreboard`. - -The backfill currently reads `/api/get_scoreboard_maps`, collects IDs, fetches -detail payloads, and calls `upsert_historical_match` from detail payloads. The -list payload already contains enough trusted data for a safe candidate: -`id`, `start`, `end`, `map.id`, `map.pretty_name`, `result.allied`, -`result.axis`, and `server_number`. - -## Constraints / DO NOT BREAK - -- Do not remove PostgreSQL migration logic. -- Do not switch back to SQLite. -- Do not break recent match cards. -- Do not show `Ver partida` in recent cards. -- Do not change detail-page scoreboard button behavior except enabling it when - `match_url` exists. -- Do not expose unsafe URLs. -- Do not generate scoreboard URLs from player names. -- Do not commit runtime DB files. - -## Allowed Changes - -- `backend/app/scoreboard_candidate_backfill.py` -- Existing backend storage/read-model helpers needed for the safe candidate - upsert path. -- Existing trusted scoreboard origin helpers needed to preserve URL safety. -- Focused backend scoreboard tests and fixtures/mocks. -- This task file when it moves through the task workflow. - -## Implementation Requirements - -1. Inspect: - - `backend/app/scoreboard_candidate_backfill.py` - - `backend/app/postgres_rcon_storage.py` - - `backend/app/postgres_display_storage.py` - - `backend/app/historical_storage.py` - - `backend/app/rcon_admin_log_materialization.py` - - `backend/app/rcon_historical_read_model.py` - - `backend/app/scoreboard_origins.py` -2. Add or reuse a safe upsert function for - `rcon_scoreboard_match_candidates`. -3. During `scoreboard_candidate_backfill`, for every list match inside the - requested window: - - build a candidate from the list payload - - validate `server_number` / `server_slug` mapping - - build `match_url` only from trusted scoreboard base URL and numeric - external match id - - persist candidate idempotently into - `rcon_scoreboard_match_candidates` -4. This candidate upsert must happen before `fetch_match_details`. -5. `fetch_match_details` must remain only for historical match/player stat - enrichment. -6. If `fetch_match_details` fails, the candidate row must still exist. -7. Add counters to the JSON report: - - `list_candidates_inserted` - - `list_candidates_updated` - - `list_candidates_skipped` - - detail candidate/detail match counters if useful -8. Keep existing historical upsert behavior. -9. Preserve trusted URL allowlist behavior. -10. Do not create candidates for untrusted origins. -11. Do not reintroduce Comunidad Hispana #03 as an active visible target. -12. Add tests covering a list payload equivalent to Foy `1562115`. -13. The test must prove: - - list payload alone persists candidate - - `match_url` is - `https://scoreboard.comunidadhll.es:5443/games/1562115` - - failure of detail fetch does not prevent candidate persistence - - operation is idempotent - -## Files to Read First - -- `AGENTS.md` -- `ai/architecture-index.md` -- `ai/repo-context.md` -- `ai/orchestrator/backend-senior.md` -- `backend/app/scoreboard_candidate_backfill.py` -- `backend/app/postgres_rcon_storage.py` - -## Expected Files to Modify - -- Backfill/storage helper files needed for the safe list-candidate upsert. -- Focused scoreboard tests covering list-only persistence and detail failure. -- This task file after moving it through the workflow. - -Keep the task within the allowed changes. If a storage boundary requires an -additional backend file from the inspected list, document why in the task -outcome. - -## Validation - -- `python -m compileall backend/app` -- `python -m unittest discover -s tests -p "*scoreboard*"` -- `python -m app.storage_diagnostics` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- `docker compose --profile advanced up -d --build backend frontend postgres` -- `docker compose exec backend python -m app.scoreboard_candidate_backfill --server comunidad-hispana-02 --from 2026-05-20T00:00:00Z --to 2026-05-21T23:59:59Z --max-pages 5 --page-size 100` -- Query `rcon_scoreboard_match_candidates` and verify external match id - `1562115` exists for `comunidad-hispana-02`. -- Invoke the detail endpoint for - `comunidad-hispana-02:1779310451:1779315851:foywarfare` and verify - `match_url` is present. -- Review `git diff --name-only` and confirm the changed files match this task. - -## Manual Verification - -1. Open: - `http://localhost:8080/historico-partida.html?server=comunidad-hispana-02&match=comunidad-hispana-02%3A1779310451%3A1779315851%3Afoywarfare` -2. Verify `Ver en Scoreboard` appears. -3. Verify it opens: - `https://scoreboard.comunidadhll.es:5443/games/1562115` -4. Verify recent cards still do not show the public scoreboard button. - -## Commit Message - -`fix: persist scoreboard list matches as rcon candidates` - -## Outcome - -Document validation, candidate upsert decisions, counters added to the JSON -report, and any follow-up task instead of widening this task. - -- Persisted list payload candidates before detail fetch through a focused - PostgreSQL upsert for `rcon_scoreboard_match_candidates`. -- Built list candidate URLs only from the trusted scoreboard origin catalog and - numeric public match IDs. List rows are accepted only when the selected - historical server slug/base URL/server number and payload `server_number` - agree with the trusted origin. -- Kept detail fetching for the existing `historical_*` match/player enrichment - path. The backfill report now exposes `list_candidates_inserted`, - `list_candidates_updated` and `list_candidates_skipped` independently from - the detail match counters. -- Added focused regression coverage for the Foy list row `1562115`; detail - fetch failure still leaves the list candidate present, and a second run - updates the same candidate key instead of creating a duplicate. -- Validation: - - `python -m compileall backend/app` - - `python -m unittest discover -s tests -p "*scoreboard*"` from `backend/` - passed with pre-existing SQLite `ResourceWarning` output in the scoreboard - regression file. - - `python -m app.storage_diagnostics` from `backend/` - - `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` - passed; the script reports no product integration tests configured for its - platform-only scope. - - `docker compose --profile advanced up -d --build backend frontend postgres` - - `docker compose exec backend python -m app.scoreboard_candidate_backfill - --server comunidad-hispana-02 --from 2026-05-20T00:00:00Z --to - 2026-05-21T23:59:59Z --max-pages 5 --page-size 100` - reported list candidate inserts/updates with no errors. - - Queried PostgreSQL and verified external match id `1562115` exists for - `comunidad-hispana-02` with URL - `https://scoreboard.comunidadhll.es:5443/games/1562115`. - - Invoked `/api/historical/matches/detail` for - `comunidad-hispana-02:1779310451:1779315851:foywarfare`; payload `found` - was true and `match_url` used the expected trusted URL. -- Scope review used `git diff --name-only`; changed implementation files stay - within this task plus this workflow task file. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split follow-up work into a new task if the scope grows. diff --git a/ai/tasks/done/TASK-148-relink-existing-rcon-matches-to-scoreboard-candidates.md b/ai/tasks/done/TASK-148-relink-existing-rcon-matches-to-scoreboard-candidates.md deleted file mode 100644 index a32fec4..0000000 --- a/ai/tasks/done/TASK-148-relink-existing-rcon-matches-to-scoreboard-candidates.md +++ /dev/null @@ -1,203 +0,0 @@ ---- -id: TASK-148 -title: Relink existing RCON matches to scoreboard candidates -status: done -type: backend -team: Backend Senior -supporting_teams: - - Arquitecto Python -roadmap_item: rcon-full-data -priority: high ---- - -# TASK-148 - Relink existing RCON matches to scoreboard candidates - -## Goal - -Add a deterministic relink flow that can update or resolve scoreboard URLs for -already-materialized RCON matches after new scoreboard candidates are inserted. - -## Background - -After manually inserting the Foy `1562115` candidate, the match detail page -showed the expected scoreboard button. Future backfills may insert candidates -after RCON matches already exist, so the system must relink existing RCON -matches with null or missing `match_url` dynamically or via materialization. - -Known Foy regression target: - -- RCON match key: - `comunidad-hispana-02:1779310451:1779315851:foywarfare` -- candidate external match id: `1562115` -- expected URL: `https://scoreboard.comunidadhll.es:5443/games/1562115` - -## Constraints / DO NOT BREAK - -- Do not relax trusted scoreboard URL allowlist. -- Do not link to unsafe origins. -- Do not choose ambiguous candidates silently. -- Do not break old Carentan match: - `comunidad-hispana-02:1779178461:1779183861:carentanwarfare` -- Do not break Kharkov: - `comunidad-hispana-02:1779315955:1779319098:kharkovwarfare` -- Do not re-add public scoreboard buttons to recent match cards. -- Do not expose correlation debug text in normal UI. - -## Allowed Changes - -- Existing RCON materialization, historical read-model, and RCON storage - modules needed for deterministic candidate relinking. -- `backend/app/scoreboard_candidate_backfill.py` only when needed to trigger - or document the relink sequence. -- A focused backend relink command module or a narrowly scoped command option - on existing materialization CLI. -- Focused backend scoreboard correlation tests and fixtures/mocks. -- This task file when it moves through the task workflow. - -## Implementation Requirements - -1. Inspect current correlation logic: - - `backend/app/rcon_admin_log_materialization.py` - - `backend/app/rcon_historical_read_model.py` - - `backend/app/postgres_rcon_storage.py` - - `backend/app/scoreboard_candidate_backfill.py` -2. Add or improve a function that matches RCON materialized matches to - `rcon_scoreboard_match_candidates` using: - - same server slug / external server id - - normalized map identity - - overlapping or close time window - - score allied/axis where present - - winner where present -3. Tolerances: - - allow reasonable time drift between RCON and scoreboard, at least - +/- 15 minutes, preferably configurable or centralized - - for matches with null `started_at` / `ended_at` but `closed_at` plus - `duration_seconds`, derive a correlation window -4. When a best safe candidate is found, make `match_url` available in detail - payload. -5. Prefer deterministic scoring: - - exact map match - - close end time - - score match - - same server - - reject ambiguous ties unless one candidate is clearly better -6. Add a command or option to relink existing matches without needing new - ingestion: - - acceptable command module: - `python -m app.rcon_scoreboard_relink` - - acceptable alternative: an option inside - `app.rcon_admin_log_materialization` -7. The relink command must print JSON summary: - - `matches_scanned` - - `candidates_scanned` - - `matches_linked` - - `matches_skipped_no_candidate` - - `matches_skipped_ambiguous` - - `errors` -8. Ensure `scoreboard_candidate_backfill` can optionally trigger relink at the - end, or document the command sequence. -9. Add regression coverage for the Foy case: - - RCON match key - `comunidad-hispana-02:1779310451:1779315851:foywarfare` - - candidate external match id `1562115` - - expected `match_url` - `https://scoreboard.comunidadhll.es:5443/games/1562115` -10. Ensure the detail endpoint returns `match_url` after relink. - -## Files to Read First - -- `AGENTS.md` -- `ai/architecture-index.md` -- `ai/repo-context.md` -- `ai/orchestrator/backend-senior.md` -- `backend/app/rcon_admin_log_materialization.py` -- `backend/app/rcon_historical_read_model.py` - -## Expected Files to Modify - -- Existing RCON correlation/materialization/storage code needed for relinking. -- One relink CLI entry point or one existing CLI option. -- Focused scoreboard correlation regression tests. -- This task file after moving it through the workflow. - -Keep correlation diagnostics out of this task except the JSON relink summary -required here. Use TASK-149 for detailed diagnostic output and docs. - -## Validation - -- `python -m compileall backend/app` -- `python -m unittest discover -s tests -p "*scoreboard*"` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- `docker compose --profile advanced up -d --build backend frontend postgres` -- `docker compose exec backend python -m app.scoreboard_candidate_backfill --server comunidad-hispana-02 --from 2026-05-20T00:00:00Z --to 2026-05-21T23:59:59Z --max-pages 5 --page-size 100` -- Run the new relink command. -- Use `Invoke-WebRequest` for the Foy detail payload and verify `found` is - true and `match_url` is present. -- Use `Invoke-WebRequest` for the Carentan detail payload and verify the - existing `match_url` is still present. -- Review `git diff --name-only` and confirm the changed files match this task. - -## Manual Verification - -1. Foy detail page shows `Ver en Scoreboard`. -2. Scoreboard button opens the `1562115` public URL. -3. Recent match cards still do not show public scoreboard links. -4. No `Detalle no disponible` state appears for the validated detail page. -5. Player filters and external profile links still work. - -## Commit Message - -`fix: relink rcon matches to scoreboard candidates` - -## Outcome - -Document correlation scoring choices, time-window derivation, ambiguity -handling, relink command output, validation, and any follow-up task instead of -expanding scope. - -- Added `python -m app.rcon_scoreboard_relink` to scan already-materialized - ended RCON matches against the same trusted candidate resolution used by the - detail read model. The command reports `matches_scanned`, - `candidates_scanned`, `matches_linked`, `matches_skipped_no_candidate`, - `matches_skipped_ambiguous` and `errors` as JSON. -- Kept URL availability dynamic in the read model instead of adding a second - persisted URL column to RCON matches. The new correlation resolution summary - preserves the existing deterministic map/time/duration/score scoring path, - returns explicit low-confidence/no-candidate/ambiguous reasons, and exposes - the selected external candidate only to command callers. -- Reused the existing materialized window derivation for closed-at plus - server-time duration cases so relink and detail payloads evaluate the same - effective correlation window. -- Added a Foy regression for materialized match key - `comunidad-hispana-02:1779310451:1779315851:foywarfare`: relink reports a - safe link and detail returns - `https://scoreboard.comunidadhll.es:5443/games/1562115`. -- Validation: - - `python -m compileall backend/app` - - `python -m unittest discover -s tests -p "*scoreboard*"` from `backend/` - passed with existing SQLite `ResourceWarning` output in the scoreboard - regression file. - - `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` - passed; the script reports no product integration tests configured for its - platform-only scope. - - `docker compose --profile advanced up -d --build backend frontend postgres` - - Re-ran `app.scoreboard_candidate_backfill` for the requested May 20-21 - window. Candidate refresh succeeded (`list_candidates_updated: 11`), while - detail enrichment returned a partial status because SQLite reported - `database is locked` for detail match `1562104`. - - `docker compose exec backend python -m app.rcon_scoreboard_relink --server - comunidad-hispana-02` reported 19 scanned matches, 13 linked matches, 6 - no-candidate skips, 0 ambiguous skips and no errors. - - HTTP detail verification returned `found: true` and the expected Foy URL. - Existing Carentan detail key - `comunidad-hispana-02:1779178461:1779183861:carentanwarfare` also kept a - trusted `match_url`. -- Scope review used `git diff --name-only`; relink changes stay within the - correlation/read-model command path, focused scoreboard tests and this task - file. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split follow-up work into a new task if the scope grows. diff --git a/ai/tasks/done/TASK-149-scoreboard-correlation-diagnostics.md b/ai/tasks/done/TASK-149-scoreboard-correlation-diagnostics.md deleted file mode 100644 index 4cd172c..0000000 --- a/ai/tasks/done/TASK-149-scoreboard-correlation-diagnostics.md +++ /dev/null @@ -1,182 +0,0 @@ ---- -id: TASK-149 -title: Add scoreboard correlation diagnostics -status: done -type: backend -team: Backend Senior -supporting_teams: - - PM -roadmap_item: rcon-full-data -priority: medium ---- - -# TASK-149 - Add scoreboard correlation diagnostics - -## Goal - -Make missing scoreboard links diagnosable without exposing debug clutter in the -normal UI. - -## Background - -When the Foy match had `match_url` null, investigation required manual -inspection of public pages, candidate tables, and historical tables. Backend -diagnostics should explain whether: - -- no candidates exist -- candidates exist but map/time/score mismatch -- candidates were ambiguous -- candidate URL was unsafe -- relink was not run - -The known Foy diagnostic target is: - -- server: `comunidad-hispana-02` -- RCON match key: - `comunidad-hispana-02:1779310451:1779315851:foywarfare` -- expected candidate when available: external match id `1562115` - -## Constraints / DO NOT BREAK - -- Do not add visible debug text to `historico-partida.html`. -- Do not add timeline/source/debug metadata back to normal UI. -- Do not change recent card layout. -- Do not require internet for unit tests. -- Use fixtures/mocks for tests. - -## Allowed Changes - -- A focused backend scoreboard correlation diagnostic command. -- Existing backend correlation/read helpers only when needed to reuse safe - candidate selection output. -- Focused backend tests using fixtures or mocks. -- Documentation explaining the missing-scoreboard-button debug sequence. -- This task file when it moves through the task workflow. - -## Implementation Requirements - -1. Add backend diagnostic capability for a given RCON match: - - preferred command: - `python -m app.scoreboard_correlation_diagnostics --server comunidad-hispana-02 --match comunidad-hispana-02:1779310451:1779315851:foywarfare` - - optional alternative: also expose it inside `storage_diagnostics`, but - never in normal frontend payloads -2. Diagnostic output must be JSON. -3. Include: - - `rcon_match_key` - - `server` - - `map` - - `started_at` / `ended_at` / `closed_at` / `duration_seconds` - - score - - candidate search window - - `candidate_count` - - top candidate summaries: - - `external_match_id` - - `started_at` - - `ended_at` - - map - - score - - `match_url` - - `correlation_score` - - `rejection_reason` if rejected - - `selected_candidate` if any - - `final_reason` -4. Add a specific diagnostic for the known Foy case. -5. Add docs explaining how to debug a missing scoreboard button: - - run `scoreboard_candidate_backfill` - - run relink - - run `scoreboard_correlation_diagnostics` - - inspect detail endpoint -6. Keep diagnostics out of normal UI. -7. Do not emit raw sensitive data. -8. Do not emit unsafe URLs. - -## Files to Read First - -- `AGENTS.md` -- `ai/architecture-index.md` -- `ai/repo-context.md` -- `ai/orchestrator/backend-senior.md` -- `backend/app/rcon_historical_read_model.py` -- Backend correlation/relink code delivered by TASK-148. - -## Expected Files to Modify - -- One backend diagnostic command module or the existing diagnostics module. -- Existing safe correlation/read helper files only if necessary. -- Focused backend diagnostic tests using fixtures/mocks. -- One focused documentation file for the debug workflow. -- This task file after moving it through the workflow. - -Do not add frontend debug surfaces or widen the normal detail payload for this -task. - -## Validation - -- `python -m compileall backend/app` -- `python -m app.scoreboard_correlation_diagnostics --server comunidad-hispana-02 --match comunidad-hispana-02:1779310451:1779315851:foywarfare` -- `python -m app.storage_diagnostics` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- `node --check frontend/assets/js/historico-partida.js` -- `node --check frontend/assets/js/historico.js` -- `node --check frontend/assets/js/historico-recent-live.js` -- Review `git diff --name-only` and confirm the changed files match this task. - -## Manual Verification - -1. Run diagnostics for Foy and verify it explains why `1562115` is selected or - why no candidate is selected. -2. Run diagnostics for a match without public candidate and verify it explains - no candidates found. -3. Normal frontend pages do not show diagnostics. - -## Commit Message - -`chore: add scoreboard correlation diagnostics` - -## Outcome - -Document diagnostic fields, known Foy output behavior, documentation added, -validation performed, and any follow-up task instead of expanding normal UI -payloads. - -- Added `python -m app.scoreboard_correlation_diagnostics` for one - materialized RCON match. JSON output includes match key, server, map, - timestamps, duration, score, candidate search window, safe top candidates, - selected candidate and `final_reason`. -- Candidate summaries expose trusted public `match_url` values only. Untrusted - URLs are omitted and receive `unsafe-url`; non-scoring candidates report - `map-or-window-mismatch` where applicable. -- Kept diagnostics out of normal detail and frontend payloads. The command - reuses the materialized correlation window and safe candidate scoring that - relink/detail use. -- Added `docs/scoreboard-correlation-debugging.md` with the missing-button - sequence: candidate backfill, relink scan, diagnostics command and detail - endpoint check. -- Extended focused Foy coverage so diagnostics select external match id - `1562115` with the expected Foy candidate summary. -- Validation: - - `python -m compileall backend/app` - - `python -m unittest discover -s tests -p "*scoreboard*"` from `backend/` - passed with existing SQLite `ResourceWarning` output in the scoreboard - regression file. - - `python -m app.scoreboard_correlation_diagnostics --server - comunidad-hispana-02 --match - comunidad-hispana-02:1779310451:1779315851:foywarfare` from `backend/` - returned `final_reason: linked` and selected candidate `1562115`. - - `python -m app.storage_diagnostics` - - `node --check frontend/assets/js/historico-partida.js` - - `node --check frontend/assets/js/historico.js` - - `node --check frontend/assets/js/historico-recent-live.js` - - `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` - exited successfully after reporting its platform checks. Its later local - route probe printed a SQLite `database disk image is malformed` traceback - from `historical_storage`; this task did not alter or repair runtime DB - files. -- Scope review used `git diff --name-only`; diagnostics changes stay in the - correlation command/test/doc path and this task file. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split follow-up work into a new task if the scope grows. diff --git a/ai/tasks/done/TASK-150-server-card-history-and-current-match-entrypoints.md b/ai/tasks/done/TASK-150-server-card-history-and-current-match-entrypoints.md deleted file mode 100644 index f89246b..0000000 --- a/ai/tasks/done/TASK-150-server-card-history-and-current-match-entrypoints.md +++ /dev/null @@ -1,190 +0,0 @@ ---- -id: TASK-150 -title: Server card history and current match entrypoints -status: done -type: frontend -team: Frontend Senior -supporting_teams: [] -roadmap_item: rcon-full-data -priority: high ---- - -# TASK-150 - Server card history and current match entrypoints - -## Goal - -Add server-specific navigation buttons to the home page and make the internal -historical page accept an initial server filter through the URL. - -## Background - -The home page currently renders live server cards in -`frontend/assets/js/main.js`. Each server card currently has a single -"Historico" action built through `renderServerAction(server)`. - -We need clearer per-server actions for the active Comunidad Hispana servers: - -- Open the public current scoreboard. -- Open our internal historical page already filtered by that server. -- Open our future internal live/current match page already filtered by that - server. - -Important URL correction: - -The current public scoreboard URLs are the base scoreboard URLs, without -`/games`: - -- `comunidad-hispana-01` -> `https://scoreboard.comunidadhll.es` -- `comunidad-hispana-02` -> `https://scoreboard.comunidadhll.es:5443` - -The `/games` URLs are only for the external public historical scoreboard, if -needed later: - -- `comunidad-hispana-01` -> `https://scoreboard.comunidadhll.es/games` -- `comunidad-hispana-02` -> `https://scoreboard.comunidadhll.es:5443/games` - -## Constraints / DO NOT BREAK - -- Do not change backend storage. -- Do not change RCON ingestion. -- Do not change scoreboard correlation logic. -- Do not depend on server #03. -- Do not expose arbitrary URLs received from API payloads. -- Do not remove existing server card live status rendering. -- Do not implement the full live match page in this task. -- Keep the change frontend-focused and minimal. -- Preserve existing responsive layout. - -## Allowed Changes - -- `frontend/assets/js/main.js` -- `frontend/assets/css/main.css` or equivalent home CSS file -- historical page JS/CSS/HTML files needed to support `?server=` -- optionally add a minimal placeholder `partida-actual.html` if needed to - avoid a broken link -- docs only if needed - -## Implementation Requirements - -1. Replace the current single "Historico" server-card action with a small - action group. -2. For each active supported server, render these actions: - - "Scoreboard público" - - "Nuestro histórico" - - "Partida actual" -3. "Scoreboard público" must open the current public scoreboard base URL: - - `comunidad-hispana-01` -> `https://scoreboard.comunidadhll.es` - - `comunidad-hispana-02` -> `https://scoreboard.comunidadhll.es:5443` - It must NOT append `/games`. -4. "Nuestro histórico" must open the internal historical page with a server - query parameter: - - `historico.html?server=comunidad-hispana-01` - - `historico.html?server=comunidad-hispana-02` -5. "Partida actual" must open: - - `partida-actual.html?server=comunidad-hispana-01` - - `partida-actual.html?server=comunidad-hispana-02` -6. Add trusted frontend mappings for supported active servers only: - - `comunidad-hispana-01` - - `comunidad-hispana-02` - Do not add server #03. -7. The server identifier should be resolved from the server payload using - `external_server_id` or another already existing stable server slug. If the - server cannot be resolved to a trusted known server, do not render - public/current-match actions for it. -8. Update the historical page initialization so that: - - `?server=comunidad-hispana-01` selects Comunidad Hispana #01 instead of - defaulting to all servers. - - `?server=comunidad-hispana-02` selects Comunidad Hispana #02 instead of - defaulting to all servers. - - unknown or missing server query values fall back to the current default - behavior. -9. If `partida-actual.html` does not exist yet, create a minimal placeholder - page that: - - reads `?server=` - - displays "Partida actual" - - displays the selected server slug/name - - explains that the live detail view will be implemented in the next task - - includes a safe link back to the home page and historical page - Do not implement live data polling yet. -10. Ensure all generated URLs are built from trusted constants, not directly - from API-provided arbitrary values. - -## Files to Read First - -- `AGENTS.md` -- `ai/architecture-index.md` -- `ai/repo-context.md` -- `ai/orchestrator/frontend-senior.md` -- `frontend/assets/js/main.js` -- historical page files used for the existing server filter flow - -## Expected Files to Modify - -- `frontend/assets/js/main.js` -- home CSS only if the new action group needs layout styling -- historical page files needed for `?server=` initialization -- `partida-actual.html` only if a placeholder is needed - -## Validation - -- Run `node --check` on every modified frontend JS file. -- Review `git diff --name-only` and confirm the changed files match this task. - -## Manual Verification - -1. Open the home page. -2. Verify Comunidad Hispana #01 card shows: - - Scoreboard público - - Nuestro histórico - - Partida actual -3. Verify Comunidad Hispana #02 card shows: - - Scoreboard público - - Nuestro histórico - - Partida actual -4. Click "Scoreboard público" for Comunidad Hispana #01 and verify it opens: - `https://scoreboard.comunidadhll.es` -5. Click "Scoreboard público" for Comunidad Hispana #02 and verify it opens: - `https://scoreboard.comunidadhll.es:5443` -6. Click "Nuestro histórico" for Comunidad Hispana #01 and verify the - historical page loads with Comunidad Hispana #01 selected. -7. Click "Nuestro histórico" for Comunidad Hispana #02 and verify the - historical page loads with Comunidad Hispana #02 selected. -8. Click "Partida actual" for both servers and verify the page opens with the - correct server query parameter. -9. Verify no server #03 action is introduced. - -## Commit Message - -`feat: add current match server entrypoints` - -## Expected Outcome - -The home page exposes clear per-server navigation actions, and the internal -historical page can open directly filtered by server. - -## Outcome - -- Replaced the home server-card history URL path with a trusted frontend action - catalog for active servers `comunidad-hispana-01` and - `comunidad-hispana-02` only. Payload-provided `community_history_url` - values and the previous server #03 fallback are no longer used for those - card actions. -- Added the three per-server entrypoints from trusted constants: public - scoreboard base URL, internal historical filter URL and internal current - match URL. -- Confirmed `frontend/assets/js/historico.js` already normalizes the supported - `?server=` values into the active selector and falls back to `all-servers` - for unknown or missing values, so no historical page code change was needed. -- Added a minimal `partida-actual.html` placeholder with a trusted server label - map and safe internal links for TASK-151 to upgrade. -- Validation: `node --check frontend/assets/js/main.js`. -- Scope review: `git diff --name-only` and `git status --short` were reviewed - for the task move plus frontend files. Browser click verification was not - completed because the in-app browser JavaScript control tool was not - available after tool discovery in this session. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if the scope grows. diff --git a/ai/tasks/done/TASK-151-current-match-page-base.md b/ai/tasks/done/TASK-151-current-match-page-base.md deleted file mode 100644 index cc129fc..0000000 --- a/ai/tasks/done/TASK-151-current-match-page-base.md +++ /dev/null @@ -1,190 +0,0 @@ ---- -id: TASK-151 -title: Current match page base -status: done -type: frontend -team: Frontend Senior -supporting_teams: - - Backend Senior -roadmap_item: rcon-full-data -priority: high ---- - -# TASK-151 - Current match page base - -## Goal - -Create the first functional internal "Partida actual" page for active -Comunidad Hispana servers. - -## Background - -The home page will link to -`partida-actual.html?server=`. We need the first real version of -our internal current-match page. - -This page should be visually aligned with the existing historical match detail -page, but it represents a live match instead of a closed historical match. - -Important public scoreboard URLs: - -- `comunidad-hispana-01` -> `https://scoreboard.comunidadhll.es` -- `comunidad-hispana-02` -> `https://scoreboard.comunidadhll.es:5443` - -These are base URLs for the current public scoreboard and must not include -`/games`. - -## Constraints / DO NOT BREAK - -- Do not break the existing historical page. -- Do not break the existing match detail page. -- Do not change scoreboard correlation logic. -- Do not implement the live kill feed in this task unless there is already a - safe endpoint that can be reused trivially. -- Do not fabricate closed-match data. -- Do not show final winner/duration/closed_at for a live match. -- Do not depend on server #03. -- Do not expose untrusted public scoreboard URLs. -- Keep polling moderate and safe. - -## Allowed Changes - -- `partida-actual.html` -- new frontend JS/CSS for current match page -- backend API endpoint only if needed -- backend read-model code only if needed for current live state -- tests where practical - -## Implementation Requirements - -1. Create or upgrade `partida-actual.html` as a real live-current-match page. -2. The page must read `?server=` from the URL. -3. Supported server values: - - `comunidad-hispana-01` - - `comunidad-hispana-02` -4. Unknown server values must show a safe error/empty state and must not build - external URLs from the unknown value. -5. Add trusted current public scoreboard links: - - `comunidad-hispana-01` -> `https://scoreboard.comunidadhll.es` - - `comunidad-hispana-02` -> `https://scoreboard.comunidadhll.es:5443` -6. Add a "Ver scoreboard público" button using the trusted base URL for that - server. -7. The page should display a live-match header with: - - server name - - live/online status - - current map - - game mode if available - - `started_at` if available - - current players / max players if available - - last updated/captured timestamp -8. The page should display a scoreboard panel: - - allied score if available - - axis score if available - - neutral state if scores are unavailable -9. Do not display: - - final duration - - final winner - - `closed_at` - - any copy implying that the match has finished -10. Add a placeholder section for future live kill feed: - - title: "Feed de combate" - - text explaining that live kill events will appear here when enabled - - no fake kill rows -11. Add a player table section if current player stats are already available - from existing APIs. If they are not available, show a clean placeholder: - - "Las estadísticas en vivo aparecerán cuando haya datos suficientes." -12. Add frontend polling with safe in-flight protection: - - default interval: 30 seconds - - avoid overlapping requests - - show stale/error states clearly -13. If no backend endpoint exists for current match state, add a minimal - endpoint that derives the current server state from existing live/RCON - snapshot data. Keep it read-only. -14. The endpoint response should be stable and minimal: - - server slug/name - - status - - map - - `game_mode` - - `started_at` - - `allied_score` - - `axis_score` - - players - - `max_players` - - `captured_at`/`updated_at` - - `public_scoreboard_url` from trusted mapping - -## Files to Read First - -- `AGENTS.md` -- `ai/architecture-index.md` -- `ai/repo-context.md` -- `ai/orchestrator/frontend-senior.md` -- current historical match detail frontend files -- live server backend/read-model files used by the existing server cards - -## Expected Files to Modify - -- `partida-actual.html` -- new current-match frontend JS/CSS files as needed -- minimal live-state backend endpoint/read-model files only if existing APIs - cannot supply the page state -- focused tests where practical - -## Validation - -- `python -m compileall backend/app` -- Run backend tests relevant to live server/read model if available. -- Run `node --check` on modified/new frontend JS files. -- Review `git diff --name-only` and confirm the changed files match this task. - -## Manual Verification - -1. Open `partida-actual.html?server=comunidad-hispana-01`. -2. Open `partida-actual.html?server=comunidad-hispana-02`. -3. Verify the public scoreboard button opens: - - `https://scoreboard.comunidadhll.es` - - `https://scoreboard.comunidadhll.es:5443` -4. Verify `/games` is not used for the current public scoreboard button. -5. Verify no final/closed-match fields are shown. -6. Verify unknown server query values do not create unsafe links. - -## Commit Message - -`feat: add current match page base` - -## Expected Outcome - -A safe first version of the internal current-match page exists and can display -live server/match state without pretending the match is closed. - -## Outcome - -- Upgraded `partida-actual.html` into the first internal live match page and - kept it aligned with the existing historical shell/styles. -- Added frontend polling every 30 seconds with an in-flight guard. The page - rejects unknown `?server=` values before building any external link, and the - public scoreboard button is populated only from the trusted backend - projection. -- Added read-only `GET /api/current-match?server=`. It supports only active - trusted scoreboard origins and projects the existing live server snapshot - fields into the current-match shape. The current live snapshot persistence - exposes status, map, population and capture time; score, game mode and match - start fields remain `null`/unavailable when the snapshot source does not - provide them. -- Kept the combat feed and live player statistics as honest empty placeholders - for the follow-up tasks rather than fabricating closed-match or kill data. -- Validation: `python -m compileall backend/app`; - `node --check frontend/assets/js/partida-actual.js`; - `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1`; - narrow inline route guard check for missing/unknown current-match server - values; narrow inline payload projection check using a controlled live - snapshot document. -- Scope review: `git diff --name-only` and `git status --short` were reviewed. - No focused product route test file exists in `backend/tests` for this API - bootstrap layer yet. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if the scope grows. diff --git a/ai/tasks/done/TASK-152-current-match-live-kill-feed.md b/ai/tasks/done/TASK-152-current-match-live-kill-feed.md deleted file mode 100644 index ba5bcff..0000000 --- a/ai/tasks/done/TASK-152-current-match-live-kill-feed.md +++ /dev/null @@ -1,174 +0,0 @@ ---- -id: TASK-152 -title: Current match live kill feed -status: done -type: backend -team: Backend Senior -supporting_teams: - - Frontend Senior -roadmap_item: rcon-full-data -priority: high ---- - -# TASK-152 - Current match live kill feed - -## Goal - -Expose recent current-match kill events and render them as a live visual feed -on `partida-actual.html`. - -## Background - -The current-match page will exist at -`partida-actual.html?server=`. The backend already stores/parses -RCON AdminLog data and materializes kill/player stats for historical matches. - -Existing materialization logic uses AdminLog kill payload fields such as: - -- `killer_id` -- `killer_name` -- `killer_team` -- `victim_id` -- `victim_name` -- `victim_team` -- `weapon` - -We now want a live/current-match kill feed similar to a FPS kill feed: killer, -weapon, victim, teamkill distinction, timestamp. - -## Constraints / DO NOT BREAK - -- Do not query RCON directly from the frontend. -- Do not expose raw AdminLog lines. -- Do not expose admin-only/sensitive fields. -- Do not break existing historical materialization. -- Do not break existing match detail player stats. -- Do not depend on server #03. -- Do not fabricate kill events. -- Do not duplicate kill rows on repeated polling. -- Keep polling safe. - -## Allowed Changes - -- backend endpoint for current match kill feed -- backend read-model/helper for current/open match event window -- frontend current-match JS/CSS -- tests for event normalization/filtering where practical - -## Implementation Requirements - -1. Add a backend endpoint for recent current-match kill events by server. -2. Supported servers: - - `comunidad-hispana-01` - - `comunidad-hispana-02` -3. Unknown server values must return a safe 400/404 style response and must - not query arbitrary targets. -4. The endpoint should return normalized event rows: - - `event_id` - - `event_timestamp` or `server_time` - - `killer_name` - - `killer_team` - - `victim_name` - - `victim_team` - - `weapon` - - `is_teamkill` - - confidence/source if needed -5. The endpoint should only return events belonging to the current/open match - if that can be determined. -6. If the current/open match window cannot be determined reliably, return a - safe recent window and include a clear confidence marker, for example: - - scope: `"recent-admin-log-window"` - - confidence: `"partial"` -7. Do not return raw AdminLog text. -8. Add frontend rendering for a kill feed: - - newest events visible at top or bottom consistently - - killer name - - weapon label/icon placeholder - - victim name - - timestamp - - teamkill visual distinction -9. Prevent duplicate rendering: - - track `event_id` values already rendered - - update existing rows only if needed -10. Poll every 15-30 seconds. -11. Add an empty state: - - "Todavía no se han detectado bajas en esta partida." -12. Add an error/stale state: - - "No se pudo actualizar el feed de combate." -13. Do not show fake/sample kill events in production UI. - -## Files to Read First - -- `AGENTS.md` -- `ai/architecture-index.md` -- `ai/repo-context.md` -- `ai/orchestrator/backend-senior.md` -- current-match page files created by TASK-151 -- AdminLog materialization/read-model files that already normalize kill data - -## Expected Files to Modify - -- backend current-match kill feed endpoint/read-model files -- current-match frontend JS/CSS files -- focused tests for event normalization/filtering where practical - -## Validation - -- `python -m compileall backend/app` -- Run backend tests related to AdminLog/materialization/current-match feed. -- Run `node --check` on current-match frontend JS. -- Review `git diff --name-only` and confirm the changed files match this task. - -## Manual Verification - -1. Open `partida-actual.html?server=comunidad-hispana-01`. -2. Open `partida-actual.html?server=comunidad-hispana-02`. -3. Verify kill feed renders only normalized events. -4. Verify repeated polling does not duplicate rows. -5. Verify teamkills are visually distinguishable. -6. Verify raw AdminLog lines are never displayed. - -## Commit Message - -`feat: add current match live kill feed` - -## Expected Outcome - -The current-match page can show a safe, normalized, non-duplicated live kill -feed based on RCON/AdminLog data. - -## Outcome - -- Added read-only `GET /api/current-match/kills?server=&limit=` for the active - trusted Comunidad Hispana servers. Unsupported servers fail before any - AdminLog query is built. -- Added a safe AdminLog kill feed read that emits normalized fields only: - generated `event_id`, event time/server time, killer/victim names and teams, - weapon, and computed `is_teamkill`. It does not return raw AdminLog text, - player ids or admin-only payload fields. -- Feed scope prefers `open-admin-log-match-window` with - `confidence: "admin-log-boundary"` when the latest AdminLog boundary for the - server is an unmatched `match_start`. Otherwise it returns - `recent-admin-log-window` with `confidence: "partial"` as the explicit - fallback. -- Extended `partida-actual.js` to poll the feed with the existing 30-second - in-flight-protected current-match refresh cycle, dedupe rows by `event_id`, - keep newest events ordered by server/event time, render a TK badge for - teamkills, and show empty/error states without fake rows. -- Added a focused AdminLog storage test for open-window filtering and teamkill - normalization. The environment does not have `pytest` installed (`pytest` - and `python -m pytest` both failed), so the same storage normalization path - was verified with a narrow inline Python scenario. -- Validation: `python -m compileall backend/app`; - `node --check frontend/assets/js/partida-actual.js`; - `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1`; - narrow inline route guard check for missing, unknown and invalid-limit feed - requests; inline storage normalization check excluding pre-window kills and - confirming no raw message field leaks. -- Scope review: `git diff --name-only` and `git status --short` were reviewed. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if the scope grows. diff --git a/ai/tasks/done/TASK-153-fix-current-match-live-projection.md b/ai/tasks/done/TASK-153-fix-current-match-live-projection.md deleted file mode 100644 index 3df8aa1..0000000 --- a/ai/tasks/done/TASK-153-fix-current-match-live-projection.md +++ /dev/null @@ -1,110 +0,0 @@ ---- -id: TASK-153 -title: Fix current match live projection -status: done -type: backend -team: Backend Senior -supporting_teams: - - Frontend Senior -roadmap_item: rcon-full-data -priority: high ---- - -# TASK-153 - Fix current match live projection - -## Goal - -Project trusted live RCON match data onto the current-match page without -misrepresenting player population or stale AdminLog kills as current activity. - -## Context - -`/api/current-match` currently reads through `/api/servers`. The direct RCON -sample already contains `game_mode` and scores, but the server snapshot -projection drops those richer live fields. Direct RCON `playerCount` is also -currently reporting `0` while manual public scoreboard observation shows `1`, -so that population value must be labeled unverified instead of shown as a -confident live count. - -## Steps - -1. Inspect the listed current-match, live RCON and AdminLog files first. -2. Keep the trusted current scoreboard URL mapping and unsupported-server - guards intact. -3. Rework the live payload, kill-feed freshness handling and current-match UI. -4. Add focused backend tests and validate the frontend JavaScript. - -## Files to Read First - -- `AGENTS.md` -- `ai/architecture-index.md` -- `ai/repo-context.md` -- `backend/app/payloads.py` -- `backend/app/rcon_client.py` -- `frontend/assets/js/partida-actual.js` - -## Expected Files to Modify - -- `backend/app/payloads.py` -- `backend/app/rcon_admin_log_storage.py` -- `backend/tests/test_rcon_admin_log_storage.py` -- `backend/tests/test_current_match_payload.py` -- `frontend/partida-actual.html` -- `frontend/assets/js/partida-actual.js` -- current-match styling only where needed - -## Constraints - -- Do not break historical pages or scoreboard correlation logic. -- Do not depend on Comunidad Hispana #03. -- Do not fabricate live data or expose arbitrary public URLs. -- Keep current scoreboard buttons on trusted base URLs without `/games`. -- Preserve null versus explicit zero semantics. -- Do not display closed-match fields or stale kill rows as live data. - -## Validation - -- `python -m compileall backend/app` -- Run focused backend tests for current-match payload and AdminLog kill feed. -- `node --check frontend/assets/js/partida-actual.js` -- Review `git diff --name-only` against this task scope. - -## Outcome - -- `/api/current-match` now queries the requested configured trusted RCON target - for the richer session projection first and falls back to the generic live - server snapshot only when direct RCON data is unavailable. -- RCA: direct RCON `GetServerInformation` samples contain `game_mode`, scores, - map ids and match timing fields. The prior current-match API lost the game - mode and score because it projected through `/api/servers`, whose snapshot - shape keeps only the server-card live fields. -- RCA: live validation on May 21, 2026 still returned RCON `playerCount: 0` - while manual scoreboard observation for the same servers had shown `1`. - Current-match payloads therefore expose RCON population with - `player_count_quality: "rcon-session-unverified"` and the frontend renders - that as `No verificado` instead of a confident `0 / 100`. -- The live page now mirrors the historical detail layout direction: map title, - server context, map art or a clean placeholder, a large in-progress - scoreboard, live metadata only, and trusted base scoreboard buttons. -- AdminLog current-match fallback kills are capped to a conservative 15-minute - freshness window. Old fallback rows now return - `scope: "no-current-match-events"` with stale-filter metadata instead of - leaking into the live feed. -- Added focused tests for direct current-match payload projection and AdminLog - fallback freshness. The repository environment and the rebuilt backend image - do not install `pytest`, so the focused test files could not be executed via - `python -m pytest`; the same payload and freshness paths were exercised with - narrow inline Python scenarios. -- Validation: `python -m compileall backend/app`; - `node --check frontend/assets/js/partida-actual.js`; - `git diff --check`; - `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1`; - rebuilt Compose `backend` and `frontend`; REST checks for both trusted - `/api/current-match` endpoints and both kill-feed endpoints; served map asset - checks for Carentan and St. Marie Du Mont; unsupported current-match server - REST check returned 404. - -## Change Budget - -The requested projection spans backend, tests and the live page. Keep changes -focused on current-match files and split unrelated work out. diff --git a/ai/tasks/done/TASK-154-current-match-killfeed-overlay-layout.md b/ai/tasks/done/TASK-154-current-match-killfeed-overlay-layout.md deleted file mode 100644 index cf50026..0000000 --- a/ai/tasks/done/TASK-154-current-match-killfeed-overlay-layout.md +++ /dev/null @@ -1,198 +0,0 @@ -# TASK-154 - Current match killfeed overlay layout - -Status: in-progress - -## Goal - -Redesign the current-match kill feed frontend so it behaves like a compact live killfeed overlay. - -## Background - -The current-match page already renders a kill feed using: - -- `GET /api/current-match/kills?server=...` - -The feed currently appears as a vertical list of large historical-style cards. This is not the desired UX. - -## Desired UX - -The kill feed should look like a compact live FPS-style overlay: - -- A rectangular live panel. -- Events rendered as compact rows/chips. -- Each event should show: - - killer name - - weapon icon or weapon label fallback - - victim name -- Events should be arranged in three visual columns inside the panel. -- New events should appear progressively. -- Older events should move left and eventually disappear. -- The feed should feel like a real-time combat screen, not a historical list. - -The user explicitly wants: - -- "una especie de pantalla en tiempo real" -- "simplemente se muestre el texto, el que mata, el arma y alguien mata" -- "iconos del arma que se utiliza" -- "una pequeña pantalla rectangular" -- "se irá poniendo de arriba abajo en tres columnas" -- "se irá desplazando hacia la izquierda e irán desapareciendo las más antiguas" - -## Scope - -Replace the current large-card kill feed with a compact live overlay on the current-match page. - -Allowed changes: - -- `frontend/assets/js/partida-actual.js` -- `frontend/partida-actual.html` if needed -- `frontend/assets/css/historico.css` or the relevant CSS used by `partida-actual.html` -- `frontend/assets/css/styles.css` only if the current-match page depends on it -- `frontend/assets/img/weapons/*` if local weapon icons/placeholders are added -- backend only if a small weapon normalization field is needed, but prefer frontend-side mapping first -- focused tests or node validation - -## Constraints - DO NOT BREAK - -- Do not break `/api/current-match/kills`. -- Do not expose raw AdminLog lines. -- Do not fabricate kill events. -- Do not show stale kills as live kills. -- Do not break the current-match scoreboard/header. -- Do not break historical match detail pages. -- Do not query RCON directly from the frontend. -- Do not depend on server #03. -- Do not require external/CDN assets at runtime. -- If weapon icons are added, they must be local/static assets or generated lightweight inline/SVG placeholders. -- Keep the UI responsive. - -## Files to inspect first - -Read: - -- `frontend/partida-actual.html` -- `frontend/assets/js/partida-actual.js` -- the CSS currently used by `frontend/partida-actual.html` -- focused current-match kill feed tests or validation scripts if present - -Inspect the current kill feed rendering, `event_id` handling, scope copy, and current polling behavior before changing code. - -## Implementation requirements - -### 1. Compact live panel - -Replace the current large-card feed rendering with a compact live killfeed panel. - -The panel must be visually rectangular and compact. It should look like a live combat overlay, not a list of historical cards. - -### 2. Layout - -- Use a three-column visual layout on desktop. -- Events should fill vertically within a column, then continue through the next visual position. -- Newer events should be visually prioritized. -- Older events should shift left and disappear once the maximum number of visible events is exceeded. -- On narrow/mobile widths, fall back to one or two columns without overflow. - -### 3. Event content - -Each kill event must show: - -- killer name -- weapon icon or weapon label -- victim name -- optional timestamp only if it does not make the UI noisy -- teamkill indicator if `is_teamkill` is true - -### 4. Weapon icons - -Add a safe mapping for common weapons currently seen in AdminLog examples: - -- `M1 GARAND` -- `MP40` -- `M1A1 THOMPSON` -- `UNKNOWN` - -Prefer local SVG/icon placeholders if real weapon assets are not available. - -- Do not hotlink external images. -- Unknown weapons must show a generic weapon icon/label fallback. -- The icon mapping should be easy to extend later. - -### 5. Motion and transition - -- Use CSS transitions/animations only if they are subtle. -- Avoid layout jumps. -- Respect users with reduced motion if possible. -- The feed should not flicker every poll. - -### 6. Deduplication - -- Preserve existing `event_id` deduplication. -- Re-rendering must not duplicate rows. -- Repeated polling must keep already visible events stable. - -### 7. Maximum visible events - -- Limit visible events to a reasonable number, for example 12 or 15. -- Older events should be dropped from the visual panel. -- Do not render an infinitely growing list. - -### 8. Copy - -Use these messages: - -- If there are no events: "Todavía no se han detectado bajas en esta partida." -- If scope is open match window: "Bajas detectadas en la partida actual." -- If scope is `recent-admin-log-window`: "Cobertura parcial desde AdminLog reciente." -- If stale/no current events: "Sin bajas recientes asociadas a la partida actual." - -### 9. Accessibility - -- Keep `aria-live` polite or equivalent. -- Event text must remain readable even if icons fail. - -## Validation - -Run: - -- `node --check frontend/assets/js/partida-actual.js` -- any existing frontend validation if available - -## Manual verification checklist - -- Open `http://localhost:8080/partida-actual.html?server=comunidad-hispana-01`. -- Open `http://localhost:8080/partida-actual.html?server=comunidad-hispana-02`. -- Verify kill feed appears as a compact rectangular live overlay. -- Verify events render as killer -> weapon/icon -> victim. -- Verify it uses three columns on desktop. -- Verify old events disappear instead of growing endlessly. -- Verify repeated polling does not duplicate events. -- Verify teamkills are visually distinguishable. -- Verify unknown weapons use a clean fallback. -- Verify no raw AdminLog line is shown. -- Verify no external image URLs are required. - -## Expected outcome - -The current-match kill feed looks and behaves like a compact live FPS-style killfeed overlay with local/fallback weapon icon support. - -## AI Platform lifecycle - -After implementation and validation: - -- Move this task according to the lifecycle defined in `AGENTS.md`. -- Do not mark unrelated tasks as done automatically. - -## Outcome - -- Replaced the historical-style kill cards with a capped 15-event rectangular overlay in `partida-actual`. -- Kept `event_id` deduplication and avoided poll flicker by only re-rendering when the visible event-id set changes. -- Rendered older visible events first so they occupy the left side of the three-column desktop panel while newer events remain visually prioritized on the right. -- Added local text-glyph weapon placeholders for `M1 GARAND`, `MP40`, `M1A1 THOMPSON` and unknown/other weapons without external assets. -- Validation run: - - `node --check frontend/assets/js/partida-actual.js` - - `scripts/run-historical-ui-regression-tests.ps1` - - `git diff --check` - - `git diff --name-only` -- Scope review: changed product files are `frontend/assets/js/partida-actual.js` and `frontend/assets/css/historico.css`. -- Manual/rendered Browser QA remains to be repeated when the Browser automation entry point is exposed; the local frontend and backend current-match endpoints were reachable during validation. diff --git a/ai/tasks/done/TASK-155-current-match-live-player-stats.md b/ai/tasks/done/TASK-155-current-match-live-player-stats.md deleted file mode 100644 index f904903..0000000 --- a/ai/tasks/done/TASK-155-current-match-live-player-stats.md +++ /dev/null @@ -1,245 +0,0 @@ -# TASK-155 - Current match live player stats - -Status: in-progress - -## Goal - -Investigate and implement live player/statistics rendering for the current-match page using the safest available data source. - -## Background - -The current-match page has an "Estadísticas en vivo" section, but it currently remains a placeholder: - -> "Las estadísticas en vivo aparecerán cuando haya datos suficientes." - -The user reports that players are not being shown. - -Known context: - -- `/api/current-match` exposes players and team player counts from RCON `getSession`, but those counts may be marked as `rcon-session-unverified`. -- Public scoreboard can show player population even when RCON `getSession` reports 0. -- AdminLog kill events already expose player names through normalized kill feed rows. -- Historical materialization already derives player stats from AdminLog data for completed matches. -- The current-match page should eventually show useful live player rows, but only if data is reliable enough. - -## Scope - -Investigate the available live player data sources and wire the current-match page to a safe current player statistics payload. - -Allowed changes: - -- `backend/app/routes.py` -- `backend/app/payloads.py` -- `backend/app/rcon_admin_log_storage.py` -- backend read-model/helper files if needed -- `frontend/assets/js/partida-actual.js` -- `frontend/partida-actual.html` -- `frontend/assets/css/historico.css` or relevant CSS -- focused backend tests - -## Constraints - DO NOT BREAK - -- Do not fabricate player stats. -- Do not show an empty/misleading table as if it were real data. -- Do not show RCON `getSession` `playerCount=0` as reliable if quality is `rcon-session-unverified`. -- Do not expose raw AdminLog lines. -- Do not expose admin-only/sensitive data. -- Do not break historical materialization. -- Do not break historical match detail stats. -- Do not query RCON directly from the frontend. -- Do not depend on server #03. -- Do not scrape the public scoreboard unless explicitly chosen and documented as a safe server-side fallback. -- Keep current public scoreboard URLs trusted and without `/games`. - -## Files to inspect first - -Read: - -- `frontend/partida-actual.html` -- `frontend/assets/js/partida-actual.js` -- `backend/app/routes.py` -- `backend/app/payloads.py` -- `backend/app/rcon_admin_log_storage.py` -- focused tests and historical player stat materialization helpers related to current-match or AdminLog data - -Inspect the existing RCON session payload, current kill feed freshness logic, open AdminLog match window support, and historical player stat aggregation before choosing a source. - -## Required investigation before implementation - -Perform RCA first and determine what live player data sources currently exist: - -- RCON session payload -- any RCON player-list command/wrapper already available in the codebase -- AdminLog kill/death events -- existing historical player stat materialization -- current open AdminLog match window if available - -Document the chosen source in the done task notes: - -- what was available -- what was not available -- whether stats are complete, partial, or event-derived - -## Implementation requirements - -### 1. Backend endpoint - -Add or extend a backend endpoint for current-match player stats. - -Preferred route: - -- `GET /api/current-match/players?server=...` - -### 2. Supported servers - -Support: - -- `comunidad-hispana-01` -- `comunidad-hispana-02` - -### 3. Unknown server values - -- Return a safe 400/404 style response. -- Do not query arbitrary targets. - -### 4. Data model - -The endpoint should return: - -- `server_slug` -- `server_name` -- `scope` -- `confidence` -- `source` -- `captured_at` or `updated_at` -- `items`: array of player rows - -### 5. Player row fields - -Include only fields that can be supported reliably: - -- `player_name` -- `team` if known -- `kills` if known -- `deaths` if known -- `teamkills` if known -- `deaths_by_teamkill` if known -- `favorite_weapon` or `most_used_weapon` if known -- `last_seen_at` if known -- `confidence`/`source` if needed - -### 6. AdminLog-derived data - -If using AdminLog-derived data: - -- Clearly mark scope/confidence as partial/event-derived. -- Only include players observed in recent/current match event windows. -- Do not imply this is the full server roster. -- Use a freshness threshold consistent with kill feed freshness logic. -- If no current/open event window exists, return empty items with a clear scope. - -### 7. RCON player-list data - -If a real RCON player-list command exists: - -- Prefer it for live roster. -- Combine it with AdminLog-derived kills/deaths only when safe. -- Mark fields not supported by RCON as null. -- Do not block the endpoint indefinitely on RCON timeouts. - -### 8. Frontend rendering - -Replace the static "Estadísticas en vivo" placeholder with dynamic rendering. - -If items exist: - -- Show a compact table or cards with player stats. -- Sort by kills descending, then deaths ascending, then name. -- Indicate if stats are partial. - -If items are empty, show: - -- "Todavía no hay estadísticas fiables de jugadores para esta partida." - -If data is partial, show: - -- "Estadísticas parciales derivadas de eventos recientes." - -### 9. Frontend polling - -- Poll player stats with the current-match page refresh cycle or a safe separate interval. -- Avoid overlapping requests. -- Do not flicker table rows on every poll. -- Avoid duplicate player rows. - -### 10. Tests - -Add focused backend tests for: - -- unsupported server rejection -- empty current stats response -- AdminLog-derived player aggregation if used -- stale event filtering -- no raw AdminLog exposure -- stable sorting -- partial confidence metadata - -## Validation - -Run: - -- `python -m compileall backend/app` -- focused backend tests if available -- `node --check frontend/assets/js/partida-actual.js` - -## Manual verification checklist - -- Call `Invoke-RestMethod "http://localhost:8000/api/current-match/players?server=comunidad-hispana-01" | ConvertTo-Json -Depth 20`. -- Call `Invoke-RestMethod "http://localhost:8000/api/current-match/players?server=comunidad-hispana-02" | ConvertTo-Json -Depth 20`. -- Verify unsupported server values are rejected safely. -- Open `http://localhost:8080/partida-actual.html?server=comunidad-hispana-01`. -- Open `http://localhost:8080/partida-actual.html?server=comunidad-hispana-02`. -- Verify the "Estadísticas en vivo" section no longer remains permanently empty when current reliable/partial player data exists. -- Verify the UI clearly says when stats are partial or unavailable. -- Verify no fake players are shown. -- Verify no raw AdminLog lines are shown. -- Verify existing historical detail stats still work. - -## Expected outcome - -The current-match page can show live or partial player statistics when supported by reliable/current data, and otherwise shows a clear honest empty state. - -## AI Platform lifecycle - -After implementation and validation: - -- Move this task according to the lifecycle defined in `AGENTS.md`. -- Do not mark unrelated tasks as done automatically. - -## Outcome - -### RCA and source choice - -- `RCON getSession` remains available for the current-match header but its current player count is explicitly marked `rcon-session-unverified`. -- No dedicated RCON player-list wrapper or route exists in the current `rcon_client` implementation. -- AdminLog kill events already expose safe normalized player names, teams, weapons and current-match window/freshness handling through the kill-feed read model. -- The historical AdminLog materializer derives player combat stats from the same kind of kill events for closed matches. -- Chosen source: current/fresh normalized AdminLog kill rows. The new current-match player projection is intentionally `event-derived-partial`, not a complete live roster. - -### Change summary - -- Added `GET /api/current-match/players?server=...` for trusted active current-match servers only. -- Added a safe AdminLog-derived player aggregator with kills, deaths, teamkills, teamkill deaths, team, last-seen timestamp and favorite weapon when observed. -- Kept stale fallback filtering aligned with the current kill feed and kept raw AdminLog messages out of the payload. -- Replaced the static current-match player placeholder with a polled partial-stat table and an honest empty state. - -### Validation - -- Ran `python -m compileall backend/app`. -- Ran `node --check frontend/assets/js/partida-actual.js`. -- Attempted `python -m pytest backend/tests/test_current_match_payload.py backend/tests/test_rcon_admin_log_storage.py`; the active Python environment does not have `pytest` installed. -- Ran a direct Python smoke harness for trusted/unsupported route resolution, AdminLog aggregation, teamkill handling, stale filtering and raw-log exclusion. -- Ran `scripts/run-historical-ui-regression-tests.ps1`. -- Ran `git diff --check` and `git diff --name-only`. -- Task-specific changed product files are `backend/app/routes.py`, `backend/app/payloads.py`, `backend/app/rcon_admin_log_storage.py`, `backend/tests/test_current_match_payload.py` and `frontend/assets/js/partida-actual.js`. The current worktree also contains `frontend/assets/css/historico.css` from completed `TASK-154`. -- Rendered Browser QA remains to be repeated when the Browser automation entry point is exposed in-session. diff --git a/ai/tasks/done/TASK-156-current-match-realtime-killfeed-and-home-buttons-layout.md b/ai/tasks/done/TASK-156-current-match-realtime-killfeed-and-home-buttons-layout.md deleted file mode 100644 index 7007878..0000000 --- a/ai/tasks/done/TASK-156-current-match-realtime-killfeed-and-home-buttons-layout.md +++ /dev/null @@ -1,203 +0,0 @@ -# TASK-156 - Current match realtime killfeed and home buttons layout - -Status: done - -## Goal - -Refine the current-match kill feed into a real-time FPS-style panel and make the home server card buttons sit at the bottom-right aligned with the map card, without changing unrelated layout. - -## Background - -The current-match page already has a compact kill feed overlay implemented in `frontend/assets/js/partida-actual.js` and related CSS. - -The current visual direction is closer to the goal, but the desired behavior is now more specific: - -- The feed should feel like a real-time FPS killfeed screen. -- It should not look like a static list of historical events. -- Each event should show only: - - killer - - weapon icon or compact weapon label - - victim -- The feed should behave like a small rectangular live panel. -- Events should fill from top to bottom in three visual columns. -- As new events arrive, old events should visually shift left and eventually disappear. -- The visible feed must be capped and must not grow indefinitely. -- Repeated polling must not duplicate events or cause visual flicker. - -There is also a small home page layout request: - -- In the home server cards, only the "Historico" and "Partida actual" buttons should remain. -- Those buttons should sit lower, at the bottom-right, aligned with the map card height. -- Do not change anything else in the home layout. - -Current user-observed issues: - -- The kill feed is still too much like a list rather than a real-time screen. -- The home server card buttons are still too high and leave unused empty space in the bottom-right corner. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `frontend/partida-actual.html` -- `frontend/assets/js/partida-actual.js` -- `frontend/assets/js/main.js` - -Inspect the current-match kill feed behavior, current polling/deduplication state, relevant current-match CSS, and the home server card action markup before changing code. - -## Expected Files to Modify - -Allowed changes: - -- `frontend/assets/js/partida-actual.js` -- `frontend/partida-actual.html` if needed -- `frontend/assets/css/historico.css` or relevant current-match CSS -- `frontend/assets/css/styles.css` or home CSS for the server card button alignment -- `frontend/assets/js/main.js` only if the button markup still needs cleanup -- local weapon icon/fallback assets if necessary -- focused frontend validation - -## Constraints - DO NOT BREAK - -- Do not break `/api/current-match/kills`. -- Do not expose raw AdminLog lines. -- Do not fabricate kill events. -- Do not show stale kills as live kills. -- Do not query RCON directly from the frontend. -- Do not break the current-match scoreboard/header. -- Do not break the historical page. -- Do not break historical match detail pages. -- Do not depend on server #03. -- Do not add external/CDN image dependencies. -- Do not reintroduce the home card "Scoreboard publico" button. -- Do not change the home server card content except button placement/layout if not strictly needed. -- Keep current public scoreboard URLs trusted and without `/games`. - -## Implementation Requirements - -### 1. Current-match kill feed layout - -- Replace any remaining card/list feel with a compact rectangular "live feed screen". -- The feed should visually fit in a bounded panel. -- It should not expand vertically without limit. -- It should show a maximum number of events, for example 12 or 15. - -### 2. Event rendering - -Each event must show only: - -- killer name -- weapon icon or compact weapon badge -- victim name - -Avoid noisy timestamp display in the main row unless it is subtle or useful. - -### 3. Three-column live flow - -- Desktop layout must visually use three columns. -- Events should fill top-to-bottom and then across columns in a predictable way. -- Newer events should be visually prioritized. -- Older events should move/disappear as the capped list updates. -- On tablet/mobile, fall back safely to two columns or one column. - -### 4. Real-time behavior - -- Preserve `event_id` deduplication. -- Do not duplicate rows on polling. -- Avoid full-panel flicker every poll. -- Keep already-rendered events stable when no new events arrive. -- Add/remove events cleanly when the cap is exceeded. - -### 5. Weapon display - -- Use local/fallback icons or compact glyph badges. -- Include mappings for currently seen examples: - - `M1 GARAND` - - `MP40` - - `M1A1 THOMPSON` - - `UNKNOWN` -- Unknown weapons should show a generic fallback, not broken image. -- Do not use external URLs. - -### 6. Teamkill - -- Teamkills must remain distinguishable but compact. -- Do not let teamkill badges dominate the layout. - -### 7. Feed copy - -- If there are no current events: "Todavia no se han detectado bajas en esta partida." -- If events are current/open-window: "Bajas detectadas en la partida actual." -- If events are fresh but partial: "Cobertura parcial desde AdminLog reciente." -- If stale/no current events: "Sin bajas recientes asociadas a la partida actual." - -### 8. Home server card layout - -- Ensure only two per-server buttons are visible: - - "Historico" - - "Partida actual" -- Remove/hide "Scoreboard publico" from the home server card. -- Move the two buttons down to the lower-right of the card, aligned visually with the map card at the bottom-left. -- Keep the map card compact and do not enlarge it. -- Do not change the rest of the home content/layout. -- Preserve responsive behavior. - -### 9. Validation - -- Run `node --check frontend/assets/js/partida-actual.js`. -- Run `node --check frontend/assets/js/main.js` if modified. -- Run `git diff --check`. -- Rebuild frontend if needed. - -## Manual Verification Steps - -- Open `http://localhost:8080/partida-actual.html?server=comunidad-hispana-01`. -- Open `http://localhost:8080/partida-actual.html?server=comunidad-hispana-02`. -- Verify the kill feed looks like a compact rectangular live overlay. -- Verify each event row shows: - - killer - - weapon icon/badge - - victim -- Verify the feed uses three columns on desktop. -- Verify older events disappear instead of growing endlessly. -- Verify repeated polling does not duplicate events. -- Verify the feed does not flicker on every refresh. -- Verify unknown weapons use a fallback. -- Verify no raw AdminLog line is displayed. -- Open the home page: `http://localhost:8080/`. -- Verify each server card shows only: - - Historico - - Partida actual -- Verify those buttons sit at the bottom-right, visually aligned with the map card. -- Verify no other home page layout area changes unexpectedly. - -## Expected Outcome - -The current-match kill feed behaves like a compact real-time combat overlay, and the home server card action buttons are cleanly aligned bottom-right with only "Historico" and "Partida actual" visible. - -## Outcome - -- Kept the existing `event_id`-based killfeed refresh path and changed only its - rendering surface: the capped 15-event panel now reads as a bounded combat - screen with three desktop columns, while smaller breakpoints remain bounded. -- Removed the home server-card public-scoreboard action from the hydrated markup - and left the remaining `Historico` / `Partida actual` actions aligned by the - existing status-column layout. -- Validated with: - - `node --check frontend/assets/js/partida-actual.js` - - `node --check frontend/assets/js/main.js` - - `git diff --check` - - `docker compose up -d --build frontend` - - live endpoint checks for `/api/current-match/kills` on Comunidad Hispana - `#01` and `#02` - - rendered Chrome headless screenshots of the home page, current-match `#01` - desktop view and current-match `#02` mobile empty-state view -- The in-app Browser automation runtime was not callable after tool discovery, - so rendered validation used local headless Chrome against the task URLs. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-157-current-match-player-team-colors.md b/ai/tasks/done/TASK-157-current-match-player-team-colors.md deleted file mode 100644 index 6bf3b5b..0000000 --- a/ai/tasks/done/TASK-157-current-match-player-team-colors.md +++ /dev/null @@ -1,197 +0,0 @@ -# TASK-157 - Current match player team colors - -Status: done - -## Goal - -Render current-match player/stat rows with team-aware colors/styles consistent with the historical match detail page. - -## Background - -The current-match page now has a live player/statistics section backed by: - -- `GET /api/current-match/players?server=...` - -The current implementation is AdminLog-derived and partial/event-derived because: - -- RCON `getSession` player counts are unverified. -- No current RCON player-list wrapper exists in the codebase. -- AdminLog kill events can identify players involved in recent/current events. - -The user now wants players to be shown like in the historical detailed match page: - -- Players should be visually distinguishable depending on team. -- Team coloring should match or be consistent with the historical match detail page. -- The current live stats section should not remain visually generic. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `frontend/assets/js/partida-actual.js` -- `frontend/partida-actual.html` -- the historical match detail frontend code and CSS that already color player teams - -Inspect the current `/api/current-match/players` payload, the live player rendering, and existing historical detail team classes before choosing frontend or backend changes. - -## Expected Files to Modify - -Allowed changes: - -- `frontend/assets/js/partida-actual.js` -- `frontend/partida-actual.html` if needed -- `frontend/assets/css/historico.css` or relevant current-match CSS -- `backend/app/payloads.py` only if team fields are not currently projected clearly -- `backend/app/rcon_admin_log_storage.py` only if normalized team values need cleanup -- focused tests if backend normalization changes - -## Constraints - DO NOT BREAK - -- Do not fabricate team values. -- Do not imply the player list is a complete live roster if it is only AdminLog-derived. -- Do not expose raw AdminLog lines. -- Do not expose admin-only/sensitive fields. -- Do not break historical match detail player stats. -- Do not break historical materialization. -- Do not query RCON directly from the frontend. -- Do not depend on server #03. -- Do not show misleading team colors if team is unknown. -- Do not show fake players. - -## Implementation Requirements - -### 1. RCA first - -- Inspect the current `/api/current-match/players` response. -- Determine whether each player row includes team or enough information to infer team safely. -- Compare CSS/classes used by the historical match detail page for team coloring. - -### 2. Backend data contract - -If player rows already include reliable team values: - -- Preserve the existing endpoint and document available team fields. - -If team values exist in storage but are not exposed: - -- Add normalized team fields to each player row, for example: - - `team` - - `team_label` - - `team_side` -- Use only values supported by AdminLog/current data. - -If team is unknown: - -- Return null/unknown. -- Do not guess. - -### 3. Frontend rendering - -- Update the current-match player stats section so rows/cards are styled by team: - - Allied/US/Soviet/Commonwealth/etc. side should use the same or consistent allied styling. - - Axis/Germany side should use the same or consistent axis styling. - - Unknown team should use neutral styling. -- Reuse historical detail team classes if possible. -- If historical detail uses existing CSS modifiers, prefer them over creating conflicting styles. - -### 4. Visual requirements - -- Player name should be readable. -- Team color should be visible but not overwhelming. -- Team badge/label may be shown if useful. -- Partial/event-derived confidence must remain visible. -- The section should not look like a final historical table unless data is complete. - -### 5. Sorting - -- Preserve current sorting if implemented: - - kills descending - - deaths ascending - - name -- If not implemented, add stable sorting consistent with current endpoint. - -### 6. Empty state - -If no player data exists: - -- Show: "Todavia no hay estadisticas fiables de jugadores para esta partida." - -### 7. Partial state - -If stats are AdminLog-derived: - -- Show: "Estadisticas parciales derivadas de eventos recientes." -- Do not imply this is the complete roster. - -### 8. Tests - -If backend changes are made, add/update focused tests for: - -- team fields are projected when available -- unknown team remains unknown/neutral -- no raw AdminLog exposure -- unsupported server rejection still works -- partial/event-derived metadata is preserved - -### 9. Validation - -- Run `python -m compileall backend/app` if backend changed. -- Run focused backend tests if changed. -- Run `node --check frontend/assets/js/partida-actual.js`. -- Run `git diff --check`. - -## Manual Verification Steps - -- Call `Invoke-RestMethod "http://localhost:8000/api/current-match/players?server=comunidad-hispana-01" | ConvertTo-Json -Depth 20`. -- Call `Invoke-RestMethod "http://localhost:8000/api/current-match/players?server=comunidad-hispana-02" | ConvertTo-Json -Depth 20`. -- Verify player rows include team/side data when available or unknown/null when not. -- Open `http://localhost:8080/partida-actual.html?server=comunidad-hispana-01`. -- Open `http://localhost:8080/partida-actual.html?server=comunidad-hispana-02`. -- Verify live player/stat rows are colored by team when team is known. -- Verify unknown-team players use neutral styling. -- Verify the section clearly indicates partial/event-derived stats. -- Verify no fake complete roster is implied. -- Verify historical match detail player colors still work. - -## Expected Outcome - -The current-match player/stat section uses team-aware colors consistent with the historical detail page while remaining honest about partial/event-derived live data. - -## Outcome - -- RCA found no backend contract gap: a live - `/api/current-match/players?server=comunidad-hispana-01` response observed - before the validation rebuild already exposed AdminLog-derived `team` values - such as `Allies` and `Axis`; unknown values remain handled by the existing - frontend neutral path. -- Reused the historical detail player row and team badge CSS modifiers from - `historico-scoreboard-detail.css` in the current-match player table instead - of adding a parallel style system. -- Included `team` in the visible player-table signature so a future team update - can rerender an already-visible row without changing its stats. -- Validated with: - - `node --check frontend/assets/js/partida-actual.js` - - `git diff --check` - - `docker compose up -d --build frontend` - - live `/api/current-match/players` checks on Comunidad Hispana `#01` and - `#02` - - rendered Chrome headless current-match validation for the available player - empty state after the backend restart - - served-script check confirming the historical row and badge modifiers are - present in `frontend/assets/js/partida-actual.js` -- The final rendered validation window had no current player rows after the - backend rebuild, so known-team colors were validated from the observed live - payload contract plus the reused historical class mapping rather than from a - live colored-row screenshot. -- Repository-level follow-up validation ran - `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1`. - It returned exit code `0`, but its output also printed a historical SQLite - `database disk image is malformed` traceback after the pass banner; that - historical storage issue is outside this frontend task scope. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-158-current-match-realtime-transport.md b/ai/tasks/done/TASK-158-current-match-realtime-transport.md deleted file mode 100644 index 62f9336..0000000 --- a/ai/tasks/done/TASK-158-current-match-realtime-transport.md +++ /dev/null @@ -1,193 +0,0 @@ ---- -id: TASK-158 -title: Current match realtime transport -status: done -type: backend -team: Backend Senior -supporting_teams: [Frontend Senior] -roadmap_item: foundation -priority: high ---- - -# TASK-158 - Current match realtime transport - -## Goal - -Implement a real-time or near-real-time update strategy for the current-match page, prioritizing the kill feed and then current match metadata/player stats. - -## Background - -The current-match page currently refreshes through polling. In `frontend/assets/js/partida-actual.js`, the current interval is: - -`CURRENT_MATCH_POLL_INTERVAL_MS = 30 * 1000` - -The user explicitly rejected this behavior: - -- "He dicho que se actualice en vivo y no cada 20 segundos" - -The page should behave much closer to real time, especially for the kill feed. A 20/30-second refresh is too slow for a live combat screen. - -Current endpoints: - -- `GET /api/current-match?server=...` -- `GET /api/current-match/kills?server=...` -- `GET /api/current-match/players?server=...` - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `frontend/assets/js/partida-actual.js` -- `backend/app/routes.py` -- `backend/app/rcon_admin_log_storage.py` - -Inspect the current frontend refresh flow, current-match route payloads, kill feed read model, trusted server validation, and recent AdminLog materialization cadence before changing code. - -## Expected Files to Modify - -Allowed changes: - -- `backend/app/routes.py` -- `backend/app/payloads.py` -- `backend/app/rcon_admin_log_storage.py` -- backend helper/read-model files if needed -- `frontend/assets/js/partida-actual.js` -- `frontend/partida-actual.html` if needed -- focused tests - -## Constraints - DO NOT BREAK - -- Do not query RCON directly from the frontend. -- Do not expose raw AdminLog lines. -- Do not fabricate events. -- Do not show stale kills as live kills. -- Do not depend on server #03. -- Do not break existing REST endpoints. -- Do not break historical pages or historical match detail pages. -- Keep trusted server validation. -- Keep current public scoreboard URLs without `/games`. -- Avoid overloading the backend/RCON/AdminLog pipeline. -- Commit and push after implementation. - -## Implementation Requirements - -### 1. RCA first - -- Document current update flow in TASK done notes. -- Confirm which parts are safe to update at high frequency: - - kill feed - - player stats - - match metadata/scoreboard -- Identify whether the backend has access to sufficiently fresh AdminLog data without calling RCON per browser poll. - -### 2. Preferred transport - -Evaluate and implement the safest available option: - -- Server-Sent Events (SSE) endpoint for live kill events, OR -- short polling for killfeed every 1-2 seconds with ETag/since cursor/last_event_id, OR -- another minimal transport that gives near-real-time updates without duplicating events. - -Prefer SSE if it is simple and safe in the current backend stack. - -If SSE is not appropriate, implement short polling with cursor semantics. - -### 3. Kill feed endpoint behavior - -Add support for incremental fetching: - -- `since_event_id` or since timestamp/server_time -- `limit` -- server slug -- trusted server validation - -The endpoint must return only new events where possible. - -### 4. Frontend behavior - -- Remove dependency on a 20/30-second interval for kill feed updates. -- Kill feed should update in near-real-time. -- Avoid overlapping requests. -- Preserve `event_id` deduplication. -- Do not re-render the whole panel if no new events arrived. -- Keep a capped event buffer. - -### 5. Match metadata and player stats - -- These do not need to update every second. -- Keep a slower safe refresh for scoreboard/player stats if needed, for example 10-30 seconds. -- The kill feed must be faster than metadata refresh. - -### 6. Failure/reconnect - -- If SSE is used, implement reconnect behavior. -- If short polling is used, handle transient errors without breaking the page. -- Show a small stale/error state only when needed. - -### 7. Backend load - -- Do not query expensive RCON calls per browser every second. -- Prefer reading already persisted/recent AdminLog materialized data. -- If a live AdminLog ingestion cadence is insufficient, document it instead of hiding the limitation. - -## Validation - -Run: - -- `python -m compileall backend/app` -- focused backend tests if added/updated -- `node --check frontend/assets/js/partida-actual.js` -- `git diff --check` - -Before completing the task also confirm that `git diff --name-only` matches the expected scope. - -## Manual Verification Steps - -- Rebuild backend and frontend. -- Open `http://localhost:8080/partida-actual.html?server=comunidad-hispana-01`. -- Open `http://localhost:8080/partida-actual.html?server=comunidad-hispana-02`. -- During an active match, verify new kill events appear without waiting 20/30 seconds. -- Verify repeated updates do not duplicate events. -- Verify no raw AdminLog lines appear. -- Verify stale events are not displayed as live. -- Verify metadata/scoreboard remains stable and does not flicker. -- Verify backend logs do not show excessive RCON/API pressure. - -## Expected Outcome - -The current-match kill feed updates in near-real-time, without depending on the existing 30-second page refresh cycle. - -## Outcome - -RCA: - -- The current page used one `30s` interval in `frontend/assets/js/partida-actual.js` for current-match metadata, player stats and the kill feed together. -- The kill feed read path is already safe for higher-frequency reads because it queries normalized persisted `rcon_admin_log_events` rows through `/api/current-match/kills`; it does not query RCON from the browser or expose raw AdminLog lines. -- Current match metadata can still call live RCON through the existing payload path, and player stats aggregate the kill feed read model, so those surfaces remain on the slower refresh path. - -Transport decision: - -- Implemented incremental short polling for the kill feed instead of SSE. The backend is still the standard-library JSON route stack, while the existing persisted read model can cheaply support a cursor. -- `/api/current-match/kills` now accepts `since_event_id` plus the existing `server` and `limit` inputs. Trusted server validation remains in `routes.py`. -- The frontend polls kill-feed rows every `1500ms`, sends the latest event id cursor after the first load, deduplicates by `event_id`, caps the in-memory visible buffer and avoids overlapping kill-feed requests. Metadata and player stats keep the existing `30s` refresh cadence. - -Validation performed: - -- `python -m compileall backend/app` -- `node --check frontend/assets/js/partida-actual.js` -- `git diff --check` -- Ran a direct Python smoke check for `list_current_match_kill_feed(..., since_event_id=...)` with temporary AdminLog rows after the focused pytest command could not run. -- Attempted focused backend tests with `python -m pytest backend/tests/test_current_match_payload.py backend/tests/test_rcon_admin_log_storage.py`; this environment failed with `No module named pytest`. -- Reviewed `git diff --name-only`; task-owned code changes are limited to the allowed current-match backend/frontend files plus the focused storage test and this task transition. The worktree already contained frontend and prior task changes from `TASK-156`/`TASK-157`. - -Load and freshness limit: - -- Browser polling now reads persisted AdminLog rows rather than issuing per-browser RCON calls. -- New kill visibility is still bounded by how quickly `app.rcon_historical_worker` or manual AdminLog ingestion persists fresh AdminLog rows. The current documented worker example is a `120s` loop, so operations may need a follow-up cadence decision if that persisted source is not fresh enough for the desired live screen. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-159-current-match-feed-rollback-and-weapon-icons.md b/ai/tasks/done/TASK-159-current-match-feed-rollback-and-weapon-icons.md deleted file mode 100644 index 5b006a6..0000000 --- a/ai/tasks/done/TASK-159-current-match-feed-rollback-and-weapon-icons.md +++ /dev/null @@ -1,188 +0,0 @@ ---- -id: TASK-159 -title: Current match feed rollback and weapon icons -status: done -type: frontend -team: Frontend Senior -supporting_teams: [Disenador grafico, Experto en interfaz] -roadmap_item: foundation -priority: high ---- - -# TASK-159 - Current match feed rollback and weapon icons - -## Goal - -Rollback/refactor the current killfeed visual layout to the previous accepted live feed style and integrate local weapon icons where available. - -## Background - -The latest compact three-column killfeed implementation is not accepted visually. The user wants to return to the previous live feed screen direction and then improve it. - -User feedback: - -- "Quiero volver a la pantalla de feed de la partida en vivo de antes, esta no me convence" -- The desired feed should still be a live combat screen, but not the current overly table/grid-like layout. -- Weapon icons were manually added to the repository for testing and should be reused. - -Current issue: - -The current killfeed visually feels too much like a table/grid and not enough like a readable live combat feed. The user wants the previous feed visual style back, then use weapon icons. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `frontend/partida-actual.html` -- `frontend/assets/js/partida-actual.js` -- relevant current-match CSS and `frontend/assets/img/weapons/` - -Inspect git history/diff around the feed changes before choosing whether to restore prior markup or intentionally recreate the previous direction. - -## Expected Files to Modify - -Allowed changes: - -- `frontend/assets/js/partida-actual.js` -- `frontend/partida-actual.html` if needed -- `frontend/assets/css/historico.css` or relevant CSS -- `frontend/assets/img/weapons/*` only if renaming/organizing existing local icons is necessary -- no backend changes unless weapon normalization is strictly needed - -## Constraints - DO NOT BREAK - -- Do not break `/api/current-match/kills`. -- Do not expose raw AdminLog lines. -- Do not fabricate kill events. -- Do not show stale kills as live kills. -- Do not query RCON directly from the frontend. -- Do not break the current-match scoreboard/header. -- Do not break the player stats section. -- Do not break historical pages. -- Do not depend on server #03. -- Do not hotlink external weapon images. -- Use local weapon icon assets only. -- Unknown weapons must have a clean fallback. -- Commit and push after implementation. - -## Implementation Requirements - -### 1. RCA first - -- Identify the previous feed layout/style before TASK-156/TASK-157 changes using git history/diff. -- Identify what parts of the previous style the user likely preferred: - - card readability - - vertical event readability - - less table/grid feel -- Document this in TASK done notes. - -### 2. Rollback/refactor visual style - -- Restore the previous feed screen style or recreate it intentionally. -- It should be readable and live-oriented. -- It should not look like the current table-like three-column grid. -- Keep the feed bounded and capped; do not allow infinite growth. -- Keep deduplication. - -### 3. Event content - -Each event should show: - -- killer -- weapon icon -- victim - -Optional timestamp may be shown only if visually subtle. - -### 4. Weapon icon discovery - -- Inspect `frontend/assets/img/weapons` or any newly added weapon icon folder. -- Reuse local icons the user added. -- Do not create external dependencies. -- If filenames are inconsistent, add a safe mapping instead of renaming unless renaming is clearly cleaner. - -### 5. Weapon icon mapping - -Add mapping for at least: - -- `M1 GARAND` -- `MP40` -- `M1A1 THOMPSON` -- `GEWEHR 43` -- `MG42` -- `UNKNOWN` -- generic fallback - -Also support simple normalization: - -- uppercase/lowercase differences -- spaces/hyphens -- common AdminLog weapon strings - -### 6. Visual behavior - -- Events should appear as compact readable live-feed entries. -- Avoid the current big empty table-like columns. -- Avoid full panel flicker. -- Limit visible entries, for example 10-15. -- Older events should disappear when the cap is exceeded. - -### 7. Empty states - -- If no current events: "Todavía no se han detectado bajas en esta partida." -- If stale/no current events: "Sin bajas recientes asociadas a la partida actual." - -## Validation - -Run: - -- `node --check frontend/assets/js/partida-actual.js` -- `git diff --check` -- rebuild frontend - -Before completing the task also confirm that `git diff --name-only` matches the expected scope. - -## Manual Verification Steps - -- Open `http://localhost:8080/partida-actual.html?server=comunidad-hispana-01`. -- Open `http://localhost:8080/partida-actual.html?server=comunidad-hispana-02`. -- Verify the feed no longer looks like the current table/grid. -- Verify it resembles the previous live feed screen direction. -- Verify each event shows killer, weapon icon, victim. -- Verify unknown weapons use fallback. -- Verify local weapon icons load correctly. -- Verify repeated updates do not duplicate rows. -- Verify stale events are not shown as live. -- Verify the player stats section still works. - -## Expected Outcome - -The current-match feed returns to the previous preferred live-feed visual direction while using the newly added local weapon icons. - -## Outcome - -Visual RCA: - -- Git history before the compact feed change showed a vertical `historical-match-card` list with one readable event per row/card. The rejected version introduced a fixed multi-column killfeed surface that reads like a grid/table. -- The feed was refactored back to a vertical card-like list while keeping the current live buffer, deduplication and no-flicker signature guard. - -Weapon icon decision: - -- Reused local assets already present under `frontend/assets/img/weapons/`. -- `partida-actual.js` maps normalized AdminLog weapon names for `M1 GARAND`, `MP40`, `M1A1 THOMPSON`, `GEWEHR 43`, `MG42` and aliases to local PNGs. -- Unknown/unmapped weapons keep their label for tooltip/accessibility and render a compact local fallback marker instead of hotlinking assets. - -Validation performed: - -- `node --check frontend/assets/js/partida-actual.js` -- `git diff --check` -- `docker compose build frontend` -- Reviewed the history diff for the prior accepted feed direction and inspected local weapon asset filenames. -- Rendered Browser verification was attempted through the required Browser workflow but blocked because the Browser JavaScript execution tool was not exposed in this session after tool discovery. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-160-home-server-card-bottom-actions.md b/ai/tasks/done/TASK-160-home-server-card-bottom-actions.md deleted file mode 100644 index 881d61f..0000000 --- a/ai/tasks/done/TASK-160-home-server-card-bottom-actions.md +++ /dev/null @@ -1,164 +0,0 @@ ---- -id: TASK-160 -title: Home server card bottom actions -status: done -type: frontend -team: Frontend Senior -supporting_teams: [Experto en interfaz] -roadmap_item: foundation -priority: high ---- - -# TASK-160 - Home server card bottom actions - -## Goal - -Cleanly restructure the home server card action layout so only Historico and Partida actual render, positioned bottom-right aligned with the map card, without changing unrelated UI. - -## Background - -The home page server cards are rendered from `frontend/assets/js/main.js`. - -Current user feedback: - -- The home card buttons are still too high. -- The user wants the buttons moved "dos pasos al div de abajo con el mapa". -- The buttons must be located at the far right in the lower area, aligned with the map card. -- The layout should be more compact. -- Do not touch anything else. - -Current known issue: - -- `renderServerAction(server)` in `frontend/assets/js/main.js` still renders "Scoreboard publico". -- CSS/HTML workarounds have been used to hide/rename buttons. -- The user wants only: - - Historico - - Partida actual - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `frontend/index.html` -- `frontend/assets/js/main.js` -- `frontend/assets/css/styles.css` - -Inspect the rendered server card structure, quickfact/map markup, trusted action URL mapping, and any existing inline or stylesheet button workarounds before changing code. - -## Expected Files to Modify - -Allowed changes: - -- `frontend/assets/js/main.js` -- `frontend/assets/css/styles.css` -- `frontend/index.html` only to remove previous inline CSS workarounds if present -- no backend changes -- no tests unless needed -- node validation - -## Constraints - DO NOT BREAK - -- Do not change backend. -- Do not change current-match page. -- Do not change historical page behavior. -- Do not change server polling logic. -- Do not reintroduce Scoreboard publico on home server cards. -- Do not remove trusted URL mappings if used elsewhere unless unused. -- Do not alter the rest of the home page layout/content. -- Preserve responsive behavior. -- Commit and push after implementation. - -## Implementation Requirements - -### 1. Remove structural rendering of Scoreboard publico - -`renderServerAction(server)` should only output: - -- Historico -- Partida actual - -### 2. Rename the rendered history action - -Rename "Nuestro historico" to "Historico" in the rendered markup. - -### 3. Avoid CSS-only hide/rename hacks - -- Remove old CSS workarounds that hide first button or replace text through pseudo-elements if present. -- Make the JS markup itself correct. - -### 4. Move buttons to the lower-right area - -- The map quickfact card remains lower-left. -- The action buttons should be in the same lower row/block, aligned far right. -- Avoid large empty bottom-right space. -- Keep card height compact. - -### 5. Suggested structure - -- Card top: eyebrow, server name, status/population. -- Card bottom row: map card left, action buttons right. -- Do not make the map card huge. -- Buttons should not float in the middle of the card. - -### 6. Responsive behavior - -- On desktop, bottom row is two columns: - - map left - - actions right -- On mobile/narrow widths, stack safely: - - map - - actions - -## Validation - -Run: - -- `node --check frontend/assets/js/main.js` -- `git diff --check` -- rebuild frontend - -Before completing the task also confirm that `git diff --name-only` matches the expected scope. - -## Manual Verification Steps - -- Open `http://localhost:8080/`. -- Verify each server card shows only: - - Historico - - Partida actual -- Verify Scoreboard publico is not rendered. -- Verify buttons are bottom-right aligned with the map card. -- Verify map card remains compact. -- Verify card layout is not broken on narrow viewport. -- Verify Historico opens: - - `historico.html?server=comunidad-hispana-01` - - `historico.html?server=comunidad-hispana-02` -- Verify Partida actual opens: - - `partida-actual.html?server=comunidad-hispana-01` - - `partida-actual.html?server=comunidad-hispana-02` - -## Expected Outcome - -The home server cards have a clean structural layout with only Historico and Partida actual positioned at the lower-right aligned with the map card. - -## Outcome - -Structural cleanup: - -- Home server card actions now live in a dedicated bottom row beside the map quickfact rather than inside the status column. -- The rendered card action markup keeps only `Historico` and `Partida actual`; trusted URL mappings stay intact for those actions. -- Removed the inline server-card layout workaround from `frontend/index.html` and moved the bottom-row layout rules into `frontend/assets/css/styles.css`, with a stacked narrow layout. - -Validation performed: - -- `node --check frontend/assets/js/main.js` -- `git diff --check` -- `docker compose build frontend` -- Checked the existing local frontend and backend endpoints were serving on `127.0.0.1:8080` and `127.0.0.1:8000`. -- Rendered Browser verification was attempted through the required Browser workflow but blocked because the Browser JavaScript execution tool was not exposed in this session after tool discovery. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-161-current-match-full-player-summary-and-feed-badges.md b/ai/tasks/done/TASK-161-current-match-full-player-summary-and-feed-badges.md deleted file mode 100644 index 8b5372b..0000000 --- a/ai/tasks/done/TASK-161-current-match-full-player-summary-and-feed-badges.md +++ /dev/null @@ -1,83 +0,0 @@ ---- -id: TASK-161 -title: Current match full player summary and feed badges -status: done -type: backend -team: Backend Senior -supporting_teams: - - Frontend Senior - - Experto en interfaz -roadmap_item: foundation -priority: medium ---- - -# TASK-161 - Current match full player summary and feed badges - -## Goal - -Ampliar el resumen de jugadores de `/api/current-match/players` para incluir a todos los participantes detectados de la partida actual y ajustar el feed de combate para mostrar nombre + facción en una sola línea sin cambiar su lógica funcional. - -## Context - -`frontend/partida-actual.html` ya expone feed de combate y tabla de estadísticas en vivo. El payload actual de jugadores depende solo de eventos `kill`, por lo que deja fuera jugadores conectados o vistos en la ventana de partida actual sin bajas registradas. - -## Steps - -1. Revisar parser, storage y payloads actuales de `current match`. -2. Ampliar la agregación backend usando eventos AdminLog y muestra live cuando exista. -3. Ajustar el render del feed para reutilizar el patrón visual de cápsulas de facción. -4. Validar el alcance con tests y checks pedidos. - -## Files to Read First - -- `AGENTS.md` -- `ai/architecture-index.md` -- `ai/repo-context.md` -- `backend/app/rcon_admin_log_storage.py` -- `backend/app/payloads.py` -- `frontend/assets/js/partida-actual.js` - -## Expected Files to Modify - -- `backend/app/rcon_admin_log_storage.py` -- `backend/app/payloads.py` -- `backend/tests/test_current_match_payload.py` -- `backend/tests/test_rcon_admin_log_storage.py` -- `frontend/assets/js/partida-actual.js` -- `frontend/assets/css/historico.css` - -## Constraints - -- No tocar histórico, rankings, retención, mantenimiento BDD ni export Gitea. -- No cambiar endpoints ni contratos incompatibles del frontend. -- No cambiar la lógica funcional del feed de combate. -- Mantener la derivación principal de estadísticas desde AdminLog y ampliarla. - -## Validation - -- `python -m compileall backend/app` -- `$env:PYTHONPATH = "backend"` -- `python -m unittest backend.tests.test_current_match_payload` -- `python -m unittest discover -s backend/tests -p "*current*"` -- `python -m unittest discover -s backend/tests -p "*rcon*"` -- `node --check frontend/assets/js/partida-actual.js` -- `git diff --check` - -## Outcome - -- `backend/app/rcon_admin_log_storage.py` ahora construye el resumen vivo de participantes de la ventana actual combinando eventos `kill`, `connected`, `disconnected`, `team_switch`, `chat` y `message`, manteniendo las estadísticas de bajas derivadas desde `kill`. -- `frontend/assets/js/partida-actual.js` y `frontend/assets/css/historico.css` ajustan solo el render visual del feed para mostrar nombre + cápsula en la misma línea reutilizando el badge de equipo de la tabla. -- Validación ejecutada: - - `python -m compileall backend/app` - - `node --check frontend/assets/js/partida-actual.js` - - `git diff --check` - - Arnes Python local que ejecuta directamente las funciones `test_*` de `backend/tests/test_current_match_payload.py` y `backend/tests/test_rcon_admin_log_storage.py` -- Observaciones de validación: - - `python -m unittest backend.tests.test_current_match_payload` y `python -m unittest discover -s backend/tests -p "*current*"` no detectan tests porque esos módulos usan estilo `pytest`. - - `python -m unittest discover -s backend/tests -p "*rcon*"` falla por un problema ajeno y preexistente en `test_rcon_materialization_pipeline`. -- Limitación conocida: el helper live actual del repositorio expone conteos y marcador (`GetServerInformation`), pero no un roster nominal de jugadores; por tanto el resumen usa todas las señales nominales ya persistidas en AdminLog y no puede inventar jugadores silenciosos si nunca fueron vistos por ningún evento. - -## Change Budget - -- Preferir menos de 5 archivos si es viable; si no, mantener el cambio concentrado en current match. -- Preferir cambios pequeños y verificables por tests. diff --git a/ai/tasks/done/TASK-161-define-stats-section-functional-contract.md b/ai/tasks/done/TASK-161-define-stats-section-functional-contract.md deleted file mode 100644 index 19eddbf..0000000 --- a/ai/tasks/done/TASK-161-define-stats-section-functional-contract.md +++ /dev/null @@ -1,199 +0,0 @@ ---- -id: TASK-161 -title: Define Stats section functional contract -status: done -type: documentation -team: Analista -supporting_teams: - - PM - - Backend Senior - - Frontend Senior - - Arquitecto de Base de Datos - - Experto en interfaz -roadmap_item: stats-section -priority: high ---- - -# TASK-161 - Define Stats section functional contract - -## Goal - -Define the functional and technical contract for a new `Stats` section where players can search themselves, view their personal statistics across the community servers, and understand their weekly and monthly ranking position. - -This task must also prepare the future annual ranking design, including a dedicated annual top 20 snapshot model, without implementing backend endpoints, database migrations or frontend UI yet. - -## Context - -HLL Vietnam already has an RCON-first historical architecture and materialized match/player statistics. The existing leaderboard read model in `backend/app/rcon_historical_leaderboards.py` supports weekly and monthly leaderboard payloads over RCON/AdminLog materialized tables. - -The next product step is to convert this foundation into a player-facing `Stats` section with a clear V1 scope: - -- player search -- personal player statistics -- weekly ranking position -- monthly ranking position -- annual top 20 ranking preparation - -The annual ranking should not be recalculated on every public request. The preferred direction is to design a dedicated snapshot table/model for yearly top 20 rankings, generated from materialized RCON historical data. - -Preserve the current product identity: Spanish-speaking HLL Vietnam community, military/Vietnam/tactical/sober visual direction and controlled repository evolution. - -## Steps - -1. Inspect the listed files first. -2. Review the current RCON-first historical and leaderboard assumptions. -3. Define the V1 user flow for the new `Stats` section. -4. Define the backend API contract needed by the frontend. -5. Define the minimum personal statistics payload. -6. Define how weekly and monthly ranking positions should be calculated for a selected player. -7. Define the annual top 20 snapshot direction and the database objects that a later implementation task should add. -8. Document explicit non-goals and future extensions. -9. Create or update a focused documentation file for this feature. -10. Do not implement backend endpoints, database migrations, frontend screens or scripts in this task. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `ai/task-template.md` -- `backend/app/rcon_historical_leaderboards.py` -- `docs/frontend-data-consumption-plan.md` - -## Expected Files to Modify - -- `docs/stats-section-functional-plan.md` -- `ai/tasks/pending/TASK-161-define-stats-section-functional-contract.md` - -If `docs/frontend-data-consumption-plan.md` must be lightly cross-referenced, keep the change minimal and explain it in the outcome. Do not modify backend or frontend implementation files in this task. - -## Functional Contract To Define - -The documentation must cover at least: - -### Stats section user flow - -- User opens the `Stats` section. -- User searches by player name or player id. -- User selects a player from search results. -- UI displays personal statistics. -- UI displays the player's weekly and monthly ranking position. -- UI can later display annual top 20 ranking snapshot data. - -### Player search contract - -Propose a future endpoint similar to: - -```http -GET /api/stats/players/search?q= -``` - -Expected fields: - -- `player_id` -- `player_name` -- `matches_considered` -- `last_seen_at` -- optional `servers_seen` - -### Personal stats contract - -Propose a future endpoint similar to: - -```http -GET /api/stats/players/{player_id}?server_id=&timeframe=weekly|monthly|all -``` - -Minimum V1 fields: - -- player id -- player name -- selected server scope -- selected timeframe -- window start/end -- matches considered -- kills -- deaths -- teamkills -- K/D ratio -- kills per match -- deaths per match -- weekly ranking position by kills -- monthly ranking position by kills -- data source and freshness metadata - -### Annual ranking snapshot contract - -Define the future annual snapshot direction with a dedicated persistence model, preferably split into: - -- `rcon_annual_ranking_snapshots` -- `rcon_annual_ranking_snapshot_items` - -The documentation should describe expected columns, uniqueness rules, generation policy and read API direction, but must not create migrations yet. - -Propose a future endpoint similar to: - -```http -GET /api/stats/rankings/annual?year=&server_id=&metric=kills -``` - -### V1 non-goals - -Explicitly exclude from this first feature contract: - -- Elo/MMR reactivation -- Comunidad Hispana #03 reintroduction -- support/combat/offense/defense scoring unless already available from reliable RCON materialized data -- weapon-level breakdowns -- charts/advanced visualizations -- authentication or private player profiles -- frontend implementation -- backend endpoint implementation -- database migration implementation - -## Constraints - -- Keep the change documentation-only. -- Preserve HLL Vietnam project identity. -- Do not introduce unnecessary frameworks or dependencies. -- Do not implement backend functionality in this task. -- Do not implement frontend functionality in this task. -- Do not expand Elo/MMR, historical workers or RCON server #03 handling. -- Do not overwrite repository-specific context with generic platform template text. -- Keep future tasks small and sequenced. - -## Validation - -Before completing the task ensure: - -- `docs/stats-section-functional-plan.md` exists and is specific to HLL Vietnam. -- The document references the RCON-first materialized data direction. -- The document defines V1 scope, API contracts, payload expectations and annual snapshot direction. -- No backend implementation files were modified. -- No frontend implementation files were modified. -- `git diff --name-only` matches the expected scope. -- If no automated tests are relevant because this is documentation-only, document that explicitly in the outcome. - -## Outcome - -Completed as documentation-only. - -- Created `docs/stats-section-functional-plan.md` as the focused contract for the future `Stats` section. -- Kept the contract aligned with the current RCON-first materialized historical read model and the weekly/monthly window policy already present in `backend/app/rcon_historical_leaderboards.py`. -- Defined the V1 user flow, player search contract, personal stats payload, ranking position rules and annual top 20 snapshot persistence direction. -- Explicitly kept backend endpoints, database migrations and frontend implementation out of scope. - -## Validation Result - -- Verified `docs/stats-section-functional-plan.md` exists and is specific to HLL Vietnam. -- Verified the document references the RCON-first materialized data direction. -- Verified the document defines V1 scope, API contracts, payload expectations and annual snapshot direction. -- Verified no backend implementation files were modified for this task. -- Verified no frontend implementation files were modified for this task. -- No automated or integration tests applied because this task is documentation-only. - -## Change Budget - -- Prefer fewer than 3 modified files. -- Prefer changes under 250 lines. -- Split implementation details into follow-up tasks instead of expanding this task. diff --git a/ai/tasks/done/TASK-162-add-stats-player-search-endpoint.md b/ai/tasks/done/TASK-162-add-stats-player-search-endpoint.md deleted file mode 100644 index 122fcec..0000000 --- a/ai/tasks/done/TASK-162-add-stats-player-search-endpoint.md +++ /dev/null @@ -1,156 +0,0 @@ ---- -id: TASK-162 -title: Add Stats player search endpoint (RCON materialized backend V1) -status: done -type: backend -team: Backend Senior -supporting_teams: [Arquitecto de Base de Datos, Arquitecto Python] -roadmap_item: foundation -priority: medium ---- - -# TASK-162 - Add Stats player search endpoint (RCON materialized backend V1) - -## Goal - -Implement a backend V1 endpoint to support player search for the future Stats section: -`GET /api/stats/players/search?q=`. - -The endpoint must use existing RCON materialized tables and return search matches that include: - -- `status` -- `query` -- `items` -- `player_id` -- `player_name` -- `matches_considered` -- `last_seen_at` -- optional `servers_seen` only if it can be added with low scope cost - -No frontend work, no migrations, no yearly ranking, no Elo/MMR workarounds, no Comunidad Hispana #03 reactivation. - -## Context - -The repository already has a RCON materialized model (`rcon_match_player_stats` + `rcon_materialized_matches`) used by leaderboard reads. -The new endpoint is the first part of the Stats backend contract defined in `docs/stats-section-functional-plan.md`. -It should reuse existing routing/payload conventions in the current backend bootstrap. - -## Steps - -1. Inspect required files first (mandatory before implementation): - - `AGENTS.md` - - `ai/repo-context.md` - - `ai/architecture-index.md` - - `docs/stats-section-functional-plan.md` - - `backend/app/rcon_historical_leaderboards.py` - - `backend/app/main.py` - - `backend/app/rcon_admin_log_materialization.py` (for table/schema context) -2. Reuse the existing `routes.py` + `payloads.py` endpoint/payload pattern. -3. Implement one new endpoint: `GET /api/stats/players/search`. -4. Validate `q` parameter and optional `server` or `server_id` and `limit` handling using current project conventions. -5. Query existing RCON materialized tables with read-only logic (preferably `rcon_match_player_stats` joined with `rcon_materialized_matches`). -6. Keep response shape aligned with existing backend payload conventions. -7. Add a minimal, self-contained module if needed (preferably `backend/app/rcon_historical_player_stats.py`). -8. Run backend validation/checks and document outcome. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `docs/stats-section-functional-plan.md` -- `backend/app/main.py` -- `backend/app/routes.py` -- `backend/app/payloads.py` -- `backend/app/rcon_historical_leaderboards.py` -- `backend/app/rcon_admin_log_materialization.py` - -## Expected Files to Modify - -- `backend/app/rcon_historical_player_stats.py` (new module preferred) -- `backend/app/payloads.py` -- `backend/app/routes.py` -- `backend/app/main.py` (solo si se detecta una dependencia de export explícita o import requerido) - -## Constraints - -- Keep the change small and verifiable. -- Keep frontend untouched. -- No migrations. -- No annual ranking implementation. -- No Elo/MMR reactivation. -- No Comunidad Hispana #03 behavior reintroduction. -- No historical worker changes. -- Do not modify `frontend/assets/js/partida-actual.js`. -- Do not create unnecessary abstractions beyond this endpoint. -- If `/ai/` is partially ignored by git-exclude, document traceability impact only. - -## Validation - -Before considering the task complete: - -- Run `scripts/run-integration-tests.ps1`. -- Run relevant backend tests if they exist for stats/player or historical materialized reads. -- If no dedicated tests exist for this endpoint, run manual validation with `curl` or `Invoke-WebRequest`. -- Validate `git diff --name-only` and check that only expected files were changed. -- Move task to `ai/tasks/done` on completion, or to `ai/tasks/review` if human validation is required. - -## Outcome (for worker) - -Document: - -- endpoint contract implemented and observed behavior -- SQL/search strategy used (scope, match logic, ordering, fallback behavior) -- validation command results -- whether `servers_seen` was included and why -- any schema/data limitations found -- any blocker from git tracking (`/ai/` ignore behavior) and impact on traceability if relevant - -## Change Budget - -- Prefer <5 modified files. -- Prefer <200 added/changed lines per file when feasible. -- Split into follow-up tasks if the scope starts expanding. - -## Outcome - -- Endpoint creado: `GET /api/stats/players/search` - - Soporte de query param `q` obligatorio. - - Soporte de `server_id` opcional (con alias alterno `server`). - - Soporte de `limit` con default 10 y validación de rango 1-100. -- Patrón SQL: - - `rcon_match_player_stats` unido con `rcon_materialized_matches`. - - filtro por `matches.source_basis = 'admin-log-match-ended'`. - - filtro por `LOWER(COALESCE(stats.player_name, '')) LIKE ...` o `LOWER(stats.player_id) LIKE ...`. - - filtro opcional por servidor con `(target_key = ? OR external_server_id = ?)`. - - agregación por `player_id` con `COUNT(DISTINCT stats.match_key)` y `MAX(COALESCE(matches.ended_at, matches.started_at))`. - - orden por `matches_considered DESC`, `last_seen_at DESC`. -- Resultado del payload: - - `status` (global) - - `data.query` - - `data.server_id` (normaliza vacío/`all` a `all-servers`) - - `data.items[]` - - `player_id` - - `player_name` - - `matches_considered` - - `last_seen_at` - - `servers_seen` (obtenido por consulta agregada por player-id y servidor) -- Validaciones ejecutadas: - - `python -m compileall backend/app` - - `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` (OK) - - validación manual de endpoint con `resolve_get_payload`: - - `/api/stats/players/search?q=a` - - `/api/stats/players/search?q=steam` - - `/api/stats/players/search?q=zzzz-no-results-expected-12345` - - validación HTTP real con `Invoke-WebRequest` contra servidor local (`127.0.0.1:8000`): - - consulta corta: `/api/stats/players/search?q=a&limit=2` - - consulta normal: `/api/stats/players/search?q=steam&server=all&limit=1` - - sin resultados: `/api/stats/players/search?q=zzzz-no-results-expected-12345` -- Limitaciones conocidas: - - alcance de texto simple por `LIKE` (`%` y `_` escapados); no hay ranking de relevancia por prefijo en este V1. - - `servers_seen` depende de coincidencia de `external_server_id`/`target_key` en materialized matches, por eso puede ser ruidoso en casos de aliases. -- No se detectó anomalía operativa con TASK-161 en esta implementación. -- Siguiente task recomendada: `endpoint de estadísticas personales del jugador`. -- Nota de numeración TASK-161: detectada doble definición de `id: TASK-161` entre - - TASK-161-current-match-full-player-summary-and-feed-badges.md - - TASK-161-define-stats-section-functional-contract.md diff --git a/ai/tasks/done/TASK-163-add-player-personal-stats-endpoint.md b/ai/tasks/done/TASK-163-add-player-personal-stats-endpoint.md deleted file mode 100644 index 3e98c32..0000000 --- a/ai/tasks/done/TASK-163-add-player-personal-stats-endpoint.md +++ /dev/null @@ -1,69 +0,0 @@ ---- -id: TASK-163 -title: Add player personal stats endpoint -status: done -type: backend -team: Backend Senior -supporting_teams: [Arquitecto de Base de Datos, Arquitecto Python] -roadmap_item: foundation -priority: medium ---- - -# TASK-163 - Add player personal stats endpoint - -## Goal - -Implementar únicamente el endpoint backend de estadísticas personales: -`GET /api/stats/players/{player_id}`. - -Use existing RCON materialized data for weekly/monthly context. - -## Files modified - -- `backend/app/rcon_historical_player_stats.py` (nuevo) -- `backend/app/payloads.py` -- `backend/app/routes.py` - -## Endpoint created - -- `GET /api/stats/players/{player_id}` - - Parámetros: - - `server_id` (opcional, alias `server`) - - `timeframe` (`weekly` | `monthly`, validación en ruta) - - Respuesta: - - `status` - - `data.player_id` - - `data.player_name` - - `data.matches_considered` - - `data.kills` - - `data.deaths` - - `data.teamkills` - - `data.kd_ratio` - - `data.kills_per_match` - - `data.deaths_per_match` - - `data.window_start` - - `data.window_end` - - `data.window_kind` - - `data.weekly_ranking` - - `data.monthly_ranking` - - `data.source` - -## Validaciones realizadas - -- `python -m compileall backend/app` -- `scripts/run-integration-tests.ps1` -- Endpoint manual con backend levantado y `Invoke-WebRequest`: - - Query corta: `/api/stats/players/a?timeframe=weekly` => `200 OK` - - Query normal: `/api/stats/players/valid-player-uuid?timeframe=monthly` => `200 OK` - - Sin resultados: `/api/stats/players/nonexistent-9999?timeframe=weekly` => `200 OK` con métricas en cero - - Rechazo de timeframe inválido: `/api/stats/players/a?timeframe=yearly` => `400 Bad Request` - -## Limitaciones conocidas - -- El ranking semanal/mensual incluye solo jugadores con `kills > 0`. -- `source_range` puede ir en `null` cuando no hay datos materializados. -- `player_name` se resuelve al `player_id` si no hay nombre persistido en el rango solicitado. - -## Siguiente task recomendada - -- Endpoint de vista inicial de estadísticas personales del jugador en frontend (consumo del contrato `GET /api/stats/players/{player_id}`). diff --git a/ai/tasks/done/TASK-164-design-stats-frontend-integration-plan.md b/ai/tasks/done/TASK-164-design-stats-frontend-integration-plan.md deleted file mode 100644 index 026e311..0000000 --- a/ai/tasks/done/TASK-164-design-stats-frontend-integration-plan.md +++ /dev/null @@ -1,92 +0,0 @@ ---- -id: TASK-164 -title: Design stats frontend integration plan -status: done -type: frontend -team: Frontend Senior -supporting_teams: [] -roadmap_item: foundation -priority: medium ---- - -# TASK-164 - Design stats frontend integration plan - -## Goal - -Define how the future Stats section will be integrated in the frontend before implementing it. - -## Context - -The backend already exposes the stats query contract used by this plan: - -- `GET /api/stats/players/search?q=` -- `GET /api/stats/players/{player_id}` - -This task is documentation only. No backend or implementation changes. - -## Steps - -1. Read all files listed in `Files to Read First` from the workspace first. -2. Define an integration strategy that preserves current navigation and behavior of Inicio / Historico / Partida actual. -3. Describe V1 components, endpoint usage and UI state transitions. -4. Propose minimal visual reuse from existing styles and assets. -5. Define future implementation files and order. -6. Record any known limitations and an open follow up recommendation. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `docs/stats-section-functional-plan.md` -- `frontend/index.html` -- `frontend/historico.html` -- `frontend/assets/css/styles.css` -- `frontend/assets/js/main.js` -- `backend/app/routes.py` -- `backend/app/payloads.py` - -## Expected Files to Modify - -- `docs/stats-frontend-integration-plan.md` -- `ai/tasks/done/TASK-164-design-stats-frontend-integration-plan.md` - -## Constraints - -- Keep current repo structure intact. -- Do not implement any frontend behavior now. -- Do not modify backend. -- No migrations. -- No ranking anual. -- No Elo/MMR reactivation. -- No Comunidad Hispana #03 reintro. -- Do not touch `frontend/assets/js/partida-actual.js`. -- Do not touch `frontend/assets/img/clans/bxb.png`. -- Do not add frameworks. -- Keep change size minimal and verified. - -## Validation - -- Confirm only documentation and task file were created/modified. -- Run `git diff --name-only`. -- Record that no automated tests are applicable for this docs-only task. - -## Outcome (for worker) - -- Outcome: - - Archivos creados/modificados: - - `docs/stats-frontend-integration-plan.md` - - `ai/tasks/done/TASK-164-design-stats-frontend-integration-plan.md` - - Movimiento de `ai/tasks/pending/TASK-164-design-stats-frontend-integration-plan.md` a `ai/tasks/done/...`. - - Validación realizada: - - `git status --short --untracked-files=all` verificado. - - `git diff --name-only` verificado. - - Confirmado que `docs/stats-frontend-integration-plan.md` existe y contiene el plan solicitado. - - Al ser una task documental: - - No se ejecutan tests automáticos. - - No aplica validación funcional automatizada. - - Restricciones verificadas: - - No se tocaron archivos de backend. - - No se implementó frontend. - - No se tocaron `frontend/assets/js/partida-actual.js`. - - No se tocó `frontend/assets/img/clans/bxb.png`. diff --git a/ai/tasks/done/TASK-165-add-stats-frontend-page.md b/ai/tasks/done/TASK-165-add-stats-frontend-page.md deleted file mode 100644 index c400163..0000000 --- a/ai/tasks/done/TASK-165-add-stats-frontend-page.md +++ /dev/null @@ -1,126 +0,0 @@ ---- -id: TASK-165 -title: Add stats frontend page -status: done -type: frontend -team: Frontend Senior -supporting_teams: [] -roadmap_item: foundation -priority: medium ---- - -# TASK-165 - Add stats frontend page - -## Goal - -Implement the first frontend version of the new `Stats` section using existing backend endpoints. - -## Context - -TASK-163 added backend support for player search and personal stats payloads under `/api/stats`. - -- `GET /api/stats/players/search?q=` -- `GET /api/stats/players/{player_id}` - -This task only covers frontend consumption and does not modify backend code. - -## Steps - -1. Read all files listed in `Files to Read First` before creating files. -2. Create `frontend/stats.html` with the V1 section layout. -3. Create `frontend/assets/js/stats.js` with vanilla JS state and API handlers: - - search call - - result rendering - - player selection - - profile request -4. Add Stats navigation entry in the shared shell used by landing/history without breaking existing sections. -5. Wire the following state blocks: - - loading - - error - - sin resultados - - jugador sin estadisticas - - backend no disponible -6. Add reserved annual ranking top 20 block (UI placeholder only, no backend call). -7. Update CSS only if required to support the new page. -8. Validate manually (and with integration tests when available) and record results in task outcome. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `docs/stats-section-functional-plan.md` -- `docs/stats-frontend-integration-plan.md` -- `frontend/index.html` -- `frontend/historico.html` -- `frontend/assets/css/styles.css` -- `frontend/assets/js/main.js` -- `backend/app/routes.py` -- `backend/app/payloads.py` - -## Expected Files to Modify - -- `frontend/stats.html` -- `frontend/assets/js/stats.js` -- `frontend/index.html` -- `frontend/historico.html` -- `frontend/assets/css/styles.css` (only if necessary) - -## Constraints - -- No backend changes. -- No migrations. -- No annual ranking real endpoint consumption in V1. -- No changes to historical workers. -- No Elo/MMR reactivation. -- Do not touch `frontend/assets/js/partida-actual.js`. -- Do not touch `frontend/assets/img/clans/bxb.png`. -- Do not reintroduce Comunidad Hispana #03. -- Keep HTML/CSS/JS vanilla (no frameworks). -- Preserve existing HLL Vietnam identity (military, Vietnam, tactical, sober). -- Keep scope small and reviewable. - -## Validation - -Before task completion: - -- Validate `frontend/stats.html` loads and executes without visible JS runtime errors. -- Validate search flow against local backend (if running): - - query -> backend search - - select player -> personal profile -- Validate empty/error/unsupported states, including backend unreachable. -- Validate annual placeholder is rendered without backend call. -- Run `scripts/run-integration-tests.ps1` when applicable. -- Run `git diff --name-only` and confirm only expected files changed for this task. -- Confirm `frontend/assets/js/partida-actual.js` and `frontend/assets/img/clans/bxb.png` were not touched. - -## Outcome - -- Archivos modificados: - - `frontend/stats.html` - - `frontend/assets/js/stats.js` - - `frontend/index.html` - - `frontend/historico.html` - - `frontend/assets/css/styles.css` -- Endpoints consumidos: - - `GET /api/stats/players/search?q=` - - `GET /api/stats/players/{player_id}` -- Validaciones realizadas: - - Validación de carga estática: - - se sirvió `frontend/stats.html` desde `python -m http.server` (status 200), - - se sirvió `frontend/assets/js/stats.js` (status 200). - - Validación del flujo con backend local: - - `GET /health` en `http://127.0.0.1:8000` no respondió (backend sin servicio en este momento), - - se dejó implementada la ruta de error `Backend no disponible`, - - no fue posible validar query corta, query normal y no-resultados contra backend en esta pasada. - - Validación de tests: - - `scripts/run-integration-tests.ps1` ejecutado y finalizó con éxito. -- Limitaciones conocidas: - - backend local no estaba levantado al momento de validación de integración, - - no se validó ranking anual real ni endpoint de ese dominio por restricción de alcance V1. -- Siguiente task recomendada: `TASK-166` diseño/implementación BDD de ranking anual top 20 (snapshot). - -## Change Budget - -- Prefer fewer than 5 modified files (allowing one extra if CSS adjustments are needed). -- Keep changes concise and aligned with V1 scope. diff --git a/ai/tasks/done/TASK-166-design-annual-ranking-snapshot-schema.md b/ai/tasks/done/TASK-166-design-annual-ranking-snapshot-schema.md deleted file mode 100644 index f5f45e4..0000000 --- a/ai/tasks/done/TASK-166-design-annual-ranking-snapshot-schema.md +++ /dev/null @@ -1,104 +0,0 @@ ---- -id: TASK-166 -title: Design annual ranking snapshot schema -status: done -type: documentation -team: Arquitecto de Base de Datos -supporting_teams: [] -roadmap_item: foundation -priority: medium ---- - -# TASK-166 - Design annual ranking snapshot schema - -## Goal - -Define a backend storage plan for annual top-20 ranking snapshots (kills) that avoids -full recalculation on each public request. - -## Context - -- TASK-162 implementó el endpoint de búsqueda de jugadores para Stats. -- TASK-163 implementó el endpoint de stats personales. -- TASK-165 implementó la vista frontend de Stats. - -This task is documentation-only and prepares the schema needed by the next backend -endpoint iteration: - -- `GET /api/stats/rankings/annual?year=&server_id=&metric=kills` - -## Steps - -1. Revisión de archivos listados en `Files to Read First`. -2. Diseñar propuesta de tablas para snapshots anuales y sus items. -3. Definir restricciones de unicidad, índices y política de reemplazo. -4. Documentar compatibilidad SQLite/Postgres siguiendo el patrón usado en `rcon_historical_leaderboards.py`. -5. Especificar API y estados esperados para lectura de snapshot. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `docs/stats-section-functional-plan.md` -- `docs/stats-frontend-integration-plan.md` -- `backend/app/rcon_historical_leaderboards.py` -- `backend/app/rcon_historical_player_stats.py` -- `backend/app/rcon_admin_log_materialization.py` -- `backend/app/postgres_rcon_storage.py` -- `backend/app/postgres_display_storage.py` -- `backend/app/sqlite_to_postgres_migration.py` - -## Expected Files to Modify - -- `ai/tasks/done/TASK-166-design-annual-ranking-snapshot-schema.md` -- `docs/annual-ranking-snapshot-schema-plan.md` - -## Constraints - -- No migrations in this task. -- No backend implementation code changes in this task. -- No frontend changes in this task. -- No Elo/MMR reactivation. -- No Comunidad Hispana #03 reintroduction. -- No modification of historical workers. -- No touch to: - - `frontend/assets/js/partida-actual.js` - - `frontend/assets/img/clans/bxb.png` - -## Validation - -- Confirm only documentation files were created/updated. -- `git diff --name-only` must match expected scope. -- Document that no automated tests are applicable for documentation-only task. - -## Outcome - -- Documento creado: - - `docs/annual-ranking-snapshot-schema-plan.md` -- Archivos revisados: - - `AGENTS.md` - - `ai/repo-context.md` - - `ai/architecture-index.md` - - `docs/stats-section-functional-plan.md` - - `docs/stats-frontend-integration-plan.md` - - `backend/app/rcon_historical_leaderboards.py` - - `backend/app/rcon_historical_player_stats.py` - - `backend/app/rcon_admin_log_materialization.py` - - `backend/app/postgres_rcon_storage.py` - - `backend/app/postgres_display_storage.py` - - `backend/app/sqlite_to_postgres_migration.py` -- Validación realizada: - - Confirmado que la tarea quedó en alcance documental y no se introdujeron cambios de backend/frontend. - - Se validó que los únicos archivos esperados para esta tarea estén cubiertos por su documentación. - - No se requiere ejecutar pruebas automáticas: es una tarea de documentación. -- Limitaciones: - - No se tocó código backend ni frontend. - - No se ejecutaron migraciones. -- Siguiente task recomendada: - - Crear migración y estructura de persistencia para snapshots anuales de ranking (`rcon_annual_ranking_*`) y su job de generación. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Keep changes concise and reviewable. diff --git a/ai/tasks/done/TASK-167-add-annual-ranking-snapshot-storage.md b/ai/tasks/done/TASK-167-add-annual-ranking-snapshot-storage.md deleted file mode 100644 index 7faf71d..0000000 --- a/ai/tasks/done/TASK-167-add-annual-ranking-snapshot-storage.md +++ /dev/null @@ -1,69 +0,0 @@ ---- -id: TASK-167 -title: Add annual ranking snapshot storage -status: done -type: backend -team: Arquitecto de Base de Datos -supporting_teams: - - Arquitecto Python - - Backend Senior -roadmap_item: foundation ---- - -# TASK-167 - Add annual ranking snapshot storage - -## Goal - -Implement storage primitives to persist annual top 20 player ranking snapshots, following the schema plan in `docs/annual-ranking-snapshot-schema-plan.md`, without adding generator logic or annual ranking APIs yet. - -## Context - -`TASK-166-design-annual-ranking-snapshot-schema.md` defined the intended schema and constraints for: - -- `rcon_annual_ranking_snapshots` -- `rcon_annual_ranking_snapshot_items` - -This task creates the storage layer so future yearly ranking generators can run on top of materialized RCON data in SQLite and PostgreSQL-compatible paths. - -The implementation must stay backend-only and must not touch frontend assets. - -## Validation Scope - -The work intentionally stayed limited to backend storage schema initialization and migration compatibility. - -## Outcome - -### Archivos modificados - -- backend/app/rcon_admin_log_materialization.py -- backend/app/postgres_rcon_storage.py -- backend/app/sqlite_to_postgres_migration.py -- ai/tasks/done/TASK-167-add-annual-ranking-snapshot-storage.md - -### Tablas nuevas añadidas - -- rcon_annual_ranking_snapshots -- rcon_annual_ranking_snapshot_items - -### Compatibilidad SQLite/Postgres - -- SQLite: tablas y restricciones añadidas en `initialize_rcon_materialized_storage()` (backend/app/rcon_admin_log_materialization.py). -- PostgreSQL: tablas, índices y restricciones añadidas a `RCON_SCHEMA_SQL` (backend/app/postgres_rcon_storage.py). -- Migración: tablas añadidas a `RCON_TABLES` y a `_sync_sequences()` en `backend/app/sqlite_to_postgres_migration.py`. - -### Validaciones realizadas - -- `python -m compileall backend/app` -- `scripts/run-integration-tests.ps1` -- Validación de inicialización de storage SQLite con base temporal y consulta en `sqlite_master` para ambas tablas. - -### Limitaciones conocidas - -- No se implementó generador anual ni endpoint de ranking anual. -- No se tocó frontend. -- No hay validación de runtime PostgreSQL porque no había entorno Postgres requerido por el alcance de esta task. - -### Próximo task recomendado - -- TASK-168 (Generador de snapshot anual top 20). - diff --git a/ai/tasks/done/TASK-168-add-annual-ranking-snapshot-generator.md b/ai/tasks/done/TASK-168-add-annual-ranking-snapshot-generator.md deleted file mode 100644 index 979e82e..0000000 --- a/ai/tasks/done/TASK-168-add-annual-ranking-snapshot-generator.md +++ /dev/null @@ -1,103 +0,0 @@ ---- -id: TASK-168 -title: Add annual ranking snapshot generator -status: done -type: backend -team: Arquitecto de Base de Datos -supporting_teams: - - Backend Senior - - Arquitecto Python -roadmap_item: foundation -priority: medium ---- - -# TASK-168 - Add annual ranking snapshot generator - -## Goal - -Implementar un generador backend para snapshots anuales top 20 de jugadores sobre datos RCON materializados. - -## Context - -TASK-166 definió el diseño de persistencia, y TASK-167 ya añadió las tablas: - -- `rcon_annual_ranking_snapshots` -- `rcon_annual_ranking_snapshot_items` - -Ahora se necesita el generador que rellene esas tablas desde -`rcon_materialized_matches` y `rcon_match_player_stats` con `source_basis = admin-log-match-ended`. - -Debe mantenerse separado de frontend y sin introducir una API pública todavía. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `docs/annual-ranking-snapshot-schema-plan.md` -- `backend/app/rcon_admin_log_materialization.py` -- `backend/app/rcon_historical_leaderboards.py` -- `backend/app/rcon_historical_player_stats.py` -- `backend/app/postgres_rcon_storage.py` -- `backend/app/sqlite_to_postgres_migration.py` - -## Expected Files to Modify - -- `backend/app/rcon_annual_rankings.py` (crear) -- `backend/app/rcon_admin_log_materialization.py` (si hace falta reutilizar inicialización o alcance) -- `backend/app/postgres_rcon_storage.py` (solo si detecta ajustes de soporte SQLite/Postgres) -- `backend/app/sqlite_to_postgres_migration.py` (solo si detecta ajustes migratorios necesarios) - -## Steps - -1. Seguir los archivos de `Files to Read First` y respetar el contrato de datos existente. -2. Implementar `generate_annual_ranking_snapshot` con: - - `year`, `server_key`, `metric`, `limit`, `replace_existing`. - - Soporte inicial para `metric='kills'`. -3. Agregar una ruta CLI opcional (`python -m app.rcon_annual_rankings generate --year ...`). -4. Reusar conexión SQLite/Postgres con `connect_sqlite_readonly`/`connect_postgres_compat` y placeholders `?`. -5. Validar la función con datos existentes y con BD vacía sin crash. -6. Preparar la Outcome con validación, comportamiento con vacío y limitaciones. - -## Constraints - -- No crear API pública en esta task. -- Mantener el cambio pequeño y verificable. -- No tocar frontend ni archivos `frontend/assets/js/partida-actual.js`. -- No tocar `frontend/assets/img/clans/bxb.png`. -- No reactivar Elo/MMR. -- No reintroducir Comunidad Hispana #03. -- No ampliar workers históricos salvo que sea imprescindible y justificable. -- No incluir métricas adicionales a `kills` salvo que no amplíe el alcance de forma razonable y segura. - -## Validation - -- `python -m compileall backend/app` -- `scripts/run-integration-tests.ps1` cuando aplique. -- Validación local con SQLite: - - inicializar storage, - - ejecutar generador con un año de prueba (si hay datos), - - verificar que se inserta el snapshot y hasta `limit` items. -- Verificar comportamiento sin datos: debe terminar sin excepción y crear snapshot vacío o sin items cuando corresponda. -- `git diff --name-only` y confirmar que no se tocó frontend. - -## Outcome - -- Archivos modificados: - - `backend/app/rcon_annual_rankings.py` (nuevo) -- Función/comando generado: - - `generate_annual_ranking_snapshot(year: int, server_key: str | None = None, metric: str = "kills", limit: int = 20, replace_existing: bool = True, db_path: Path | None = None) -> dict[str, object]`. - - CLI opcional: `python -m app.rcon_annual_rankings generate --year [--server-key ] [--metric kills] [--limit ] [--replace-existing]`. -- Validaciones ejecutadas y resultados: - - `python -m compileall backend/app` (sin errores). - - `scripts/run-integration-tests.ps1` (pasado). - - `initialize_rcon_materialized_storage()` + `generate_annual_ranking_snapshot(year=2026, metric='kills', limit=10)` con datos existentes: snapshot creado (`source_matches_count` > 0), `items <= 10`. - - `generate_annual_ranking_snapshot(year=1990, metric='kills', limit=20)` con ventana sin datos: snapshot creado y `items: []` sin excepción. - - `replace_existing=False` devuelve `skipped_regeneration: True` y reutiliza snapshot existente. - - CLI manual ejecutada: `python -m app.rcon_annual_rankings generate --year 1990 --metric kills --limit 3`. -- Limitaciones conocidas: - - Soporte inicial exclusivamente para `metric='kills'`. - - No se implementó API pública ni refresco programado. - - No se modificón workers históricos. - - No se tocó frontend ni archivos preexistentes `frontend/assets/js/partida-actual.js` y `frontend/assets/img/clans/bxb.png`. -- Siguiente task recomendada: API pública de ranking anual snapshot. diff --git a/ai/tasks/done/TASK-169-add-annual-ranking-snapshot-api.md b/ai/tasks/done/TASK-169-add-annual-ranking-snapshot-api.md deleted file mode 100644 index d24be69..0000000 --- a/ai/tasks/done/TASK-169-add-annual-ranking-snapshot-api.md +++ /dev/null @@ -1,110 +0,0 @@ ---- -id: TASK-169-add-annual-ranking-snapshot-api -title: Add annual ranking snapshot API -status: done -type: backend -team: Backend Senior -supporting_teams: - - Arquitecto Python - - Arquitecto de Base de Datos -roadmap_item: foundation -priority: medium ---- - -# TASK-169-add-annual-ranking-snapshot-api - -## Goal - -Exponer una API de lectura publica para el ranking anual top 20 precomputado desde snapshots almacenadas. - -## Context - -La API debe consumir `rcon_annual_ranking_snapshots` y `rcon_annual_ranking_snapshot_items` generados por el modulo de generacion (TASK-168) y las tablas añadidas por TASK-167. - -Mantiene compatibilidad entre SQLite y Postgres usando el patron de conexion compartido. - -## Steps - -1. Leer los archivos indicados en "Files to Read First". -2. Implementar el endpoint GET `/api/stats/rankings/annual` en backend sin recalcular ranking. -3. Anadir payload y registro de ruta siguiendo patrones existentes. -4. Validar comportamientos esperados (snapshot existente, faltante, metrica no soportada). - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `docs/annual-ranking-snapshot-schema-plan.md` -- `docs/stats-section-functional-plan.md` -- `backend/app/rcon_annual_rankings.py` -- `backend/app/rcon_historical_leaderboards.py` -- `backend/app/rcon_historical_player_stats.py` -- `backend/app/routes.py` -- `backend/app/payloads.py` -- `backend/app/rcon_admin_log_materialization.py` -- `backend/app/postgres_rcon_storage.py` - -## Expected Files to Modify - -- `backend/app/rcon_annual_rankings.py` -- `backend/app/payloads.py` -- `backend/app/routes.py` - -## Constraints - -- Endpoint: `GET /api/stats/rankings/annual?year=&server_id=&metric=kills&limit=` -- `server_id` opcional, `all` por defecto. -- `metric` por ahora solo `kills`. -- `limit` opcional, por defecto 20, validado razonablemente. -- Si no existe snapshot debe responder `snapshot_status="missing"` con `items=[]` y estado HTTP 200. -- No generar snapshot en el endpoint. -- Mantener compatibilidad SQLite/Postgres. -- No tocar frontend. -- No tocar `frontend/assets/js/partida-actual.js` ni `frontend/assets/img/clans/bxb.png`. -- No reactivar Elo/MMR. -- No incluir Comunidad Hispana #03. -- No modificar workers historicos salvo justificacion imprescindible. - -## Validation - -- `python -m compileall backend/app` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- Validacion manual del contrato con backend local o metodo equivalente. - -## Outcome - -### Files modified - -- `backend/app/rcon_annual_rankings.py` -- `backend/app/payloads.py` -- `backend/app/routes.py` - -### Endpoint created - -- `GET /api/stats/rankings/annual?year=&server_id=&metric=kills&limit=` -- Respuestas: - - `snapshot_status=ready` cuando existe snapshot. - - `snapshot_status=missing` cuando no existe snapshot, y devuelve `items=[]`. -- Soporta `metric=kills` y devuelve 400 para metricas no soportadas. - -### Validations performed - -- `python -m compileall backend/app` ✅ -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` ✅ -- Validacion manual usando `app.routes.resolve_get_payload`: - - `/api/stats/rankings/annual` (HTTP 200, respuesta OK) - - `/api/stats/rankings/annual?year=1990` (HTTP 200) - - `/api/stats/rankings/annual?year=1990&metric=kills&limit=3` (HTTP 200) - - `/api/stats/rankings/annual?metric=deaths` (HTTP 400, metrica invalida) - - `/api/stats/rankings/annual?year=1900` (HTTP 200, snapshot_status `missing`, `items=[]`) - -### Limitations - -- Soporta solo `metric=kills` en esta fase. -- Endpoint no genera snapshots (no recalculo); requiere que TASK-168 haya generado datos. -- No se toco frontend en este alcance. - -### Next task recommendation - -Conectar ranking anual top 20 desde frontend Stats. diff --git a/ai/tasks/done/TASK-170-connect-annual-ranking-snapshot-to-stats-frontend.md b/ai/tasks/done/TASK-170-connect-annual-ranking-snapshot-to-stats-frontend.md deleted file mode 100644 index 5d17640..0000000 --- a/ai/tasks/done/TASK-170-connect-annual-ranking-snapshot-to-stats-frontend.md +++ /dev/null @@ -1,125 +0,0 @@ ---- -id: TASK-170 -title: Connect annual ranking snapshot to Stats frontend -status: done -type: frontend -team: Frontend Senior -supporting_teams: [] -roadmap_item: foundation -priority: medium ---- - -# TASK-170 - Connect annual ranking snapshot to Stats frontend - -## Goal - -Conectar el bloque anual top 20 del módulo Stats con la API pública ya creada: - -- `GET /api/stats/rankings/annual?year=&server_id=&metric=kills&limit=20` - -## Context - -Después de implementar el endpoint anual en backend y diseñar la integración frontend de Stats, esta tarea conecta el bloque de placeholder con datos reales de snapshots precomputados y mantiene el comportamiento por estados sin romper la sección actual. - -No se implementan cambios de backend ni migraciones en esta tarea. - -## Steps - -1. Revisar los archivos obligatorios antes de iniciar cambios: - - `AGENTS.md` - - `ai/repo-context.md` - - `ai/architecture-index.md` - - `docs/stats-section-functional-plan.md` - - `docs/stats-frontend-integration-plan.md` - - `docs/annual-ranking-snapshot-schema-plan.md` - - `frontend/stats.html` - - `frontend/assets/js/stats.js` - - `frontend/assets/css/styles.css` - - `backend/app/routes.py` - - `backend/app/payloads.py` - - `backend/app/rcon_annual_rankings.py` -2. Mantener el placeholder de ranking anual en el HTML, reemplazándolo por estados y tabla dinámica del endpoint. -3. Implementar consumo del endpoint anual con estado por: - - ready - - missing - - error/backend no disponible -4. Mantener `metric=kills` y `limit=20` fijos en V1. -5. Validar carga/estado con `node --check` y pruebas de endpoint si hay backend. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `docs/stats-section-functional-plan.md` -- `docs/stats-frontend-integration-plan.md` -- `docs/annual-ranking-snapshot-schema-plan.md` -- `frontend/stats.html` -- `frontend/assets/js/stats.js` -- `frontend/assets/css/styles.css` -- `backend/app/routes.py` -- `backend/app/payloads.py` -- `backend/app/rcon_annual_rankings.py` - -## Expected Files to Modify - -- `frontend/stats.html` -- `frontend/assets/js/stats.js` -- `frontend/assets/css/styles.css` (solo si se requiere ajuste visual para el bloque anual) -- `ai/tasks/pending/TASK-170-connect-annual-ranking-snapshot-to-stats-frontend.md` (estado + outcome) - -## Constraints - -- Mantener frontend vanilla sin frameworks ni cambios de backend. -- No crear migraciones. -- No modificar `frontend/assets/js/partida-actual.js`. -- No modificar `frontend/assets/img/clans/bxb.png`. -- No reintroducir Comunidad Hispana #03. -- Mantener el bloque anual como consumo de snapshot (`ready`, `missing` o backend no disponible). -- No implementar generador anual desde frontend. - -## Validation - -Antes de cerrar: - -- `node --check frontend/assets/js/stats.js` -- (si aplica) `python -m http.server` y comprobar HTTP 200 para `frontend/stats.html` y `frontend/assets/js/stats.js`. -- Consumir `GET /api/stats/rankings/annual` desde la UI cuando backend local esté disponible. -- Verificar caso con snapshot existente y caso sin snapshot (`snapshot_status="missing"`). -- `scripts/run-integration-tests.ps1` si aplica. -- `git diff --name-only` y validar que el alcance no excede la task. -- `git status --short --untracked-files=all` y confirmar que no se tocó `partida-actual.js` ni `img/clans/bxb.png`. - -## Outcome - -- Archivos modificados: - - `frontend/stats.html` - - `frontend/assets/js/stats.js` - - `frontend/assets/css/styles.css` (ajustes del bloque anual) - - `ai/tasks/done/TASK-170-connect-annual-ranking-snapshot-to-stats-frontend.md` -- Endpoint consumido: - - `GET /api/stats/rankings/annual?year=&server_id=&metric=kills&limit=20` -- Comportamiento `snapshot_status=ready`: - - Muestra el bloque de ranking anual con filas del top (`ranking_position`, `player_name`, `metric_value`, `matches_considered`, `kills`, `deaths`, `teamkills`, `kd_ratio`), metadatos de servidor, fuente y fecha. -- Comportamiento `snapshot_status=missing`: - - Muestra estado informativo de no disponibilidad de ranking para el año seleccionado. - - No lanza error ni bloquea el resto del flujo. -- Comportamiento con backend no disponible: - - El estado general y anual muestran error (`Backend no disponible...`) y no se hacen cambios de UI inconsistentes. -- Validaciones ejecutadas: - - `node --check frontend/assets/js/stats.js` - - `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` - - Servido local con `python -m http.server` y comprobación HTTP 200 de `frontend/stats.html` y `frontend/assets/js/stats.js` - - `git status --short --untracked-files=all` - - `git diff --name-only` -- Limitaciones conocidas: - - No se pudo validar integración real contra backend porque `http://127.0.0.1:8000` no estaba disponible en este entorno. - - Los textos en este bloque se mantienen en ASCII para evitar cambios de encoding. -- Siguiente tarea recomendada: - - Conectar la vista de `Stats` con `frontend/index.html`/`frontend/historico.html` si aplica y/o añadir mejoras visuales en el bloque anual. - - -## Change Budget - -- Preferir cambios < 5 archivos y < 200 líneas. -- Mantener cambio pequeño y verificable. diff --git a/ai/tasks/done/TASK-171-validate-stats-section-with-backend-data.md b/ai/tasks/done/TASK-171-validate-stats-section-with-backend-data.md deleted file mode 100644 index 3a4a6ef..0000000 --- a/ai/tasks/done/TASK-171-validate-stats-section-with-backend-data.md +++ /dev/null @@ -1,131 +0,0 @@ ---- -id: TASK-171 -title: Validate Stats section with backend data -status: done -type: platform -team: Frontend Senior -supporting_teams: [Backend Senior] -roadmap_item: foundation -priority: medium ---- - -# TASK-171 - Validate Stats section with backend real data - -## Goal - -Validate the Stats section end-to-end against local backend and data sources without -introducing new features. - -## Context - -The previous tasks already implemented player search, player profile, annual -ranking endpoint, and the Stats frontend page. - -Maintain the current product identity: Spanish-speaking HLL Vietnam community, -military/Vietnam/tactical/sober visual direction and controlled repository evolution. - -## Steps - -1. Confirm git status before starting validation and verify pre-existing local frontend files. -2. Read required files first (AGENTS + docs + frontend/backend files for Stats). -3. Validate backend endpoints when available: - - GET /health - - GET /api/stats/players/search?q= - - GET /api/stats/players/{player_id} - - GET /api/stats/rankings/annual?year=&server_id=all&metric=kills&limit=20 -4. Serve or open `frontend/stats.html` and validate UI states. -5. Run required checks: - - `node --check frontend/assets/js/stats.js` - - `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` (if applicable) -6. Record validation results and keep any changes within minimal scope. -7. If a small Stats-specific bug is found, patch it. - -## Files to Read First - -- AGENTS.md -- ai/repo-context.md -- ai/architecture-index.md -- docs/stats-section-functional-plan.md -- frontend/stats.html -- frontend/assets/js/stats.js -- backend/app/routes.py -- backend/app/rcon_historical_player_stats.py -- backend/app/rcon_historical_leaderboards.py -- backend/app/rcon_annual_rankings.py - -## Expected Files to Modify - -- ai/tasks/done/TASK-171-validate-stats-section-with-backend-data.md -- (Optional) `frontend/assets/js/stats.js` or `frontend/stats.html` only for - minimal Stats-specific bug fixes. - -## Constraints - -- No new features. -- No visual redesign. -- Do not touch `frontend/assets/js/partida-actual.js`. -- Do not touch `frontend/assets/img/clans/bxb.png`. -- Do not reactivate Elo/MMR. -- Do not reintroduce Comunidad Hispana #03. -- Do not modify historical workers. -- Do not modify DB unless a migration follow-up is explicitly required. - -## Validation - -Before completing, ensure: - -- backend endpoints were tested where possible. -- frontend runtime states were checked. -- `node --check frontend/assets/js/stats.js`. -- `scripts/run-integration-tests.ps1` executed when available. -- `git diff --name-only` checked if modifications were made. - -## Outcome - -Status: completed - -### Files read -- AGENTS.md -- ai/repo-context.md -- ai/architecture-index.md -- docs/stats-section-functional-plan.md -- frontend/stats.html -- frontend/assets/js/stats.js -- backend/app/routes.py -- backend/app/rcon_historical_player_stats.py -- backend/app/rcon_historical_leaderboards.py -- backend/app/rcon_annual_rankings.py - -### Endpoints probados -- `GET /health` -> 200 -- `GET /api/stats/players/search?q=rambo` -> 200 (items empty) -- `GET /api/stats/players/76561198350628987?timeframe=weekly` -> 200 -- `GET /api/stats/rankings/annual?year=2026&server_id=all&metric=kills&limit=20` -> 200, `snapshot_status="ready"` -- `GET /api/stats/rankings/annual?year=1990&server_id=all&metric=kills&limit=3` -> 200, ready and empty -- `GET /api/stats/rankings/annual?year=2040&server_id=all&metric=kills&limit=20` -> 200, `snapshot_status="missing"`, `items=[]` -- `GET /api/stats/rankings/annual?year=2026&metric=deaths&limit=20` -> 400 (`Invalid metric parameter`) - -### Respuestas y estado visual -- Health and payload endpoints responded correctly. -- Search can return empty set with local dataset. -- Player profile endpoint returns weekly/monthly ranking payloads and allows runtime rendering. -- Annual ranking endpoint returns ready/empty and missing states as expected. -- `frontend/stats.html` and `frontend/assets/js/stats.js` were served with HTTP 200. -- `node --check frontend/assets/js/stats.js` passed. -- Browser interactive runtime error checks could not be executed in this environment. - -### Validaciones ejecutadas -- `node --check frontend/assets/js/stats.js` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- local backend started and queried via endpoints -- local static server started and `stats.html` / `stats.js` fetched successfully - -### Validaciones pendientes / limitaciones -- No se dispuso de DB con jugadores de prueba para validar search con resultados positivos y render completo en UI. -- No se hizo comprobacion interactiva de "backend no disponible" en navegador real. - -### Archivos modificados -- `ai/tasks/in-progress/TASK-171-validate-stats-section-with-backend-data.md` - -### Siguiente task recomendada -- Añadir smoke test de UI con navegador/headless para validar estados runtime de `stats.js` y errores de backend en integración local. diff --git a/ai/tasks/done/TASK-172-polish-stats-section-empty-states-and-copy.md b/ai/tasks/done/TASK-172-polish-stats-section-empty-states-and-copy.md deleted file mode 100644 index accdc91..0000000 --- a/ai/tasks/done/TASK-172-polish-stats-section-empty-states-and-copy.md +++ /dev/null @@ -1,149 +0,0 @@ ---- -id: TASK-172 -title: Pulir estados UX de la sección Stats -status: done -type: frontend -team: Frontend Senior -supporting_teams: [Backend Senior, Disenador grafico, Experto en interfaz] -roadmap_item: foundation -priority: medium ---- - -# TASK-172 - Pulir estados UX de la sección Stats - -## Goal - -Pulir la experiencia de usuario de la sección Stats en estados vacíos y errores, manteniendo la funcionalidad actual y el contrato backend existente. - -Preservar la identidad: comunidad hispana de HLL Vietnam con tono militar/Vietnam/táctico/sobrio y cambios progresivos del frontend. - -## Context - -Tras TASK-171, la sección Stats debe comunicar mejor: -- estados de backend no disponible, -- búsqueda sin resultados, -- jugador sin estadísticas, -- ranking anual listo pero vacío, -- ranking anual sin generar, -- y soporte inválido para métrica no soportada. - -No se modifica la lógica de datos ni se crean nuevos endpoints. - -## Steps - -1. Confirmar la lectura de los archivos listados en "Files to Read First". -2. Revisar textos de estado actuales y su trazabilidad UX en `frontend/stats.html` y `frontend/assets/js/stats.js`. -3. Ajustar mensajes para que sean claros, consistentes y diferenciados entre: - - backend no disponible - - búsqueda sin resultados - - jugador sin estadísticas - - ranking anual listo sin items - - ranking anual missing - - métrica anual no soportada -4. Mantener HTML/CSS/JS vanilla y la estética actual. -5. Mantener cualquier cambio de texto o estado dentro de los ficheros de Scope. -6. Ejecutar validaciones mínimas de task: sintaxis, tests de integración y carga de frontend. - -## Files to Read First - -- AGENTS.md -- ai/repo-context.md -- ai/architecture-index.md -- docs/stats-section-functional-plan.md -- frontend/stats.html -- frontend/assets/js/stats.js -- frontend/assets/css/styles.css -- ai/tasks/done/TASK-171-validate-stats-section-with-backend-data.md - -## Expected Files to Modify - -- frontend/stats.html -- frontend/assets/js/stats.js -- frontend/assets/css/styles.css - -## Constraints - -- No crear endpoints. -- No modificar backend. -- No modificar base de datos. -- No cambiar la lógica de ranking. -- No reactivar Elo/MMR. -- No reintroducir Comunidad Hispana #03. -- No tocar: - - frontend/assets/img/clans/bxb.png - - frontend/assets/js/partida-actual.js - -## Validation - -Antes de completar la task, validar: -- `node --check frontend/assets/js/stats.js` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- servir frontend con `python -m http.server` y comprobar: - - `stats.html` -> 200 - - `assets/js/stats.js` -> 200 -- revisar `git diff --name-only` y confirmar scope. - -## Outcome - -### Status - -Done - -### Files modified - -- frontend/stats.html -- frontend/assets/js/stats.js - -### Estados y textos mejorados - -1. Estado inicial: - - Mensaje de inicio del buscador, ranking semanal/mensual y estado anual clarifica el flujo. -2. Backend no disponible: - - Mensajes específicos para búsqueda/perfil y ranking anual. -3. Busqueda sin resultados: - - Mensaje textual objetivo y sin ambiguedad. -4. Jugador sin estadisticas: - - Mensaje de estado explicito y panel de resumen con warning. -5. Ranking anual ready pero vacio: - - Distinguido de snapshot missing. -6. Ranking anual missing: - - Mensaje que indica ausencia de snapshot y estado pendiente. -7. Metrica anual no soportada: - - Detectada por 400 + mensaje de soporte invalid. - -### Mensajes de ayuda - -- Se agrega ayuda explicita para: - - resumen semanal, - - resumen mensual, - - ranking anual pre-computado. - -### Accesibilidad y usabilidad - -- Botones con `aria-label`. -- Estados con role/status y mensajes persistentes en bloques dedicados. - -### Validaciones realizadas - -- `node --check frontend/assets/js/stats.js` (ok). -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` (ok). -- Servidor local levantado con `python -m http.server` en 8080: - - `http://127.0.0.1:8080/stats.html` -> 200 - - `http://127.0.0.1:8080/assets/js/stats.js` -> 200 -- `git diff --name-only` revisado para confirmar alcance de cambios. - -### Limitaciones detectadas - -- Mensajes y UI se mantienen en ASCII en algunos textos para evitar regresiones de encoding existente en entorno. -- No se modificaron ni se revalidaron flujos visuales de backend offline via navegador. - -### Follow ups - --- Revisar posibles mejoras tipograficas de textos de apoyo para corregir - errores menores de copy en futuras iteraciones. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Mantener cambios acotados y revisables. diff --git a/ai/tasks/done/TASK-173-add-annual-ranking-snapshot-runbook.md b/ai/tasks/done/TASK-173-add-annual-ranking-snapshot-runbook.md deleted file mode 100644 index 174531a..0000000 --- a/ai/tasks/done/TASK-173-add-annual-ranking-snapshot-runbook.md +++ /dev/null @@ -1,121 +0,0 @@ ---- -id: TASK-173 -title: Add annual ranking snapshot runbook -status: done -type: documentation -team: PM -supporting_teams: [Backend Senior, Frontend Senior, Arquitecto de Base de Datos] -roadmap_item: foundation -priority: medium ---- - -# TASK-173 - Add annual ranking snapshot runbook - -## Goal - -Documentar la operacion del ranking anual top 20 para la seccion Stats: como generar, regenerar y validar usando snapshots precomputados para evitar recalcular anualmente en cada request. - -## Context - -TASK-173 define el proceso operativo para el bloque anual de Stats que consume: - -- `GET /api/stats/rankings/annual?year=&server_id=&metric=kills&limit=20` - -El documento mantiene alcance documentación-only y reitera que la fuente preferente es RCON materializado. - -## Steps - -1. Revisar archivos obligatorios indicados en la task. -2. Crear/actualizar runbook sin tocar backend ni frontend. -3. Documentar fuente, comandos, validaciones y casos esperados. - -## Files to Read First - -- AGENTS.md -- ai/repo-context.md -- ai/architecture-index.md -- docs/stats-section-functional-plan.md -- backend/app/rcon_annual_rankings.py -- backend/app/routes.py -- frontend/assets/js/stats.js -- ai/tasks/done/TASK-170-connect-annual-ranking-snapshot-to-stats-frontend.md -- ai/tasks/done/TASK-171-validate-stats-section-with-backend-data.md -- ai/tasks/done/TASK-172-polish-stats-section-empty-states-and-copy.md - -## Expected Files to Modify - -- `docs/annual-ranking-snapshot-runbook.md` -- `ai/tasks/done/TASK-173-add-annual-ranking-snapshot-runbook.md` - -## Constraints - -- Documentacion-only. -- No modificar backend. -- No modificar frontend. -- No crear migraciones. -- No cambiar scripts salvo que exista comando explícito y se limite a documentación. -- No tocar: - - `frontend/assets/js/partida-actual.js` - - `frontend/assets/img/clans/bxb.png` -- Mantener restricciones funcionales: - - no reactivar Elo/MMR - - no reintroducir Comunidad Hispana #03 - -## Validation - -- Confirmar que `docs/annual-ranking-snapshot-runbook.md` existe. -- Ejecutar `git diff --name-only`. -- Validar alcance esperado de archivos modificados. -- Si no hay test automáticos por ser documentación-only, documentarlo en Outcome. - -## Outcome - -### Status - -Done - -### Files modified - -- `docs/annual-ranking-snapshot-runbook.md` -- `ai/tasks/done/TASK-173-add-annual-ranking-snapshot-runbook.md` - -### Documentation created - -- Runbook creado en `docs/annual-ranking-snapshot-runbook.md` con: - - propósito del snapshot anual top 20, - - fuente de datos materializada RCON (`rcon_materialized_matches`, `rcon_match_player_stats`) y filtro `source_basis=admin-log-match-ended`, - - endpoint consumidor `GET /api/stats/rankings/annual?...`, - - pasos de generacion y regeneracion, - - validacion de existencia, - - validacion desde API y desde frontend Stats, - - casos esperados: - - `snapshot_status="ready"` con items, - - `snapshot_status="ready"` vacío, - - `snapshot_status="missing"`, - - metrica no soportada en V1. - - alertas: - - no recalcular ranking anual por request público, - - no usar scoreboard publico como fuente primaria si RCON disponible, - - no reintroducir Elo/MMR, - - no reintroducir Comunidad Hispana #03. - -### Validacion - -- Confirmado que `docs/annual-ranking-snapshot-runbook.md` existe. -- `git diff --name-only` y `git status --short --untracked-files=all` revisados para validar alcance. -- Esta tarea es documentación-only; no aplica tests automáticos. - -### Limitaciones conocidas - -- No se cambian scripts ni operaciones de mantenimiento en esta tarea. -- No se realizan cambios de backend/frontend. - -### Siguiente task recomendada - -- Automatizar la ejecucion del generador anual (cron/manual) y capturar artefactos de operador. - -## Change Budget - -- Prefer < 5 files. -- Prefer cambios acotados y revisables. -- Mantener doc corta y accionable. diff --git a/ai/tasks/done/TASK-174-review-existing-current-match-and-bxb-local-changes.md b/ai/tasks/done/TASK-174-review-existing-current-match-and-bxb-local-changes.md deleted file mode 100644 index 7b74490..0000000 --- a/ai/tasks/done/TASK-174-review-existing-current-match-and-bxb-local-changes.md +++ /dev/null @@ -1,121 +0,0 @@ ---- -id: TASK-174 -title: Review existing current-match and bxb local changes -status: done -type: documentation -team: PM -supporting_teams: [Frontend Senior, Backend Senior] -roadmap_item: foundation -priority: medium ---- - -# TASK-174 - Review existing current-match and bxb local changes - -## Goal - -Analizar y decidir cómo tratar los cambios locales existentes en: - -- `frontend/assets/img/clans/bxb.png` -- `frontend/assets/js/partida-actual.js` - -sin tocar Stats ni backend, y sin descartar cambios sin confirmación humana. - -## Context - -Se detectaron cambios locales preexistentes fuera del flujo Stats que deben resolverse de forma controlada y trazable: - -- asset de clan `bxb.png` -- mejoras funcionales sobre `partida-actual.js` - -## Steps - -1. Confirmar estado local actual y alcance de cambios. -2. Mover esta tarea a `ai/tasks/in-progress`. -3. Revisar los archivos indicados en `Files to Read First`. -4. Revisar `git diff frontend/assets/js/partida-actual.js` y resumir cambios exactos. -5. Revisar cambio binario de `frontend/assets/img/clans/bxb.png` (tamaño/tipo/posible finalidad como reemplazo de asset). -6. Decidir si ambos cambios son relacionados o deben tratarse por separado. -7. Ejecutar validaciones básicas solo si procede conservar y no hay dudas: - - `node --check frontend/assets/js/partida-actual.js` - - `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -8. Definir decisión: - - commitear juntos si ambos cambios son relacionados y correctos, - - separar en commits si ambos son correctos pero no relacionados, - - mover a `ai/tasks/review` si hay dudas o requeriría confirmación humana. - -## Files to Read First - -- AGENTS.md -- ai/repo-context.md -- ai/architecture-index.md -- frontend/assets/js/partida-actual.js -- frontend/stats.html -- frontend/assets/js/stats.js -- docs/annual-ranking-snapshot-runbook.md -- ai/tasks/done/TASK-173-add-annual-ranking-snapshot-runbook.md - -## Expected Files to Modify - -- `ai/tasks/in-progress/TASK-174-review-existing-current-match-and-bxb-local-changes.md` (actualización de outcome) -- `ai/tasks/done/TASK-174-review-existing-current-match-and-bxb-local-changes.md` o -- `ai/tasks/review/TASK-174-review-existing-current-match-and-bxb-local-changes.md` - -## Constraints - -- No implementar nuevas features. -- No tocar backend. -- No tocar Stats (más allá de verificación pasiva de que no se rompe). -- No tocar endpoints. -- No reactivar Elo/MMR. -- No reintroducir Comunidad Hispana #03. -- No cambiar workers históricos. -- No descartar cambios sin confirmación humana. -- No mezclar estos cambios con futuras tareas de Stats. - -## Validation - -- Revisar que `git status --short --untracked-files=all` refleje únicamente estos cambios de producto. -- `git diff --name-only` dentro del scope de esta tarea. -- Si se ejecutan validaciones, registrar resultados (check JS, tests, estado HTTP de assets/página relacionada si aplica). - -## Outcome - -### Resultados de revisión - -- En `frontend/assets/js/partida-actual.js` cambia exclusivamente la etiqueta visible del arma para aliases de Kar98k: - - `kar98k` - - `kar 98k` - - `kar98` - - `k98` - - `k98k` - - El valor pasó de `"Kar98k"` a `"KARABINER 98K"` en esas cinco entradas. -- `frontend/assets/js/partida-actual.js` mantiene funcionalidad intacta y no afecta a rutas de API, backend ni Stats. -- `frontend/assets/img/clans/bxb.png` es un cambio binario de imagen. - - Tipo detectado: `PNG`. - - Tamaño en HEAD: `370262` bytes. - - Tamaño actual: `1148813` bytes. - - Dimensiones HEAD: `1145x691`. - - Dimensiones actuales: `1376x752`. -- La evidencia sugiere que `bxb.png` es un reemplazo de asset de clan (resolución y peso mayores), no una edición de código. - -### Relación y resolución - -- Los cambios no están relacionados entre sí: - - `partida-actual.js`: ajuste de texto de etiqueta visual de arma. - - `bxb.png`: sustitución de asset gráfico de clan. -- Se conservarán por separado y se commitean de forma independiente para mantener trazabilidad. - -### Validaciones ejecutadas - -- `node --check frontend/assets/js/partida-actual.js` (sin errores). -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` (exit 0, validación de plataforma e historial OK; sin tests de integración de producto necesarios para este scope). -- `python -m http.server 8080` validado contra `frontend`: - - `http://127.0.0.1:8080/partida-actual.html` → HTTP 200. - - `http://127.0.0.1:8080/assets/js/partida-actual.js` → HTTP 200. - -### Decisión final - -- Mantener ambos cambios y no descartarlos. -- Ejecutar commits separados por no estar relacionados. -- Se deja marcada como completa y se prepara para mover a `done`. diff --git a/ai/tasks/done/TASK-175-add-stats-regression-validation-script.md b/ai/tasks/done/TASK-175-add-stats-regression-validation-script.md deleted file mode 100644 index 97dddcb..0000000 --- a/ai/tasks/done/TASK-175-add-stats-regression-validation-script.md +++ /dev/null @@ -1,97 +0,0 @@ ---- -id: TASK-175-add-stats-regression-validation-script -title: Add Stats regression validation script -status: done -type: platform -team: PM -supporting_teams: - - Backend Senior - - Frontend Senior -roadmap_item: foundation -priority: high ---- - -# TASK-175-add-stats-regression-validation-script - Add Stats regression validation script - -## Goal - -Add a small, repeatable validation for the existing Stats frontend/backend surfaces that protects current endpoints and assets, without changing behavior. - -## Context - -The Stats section already has public-facing pages, JS assets, and backend endpoints that can regress independently. This task should add a lightweight executable validation flow (script-based) that is tolerant to envs with no local data and can still verify expected behavior and error states. - -## Steps - -1. Read the listed files first. -2. Define a focused Stats validation workflow without changing any application behavior. -3. Add/update a script that checks key assets and endpoints, including supported and empty/missing states. -4. Ensure the validation outputs clear status and actionable next steps when backend is unavailable. -5. Document endpoint behavior, known environment limits, and the recommended follow-up task. - -## Files to Read First - -- AGENTS.md -- ai/repo-context.md -- ai/architecture-index.md -- docs/stats-section-functional-plan.md -- docs/annual-ranking-snapshot-runbook.md -- frontend/stats.html -- frontend/assets/js/stats.js -- backend/app/routes.py -- scripts/run-integration-tests.ps1 - -## Expected Files to Modify - -- scripts/run-stats-validation.ps1 (or equivalent repo-preferred validation script) -- scripts/run-integration-tests.ps1 only if a safe integration point is justified -- ai/tasks/done/TASK-175-add-stats-regression-validation-script.md - -## Constraints - -- No behavior change in Stats. -- No UI redesign. -- No ranking logic changes. -- No database schema changes. -- Do not re-enable Elo/MMR. -- Do not reintroduce Comunidad Hispana #03. -- Keep validation tolerant to environments without positive local data. -- If backend is unavailable, document the expected validation behavior instead of failing with ambiguous output. - -## Validation - -- Run `node --check frontend/assets/js/stats.js`. -- Run `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1`. -- Run the new Stats validation script. -- Run `git diff --name-only` and verify scope is within the task plan. - -## Outcome - -Validated surfaces: - -- `frontend/stats.html` asset wiring and required Stats UI anchors -- `GET /health` -- `GET /api/stats/players/search` -- `GET /api/stats/players/{player_id}` -- `GET /api/stats/rankings/annual` - -Implemented validation: - -- Added `scripts/run-stats-validation.ps1` to check Stats asset presence, route-contract behavior, invalid parameter handling, and controlled backend-unavailable messaging. -- Wired `scripts/run-integration-tests.ps1` to execute the Stats validation and fail on non-zero child process exit codes. - -Controlled limitations observed during validation: - -- The local live backend was not running during task validation, so live HTTP checks reported the expected offline guidance instead of ambiguous failure. -- Current normalized all-server scope is returned as `all-servers`. -- Annual ranking `data.limit` currently reflects the effective stored snapshot size when a ready snapshot contains fewer rows than the requested limit; the validator accepts that current behavior without changing runtime logic. - -Validation run: - -- `node --check frontend/assets/js/stats.js` -- `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` - -Immediate follow-up recommendation: - -- Continue with `TASK-176-add-stats-player-comparison-cards`, using the new Stats validation script as the regression guard for the existing Stats surface. diff --git a/ai/tasks/done/TASK-176-add-stats-player-comparison-cards.md b/ai/tasks/done/TASK-176-add-stats-player-comparison-cards.md deleted file mode 100644 index a333349..0000000 --- a/ai/tasks/done/TASK-176-add-stats-player-comparison-cards.md +++ /dev/null @@ -1,124 +0,0 @@ ---- -id: TASK-176-add-stats-player-comparison-cards -title: Add stats player comparison cards -status: done -type: frontend -team: Frontend Senior -supporting_teams: - - Experto en interfaz - - Backend Senior -roadmap_item: foundation -priority: high ---- - -# TASK-176-add-stats-player-comparison-cards - Add stats player comparison cards - -## Goal - -Improve the Stats UI with comparison cards that help a selected player quickly understand personal metrics and weekly/monthly position, using already available backend data and without creating new endpoints. - -## Context - -The Stats page already exposes player lookup and detail payloads. This task should improve clarity and trust by surfacing key performance values in cards, while preserving empty/loading/error behavior and the existing visual identity. - -## Steps - -1. Read the listed files first. -2. Add UI card components in the existing Stats section for selected-player context. -3. Consume existing fields from current responses only, without changing API contracts. -4. Show explicit states for missing ranking, insufficient ranking depth, or missing player in weekly/monthly snapshots. -5. Keep design aligned with military/Vietnam/tactical sober style and keep existing empty/loading/error states intact. - -## Files to Read First - -- AGENTS.md -- ai/repo-context.md -- ai/architecture-index.md -- docs/stats-section-functional-plan.md -- frontend/stats.html -- frontend/assets/js/stats.js -- frontend/assets/css/styles.css -- backend/app/rcon_historical_player_stats.py -- ai/tasks/done/TASK-172-polish-stats-section-empty-states-and-copy.md - -## Expected Files to Modify - -- frontend/stats.html -- frontend/assets/js/stats.js -- frontend/assets/css/styles.css -- ai/tasks/done/TASK-176-add-stats-player-comparison-cards.md - -## Constraints - -- No backend modifications. -- No new endpoints. -- No database changes. -- Do not change existing API contracts. -- Do not re-enable Elo/MMR. -- Do not reintroduce Comunidad Hispana #03. -- Do not introduce frameworks. -- Keep vanilla HTML/CSS/JS implementation. -- Keep military/Vietnam/tactical/sober visual identity. -- Preserve existing empty/loading/error states and avoid regressions. - -## Validation - -- Run `node --check frontend/assets/js/stats.js`. -- Run `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1`. -- Serve frontend with `python -m http.server` and verify HTTP 200 for `stats.html` and `assets/js/stats.js`. -- If possible, visually validate with local backend. -- Run `git diff --name-only` and verify scope is limited to this task. - -## Outcome - -Implemented comparison cards: - -- Added a dedicated comparison-card grid inside the selected-player profile panel. -- Added weekly and monthly window cards using only existing profile payload fields. -- Added a comparison card that contrasts weekly vs monthly KPM, K/D, kills delta, and matches delta. - -Payload fields consumed: - -- `player_id` -- `player_name` -- `matches_considered` -- `kills` -- `deaths` -- `teamkills` -- `kd_ratio` -- `kills_per_match` -- `deaths_per_match` -- `weekly_ranking` -- `monthly_ranking` -- `window_kind` -- `window_start` -- `window_end` - -Behavior with no data or limited ranking: - -- If both weekly and monthly windows have zero matches, the existing warning state remains and the comparison cards show explicit "Sin actividad" messaging. -- If a ranking block is absent, the cards show `Ranking ausente`. -- If a ranking exists but `ranking_position` is empty and the active window is a fallback `previous-*` window, the cards show `Profundidad insuficiente`. -- If a ranking exists but the player is not positioned in the visible ranking, the cards show `Fuera del ranking visible`. - -Implementation notes: - -- The frontend now fetches the existing player profile endpoint twice in parallel, once for `weekly` and once for `monthly`, without adding endpoints or changing backend contracts. -- The tactical visual style stays within the current Stats surface and reuses the existing palette and panel language. - -Validation run: - -- `node --check frontend/assets/js/stats.js` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- Local static server: - - `http://127.0.0.1:8091/stats.html` -> 200 - - `http://127.0.0.1:8091/assets/js/stats.js` -> 200 - -Known limitations: - -- Visual validation against a live local backend was not possible because `http://127.0.0.1:8000` was unavailable during this task. -- The Browser plugin surface was not available as `iab` in this session, so browser-level visual inspection could not be completed through the in-app browser. - -Immediate follow-up improvements: - -- Continue with `TASK-177-harden-annual-ranking-snapshot-operations` so the annual ranking endpoint behavior around effective limits and missing years is better defined and easier for the Stats UI to explain. diff --git a/ai/tasks/done/TASK-177-harden-annual-ranking-snapshot-operations.md b/ai/tasks/done/TASK-177-harden-annual-ranking-snapshot-operations.md deleted file mode 100644 index 0dbfbf6..0000000 --- a/ai/tasks/done/TASK-177-harden-annual-ranking-snapshot-operations.md +++ /dev/null @@ -1,118 +0,0 @@ ---- -id: TASK-177-harden-annual-ranking-snapshot-operations -title: Harden annual ranking snapshot operations -status: done -type: backend -team: Backend Senior -supporting_teams: - - Arquitecto de Base de Datos - - PM -roadmap_item: foundation -priority: medium ---- - -# TASK-177-harden-annual-ranking-snapshot-operations - Harden annual ranking snapshot operations - -## Goal - -Improve annual ranking snapshot reliability for production use without recalculating on public requests or changing visible frontend behavior. - -## Context - -The annual snapshot flow is implemented and documented, but edge cases around missing data, empty years, unsupported years/metrics, and limit normalization should be hardened with small, verifiable backend improvements. - -## Steps - -1. Read the listed files first. -2. Review generation and read flow for annual ranking snapshots. -3. Apply small validation and response consistency improvements in backend code. -4. Ensure snapshot behavior remains stable for ready/empty/missing and unsupported metric states. -5. Document any follow-up work that should remain a separate task instead of broadening this one. - -## Files to Read First - -- AGENTS.md -- ai/repo-context.md -- ai/architecture-index.md -- docs/stats-section-functional-plan.md -- docs/annual-ranking-snapshot-runbook.md -- backend/app/routes.py -- backend/app/rcon_annual_rankings.py -- backend/app/rcon_historical_leaderboards.py -- ai/tasks/done/TASK-171-validate-stats-section-with-backend-data.md -- ai/tasks/done/TASK-173-add-annual-ranking-snapshot-runbook.md - -## Expected Files to Modify - -- backend/app/rcon_annual_rankings.py -- backend/app/routes.py only if endpoint mapping/validation requires changes -- docs/annual-ranking-snapshot-runbook.md only if documented operations change -- ai/tasks/done/TASK-177-harden-annual-ranking-snapshot-operations.md - -## Constraints - -- No frontend modifications unless a strict critical backend-related bug requires it (and document the reason). -- No new architecture. -- No major migrations. -- Do not re-enable Elo/MMR. -- Do not reintroduce Comunidad Hispana #03. -- Do not use public scoreboard as primary source. -- Do not recalculate annual ranking in each public request. -- Keep changes small and independently verifiable. - -## Validation - -- Run `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1`. -- Test annual ranking endpoint for: - - current year with `metric=kills` - - past year with no data - - future year missing snapshot - - unsupported metric - - low limit, e.g. `3` - - high limit, verifying normalization if applicable -- Run `git diff --name-only` and verify scoped files only. - -## Outcome - -Applied hardening: - -- Added explicit annual year normalization in `backend/app/rcon_annual_rankings.py` for supported `1..9999` values. -- Added reusable limit normalization in the annual snapshot reader/generator with a bounded cap of `100`. -- Added response metadata for annual snapshot reads: - - `requested_limit` - - `effective_limit` - - `snapshot_limit` - - `item_count` -- Hardened effective-limit resolution so a ready snapshot serves no more rows than: - - the requested limit, - - the persisted snapshot limit, - - and the actual stored item count. -- Wrapped the annual route payload build in a `ValueError` guard so invalid annual requests return controlled `400` payloads. - -Documentation updated: - -- `docs/annual-ranking-snapshot-runbook.md` now documents annual limit metadata and explains why `effective_limit` can be lower than `requested_limit` for ready snapshots. - -Validated responses: - -- current year with `metric=kills` -> `200` -- past year with no guaranteed data -> controlled `200` with `ready` or `missing` depending on stored snapshot presence -- future year without snapshot -> `200` with `snapshot_status="missing"` -- unsupported metric -> `400` -- low limit `3` -> `200`, `requested_limit=3`, `effective_limit<=3` -- high limit `101` -> `400` -- unsupported year `10000` -> `400` - -Validation run: - -- Inline Python route validation for the annual endpoint cases above -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` - -Known limits: - -- The API still keeps `limit` aligned with the served effective limit for ready snapshots so current frontend behavior remains unchanged. -- This task does not add scheduling or regeneration automation; it only hardens the existing read/generate contract. - -Future task recommendation: - -- If operations need stronger guarantees, create a follow-up task for scheduled annual snapshot generation/audit reporting rather than broadening this read-path hardening further. diff --git a/ai/tasks/done/TASK-178-review-stats-implementation-after-hardening.md b/ai/tasks/done/TASK-178-review-stats-implementation-after-hardening.md deleted file mode 100644 index 53f1dbe..0000000 --- a/ai/tasks/done/TASK-178-review-stats-implementation-after-hardening.md +++ /dev/null @@ -1,143 +0,0 @@ ---- -id: TASK-178 -title: Review Stats Implementation After Hardening -status: done -type: documentation -team: Analista -supporting_teams: - - Frontend Senior - - Backend Senior - - PM -roadmap_item: foundation -priority: medium ---- - -# TASK-178 - Review Stats Implementation After Hardening - -## Goal - -Realizar una revisión técnica del bloque Stats tras TASK-175, TASK-176 y TASK-177, sin implementar nuevas funcionalidades, para verificar coherencia funcional, robustez y consistencia entre documentación, contratos y comportamiento real. - -## Context - -La revisión debe cubrir el estado actual de Stats en frontend y backend con enfoque en comportamiento funcional estable, confiabilidad operativa y ausencia de regresiones en restricciones previas (sin Elo/MMR, sin reintroducir Comunidad Hispana #03). -Se debe preservar la identidad del repositorio y no ampliar alcance fuera del bloque Stats. - -## Steps - -1. Leer los archivos listados en “Files to Read First” para ubicar el estado base de la revisión. -2. Auditar los archivos objetivo y verificar los 9 puntos solicitados por el alcance de la task. -3. Ejecutar las validaciones técnicas solicitadas (`node --check`, scripts de stats y de integración). -4. Documentar hallazgos por severidad y marcar follow-up tasks para gaps no triviales. - -## Files to Read First - -- `ai/task-template.md` -- `ai/tasks/done/TASK-175-add-stats-regression-validation-script.md` -- `ai/tasks/done/TASK-176-add-stats-player-comparison-cards.md` -- `ai/tasks/done/TASK-177-harden-annual-ranking-snapshot-operations.md` -- `frontend/stats.html` -- `frontend/assets/js/stats.js` - -## Expected Files to Modify - -- `ai/tasks/pending/TASK-178-review-stats-implementation-after-hardening.md` - -## Scope - -Revisar técnicamente los siguientes archivos: - -- `frontend/stats.html` -- `frontend/assets/js/stats.js` -- `frontend/assets/css/styles.css` -- `backend/app/rcon_historical_player_stats.py` -- `backend/app/rcon_annual_rankings.py` -- `backend/app/payloads.py` -- `backend/app/routes.py` -- `scripts/run-stats-validation.ps1` -- `scripts/run-integration-tests.ps1` -- `docs/stats-section-functional-plan.md` -- `docs/annual-ranking-snapshot-runbook.md` - -La revisión debe cubrir explícitamente: - -1. Consistencia entre contratos documentados y payloads reales. -2. Confirmación de que Stats no depende de Elo/MMR. -3. Confirmación de que no se reintroduce Comunidad Hispana #03. -4. Validación del manejo frontend para: - - backend offline - - búsqueda sin resultados - - jugador sin stats - - ranking anual missing - - ranking anual ready vacío - - métrica inválida -5. Revisión de fetch semanal + mensual en paralelo y análisis de fallo parcial. -6. Revisión de documentación y validación de los nuevos metadatos `requested_limit`, `effective_limit`, `snapshot_limit`, `item_count`. -7. Revisión de fragilidad de `scripts/run-stats-validation.ps1` por comparaciones de strings exactos. -8. Ejecutar validaciones técnicas: - - `node --check frontend/assets/js/stats.js` - - `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` - - `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -9. Documentar hallazgos, clasificarlos y, si hay gaps no triviales, crear tareas de seguimiento en vez de ampliar esta task. - -## Constraints - -- No implementar nuevas funcionalidades. -- No modificar backend salvo bug menor evidente y estrictamente necesario para permitir una revisión correcta. -- No modificar frontend salvo bug menor evidente y estrictamente necesario. -- No crear migraciones. -- No cambiar lógica de ranking. -- No reactivar Elo/MMR. -- No reintroducir Comunidad Hispana #03. - -## Validation - -- `node --check frontend/assets/js/stats.js` -- `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` - -Antes de completar, verificar: - -- alcance evaluado solo en los archivos de esta task; -- hallazgos priorizados por severidad; -- `git diff --name-only` debe incluir únicamente este archivo de task. -- no se ejecuta ningún cambio de código fuera del objetivo de revisión. - -## Outcome - -## Outcome - -- Hallazgos de calidad funcional y consistencia: - 1. [SEVERIDAD BAJA] Documentación funcional (`docs/stats-section-functional-plan.md`) incluye `timeframe=weekly|monthly|all` en la sección de perfil jugador, pero el contrato real expuesto en `backend/app/routes.py` acepta solo `weekly|monthly` (`/api/stats/players/{id}?timeframe=`). Esto limita la superficie a lo realmente probado. - 2. [SEVERIDAD BAJA] El flujo de perfil en `frontend/assets/js/stats.js` consulta semanal y mensual en paralelo con `Promise.all`. Si una de esas dos peticiones falla (timeout o error puntual), se marca el backend offline y se pierde información parcial del otro periodo. Se recomienda separación con `Promise.allSettled` para degradación parcial. -- Validación de consistencia de contratos vs payloads: - - `frontend/assets/js/stats.js` consume exactamente los contratos actuales definidos en `backend/app/payloads.py`: - - búsqueda en `build_stats_player_search_payload` (`/api/stats/players/search`) con `data.query`, `data.server_id`, `data.items` - - perfil en `build_stats_player_profile_payload` (`/api/stats/players/{id}`) con `data.matches_considered`, `weekly_ranking`, `monthly_ranking`, metadatos de `source` - - ranking anual en `build_annual_ranking_snapshot_payload` (`/api/stats/rankings/annual`) con `snapshot_status`, `requested_limit`, `effective_limit`, `snapshot_limit`, `item_count` - - Los nuevos metadatos de snapshot (`requested_limit`, `effective_limit`, `snapshot_limit`, `item_count`) están documentados en `docs/annual-ranking-snapshot-runbook.md` y aparecen en los payloads. -- Restricciones de producto verificadas: - - No hay dependencia de Elo/MMR en el bloque Stats revisado (endpoints de Elo/MMR son rutas separadas en `routes.py`). - - No se detectó reintroducción de `Comunidad Hispana #03` en `frontend/stats.html`, `frontend/assets/js/stats.js`, `docs/stats-section-functional-plan.md`, `docs/annual-ranking-snapshot-runbook.md` ni en los endpoints de Stats revisados. - - El manejo de estados solicitados en frontend se encuentra cubierto: - - backend offline -> mensajes de estado y estado de paneles configurados en `markAsBackendUnavailable` - - búsqueda sin resultados -> `search_empty` con "Sin resultados" - - jugador sin stats -> aviso `profileNoStats` con bloque de identidad/counters en 0 - - ranking anual `missing` -> `annualMissing` - - ranking anual `ready` pero vacío -> `annualReadyEmpty` - - métrica inválida anual -> `annualMetricInvalid` -- Fragilidad de validación script: - - `scripts/run-stats-validation.ps1` usa múltiples `Assert-Contains` con cadenas exactas para comprobar assets/endpoints/mensajes. - - Es útil como regresión, pero es sensible a cambios de copy/UI no funcionales; recomendado considerar validación semántica adicional (`toLowerCase`, patrones de forma/falla HTTP) en un follow-up. -- Evidencia de validaciones ejecutadas: - - `node --check frontend/assets/js/stats.js` - - `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` - - `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- Riesgos/acciones: - - No se observan bloqueos funcionales críticos en el estado actual. - - Riesgo residual de degradación parcial del perfil semanal/mensual por fallo parcial en cargas paralelas. - -Tareas de seguimiento: -1. Alinear `docs/stats-section-functional-plan.md` con el contrato real de `timeframe` (o ampliar explícitamente ruta para aceptar `all`) como decisión de producto. -2. Implementar degradación parcial en carga de perfil (semana/mensual) para no degradar ambas tablas por un fallo aislado. -3. Endurecer `scripts/run-stats-validation.ps1` para validar semántica de estados además de string-matches exactos. diff --git a/ai/tasks/done/TASK-179-fix-stats-review-followups.md b/ai/tasks/done/TASK-179-fix-stats-review-followups.md deleted file mode 100644 index c4c0beb..0000000 --- a/ai/tasks/done/TASK-179-fix-stats-review-followups.md +++ /dev/null @@ -1,116 +0,0 @@ ---- -id: TASK-179 -title: Fix Stats Review Follow-ups -status: done -type: documentation -team: Analista -supporting_teams: - - Frontend Senior - - Backend Senior - - PM -roadmap_item: foundation -priority: medium ---- - -# TASK-179 - Fix Stats Review Follow-ups - -## Goal - -Resolver los hallazgos no bloqueantes detectados en TASK-178 sobre el bloque Stats después del hardening. - -## Context - -Tras la revisión de TASK-178 quedaron pendientes 3 correcciones de consistencia y resiliencia: -- documentación desincronizada en `timeframe`, -- fallo total de perfil al fallar en paralelo una ventana semanal/mensual, -- validación de regresión demasiado dependiente de texto literal en UI. - -El objetivo es cerrar estos puntos sin ampliar el alcance funcional del bloque Stats ni de ranking. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `ai/tasks/done/TASK-178-review-stats-implementation-after-hardening.md` -- `docs/stats-section-functional-plan.md` -- `frontend/stats.html` -- `frontend/assets/js/stats.js` -- `scripts/run-stats-validation.ps1` -- `scripts/run-integration-tests.ps1` -- `backend/app/routes.py` - -## Steps - -1. Leer los archivos listados arriba. -2. Corregir únicamente los cambios de alcance identificados: - - actualizar documentación para reflejar `timeframe=weekly|monthly`, - - tolerar fallo parcial entre `weekly` y `monthly` en el frontend, - - endurecer el script de validación para no depender de textos literales cuando no sea necesario. -3. Ejecutar validaciones: - - `node --check frontend/assets/js/stats.js` - - `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` - - `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` - - Servidor HTTP local para validar HTTP 200 de `stats.html` y `assets/js/stats.js`. -4. Documentar resultado en el apartado Outcome y cerrar la task. - -## Expected Files to Modify - -- `docs/stats-section-functional-plan.md` -- `frontend/assets/js/stats.js` -- `scripts/run-stats-validation.ps1` -- `ai/tasks/done/TASK-179-fix-stats-review-followups.md` - -## Constraints - -- Corregir sin agregar nuevas funcionalidades. -- No cambiar la lógica de ranking. -- No introducir o reactivar Elo/MMR. -- No reintroducir `Comunidad Hispana #03`. -- No crear migraciones. -- No modificar backend salvo bug menor estrictamente necesario. -- Mantener estilos y comportamiento existente salvo el mensaje mínimo necesario para fallo parcial. -- No ampliar la sección Stats con nuevas funcionalidades. - -## Validation - -- `node --check frontend/assets/js/stats.js` -- `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- Servir frontend y confirmar HTTP 200 para `stats.html` y `assets/js/stats.js`. -- `git diff --name-only` y verificación de scope. - -## Outcome - -- Cambios aplicados: - - `docs/stats-section-functional-plan.md`: - - Se actualizó la especificación de `timeframe` en - `/api/stats/players/{player_id}` a `weekly|monthly`. - - Se explicitó que `timeframe=all` no está soportado en el contrato actual. - - `frontend/assets/js/stats.js`: - - Se reemplazó `Promise.all` por `Promise.allSettled` para carga semanal/mensual. - - Se añadio render parcial para escenarios de éxito parcial por ventana. - - Se mantiene fallback de error total si ambas ventanas fallan. - - `scripts/run-stats-validation.ps1`: - - Se reforzaron validaciones de IDs, endpoints y shape de payload. - - Se quitaron chequeos frágiles dependientes de texto visible de UI. - - Se añadieron verificaciones para `requested_limit`, `effective_limit`, `snapshot_limit` y `item_count`. -- Modo de fallo parcial semanal/mensual: - - Si una ventana responde y la otra falla: - - se muestran sus datos y estado disponible. - - la otra muestra aviso de bloque no disponible y se evita degradar todo el panel. - - se agrega aviso global de carga parcial. - - Si ambas fallan: - - se conserva el estado de error completo y backend-inusable para ese perfil. -- Validaciones endurecidas: - - Validación de contrato en JS y HTML basada en funciones/rutas/IDs. - - Validación de forma de payload y metadatos de snapshot en bloque anual. -- Validaciones ejecutadas: - - `node --check frontend/assets/js/stats.js` - - `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` - - `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` - - `python -m http.server` (servido desde `frontend/`) con `HTTP 200` para: - - `stats.html` - - `assets/js/stats.js` -- Limitaciones o follow-ups: - - No se identificaron follow-ups de producto inmediatos dentro del alcance de TASK-179. diff --git a/ai/tasks/done/TASK-180-define-global-ranking-page-contract.md b/ai/tasks/done/TASK-180-define-global-ranking-page-contract.md deleted file mode 100644 index 40e936b..0000000 --- a/ai/tasks/done/TASK-180-define-global-ranking-page-contract.md +++ /dev/null @@ -1,111 +0,0 @@ ---- -id: TASK-180-define-global-ranking-page-contract -title: Define global ranking page contract -status: done -type: documentation -team: Analista -supporting_teams: - - PM - - Backend Senior - - Frontend Senior - - Experto en interfaz -roadmap_item: foundation -priority: high ---- - -# TASK-180-define-global-ranking-page-contract - Define global ranking page contract - -## Goal - -Define a separate, explicit global ranking page contract that is clearly distinct from Stats, so product and engineering can execute backend and frontend ranking work independently. - -## Context - -Stats focuses on one player workflow (search and personal performance), while Ranking exposes public top lists. This task formalizes the Ranking contract, filters, payload shape and UI states needed for an incremental, RCON-first implementation. - -## Steps - -1. Read the listed files first. -2. Draft a concise, implementation-ready contract for Ranking. -3. Document how Ranking and Stats are separated and where they can share frontend patterns safely. -4. Define API expectations for weekly/monthly vs annual reads, including missing/ready/error behavior. -5. Keep constraints explicit. -6. Capture follow-up items and a clear next-task suggestion. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `docs/stats-section-functional-plan.md` -- `docs/annual-ranking-snapshot-runbook.md` -- `backend/app/rcon_historical_leaderboards.py` -- `backend/app/rcon_annual_rankings.py` -- `frontend/stats.html` -- `frontend/assets/js/stats.js` - -## Expected Files to Modify - -- `docs/global-ranking-page-plan.md` -- `ai/tasks/done/TASK-180-define-global-ranking-page-contract.md` - -## Constraints - -- Documentation-only task. -- No backend implementation changes. -- No frontend implementation changes. -- No migrations or schema modifications. -- Keep the contract aligned with RCON-first architecture. -- No Elo/MMR reactivation. -- No reintroduction of Comunidad Hispana #03. -- No public-scoreboard as primary source when RCON coverage is available. - -## Validation - -- Confirm `docs/global-ranking-page-plan.md` exists. -- Confirm no backend/frontend files were modified. -- Run `git diff --name-only` within task scope. -- Document explicitly that no automated tests apply. - -## Outcome - -- Created `docs/global-ranking-page-plan.md`. -- Documented a dedicated `Ranking` page contract separate from `Stats`. -- Defined dedicated endpoint direction as `GET /api/ranking`. -- Documented timeframe behavior: - - weekly/monthly from RCON materialized leaderboard reads - - annual from persisted annual snapshots -- Documented required payload fields: - - `ranking_position` - - `player_id` - - `player_name` - - `metric_value` - - `matches_considered` - - `kills` - - `deaths` - - `teamkills` - - `kd_ratio` - - `window_start` - - `window_end` - - `snapshot_status` -- Documented required UI states: - - loading - - backend offline - - no data - - annual snapshot missing - - unsupported metric - - controlled error -- Explicitly preserved constraints: - - no Elo/MMR - - no Comunidad Hispana #03 - - no public-scoreboard primary path while RCON exists - -Validation performed: - -- Confirmed documentation file creation. -- Kept changes out of `backend/` and `frontend/`. -- Automated tests do not apply to this documentation-only task. - -Recommended next task: - -- `TASK-181-add-global-ranking-backend-support` diff --git a/ai/tasks/done/TASK-181-add-global-ranking-backend-support.md b/ai/tasks/done/TASK-181-add-global-ranking-backend-support.md deleted file mode 100644 index 2568ebb..0000000 --- a/ai/tasks/done/TASK-181-add-global-ranking-backend-support.md +++ /dev/null @@ -1,110 +0,0 @@ ---- -id: TASK-181-add-global-ranking-backend-support -title: Add global ranking backend support -status: done -type: backend -team: Backend Senior -supporting_teams: - - Arquitecto Python - - Arquitecto de Base de Datos -roadmap_item: foundation -priority: high ---- - -# TASK-181-add-global-ranking-backend-support - Add global ranking backend support - -## Goal - -Implement backend API support for the new global ranking page using existing RCON historical leaderboard logic and annual snapshot readers, without changing public Stats endpoints. - -## Context - -The backend now exposes a dedicated global ranking route that supports weekly, monthly and annual modes with V1 metric scope limited to `kills`. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `docs/global-ranking-page-plan.md` -- `docs/stats-section-functional-plan.md` -- `docs/annual-ranking-snapshot-runbook.md` -- `backend/app/routes.py` -- `backend/app/payloads.py` -- `backend/app/rcon_historical_leaderboards.py` -- `backend/app/rcon_annual_rankings.py` -- `scripts/run-stats-validation.ps1` -- `scripts/run-integration-tests.ps1` - -## Expected Files to Modify - -- `backend/app/routes.py` -- `backend/app/payloads.py` -- `scripts/run-stats-validation.ps1` -- `ai/tasks/done/TASK-181-add-global-ranking-backend-support.md` - -## Constraints Verified - -- No new architecture was introduced. -- No migrations were added. -- Annual ranking remains snapshot-backed and is not recalculated per request. -- Stats endpoints were left compatible. -- Comunidad Hispana #03 was not exposed through the new route. -- Public scoreboard was not introduced as a primary ranking source. - -## Outcome - -- Added `GET /api/ranking`. -- Added route validation for: - - `timeframe` - - `metric` - - `limit` - - `server_id` - - required `year` when `timeframe=annual` -- Reused existing readers: - - weekly/monthly from materialized RCON leaderboard reads - - annual from annual snapshot storage -- Normalized the dedicated ranking response with: - - `page_kind` - - `timeframe` - - `server_id` - - `metric` - - `limit` - - `requested_limit` - - `effective_limit` - - `window_start` - - `window_end` - - `snapshot_status` - - `source` - - `items` -- Updated regression validation to cover the new route and its invalid-input cases. - -## Validation - -Executed: - -- `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- Direct local route checks through `resolve_get_payload(...)` for: - - weekly `metric=kills` - - monthly `metric=kills` - - annual `metric=kills` - - annual missing `year` - -Observed: - -- Weekly route returned `200`. -- Monthly route returned `200`. -- Annual route returned `200`. -- Annual route without `year` returned `400`. -- Unsupported metric returned `400`. -- Unsupported timeframe returned `400`. -- High invalid limit returned `400`. - -Known limitation: - -- Live HTTP verification against a running backend at `http://127.0.0.1:8000` was not available during validation; route-contract checks passed through local Python imports and the integration script reported that explicitly. - -## Recommended Next Task - -- `TASK-182-add-global-ranking-frontend-page` diff --git a/ai/tasks/done/TASK-182-add-global-ranking-frontend-page.md b/ai/tasks/done/TASK-182-add-global-ranking-frontend-page.md deleted file mode 100644 index 7480e8b..0000000 --- a/ai/tasks/done/TASK-182-add-global-ranking-frontend-page.md +++ /dev/null @@ -1,99 +0,0 @@ ---- -id: TASK-182-add-global-ranking-frontend-page -title: Add global ranking frontend page -status: done -type: frontend -team: Frontend Senior -supporting_teams: - - Experto en interfaz - - Disenador grafico - - Backend Senior -roadmap_item: foundation -priority: high ---- - -# TASK-182-add-global-ranking-frontend-page - Add global ranking frontend page - -## Goal - -Create a dedicated Ranking page that displays public top lists by timeframe, server, metric and limit, consuming the backend support built in TASK-181. - -## Context - -Ranking is now separated from Stats in both navigation and interaction model. Stats remains player-centric; Ranking is list-centric and links back to Stats only when a user wants individual lookup. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `docs/global-ranking-page-plan.md` -- `frontend/index.html` -- `frontend/historico.html` -- `frontend/stats.html` -- `frontend/assets/js/stats.js` -- `frontend/assets/css/styles.css` -- `backend/app/routes.py` -- `ai/tasks/done/TASK-181-add-global-ranking-backend-support.md` - -## Expected Files Modified - -- `frontend/ranking.html` -- `frontend/assets/js/ranking.js` -- `frontend/assets/css/styles.css` -- `frontend/index.html` -- `ai/tasks/done/TASK-182-add-global-ranking-frontend-page.md` - -## Constraints Verified - -- No backend files were changed in this task. -- No new endpoints were added. -- No database changes were made. -- No Elo/MMR reactivation. -- No Comunidad Hispana #03 reintroduction. -- Stats behavior was left intact. -- Implementation stayed in vanilla HTML/CSS/JS. - -## Outcome - -- Added `frontend/ranking.html` as a dedicated Ranking page. -- Added `frontend/assets/js/ranking.js` to: - - check backend health - - request `/api/ranking` - - switch between weekly, monthly and annual flows - - render loading, offline, no-data, annual-missing and controlled-error states -- Extended shared styling in `frontend/assets/css/styles.css` for: - - ranking filter layout - - ranking metadata cards - - ranking table - - ranking empty state -- Added a minimal `Ranking` entry point in `frontend/index.html`. -- Kept cross-linking minimal by linking from Ranking to Stats without modifying `stats.html`. - -## Validation - -Executed: - -- `node --check frontend/assets/js/ranking.js` -- `node --check frontend/assets/js/stats.js` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- Local static serving with `python -m http.server` - -HTTP checks: - -- `ranking.html` -> `200` -- `assets/js/ranking.js` -> `200` -- `stats.html` -> `200` - -Offline-state check: - -- Backend was unavailable at `http://127.0.0.1:8000`. -- A headless Edge DOM capture of `ranking.html` showed `#ranking-backend-state` rendered as `Backend no disponible`, confirming the intended offline fallback path. - -Known limitation: - -- Live successful ranking calls could not be verified through a running backend during this task because the backend was not available over HTTP in the environment. - -## Recommended Follow-up - -- Add a dedicated ranking frontend regression script so `ranking.html` state coverage is validated alongside existing historical and stats checks. diff --git a/ai/tasks/done/TASK-183-review-global-ranking-implementation.md b/ai/tasks/done/TASK-183-review-global-ranking-implementation.md deleted file mode 100644 index 3f7a4ca..0000000 --- a/ai/tasks/done/TASK-183-review-global-ranking-implementation.md +++ /dev/null @@ -1,187 +0,0 @@ ---- -id: TASK-183-review-global-ranking-implementation -title: Review global ranking implementation -status: done -type: research -team: Analista -supporting_teams: - - PM - - Backend Senior - - Frontend Senior - - Arquitecto Python - - Experto en interfaz -roadmap_item: foundation -priority: high ---- - -# TASK-183-review-global-ranking-implementation - Review global ranking implementation - -## Goal - -Review the current technical implementation of the new `Ranking global` section after TASK-180, TASK-181 and TASK-182, and document whether the delivered backend/frontend behavior matches the approved contract without implementing new functionality. - -## Context - -`Ranking` was introduced as a dedicated public leaderboard flow separate from `Stats`. Before any follow-up changes, HLL Vietnam needs one focused technical review task that confirms the real route contract, the actual data sources, the frontend failure handling, the validation coverage and the navigation impact on the landing. - -Preserve the current product identity: Spanish-speaking HLL Vietnam community, military/Vietnam/tactical/sober visual direction and controlled repository evolution. - -## Steps - -1. Read the listed files first. -2. Compare `docs/global-ranking-page-plan.md` against the implemented backend/frontend behavior. -3. Verify the real global ranking endpoint contract: - - exact route - - supported parameters - - supported timeframes - - supported metric - - normalized limit behavior -4. Confirm weekly and monthly ranking reads use the RCON materialized read model. -5. Confirm annual ranking reads use persisted annual snapshots and do not recalculate on each public request. -6. Verify Elo/MMR is not required by this flow and that Comunidad Hispana #03 was not reintroduced. -7. Review frontend handling for: - - backend offline - - no data - - annual snapshot missing - - unsupported metric - - unsupported timeframe - - invalid limit -8. Review whether `frontend/assets/js/ranking.js` duplicates logic from `frontend/assets/js/stats.js` in a risky way or only reuses patterns safely. -9. Review whether `scripts/run-stats-validation.ps1` covers `Ranking global` sufficiently or whether a future dedicated validation task is justified. -10. Confirm navigation from `frontend/index.html` to `frontend/ranking.html` does not break the landing flow. -11. Document findings, validation executed, open risks and any follow-up tasks instead of expanding scope. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `docs/global-ranking-page-plan.md` -- `frontend/ranking.html` -- `frontend/assets/js/ranking.js` -- `backend/app/routes.py` -- `backend/app/payloads.py` -- `scripts/run-stats-validation.ps1` - -## Expected Files to Modify - -- `ai/tasks/pending/TASK-183-review-global-ranking-implementation.md` - -## Constraints - -- Create findings only; do not implement fixes in this task. -- Do not execute product changes beyond the scoped technical review. -- Do not modify backend files. -- Do not modify frontend files. -- Do not modify docs outside the task outcome if a follow-up is needed. -- Do not create new features. -- Do not reactivate Elo/MMR. -- Do not reintroduce Comunidad Hispana #03. -- Keep the review aligned with the existing RCON-first architecture and the approved separation between `Stats` and `Ranking`. - -## Validation - -Before completing the task ensure: - -- the implementation was reviewed against `docs/global-ranking-page-plan.md` -- the real route contract for `GET /api/ranking` was documented from code, not assumed -- weekly/monthly vs annual source behavior was verified from implementation files -- frontend error-state handling was reviewed from `ranking.html` and `ranking.js` -- validation-script coverage was reviewed from `scripts/run-stats-validation.ps1` -- landing navigation impact was checked from `frontend/index.html` -- no unrelated files were modified -- `git diff --name-only` matches the expected scope -- if no integration tests apply beyond the existing validation script, that limitation is documented explicitly - -## Outcome - -Review result: - -- The real reviewed endpoint is `GET /api/ranking`. -- Supported parameters confirmed from `backend/app/routes.py`: - - `timeframe`: optional, defaults to `weekly`; allowed values `weekly`, `monthly`, `annual` - - `server_id`: optional, defaults effectively to `all`; accepted values for Ranking are `all`, `all-servers`, `comunidad-hispana-01`, `comunidad-hispana-02` - - `metric`: optional, defaults to `kills`; V1 only supports `kills` - - `limit`: optional, defaults to `20`; validated as `1..100` - - `year`: required only when `timeframe=annual` -- Weekly and monthly Ranking reads are confirmed to use the RCON materialized read model through `list_rcon_materialized_leaderboard(...)` in `backend/app/rcon_historical_leaderboards.py`. -- Annual Ranking is confirmed to use persisted annual snapshots through `get_annual_ranking_snapshot(...)` in `backend/app/rcon_annual_rankings.py`, and the public request path does not call `generate_annual_ranking_snapshot(...)`. -- No Elo/MMR dependency was found in the Ranking flow. Elo/MMR routes still exist elsewhere, but `GET /api/ranking`, `build_global_ranking_payload(...)` and `frontend/assets/js/ranking.js` do not rely on them. -- Comunidad Hispana #03 was not reintroduced: - - frontend server selector exposes only `all`, `comunidad-hispana-01`, `comunidad-hispana-02` - - backend Ranking validation rejects unsupported server ids -- Navigation added in `frontend/index.html` does not break the landing in the reviewed static flow; `index.html`, `ranking.html`, `stats.html` and `assets/js/ranking.js` were served locally with HTTP `200`. - -Consistency against `docs/global-ranking-page-plan.md`: - -- The implementation matches the main contract direction: - - dedicated `GET /api/ranking` - - weekly/monthly from RCON materialized leaderboard reads - - annual from snapshots - - V1 metric limited to `kills` - - no Elo/MMR - - no Comunidad Hispana #03 - - frontend handles offline, empty, annual missing and controlled errors -- The route contract is slightly broader than the documented plan because backend also accepts `server_id=all-servers` as an alias. -- The frontend implementation is slightly narrower than the broadest possible contract because the UI only exposes limit options `10`, `20` and `30`, even though backend accepts `1..100`. - -Frontend state review: - -- `backend offline`: explicitly handled in `refreshBackendHealth()` and in guarded calls when backend state is offline. -- `sin datos`: explicitly handled in `renderRanking(...)` when `items=[]`. -- `annual snapshot missing`: explicitly handled when `timeframe=annual` and `snapshot_status="missing"`. -- `metric no soportada`: explicitly handled on HTTP `400` with `metric` in the error message. -- `timeframe no soportado`: explicitly handled on HTTP `400` with `timeframe` in the error message. -- `limit invalido`: handled only through the generic controlled-error branch; there is no dedicated invalid-limit message in `ranking.js`. - -`ranking.js` versus `stats.js`: - -- There is duplication of helper patterns such as backend health checks, state setters, JSON-safe parsing, formatting and HTML escaping. -- The duplication is not currently dangerous because the flows are separated and the duplicated logic is simple. -- It is still a maintainability risk if future endpoint/error handling changes need to stay synchronized across both files. - -Validation coverage review: - -- `scripts/run-stats-validation.ps1` already covers the global Ranking route contract well enough for the current backend scope: - - weekly/monthly/annual happy paths - - unsupported metric - - unsupported timeframe - - invalid high limit - - annual missing year -- It does not directly validate frontend rendering states for `ranking.html`. -- A future dedicated Ranking frontend regression task is still advisable if UI-state coverage becomes important. - -Risks detected: - -- `ranking.js` does not provide a dedicated user-facing message for invalid `limit`; it falls back to the generic controlled-error state. -- Shared helper logic between `ranking.js` and `stats.js` may drift over time because it is duplicated rather than centralized. -- Live backend HTTP verification at `http://127.0.0.1:8000` was not available during validation, so successful HTTP checks for Ranking were confirmed through local route-contract execution instead of a running backend. - -Validation executed: - -- `node --check frontend/assets/js/ranking.js` -- `node --check frontend/assets/js/stats.js` -- `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- Local static serving with `python -m http.server` -- HTTP `200` confirmed for: - - `ranking.html` - - `assets/js/ranking.js` - - `index.html` - - `stats.html` - -Change scope: - -- No backend or frontend code changes were needed. -- This task completed as review/documentation only. - -Recommended follow-up tasks: - -- Add a dedicated Ranking frontend regression validation task covering offline, empty, annual-missing and controlled-error UI states. -- Evaluate whether shared frontend helpers between `stats.js` and `ranking.js` should be consolidated if more stateful pages are added. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-184-define-ranking-metric-expansion-contract.md b/ai/tasks/done/TASK-184-define-ranking-metric-expansion-contract.md deleted file mode 100644 index a384e56..0000000 --- a/ai/tasks/done/TASK-184-define-ranking-metric-expansion-contract.md +++ /dev/null @@ -1,177 +0,0 @@ ---- -id: TASK-184-define-ranking-metric-expansion-contract -title: Define ranking metric expansion contract -status: done -type: documentation -team: Analista -supporting_teams: - - PM - - Backend Senior - - Frontend Senior - - Arquitecto de Base de Datos - - Experto en interfaz -roadmap_item: foundation -priority: high ---- - -# TASK-184-define-ranking-metric-expansion-contract - Define ranking metric expansion contract - -## Goal - -Define the functional and technical contract for expanding `Ranking global` with additional metrics in V1.1 without reactivating Elo/MMR or introducing a new architecture. - -## Context - -The current Ranking implementation is limited to `kills`. The repository already has a dedicated Ranking route, an RCON materialized weekly/monthly read path, and an annual snapshot read path. Before backend or frontend expansion, HLL Vietnam needs explicit documentation that defines which extra metrics are safe, how they are calculated, what timeframes they support, and where annual support must remain constrained. - -Preserve the current product identity: Spanish-speaking HLL Vietnam community, military/Vietnam/tactical/sober visual direction and controlled repository evolution. - -## Steps - -1. Read the listed files first. -2. Update the Ranking contract documentation for V1.1 metric expansion only. -3. Define the supported metrics and the formula or aggregation rule for each one. -4. Define expected ordering for each metric and clarify tie-break behavior. -5. Define supported timeframes per metric: - - `weekly` - - `monthly` - - `annual` -6. Clarify the difference between weekly/monthly runtime reads and annual snapshot reads. -7. Clarify whether annual remains limited to `kills` or only allows additional metrics when a safe snapshot-backed read path already exists. -8. Define payload expectations and controlled error behavior for unsupported metrics. -9. Keep non-goals and source-policy restrictions explicit. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `docs/global-ranking-page-plan.md` -- `docs/stats-section-functional-plan.md` -- `docs/annual-ranking-snapshot-runbook.md` -- `backend/app/rcon_historical_leaderboards.py` -- `backend/app/rcon_annual_rankings.py` -- `backend/app/routes.py` -- `backend/app/payloads.py` -- `ai/tasks/done/TASK-183-review-global-ranking-implementation.md` - -## Expected Files to Modify - -- `docs/global-ranking-page-plan.md` -- `ai/tasks/done/TASK-184-define-ranking-metric-expansion-contract.md` - -## Constraints - -- Documentation-only task. -- Do not modify backend files. -- Do not modify frontend files. -- Do not create migrations. -- Do not change scripts. -- Do not reactivate Elo/MMR. -- Do not reintroduce Comunidad Hispana #03. -- Do not define public scoreboard as the normal primary source while RCON is available. -- Do not expand annual behavior into runtime full-year recalculation on public requests. - -## Validation - -Before completing the task ensure: - -- `docs/global-ranking-page-plan.md` explicitly documents V1.1 supported Ranking metrics -- the contract defines formulas for: - - `kills` - - `deaths` - - `teamkills` - - `matches_considered` - - `kd_ratio` - - `kills_per_match` -- the contract defines safe handling for: - - `deaths=0` - - `matches_considered=0` -- the contract defines expected ordering for each metric -- the contract defines timeframe support per metric and annual limitations explicitly -- unsupported-metric error behavior is documented -- non-goals remain explicit: - - Elo/MMR - - public scoreboard as primary source - - large new tables - - advanced charts - - authentication - - Comunidad Hispana #03 -- `git diff --name-only` stays within task scope -- if automated tests do not apply because the task is documentation-only, that limitation is documented in the task outcome - -## Outcome - -Supported Ranking V1.1 metrics documented in `docs/global-ranking-page-plan.md`: - -- `kills` -- `deaths` -- `teamkills` -- `matches_considered` -- `kd_ratio` -- `kills_per_match` - -Formula and aggregation rules documented: - -- `kills = SUM(kills)` -- `deaths = SUM(deaths)` -- `teamkills = SUM(teamkills)` -- `matches_considered = COUNT(DISTINCT match_key)` -- `kd_ratio = SUM(kills) / SUM(deaths)` -- `kills_per_match = SUM(kills) / COUNT(DISTINCT match_key)` - -Safety rules documented: - -- `deaths=0` returns finite display-safe `kd_ratio` using kills as the fallback value -- `matches_considered=0` returns `kills_per_match = 0` - -Ordering and tie-break expectations documented: - -- totals metrics sort by active metric desc, then stable tie-break fields -- `matches_considered` ties break on `kills` desc, then `player_name` asc -- ratio metrics tie-break on `kills` desc, `matches_considered` desc, `player_name` asc - -Supported timeframes by metric documented: - -- weekly: all V1.1 metrics through the materialized RCON runtime leaderboard -- monthly: all V1.1 metrics through the materialized RCON runtime leaderboard -- annual: snapshot-safe path only; `kills` required, extra metrics only if an explicit snapshot-backed read path exists - -Annual snapshot limitations and safety rules documented: - -- no runtime annual recomputation on public requests -- unsupported annual metrics must return controlled `400` -- until extra annual snapshots exist, annual remains effectively `kills`-only - -Expected payload adjustments documented: - -- `metric_value` remains the active display/sort field -- weekly/monthly payloads may include rounded ratio fields and `kills_per_match` -- annual payload shape remains stable and only expands when snapshot-backed safely - -Controlled error behavior documented: - -- unsupported metric, unsupported timeframe and unsupported annual metric must fail with controlled request-validation errors -- backend must not silently downgrade unsupported requests to `kills` - -Validation performed: - -- reviewed `docs/global-ranking-page-plan.md` -- reviewed `docs/stats-section-functional-plan.md` -- reviewed `docs/annual-ranking-snapshot-runbook.md` -- reviewed `backend/app/rcon_historical_leaderboards.py` -- reviewed `backend/app/rcon_annual_rankings.py` -- reviewed `backend/app/routes.py` -- reviewed `backend/app/payloads.py` -- reviewed `ai/tasks/done/TASK-183-review-global-ranking-implementation.md` -- confirmed `git diff --name-only` scope stays documentation-only for this task - -Automated tests: - -- No automated tests apply because this task remained documentation-only. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-185-add-ranking-extra-metrics-backend-support.md b/ai/tasks/done/TASK-185-add-ranking-extra-metrics-backend-support.md deleted file mode 100644 index 4478c70..0000000 --- a/ai/tasks/done/TASK-185-add-ranking-extra-metrics-backend-support.md +++ /dev/null @@ -1,179 +0,0 @@ ---- -id: TASK-185-add-ranking-extra-metrics-backend-support -title: Add ranking extra metrics backend support -status: done -type: backend -team: Backend Senior -supporting_teams: - - Arquitecto Python - - Arquitecto de Base de Datos -roadmap_item: foundation -priority: high ---- - -# TASK-185-add-ranking-extra-metrics-backend-support - Add ranking extra metrics backend support - -## Goal - -Add backend support for additional `Ranking global` metrics by reusing the existing RCON materialized read model, while preserving the current Ranking route and avoiding unsafe annual recomputation. - -## Context - -`TASK-183` confirmed that `GET /api/ranking` currently supports only `metric=kills`, with weekly/monthly reading from the RCON materialized leaderboard and annual reading from snapshots. The next backend step is to extend metric support safely for weekly/monthly and keep annual constrained to snapshot-safe behavior only. - -Preserve the current product identity: Spanish-speaking HLL Vietnam community, military/Vietnam/tactical/sober visual direction and controlled repository evolution. - -## Steps - -1. Read the listed files first. -2. Keep the public endpoint as: - - `GET /api/ranking?timeframe=weekly|monthly|annual&server_id=&metric=&limit=&year=` -3. Extend weekly/monthly support for: - - `kills` - - `deaths` - - `teamkills` - - `matches_considered` - - `kd_ratio` - - `kills_per_match` -4. Preserve `metric=kills` behavior and compatibility for existing Ranking requests. -5. Reuse the materialized RCON read model and avoid introducing a new ranking architecture. -6. Keep annual support safe: - - support `kills` - - only support additional annual metrics if they are snapshot-backed without public full-year recomputation - - otherwise return a controlled `400` for unsupported annual metrics -7. Update route validation and payload normalization only where necessary. -8. Extend validation coverage for the new metrics and failure cases. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `docs/global-ranking-page-plan.md` -- `backend/app/routes.py` -- `backend/app/payloads.py` -- `backend/app/rcon_historical_leaderboards.py` -- `backend/app/rcon_annual_rankings.py` -- `scripts/run-stats-validation.ps1` -- `scripts/run-integration-tests.ps1` -- `ai/tasks/done/TASK-183-review-global-ranking-implementation.md` -- `ai/tasks/done/TASK-184-define-ranking-metric-expansion-contract.md` - -## Expected Files to Modify - -- `backend/app/rcon_historical_leaderboards.py` -- `backend/app/routes.py` -- `backend/app/payloads.py` -- `backend/app/rcon_annual_rankings.py` -- `scripts/run-stats-validation.ps1` -- `ai/tasks/done/TASK-185-add-ranking-extra-metrics-backend-support.md` - -## Constraints - -- Do not create migrations. -- Do not introduce a new architecture. -- Do not recalculate the annual full-year ranking on public requests. -- Do not reactivate Elo/MMR. -- Do not reintroduce Comunidad Hispana #03. -- Do not use public scoreboard as the normal primary source. -- Do not modify frontend files. -- Do not break Stats endpoints. -- Do not break the existing Ranking route for `metric=kills`. - -## Validation - -Before completing the task ensure: - -- `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- validate `GET /api/ranking` for: - - `timeframe=weekly&metric=kills` - - `timeframe=weekly&metric=deaths` - - `timeframe=weekly&metric=teamkills` - - `timeframe=weekly&metric=matches_considered` - - `timeframe=weekly&metric=kd_ratio` - - `timeframe=weekly&metric=kills_per_match` - - `timeframe=monthly&metric=kd_ratio` - - `timeframe=monthly&metric=kills_per_match` - - `timeframe=annual&metric=kills` - - unsupported metric - - unsupported timeframe - - `limit=3` - - `limit=101` or invalid limit according to the current contract -- confirm annual behavior is still snapshot-safe -- confirm `git diff --name-only` stays within scope - -## Outcome - -Metrics added for `GET /api/ranking` weekly/monthly reads: - -- `kills` -- `deaths` -- `teamkills` -- `matches_considered` -- `kd_ratio` -- `kills_per_match` - -Backend formulas and ordering applied: - -- `kills = SUM(kills)` ordered by `kills` desc, `matches_considered` desc, `player_name` asc -- `deaths = SUM(deaths)` ordered by `deaths` desc, `matches_considered` desc, `player_name` asc -- `teamkills = SUM(teamkills)` ordered by `teamkills` desc, `matches_considered` desc, `player_name` asc -- `matches_considered = COUNT(DISTINCT match_key)` ordered by `matches_considered` desc, `kills` desc, `player_name` asc -- `kd_ratio = SUM(kills) / SUM(deaths)` with `deaths=0 -> kills`, ordered by `kd_ratio` desc, `kills` desc, `matches_considered` desc, `player_name` asc -- `kills_per_match = SUM(kills) / COUNT(DISTINCT match_key)` with `matches_considered=0 -> 0`, ordered by `kills_per_match` desc, `kills` desc, `matches_considered` desc, `player_name` asc - -Implementation summary: - -- `backend/app/rcon_historical_leaderboards.py` now supports the V1.1 ranking metrics while preserving the existing materialized RCON read model. -- `backend/app/routes.py` now validates the expanded public Ranking metric set without changing the endpoint shape. -- `backend/app/payloads.py` now preserves decimal `metric_value` when needed and exposes `kills_per_match` in normalized ranking items. -- `backend/app/rcon_annual_rankings.py` remains snapshot-safe and returns a controlled annual-specific `400` for unsupported annual metrics. -- `scripts/run-stats-validation.ps1` now covers the new happy paths and annual guardrail failures. - -Annual metric behavior and limitations: - -- annual remains snapshot-backed only -- `metric=kills` remains supported -- extra annual metrics currently return controlled `400` -- no runtime full-year recomputation was introduced - -Validations executed: - -- `python -m compileall backend/app/routes.py backend/app/payloads.py backend/app/rcon_historical_leaderboards.py backend/app/rcon_annual_rankings.py` -- `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` - -Validation notes: - -- live backend HTTP validation at `http://127.0.0.1:8000` was not available during execution -- route-contract validation still passed through local Python imports - -Scope notes: - -- task-owned modifications stayed within: - - `backend/app/rcon_historical_leaderboards.py` - - `backend/app/routes.py` - - `backend/app/payloads.py` - - `backend/app/rcon_annual_rankings.py` - - `scripts/run-stats-validation.ps1` -- `git diff --name-only` also showed pre-existing or previous-task changes outside this task: - - moved task files from `TASK-184` / `TASK-185` - - `docs/global-ranking-page-plan.md` from `TASK-184` - - unrelated existing workspace change `frontend/assets/img/weapons/black/gewehr_black.svg` -- those files were not modified as part of this backend task. - -Known limitations: - -- annual extra metrics are intentionally blocked until an explicit snapshot-backed implementation exists -- ranking item decimals are validated through route-contract checks, not through a running backend HTTP instance in this run - -Recommended next task: - -- expose the new metrics safely in the Ranking frontend UX. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-186-polish-ranking-metric-ux-and-limits.md b/ai/tasks/done/TASK-186-polish-ranking-metric-ux-and-limits.md deleted file mode 100644 index c09d5bf..0000000 --- a/ai/tasks/done/TASK-186-polish-ranking-metric-ux-and-limits.md +++ /dev/null @@ -1,191 +0,0 @@ ---- -id: TASK-186-polish-ranking-metric-ux-and-limits -title: Polish ranking metric UX and limits -status: done -type: frontend -team: Frontend Senior -supporting_teams: - - Experto en interfaz - - Disenador grafico - - Backend Senior -roadmap_item: foundation -priority: high ---- - -# TASK-186-polish-ranking-metric-ux-and-limits - Polish ranking metric UX and limits - -## Goal - -Update the `Ranking` page UX so it exposes the backend-supported metric set clearly, improves limit handling and error messaging, and preserves the separation between global tops and player-specific Stats. - -## Context - -The current Ranking UI is limited to `kills`, only exposes a small set of limits, and handles invalid `limit` through a generic error path. If backend metric expansion is delivered, the frontend must expose the new metric set safely, keep annual constraints clear, and improve the explanatory UX without changing backend architecture. - -Preserve the current product identity: Spanish-speaking HLL Vietnam community, military/Vietnam/tactical/sober visual direction and controlled repository evolution. - -## Steps - -1. Read the listed files first. -2. Update `ranking.html`, `ranking.js` and styling only as needed to expose the supported Ranking metric set. -3. Allow selecting: - - `kills` - - `deaths` - - `teamkills` - - `matches_considered` - - `kd_ratio` - - `kills_per_match` -4. Make the UI clearly show: - - the active metric - - the active timeframe - - the active server -5. If annual remains `kills`-only, hide, disable or clearly message unsupported annual metrics without breaking the flow. -6. Improve limit UX so the available UI limits are reasonable and aligned with backend constraints. -7. Add a clearer message for invalid `limit` if it arrives from manual URL or parameter manipulation. -8. Keep or improve the message for unsupported metric and unsupported timeframe. -9. Preserve the guidance that `Stats` is for one-player lookup and `Ranking` is for global tops. -10. Add only minimal cross-linking between `Ranking` and `Stats` if helpful and already aligned with existing page patterns. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `docs/global-ranking-page-plan.md` -- `frontend/ranking.html` -- `frontend/assets/js/ranking.js` -- `frontend/assets/css/styles.css` -- `frontend/stats.html` -- `frontend/assets/js/stats.js` -- `backend/app/routes.py` -- `ai/tasks/done/TASK-185-add-ranking-extra-metrics-backend-support.md` - -## Expected Files to Modify - -- `frontend/ranking.html` -- `frontend/assets/js/ranking.js` -- `frontend/assets/css/styles.css` -- `frontend/stats.html` -- `scripts/run-stats-validation.ps1` -- `ai/tasks/done/TASK-186-polish-ranking-metric-ux-and-limits.md` - -## Constraints - -- Do not modify backend files. -- Do not create endpoints. -- Do not modify the database. -- Do not reactivate Elo/MMR. -- Do not reintroduce Comunidad Hispana #03. -- Do not introduce frameworks. -- Keep HTML/CSS/JS vanilla. -- Maintain the military/Vietnam/tactical/sober visual identity. -- Do not break Stats. -- Do not duplicate complex logic unnecessarily. - -## Validation - -Before completing the task ensure: - -- `node --check frontend/assets/js/ranking.js` -- `node --check frontend/assets/js/stats.js` -- `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- serve frontend with `python -m http.server` and confirm HTTP `200` for: - - `ranking.html` - - `assets/js/ranking.js` - - `stats.html` - - `index.html` -- if local backend is available, validate real metric selection against the supported backend contract -- if backend is unavailable, validate the offline fallback path explicitly -- confirm `git diff --name-only` stays within scope - -## Outcome - -Metrics exposed in Ranking UI: - -- `kills` -- `deaths` -- `teamkills` -- `matches_considered` -- `kd_ratio` -- `kills_per_match` - -Frontend UX changes delivered: - -- `frontend/ranking.html` now exposes the expanded metric selector and wider limit options. -- the ranking table now highlights the active metric dynamically while still showing the core supporting stats (`kills`, `deaths`, `teamkills`, `matches_considered`, `kd_ratio`, `kills_per_match`) -- the metadata strip now shows the active timeframe, active server, active metric, limit, window and source more explicitly -- `frontend/assets/js/ranking.js` now restores filter state from URL parameters and keeps the URL synced as filters change -- `frontend/stats.html` now includes a minimal direct link back to `Ranking` - -Annual behavior in the UX: - -- annual keeps `kills` as the only selectable active metric -- when the user switches to annual, non-snapshot-safe metrics are disabled in the selector -- the page shows an explicit note that annual remains `kills`-only until additional safe snapshots exist -- annual unsupported-metric and missing-snapshot states remain clearly differentiated - -UI limit choices: - -- `Top 5` -- `Top 10` -- `Top 20` -- `Top 50` -- `Top 100` - -Error and state coverage improved: - -- dedicated invalid-limit message for manual URL or parameter manipulation -- dedicated annual kills-only warning -- preserved unsupported metric message -- preserved unsupported timeframe message -- preserved backend offline fallback path -- preserved annual snapshot missing state -- preserved empty-ready states - -Validation updates: - -- `scripts/run-stats-validation.ps1` now asserts the new Ranking metric options, annual kills-only guidance, URL-state handling and the Stats-to-Ranking link - -Validations executed: - -- `node --check frontend/assets/js/ranking.js` -- `node --check frontend/assets/js/stats.js` -- `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- temporary static serving with `python -m http.server 8081` -- confirmed HTTP `200` for: - - `ranking.html` - - `assets/js/ranking.js` - - `stats.html` - - `index.html` - -Validation notes: - -- local backend HTTP validation at `http://127.0.0.1:8000` was unavailable during the run -- offline fallback behavior was therefore validated through the existing frontend logic plus route-contract checks from the shared validation script - -Scope notes: - -- task-owned frontend changes stayed within: - - `frontend/ranking.html` - - `frontend/assets/js/ranking.js` - - `frontend/assets/css/styles.css` - - `frontend/stats.html` - - `scripts/run-stats-validation.ps1` -- `git diff --name-only` also shows previous-task backend/docs changes and an unrelated existing workspace change: - - moved task files from `TASK-184` / `TASK-185` / `TASK-186` - - `backend/app/*` and `docs/global-ranking-page-plan.md` from prior tasks in this run - - `frontend/assets/img/weapons/black/gewehr_black.svg` -- those files were not modified as part of this frontend task. - -Recommended follow-ups: - -- if a live backend session becomes available, run an explicit browser-side validation pass for every supported metric against real responses -- if annual extra metrics are introduced later, keep the current UX branch but switch from disabled options to active snapshot-backed support only when backend snapshots exist. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-187-review-ranking-metric-expansion.md b/ai/tasks/done/TASK-187-review-ranking-metric-expansion.md deleted file mode 100644 index dc324b5..0000000 --- a/ai/tasks/done/TASK-187-review-ranking-metric-expansion.md +++ /dev/null @@ -1,162 +0,0 @@ ---- -id: TASK-187-review-ranking-metric-expansion -title: Review ranking metric expansion -status: done -type: research -team: Analista -supporting_teams: - - Backend Senior - - Frontend Senior -roadmap_item: foundation -priority: medium ---- - -# TASK-187-review-ranking-metric-expansion - Review ranking metric expansion - -## Goal - -Review the implemented `Ranking global` metric expansion from `TASK-184`, `TASK-185` and `TASK-186` without adding new functionality. - -## Context - -The repository already shipped documentation, backend and frontend changes for expanded global ranking metrics. HLL Vietnam now needs a short post-implementation review to confirm that the documented contract, backend behavior, frontend behavior and validation coverage remain aligned before any further follow-up work. - -Preserve the current product identity: Spanish-speaking HLL Vietnam community, military/Vietnam/tactical/sober visual direction and controlled repository evolution. - -## Steps - -1. Read the listed files first. -2. Review the documented and implemented ranking metric expansion without broadening scope. -3. Run the listed validations and document the result. -4. Record only review findings, confirmed behavior and follow-up notes if needed. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `docs/global-ranking-page-plan.md` -- `frontend/ranking.html` -- `frontend/assets/js/ranking.js` -- `frontend/assets/css/styles.css` -- `backend/app/routes.py` -- `backend/app/payloads.py` -- `backend/app/rcon_historical_leaderboards.py` -- `backend/app/rcon_annual_rankings.py` -- `scripts/run-stats-validation.ps1` -- `ai/tasks/done/TASK-184-define-ranking-metric-expansion-contract.md` -- `ai/tasks/done/TASK-185-add-ranking-extra-metrics-backend-support.md` -- `ai/tasks/done/TASK-186-polish-ranking-metric-ux-and-limits.md` - -## Expected Files to Modify - -- `ai/tasks/done/TASK-187-review-ranking-metric-expansion.md` - -## Constraints - -- No añadir nuevas métricas. -- No cambiar diseño. -- No crear endpoints. -- No modificar base de datos. -- No cambiar lógica salvo bug menor evidente. -- Si hay hallazgos no triviales, documentarlos como follow-up y no ampliar scope. -- No incluir archivos fuera del scope de revisión. - -## Validation - -Before completing the task ensure: - -- review `docs/global-ranking-page-plan.md` against implemented ranking behavior -- confirm weekly/monthly/annual metric support and annual safety boundaries -- confirm unsupported `metric`, unsupported `timeframe` and invalid `limit` still return controlled errors -- confirm the frontend metric selector, decimal handling, annual limitation messaging and fallback states still align with backend behavior -- confirm `scripts/run-stats-validation.ps1` covers the expanded ranking metrics without breaking Stats validation -- run: - - `node --check frontend/assets/js/ranking.js` - - `node --check frontend/assets/js/stats.js` - - `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` - - `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- if the environment allows it, probe: - - `/api/ranking?timeframe=weekly&metric=kills&limit=3` - - `/api/ranking?timeframe=weekly&metric=deaths&limit=3` - - `/api/ranking?timeframe=weekly&metric=teamkills&limit=3` - - `/api/ranking?timeframe=weekly&metric=matches_considered&limit=3` - - `/api/ranking?timeframe=weekly&metric=kd_ratio&limit=3` - - `/api/ranking?timeframe=weekly&metric=kills_per_match&limit=3` - - `/api/ranking?timeframe=monthly&metric=kd_ratio&limit=3` - - `/api/ranking?timeframe=annual&metric=kills&limit=3` - - `/api/ranking?timeframe=annual&metric=kd_ratio&limit=3` - - `/api/ranking?timeframe=invalid&metric=kills&limit=3` - - `/api/ranking?timeframe=weekly&metric=invalid&limit=3` - - `/api/ranking?timeframe=weekly&metric=kills&limit=101` -- `git diff --name-only` stays within review scope - -## Outcome - -Review result: - -- No blocking findings were identified for the implemented ranking metric expansion scope. -- `docs/global-ranking-page-plan.md` matches the implemented metric set and annual safety boundary. -- The implemented public metric set is confirmed as: - - weekly: `kills`, `deaths`, `teamkills`, `matches_considered`, `kd_ratio`, `kills_per_match` - - monthly: `kills`, `deaths`, `teamkills`, `matches_considered`, `kd_ratio`, `kills_per_match` - - annual: `kills` only through snapshot-backed reads -- Annual requests remain snapshot-only and do not trigger runtime full-year recomputation in the public request path. -- Unsupported `metric`, unsupported `timeframe` and invalid `limit` continue to return controlled `400` responses. - -Frontend review: - -- `frontend/ranking.html` exposes the supported metric selector options. -- `frontend/assets/js/ranking.js` formats integer metrics through integer rendering and decimal metrics through fixed decimal rendering. -- Annual non-supported metrics are disabled in the selector and explicitly explained in the filter note and error state. -- The limit selector remains aligned with backend constraints through `5`, `10`, `20`, `50`, `100`, all within the backend `1..100` contract. -- Offline, controlled-error, empty-ready and annual-missing states remain explicitly handled. - -Validation coverage review: - -- `scripts/run-stats-validation.ps1` covers the expanded Ranking metrics, annual guardrail failures, invalid metric/timeframe/limit checks and existing Stats contracts. -- Existing Stats validation remains intact and passed during this review. - -Route-resolution probes executed: - -- `200`: - - `/api/ranking?timeframe=weekly&metric=kills&limit=3` - - `/api/ranking?timeframe=weekly&metric=deaths&limit=3` - - `/api/ranking?timeframe=weekly&metric=teamkills&limit=3` - - `/api/ranking?timeframe=weekly&metric=matches_considered&limit=3` - - `/api/ranking?timeframe=weekly&metric=kd_ratio&limit=3` - - `/api/ranking?timeframe=weekly&metric=kills_per_match&limit=3` - - `/api/ranking?timeframe=monthly&metric=kd_ratio&limit=3` - - `/api/ranking?timeframe=annual&metric=kills&limit=3&year=2026` -- `400`: - - `/api/ranking?timeframe=annual&metric=kd_ratio&limit=3&year=2026` - - `/api/ranking?timeframe=invalid&metric=kills&limit=3` - - `/api/ranking?timeframe=weekly&metric=invalid&limit=3` - - `/api/ranking?timeframe=weekly&metric=kills&limit=101` - -Validations executed: - -- `node --check frontend/assets/js/ranking.js` -- `node --check frontend/assets/js/stats.js` -- `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` - -Validation notes: - -- Live backend HTTP validation at `http://127.0.0.1:8000` was not available during this review. -- Route and contract checks passed through local Python imports, so the remaining residual risk is limited to live-environment verification rather than contract drift. - -Scope notes: - -- The review remained scoped to the task file plus repository inspection and validation commands. -- No product code changes were made. - -Follow-up: - -- Optional future follow-up only if needed: rerun the same ranking probes against a live backend session to confirm HTTP behavior matches the local route-resolution checks. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-188-audit-ranking-and-stats-query-performance.md b/ai/tasks/done/TASK-188-audit-ranking-and-stats-query-performance.md deleted file mode 100644 index 88fa550..0000000 --- a/ai/tasks/done/TASK-188-audit-ranking-and-stats-query-performance.md +++ /dev/null @@ -1,108 +0,0 @@ ---- -id: TASK-188-audit-ranking-and-stats-query-performance -title: Audit ranking and stats query performance -status: done -type: research -team: Arquitecto de Base de Datos -supporting_teams: - - Backend Senior - - Arquitecto Python -roadmap_item: foundation -priority: high ---- - -# TASK-188 - Audit ranking and stats query performance - -## Goal - -Measure and document the real performance of the public Ranking and Stats endpoints before applying any optimization. - -## Context - -`/api/ranking` weekly/monthly currently reads runtime aggregates over materialized RCON/AdminLog tables, while annual ranking already uses snapshots. `Stats` search and player detail also depend on runtime reads over the same materialized domain. HLL Vietnam needs a concrete baseline for latency, query shape, table size and execution plan so follow-up work can target the real bottlenecks instead of guessing. - -Preserve the current product identity: Spanish-speaking HLL Vietnam community, military/Vietnam/tactical/sober visual direction and controlled repository evolution. - -## Steps - -1. Read the listed files first. -2. Identify the exact queries and tables used by the target endpoints. -3. Measure request time and, if possible, approximate SQL time for each target endpoint. -4. Inspect relevant row counts, current indexes and execution plans when the engine allows it. -5. Document the slowest endpoint and provide a concrete index/snapshot recommendation without changing runtime code. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `backend/app/routes.py` -- `backend/app/rcon_historical_leaderboards.py` -- `backend/app/rcon_historical_player_stats.py` -- `backend/app/rcon_annual_rankings.py` -- `docs/global-ranking-page-plan.md` -- `scripts/run-stats-validation.ps1` - -## Expected Files to Modify - -- `docs/ranking-stats-performance-audit.md` -- `ai/tasks/done/TASK-188-audit-ranking-and-stats-query-performance.md` - -## Constraints - -- No modificar lógica de backend. -- No modificar frontend. -- No crear migraciones. -- No crear índices todavía. -- No cambiar APIs. -- No reactivar Elo/MMR. -- No reintroducir Comunidad Hispana #03. -- Mantener el trabajo limitado a medición y documentación. - -## Validation - -Before completing the task ensure: - -- the audit covers: - - `/api/ranking` weekly `kills` - - `/api/ranking` weekly `kd_ratio` - - `/api/ranking` monthly `kills_per_match` - - `/api/ranking` annual `kills` - - `/api/stats/players/search` - - `/api/stats/players/{player_id}` -- the document records: - - total request time - - approximate SQL time if measurable - - row counts for relevant tables - - existing indexes - - current query shapes - - execution plan if available - - slowest endpoint - - concrete recommendation for indexes and/or snapshots -- executed commands are documented -- inability to obtain `EXPLAIN` is documented if the environment blocks it -- `git diff --name-only` stays within scope - -## Outcome - -- Audit completed in `docs/ranking-stats-performance-audit.md`. -- Measured baseline captured for the six required endpoint probes. -- Environment limitation documented: backend HTTP server was not running locally, so request timing used in-process route resolution and SQL tracing over SQLite. -- Current runtime weekly/monthly ranking windows on `2026-06-09` are empty because the latest materialized `admin-log-match-ended` data ends on `2026-05-20T23:21:45.816Z`. -- Slowest measured endpoint is `/api/stats/players/{player_id}` because it issues 16 SQL statements, including repeated window counts and two ranking-position subqueries. -- Primary future performance risks identified: - - full scans on `rcon_materialized_matches` for `source_basis + time-window` filters - - a full scan on `rcon_match_player_stats` for player-detail-by-`player_id` - - temp B-trees for grouping, `COUNT(DISTINCT)` and ordering in leaderboard/search queries -- Follow-up recommendation for `TASK-189`: - - add time-window indexes on `rcon_materialized_matches` - - add a direct `player_id` index on `rcon_match_player_stats` - - keep annual snapshot indexes as-is -- Follow-up recommendation for `TASK-190`: - - move weekly/monthly public ranking to snapshot-backed reads with controlled runtime fallback - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-189-add-ranking-materialized-read-indexes.md b/ai/tasks/done/TASK-189-add-ranking-materialized-read-indexes.md deleted file mode 100644 index d3e12f5..0000000 --- a/ai/tasks/done/TASK-189-add-ranking-materialized-read-indexes.md +++ /dev/null @@ -1,106 +0,0 @@ ---- -id: TASK-189-add-ranking-materialized-read-indexes -title: Add ranking materialized read indexes -status: done -type: backend -team: Arquitecto de Base de Datos -supporting_teams: - - Backend Senior -roadmap_item: foundation -priority: high ---- - -# TASK-189 - Add ranking materialized read indexes - -## Goal - -Add safe indexes on the materialized tables used by Ranking and Stats to reduce scans and improve join performance. - -## Context - -The current Ranking and Stats runtime reads depend on `rcon_materialized_matches`, `rcon_match_player_stats` and annual snapshot tables. After `TASK-188` documents the real bottlenecks, HLL Vietnam needs a narrow indexing pass that improves read performance without changing API contracts, recalculating rankings or introducing a second architecture. - -Preserve the current product identity: Spanish-speaking HLL Vietnam community, military/Vietnam/tactical/sober visual direction and controlled repository evolution. - -## Steps - -1. Read the listed files first. -2. Use `docs/ranking-stats-performance-audit.md` as the primary justification source. -3. Add only the indexes supported by the audit findings and the existing storage initialization/migration pattern. -4. Keep SQLite/Postgres compatibility if both storage modes are supported in the current backend. -5. Re-run the validation scripts and, if possible, compare before/after timing for one or two representative endpoints. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `docs/ranking-stats-performance-audit.md` -- `backend/app/rcon_admin_log_materialization.py` -- `backend/app/rcon_historical_leaderboards.py` -- `backend/app/rcon_historical_player_stats.py` -- `backend/app/rcon_annual_rankings.py` -- `backend/app/postgres_rcon_storage.py` -- `backend/app/sqlite_utils.py` - -## Expected Files to Modify - -- `backend` storage/migration/init module correspondiente, según patrón existente -- `docs/ranking-stats-performance-audit.md`, solo si se documenta índice aplicado -- `ai/tasks/done/TASK-189-add-ranking-materialized-read-indexes.md` - -## Constraints - -- No cambiar contratos API. -- No cambiar frontend. -- No recalcular rankings. -- No crear snapshots en esta task. -- No reactivar Elo/MMR. -- No reintroducir Comunidad Hispana #03. -- Mantener compatibilidad SQLite/Postgres si el proyecto usa ambos. -- Basar los índices en evidencia documentada por `TASK-188`, no en suposiciones. - -## Validation - -Before completing the task ensure: - -- the chosen indexes are justified by `TASK-188` -- candidate coverage explicitly considers: - - `target_key + match_key` - - `source_basis + ended_at/started_at` - - `target_key + ended_at/started_at` - - `player_id` - - `player_name` if search benefits from it - - `snapshot_id + ranking_position` in snapshot tables if applicable -- `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- if possible, before/after timing is captured for one or two endpoints -- any measurement limitations are documented -- `git diff --name-only` stays within scope - -## Outcome - -- Added SQLite/PostgreSQL-compatible indexes in the materialized storage initialization path: - - `idx_rcon_materialized_matches_source_window_text` - - `idx_rcon_materialized_matches_target_source_window_text` - - `idx_rcon_materialized_matches_external_source_window_text` - - `idx_rcon_match_player_stats_player_id_match` -- Kept existing annual snapshot indexes unchanged because the annual read path was already using matching indexes. -- Did not add a plain `player_name` B-tree because the current search query uses `LOWER(player_name) LIKE '%term%'` with a leading wildcard, so the audit did not justify it as a useful narrow index. -- Post-index validation confirmed plan improvement: - - weekly count queries now use the new `source_basis + window` covering index - - the stats player-detail aggregate now narrows through the match window index and then probes stats by `(target_key, match_key, player_id)` -- Before/after timing was captured for representative endpoints: - - `/api/stats/players/{player_id}` weekly improved from `8.924 ms / 4.494 ms SQL` to `4.300 ms / 1.043 ms SQL` - - `/api/ranking` weekly `kills` showed no meaningful change in this dataset because the active weekly window on `2026-06-09` is empty -- Validation scripts executed successfully: - - `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` - - `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- Remaining gap: - - weekly/monthly public ranking still does repeated runtime counting and grouped aggregation per request, so snapshot-backed reads remain necessary in `TASK-190` and `TASK-191` - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-190-design-weekly-monthly-ranking-snapshots.md b/ai/tasks/done/TASK-190-design-weekly-monthly-ranking-snapshots.md deleted file mode 100644 index d6b3230..0000000 --- a/ai/tasks/done/TASK-190-design-weekly-monthly-ranking-snapshots.md +++ /dev/null @@ -1,134 +0,0 @@ ---- -id: TASK-190-design-weekly-monthly-ranking-snapshots -title: Design weekly monthly ranking snapshots -status: done -type: documentation -team: Arquitecto de Base de Datos -supporting_teams: - - Backend Senior - - PM -roadmap_item: foundation -priority: high ---- - -# TASK-190 - Design weekly monthly ranking snapshots - -## Goal - -Design a weekly/monthly ranking snapshot read model, equivalent in philosophy to the annual snapshot model, so public ranking requests do not depend on expensive runtime aggregation. - -## Context - -Annual ranking already follows a snapshot-backed read path, but weekly/monthly public ranking still depends on runtime aggregation over materialized match stats. HLL Vietnam needs a documented snapshot model for weekly and monthly ranking windows that preserves the current RCON-first policy, keeps annual behavior intact and defines a controlled fallback strategy during transition. - -Preserve the current product identity: Spanish-speaking HLL Vietnam community, military/Vietnam/tactical/sober visual direction and controlled repository evolution. - -## Steps - -1. Read the listed files first. -2. Use the performance audit and the annual snapshot runbook as reference points. -3. Define the proposed tables, keys, metadata and item payload needed for weekly/monthly ranking snapshots. -4. Define refresh cadence and lifecycle rules for current and closed windows. -5. Define the public fallback policy without reintroducing heavy recomputation on every request. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `docs/ranking-stats-performance-audit.md` -- `docs/global-ranking-page-plan.md` -- `docs/annual-ranking-snapshot-runbook.md` -- `backend/app/rcon_historical_leaderboards.py` -- `backend/app/rcon_annual_rankings.py` - -## Expected Files to Modify - -- `docs/ranking-snapshot-read-model-plan.md` -- `ai/tasks/done/TASK-190-design-weekly-monthly-ranking-snapshots.md` - -## Constraints - -- Documentación-only. -- No modificar backend. -- No modificar frontend. -- No crear migraciones. -- No implementar snapshots todavía. -- No reactivar Elo/MMR. -- No reintroducir Comunidad Hispana #03. -- Mantener el diseño alineado con Python backend y con el snapshot anual existente. - -## Validation - -Before completing the task ensure: - -- the plan defines `ranking_snapshots` -- the plan defines `ranking_snapshot_items` -- the model covers: - - `timeframe` weekly/monthly/annual - - `server_id` - - `metric` - - `window_start` and `window_end` - - `generated_at` - - `source` - - `snapshot_status` - - `item_count` - - `limit_size` - - `ranking_position` - - `player_id` - - `player_name` - - `metric_value` - - `matches_considered` - - `kills` - - `deaths` - - `teamkills` - - `kd_ratio` - - `kills_per_match` -- the refresh policy is explicit: - - weekly current every 5-15 minutes - - monthly current every 15-30 minutes - - previous week/month closed and stable - - annual manual or daily -- the fallback policy is explicit: - - serve snapshot if present - - return controlled missing or use runtime fallback only by configuration if missing - - never recalculate by default on every public request -- the plan names impacted endpoints and expected response metadata -- `git diff --name-only` stays within scope - -## Outcome - -- Snapshot design documented in `docs/ranking-snapshot-read-model-plan.md`. -- Proposed read model uses: - - `ranking_snapshots` - - `ranking_snapshot_items` -- The plan explicitly covers: - - `timeframe` weekly/monthly/annual - - `server_id` - - `metric` - - `window_start` - - `window_end` - - `generated_at` - - `source` - - `snapshot_status` - - `item_count` - - `limit_size` - - per-item ranking and player fields -- Refresh policy defined: - - weekly current every `5` to `15` minutes - - monthly current every `15` to `30` minutes - - previous week/month stable once closed - - annual manual or daily -- Fallback policy defined: - - serve snapshot when `ready` - - return controlled `missing` or use runtime fallback only by configuration when snapshot is absent - - never recalculate by default on every public request -- Transition notes prepared for `TASK-191`: - - weekly/monthly snapshot-first read path - - annual remains on the existing annual snapshot implementation until a dedicated migration task consolidates storage - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-191-serve-ranking-from-snapshots-with-runtime-fallback.md b/ai/tasks/done/TASK-191-serve-ranking-from-snapshots-with-runtime-fallback.md deleted file mode 100644 index a112dcd..0000000 --- a/ai/tasks/done/TASK-191-serve-ranking-from-snapshots-with-runtime-fallback.md +++ /dev/null @@ -1,136 +0,0 @@ ---- -id: TASK-191-serve-ranking-from-snapshots-with-runtime-fallback -title: Serve ranking from snapshots with runtime fallback -status: done -type: backend -team: Backend Senior -supporting_teams: - - Arquitecto de Base de Datos - - Arquitecto Python -roadmap_item: foundation -priority: high ---- - -# TASK-191 - Serve ranking from snapshots with runtime fallback - -## Goal - -Implement the `/api/ranking` read path so weekly and monthly ranking are served from snapshots when available, with a controlled runtime fallback only when configured and only when the snapshot is missing. - -## Context - -Public Ranking requests currently pay the cost of runtime aggregation for weekly and monthly windows, while annual ranking already reads from snapshots. After `TASK-190` defines the snapshot read model, HLL Vietnam needs the public ranking endpoint to prefer snapshot-backed reads, preserve annual snapshot behavior and expose enough metadata for frontend and operations to understand source, freshness and fallback usage. - -Preserve the current product identity: Spanish-speaking HLL Vietnam community, military/Vietnam/tactical/sober visual direction and controlled repository evolution. - -## Steps - -1. Read the listed files first. -2. Implement weekly/monthly snapshot lookup according to `docs/ranking-snapshot-read-model-plan.md`. -3. Keep annual requests on the existing annual snapshot path. -4. Add controlled runtime fallback only for missing weekly/monthly snapshots when configuration allows it. -5. Expose response metadata needed to distinguish snapshot-ready, snapshot-missing and runtime-fallback responses. -6. Validate weekly, monthly, annual and invalid-request behavior. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `docs/ranking-snapshot-read-model-plan.md` -- `backend/app/routes.py` -- `backend/app/payloads.py` -- `backend/app/rcon_historical_leaderboards.py` -- `backend/app/rcon_annual_rankings.py` -- `scripts/run-stats-validation.ps1` - -## Expected Files to Modify - -- `backend/app/rcon_historical_leaderboards.py` -- `backend/app/routes.py` -- `backend/app/payloads.py` -- `scripts/run-stats-validation.ps1` -- `docs/ranking-snapshot-read-model-plan.md`, solo si se documenta comportamiento final -- `ai/tasks/done/TASK-191-serve-ranking-from-snapshots-with-runtime-fallback.md` - -## Constraints - -- No cambiar frontend salvo que sea imprescindible y esté documentado. -- No crear nuevas features visuales. -- No reactivar Elo/MMR. -- No reintroducir Comunidad Hispana #03. -- No usar scoreboard público como fuente primaria. -- No recalcular rankings pesados si snapshot `ready` existe. -- Mantener fallback runtime controlado para transición. -- La task depende del diseño de `TASK-190`. - -## Validation - -Before completing the task ensure: - -- `/api/ranking` weekly/monthly: - - attempts snapshot read first - - returns snapshot when status is `ready` - - uses runtime materialized fallback only when snapshot is missing and fallback is allowed - - returns controlled missing when snapshot is missing and fallback is not allowed -- `/api/ranking` annual keeps current snapshot behavior -- response metadata includes: - - `source` - - `snapshot_status` - - `generated_at` - - `freshness` - - `fallback_used` - - `window_start` - - `window_end` -- run: - - `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` - - `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- probe: - - `/api/ranking` weekly - - `/api/ranking` monthly - - `/api/ranking` annual - - snapshot-missing behavior - - invalid `metric` - - invalid `timeframe` - - invalid `limit` -- confirm annual still works -- document if snapshots are not yet generated automatically -- `git diff --name-only` stays within scope - -## Outcome - -- Implemented weekly/monthly `/api/ranking` as snapshot-first: - - snapshot `ready` rows are served from `ranking_snapshots` + `ranking_snapshot_items` - - annual requests remain on the existing annual snapshot path -- Added controlled runtime fallback behavior: - - fallback is used only when the weekly/monthly snapshot is missing - - fallback is controlled by `HLL_BACKEND_RANKING_RUNTIME_FALLBACK_ENABLED` - - default remains enabled for transition - - setting the variable to `false` returns controlled `snapshot_status='missing'` with empty items -- Response metadata now distinguishes: - - snapshot-ready - - snapshot-missing - - runtime-fallback -- Metadata exposed on ranking responses now includes: - - `source` - - `snapshot_status` - - `generated_at` - - `freshness` - - `fallback_used` - - `window_start` - - `window_end` -- Validation completed: - - `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` - - `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- Validation script now proves: - - normal route-contract behavior - - snapshot-ready behavior using temporary fixture rows - - snapshot-missing behavior with runtime fallback disabled -- Remaining operational dependency: - - snapshot tables now exist on first access, but snapshot rows are not generated automatically yet; a future generator/job still needs to populate weekly/monthly snapshots for production use - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-192-fix-postgres-ranking-snapshot-schema.md b/ai/tasks/done/TASK-192-fix-postgres-ranking-snapshot-schema.md deleted file mode 100644 index cbff736..0000000 --- a/ai/tasks/done/TASK-192-fix-postgres-ranking-snapshot-schema.md +++ /dev/null @@ -1,126 +0,0 @@ ---- -id: TASK-192-fix-postgres-ranking-snapshot-schema -title: Fix PostgreSQL ranking snapshot schema -status: done -type: backend -team: Backend Senior -supporting_teams: - - Arquitecto de Base de Datos - - Arquitecto Python -roadmap_item: foundation -priority: high ---- - -# TASK-192 - Fix PostgreSQL ranking snapshot schema - -## Goal - -Apply a backend hotfix so weekly and monthly ranking snapshot storage initializes correctly in PostgreSQL without executing SQLite-only schema syntax. - -## Context - -Production `GET /api/ranking?timeframe=weekly&metric=kills&limit=20` currently fails because `backend/app/rcon_historical_leaderboards.py` executes SQLite DDL with `AUTOINCREMENT` through `psycopg`. HLL Vietnam operational storage must stay in PostgreSQL, including ranking snapshots, and this fix must preserve the current annual snapshot path and avoid any SQLite expansion for this functionality. - -Preserve the current product identity: Spanish-speaking HLL Vietnam community, military/Vietnam/tactical/sober visual direction and controlled repository evolution. - -## Steps - -1. Inspect the listed files first. -2. Create the PostgreSQL-compatible ranking snapshot schema following the existing backend storage pattern. -3. Keep annual snapshot storage intact and scoped to `rcon_annual_ranking_snapshots`. -4. Validate the backend path and document the root cause, fix and production verification steps. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `backend/app/rcon_historical_leaderboards.py` -- `backend/app/postgres_rcon_storage.py` -- `backend/app/rcon_admin_log_materialization.py` -- `backend/app/rcon_annual_rankings.py` -- `backend/app/payloads.py` -- `backend/app/routes.py` -- `scripts/run-stats-validation.ps1` -- `ai/tasks/done/TASK-191-serve-ranking-from-snapshots-with-runtime-fallback.md` - -## Expected Files to Modify - -- `backend/app/rcon_historical_leaderboards.py` -- `backend/app/postgres_rcon_storage.py`, solo si el patrón del proyecto lo requiere -- `scripts/run-stats-validation.ps1`, solo si se añade validación de regresión -- `ai/tasks/done/TASK-192-fix-postgres-ranking-snapshot-schema.md` - -## Constraints - -- Keep the change minimal. -- Preserve HLL Vietnam project identity. -- Do not introduce unnecessary frameworks or dependencies. -- Do not create or depend on a separate SQLite database for ranking snapshots. -- Do not expand legacy SQLite compatibility routes for this functionality beyond what already exists. -- Do not modify frontend, visual logic, Elo/MMR or Comunidad Hispana #03 handling. -- Keep annual ranking on `rcon_annual_ranking_snapshots`. -- Do not overwrite repository-specific context with generic platform template text. - -## Validation - -Before completing the task ensure: - -- `node --check frontend/assets/js/ranking.js` -- `node --check frontend/assets/js/stats.js` -- `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- local validation proves `initialize_ranking_snapshot_storage` does not contain or execute `AUTOINCREMENT` on the PostgreSQL path -- local validation proves PostgreSQL schema defines `ranking_snapshots` and `ranking_snapshot_items` with PostgreSQL-compatible syntax -- `/api/ranking?timeframe=weekly&metric=kills&limit=20` no longer fails because of table creation -- `/api/ranking?timeframe=annual&metric=kills&limit=20&year=2026` keeps working -- `git diff --name-only` matches the expected scope - -If local PostgreSQL is unavailable, document that in Outcome and validate by code inspection plus existing scripts. - -## Outcome - -- Root cause: - - `backend/app/rcon_historical_leaderboards.py` defined `ranking_snapshots` / `ranking_snapshot_items` with SQLite syntax and executed that same DDL through `psycopg` on the PostgreSQL path. - - Production failure matched the SQLite-only token exactly: `AUTOINCREMENT`. -- Confirmation: - - The failing path was `build_global_ranking_payload` -> `get_latest_ranking_snapshot` -> `initialize_ranking_snapshot_storage`. - - The hotfix removes PostgreSQL execution of the SQLite snapshot DDL and routes PostgreSQL initialization through the central PostgreSQL schema initializer. -- Applied change: - - Kept the SQLite snapshot schema local to the SQLite path in `backend/app/rcon_historical_leaderboards.py`. - - Added PostgreSQL-compatible `ranking_snapshots` and `ranking_snapshot_items` tables plus indexes to `backend/app/postgres_rcon_storage.py`. - - Used `BIGSERIAL` primary keys and PostgreSQL-compatible `BIGINT`, `DOUBLE PRECISION`, `TIMESTAMPTZ`, foreign keys and index syntax. - - Added regression validation in `scripts/run-stats-validation.ps1` to prove the PostgreSQL path does not depend on `AUTOINCREMENT` and that it delegates to `initialize_postgres_rcon_storage`. -- Expected PostgreSQL tables: - - `ranking_snapshots` - - `ranking_snapshot_items` - - Annual ranking remains on: - - `rcon_annual_ranking_snapshots` - - `rcon_annual_ranking_snapshot_items` -- Validations executed: - - `node --check frontend/assets/js/ranking.js` - - `node --check frontend/assets/js/stats.js` - - `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` - - `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` - - Local regression validation now proves: - - PostgreSQL schema text contains `ranking_snapshots` and `ranking_snapshot_items` - - PostgreSQL schema text does not contain `AUTOINCREMENT` - - `initialize_ranking_snapshot_storage()` delegates to PostgreSQL schema initialization on the PostgreSQL path - - `/api/ranking?timeframe=annual&year=2026&server_id=all&metric=kills&limit=20` still resolves -- Environment note: - - Local backend HTTP at `http://127.0.0.1:8000` was not available during validation. - - Validation therefore completed by local Python imports, route resolution and existing scripts, which passed. -- How to validate in production: - - Deploy the backend hotfix. - - Confirm PostgreSQL contains `ranking_snapshots` and `ranking_snapshot_items`. - - Request: - - `/api/ranking?timeframe=weekly&metric=kills&limit=20` - - `/api/ranking?timeframe=monthly&metric=kills&limit=20` - - `/api/ranking?timeframe=annual&metric=kills&limit=20&year=2026` - - Verify weekly/monthly no longer fail during table initialization and annual remains unchanged. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-193-fix-postgres-ranking-derived-metrics.md b/ai/tasks/done/TASK-193-fix-postgres-ranking-derived-metrics.md deleted file mode 100644 index f251e14..0000000 --- a/ai/tasks/done/TASK-193-fix-postgres-ranking-derived-metrics.md +++ /dev/null @@ -1,126 +0,0 @@ ---- -id: TASK-193-fix-postgres-ranking-derived-metrics -title: Fix PostgreSQL ranking derived metrics -status: done -type: backend -team: Backend Senior -supporting_teams: - - Arquitecto Python - - Arquitecto de Base de Datos -roadmap_item: foundation -priority: high ---- - -# TASK-193 - Fix PostgreSQL ranking derived metrics - -## Goal - -Apply a backend hotfix so `kd_ratio` and `kills_per_match` work correctly on PostgreSQL when `/api/ranking` falls back to the runtime materialized leaderboard path. - -## Context - -Production weekly/monthly ranking snapshots are currently missing, so `/api/ranking` falls back to runtime aggregation. In that fallback path, the shared SQL uses `ROUND(double precision, integer)`, which is accepted by SQLite patterns but fails in PostgreSQL and breaks derived metrics while base metrics like `kills`, `deaths`, `teamkills` and `matches_considered` should remain operational. - -Preserve the current product identity: Spanish-speaking HLL Vietnam community, military/Vietnam/tactical/sober visual direction and controlled repository evolution. - -## Steps - -1. Read the listed files first. -2. Apply only the scoped backend hotfix for derived ranking metrics. -3. Validate the result and document the root cause, fix and operational follow-up. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `backend/app/rcon_historical_leaderboards.py` -- `backend/app/postgres_rcon_storage.py` -- `backend/app/payloads.py` -- `backend/app/routes.py` -- `scripts/run-stats-validation.ps1` -- `ai/tasks/done/TASK-185-add-ranking-extra-metrics-backend-support.md` -- `ai/tasks/done/TASK-191-serve-ranking-from-snapshots-with-runtime-fallback.md` -- `ai/tasks/done/TASK-192-fix-postgres-ranking-snapshot-schema.md` - -## Expected Files to Modify - -- `backend/app/rcon_historical_leaderboards.py` -- `scripts/run-stats-validation.ps1`, only if a regression check is needed -- `ai/tasks/done/TASK-193-fix-postgres-ranking-derived-metrics.md` - -## Constraints - -- Keep the change minimal. -- Do not create new features. -- Do not modify frontend, images, assets or design. -- Do not reactivate Elo/MMR. -- Do not reintroduce Comunidad Hispana #03. -- Avoid `ROUND(double precision, integer)` on PostgreSQL. -- Prefer safe numeric casting or Python-side rounding while preserving SQLite compatibility if it already exists. -- Keep public contracts unchanged unless strictly necessary. -- Preserve `kills`, `deaths`, `teamkills` and `matches_considered` behavior. - -## Validation - -Before completing the task ensure: - -- `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- validate: - - `/api/ranking?timeframe=weekly&metric=kd_ratio&limit=20` - - `/api/ranking?timeframe=monthly&metric=kills_per_match&limit=20` - - `/api/ranking?timeframe=weekly&metric=kills&limit=20` - - `/api/ranking?timeframe=weekly&metric=deaths&limit=20` - - `/api/ranking?timeframe=weekly&metric=matches_considered&limit=20` -- confirm the missing weekly/monthly snapshots explain latency but not the `kd_ratio` / `kills_per_match` PostgreSQL error -- `git diff --name-only` matches the expected scope - -## Outcome - -- Root cause: - - `backend/app/rcon_historical_leaderboards.py` built shared SQL for `kd_ratio` and `kills_per_match` with `ROUND(..., 2)` over `REAL`-cast arithmetic. - - That pattern works on the SQLite path but fails on PostgreSQL fallback reads because PostgreSQL does not define `round(double precision, integer)`. - - The failure path matches production: `build_global_ranking_payload` -> `list_rcon_materialized_leaderboard` -> `_fetch_leaderboard_rows`. -- Applied change: - - Replaced SQLite-oriented `REAL` casts in derived metric SQL with `NUMERIC` casts before division and rounding. - - Kept the same public ranking route and preserved base metrics: - - `kills` - - `deaths` - - `teamkills` - - `matches_considered` - - Kept Python-side item normalization unchanged so response contracts remain stable. - - Added regression checks in `scripts/run-stats-validation.ps1` to assert derived metric SQL no longer uses `AS REAL` and now uses `AS NUMERIC`. -- Validations executed: - - `python -m compileall backend/app/rcon_historical_leaderboards.py backend/app/payloads.py backend/app/routes.py` - - `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` - - `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` - - local route-resolution probes for: - - `/api/ranking?timeframe=weekly&metric=kd_ratio&limit=20` - - `/api/ranking?timeframe=monthly&metric=kills_per_match&limit=20` - - `/api/ranking?timeframe=weekly&metric=kills&limit=20` - - `/api/ranking?timeframe=weekly&metric=deaths&limit=20` - - `/api/ranking?timeframe=weekly&metric=matches_considered&limit=20` -- Validation results: - - All requested ranking probes resolved with HTTP 200 via local route imports. - - In this environment they returned `snapshot_status=missing` and `fallback_used=true`, which is consistent with missing weekly/monthly snapshots. - - No backend HTTP service was available at `http://127.0.0.1:8000`, so endpoint validation completed through local imports and repository scripts. -- Operational confirmation: - - Missing weekly/monthly snapshots explain the slower runtime fallback path. - - Missing snapshots do not explain the `kd_ratio` / `kills_per_match` crash; that error came from PostgreSQL-incompatible rounding SQL in the runtime fallback query. -- Scope review: - - Task-owned changes: - - `backend/app/rcon_historical_leaderboards.py` - - `scripts/run-stats-validation.ps1` - - `ai/tasks/done/TASK-193-fix-postgres-ranking-derived-metrics.md` - - `git diff --name-only` also showed a pre-existing unrelated modification: - - `ai/system-metrics.md` - - Existing untracked frontend assets were left untouched. -- Recommended next step: - - generate and maintain weekly/monthly ranking snapshots so `/api/ranking` stops paying the runtime fallback cost in production - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-194-add-weekly-monthly-ranking-snapshot-generator.md b/ai/tasks/done/TASK-194-add-weekly-monthly-ranking-snapshot-generator.md deleted file mode 100644 index 45ffe7d..0000000 --- a/ai/tasks/done/TASK-194-add-weekly-monthly-ranking-snapshot-generator.md +++ /dev/null @@ -1,149 +0,0 @@ ---- -id: TASK-194-add-weekly-monthly-ranking-snapshot-generator -title: Add weekly monthly ranking snapshot generator -status: done -type: backend -team: Backend Senior -supporting_teams: - - Arquitecto de Base de Datos - - Arquitecto Python -roadmap_item: foundation -priority: high ---- - -# TASK-194 - Add weekly monthly ranking snapshot generator - -## Goal - -Implement a manual weekly/monthly ranking snapshot generator plus CLI so PostgreSQL-backed `/api/ranking` can serve persisted global ranking snapshots instead of runtime fallback when operators generate the required combinations. - -## Context - -`TASK-191` introduced the snapshot-first read path for weekly/monthly global ranking, and `TASK-192` / `TASK-193` stabilized the PostgreSQL path and runtime fallback metrics. The missing piece is still out-of-band generation for `ranking_snapshots` and `ranking_snapshot_items`, so production ranking requests continue to return `snapshot_status=missing`, `freshness=runtime` and `fallback_used=true`. - -Preserve the current product identity: Spanish-speaking HLL Vietnam community, military/Vietnam/tactical/sober visual direction and controlled repository evolution. - -## Steps - -1. Read the listed files first. -2. Add a manual generator for weekly/monthly ranking snapshots using the existing materialized RCON leaderboard logic and snapshot tables. -3. Expose a CLI command for one explicit combination; only add matrix generation if it remains small and justified. -4. Validate generated snapshot reads, preserved runtime fallback behavior and production-oriented run commands. -5. Document the manual generation workflow and recommended combinations. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `backend/app/rcon_historical_leaderboards.py` -- `backend/app/rcon_annual_rankings.py` -- `backend/app/routes.py` -- `backend/app/payloads.py` -- `backend/app/postgres_rcon_storage.py` -- `scripts/run-stats-validation.ps1` -- `docs/ranking-snapshot-read-model-plan.md` -- `docs/ranking-stats-performance-audit.md` -- `ai/tasks/done/TASK-191-serve-ranking-from-snapshots-with-runtime-fallback.md` -- `ai/tasks/done/TASK-192-fix-postgres-ranking-snapshot-schema.md` -- `ai/tasks/done/TASK-193-fix-postgres-ranking-derived-metrics.md` - -## Expected Files to Modify - -- `backend/app/rcon_historical_leaderboards.py` -- `scripts/run-stats-validation.ps1` -- `docs/ranking-snapshot-read-model-plan.md` -- `ai/tasks/done/TASK-194-add-weekly-monthly-ranking-snapshot-generator.md` - -## Constraints - -- Keep the change minimal. -- Do not modify frontend, assets or design. -- Do not reactivate Elo/MMR. -- Do not reintroduce Comunidad Hispana #03. -- Keep annual ranking behavior unchanged unless a helper can be safely shared without changing annual contracts. -- Prefer the existing module pattern already used by `backend/app/rcon_annual_rankings.py`. -- Do not change `/api/ranking` unless strictly necessary for validation-safe compatibility. -- Keep PostgreSQL as the operational target and preserve SQLite compatibility already present in the shared backend path. - -## Validation - -Before completing the task ensure: - -- `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- local import validation proves: - - `generate_ranking_snapshot(timeframe="weekly", server_key="all", metric="kills", limit=20)` creates a snapshot - - `get_latest_ranking_snapshot(...)` can read that snapshot - - `/api/ranking?timeframe=weekly&server_id=all&metric=kills&limit=20` returns `snapshot_status=ready` - - the same response returns `fallback_used=false` - - requesting a combination without a snapshot still preserves runtime fallback when enabled -- document the manual CLI command for local and Docker execution -- `git diff --name-only` matches the expected scope - -## Outcome - -Implemented: - -- `backend/app/rcon_historical_leaderboards.py` - - `generate_ranking_snapshot(...)` - - persistence helpers for `ranking_snapshots` and `ranking_snapshot_items` - - manual CLI entrypoint: - - `python -m app.rcon_historical_leaderboards generate-ranking-snapshot --timeframe weekly --server-key all --metric kills --limit 20` -- `scripts/run-stats-validation.ps1` - - now validates a real generated weekly snapshot through: - - direct function import - - `get_latest_ranking_snapshot(...)` - - `/api/ranking` - - confirms generated snapshot reads return: - - `snapshot_status=ready` - - `fallback_used=false` - - confirms runtime fallback still works for a missing combination -- `docs/ranking-snapshot-read-model-plan.md` - - documents the manual command - - documents the recommended weekly/monthly/server/metric matrix - - documents suggested refresh cadence - - documents the expected `ready` vs fallback response states - -Supported generation scope: - -- `timeframe` - - `weekly` - - `monthly` -- `server-key` - - `all` - - `all-servers` - - `comunidad-hispana-01` - - `comunidad-hispana-02` -- `metric` - - `kills` - - `deaths` - - `teamkills` - - `matches_considered` - - `kd_ratio` - - `kills_per_match` - -Validations executed: - -- `python -m compileall backend/app/rcon_historical_leaderboards.py backend/app/payloads.py backend/app/routes.py backend/app/postgres_rcon_storage.py` -- direct local import probe for `generate_ranking_snapshot(...)` -- `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- local CLI probe: - - `python -m app.rcon_historical_leaderboards generate-ranking-snapshot --timeframe weekly --server-key all --metric kills --limit 20` - -Validation notes: - -- Live backend HTTP at `http://127.0.0.1:8000` was not available, so route validation completed through local imports and repository scripts. -- The manual CLI is unitary per `(timeframe, server-key, metric)` combination. -- A broader matrix helper was intentionally left out to keep the task small and verifiable. - -Recommended Docker command for production: - -- `docker compose exec backend python -m app.rcon_historical_leaderboards generate-ranking-snapshot --timeframe weekly --server-key all --metric kills --limit 20` - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-195-fix-ranking-snapshot-generator-postgres-default.md b/ai/tasks/done/TASK-195-fix-ranking-snapshot-generator-postgres-default.md deleted file mode 100644 index 87690d2..0000000 --- a/ai/tasks/done/TASK-195-fix-ranking-snapshot-generator-postgres-default.md +++ /dev/null @@ -1,134 +0,0 @@ ---- -id: TASK-195-fix-ranking-snapshot-generator-postgres-default -title: Fix ranking snapshot generator PostgreSQL default -status: done -type: backend -team: Backend Senior -supporting_teams: - - Arquitecto de Base de Datos - - Arquitecto Python -roadmap_item: foundation -priority: high ---- - -# TASK-195 - Fix ranking snapshot generator PostgreSQL default - -## Goal - -Correct the weekly/monthly ranking snapshot CLI so production generation uses PostgreSQL by default, matching the operational `/api/ranking` read path. - -## Context - -`TASK-194` added a manual weekly/monthly snapshot generator, but the CLI currently passes `db_path=get_storage_path()` into `generate_ranking_snapshot(...)`. In this repository, `use_postgres_rcon_storage(...)` only enables PostgreSQL when `explicit_sqlite_path is None` and `HLL_BACKEND_DATABASE_URL` exists, so the current CLI forces SQLite while `/api/ranking` reads PostgreSQL. - -This causes operational commands to generate `ready` snapshots with `item_count=0` and `source_matches_count=0` in SQLite even when runtime fallback over PostgreSQL returns ranking players. - -Preserve the current product identity: Spanish-speaking HLL Vietnam community, military/Vietnam/tactical/sober visual direction and controlled repository evolution. - -## Steps - -1. Read the listed files first. -2. Change the ranking snapshot CLI to use PostgreSQL by default in operational mode. -3. Keep SQLite available only as an explicit local-development override if needed. -4. Validate the CLI default path, repository scripts and documentation. -5. Document root cause, fix and production validation steps. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `backend/app/config.py` -- `backend/app/rcon_historical_leaderboards.py` -- `backend/app/postgres_rcon_storage.py` -- `scripts/run-stats-validation.ps1` -- `docs/ranking-snapshot-read-model-plan.md` -- `ai/tasks/done/TASK-194-add-weekly-monthly-ranking-snapshot-generator.md` - -## Expected Files to Modify - -- `backend/app/rcon_historical_leaderboards.py` -- `scripts/run-stats-validation.ps1` -- `docs/ranking-snapshot-read-model-plan.md` -- `ai/tasks/done/TASK-195-fix-ranking-snapshot-generator-postgres-default.md` - -## Constraints - -- Keep the change minimal. -- Do not modify frontend, assets or design. -- Do not change public endpoint behavior beyond the intended generator hotfix. -- Keep annual ranking behavior unchanged. -- Do not reactivate Elo/MMR. -- Do not reintroduce Comunidad Hispana #03. -- Keep PostgreSQL as the operational default and SQLite only as an explicit local-development mode. - -## Validation - -Before completing the task ensure: - -- `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- local import or parser validation proves the CLI no longer passes `get_storage_path()` by default -- local validation proves `generate_ranking_snapshot(..., db_path=None)` uses PostgreSQL when `HLL_BACKEND_DATABASE_URL` is configured -- `git diff --name-only` matches the expected scope - -## Outcome - -Root cause: - -- the manual CLI in `backend/app/rcon_historical_leaderboards.py` called `generate_ranking_snapshot(..., db_path=get_storage_path())` -- that forced `explicit_sqlite_path != None` -- `use_postgres_rcon_storage(...)` therefore disabled PostgreSQL even when `HLL_BACKEND_DATABASE_URL` was configured -- operational `/api/ranking` reads PostgreSQL, so the generator and the public ranking endpoint diverged onto different storage backends - -Applied change: - -- `backend/app/rcon_historical_leaderboards.py` - - removed the default CLI path that forced SQLite - - changed the operational default to `db_path=None` - - added explicit `--sqlite-path ` override for local development only -- `scripts/run-stats-validation.ps1` - - now validates that the CLI default passes `db_path=None` - - now validates that PostgreSQL selection activates when `HLL_BACKEND_DATABASE_URL` is configured and no explicit SQLite path is provided -- `docs/ranking-snapshot-read-model-plan.md` - - now documents PostgreSQL as the operational default - - now documents `--sqlite-path` as an explicit local override only - -Previous vs new behavior: - -- before: - - `python -m app.rcon_historical_leaderboards generate-ranking-snapshot ...` - - forced SQLite by default - - could generate empty snapshots operationally while `/api/ranking` fallback over PostgreSQL still returned players -- now: - - the same command uses PostgreSQL by default when `HLL_BACKEND_DATABASE_URL` is configured - - SQLite is used only when the operator passes `--sqlite-path` - -Validation executed: - -- `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` - -Validation notes: - -- live backend HTTP at `http://127.0.0.1:8000` was not available in this environment -- route and CLI validation completed through local Python imports and repository validation scripts -- no local PostgreSQL instance was required because the validation proved backend selection by inspection and monkeypatched connection-path checks - -Final recommended Docker command: - -- `docker compose exec backend python -m app.rcon_historical_leaderboards generate-ranking-snapshot --timeframe weekly --server-key all --metric kills --limit 20` - -How to validate in production: - -1. run the Docker command above in the production backend container -2. query PostgreSQL `ranking_snapshots` for the selected `(timeframe, server_id, metric, window_start, window_end)` -3. confirm `item_count > 0` and `source_matches_count > 0` for covered windows -4. call `/api/ranking?timeframe=weekly&server_id=all&metric=kills&limit=20` -5. confirm `snapshot_status=ready` and `fallback_used=false` - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-196-fix-ranking-snapshot-cli-json-serialization.md b/ai/tasks/done/TASK-196-fix-ranking-snapshot-cli-json-serialization.md deleted file mode 100644 index 056277e..0000000 --- a/ai/tasks/done/TASK-196-fix-ranking-snapshot-cli-json-serialization.md +++ /dev/null @@ -1,108 +0,0 @@ ---- -id: TASK-196-fix-ranking-snapshot-cli-json-serialization -title: Fix ranking snapshot CLI JSON serialization -status: done -type: backend -team: Backend Senior -supporting_teams: - - Arquitecto Python -roadmap_item: foundation -priority: high ---- - -# TASK-196 - Fix ranking snapshot CLI JSON serialization - -## Goal - -Correct the `generate-ranking-snapshot` CLI output path so it can print the generated payload as JSON without failing on `datetime` or `date` values. - -## Context - -The weekly ranking snapshot command already generates and persists snapshots correctly in PostgreSQL. Production validation confirmed `ranking_snapshots.snapshot_status=ready`, `item_count=20`, `source_matches_count=41`, and `/api/ranking?timeframe=weekly&metric=kills&limit=20` returns `snapshot_status=ready` with `fallback_used=false`. - -The remaining bug is only in the CLI print path inside `backend/app/rcon_historical_leaderboards.py`, where `_main()` currently calls `json.dumps({"status": "ok", "data": payload}, ensure_ascii=True, indent=2)` and can still receive native `datetime` values inside `payload`. - -Preserve the current product identity: Spanish-speaking HLL Vietnam community, military/Vietnam/tactical/sober visual direction and controlled repository evolution. - -## Steps - -1. Read the listed files first. -2. Apply only the scoped JSON serialization fix for the CLI output path. -3. Reuse an existing serialization pattern if a safe local helper already exists. -4. Validate scripts, local serialization behavior and CLI output behavior when possible. -5. Document root cause, applied change and validation results. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `backend/app/rcon_historical_leaderboards.py` -- `backend/app/main.py` -- `scripts/run-stats-validation.ps1` - -## Expected Files to Modify - -- `backend/app/rcon_historical_leaderboards.py` -- `scripts/run-stats-validation.ps1` -- `ai/tasks/done/TASK-196-fix-ranking-snapshot-cli-json-serialization.md` - -## Constraints - -- Keep the change minimal. -- Fix only the CLI JSON serialization path. -- Do not change snapshot generation logic. -- Do not change `/api/ranking`. -- Do not touch frontend, assets or design. -- Do not reactivate Elo/MMR. -- Do not reintroduce Comunidad Hispana #03. -- Do not change annual behavior except reusing a generic serializer pattern if it already exists. - -## Validation - -Before completing the task ensure: - -- `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- local import validation proves the payload from `generate_ranking_snapshot(...)` can be serialized with `json.dumps` -- if the environment allows it, execute the CLI and confirm it prints JSON without `TypeError` -- `git diff --name-only` matches the expected scope - -## Outcome - -Document: - -- Root cause: - - `generate_ranking_snapshot(...)` already generated and persisted the snapshot correctly. - - the CLI failure happened afterwards in `_main()`, when `json.dumps({"status": "ok", "data": payload}, ensure_ascii=True, indent=2)` received native `datetime` / `date` objects inside `payload`. - - the bug only affected CLI JSON printing and did not affect PostgreSQL snapshot persistence or `/api/ranking`. - -- Applied change: - - `backend/app/rcon_historical_leaderboards.py` - - added a local controlled `_json_default(...)` serializer for `datetime` and `date` - - serializes `datetime` through the module's existing `_to_iso(...)` helper - - serializes `date` with `isoformat()` - - updated the CLI `json.dumps(...)` call to use `default=_json_default` - - `scripts/run-stats-validation.ps1` - - extended the CLI regression to return a payload containing both `datetime` and `date` - - verifies `_main(...)` exits successfully - - verifies stdout JSON contains ISO strings instead of failing with `TypeError` - -- Validation executed: - - `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` - - `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` - - local import validation with `json.dumps(..., default=app.rcon_historical_leaderboards._json_default)` - - local `_main(...)` validation with a monkeypatched `generate_ranking_snapshot(...)` payload containing `datetime` and `date` - - local CLI execution: - - `python -m app.rcon_historical_leaderboards generate-ranking-snapshot --timeframe weekly --server-key all --metric kills --limit 20 --sqlite-path backend/data/hll_vietnam_dev.sqlite3` - -- Validation notes: - - the live backend at `http://127.0.0.1:8000` was not available in this environment, so route-contract validation completed through local Python imports. - - the local CLI command printed JSON successfully and no longer raised `TypeError: Object of type datetime is not JSON serializable`. - - production behavior described in the task context remains confirmed: snapshot generation already worked, and the observed failure was only the final CLI JSON print step. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-197-automate-ranking-snapshot-refresh.md b/ai/tasks/done/TASK-197-automate-ranking-snapshot-refresh.md deleted file mode 100644 index 85a8d78..0000000 --- a/ai/tasks/done/TASK-197-automate-ranking-snapshot-refresh.md +++ /dev/null @@ -1,174 +0,0 @@ ---- -id: TASK-197-automate-ranking-snapshot-refresh -title: Automate ranking snapshot refresh -status: done -type: backend -team: Backend Senior -supporting_teams: - - Arquitecto de Base de Datos - - Arquitecto Python -roadmap_item: foundation -priority: high ---- - -# TASK-197 - Automate ranking snapshot refresh - -## Goal - -Automate the periodic refresh of weekly and monthly ranking snapshots in PostgreSQL so `/api/ranking` can keep serving `ranking-snapshot` read-model responses for the supported public combinations without relying on manual one-by-one generation. - -## Context - -`TASK-194`, `TASK-195` and `TASK-196` already validated the manual generator path in production: - -- `generate-ranking-snapshot` works -- PostgreSQL is the default operational backend -- CLI JSON serialization is fixed -- the expected `36` combinations were generated successfully -- all generated rows ended with `snapshot_status=ready` -- `/api/ranking` returns `source.read_model=ranking-snapshot` -- `/api/ranking` returns `fallback_used=false` when a ready snapshot exists -- `limit_size=30` already covers the current UI limits `10`, `20` and `30` - -The remaining gap is operational automation. The repository already has a periodic backend runner in `backend/app/historical_runner.py`, so the default direction for this task is to integrate ranking snapshot refresh there rather than invent a separate scheduler. If that integration becomes too invasive, the fallback is a controlled bulk CLI/manual helper such as `python -m app.rcon_historical_leaderboards refresh-ranking-snapshots --limit 30`, with the periodic integration left prepared for the next step. - -Preserve the current product identity: Spanish-speaking HLL Vietnam community, military/Vietnam/tactical/sober visual direction and controlled repository evolution. - -## Steps - -1. Read the listed files first. -2. Inspect the existing historical runner and ranking snapshot generator entrypoints. -3. Add the smallest safe backend mechanism that refreshes the weekly/monthly ranking snapshot matrix in PostgreSQL. -4. Generate the supported matrix with per-combination error reporting so one failure does not necessarily abort the entire refresh. -5. Keep the manual single-snapshot CLI working. -6. Preserve `/api/ranking` snapshot-first behavior and runtime fallback when a snapshot is missing. -7. Document the recommended refresh cadence and manual operational commands. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `backend/app/rcon_historical_leaderboards.py` -- `backend/app/historical_runner.py` -- `backend/app/rcon_historical_worker.py` -- `backend/app/payloads.py` -- `docs/ranking-snapshot-read-model-plan.md` -- `scripts/run-stats-validation.ps1` -- `ai/tasks/done/TASK-194-add-weekly-monthly-ranking-snapshot-generator.md` -- `ai/tasks/done/TASK-195-fix-ranking-snapshot-generator-postgres-default.md` -- `ai/tasks/done/TASK-196-fix-ranking-snapshot-cli-json-serialization.md` - -## Expected Files to Modify - -- `backend/app/rcon_historical_leaderboards.py` -- `backend/app/historical_runner.py` -- `backend/app/payloads.py` -- `docs/ranking-snapshot-read-model-plan.md` -- `scripts/run-stats-validation.ps1` - -## Constraints - -- Keep the change minimal and backend-only. -- Do not modify frontend. -- Do not change design. -- Do not touch images or assets. -- Use PostgreSQL as the operational storage target. -- Do not depend on SQLite for the automated refresh path. -- Do not change the public `/api/ranking` contract except internal metadata already present if strictly needed. -- Do not break the manual `generate-ranking-snapshot` CLI. -- Keep runtime fallback as a safety net when a snapshot is missing. -- Do not reactivate Elo/MMR. -- Do not reintroduce Comunidad Hispana #03. -- Do not introduce an invasive scheduler architecture if the existing runner can safely host the refresh. - -## Validation - -Before completing the task ensure: - -- `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- the automated or bulk refresh path generates the expected `36` combinations: - - timeframes: `weekly`, `monthly` - - servers: `all`, `comunidad-hispana-01`, `comunidad-hispana-02` - - metrics: `kills`, `deaths`, `teamkills`, `matches_considered`, `kd_ratio`, `kills_per_match` - - limit: `30` -- validation proves per-combination failures are reported and do not necessarily stop every remaining combination -- validation proves the manual CLI `generate-ranking-snapshot` still works -- validation proves `/api/ranking` still serves `snapshot_status=ready` and `read_model=ranking-snapshot` when ready snapshots exist -- validation proves runtime fallback remains available for missing snapshots -- `git diff --name-only` matches the expected scope - -## Outcome - -Implemented: - -- `backend/app/rcon_historical_leaderboards.py` - - added `refresh_ranking_snapshots(...)` to generate the full weekly/monthly matrix in one run - - added bulk CLI entrypoint: - - `python -m app.rcon_historical_leaderboards refresh-ranking-snapshots --limit 30` - - preserved the existing manual CLI entrypoint: - - `python -m app.rcon_historical_leaderboards generate-ranking-snapshot --timeframe weekly --server-key all --metric kills --limit 30` -- `backend/app/historical_runner.py` - - integrated ranking snapshot refresh into the periodic historical backend cycle through `refresh_periodic_ranking_snapshots(...)` - - the cycle now reports `ranking_snapshot_result` separately from the existing historical snapshot result -- `docs/ranking-snapshot-read-model-plan.md` - - documents the new bulk command - - documents the runner integration direction - - documents `limit=30` as the operational default for the weekly/monthly matrix -- `scripts/run-stats-validation.ps1` - - validates the bulk CLI argument path - - validates that bulk refresh covers `36` combinations - - validates partial failure reporting without aborting the remaining combinations - - keeps validating the existing manual `generate-ranking-snapshot` path - -Generated matrix: - -- timeframes: `weekly`, `monthly` -- servers: `all`, `comunidad-hispana-01`, `comunidad-hispana-02` -- metrics: `kills`, `deaths`, `teamkills`, `matches_considered`, `kd_ratio`, `kills_per_match` -- limit: `30` -- total combinations per refresh cycle: `36` - -Per-combination failure behavior: - -- bulk refresh catches exceptions per combination -- the full refresh result returns `status=partial` when at least one combination fails and at least one succeeds -- each failed combination reports: - - `timeframe` - - `server_key` - - `metric` - - `error_type` - - `error` -- a single failure does not abort the remaining combinations - -Recommended frequency: - -- weekly current window: every `5` to `15` minutes -- monthly current window: every `15` to `30` minutes -- closed previous week / previous month windows: once after closure or after historical backfill - -Validations executed: - -- `python -m compileall backend/app/rcon_historical_leaderboards.py backend/app/historical_runner.py` -- `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- isolated real CLI validation against temporary SQLite files outside the workspace: - - `refresh-ranking-snapshots --limit 30` returned `combinations_expected=36`, `succeeded=36`, `failed=0` - - `generate-ranking-snapshot` still returned `status=ok` and `snapshot_status=ready` - -Validation notes: - -- live backend HTTP at `http://127.0.0.1:8000` was not available in this environment -- `/api/ranking` snapshot-ready and fallback behavior remained validated through the existing local route-contract checks in `scripts/run-stats-validation.ps1` -- no frontend, design, asset, Elo/MMR or Comunidad Hispana `#03` changes were made - -Pending limitation kept out of scope: - -- this task integrates the refresh into the existing periodic historical runner and adds a bulk CLI, but it does not introduce a separate external scheduler or deployment-specific cron wiring - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-198-add-player-search-read-model.md b/ai/tasks/done/TASK-198-add-player-search-read-model.md deleted file mode 100644 index 75b77b5..0000000 --- a/ai/tasks/done/TASK-198-add-player-search-read-model.md +++ /dev/null @@ -1,163 +0,0 @@ ---- -id: TASK-198-add-player-search-read-model -title: Add player search read model -status: done -type: backend -team: Backend Senior -supporting_teams: - - Arquitecto de Base de Datos - - Arquitecto Python -roadmap_item: foundation -priority: high ---- - -# TASK-198 - Add player search read model - -## Goal - -Add the first PostgreSQL read model for player search so `/api/stats/players/search` can serve compact search results without aggregating large RCON historical tables on every public request. - -## Context - -Weekly and monthly ranking snapshots are already implemented and validated in PostgreSQL with runtime fallback preserved. The next high-cost public path is the player search flow, which currently reads directly from `rcon_match_player_stats` and `rcon_materialized_matches` at request time. - -This task adds a dedicated regenerable read model for player lookup, refreshed manually out of band from materialized RCON PostgreSQL tables. The public search endpoint must prefer that read model when it exists and has rows, while preserving controlled runtime fallback if the read model is missing, empty or temporarily unreadable. - -Preserve the current product identity: Spanish-speaking HLL Vietnam community, military/Vietnam/tactical/sober visual direction and controlled repository evolution. - -## Steps - -1. Read the listed files first. -2. Add a dedicated player search index table as a regenerable read model. -3. Implement a refresh function that rebuilds the index from materialized RCON PostgreSQL tables, with current-year counters and recent player rows only. -4. Add a manual CLI command to rebuild the read model on demand. -5. Make `/api/stats/players/search` prefer the read model and keep runtime fallback when needed. -6. Preserve the current frontend contract consumed by `frontend/assets/js/stats.js`. -7. Document the operational command, fallback behavior and current limitations. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `backend/app/payloads.py` -- `backend/app/rcon_historical_player_stats.py` -- `backend/app/postgres_rcon_storage.py` -- `backend/app/rcon_admin_log_materialization.py` -- `docs/stats-section-functional-plan.md` -- `docs/ranking-snapshot-read-model-plan.md` -- `ai/tasks/done/TASK-197-automate-ranking-snapshot-refresh.md` - -## Expected Files to Modify - -- `backend/app/rcon_historical_player_stats.py` -- `backend/app/postgres_rcon_storage.py` -- `scripts/run-stats-validation.ps1` -- `docs/player-search-read-model-plan.md` -- `ai/tasks/done/TASK-198-add-player-search-read-model.md` - -## Constraints - -- Keep the change minimal and backend-only. -- Do not execute `ai-platform run`. -- Do not modify frontend. -- Do not change design. -- Do not touch images or assets. -- Do not reactivate Elo/MMR. -- Do not reintroduce Comunidad Hispana `#03`. -- Do not mix visual corrections into this task. -- PostgreSQL is the operational storage target. -- SQLite may remain only as explicit local compatibility where the current backend architecture already supports it. -- The new table is a regenerable read model, not a canonical source of truth. -- Do not require PostgreSQL extensions such as `pg_trgm`. -- Keep the current frontend contract for player search results compatible with `frontend/assets/js/stats.js`. - -## Validation - -Before completing the task ensure: - -- `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- local validation proves the `player_search_index` table can be initialized -- local validation proves `refresh_player_search_index(...)` generates rows from materialized test data -- local validation proves player search uses `player_search_index` when data exists -- local validation proves search falls back to the runtime aggregation path when the index is empty or unavailable -- the public search payload remains compatible with `frontend/assets/js/stats.js` -- `git diff --name-only` matches the expected scope - -## Outcome - -Implemented: - -- `backend/app/rcon_historical_player_stats.py` - - added `player_search_index` initialization for SQLite compatibility and PostgreSQL-first operational mode - - added `refresh_player_search_index(...)` - - added snapshot-first search logic for `/api/stats/players/search` - - preserved runtime fallback when the read model is empty or unavailable - - added manual CLI: - - `python -m app.rcon_historical_player_stats refresh-player-search-index` -- `backend/app/postgres_rcon_storage.py` - - added PostgreSQL schema for `player_search_index` - - added scope-aware indexes for normalized name, last seen and player id -- `backend/app/payloads.py` - - preserved the public search payload contract and added backward-compatible source metadata -- `scripts/run-stats-validation.ps1` - - validates PostgreSQL schema wiring - - validates CLI defaults - - validates fixture-driven refresh generation - - validates read-model-first search - - validates fallback when the index is empty or unavailable -- `docs/player-search-read-model-plan.md` - - documents objective, fields, CLI, PostgreSQL role, fallback and current limitations - -Created table: - -- `player_search_index` - -Table behavior: - -- regenerable read model only -- one row per `(server_id, player_id)` public search scope -- supported scopes: - - `all-servers` - - `comunidad-hispana-01` - - `comunidad-hispana-02` -- aggregates only current UTC year counters -- stores Python-normalized accent-insensitive `normalized_player_name` - -CLI added: - -- `python -m app.rcon_historical_player_stats refresh-player-search-index` - -Production validation path: - -- refresh manually with the CLI above -- confirm row counts are reported for `all-servers`, `comunidad-hispana-01` and `comunidad-hispana-02` -- call `/api/stats/players/search?q=&limit=5` -- verify `data.source.read_model=player-search-index` -- verify `data.source.fallback_used=false` when the read model is populated -- verify fallback metadata appears only when the read model is empty or unavailable - -Validations executed: - -- `python -m py_compile backend/app/rcon_historical_player_stats.py backend/app/payloads.py backend/app/postgres_rcon_storage.py` -- `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- local CLI smoke check: - - `python -m app.rcon_historical_player_stats refresh-player-search-index --sqlite-path backend/data/hll_vietnam_dev.sqlite3` - -Validation notes: - -- live backend HTTP at `http://127.0.0.1:8000` was not available in this environment -- route-contract validation still passed through local Python imports -- no frontend, design, asset, Elo/MMR or Comunidad Hispana `#03` changes were made - -Pending follow-up kept out of scope: - -- player profile and personal stats still read from runtime aggregates; only the search path is snapshot-backed in this task - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-199-add-player-period-stats-read-model.md b/ai/tasks/done/TASK-199-add-player-period-stats-read-model.md deleted file mode 100644 index 61747d2..0000000 --- a/ai/tasks/done/TASK-199-add-player-period-stats-read-model.md +++ /dev/null @@ -1,172 +0,0 @@ ---- -id: TASK-199-add-player-period-stats-read-model -title: Add player period stats read model -status: done -type: backend -team: Backend Senior -supporting_teams: - - Arquitecto de Base de Datos - - Arquitecto Python -roadmap_item: foundation -priority: high ---- - -# TASK-199 - Add player period stats read model - -## Goal - -Add a dedicated PostgreSQL read model for player personal stats by period so `/api/stats/players/{player_id}` can avoid aggregating large RCON historical tables on every public request when a regenerated read model is available. - -## Context - -The repository already has PostgreSQL-backed ranking snapshots and a player search read model with controlled runtime fallback. The next expensive public path is the player profile/stats flow, which still aggregates directly from `rcon_materialized_matches` and `rcon_match_player_stats` at request time. - -This task adds a regenerable `player_period_stats` read model for weekly, monthly and yearly player totals across the supported public scopes. The profile read path must prefer the read model when it exists and contains rows for the requested player, scope and period, while preserving the current runtime fallback path if the table is missing, empty, incomplete or temporarily unreadable. - -Preserve the current product identity: Spanish-speaking HLL Vietnam community, military/Vietnam/tactical/sober visual direction and controlled repository evolution. - -## Steps - -1. Read the listed files first. -2. Add a dedicated PostgreSQL read-model table for player personal stats by period. -3. Implement a refresh function that rebuilds the table from materialized RCON PostgreSQL tables for the supported scopes and windows. -4. Add a manual CLI command to rebuild the read model on demand. -5. Make `/api/stats/players/{player_id}` prefer the read model and keep controlled runtime fallback when needed. -6. Preserve the current frontend contract consumed by `frontend/assets/js/stats.js`. -7. Document the operational command, fallback behavior and current limitations. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `backend/app/routes.py` -- `backend/app/payloads.py` -- `backend/app/rcon_historical_player_stats.py` -- `backend/app/postgres_rcon_storage.py` -- `backend/app/rcon_admin_log_materialization.py` -- `docs/stats-section-functional-plan.md` -- `docs/player-search-read-model-plan.md` -- `ai/tasks/done/TASK-198-add-player-search-read-model.md` - -## Expected Files to Modify - -- `backend/app/rcon_historical_player_stats.py` -- `backend/app/postgres_rcon_storage.py` -- `scripts/run-stats-validation.ps1` -- `docs/player-period-stats-read-model-plan.md` -- `ai/tasks/done/TASK-199-add-player-period-stats-read-model.md` - -## Constraints - -- Keep the change minimal and backend-only. -- Do not execute `ai-platform run`. -- Do not modify frontend. -- Do not change design. -- Do not touch images or assets. -- Do not reactivate Elo/MMR. -- Do not reintroduce Comunidad Hispana `#03`. -- Do not mix visual corrections into this task. -- PostgreSQL is the operational storage target. -- SQLite may remain only as explicit local compatibility where the current backend architecture already supports it. -- The new table is a regenerable read model, not a canonical source of truth. -- Do not require PostgreSQL extensions that are not already installed. -- Keep the current frontend contract for player profile data compatible with `frontend/assets/js/stats.js`. -- Minimum supported period types are `weekly`, `monthly` and `yearly`. -- Minimum supported public scopes are `all-servers`, `comunidad-hispana-01` and `comunidad-hispana-02`. - -## Validation - -Before completing the task ensure: - -- `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- local validation proves the `player_period_stats` table can be initialized -- local validation proves `refresh_player_period_stats(...)` generates rows from materialized test data -- local validation proves player profile/stats uses `player_period_stats` when data exists -- local validation proves profile/stats falls back when the read model is empty, missing or unavailable -- the public player profile payload remains compatible with `frontend/assets/js/stats.js` -- player search refresh and read path remain functional -- `git diff --name-only` matches the expected scope - -## Outcome - -Implemented: - -- `backend/app/rcon_historical_player_stats.py` - - added `player_period_stats` initialization for SQLite compatibility and PostgreSQL-first operational mode - - added `refresh_player_period_stats(...)` - - added snapshot-first player profile reads over `player_period_stats` - - preserved runtime fallback when the read model is empty, incomplete or unavailable - - added manual CLI: - - `python -m app.rcon_historical_player_stats refresh-player-period-stats` -- `backend/app/postgres_rcon_storage.py` - - added PostgreSQL schema for `player_period_stats` - - added indexes for: - - `(player_id, period_type, server_id)` - - `(server_id, period_type)` - - `last_seen_at` - - `updated_at` -- `scripts/run-stats-validation.ps1` - - validates PostgreSQL schema wiring - - validates CLI defaults - - validates fixture-driven refresh generation - - validates read-model-first profile reads - - validates fallback when the read model is empty, incomplete or unavailable -- `docs/player-period-stats-read-model-plan.md` - - documents objective, fields, windows, CLI, PostgreSQL role, fallback and current limitations - -Created table: - -- `player_period_stats` - -Table behavior: - -- regenerable read model only -- one row per `(period_type, server_id, player_id)` public scope -- supported periods: - - `weekly` - - `monthly` - - `yearly` -- supported scopes: - - `all-servers` - - `comunidad-hispana-01` - - `comunidad-hispana-02` -- stores ranking position by kills for the selected window -- preserves latest player name inside each generated window - -CLI added: - -- `python -m app.rcon_historical_player_stats refresh-player-period-stats` - -Production validation path: - -- refresh manually with the CLI above -- confirm row counts are reported for the supported scopes and periods -- call `/api/stats/players/?timeframe=weekly` -- verify `data.source.read_model=player-period-stats` -- verify `data.source.fallback_used=false` when the read model is populated -- verify fallback metadata appears only when the read model is empty, incomplete or unavailable - -Validations executed: - -- `python -m py_compile backend/app/rcon_historical_player_stats.py backend/app/postgres_rcon_storage.py` -- `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` - -Validation notes: - -- live backend HTTP at `http://127.0.0.1:8000` was not available in this environment -- route-contract validation still passed through local Python imports -- no frontend, design, asset, Elo/MMR or Comunidad Hispana `#03` changes were made - -Pending follow-up kept out of scope: - -- automate periodic refresh scheduling for `player_period_stats` -- decide whether production refresh should be chained with ranking snapshot/search index refresh jobs - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-200-fix-player-profile-runtime-postgres-grouping.md b/ai/tasks/done/TASK-200-fix-player-profile-runtime-postgres-grouping.md deleted file mode 100644 index 8551143..0000000 --- a/ai/tasks/done/TASK-200-fix-player-profile-runtime-postgres-grouping.md +++ /dev/null @@ -1,176 +0,0 @@ ---- -id: TASK-200-fix-player-profile-runtime-postgres-grouping -title: Fix player profile runtime PostgreSQL grouping -status: done -type: backend -team: Backend Senior -supporting_teams: - - Arquitecto de Base de Datos - - Arquitecto Python -roadmap_item: foundation -priority: high ---- - -# TASK-200 - Fix player profile runtime PostgreSQL grouping - -## Goal - -Corregir el `500` de `/api/stats/players/{player_id}?server_id={server}` cuando el jugador no tiene fila en `player_period_stats` para el timeframe solicitado y la ruta cae al fallback runtime sobre PostgreSQL. - -## Context - -`TASK-199` introdujo `player_period_stats` y el endpoint público ya usa correctamente el read model cuando existe una fila para el jugador/scope/timeframe solicitado. El problema aparece cuando el read model no tiene fila para ese jugador en el timeframe pedido y la lectura cae a `_get_rcon_materialized_player_stats_runtime(...)`. - -La causa raíz validada en producción es una query de `_fetch_player_stats(...)` en `backend/app/rcon_historical_player_stats.py` que usa una expresión equivalente a `COALESCE(MAX(stats.player_name), stats.player_id)` sin agregar ni agrupar `stats.player_id`. SQLite lo tolera, pero PostgreSQL lanza `psycopg.errors.GroupingError`, provocando un `500` para casos como `server_id=comunidad-hispana-01` cuando no hay fila `weekly` o `monthly` en `player_period_stats`. - -Preserve the current product identity: Spanish-speaking HLL Vietnam community, military/Vietnam/tactical/sober visual direction and controlled repository evolution. - -## Steps - -1. Inspect the listed files first. -2. Fix the runtime fallback query used by `_fetch_player_stats(...)` so it is valid in PostgreSQL. -3. Preserve SQLite/local compatibility when the explicit local path is used. -4. Keep `player_period_stats` as the preferred source whenever a row exists. -5. Keep runtime fallback when the read model is missing, incomplete or unavailable. -6. Ensure the no-read-model-row case returns the existing controlled contract instead of a `500`. -7. Validate the affected player-profile, player-search and ranking snapshot paths. -8. Document the root cause, affected SQL, new behavior and production validation path. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `backend/app/rcon_historical_player_stats.py` -- `backend/app/payloads.py` -- `backend/app/routes.py` -- `backend/app/postgres_rcon_storage.py` -- `scripts/run-stats-validation.ps1` -- `docs/player-period-stats-read-model-plan.md` -- `ai/tasks/done/TASK-199-add-player-period-stats-read-model.md` - -## Expected Files to Modify - -- `backend/app/rcon_historical_player_stats.py` -- `scripts/run-stats-validation.ps1` -- `ai/tasks/in-progress/TASK-200-fix-player-profile-runtime-postgres-grouping.md` - -## Constraints - -- Keep the change minimal and backend-only. -- Do not execute `ai-platform run`. -- Do not modify frontend. -- Do not change design. -- Do not touch images or assets. -- Do not reactivate Elo/MMR. -- Do not reintroduce Comunidad Hispana `#03`. -- Do not mix automation changes into this task. -- Do not change public contracts except to avoid the runtime `500`. -- Keep `player_period_stats` as the preferred source when data exists. -- Keep runtime fallback active when the read model has no row for the requested scope/window. -- If runtime also has no rows for that scope/window, return the existing controlled empty/zero contract instead of throwing. -- Do not break: - - `/api/stats/players/search` - - `/api/stats/players/{player_id}` - - ranking snapshots - - `refresh-player-search-index` - - `refresh-player-period-stats` - -## Validation - -Before completing the task ensure: - -- `python -m py_compile backend/app/rcon_historical_player_stats.py` -- `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- local validation proves `_fetch_player_stats(...)` no longer emits PostgreSQL-invalid aggregate SQL -- local validation proves the runtime fallback path does not throw when a server-specific read-model row is missing -- local validation proves `player_period_stats` is still used when a row exists -- local validation proves `player_search_index` still works -- local validation proves ranking snapshots are not broken -- validate these profile cases: - - `/api/stats/players/76561197978442431` - - `/api/stats/players/76561197978442431?server_id=all` - - `/api/stats/players/76561197978442431?server_id=all-servers` - - `/api/stats/players/76561197978442431?server_id=comunidad-hispana-02` - - `/api/stats/players/76561197978442431?server_id=comunidad-hispana-01` -- the last case must not return `500` -- `git diff --name-only` matches the expected scope - -## Outcome - -Implemented: - -- `backend/app/rcon_historical_player_stats.py` - - fixed `_fetch_player_stats(...)` runtime aggregation SQL - - removed the PostgreSQL-invalid expression `COALESCE(MAX(stats.player_name), stats.player_id)` - - kept the player-name fallback in Python with `row["player_name"] or player_id` -- `scripts/run-stats-validation.ps1` - - added a SQL-shape regression check for `_fetch_player_stats(...)` - - added a fixture with a `yearly-only-player` on `comunidad-hispana-01` - - validated the server-specific fallback path when `player_period_stats` has no weekly/monthly row and runtime also has no rows in the requested window - -Root cause of the `500`: - -- when `/api/stats/players/{player_id}` could not serve `player_period_stats`, it fell back to `_get_rcon_materialized_player_stats_runtime(...)` -- `_fetch_player_stats(...)` executed a grouped aggregate query that selected: - - `COALESCE(MAX(stats.player_name), stats.player_id) AS player_name` -- PostgreSQL rejects `stats.player_id` in that expression because it is neither aggregated nor part of `GROUP BY` -- SQLite/local compatibility masked the issue because SQLite tolerates that aggregate shape - -Concrete affected SQL shape: - -- previous: - - `SELECT COALESCE(MAX(stats.player_name), stats.player_id) AS player_name, ...` -- new: - - `SELECT MAX(stats.player_name) AS player_name, ...` -- public fallback behavior stays intact because Python already normalizes the result with `str(row["player_name"] or player_id)` - -Previous behavior: - -- read-model hits returned `read_model=player-period-stats` and `fallback_used=false` -- if the requested scope/timeframe had no player row and runtime fallback executed on PostgreSQL, the endpoint could raise `psycopg.errors.GroupingError` -- the request then returned HTTP `500` - -New behavior: - -- `player_period_stats` remains the preferred source when a row exists -- runtime fallback remains active when the read model is empty, incomplete or unavailable -- PostgreSQL fallback SQL is now valid -- if the requested scope/window has no runtime rows, the endpoint returns the existing controlled zero-value profile contract instead of throwing -- no frontend, design, asset, Elo/MMR or Comunidad Hispana `#03` changes were made - -Validations executed: - -- `python -m py_compile backend/app/rcon_historical_player_stats.py` -- `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` - -Validation notes: - -- local import-based validation confirmed `_fetch_player_stats(...)` no longer emits the PostgreSQL-invalid aggregate shape -- local fixture validation confirmed the server-specific missing-read-model fallback does not throw and returns a controlled response -- `player_period_stats` still serves the profile path when rows exist -- `player_search_index` and ranking snapshot validations still pass through `scripts/run-stats-validation.ps1` -- live HTTP validation at `http://127.0.0.1:8000` could not run in this environment because the backend was not up; the script reported that explicitly and route-contract checks still passed via local Python imports -- `git diff --name-only` included unrelated pre-existing changes in `ai/system-metrics.md` and `frontend/assets/img/weapons/black/*`; those files were not modified by this task - -How to validate in production: - -- call: - - `/api/stats/players/76561197978442431` - - `/api/stats/players/76561197978442431?server_id=all` - - `/api/stats/players/76561197978442431?server_id=all-servers` - - `/api/stats/players/76561197978442431?server_id=comunidad-hispana-02` - - `/api/stats/players/76561197978442431?server_id=comunidad-hispana-01` -- verify the first four still report: - - `source.read_model = "player-period-stats"` - - `source.fallback_used = false` -- verify the last case no longer returns HTTP `500` -- verify the last case returns a controlled stats payload with fallback metadata instead of a PostgreSQL grouping exception - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-201-automate-player-read-model-refresh.md b/ai/tasks/done/TASK-201-automate-player-read-model-refresh.md deleted file mode 100644 index 765a6cf..0000000 --- a/ai/tasks/done/TASK-201-automate-player-read-model-refresh.md +++ /dev/null @@ -1,223 +0,0 @@ ---- -id: TASK-201-automate-player-read-model-refresh -title: Automate player read model refresh -status: done -type: backend -team: Backend Senior -supporting_teams: - - Arquitecto de Base de Datos - - Arquitecto Python -roadmap_item: foundation -priority: high ---- - -# TASK-201 - Automate player read model refresh - -## Goal - -Automate the periodic refresh of `player_search_index` and `player_period_stats` inside the existing backend historical runner so the public stats endpoints can keep using their read models without depending on manual operator refreshes. - -## Context - -Production already validates the full read-model chain required by the public player stats flows: - -- `player_search_index` exists and `/api/stats/players/search` already uses `read_model=player-search-index` with `fallback_used=false` -- `player_period_stats` exists and `/api/stats/players/{player_id}` already uses `read_model=player-period-stats` with `fallback_used=false` -- `ranking_snapshots` / `ranking_snapshot_items` already exist -- `refresh-ranking-snapshots --limit 30` already runs in the periodic historical runner -- PostgreSQL is the operational storage target -- runtime fallback must remain preserved for player stats and ranking - -The remaining gap is operational automation for the two player read models. The existing periodic runner in `backend/app/historical_runner.py` is the intended scheduler surface, so this task must extend that cycle instead of inventing a new scheduler. The cycle should keep `refresh-ranking-snapshots` and add dedicated, separately reported refresh steps for player search and player period stats. - -Preserve the current product identity: Spanish-speaking HLL Vietnam community, military/Vietnam/tactical/sober visual direction and controlled repository evolution. - -## Steps - -1. Read the listed files first. -2. Inspect the current historical runner flow and the existing manual read-model refresh entrypoints. -3. Integrate `refresh_player_search_index(...)` into the periodic backend cycle. -4. Integrate `refresh_player_period_stats(...)` into the periodic backend cycle. -5. Keep `refresh-ranking-snapshots` in the same cycle and preserve its current behavior. -6. Run the cycle in this order unless the current runner architecture safely requires a different invariant: - - existing RCON ingestion/materialization cycle - - `player_search_index` - - `player_period_stats` - - `ranking_snapshots` -7. Report `player_search_index_result`, `player_period_stats_result` and `ranking_snapshot_result` separately. -8. Preserve visibility of failures and avoid hiding one read-model failure behind another. One failure should not necessarily prevent the remaining refresh attempts unless the runner already enforces a stricter global policy. -9. Preserve the manual CLIs and the public contracts of: - - `/api/stats/players/search` - - `/api/stats/players/{player_id}` - - `/api/ranking` -10. Document the automatic runner refresh, inherited cadence, emergency manual commands, fallback preservation and final cycle order. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `backend/app/historical_runner.py` -- `backend/app/rcon_historical_player_stats.py` -- `backend/app/rcon_historical_leaderboards.py` -- `backend/app/postgres_rcon_storage.py` -- `backend/app/payloads.py` -- `docs/player-search-read-model-plan.md` -- `docs/player-period-stats-read-model-plan.md` -- `docs/ranking-snapshot-read-model-plan.md` -- `scripts/run-stats-validation.ps1` -- `ai/tasks/done/TASK-197-automate-ranking-snapshot-refresh.md` -- `ai/tasks/done/TASK-198-add-player-search-read-model.md` -- `ai/tasks/done/TASK-199-add-player-period-stats-read-model.md` -- `ai/tasks/done/TASK-200-fix-player-profile-runtime-postgres-grouping.md` - -## Expected Files to Modify - -- `backend/app/historical_runner.py` -- `docs/player-search-read-model-plan.md` -- `docs/player-period-stats-read-model-plan.md` -- `docs/ranking-snapshot-read-model-plan.md` -- `scripts/run-stats-validation.ps1` -- `ai/tasks/in-progress/TASK-201-automate-player-read-model-refresh.md` - -## Constraints - -- Keep the change minimal and backend/documentation only. -- Do not execute `ai-platform run`. -- Do not modify frontend. -- Do not change design. -- Do not touch images or assets. -- Do not reactivate Elo/MMR. -- Do not reintroduce Comunidad Hispana `#03`. -- Do not mix visual corrections into this task. -- Preserve PostgreSQL as the operational storage target. -- Preserve runtime fallback for player stats and ranking. -- Do not break the manual CLIs: - - `refresh-player-search-index` - - `refresh-player-period-stats` - - `refresh-ranking-snapshots` - - `generate-ranking-snapshot` -- Do not change public contracts of: - - `/api/stats/players/search` - - `/api/stats/players/{player_id}` - - `/api/ranking` - -## Validation - -Before completing the task ensure: - -- `python -m py_compile backend/app/historical_runner.py backend/app/rcon_historical_player_stats.py` -- `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- local/import validation proves the runner calls: - - `refresh_player_search_index(...)` - - `refresh_player_period_stats(...)` - - `refresh_ranking_snapshots(...)` -- validation proves the periodic cycle reports these results separately: - - `player_search_index_result` - - `player_period_stats_result` - - `ranking_snapshot_result` -- validation proves the manual CLIs still work: - - `refresh-player-search-index` - - `refresh-player-period-stats` - - `refresh-ranking-snapshots` -- validation proves `/api/stats/players/search` can still use `player-search-index` -- validation proves `/api/stats/players/{player_id}` can still use `player-period-stats` -- validation proves ranking snapshots are not broken -- `git diff --name-only` matches the expected scope - -## Outcome - -Implemented: - -- `backend/app/historical_runner.py` - - integrated automatic periodic refresh of `player_search_index` - - integrated automatic periodic refresh of `player_period_stats` - - preserved the existing `ranking_snapshots` refresh - - the runner now reports: - - `player_search_index_result` - - `player_period_stats_result` - - `ranking_snapshot_result` - - one read-model failure is now reported explicitly and does not prevent the runner from attempting the remaining refresh steps in the same cycle - - the runner returns `status=partial` when one of those periodic read-model refresh steps fails but the cycle continues -- `docs/player-search-read-model-plan.md` - - documents automatic runner refresh - - documents inherited cadence from `HLL_HISTORICAL_REFRESH_INTERVAL_SECONDS` - - documents the emergency manual command - - documents fallback preservation -- `docs/player-period-stats-read-model-plan.md` - - documents automatic runner refresh - - documents inherited cadence from `HLL_HISTORICAL_REFRESH_INTERVAL_SECONDS` - - documents the emergency manual command - - documents fallback preservation -- `docs/ranking-snapshot-read-model-plan.md` - - documents the final runner order - - documents that ranking refresh remains part of the same periodic cycle - - documents cadence inheritance and fallback preservation -- `scripts/run-stats-validation.ps1` - - validates that the runner calls the player read-model refreshes before ranking snapshots - - validates separate result reporting - - validates that a `player_search_index` refresh failure remains visible and does not stop the remaining periodic refresh attempts - -Modified files: - -- `backend/app/historical_runner.py` -- `docs/player-search-read-model-plan.md` -- `docs/player-period-stats-read-model-plan.md` -- `docs/ranking-snapshot-read-model-plan.md` -- `scripts/run-stats-validation.ps1` -- `ai/tasks/done/TASK-201-automate-player-read-model-refresh.md` - -Final runner order: - -1. existing RCON ingestion/materialization cycle -2. `player_search_index` -3. `player_period_stats` -4. `ranking_snapshots` - -Added cycle results/logs: - -- `player_search_index_result` -- `player_period_stats_result` -- `ranking_snapshot_result` -- start events: - - `player-search-index-refresh-started` - - `player-period-stats-refresh-started` -- failure events: - - `player-search-index-refresh-failed` - - `player-period-stats-refresh-failed` - -Validations executed: - -- `python -m py_compile backend/app/historical_runner.py backend/app/rcon_historical_player_stats.py` -- `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` - -Production validation path: - -- run one controlled backend cycle: - - `python -m app.historical_runner --max-runs 1` -- verify the cycle output includes: - - `player_search_index_result` - - `player_period_stats_result` - - `ranking_snapshot_result` -- confirm the player stats endpoints still report: - - `/api/stats/players/search` -> `source.read_model=player-search-index` - - `/api/stats/players/{player_id}` -> `source.read_model=player-period-stats` -- confirm `/api/ranking` still serves ranking snapshots when ready and preserves fallback behavior when a snapshot is missing -- if emergency rebuild is needed, operators can still run: - - `python -m app.rcon_historical_player_stats refresh-player-search-index` - - `python -m app.rcon_historical_player_stats refresh-player-period-stats` - - `python -m app.rcon_historical_leaderboards refresh-ranking-snapshots --limit 30` - -Pending limitations kept out of scope: - -- the runner still refreshes the player read models for all supported public scopes even when a manual runner execution is limited with `--server` -- this task does not introduce a separate external scheduler or deployment-specific cron wiring -- live HTTP validation at `http://127.0.0.1:8000` was not available in this environment; route-contract validation passed via local Python imports instead - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-202-isolate-runner-read-model-refresh-from-legacy-snapshot-failures.md b/ai/tasks/done/TASK-202-isolate-runner-read-model-refresh-from-legacy-snapshot-failures.md deleted file mode 100644 index 5023a3d..0000000 --- a/ai/tasks/done/TASK-202-isolate-runner-read-model-refresh-from-legacy-snapshot-failures.md +++ /dev/null @@ -1,196 +0,0 @@ ---- -id: TASK-202-isolate-runner-read-model-refresh-from-legacy-snapshot-failures -title: Isolate runner read model refresh from legacy snapshot failures -status: done -type: backend -team: Backend Senior -supporting_teams: - - Arquitecto de Base de Datos - - Arquitecto Python -roadmap_item: foundation -priority: high ---- - -# TASK-202 - Isolate runner read model refresh from legacy snapshot failures - -## Goal - -Prevent legacy historical snapshot failures from blocking the operational PostgreSQL read-model refreshes in the periodic historical runner. - -## Context - -After `TASK-201`, the periodic runner starts correctly and announces the expected hourly scope, but the first cycle aborts before reaching the PostgreSQL operational read models when legacy historical snapshot generation fails with `sqlite3.OperationalError: no such table: player_event_raw_ledger`. - -The current failure path happens inside `generate_historical_snapshots(...)`, which was still executed inside the runner's broader refresh attempt. That legacy failure prevented the cycle from refreshing: - -- `player_search_index` -- `player_period_stats` -- `ranking_snapshots` - -This task isolates the cycle steps so the legacy error stays visible in logs and results, while the operational PostgreSQL refreshes are still attempted in the same cycle. Preserve the current product identity: Spanish-speaking HLL Vietnam community, military/Vietnam/tactical/sober visual direction and controlled repository evolution. - -## Steps - -1. Read the listed files first. -2. Confirm the current runner failure path and where legacy snapshot generation aborts the cycle. -3. Refactor the periodic runner so each refresh step is handled as an isolated unit with a separately reported result. -4. Preserve retries for full-attempt failures where they still apply, but avoid retry-only behavior for a legacy step that should no longer block operational refreshes. -5. Keep the legacy snapshot error visible in logs and cycle results. -6. Ensure the runner still attempts: - - `refresh_player_search_index(...)` - - `refresh_player_period_stats(...)` - - `refresh_ranking_snapshots(...)` - even when `generate_historical_snapshots(...)` fails. -7. Return a global cycle status of `partial` or equivalent when the legacy snapshot step fails but operational steps continue. -8. Keep manual CLIs and public API contracts unchanged. -9. Update operational documentation with the new partial-cycle behavior and production validation guidance. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `backend/app/historical_runner.py` -- `backend/app/historical_snapshots.py` -- `backend/app/historical_storage.py` -- `backend/app/rcon_historical_player_stats.py` -- `backend/app/rcon_historical_leaderboards.py` -- `scripts/run-stats-validation.ps1` -- `docs/player-search-read-model-plan.md` -- `docs/player-period-stats-read-model-plan.md` -- `docs/ranking-snapshot-read-model-plan.md` -- `ai/tasks/done/TASK-201-automate-player-read-model-refresh.md` - -## Expected Files to Modify - -- `backend/app/historical_runner.py` -- `backend/tests/test_historical_snapshot_refresh.py` -- `scripts/run-stats-validation.ps1` -- `docs/player-search-read-model-plan.md` -- `docs/player-period-stats-read-model-plan.md` -- `docs/ranking-snapshot-read-model-plan.md` -- `ai/tasks/done/TASK-202-isolate-runner-read-model-refresh-from-legacy-snapshot-failures.md` - -## Constraints - -- Keep the change minimal and backend/documentation only. -- Do not execute `ai-platform run`. -- Do not modify frontend. -- Do not change design. -- Do not touch images or assets. -- Do not reactivate Elo/MMR. -- Do not reintroduce Comunidad Hispana `#03`. -- Do not fix or migrate `player_event_raw_ledger` in this task unless analysis proves it is strictly necessary. -- Do not create or modify legacy tables unless it becomes strictly necessary and is explicitly justified in the outcome. -- Do not hide legacy errors; they must remain visible in logs and result payloads. -- Do not change manual CLI behavior. -- Do not change public API contracts. - -## Validation - -Before completing the task ensure: - -- `python -m py_compile backend/app/historical_runner.py` -- `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- local/import validation proves that when `generate_historical_snapshots(...)` fails: - - `refresh_player_search_index(...)` is still attempted - - `refresh_player_period_stats(...)` is still attempted - - `refresh_ranking_snapshots(...)` is still attempted - - the global result is `partial` or equivalent - - the legacy error remains reported -- local/import validation proves that when all steps succeed, the cycle still returns `ok` -- local/import validation proves separate result payloads still exist: - - `historical_snapshot_result` - - `player_search_index_result` - - `player_period_stats_result` - - `ranking_snapshot_result` -- `git diff --name-only` matches the expected scope - -## Outcome - -Root cause: - -- `generate_historical_snapshots(...)` still ran inside the runner attempt's broad failure boundary. -- When the legacy monthly MVP V2 snapshot path touched missing `player_event_raw_ledger` state, it raised `OperationalError`. -- That exception aborted the attempt before the PostgreSQL operational read-model refreshes were called. - -Previous behavior: - -- a legacy snapshot failure stopped the cycle before: - - `player_search_index` - - `player_period_stats` - - `ranking_snapshots` -- the cycle returned attempt-level failure instead of a partial operational result -- operators could see the legacy error, but the operational read models stayed stale - -New behavior: - -- `backend/app/historical_runner.py` - - wraps legacy snapshot refresh in an isolated step via `refresh_periodic_historical_snapshots(...)` - - preserves the legacy error in logs and result payloads with: - - `historical_snapshot_result` - - compatibility alias `snapshot_result` - - event `historical-snapshot-refresh-failed` - - continues attempting: - - `player_search_index` - - `player_period_stats` - - `ranking_snapshots` - after a legacy snapshot failure - - resolves the overall cycle to `partial` when the isolated legacy step fails but operational refreshes continue -- `backend/tests/test_historical_snapshot_refresh.py` - - adds coverage for legacy snapshot failure isolation - - adds coverage for the all-success path still returning `ok` -- `scripts/run-stats-validation.ps1` - - validates that a legacy snapshot failure still leaves the operational read-model refresh sequence running - - validates: - - `historical_snapshot_result` - - `player_search_index_result` - - `player_period_stats_result` - - `ranking_snapshot_result` - - validates the global `partial` result and preserved legacy error reporting -- operational docs now explain that the runner can finish `partial` if the legacy block fails while PostgreSQL read-model refreshes still run - -Validations executed: - -- `python -m py_compile backend/app/historical_runner.py` -- `python -m unittest tests.test_historical_snapshot_refresh` -- `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` - -Production validation: - -1. Run one controlled cycle: - - `python -m app.historical_runner --max-runs 1` -2. Inspect the cycle payload and logs for: - - `status` equal to `ok` or `partial` - - `historical_snapshot_result` - - `player_search_index_result` - - `player_period_stats_result` - - `ranking_snapshot_result` -3. If `status=partial`, confirm the legacy failure remains visible under: - - `historical_snapshot_result.error_type` - - `historical_snapshot_result.error` - - `historical_snapshot_result.traceback` -4. Confirm operational timestamps still advance in PostgreSQL for: - - `player_search_index` - - `player_period_stats` - - `ranking_snapshots` -5. Confirm public reads still use the refreshed read models: - - `/api/stats/players/search` - - `/api/stats/players/{player_id}` - - `/api/ranking` - -Scope notes: - -- no frontend files were modified -- no images/assets were touched -- `player_event_raw_ledger` was not fixed or migrated in this task -- manual CLIs were preserved unchanged -- pre-existing unrelated changes in `ai/system-metrics.md` and frontend assets were intentionally left untouched - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-203-public-pages-navigation-and-copy-polish.md b/ai/tasks/done/TASK-203-public-pages-navigation-and-copy-polish.md deleted file mode 100644 index 8f93c55..0000000 --- a/ai/tasks/done/TASK-203-public-pages-navigation-and-copy-polish.md +++ /dev/null @@ -1,139 +0,0 @@ ---- -id: TASK-203 -title: Public pages navigation and copy polish -status: done -type: frontend -team: Frontend Senior -supporting_teams: - - Experto en interfaz -roadmap_item: foundation -priority: medium ---- - -# TASK-203 - Public pages navigation and copy polish - -## Goal - -Reorganizar la navegacion superior y normalizar el layout visual de `index`, `historico`, `stats` y `ranking` para que compartan una navegacion publica coherente, una cabecera visual alineada y textos visibles corregidos en UTF-8. - -## Context - -Las paginas publicas principales ya exponen el producto, pero hoy mezclan botones sueltos dentro del hero, encabezados desalineados y varios textos mal codificados o demasiado tecnicos para usuarios normales. Esta tarea corrige solo la capa visual y de copy en `frontend/`, sin tocar backend, endpoints, logica de datos, Elo/MMR pausado, Comunidad Hispana #03 ni assets/SVGs de armas. - -Preserve the current product identity: Spanish-speaking HLL Vietnam community, military/Vietnam/tactical/sober visual direction and controlled repository evolution. - -## Steps - -1. Inspeccionar el HTML, CSS y JS compartidos de las paginas publicas afectadas. -2. Crear o reutilizar una navegacion superior global para `index`, `historico`, `stats` y `ranking`. -3. Alinear el hero de `stats` y `ranking` con la composicion visual usada por `index` y `historico`. -4. Limpiar botones duplicados dentro del hero y simplificar el copy visible sin cambiar logica de datos. -5. Corregir textos visibles con problemas de codificacion en las paginas afectadas y validar el resultado por inspeccion. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `frontend/index.html` -- `frontend/historico.html` -- `frontend/assets/css/styles.css` - -## Expected Files to Modify - -- `ai/tasks/done/TASK-203-public-pages-navigation-and-copy-polish.md` -- `frontend/index.html` -- `frontend/historico.html` -- `frontend/stats.html` -- `frontend/ranking.html` -- `frontend/assets/css/styles.css` -- `frontend/assets/js/stats.js` -- `frontend/assets/js/ranking.js` - -## Constraints - -- Keep the change minimal. -- Preserve HLL Vietnam project identity. -- Do not introduce unnecessary frameworks or dependencies. -- Do not implement backend functionality unless the task explicitly requires it. -- Do not expand Elo/MMR, historical workers or RCON server #03 handling unless the task explicitly requires it. -- Do not overwrite repository-specific context with generic platform template text. -- No ejecutar `ai-platform run`. -- No modificar `backend/`, scripts de validacion backend, endpoints, logica de datos, assets/SVGs de armas ni siluetas. -- No reactivar Elo/MMR ni reintroducir Comunidad Hispana #03. - -## Validation - -Before completing the task ensure: - -- `index.html`, `historico.html`, `stats.html` y `ranking.html` muestran navegacion superior con acceso a Inicio, Historico, Stats y Ranking -- `index.html` mantiene `Unirse al Discord` dentro del hero -- `stats.html` y `ranking.html` muestran imagen/icono de comunidad en hero -- `stats.html` y `ranking.html` ya no muestran `Backend operativo` -- no aparecen textos mal codificados visibles como `Público`, `Públicos`, `Año`, `AÃo`, `Histórico` -- `ranking.html` ya no muestra `Fuente` en el panel visible de tabla activa -- `git diff --name-only` matches the expected scope -- no unrelated files were modified -- integration tests are run when relevant and configured - -## Outcome - -Archivos modificados: - -- `frontend/index.html` -- `frontend/historico.html` -- `frontend/stats.html` -- `frontend/ranking.html` -- `frontend/assets/css/styles.css` -- `frontend/assets/js/stats.js` -- `frontend/assets/js/ranking.js` -- `ai/tasks/done/TASK-203-public-pages-navigation-and-copy-polish.md` - -Navegacion nueva: - -- Se anadio una navegacion superior comun en las cuatro paginas publicas con acceso directo a Inicio, Historico, Stats y Ranking. -- El estado activo se marca por pagina y la navegacion queda separada del hero como banda superior de tabs tacticos. - -Textos corregidos: - -- Se corrigieron textos visibles relacionados con Historico, publico/publicos, estadisticas, metrica, limite y ano/anual. -- En HTML se usaron entidades para asegurar render correcto en entorno Windows y lectura segura en navegador. -- En JS visible se usaron escapes Unicode donde hacia falta para evitar mojibake. - -Botones movidos: - -- En `index`, `Stats`, `Ranking` y `Ver historico propio` salieron del hero y pasaron a la navegacion global. -- En `historico`, `Volver inicio` y `Stats` se sustituyeron por la navegacion global, y se anadio acceso directo a Ranking. -- En `stats` y `ranking`, los enlaces de retorno cruzado del hero se sustituyeron por la navegacion global. - -Elementos retirados: - -- Se elimino el badge visible de backend en `stats` y `ranking`. -- Se elimino el campo visual `Fuente` del panel visible de metadata en `ranking`. - -Validaciones ejecutadas: - -- Revision por inspeccion de `frontend/index.html`, `frontend/historico.html`, `frontend/stats.html` y `frontend/ranking.html`. -- Verificacion de navegacion superior comun en las cuatro paginas. -- Verificacion de que `Unirse al Discord` permanece en el hero de `index`. -- Verificacion de que `stats` y `ranking` incluyen `logo.png` en el hero. -- Verificacion de que ya no existen `id="stats-backend-state"` ni `id="ranking-backend-state"` en HTML. -- Verificacion de que `ranking.js` ya no genera la tarjeta visible `Fuente`. -- Revision de `git status --short --untracked-files=all` y `git diff --name-only`. -- Confirmacion de que no hay cambios en `backend/` ni en `scripts/`. - -Tests: - -- No se ejecutaron scripts de validacion frontend existentes porque los scripts disponibles no son ligeros para este alcance y uno de ellos (`scripts/run-stats-validation.ps1`) exige el chip `stats-backend-state`, eliminado intencionadamente por esta task. No se modifico ese script por estar fuera de alcance. - -Confirmaciones de alcance: - -- No se tocaron `backend/`, endpoints, logica de datos, scripts backend, Elo/MMR ni Comunidad Hispana #03. -- No se tocaron assets/SVGs de armas. Los cambios ya presentes en `frontend/assets/img/weapons/` y `ai/system-metrics.md` eran previos y se dejaron intactos. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. - diff --git a/ai/tasks/done/TASK-205-fix-annual-ranking-generator-postgres-default.md b/ai/tasks/done/TASK-205-fix-annual-ranking-generator-postgres-default.md deleted file mode 100644 index c7770c9..0000000 --- a/ai/tasks/done/TASK-205-fix-annual-ranking-generator-postgres-default.md +++ /dev/null @@ -1,185 +0,0 @@ ---- -id: TASK-205 -title: Fix annual ranking generator PostgreSQL default -status: done -type: backend -team: Backend Senior -supporting_teams: - - Arquitecto de Base de Datos - - Arquitecto Python -roadmap_item: foundation -priority: high ---- - -# TASK-205 - Fix annual ranking generator PostgreSQL default - -## Goal - -Corregir el CLI anual de `backend/app/rcon_annual_rankings.py` para que use PostgreSQL por defecto cuando `HLL_BACKEND_DATABASE_URL` esta configurado, alineando la generacion operativa con el read path de `/api/ranking?timeframe=annual...`. - -## Context - -Produccion ya confirma que la API anual consulta el read model correcto pero no encuentra snapshot, mientras el comando manual anual generaba en SQLite local. La causa raiz validada era que `_main()` llamaba a `generate_annual_ranking_snapshot(..., db_path=get_storage_path())`, lo que forzaba `explicit_sqlite_path != None` y desactivaba `use_postgres_rcon_storage(...)` aunque `get_database_url()` existiera. - -Este comportamiento ya se habia corregido en weekly/monthly durante `TASK-195`, por lo que esta task replica el mismo criterio operacional en el flujo anual sin tocar frontend, endpoints publicos ni la logica anual fuera de la seleccion de storage por defecto. - -Preserve the current product identity: Spanish-speaking HLL Vietnam community, military/Vietnam/tactical/sober visual direction and controlled repository evolution. - -## Steps - -1. Revisar el flujo anual actual y comparar `_main()` con el patron corregido en weekly/monthly. -2. Cambiar el CLI anual para que use `db_path=None` por defecto y PostgreSQL cuando el entorno lo soporte. -3. Mantener SQLite solo como override explicito mediante `--sqlite-path`. -4. Preservar la salida JSON del CLI y el contrato publico del endpoint anual. -5. Extender la regresion de `scripts/run-stats-validation.ps1` para cubrir la ruta anual. -6. Documentar causa raiz, comportamiento anterior, comportamiento nuevo y validacion operacional. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `backend/app/rcon_annual_rankings.py` -- `backend/app/config.py` -- `backend/app/postgres_rcon_storage.py` -- `backend/app/rcon_historical_leaderboards.py` -- `scripts/run-stats-validation.ps1` -- `docs/ranking-snapshot-read-model-plan.md` -- `docs/annual-ranking-snapshot-runbook.md` -- `docs/annual-ranking-snapshot-schema-plan.md` -- `ai/tasks/done/TASK-195-fix-ranking-snapshot-generator-postgres-default.md` -- `ai/tasks/done/TASK-196-fix-ranking-snapshot-cli-json-serialization.md` - -## Expected Files to Modify - -- `backend/app/rcon_annual_rankings.py` -- `scripts/run-stats-validation.ps1` -- `docs/annual-ranking-snapshot-runbook.md` -- `ai/tasks/done/TASK-205-fix-annual-ranking-generator-postgres-default.md` - -## Constraints - -- Keep the change minimal. -- No ejecutar `ai-platform run`. -- No modificar frontend ni diseno. -- No cambiar el contrato publico de `/api/ranking?timeframe=annual...`. -- No cambiar la logica de calculo anual salvo lo necesario para usar PostgreSQL por defecto. -- No tocar weekly/monthly salvo reutilizacion minima de patron o helper ya existente. -- No tocar `player_search_index`, `player_period_stats` ni el runner. -- No tocar `frontend/assets/img/weapons/` ni SVGs de armas. -- No reactivar Elo/MMR. -- No reintroducir Comunidad Hispana #03. -- No mezclar esta task con los cambios visuales pendientes de `TASK-204`. - -## Validation - -Before completing the task ensure: - -- `python -m py_compile backend/app/rcon_annual_rankings.py` -- `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` -- validacion local o por import demuestra que `_main()` ya no pasa `get_storage_path()` por defecto -- validacion local demuestra que `generate_annual_ranking_snapshot(..., db_path=None)` usa PostgreSQL cuando `HLL_BACKEND_DATABASE_URL` esta configurado -- la salida JSON del CLI anual sigue serializando correctamente -- `git diff --name-only` matches the expected scope - -## Outcome - -Causa raiz: - -- `backend/app/rcon_annual_rankings.py` llamaba a `generate_annual_ranking_snapshot(..., db_path=get_storage_path())` desde `_main()` -- eso forzaba `explicit_sqlite_path != None` -- `use_postgres_rcon_storage(...)` devolvia `False` incluso con `HLL_BACKEND_DATABASE_URL` configurado -- el CLI anual generaba snapshots en SQLite mientras `/api/ranking?timeframe=annual...` leia PostgreSQL - -Comportamiento anterior: - -- `python -m app.rcon_annual_rankings generate ...` -- usaba SQLite por defecto -- podia dejar `rcon_annual_ranking_snapshots` y `rcon_annual_ranking_snapshot_items` vacias en PostgreSQL aunque el operador hubiera ejecutado el comando con exito - -Comportamiento nuevo: - -- el CLI anual usa PostgreSQL por defecto cuando `HLL_BACKEND_DATABASE_URL` esta configurado -- SQLite queda disponible solo mediante `--sqlite-path` -- la salida JSON del CLI anual sigue serializando `datetime` y `date` correctamente - -Archivos modificados: - -- `backend/app/rcon_annual_rankings.py` -- `scripts/run-stats-validation.ps1` -- `docs/annual-ranking-snapshot-runbook.md` -- `ai/tasks/done/TASK-205-fix-annual-ranking-generator-postgres-default.md` - -Cambio aplicado en codigo: - -- `backend/app/rcon_annual_rankings.py` - - elimina el default que forzaba `get_storage_path()` en `_main()` - - anade `--sqlite-path ` como override explicito - - pasa `db_path=args.sqlite_path` al generador anual - - anade serializacion JSON segura para `datetime` y `date` - -Regresion anadida: - -- `scripts/run-stats-validation.ps1` - - valida que el CLI anual use `db_path=None` por defecto - - valida que `--sqlite-path` siga funcionando - - valida por import que `generate_annual_ranking_snapshot(..., db_path=None)` seleccione PostgreSQL cuando `HLL_BACKEND_DATABASE_URL` esta configurado - -Comando operativo final: - -- local / contenedor backend: - - `python -m app.rcon_annual_rankings generate --year 2026 --server-key all-servers --metric kills --limit 30 --replace-existing` - -Comando Docker final recomendado: - -- `docker compose exec backend python -m app.rcon_annual_rankings generate --year 2026 --server-key all-servers --metric kills --limit 30 --replace-existing` - -Validaciones ejecutadas: - -- `python -m py_compile backend/app/rcon_annual_rankings.py` -- validacion local por import de `_main()`: - - confirma `db_path=None` por defecto - - confirma serializacion JSON correcta de `datetime` y `date` -- validacion local por import de `generate_annual_ranking_snapshot(..., db_path=None)`: - - confirma seleccion de PostgreSQL cuando `HLL_BACKEND_DATABASE_URL` esta configurado -- ejecucion manual real del CLI: - - `python -m app.rcon_annual_rankings generate --year 2026 --server-key all-servers --metric kills --limit 30 --replace-existing --sqlite-path data/hll_vietnam_dev.sqlite3` -- validacion local del endpoint anual por import: - - `/api/ranking?timeframe=annual&year=&server_id=all&metric=kills&limit=20` - - mantiene `status=ok`, `timeframe=annual`, `metric=kills`, `snapshot_status`, `items`, `generated_at`, `window_start` y `window_end` - -Resultado de scripts globales: - -- `powershell -ExecutionPolicy Bypass -File scripts/run-stats-validation.ps1` - - falla antes de la nueva regresion anual por una asercion de frontend preexistente: - - `Stats page no longer exposes backend state chip.` -- `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1` - - falla por arrastrar el mismo fallo previo de `run-stats-validation.ps1` - -Nota de alcance sobre esos fallos: - -- la causa no pertenece a esta task backend -- viene del arbol local ya modificado en frontend y de la validacion global que aun espera `id="stats-backend-state"` -- no se corrigio aqui porque el usuario pidio no modificar frontend ni mezclar esta task con `TASK-204` - -Como validar en produccion: - -1. Ejecutar: - - `docker compose exec backend python -m app.rcon_annual_rankings generate --year 2026 --server-key all-servers --metric kills --limit 30 --replace-existing` -2. Consultar PostgreSQL: - - `rcon_annual_ranking_snapshots` - - `rcon_annual_ranking_snapshot_items` -3. Confirmar que ya no se escriben filas nuevas en SQLite por defecto. -4. Llamar a: - - `/api/ranking?timeframe=annual&metric=kills&limit=30&year=2026` -5. Confirmar: - - `snapshot_status=ready` - - `items` no vacio cuando exista cobertura anual - - `read_model = rcon-annual-ranking-snapshot` - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-206-public-frontend-visual-consistency-and-annual-ranking-layout.md b/ai/tasks/done/TASK-206-public-frontend-visual-consistency-and-annual-ranking-layout.md deleted file mode 100644 index 6ddefc6..0000000 --- a/ai/tasks/done/TASK-206-public-frontend-visual-consistency-and-annual-ranking-layout.md +++ /dev/null @@ -1,158 +0,0 @@ ---- -id: TASK-206 -title: Public frontend visual consistency and annual ranking layout -status: done -type: frontend -team: Frontend Senior -supporting_teams: - - Experto en interfaz -roadmap_item: foundation -priority: medium ---- - -# TASK-206 - Public frontend visual consistency and annual ranking layout - -## Goal - -Corregir la segunda pasada visual del frontend publico para unificar definitivamente las cabeceras de `index`, `historico`, `stats` y `ranking`, mejorar la legibilidad del ranking anual y ajustar la presencia visual del logo `BxB` en la seccion de clanes. - -## Context - -Tras `TASK-203` y la task local no commiteada `TASK-204`, el frontend publico sigue mostrando diferencias visibles entre heroes, etiquetas redundantes dentro de cabecera y un bloque anual demasiado compacto en `stats`. Esta tarea se limita a `frontend/` y a su documentacion de task: no toca backend, endpoints, logica de datos, scripts backend, snapshots, Elo/MMR pausado, Comunidad Hispana #03 ni assets/SVGs de armas. - -Preserve the current product identity: Spanish-speaking HLL Vietnam community, military/Vietnam/tactical/sober visual direction and controlled repository evolution. - -## Steps - -1. Confirmar el estado actual del frontend publico y de la task previa local `TASK-204`. -2. Unificar el patron visual del hero tomando `index` como referencia principal y `historico` como referencia secundaria. -3. Eliminar chips o labels de pagina redundantes dentro del hero manteniendo la navegacion superior comun. -4. Rehacer solo la presentacion frontend del Top 20 anual en `stats` para separar claramente posicion, jugador y metricas. -5. Ajustar la presentacion del logo `BxB` en la seccion de clanes sin reemplazar el asset. -6. Validar por inspeccion y documentar outcome, alcance y exclusiones. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `frontend/index.html` -- `frontend/historico.html` -- `frontend/stats.html` -- `frontend/ranking.html` -- `frontend/assets/css/styles.css` -- `frontend/assets/js/stats.js` -- `frontend/assets/js/ranking.js` -- `ai/tasks/done/TASK-203-public-pages-navigation-and-copy-polish.md` - -## Expected Files to Modify - -- `ai/tasks/in-progress/TASK-206-public-frontend-visual-consistency-and-annual-ranking-layout.md` -- `frontend/index.html` -- `frontend/historico.html` -- `frontend/stats.html` -- `frontend/ranking.html` -- `frontend/assets/css/styles.css` -- `frontend/assets/css/hero-header-compact.css` -- `frontend/assets/css/historico.css` -- `frontend/assets/js/stats.js` -- `frontend/assets/js/main.js` - -## Constraints - -- Keep the change minimal. -- Preserve HLL Vietnam project identity. -- Do not introduce unnecessary frameworks or dependencies. -- Do not implement backend functionality unless the task explicitly requires it. -- Do not expand Elo/MMR, historical workers or RCON server #03 handling unless the task explicitly requires it. -- Do not overwrite repository-specific context with generic platform template text. -- No ejecutar `ai-platform run`. -- No modificar backend, endpoints, logica de datos, generacion de snapshots ni scripts backend. -- No tocar `ai/system-metrics.md`. -- No tocar `frontend/assets/img/weapons/`, assets/SVGs de armas ni copias relacionadas. -- No reemplazar ni editar fisicamente imagenes de clanes. -- No reactivar Elo/MMR ni reintroducir Comunidad Hispana #03. - -## Validation - -Before completing the task ensure: - -- `index.html`, `historico.html`, `stats.html` y `ranking.html` mantienen navegacion superior comun con `Inicio`, `Historico`, `Estadisticas` y `Ranking` -- los cuatro hero muestran composicion coherente con logo a la izquierda y bloque textual a la derecha -- desaparecen del hero `Historico propio`, `Seccion Stats`, `Seccion Ranking` y cualquier chip equivalente de pagina -- el logo de comunidad no cambia de tamano de forma notable entre `index`, `historico`, `stats` y `ranking` -- el copy visible mantiene `Busca un jugador por nombre o ID y revisa sus resultados semanales, mensuales y ranking anual.` -- el copy visible mantiene `Consulta los lideres publicos de la comunidad, cambia de periodo y servidor sin salir de la pagina y revisa quien destaca en cada ventana.` -- el Top 20 anual se muestra en columnas o grid legible y el `player_id` no queda pegado al nombre como dato principal -- el logo `BxB` gana presencia visual sin romper responsive -- `git diff --name-only` matches the expected scope -- no unrelated files were modified -- integration tests are run when relevant and configured - -## Outcome - -Archivos modificados: - -- `frontend/index.html` -- `frontend/historico.html` -- `frontend/stats.html` -- `frontend/ranking.html` -- `frontend/assets/css/hero-header-compact.css` -- `frontend/assets/css/historico.css` -- `frontend/assets/css/styles.css` -- `frontend/assets/js/main.js` -- `frontend/assets/js/stats.js` -- `ai/tasks/in-progress/TASK-206-public-frontend-visual-consistency-and-annual-ranking-layout.md` - -Hero unificado: - -- Se marco `index`, `historico`, `stats` y `ranking` como `hero--public-page` para dejar explicita la variante publica comun. -- `hero-header-compact.css` quedo restringido a ese patron comun y `historico.css` se alineo con la misma escala de padding, gap, logo y copy. -- `historico` dejo de usar una separacion mas amplia y un logo base mas pequeno que el resto; ahora mantiene una proporcion equivalente a `index`, `stats` y `ranking`. -- `stats` y `ranking` conservan logo a la izquierda y bloque textual a la derecha con la misma composicion visual base del hero publico. - -Chips eliminados del hero: - -- `Historico propio` -- `Seccion Stats` -- `Seccion Ranking` - -Ranking anual: - -- El Top 20 anual de `stats` paso de lista compacta apilada a una tabla legible con columnas `Posicion`, `Jugador`, `Valor / Kills`, `Partidas`, `Muertes`, `Teamkills` y `K/D`. -- El `player_id` se mantiene como dato secundario visual en una segunda linea bajo el nombre, en vez de aparecer pegado al jugador. -- El bloque superior del ranking anual se suavizo con copy menos tecnico y metadatos presentados en tarjetas (`Servidor`, `Año`, `Lectura`, `Partidas base`, `Actualizado`). -- No se tocaron endpoint ni contrato API; solo se cambio la presentacion generada por `stats.js` y su CSS asociado. - -Clanes / BxB: - -- `BxB` recibio una variante visual especifica de tarjeta y logo (`clan-card--bxb`, `clan-card__logo--bxb`) para ganar presencia sin reemplazar la imagen ni alterar el asset original. -- El ajuste se hizo en layout y CSS, manteniendo la coherencia general de la grilla de clanes y sin romper responsive. - -Textos y navegacion: - -- La navegacion superior comun queda en `Inicio`, `Historico`, `Estadisticas` y `Ranking`. -- Se mantuvo el copy principal pedido en `stats` y `ranking`. -- Se corrigieron textos visibles de apoyo en `main.js` como `Historico`, `Region`, `Informacion`, `Ultimo snapshot` y `Proximamente`. - -Validaciones ejecutadas: - -- `git status --short --untracked-files=all` ejecutado antes de modificar. -- Confirmacion de que `TASK-204-align-public-page-heroes-and-navigation-labels.md` existe en disco pero sigue `untracked`; no estaba commiteada. -- Confirmacion previa de cambios no relacionados en `ai/system-metrics.md` y en `frontend/assets/img/weapons/` / SVGs de armas; no se tocaron. -- Lectura previa de `AGENTS.md`, `ai/repo-context.md`, `ai/architecture-index.md`, task previa relevante, HTML/CSS/JS del frontend publico y seccion de clanes. -- Revision de `git diff --name-only` para comprobar alcance restringido a frontend publico y task. -- Inspeccion visual con capturas headless de Edge sobre `frontend/index.html`, `frontend/historico.html`, `frontend/stats.html` y `frontend/ranking.html` para verificar navegacion y coherencia del hero. -- Validacion estructural de la nueva tabla anual por inspeccion del HTML/JS/CSS renderizado. La vista con datos reales no pudo comprobarse visualmente porque el backend no estaba disponible en la validacion local. - -Confirmaciones de alcance: - -- No se tocaron `backend/`, endpoints, logica de datos, snapshots ni scripts backend. -- No se tocaron `ai/system-metrics.md`, `frontend/assets/img/weapons/` ni los SVGs de armas con cambios previos. -- No se reactivo Elo/MMR ni se reintrodujo Comunidad Hispana #03. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-207-annual-ranking-default-load-and-kpm-columns.md b/ai/tasks/done/TASK-207-annual-ranking-default-load-and-kpm-columns.md deleted file mode 100644 index e0b7e60..0000000 --- a/ai/tasks/done/TASK-207-annual-ranking-default-load-and-kpm-columns.md +++ /dev/null @@ -1,171 +0,0 @@ ---- -id: TASK-207 -title: Annual ranking default load and KPM columns -status: done -type: frontend -team: Frontend Senior -supporting_teams: - - Experto en interfaz -roadmap_item: foundation -priority: medium ---- - -# TASK-207 - Annual ranking default load and KPM columns - -## Goal - -Ajustar el ranking anual publico en `stats` para que muestre la temporada fija 2026 con carga automatica inicial y anadir la columna `KPM` en los listados publicos multi-registro donde existan datos suficientes sin tocar backend ni endpoints. - -## Context - -Tras `TASK-206`, la presentacion publica del frontend ya es consistente, pero el bloque anual de `stats` sigue requiriendo seleccion manual de anio y una accion extra para cargar un ranking que ahora debe mostrarse como lectura fija de temporada. Ademas, las tablas publicas con varios jugadores no muestran de forma uniforme `KPM` aunque ya existen datos o pueden derivarse desde `kills` y `matches_considered`. - -Preserve the current product identity: Spanish-speaking HLL Vietnam community, military/Vietnam/tactical/sober visual direction and controlled repository evolution. - -## Steps - -1. Crear la task y moverla a `ai/tasks/in-progress`. -2. Fijar el ranking anual de `stats` a la temporada 2026 sin selector editable de anio ni boton obligatorio de carga. -3. Cargar automaticamente el ranking anual al abrir `stats.html`, manteniendo estados de carga y error controlados. -4. Cambiar la tabla anual para mostrar `Kills` y anadir `KPM`, usando `kills_per_match` cuando exista o calculandolo desde `kills / matches_considered`. -5. Revisar `ranking.html` y `historico.html` para unificar la etiqueta visual a `KPM` y anadir la columna donde aplique sin duplicarla. -6. Validar por inspeccion, revisar `git diff --name-only`, documentar exclusiones y mover la task a `ai/tasks/done` al terminar. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `frontend/stats.html` -- `frontend/ranking.html` -- `frontend/historico.html` -- `frontend/assets/js/stats.js` -- `frontend/assets/js/ranking.js` -- `frontend/assets/js/historico.js` -- `frontend/assets/css/styles.css` -- `ai/tasks/done/TASK-206-public-frontend-visual-consistency-and-annual-ranking-layout.md` - -## Expected Files to Modify - -- `ai/tasks/done/TASK-207-annual-ranking-default-load-and-kpm-columns.md` -- `frontend/stats.html` -- `frontend/ranking.html` -- `frontend/historico.html` -- `frontend/assets/js/stats.js` -- `frontend/assets/js/ranking.js` -- `frontend/assets/js/historico.js` -- `frontend/assets/css/styles.css` - -## Constraints - -- Keep the change minimal. -- Preserve HLL Vietnam project identity. -- Do not introduce unnecessary frameworks or dependencies. -- Do not implement backend functionality unless the task explicitly requires it. -- Do not expand Elo/MMR, historical workers or RCON server #03 handling unless the task explicitly requires it. -- Do not overwrite repository-specific context with generic platform template text. -- No ejecutar `ai-platform run`. -- No modificar `backend/`, endpoints, logica de datos, generacion de snapshots ni scripts backend. -- No tocar `ai/system-metrics.md`. -- No tocar `frontend/assets/img/weapons/`, assets/SVGs de armas ni copias relacionadas. -- No reactivar Elo/MMR ni reintroducir Comunidad Hispana #03. - -## Validation - -Before completing the task ensure: - -- `stats.html` no muestra selector editable de anio para el ranking anual -- `stats.html` muestra de forma simple la temporada fija 2026 -- el ranking anual se carga automaticamente al abrir la pagina -- ya no hace falta pulsar un boton para la carga inicial del ranking anual -- la tabla anual muestra `Kills` y `KPM` y ya no muestra `Valor / Kills` -- `KPM` usa `kills_per_match` si existe o `kills / matches_considered` con 2 decimales cuando haya datos suficientes -- `ranking.html` usa la etiqueta visual `KPM` sin duplicar columnas -- `historico.html` y `stats.html` solo muestran `KPM` adicional donde aplique por datos disponibles -- `git diff --name-only` matches the expected scope -- no unrelated files were modified -- integration tests are run when relevant and configured - -## Outcome - -Archivos modificados: - -- `frontend/stats.html` -- `frontend/ranking.html` -- `frontend/historico.html` -- `frontend/assets/js/stats.js` -- `frontend/assets/js/ranking.js` -- `frontend/assets/js/historico.js` -- `frontend/assets/js/historico-partida.js` -- `frontend/assets/js/main.js` -- `frontend/assets/css/styles.css` -- `frontend/assets/css/historico-scoreboard-detail.css` -- `ai/tasks/in-progress/TASK-207-annual-ranking-default-load-and-kpm-columns.md` - -Temporada anual fija: - -- Se elimino el selector editable de anio y cualquier control de carga manual del bloque anual en `stats`. -- La interfaz muestra la temporada fija con un bloque visual simple `Temporada 2026`. -- El titulo del bloque anual queda orientado a la lectura fija: `Top 20 temporada 2026`. - -Carga automatica del ranking anual: - -- `stats.js` deja de leer un input de anio y fija `annualDefaultYear = 2026`. -- Tras confirmar `health`, la pagina dispara automaticamente la carga del ranking anual usando `year=2026`, `metric=kills`, `limit=20` y `server_id=all`. -- Se mantienen mensajes de carga, vacio y error controlados; ya no hace falta pulsar `Cargar ranking anual`. - -KPM anadido y unificado: - -- `stats` anual ahora muestra columnas `Posicion`, `Jugador`, `Kills`, `Partidas`, `KPM`, `Muertes`, `Teamkills` y `K/D`. -- `ranking.html` cambia la etiqueta visual de `kills_per_match` a `KPM` tanto en el selector como en la tabla. -- `ranking.js` evita duplicar `KPM` cuando la metrica activa ya es `kills_per_match`, ocultando la columna secundaria en ese caso. -- `historico.html` y `historico.js` anaden una columna `KPM` al ranking multi-registro; si no hay datos suficientes se muestra `-`. - -Busqueda de jugador endurecida: - -- `stats` ahora exige un minimo de 4 caracteres utiles antes de permitir la busqueda. -- El boton `Buscar jugador` queda deshabilitado hasta cumplir el minimo y la validacion tambien se aplica al pulsar o enviar con Enter. -- Si el texto no alcanza el minimo, el frontend muestra `Introduce al menos 4 caracteres para buscar un jugador.` y no lanza la llamada a `/api/stats/players/search`. - -Logos de clanes ampliados: - -- Se aumento la presencia visual general de los logos de la seccion de clanes mediante layout y CSS, sin tocar imagenes. -- `BxB` recibe un ajuste especifico adicional para que deje de verse pequeno dentro de su tarjeta. -- El ajuste mantiene responsive y no reemplaza assets. - -Brands en botones externos: - -- El detalle de jugador dentro de `historico-partida` ahora usa los logos disponibles en `frontend/assets/img/brands/` para `Hellor`, `HLL Records` y `Helo`. -- `Steam` conserva boton solo con texto porque no existe logo brand disponible en esa carpeta. -- Los enlaces actuales no cambian; solo se enriquece su presentacion visual con logos decorativos cuando hay asset. - -Calculo de KPM: - -- Si el backend ya entrega `kills_per_match`, el frontend usa ese valor. -- Si no existe `kills_per_match` y hay `kills` mas `matches_considered`, el frontend calcula `kills / matches_considered`. -- Si faltan datos o `matches_considered <= 0`, el frontend muestra `-`. -- La comprobacion pedida `1222 / 32` da `38.19`. - -Validaciones realizadas: - -- `git status --short --untracked-files=all` ejecutado antes de modificar. -- Confirmacion previa de cambios no relacionados en `ai/system-metrics.md` y en assets/SVGs de armas; no se tocaron. -- Lectura previa de `AGENTS.md`, `ai/repo-context.md`, `ai/architecture-index.md`, `frontend/stats.html`, `frontend/ranking.html`, `frontend/historico.html`, `frontend/assets/js/stats.js`, `frontend/assets/js/ranking.js`, `frontend/assets/js/historico.js`, `frontend/assets/css/styles.css` y `TASK-206`. -- Lectura adicional para esta ampliacion de `frontend/historico-partida.html`, `frontend/assets/js/historico-partida.js`, `frontend/assets/js/main.js`, `frontend/assets/css/historico-scoreboard-detail.css`, rutas existentes en `frontend/assets/img/brands/` y rutas existentes de la seccion de clanes. -- Parseo sintactico local con `node --check frontend/assets/js/stats.js`, `node --check frontend/assets/js/historico.js`, `node --check frontend/assets/js/ranking.js` y `node --check frontend/assets/js/historico-partida.js`. -- Verificacion especifica por inspeccion del minimo de 4 caracteres, de la presencia de logos de clan ampliados y de la asignacion de brands a botones externos sin rutas rotas. -- Verificacion por inspeccion de presencia/eliminacion de textos y columnas clave con `rg`. -- Revision de `git diff --name-only` filtrado a los archivos esperados para confirmar alcance acotado. -- No existe una validacion frontend automatizada configurada para este alcance; la validacion queda documentada por inspeccion y parseo local. - -Confirmaciones de alcance: - -- No se tocaron `backend/`, endpoints, logica de datos, snapshots ni scripts backend. -- No se tocaron `ai/system-metrics.md`, `frontend/assets/img/weapons/` ni SVGs de armas. -- No se reactivo Elo/MMR ni se reintrodujo Comunidad Hispana #03. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-208-analyze-weapon-icons-black-folder-mapping.md b/ai/tasks/done/TASK-208-analyze-weapon-icons-black-folder-mapping.md deleted file mode 100644 index 420b9b7..0000000 --- a/ai/tasks/done/TASK-208-analyze-weapon-icons-black-folder-mapping.md +++ /dev/null @@ -1,123 +0,0 @@ ---- -id: TASK-208 -title: Analyze weapon icons black folder mapping -status: done -type: research -team: Analista -supporting_teams: [Frontend Senior] -roadmap_item: foundation -priority: medium ---- - -# TASK-208 - Analyze weapon icons black folder mapping - -## Goal - -Build a reviewable mapping between the pasted RCON weapon universe and the SVG silhouettes currently present in `frontend/assets/img/weapons/black/`, without modifying SVG files or frontend behavior yet. - -## Context - -The repository already contains a large local set of black weapon silhouettes and an older partial frontend mapping in `frontend/assets/js/partida-actual.js`. Before implementing a new operational resolver, the project needs a full documentary matrix that: - -- uses the pasted RCON source as truth for weapon names -- lists every current `black` SVG -- assigns every unique RCON weapon to an icon -- makes every `black` icon appear in the inverse table -- flags fallbacks and doubtful assignments explicitly - -This task is analysis/documentation only. No backend, endpoint, JS runtime, image or SVG changes are allowed. - -## Steps - -1. Inspect the repository context, current weapon icon folder and current frontend alias mapping. -2. Consolidate the pasted RCON weapon lists into one unique weapon universe. -3. Cross-map that universe against the local `black` icon set and document exact/shared/fallback assignments. -4. Validate that no RCON weapon is left without an icon and no `black` icon is left out of the inverse table. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `ai/orchestrator/analyst.md` -- `frontend/assets/js/partida-actual.js` -- `frontend/assets/img/weapons/black/` - -## Expected Files to Modify - -- `docs/weapon-icon-black-mapping-analysis.md` -- `ai/tasks/done/TASK-208-analyze-weapon-icons-black-folder-mapping.md` - -## Constraints - -- Do not modify SVGs. -- Do not rename, delete or replace image files. -- Do not touch backend code, endpoints or scripts. -- Do not touch `ai/system-metrics.md`. -- Do not push. -- Keep the result documentary and reviewable. - -## Validation - -Before completing the task ensure: - -- all unique RCON weapons have an assigned icon in the document -- all `frontend/assets/img/weapons/black/` SVGs appear in the inverse table -- `git diff --name-only` matches the expected scope -- `git status --short --untracked-files=all` confirms no SVGs were edited by this task - -## Outcome - -Files read: - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `ai/orchestrator/analyst.md` -- `frontend/assets/js/partida-actual.js` -- `frontend/assets/img/weapons/black/` -- `ai/tasks/done/TASK-159-current-match-feed-rollback-and-weapon-icons.md` -- `ai/tasks/done/TASK-135-fix-rcon-match-detail-faction-assets.md` -- pasted RCON source provided by the user - -Result: - -- Created `docs/weapon-icon-black-mapping-analysis.md`. -- Consolidated `220` unique RCON weapon names including `UNKNOWN`. -- Listed and mapped `123` current SVGs from `frontend/assets/img/weapons/black/`. -- Produced a full direct/shared/fallback matrix with no unmapped weapon and no omitted icon in the inverse table. - -Key findings: - -- `frontend/assets/js/partida-actual.js` only covers a subset of infantry weapons and uses several legacy filename forms such as `browing_m1919`, `flammenwefer41`, `m1_carabine`, `mosing_nagant_*`, `panzerchreck` and `sten_mk_v`. -- Several RCON entries need fallback handling because there is no exact silhouette in the current folder, especially `Daimler`, `GAZ-67`, `MOLOTOV`, `No.77`, towed howitzers and `UNKNOWN`. -- `lee_enfield_jungle_carbine_black.svg` and `rifle_no5_mk_i_black.svg` are identical by file hash and were documented separately because both names still matter at the RCON layer. - -Validation performed: - -- `git status --short --untracked-files=all` before work and at the end -- `git diff --name-only` -- programmatic validation inside the document generator that: - - total unique weapons = `220` - - total icons = `123` - - mapped weapons = `220` - - used icons = `123` - - unused icons = `0` - - missing weapons = `0` -- final generated counts: - - direct assignments = `73` - - shared assignments = `92` - - fallback assignments = `55` - - doubtful assignments (`confidence=low`) = `38` - - shared icons = `46` - -Scope confirmation: - -- No SVG was modified. -- No backend file was touched. -- No push was made. - -## Change Budget - -- Modified files: 2 -- This task stayed in documentation scope and did not expand into frontend implementation. diff --git a/ai/tasks/done/TASK-209-implement-rcon-weapon-icon-alias-mapping.md b/ai/tasks/done/TASK-209-implement-rcon-weapon-icon-alias-mapping.md deleted file mode 100644 index 7155298..0000000 --- a/ai/tasks/done/TASK-209-implement-rcon-weapon-icon-alias-mapping.md +++ /dev/null @@ -1,131 +0,0 @@ ---- -id: TASK-209 -title: Implement RCON weapon icon alias mapping -status: done -type: frontend -team: Frontend Senior -supporting_teams: [Analista] -roadmap_item: foundation -priority: high ---- - -# TASK-209 - Implement RCON weapon icon alias mapping - -## Goal - -Implement the full RCON weapon-to-icon mapping in frontend JavaScript using explicit aliases and the `frontend/assets/img/weapons/black/` icon set, without modifying SVG files. - -## Context - -`TASK-208` produced the reviewable mapping matrix between the pasted RCON weapon universe and the local `black` silhouettes. The runtime still uses an older partial `white/` mapping in `frontend/assets/js/partida-actual.js`, with legacy filenames and incomplete coverage. - -This task applies the documented mapping in frontend code only: - -- cover the 220 documented RCON weapons plus `UNKNOWN` -- use actual `black` SVG filenames -- preserve legacy/ambiguous cases through explicit aliases -- keep SVG files untouched - -## Steps - -1. Inspect the analysis document, current runtime resolver and actual `black` icon filenames. -2. Replace the partial runtime weapon mapping with the documented full alias mapping. -3. Add local validation that checks mapping coverage and that assigned icon filenames exist in `frontend/assets/img/weapons/black/`. -4. Update documentation with implementation notes and validation results. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `docs/weapon-icon-black-mapping-analysis.md` -- `ai/tasks/done/TASK-208-analyze-weapon-icons-black-folder-mapping.md` -- `frontend/assets/js/partida-actual.js` - -## Expected Files to Modify - -- `frontend/assets/js/current-match-weapon-icons.js` -- `frontend/assets/js/partida-actual.js` -- `frontend/partida-actual.html` -- `docs/weapon-icon-black-mapping-analysis.md` -- `ai/tasks/done/TASK-209-implement-rcon-weapon-icon-alias-mapping.md` - -## Constraints - -- Do not modify, rename, delete, replace or move SVG files. -- Do not touch backend code, endpoints or scripts. -- Do not touch `ai/system-metrics.md`. -- Do not push. -- Keep aliases explicit and reviewable. -- Use existing `black` filenames even when they are legacy or inconsistent. - -## Validation - -Before completing the task ensure: - -- `node --check frontend/assets/js/partida-actual.js` -- a local script confirms all documented RCON names resolve to an existing `black` SVG or to the documented fallback UI path -- `git diff --name-only` matches the expected scope -- `git status --short --untracked-files=all` confirms no SVGs were modified by this task - -## Outcome - -Document: - -- the JS file modified -- alias strategy used -- number of covered weapons -- implemented fallback cases -- validation results -- confirmation that no SVG or backend file was touched - -Result: - -- Added `frontend/assets/js/current-match-weapon-icons.js` with: - - `123` real `black` filenames - - `220` explicit RCON `weapon -> svg` entries - - `120` legacy/colloquial aliases for runtime lookup -- Updated `frontend/partida-actual.html` to load the new runtime mapping before `partida-actual.js`. -- Updated `frontend/assets/js/partida-actual.js` so killfeed weapon resolution now prefers the complete `black` runtime mapping and falls back to the old local resolver only if the new asset is unavailable. -- Updated `docs/weapon-icon-black-mapping-analysis.md` with an `Implementación aplicada` section. - -Validation performed: - -- PASS: `node --check frontend/assets/js/partida-actual.js` -- PASS: `node --check frontend/assets/js/current-match-weapon-icons.js` -- PASS: local Node validation against the analysis document and runtime mapping: - - `totalWeapons = 220` - - `mappedWeapons = 220` - - `totalIcons = 123` - - `usedIcons = 123` - - `aliasCount = 120` - - `missingWeapons = 0` - - `brokenIcons = 0` - - `missingAliases = 0` - - `unusedIcons = 0` -- PASS: reviewed `git diff --name-only` -- PASS: reviewed `git status --short --untracked-files=all` - -Main implemented fallbacks: - -- `UNKNOWN -> precision_strike_black.svg` -- `MOLOTOV -> rg42_grenade_black.svg` -- `No.77 -> no82_grenade_black.svg` -- `Daimler` and `QF 2-POUNDER [Daimler]` / `COAXIAL BESA [Daimler] -> m8_greyhound_black.svg` -- `GAZ-67 -> jeep_black.svg` -- `122MM HOWITZER [M1938 (M-30)] -> zis2_57mm_cannon_black.svg` -- `155MM HOWITZER [M114] -> m1_57mm_cannon_black.svg` -- `150MM HOWITZER [sFH 18] -> pak_40_75mm_black.svg` -- `FLAMETHROWER -> m2_flamethrower_black.svg` -- `FairbairnSykes -> m3_knife_black.svg` - -Scope confirmation: - -- No SVG was modified, renamed, deleted or replaced. -- No backend file, endpoint or backend script was touched. -- No push was made. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Split follow-up cleanups, visual tuning or future icon creation into separate tasks. diff --git a/ai/tasks/done/TASK-210-increase-clan-logo-visual-size.md b/ai/tasks/done/TASK-210-increase-clan-logo-visual-size.md deleted file mode 100644 index 0547aa9..0000000 --- a/ai/tasks/done/TASK-210-increase-clan-logo-visual-size.md +++ /dev/null @@ -1,134 +0,0 @@ ---- -id: TASK-210 -title: Increase clan logo visual size -status: done -type: frontend -team: Frontend Senior -supporting_teams: - - Experto en interfaz -roadmap_item: foundation -priority: medium ---- - -# TASK-210 - Increase clan logo visual size - -## Goal - -Corregir la presencia visual de los logos de clanes en la landing publica para que ganen tamano perceptible de forma clara, con un refuerzo especifico para `BxB`, sin tocar imagenes fisicas, backend, endpoints ni logica de datos. - -## Context - -La seccion de clanes en `frontend/index.html` ya recibe clases especificas desde `frontend/assets/js/main.js`, incluyendo `clan-card__logo--bxb` y `clan-card--bxb`. Tambien existen reglas CSS en `frontend/assets/css/styles.css`, pero el ajuste anterior es demasiado conservador y el usuario sigue percibiendo `BxB` casi igual que antes. - -El cambio debe concentrarse en el layout visual y el tratamiento CSS del contenedor/logo para aumentar la presencia de todos los clanes y dar a `BxB` un area claramente mayor, manteniendo el tono sobrio/militar del proyecto y el comportamiento responsive. - -Preserve the current product identity: Spanish-speaking HLL Vietnam community, military/Vietnam/tactical/sober visual direction and controlled repository evolution. - -## Steps - -1. Ejecutar `git status --short --untracked-files=all` antes de modificar y confirmar que los cambios previos en `ai/system-metrics.md` y en los SVGs/assets de armas no forman parte de esta task. -2. Revisar los archivos listados en `Files to Read First`, con foco en la estructura de la seccion de clanes y en las reglas actuales de `.clan-card__logo`, `.clan-card--bxb .clan-card__brand`, `.clan-card__logo--bxb` y `.clan-card__logo--bxb img`. -3. Aumentar el tamano visual base del bloque de logo de clanes y reducir padding interno cuando limite el crecimiento real del PNG. -4. Reforzar `BxB` con una caja visual notablemente mayor que el resto, ampliando ancho/alto disponible y, si hace falta, aplicando un ajuste mas agresivo sobre `.clan-card__logo--bxb img` para compensar transparencia interna del PNG. -5. Mantener el equilibrio visual de la tarjeta para que el texto no quede aplastado ni se rompa la composicion en movil. -6. Validar por inspeccion visual, revisar `git diff --name-only`, documentar reglas cambiadas, tamanos anteriores vs nuevos y mover la task a `ai/tasks/done` al terminar. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `frontend/index.html` -- `frontend/assets/js/main.js` -- `frontend/assets/css/styles.css` -- `ai/tasks/done/TASK-207-annual-ranking-default-load-and-kpm-columns.md` - -## Expected Files to Modify - -- `ai/tasks/in-progress/TASK-210-increase-clan-logo-visual-size.md` -- `frontend/assets/css/styles.css` - -Optional only if strictly necessary: - -- `frontend/assets/js/main.js` - -## Constraints - -- Keep the change minimal. -- Preserve HLL Vietnam project identity. -- Do not introduce unnecessary frameworks or dependencies. -- Do not implement backend functionality unless the task explicitly requires it. -- Do not expand Elo/MMR, historical workers or RCON server #03 handling unless the task explicitly requires it. -- Do not overwrite repository-specific context with generic platform template text. -- No ejecutar `ai-platform run`. -- No modificar `backend/`, endpoints, logica de datos ni scripts backend. -- No tocar `ai/system-metrics.md`. -- No tocar `frontend/assets/img/weapons/`, SVGs de armas ni copias relacionadas. -- No modificar imagenes fisicas de clanes ni reemplazar PNGs. -- No reactivar Elo/MMR ni reintroducir Comunidad Hispana #03. -- Mantener compatibilidad con apertura directa en navegador y comportamiento responsive. - -## Validation - -Before completing the task ensure: - -- `git status --short --untracked-files=all` fue ejecutado antes de modificar -- se confirmo que los cambios previos en `ai/system-metrics.md` y en assets/SVGs de armas eran no relacionados y no se tocaron -- la caja visual base del logo de clanes subio aproximadamente a `150-170px` de alto visual o equivalente perceptible -- `BxB` dispone de un area notablemente mayor, aproximadamente `220-260px` de ancho disponible y `170-200px` de alto visual o equivalente perceptible -- las reglas CSS fuerzan mejor aprovechamiento del espacio disponible con `width`, `height`, `max-width`, `max-height` y `object-fit: contain` cuando convenga -- `BxB` se ve claramente mas grande que antes por inspeccion -- el resto de clanes tambien gana presencia visual por inspeccion -- el texto de las tarjetas no queda aplastado ni roto de forma fea -- responsive no rompe en movil por inspeccion -- `backend/`, scripts backend, `frontend/assets/img/weapons/` y SVGs de armas no fueron modificados -- `node --check frontend/assets/js/main.js` solo se ejecuta si se toca JS -- si solo se toca CSS, la validacion queda documentada como validacion visual -- `git diff --name-only` matches the expected scope -- no unrelated files were modified - -## Outcome - -Documentar: - -- Reglas CSS cambiadas: - - `.clan-card__brand` - - `.clan-card__logo` - - `.clan-card__logo--standard` - - `.clan-card__logo--wide` - - `.clan-card__logo--shield` - - `.clan-card--bxb .clan-card__brand` - - `.clan-card__logo--bxb` - - `.clan-card__logo img` - - `.clan-card__logo--wide img` - - `.clan-card__logo--shield img` - - `.clan-card__logo--bxb img` -- Tamano anterior vs nuevo: - - base `.clan-card__brand`: `124-154px` a `156-176px` - - base `.clan-card__logo`: `124px` a `160px` - - base `img max-height`: `108px` a `144px` - - `BxB` columna: `146-184px` a `232-268px` - - `BxB` logo: `148px` a `204px` - - `BxB img max-height`: `132px` a `196px` -- Tratamiento especifico de `BxB`: - - se amplio de forma agresiva la columna visual - - se redujo el padding interno a `4px` - - el `img` usa `width: 100%`, `height: 100%`, `max-width: 100%`, `max-height: 196px` y `object-fit: contain` para compensar mejor el aire interno del PNG -- Validacion realizada: - - `git status --short --untracked-files=all` ejecutado antes de cerrar la task - - `git diff -- frontend/assets/css/styles.css` revisado antes del commit - - validacion visual por inspeccion en desktop y movil sobre la seccion de clanes - - confirmacion de que `BxB` gana una caja notablemente mayor y el resto de logos tambien gana presencia - - confirmacion de que no fue necesario tocar `frontend/assets/js/main.js` -- Confirmaciones de alcance: - - no se modificaron imagenes fisicas de clanes - - no se tocaron `frontend/assets/img/weapons/` ni SVGs de armas - - no se tocaron `backend/`, endpoints, logica de datos ni scripts backend - - no se toco `ai/system-metrics.md` - - commit aplicado: `Increase clan logo visual size` - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-211-optimize-annual-ranking-read-path.md b/ai/tasks/done/TASK-211-optimize-annual-ranking-read-path.md deleted file mode 100644 index bb8c300..0000000 --- a/ai/tasks/done/TASK-211-optimize-annual-ranking-read-path.md +++ /dev/null @@ -1,220 +0,0 @@ ---- -id: TASK-211 -title: Optimize annual ranking read path -status: done -type: backend -team: Backend Senior -supporting_teams: - - Arquitecto Python -roadmap_item: foundation -priority: medium ---- - -# TASK-211 - Optimize annual ranking read path - -## Goal - -Optimizar la ruta publica de lectura del ranking anual para que lea exclusivamente los snapshots anuales ya materializados, evitando inicializacion, migracion o setup de storage en cada request publico y reduciendo la latencia del cold/read path sin tocar frontend. - -## Context - -El endpoint publico anual `/api/ranking?timeframe=annual&metric=kills&limit=30&year=2026` ha llegado a tardar 24-42 segundos en produccion. Sin embargo, las mediciones disponibles descartan a PostgreSQL como cuello de botella: - -- `EXPLAIN ANALYZE` sobre `rcon_annual_ranking_snapshots` tarda ~`0.073 ms` -- `EXPLAIN ANALYZE` sobre `rcon_annual_ranking_snapshot_items` tarda ~`0.083 ms` -- `cProfile` directo posterior de `build_global_ranking_payload(... annual ...)` tarda ~`0.244 s` -- weekly ranking tarda ~`0.055 s` -- player search tarda ~`0.069 s` -- player profile tarda ~`0.136 s` - -El hallazgo actual es que `backend/app/rcon_annual_rankings.py` llama a `initialize_rcon_materialized_storage(db_path=db_path)` al inicio de `get_annual_ranking_snapshot()`, incluso cuando la request publica solo necesita leer snapshots anuales ya calculados. Esta task debe separar con claridad la ruta de generacion/escritura anual de la ruta publica de lectura anual. - -Preserve the current product identity: Spanish-speaking HLL Vietnam community, military/Vietnam/tactical/sober visual direction and controlled repository evolution. - -## Steps - -1. Revisar primero la ruta actual de lectura anual en `backend/app/rcon_annual_rankings.py` y el ensamblado de payloads en `backend/app/payloads.py`. -2. Identificar exactamente donde la lectura publica annual entra en setup o inicializacion innecesaria y separar esa responsabilidad de la generacion/escritura anual. -3. Hacer que la lectura publica anual use solo conexion de lectura y consultas sobre: - - `rcon_annual_ranking_snapshots` - - `rcon_annual_ranking_snapshot_items` -4. Evitar `initialize_rcon_materialized_storage()` dentro de `get_annual_ranking_snapshot()` salvo que exista un modo SQLite legacy explicito con `--sqlite-path`. -5. Mantener PostgreSQL como ruta operativa por defecto y conservar compatibilidad con SQLite solo como modo legacy explicito, sin migracion/setup durante la lectura publica. -6. Revisar `build_annual_ranking_snapshot_payload()` y `build_global_ranking_payload()` para asegurar que la lectura annual publica sigue devolviendo el contrato correcto sin fallback runtime. -7. Ejecutar la validacion funcional y de tiempos pedida, documentar antes/despues y anadir un test pequeno si el stack lo permite para blindar que la ruta PostgreSQL de lectura no inicializa storage. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `backend/app/rcon_annual_rankings.py` -- `backend/app/payloads.py` -- `ai/tasks/done/TASK-188-audit-ranking-and-stats-query-performance.md` - -## Expected Files to Modify - -- `ai/tasks/in-progress/TASK-211-optimize-annual-ranking-read-path.md` -- `backend/app/rcon_annual_rankings.py` -- `backend/app/payloads.py` - -Optional only if strictly necessary: - -- backend unit test file related to annual rankings or payloads - -## Constraints - -- Keep the change minimal. -- Preserve HLL Vietnam project identity. -- Do not introduce unnecessary frameworks or dependencies. -- Do not overwrite repository-specific context with generic platform template text. -- No ejecutar `ai-platform run`. -- No tocar `frontend/`. -- No tocar assets de armas ni SVGs. -- No reactivar Elo/MMR. -- No reintroducir Comunidad Hispana #03. -- No consultar RCON, scoreboard publico ni recalcular ranking dentro de la lectura publica annual. -- No escanear `rcon_match_player_stats` en la ruta publica annual. -- No hacer N+1 por jugador en la ruta publica annual. -- Los endpoints publicos deben leer read models propios en PostgreSQL. -- La lectura publica annual debe leer exclusivamente `rcon_annual_ranking_snapshots` y `rcon_annual_ranking_snapshot_items`. -- Mantener compatibilidad con `--sqlite-path` solo como modo legacy explicito. - -## Validation - -Before completing the task ensure: - -- `get_annual_ranking_snapshot()` no ejecuta `initialize_rcon_materialized_storage()` en la ruta PostgreSQL de lectura publica -- la generacion/escritura annual sigue pudiendo inicializar storage cuando sea necesario -- la lectura publica annual no recalcula ranking ni cae a runtime aggregates -- la respuesta annual mantiene: - - `read_model = rcon-annual-ranking-snapshot` - - `snapshot_status = ready` - - `fallback_used = false` - - `items = 30` -- se ejecuta esta medicion directa 3 veces: - -```bash -python - <<'PY' -import time -from app.payloads import build_global_ranking_payload - -for i in range(3): - start = time.perf_counter() - payload = build_global_ranking_payload( - timeframe="annual", - metric="kills", - limit=30, - year=2026, - server_id="all", - ) - elapsed = time.perf_counter() - start - data = payload.get("data", payload) - print({ - "attempt": i + 1, - "seconds": round(elapsed, 3), - "items": len(data.get("items") or []), - "snapshot_status": data.get("snapshot_status"), - "read_model": (data.get("source") or {}).get("read_model"), - }) -PY -``` - -- se ejecuta esta medicion HTTP interna 3 veces: - -```bash -python - <<'PY' -import json -import time -from urllib.request import urlopen - -url = "http://127.0.0.1:8000/api/ranking?timeframe=annual&metric=kills&limit=30&year=2026" - -for i in range(3): - start = time.perf_counter() - with urlopen(url, timeout=30) as response: - body = response.read() - elapsed = time.perf_counter() - start - payload = json.loads(body.decode("utf-8")) - data = payload.get("data", {}) - print({ - "attempt": i + 1, - "seconds": round(elapsed, 3), - "http": response.status, - "items": len(data.get("items") or []), - "snapshot_status": data.get("snapshot_status"), - "read_model": (data.get("source") or {}).get("read_model"), - }) -PY -``` - -- annual ranking queda claramente por debajo de `1 segundo` en caliente -- idealmente annual ranking queda por debajo de `300 ms` -- se ejecutan tests existentes relacionados si los hay -- si no hay tests suficientes, se anade un test unitario pequeno para verificar con monkeypatch/mock que `get_annual_ranking_snapshot()` no invoca `initialize_rcon_materialized_storage()` en la ruta PostgreSQL de lectura -- `git diff --name-only` matches the expected scope -- no unrelated files were modified - -## Outcome - -Documentar: - -- causa exacta del problema de latencia en la ruta annual/cold path -- que separacion se hizo entre generacion annual y lectura publica annual -- como queda tratada la compatibilidad PostgreSQL por defecto y SQLite legacy explicito -- antes/despues de tiempos en la medicion directa y en la medicion HTTP -- test ejecutados o test anadido -- confirmacion explicita de que no se tocaron frontend, assets de armas, SVGs, Elo/MMR ni Comunidad Hispana #03 - -Result: - -- Updated `backend/app/rcon_annual_rankings.py` to split annual snapshot reads from annual snapshot generation/storage initialization. -- Public annual reads now open PostgreSQL directly for snapshot queries and no longer call `initialize_rcon_materialized_storage()` on the PostgreSQL path. -- Legacy SQLite remains available only when an explicit `db_path`/`--sqlite-path` is used; the read path now resolves the file path without running initialization or migrations. -- Added `backend/tests/test_annual_ranking_payload.py` with a regression test asserting PostgreSQL annual reads do not invoke storage initialization. - -Cause fixed: - -- The annual public read path entered `initialize_rcon_materialized_storage()` before deciding between PostgreSQL and SQLite. -- In PostgreSQL mode that introduced avoidable cold-path schema/setup work in a request that only needed to read precomputed annual snapshots. -- The fix moves annual public reads to a read-only connection path that consults only: - - `rcon_annual_ranking_snapshots` - - `rcon_annual_ranking_snapshot_items` - -Validation performed: - -- PASS: `python -m compileall backend\\app\\rcon_annual_rankings.py backend\\tests\\test_annual_ranking_payload.py` -- PASS: direct unit test with stdlib `unittest`: - - `AnnualRankingPayloadTests.test_get_annual_ranking_snapshot_skips_storage_init_on_postgres_read` -- PASS: direct in-process timing: - - attempt 1: `0.010 s` - - attempt 2: `0.001 s` - - attempt 3: `0.001 s` - - `items = 30` - - `snapshot_status = ready` - - `read_model = rcon-annual-ranking-snapshot` -- INFO: HTTP timing probe against `http://127.0.0.1:8000/api/ranking?...` could not run because the local server was not listening (`ConnectionRefusedError`). - -Before/after timing summary: - -- Before, per task diagnosis: - - public production annual endpoint observed around `24-42 s` - - direct in-process profiling around `0.244 s` -- After this change in local direct payload validation: - - first call `0.010 s` - - warm calls `0.001 s` - -Scope confirmation: - -- No frontend file was touched. -- No weapon asset, SVG or physical image was touched. -- No Elo/MMR code was reactivated. -- Comunidad Hispana #03 was not reintroduced. -- `ai/system-metrics.md` was not touched by this task. -- No push was made. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-212-add-killfeed-weapon-icon-background.md b/ai/tasks/done/TASK-212-add-killfeed-weapon-icon-background.md deleted file mode 100644 index 68478fa..0000000 --- a/ai/tasks/done/TASK-212-add-killfeed-weapon-icon-background.md +++ /dev/null @@ -1,150 +0,0 @@ ---- -id: TASK-212 -title: Add killfeed weapon icon background -status: done -type: frontend -team: Frontend Senior -supporting_teams: - - Experto en interfaz -roadmap_item: foundation -priority: medium ---- - -# TASK-212 - Add killfeed weapon icon background - -## Goal - -Anadir una placa visual clara detras de los iconos de arma negros en la feed de bajas de `partida-actual`, sin modificar ningun SVG, asset fisico ni mapping de armas, para mejorar legibilidad dentro de la estetica militar sobria del proyecto. - -## Context - -En `frontend/assets/js/partida-actual.js`, la feed de bajas renderiza iconos mediante `renderKillFeedWeaponIcon()`. Actualmente esa funcion devuelve directamente un ``. - -Despues de `TASK-209`, `resolveKillFeedWeapon()` prioriza `globalThis.HLL_VIETNAM_CURRENT_MATCH_WEAPON_ICONS`, definido en `frontend/assets/js/current-match-weapon-icons.js`, que apunta a iconos negros desde `./assets/img/weapons/black/`. Como esos SVG tienen fondo transparente, en la feed se ve la silueta negra sin una base clara que la separe del fondo del panel. - -La implementacion debe envolver el icono en un contenedor visual estable, mantener el fallback `?` dentro de la misma placa o con estilo compatible, conservar el texto del arma visible y no alterar la fila de forma exagerada ni romper responsive. - -Preserve the current product identity: Spanish-speaking HLL Vietnam community, military/Vietnam/tactical/sober visual direction and controlled repository evolution. - -## Steps - -1. Revisar los archivos listados en `Files to Read First`, confirmando como se resuelve el icono, donde se renderiza el arma y donde viven los estilos reales del kill feed. -2. Modificar `renderKillFeedWeaponIcon()` para envolver el icono en un contenedor especifico, por ejemplo `current-match-killfeed__weapon-icon-frame`. -3. Mantener el fallback `?` dentro de la misma placa o con un estilo visual equivalente, sin cambiar el mapping de armas. -4. Anadir o ajustar CSS para dar al contenedor: - - fondo blanco o crema militar claro - - borde sutil - - `border-radius` - - `padding` - - tamano estable - - `display: grid` y `place-items: center` -5. Mantener el `` con `object-fit: contain` y sin deformacion. -6. Validar sintaxis JS, revisar visualmente `partida-actual` en local y documentar exclusiones. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `frontend/partida-actual.html` -- `frontend/assets/js/partida-actual.js` -- `frontend/assets/js/current-match-weapon-icons.js` -- `frontend/assets/css/historico.css` - -## Expected Files to Modify - -- `ai/tasks/in-progress/TASK-212-add-killfeed-weapon-icon-background.md` -- `frontend/assets/js/partida-actual.js` -- `frontend/assets/css/historico.css` - -Optional only if strictly necessary: - -- `frontend/partida-actual.html` -- `frontend/assets/css/styles.css` - -## Constraints - -- Keep the change minimal. -- Preserve HLL Vietnam project identity. -- Do not introduce unnecessary frameworks or dependencies. -- Do not overwrite repository-specific context with generic platform template text. -- No ejecutar `ai-platform run`. -- No tocar `backend/` ni endpoints. -- No tocar `frontend/assets/img/weapons/`. -- No tocar SVGs. -- No modificar imagenes fisicas. -- No cambiar el mapping de armas. -- No reactivar Elo/MMR. -- No reintroducir Comunidad Hispana #03. -- Mantener compatibilidad con apertura directa en navegador y responsive. - -## Validation - -Before completing the task ensure: - -- `renderKillFeedWeaponIcon()` envuelve el icono en un contenedor visual claro y estable -- los iconos negros se ven sobre una caja clara/blanca integrada con la estetica militar de la feed -- el fallback `?` usa la misma placa o un estilo compatible -- el `` mantiene `object-fit: contain` y no se deforma -- la fila del kill feed no crece de forma exagerada -- el texto del arma sigue visible -- se ejecuta: - -```bash -node --check frontend/assets/js/partida-actual.js -node --check frontend/assets/js/current-match-weapon-icons.js -``` - -- se realiza inspeccion visual local de `partida-actual` -- se confirma que no se tocaron: - - `backend/` - - `frontend/assets/img/weapons/` - - SVGs - - `ai/system-metrics.md` -- `git diff --name-only` matches the expected scope -- no unrelated files were modified - -## Outcome - -Documentar: - -- que cambio se hizo en `renderKillFeedWeaponIcon()` -- que clases CSS nuevas o ajustadas se anadieron para la placa del icono -- como queda tratado el fallback `?` -- validacion sintactica y visual realizada -- confirmacion explicita de que no se tocaron backend, assets de armas, SVGs, imagenes fisicas, Elo/MMR ni Comunidad Hispana #03 - -Result: - -- Updated `frontend/assets/js/partida-actual.js` so `renderKillFeedWeaponIcon()` now wraps both the `` and the `?` fallback inside `current-match-killfeed__weapon-icon-frame`. -- Updated `frontend/assets/css/historico.css` with a stable light cream weapon plate and adjusted icon/fallback sizing so black transparent SVGs remain readable without changing the weapon mapping. -- Kept the weapon label visible below the icon plate and preserved the current kill feed structure and responsive behavior. - -Validation performed: - -- PASS: `node --check frontend/assets/js/partida-actual.js` -- PASS: `node --check frontend/assets/js/current-match-weapon-icons.js` -- PASS: visual local inspection using temporary headless-browser screenshots for desktop and mobile widths confirmed: - - black weapon icon visible over a light plate - - fallback `?` rendered inside the same plate - - weapon text still visible - - no exaggerated row growth - - responsive layout remained usable -- PASS: reviewed `git status --short --untracked-files=all` -- PASS: reviewed `git diff --name-only` - -Scope confirmation: - -- No backend file or endpoint was touched. -- No weapon asset, SVG or physical image was modified. -- No weapon mapping or icon path was changed. -- `ai/system-metrics.md` was not touched by this task. -- Elo/MMR was not reactivated. -- Comunidad Hispana #03 was not reintroduced. -- No push was made. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-213-fix-ranking-layout-and-loading-state.md b/ai/tasks/done/TASK-213-fix-ranking-layout-and-loading-state.md deleted file mode 100644 index f7e6992..0000000 --- a/ai/tasks/done/TASK-213-fix-ranking-layout-and-loading-state.md +++ /dev/null @@ -1,178 +0,0 @@ ---- -id: TASK-213 -title: Fix ranking layout and loading state -status: done -type: frontend -team: Frontend Senior -supporting_teams: - - Experto en interfaz -roadmap_item: foundation -priority: high ---- - -# TASK-213 - Fix ranking layout and loading state - -## Goal - -Corregir la UX del ranking publico en `frontend/ranking.html` para que filtros y tabla queden en una unica seccion, la carga no quede bloqueada cuando la API ya respondio, y el copy visible use `periodo` de forma consistente sin cambiar ningun contrato de API. - -## Context - -La API de ranking ya responde rapido para combinaciones reales de filtros: - -- `/api/ranking?timeframe=weekly&metric=kills&limit=20` -> ~127 ms -- `/api/ranking?timeframe=weekly&metric=kills&limit=30` -> ~81 ms -- `/api/ranking?timeframe=monthly&metric=kills&limit=20` -> ~77 ms -- `/api/ranking?timeframe=annual&metric=kills&limit=20&year=2026` -> ~39 ms - -Por tanto, el cuello de botella actual no esta en backend ni base de datos. El problema a resolver es frontend: estado de carga, renderizado, carreras entre peticiones, logica de actualizacion y separacion visual entre filtros y resultados. - -La revision actual de `frontend/assets/js/ranking.js` ya muestra una posible causa probable que debe confirmarse y corregirse durante la ejecucion: - -- la carga inicial depende de `refreshBackendHealth()` antes de disparar `loadRanking()` -- no existe proteccion simple contra request race -- el estado de carga y el render comparten rutas que pueden dejar la UI en un estado obsoleto o visualmente vacio aunque la API responda rapido - -Preserve the current product identity: Spanish-speaking HLL Vietnam community, military/Vietnam/tactical/sober visual direction and controlled repository evolution. - -## Steps - -1. Leer primero los archivos listados en esta task y confirmar el comportamiento actual de `ranking.html` y `ranking.js`. -2. Unificar filtros, ayuda, acciones, estado y tabla dentro de una unica card o seccion, eliminando la card separada `Resultados / Tabla activa`. -3. Cambiar el copy visible para usar `periodo` en lugar de `ventana` donde aplique en la UI de ranking. -4. Revisar `frontend/assets/js/ranking.js` completo y eliminar cualquier causa de retardo artificial o bloqueo de loading: - - `setTimeout` innecesario - - debounce excesivo - - promesas no esperadas - - render condicionado a estado obsoleto - - loading que no se limpia en `finally` o `catch` - - botones que quedan deshabilitados - - render silenciosamente omitido -5. Anadir proteccion simple contra carreras con `currentRequestId` incremental o `AbortController`. -6. Garantizar que la ultima peticion lanzada sea la unica autorizada a pintar la tabla. -7. Mantener los contratos actuales de API y el comportamiento de carga automatica existente solo si sigue siendo inmediato y sin bloqueos. -8. Validar por sintaxis, inspeccion visual y comprobacion de respuestas reales o equivalentes del endpoint antes de cerrar la task. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `frontend/ranking.html` -- `frontend/assets/js/ranking.js` -- `frontend/assets/css/styles.css` -- `frontend/assets/css/historico.css` -- `ai/tasks/done/TASK-207-annual-ranking-default-load-and-kpm-columns.md` - -## Expected Files to Modify - -- `ai/tasks/in-progress/TASK-213-fix-ranking-layout-and-loading-state.md` -- `frontend/ranking.html` -- `frontend/assets/js/ranking.js` -- `frontend/assets/css/styles.css` - -Si `frontend/assets/css/historico.css` resulta estar afectando realmente a `ranking.html`, documentarlo primero y mantener cualquier cambio alli como ajuste minimo y justificado. - -## Constraints - -- Keep the change minimal. -- Preserve HLL Vietnam project identity. -- Do not introduce unnecessary frameworks or dependencies. -- Do not implement backend functionality unless the task explicitly requires it. -- Do not expand Elo/MMR, historical workers or RCON server #03 handling unless the task explicitly requires it. -- Do not overwrite repository-specific context with generic platform template text. -- No ejecutar `ai-platform run`. -- No tocar `backend/`. -- No tocar endpoints ni contratos de API. -- No tocar `frontend/assets/img/weapons/`. -- No tocar SVGs. -- No modificar imagenes fisicas. -- No tocar `ai/system-metrics.md`. -- No reactivar Elo/MMR. -- No reintroducir Comunidad Hispana #03. -- No hacer `push`. -- No hacer `commit` en esta task. -- Mantener compatibilidad con apertura directa en navegador cuando aplique. - -## Validation - -Before completing the task ensure: - -- `node --check frontend/assets/js/ranking.js` -- si se toca cualquier otro archivo JS, ejecutar `node --check` sobre cada JS modificado -- por inspeccion visual local: - - filtros y tabla aparecen dentro de una unica card o seccion - - ya no queda una card separada `Resultados / Tabla activa` vacia - - `Top publico por periodo` aparece correctamente - - `El ranking expone los resultados de los lideres. Para busqueda individual usa Estadisticas.` aparece correctamente - - semanal, mensual y anual pintan resultados - - cambiar a mensual no deja la UI bloqueada - - `Actualizar ranking` dispara una sola peticion visible y pinta rapido - - `Top 20` y `Top 30` funcionan si el backend los acepta por URL o por interfaz habilitada -- validar contra backend real o equivalente local que los endpoints siguen respondiendo con: - - `status = ok` - - `snapshot_status = ready` - - `read_model = ranking-snapshot` o `rcon-annual-ranking-snapshot` - - `fallback_used = false` -- `git diff --name-only` matches the expected scope -- no unrelated files were modified -- documentar explicitamente si no existe automatizacion adicional para esta validacion frontend - -## Outcome - -Archivos modificados: - -- `frontend/ranking.html` -- `frontend/assets/js/ranking.js` -- `frontend/assets/css/styles.css` -- `ai/tasks/done/TASK-213-fix-ranking-layout-and-loading-state.md` - -Causa probable encontrada en `frontend/assets/js/ranking.js`: - -- la carga inicial dependia de `refreshBackendHealth()` antes de pedir `/api/ranking` -- no existia proteccion contra request race entre cambios rapidos de filtros -- el estado de carga se combinaba con limpieza temprana de superficie, dejando la UI vacia o aparentemente bloqueada aunque la API respondiera rapido - -Resumen del layout nuevo: - -- filtros, nota, acciones, estado, metadatos y tabla quedaron dentro de una sola card -- se elimino la card separada `Resultados / Tabla activa` -- el copy visible principal se actualizo a `Top publico por periodo` -- la descripcion pasa a `El ranking expone los resultados de los lideres. Para busqueda individual usa Estadisticas.` - -Cambio funcional aplicado en frontend: - -- `ranking.js` ya no espera `/health` para cargar el ranking inicial -- la carga inicial llama directamente a `/api/ranking` -- se anadio `currentRequestId` mas `AbortController` -- cada nueva peticion aborta la anterior y solo la ultima puede pintar -- el boton `Actualizar ranking` se deshabilita mientras la peticion activa esta en curso y siempre se limpia en `finally` -- durante loading ya no se vacia la tabla de forma agresiva antes de tener la nueva respuesta -- se anadio `Top 30` a la interfaz para alinear la UI con el endpoint validado en contexto - -Validaciones ejecutadas: - -- `node --check frontend/assets/js/ranking.js` -- revision de diff acotado con `git diff --name-only` sobre los archivos esperados -- intento de validacion HTTP local de: - - `/api/ranking?timeframe=weekly&metric=kills&limit=20` - - `/api/ranking?timeframe=weekly&metric=kills&limit=30` - - `/api/ranking?timeframe=monthly&metric=kills&limit=20` - - `/api/ranking?timeframe=annual&metric=kills&limit=20&year=2026` -- el backend local no estaba disponible en `http://127.0.0.1:8000`, por lo que esa validacion quedo bloqueada con `No es posible conectar con el servidor remoto` -- no existe en esta ejecucion una inspeccion visual automatizada del DOM; la comprobacion queda por lectura del marcado y de la logica aplicada - -Confirmacion de exclusiones: - -- no se tocaron `backend/`, endpoints ni contratos de API -- no se tocaron `frontend/assets/img/weapons/`, SVGs ni imagenes fisicas -- no se toco `ai/system-metrics.md` -- no se reactivo Elo/MMR -- no se reintrodujo Comunidad Hispana #03 -- no se hizo `push` - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-214-audit-public-query-performance-bottlenecks.md b/ai/tasks/done/TASK-214-audit-public-query-performance-bottlenecks.md deleted file mode 100644 index 9abb832..0000000 --- a/ai/tasks/done/TASK-214-audit-public-query-performance-bottlenecks.md +++ /dev/null @@ -1,134 +0,0 @@ ---- -id: TASK-214 -title: Audit public query performance bottlenecks -status: done -type: research -team: Analista -supporting_teams: - - Frontend Senior - - Backend Senior - - Arquitecto de Base de Datos -roadmap_item: foundation -priority: high ---- - -# TASK-214 - Audit public query performance bottlenecks - -## Goal - -Auditar los posibles cuellos de botella de las consultas publicas de HLL Vietnam y producir un analisis tecnico accionable para futuras optimizaciones, sin implementar cambios funcionales todavia. - -## Context - -El ranking anual ya sufrio un cuello de botella grave y quedo corregido al sacar `initialize_rcon_materialized_storage()` del path publico de lectura anual en PostgreSQL. Tras ese fix, las latencias confirmadas de API de ranking son bajas, pero la UI publica aun puede percibirse lenta o quedarse temporalmente en estados de carga. - -La regla arquitectonica objetivo de esta auditoria es explicita: - -- los endpoints publicos deben leer read models propios en PostgreSQL -- no deben consultar RCON directo -- no deben consultar scoreboard publico -- no deben recalcular rankings en runtime -- no deben escanear `rcon_match_player_stats` salvo en procesos internos -- no deben inicializar o migrar storage dentro de request publico -- no deben bloquearse por health checks no necesarios - -Preserve the current product identity: Spanish-speaking HLL Vietnam community, military/Vietnam/tactical/sober visual direction and controlled repository evolution. - -## Steps - -1. Revisar primero la documentacion base, las rutas publicas y los frontends que las consumen. -2. Auditar endpoints publicos, fallbacks, read models, polling, cargas secuenciales y riesgos de runtime. -3. Redactar el informe tecnico en `docs/PERFORMANCE_PUBLIC_QUERY_AUDIT.md`. -4. Cerrar esta task en `ai/tasks/done/` documentando hallazgos, validacion y exclusiones. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `docs/decisions.md` -- `backend/app/routes.py` -- `backend/app/payloads.py` - -## Expected Files to Modify - -- `docs/PERFORMANCE_PUBLIC_QUERY_AUDIT.md` -- `ai/tasks/done/TASK-214-audit-public-query-performance-bottlenecks.md` - -## Constraints - -- Keep the change minimal. -- Preserve HLL Vietnam project identity. -- Do not introduce unnecessary frameworks or dependencies. -- Do not implement backend functionality unless the task explicitly requires it. -- Do not expand Elo/MMR, historical workers or RCON server #03 handling unless the task explicitly requires it. -- Do not overwrite repository-specific context with generic platform template text. -- No ejecutar `ai-platform run`. -- No implementar optimizaciones funcionales todavia. -- No cambiar comportamiento de endpoints. -- No tocar frontend funcional. -- No tocar backend funcional. -- No tocar tests. -- No tocar assets de armas. -- No tocar SVGs. -- No modificar imagenes fisicas. -- No reactivar Elo/MMR. -- No reintroducir Comunidad Hispana #03. -- No hacer `push`. - -## Validation - -Before completing the task ensure: - -- `git status --short --untracked-files=all` -- `git diff --name-only` -- confirmar que solo se crean o modifican: - - `docs/PERFORMANCE_PUBLIC_QUERY_AUDIT.md` - - `ai/tasks/done/TASK-214-audit-public-query-performance-bottlenecks.md` -- no unrelated files were modified -- documentation remains consistent with the repository state - -## Outcome - -Archivos creados: - -- `docs/PERFORMANCE_PUBLIC_QUERY_AUDIT.md` -- `ai/tasks/done/TASK-214-audit-public-query-performance-bottlenecks.md` - -Resumen de hallazgos: - -- `ranking.js` y `stats.js` bloquean carga principal detras de `/health`. -- `ranking.js` no protege request race ni estados de carga obsoletos. -- `/api/ranking` weekly/monthly conserva fallback runtime sobre tablas materializadas. -- search y profile de `stats` pueden caer a runtime si faltan read models dedicados. -- `historico.js` ya muestra un patron frontend mas sano: cache, deduplicacion y `requestId`. -- `/api/current-match` sigue consultando RCON directo en request publico. -- `partida-actual.js` hace polling agresivo a tres endpoints en paralelo. -- varias queries runtime filtran con `COALESCE(CAST(... AS TEXT))`, con riesgo de degradar indices. - -Validacion ejecutada: - -- lectura de contexto base: `AGENTS.md`, `ai/repo-context.md`, `ai/architecture-index.md`, `docs/decisions.md` -- lectura de endpoints y builders: `backend/app/routes.py`, `backend/app/payloads.py` -- lectura de modulos clave: `backend/app/rcon_annual_rankings.py`, `backend/app/rcon_historical_leaderboards.py`, `backend/app/rcon_historical_player_stats.py`, `backend/app/rcon_historical_read_model.py`, `backend/app/postgres_rcon_storage.py`, `backend/app/historical_runner.py`, `backend/app/main.py`, `backend/app/config.py` -- lectura de frontends clave: `frontend/assets/js/ranking.js`, `stats.js`, `historico.js`, `historico-partida.js`, `partida-actual.js`, `main.js` -- lectura de paginas clave: `frontend/ranking.html`, `stats.html`, `historico.html`, `partida-actual.html` -- lectura de tests relevantes: `backend/tests/test_annual_ranking_payload.py`, `test_rcon_materialization_pipeline.py`, `test_historical_snapshot_refresh.py` -- validacion de alcance con `git status --short --untracked-files=all` y `git diff --name-only` - -Confirmaciones de exclusiones: - -- no se toco codigo funcional de frontend ni backend -- no se tocaron tests -- no se tocaron endpoints ni contratos -- no se tocaron assets de armas, SVGs ni imagenes fisicas -- no se reactivo Elo/MMR -- no se reintrodujo Comunidad Hispana #03 -- no se ejecuto `ai-platform run` -- no se hizo `push` - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-215-optimize-weekly-monthly-ranking-read-path.md b/ai/tasks/done/TASK-215-optimize-weekly-monthly-ranking-read-path.md deleted file mode 100644 index fe79050..0000000 --- a/ai/tasks/done/TASK-215-optimize-weekly-monthly-ranking-read-path.md +++ /dev/null @@ -1,312 +0,0 @@ ---- -id: TASK-215 -title: Optimize weekly and monthly ranking read path -status: done -type: backend -team: Backend Senior -supporting_teams: - - Arquitecto Python -roadmap_item: foundation -priority: high ---- - -# TASK-215 - Optimize weekly and monthly ranking read path - -## Goal - -Optimizar la ruta publica de lectura de los rankings weekly y monthly para que lean exclusivamente snapshots ya materializados, evitando inicializacion, migracion o setup de storage en cada request publica y reduciendo la latencia del read path sin tocar frontend, assets ni Elo/MMR. - -## Context - -Tras `TASK-211` se corrigio la ruta anual para separar lectura publica de generacion/escritura. Ahora se ha detectado el mismo patron en weekly/monthly. - -Evidencia de produccion: - -- la API publica devuelve correctamente: - - `snapshot_status = ready` - - `read_model = ranking-snapshot` - - `fallback_used = false` - - `items = 20` -- el perfilado directo de: - -```python -build_global_ranking_payload( - timeframe="weekly", - metric="kills", - limit=20, - server_id="all", -) -``` - -ha tardado `101.33 segundos`. - -`cProfile` indica: - -- `payloads.py:787 build_global_ranking_payload -> 101.330s` -- `rcon_historical_leaderboards.py:315 get_latest_ranking_snapshot -> 101.330s` -- `rcon_historical_leaderboards.py:98 initialize_ranking_snapshot_storage -> 101.306s` -- `rcon_admin_log_materialization.py:24 initialize_rcon_materialized_storage -> 101.294s` -- `postgres_rcon_storage.py:383 initialize_postgres_rcon_storage -> 101.315s` - -La causa actual es que `get_latest_ranking_snapshot()` llama a `initialize_ranking_snapshot_storage()` dentro de una ruta publica de solo lectura. Esa funcion inicializa o migra storage y no debe ejecutarse durante una request publica que solo lee snapshots ya materializados. - -Regla arquitectonica: - -- los endpoints publicos de ranking weekly/monthly deben leer unicamente: - - `ranking_snapshots` - - `ranking_snapshot_items` -- no deben: - - consultar RCON - - consultar scoreboard publico - - recalcular rankings en runtime - - escanear `rcon_match_player_stats` - - inicializar o migrar storage en request publico - - hacer N+1 por jugador - - preparar fallback runtime salvo modo interno explicito - -Preserve the current product identity: Spanish-speaking HLL Vietnam community, military/Vietnam/tactical/sober visual direction and controlled repository evolution. - -## Steps - -1. Revisar primero la implementacion actual en `backend/app/rcon_historical_leaderboards.py` y el ensamblado de payloads en `backend/app/payloads.py`. -2. Tomar como referencia conceptual la separacion aplicada en `TASK-211` para annual. -3. Separar con claridad: - - inicializacion, generacion o escritura de snapshots - - lectura publica de snapshots -4. Mantener `initialize_ranking_snapshot_storage()` disponible para: - - generacion - - refresh - - CLI - - procesos internos - - SQLite legacy si realmente lo requiere -5. Evitar `initialize_ranking_snapshot_storage()` en `get_latest_ranking_snapshot()` cuando se use PostgreSQL por defecto. -6. En la ruta PostgreSQL publica: - - abrir conexion directa con `connect_postgres_compat()` - - buscar snapshot en `ranking_snapshots` - - contar o listar `ranking_snapshot_items` - - devolver payload sin inicializar storage -7. Mantener compatibilidad SQLite legacy explicita: - - si `db_path` se pasa explicitamente, resolver path de solo lectura sin migrar o inicializar si el diseno actual lo permite - - no romper tests existentes -8. Mantener el contrato de respuesta: - - `read_model = ranking-snapshot` - - `snapshot_status = ready` - - `fallback_used = false` - - `items` segun `limit` - - weekly/monthly siguen funcionando para `all`, `comunidad-hispana-01` y `comunidad-hispana-02` - - las metricas existentes siguen funcionando -9. Anadir un test unitario con monkeypatch o mock para verificar que `get_latest_ranking_snapshot()` no invoca `initialize_ranking_snapshot_storage()` en la ruta PostgreSQL de lectura publica, tomando como referencia el test creado en `TASK-211`. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `backend/app/rcon_historical_leaderboards.py` -- `backend/app/payloads.py` -- `ai/tasks/done/TASK-211-optimize-annual-ranking-read-path.md` - -## Expected Files to Modify - -- `ai/tasks/in-progress/TASK-215-optimize-weekly-monthly-ranking-read-path.md` -- `backend/app/rcon_historical_leaderboards.py` -- `backend/app/payloads.py` - -Optional only if strictly necessary: - -- backend unit test file related to ranking snapshots or payloads - -## Constraints - -- Keep the change minimal. -- Preserve HLL Vietnam project identity. -- Do not introduce unnecessary frameworks or dependencies. -- Do not overwrite repository-specific context with generic platform template text. -- No ejecutar `ai-platform run`. -- No tocar `frontend/`. -- No tocar assets de armas. -- No tocar SVGs. -- No modificar imagenes fisicas. -- No reactivar Elo/MMR. -- No reintroducir Comunidad Hispana #03. -- No tocar `ai/system-metrics.md`. -- No hacer push. -- No consultar RCON, scoreboard publico ni recalcular ranking dentro de la lectura publica weekly/monthly. -- No escanear `rcon_match_player_stats` en la ruta publica weekly/monthly. -- No hacer N+1 por jugador en la ruta publica weekly/monthly. -- No inicializar ni migrar storage en request publico weekly/monthly. -- Los endpoints publicos deben leer read models propios en PostgreSQL. -- La lectura publica weekly/monthly debe leer exclusivamente `ranking_snapshots` y `ranking_snapshot_items`. -- Mantener compatibilidad con SQLite legacy solo como modo explicito si ya existe soporte real para ello. - -## Validation - -Before completing the task ensure: - -- `get_latest_ranking_snapshot()` no invoca `initialize_ranking_snapshot_storage()` en la ruta PostgreSQL de lectura publica -- no aparece `initialize_ranking_snapshot_storage` en el perfil de la ruta publica -- no aparece `initialize_rcon_materialized_storage` en el perfil de la ruta publica -- no aparece `initialize_postgres_rcon_storage` en el perfil de la ruta publica -- la generacion o escritura de snapshots sigue pudiendo inicializar storage cuando sea necesario -- la lectura publica weekly/monthly no recalcula ranking ni cae a runtime aggregates -- la respuesta mantiene: - - `read_model = ranking-snapshot` - - `snapshot_status = ready` - - `fallback_used = false` - - `items` segun `limit` -- se ejecuta `compileall`: - -```bash -python -m compileall backend\app\rcon_historical_leaderboards.py backend\tests\.py -``` - -- se ejecuta el test unitario anadido -- se ejecuta esta medicion directa: - -```bash -python - <<'PY' -import time -from app.payloads import build_global_ranking_payload - -tests = [ - {"timeframe": "weekly", "metric": "kills", "limit": 20, "server_id": "all"}, - {"timeframe": "weekly", "metric": "kills", "limit": 30, "server_id": "all"}, - {"timeframe": "monthly", "metric": "kills", "limit": 20, "server_id": "all"}, -] - -for params in tests: - for i in range(3): - start = time.perf_counter() - payload = build_global_ranking_payload(**params) - elapsed = time.perf_counter() - start - data = payload.get("data", payload) - print({ - "params": params, - "attempt": i + 1, - "seconds": round(elapsed, 3), - "items": len(data.get("items") or []), - "snapshot_status": data.get("snapshot_status"), - "read_model": (data.get("source") or {}).get("read_model"), - "fallback_used": data.get("fallback_used"), - }) -PY -``` - -- si hay backend local accesible, se ejecuta esta medicion HTTP interna: - -```bash -python - <<'PY' -import json -import time -from urllib.request import urlopen - -urls = [ - "http://127.0.0.1:8000/api/ranking?timeframe=weekly&metric=kills&limit=20", - "http://127.0.0.1:8000/api/ranking?timeframe=weekly&metric=kills&limit=30", - "http://127.0.0.1:8000/api/ranking?timeframe=monthly&metric=kills&limit=20", -] - -for url in urls: - for i in range(3): - start = time.perf_counter() - with urlopen(url, timeout=30) as response: - body = response.read() - elapsed = time.perf_counter() - start - payload = json.loads(body.decode("utf-8")) - data = payload.get("data", {}) - print({ - "url": url, - "attempt": i + 1, - "seconds": round(elapsed, 3), - "http": response.status, - "items": len(data.get("items") or []), - "snapshot_status": data.get("snapshot_status"), - "read_model": (data.get("source") or {}).get("read_model"), - "fallback_used": data.get("fallback_used"), - }) -PY -``` - -- weekly top 20 queda por debajo de `1 segundo` -- idealmente weekly top 20 queda por debajo de `300 ms` -- weekly/monthly siguen funcionando para `all`, `comunidad-hispana-01` y `comunidad-hispana-02` -- las metricas existentes siguen funcionando -- `git diff --name-only` matches the expected scope -- no unrelated files were modified - -## Outcome - -Result: - -- Updated `backend/app/rcon_historical_leaderboards.py` to split public weekly/monthly snapshot reads from storage initialization and snapshot generation. -- Public reads now use a dedicated read-only connection helper: - - PostgreSQL default path opens a direct compat read connection without `initialize_ranking_snapshot_storage()` - - explicit SQLite legacy path resolves the file in read-only mode without migrations or setup -- Kept `initialize_ranking_snapshot_storage()` for generation, refresh, CLI and internal write flows. -- Tightened public ranking behavior so runtime fallback is no longer enabled by default; public requests only fall back when `HLL_BACKEND_RANKING_RUNTIME_FALLBACK_ENABLED` is explicitly enabled. -- Added `backend/tests/test_ranking_snapshot_payload.py` with a regression test asserting PostgreSQL public reads do not invoke ranking snapshot storage initialization. - -Modified files: - -- `ai/tasks/done/TASK-215-optimize-weekly-monthly-ranking-read-path.md` -- `backend/app/rcon_historical_leaderboards.py` -- `backend/tests/test_ranking_snapshot_payload.py` - -Cause fixed: - -- `get_latest_ranking_snapshot()` initialized ranking snapshot storage before deciding the read path. -- On the PostgreSQL public read path that pulled in setup or migration work through: - - `initialize_ranking_snapshot_storage()` - - `initialize_rcon_materialized_storage()` - - `initialize_postgres_rcon_storage()` -- The fix separates public snapshot reads from generation and prevents those initializers from appearing in the default public weekly/monthly read path. - -Validation performed: - -- PASS: `python -m compileall backend\app\rcon_historical_leaderboards.py backend\tests\test_ranking_snapshot_payload.py` -- PASS: `python -m unittest backend.tests.test_ranking_snapshot_payload` -- PASS: direct timing probe through `build_global_ranking_payload(...)` -- PASS: targeted `cProfile` probe confirms the profiled public read path now shows: - - `build_global_ranking_payload` - - `get_latest_ranking_snapshot` - - and does not show: - - `initialize_ranking_snapshot_storage` - - `initialize_rcon_materialized_storage` - - `initialize_postgres_rcon_storage` -- INFO: HTTP probe against `http://127.0.0.1:8000` could not run because the local backend was not listening (`ConnectionRefusedError`). -- INFO: local SQLite had no persisted weekly/monthly snapshots available: - - `ranking_snapshots = 0` - - `ranking_snapshot_items = 0` - - because of that, local payload validation exercised the fast missing-snapshot public path, not a ready snapshot payload with items. - -Before/after timing summary: - -- Before, per production evidence: - - `build_global_ranking_payload(timeframe="weekly", metric="kills", limit=20, server_id="all")` took `101.33 s` -- After, local direct payload timing: - - weekly limit 20: `0.002 s`, `0.001 s`, `0.001 s` - - weekly limit 30: `0.001 s`, `0.001 s`, `0.001 s` - - monthly limit 20: `0.001 s`, `0.001 s`, `0.001 s` -- Local response contract after the change in this environment: - - `snapshot_status = missing` - - `read_model = ranking-snapshot` - - `fallback_used = false` - - `items = 0` -- Note: the `ready/items>0` contract could not be revalidated locally because no ranking snapshots existed in local storage. - -Scope confirmation: - -- No frontend file was touched. -- No weapon asset was touched. -- No SVG was touched. -- No physical image was modified. -- Elo/MMR was not reactivated. -- Comunidad Hispana #03 was not reintroduced. -- `ai/system-metrics.md` was not touched. -- No push was made. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-216-clean-ranking-ui-and-fix-kpm-metric.md b/ai/tasks/done/TASK-216-clean-ranking-ui-and-fix-kpm-metric.md deleted file mode 100644 index f902eff..0000000 --- a/ai/tasks/done/TASK-216-clean-ranking-ui-and-fix-kpm-metric.md +++ /dev/null @@ -1,236 +0,0 @@ ---- -id: TASK-216 -title: Clean ranking UI and fix KPM metric -status: done -type: frontend -team: Frontend Senior -supporting_teams: - - Backend Senior - - Arquitecto Python - - Experto en interfaz -roadmap_item: foundation -priority: high ---- - -# TASK-216 - Clean ranking UI and fix KPM metric - -## Goal - -Limpiar la UX de `frontend/ranking.html`, eliminar estados y controles redundantes, corregir el uso conceptual de KPM y ampliar el ranking anual solo para metricas soportadas por snapshots/read models seguros sin introducir lecturas runtime pesadas en requests publicos. - -## Context - -Despues de `TASK-213`, la vista de ranking ya carga rapido y concentra filtros + tabla dentro de una sola card. Sin embargo, la revision visual detecto varios residuos de UX y un problema funcional serio: la interfaz seguia mostrando mensajes redundantes, mantenia un boton `Actualizar ranking` innecesario y exponia `KPM` usando un valor que correspondia a `kills_per_match`. - -En paralelo, `TASK-211` dejo la lectura publica annual optimizada para snapshots anuales, pero `backend/app/rcon_annual_rankings.py` sigue restringiendo annual a `kills`. Esta task revisa ese limite sin introducir lecturas publicas runtime sobre `rcon_match_player_stats`. - -Preserve the current product identity: Spanish-speaking HLL Vietnam community, military/Vietnam/tactical/sober visual direction and controlled repository evolution. - -## Steps - -1. Leer primero los archivos listados y confirmar el estado actual de UI, payloads y snapshots de ranking. -2. Auditar si existe tiempo jugado real por jugador antes de tocar la UI. -3. Limpiar la UI de `ranking.html` y `ranking.js`: - - eliminar del DOM visible el texto `El ranking expone los resultados de los lideres. Para busqueda individual usa Estadisticas.` - - eliminar el estado informativo tipo `Kills listo en semanal para Todos los servidores.` - - mantener solo estados utiles de loading, error y metadatos compactos - - quitar el boton `Actualizar ranking` - - cargar automaticamente al entrar y al cambiar periodo, servidor, metrica o limite - - mover `Buscar jugador en Estadisticas` por encima de los filtros dentro de la misma card -4. Ajustar el modo annual en frontend: - - no mostrar input de ano - - usar `2026` internamente en JS - - no mostrar mensaje de limitacion anual a kills -5. No exponer metricas annual que no tengan snapshots propios y seguros. -6. Documentar la decision final sobre KPM y el diseno futuro de `player_active_seconds`. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `frontend/ranking.html` -- `frontend/assets/js/ranking.js` -- `backend/app/rcon_annual_rankings.py` - -Tambien se revisaron: - -- `frontend/assets/css/styles.css` -- `backend/app/payloads.py` -- `backend/app/postgres_rcon_storage.py` -- `backend/app/rcon_historical_leaderboards.py` -- `backend/app/rcon_historical_player_stats.py` -- `backend/app/rcon_admin_log_storage.py` -- `backend/app/rcon_admin_log_materialization.py` -- `backend/app/historical_runner.py` -- `ai/tasks/done/TASK-211-optimize-annual-ranking-read-path.md` -- `ai/tasks/done/TASK-213-fix-ranking-layout-and-loading-state.md` -- `ai/tasks/done/TASK-215-optimize-weekly-monthly-ranking-read-path.md` -- `docs/PERFORMANCE_PUBLIC_QUERY_AUDIT.md` - -## Expected Files to Modify - -- `frontend/ranking.html` -- `frontend/assets/js/ranking.js` -- `frontend/assets/css/styles.css` -- `ai/tasks/done/TASK-216-clean-ranking-ui-and-fix-kpm-metric.md` - -## Constraints - -- Keep the change minimal. -- Preserve HLL Vietnam project identity. -- Do not introduce unnecessary frameworks or dependencies. -- Do not overwrite repository-specific context with generic platform template text. -- No ejecutar `ai-platform run`. -- No tocar `frontend/assets/img/weapons/`. -- No tocar SVGs. -- No modificar imagenes fisicas. -- No tocar `ai/system-metrics.md`. -- No reactivar Elo/MMR. -- No reintroducir Comunidad Hispana #03. -- No hacer `push`. -- No hacer `commit` en esta task. -- No introducir runtime pesado ni fallback publico sobre `rcon_match_player_stats`. -- La lectura publica annual debe seguir leyendo unicamente: - - `rcon_annual_ranking_snapshots` - - `rcon_annual_ranking_snapshot_items` -- Weekly/monthly/annual deben seguir priorizando read models/snapshots con `fallback_used = false` en la ruta publica normal. -- No aceptar que `kills_per_match` se muestre como `KPM`. -- Si no existe tiempo jugado fiable materializado, no inventar `KPM`. -- Mantener compatibilidad con apertura directa en navegador cuando aplique. - -## Validation - -Before completing the task ensure: - -- `node --check frontend/assets/js/ranking.js` -- validar endpoints: - - `/api/ranking?timeframe=weekly&metric=kills&limit=20` - - `/api/ranking?timeframe=monthly&metric=kills&limit=20` - - `/api/ranking?timeframe=annual&metric=kills&limit=20&year=2026` -- por inspeccion visual o revision DOM: - - no aparece boton `Actualizar ranking` - - `Buscar jugador en Estadisticas` queda encima de filtros y dentro de la misma card - - no aparecen los textos redundantes eliminados - - annual no muestra input de ano - - annual no muestra mensaje de limitacion a kills - - la columna `KPM` no aparece si no existe KPM real - - si no hay minutos reales, aparece `Kills/partida` -- `git diff --name-only` matches the expected scope -- no unrelated files were modified - -## Outcome - -Archivos modificados por esta task: - -- `frontend/ranking.html` -- `frontend/assets/js/ranking.js` -- `frontend/assets/css/styles.css` -- `ai/tasks/done/TASK-216-clean-ranking-ui-and-fix-kpm-metric.md` - -Resultado de auditoria KPM: - -- No existe hoy un campo materializado y fiable de tiempo jugado real por jugador listo para el ranking publico. -- Se encontro `rcon_player_profile_snapshots.play_time`, pero es texto procedente de snapshots de perfil, no un campo numerico normalizado por jugador/partida ni agregado en los read models publicos de ranking. -- Se encontraron `rcon_match_player_stats.first_seen_server_time` y `rcon_match_player_stats.last_seen_server_time`, pero representan presencia observada por eventos dentro de una partida, no minutos reales jugados materializados como contrato estable de ranking. -- Se encontraron `rcon_materialized_matches.started_at`, `ended_at`, `started_server_time` y `ended_server_time`, pero son duracion de partida o ventana de partida, no tiempo real por jugador. -- Las tablas `ranking_snapshot_items`, `rcon_annual_ranking_snapshot_items` y `player_period_stats` no tienen `player_active_seconds`, `minutes_played`, `seconds_played` ni equivalente fiable. - -Decision final sobre KPM: - -- No se implemento KPM real. -- Se elimino el uso visible de `KPM` en `ranking.html` y `ranking.js`. -- `kills_per_match` se conserva solo bajo el nombre `Kills/partida`. -- No se reutilizo `kills_per_match` como kills por minuto. - -Propuesta para KPM real futuro: - -- Crear `player_active_seconds` como campo numerico base por jugador y partida. -- Ubicacion preferida: `rcon_match_player_stats`, si se acepta extender la tabla materializada principal. -- Alternativa: nueva tabla derivada `rcon_match_player_presence` con `target_key`, `match_key`, `player_id`, `first_seen_server_time`, `last_seen_server_time`, `active_seconds`, `quality`. -- Relleno exacto: eventos `connected` y `disconnected` dentro de limites `match_start`/`match_end`. -- Relleno razonable: presencia observada por eventos `kill`, `team_switch`, `chat`, `message`, acotada por `first_seen_server_time` y `last_seen_server_time`. -- Relleno estimado: duracion completa de partida solo como calidad `estimated`, no apta para publicar como KPM real sin etiqueta. -- Criterios de calidad propuestos: - - `exact`: join/leave real dentro de partida. - - `observed`: presencia inferida por eventos del jugador. - - `estimated`: duracion completa de partida. - - `unknown`: no calcular. -- Read models a extender cuando exista el campo: - - `player_period_stats` - - `ranking_snapshot_items` - - `rcon_annual_ranking_snapshot_items` -- Task futura recomendada: `TASK-XXX-materialize-player-active-seconds-for-real-kpm`. - -Decision sobre metricas annual: - -- No se ampliaron metricas annual en esta task. -- Annual sigue exponiendo solo `kills` porque es la unica metrica con snapshot anual seguro ya soportado por `rcon_annual_rankings.py`. -- No se usa snapshot top kills para representar `deaths`, `teamkills`, `matches_considered`, `kd_ratio` ni `kills_per_match`. -- No se introdujo runtime publico pesado ni fallback sobre `rcon_match_player_stats`. - -Cambios de UI aplicados: - -- Se elimino el texto redundante de introduccion dentro de la card. -- Se elimino el boton `Actualizar ranking`. -- La tabla sigue cargando automaticamente al entrar y al cambiar periodo, servidor, metrica o limite. -- `Buscar jugador en Estadisticas` queda encima de los filtros dentro de la misma card. -- En annual no hay input visible de ano. -- `ranking.js` usa `2026` internamente para annual. -- Se elimino el mensaje visible de annual limitado a kills. -- Se elimino el estado de exito tipo `Kills listo en semanal para Todos los servidores.` -- La metrica `kills_per_match` se muestra como `Kills/partida`. - -Comandos de produccion: - -- No hace falta regenerar snapshots para este cambio de UI. -- Si falta el snapshot anual existente de kills para 2026, regenerarlo con: - -```bash -docker compose exec backend python -m app.rcon_annual_rankings generate --year 2026 --server-key all-servers --metric kills --limit 30 --replace-existing -``` - -- No ejecutar comandos de metricas annual adicionales hasta que existan snapshots propios por metrica. - -Validaciones ejecutadas: - -- `node --check frontend/assets/js/ranking.js` -- Revision por busqueda de que `frontend/ranking.html` y `frontend/assets/js/ranking.js` ya no contienen `KPM`, `Actualizar ranking`, `ranking-year`, `ranking-submit`, `ranking-filter-note`, `El ranking expone` ni `listo en`. -- Intento de validacion HTTP local contra: - - `/api/ranking?timeframe=weekly&metric=kills&limit=20` - - `/api/ranking?timeframe=monthly&metric=kills&limit=20` - - `/api/ranking?timeframe=annual&metric=kills&limit=20&year=2026` -- El backend local no estaba disponible en `http://127.0.0.1:8000`; las tres peticiones fallaron con `No es posible conectar con el servidor remoto`. -- Revision de alcance con `git status --short` y `git diff --name-only`. - -Validaciones no ejecutadas: - -- No se ejecuto `compileall` ni `unittest` porque no se tocaron archivos backend. - -Tiempos obtenidos: - -- No se obtuvieron tiempos nuevos de endpoint porque el backend local no estaba escuchando. -- Intentos HTTP fallidos por conexion: - - weekly kills top 20: `2156.7 ms` - - monthly kills top 20: `2033.7 ms` - - annual kills top 20 2026: `2046.1 ms` -- Referencia previa de `TASK-213`: annual kills 2026 ~39 ms, weekly/monthly kills < 130 ms. - -Confirmacion de exclusiones: - -- No se ejecuto `ai-platform run`. -- No se hizo push. -- No se hizo commit. -- No se tocaron assets de armas. -- No se tocaron SVGs. -- No se modificaron imagenes fisicas. -- No se toco `ai/system-metrics.md`. -- No se reactivo Elo/MMR. -- No se reintrodujo Comunidad Hispana #03. -- No se incluyeron cambios previos no relacionados. - -## Change Budget - -- Archivos de producto modificados: 3. -- Sin cambios backend. -- El alcance se mantuvo dentro de la limpieza UI y documentacion de task. diff --git a/ai/tasks/done/TASK-217-add-annual-ranking-snapshots-for-supported-metrics.md b/ai/tasks/done/TASK-217-add-annual-ranking-snapshots-for-supported-metrics.md deleted file mode 100644 index 4e0864e..0000000 --- a/ai/tasks/done/TASK-217-add-annual-ranking-snapshots-for-supported-metrics.md +++ /dev/null @@ -1,198 +0,0 @@ ---- -id: TASK-217 -title: Add annual ranking snapshots for supported metrics -status: done -type: backend -team: Backend Senior -supporting_teams: - - Frontend Senior - - Arquitecto de Base de Datos - - Arquitecto Python -roadmap_item: foundation -priority: high ---- - -# TASK-217 - Add annual ranking snapshots for supported metrics - -## Goal - -Permitir ranking anual para metricas adicionales usando un snapshot anual independiente por metrica, sin runtime publico pesado ni reutilizacion del snapshot top kills para otras metricas. - -## Context - -`TASK-211` dejo la lectura publica anual rapida y basada en `rcon_annual_ranking_snapshots` y `rcon_annual_ranking_snapshot_items`. `TASK-216` mantuvo annual limitado a `kills` porque no habia snapshot propio para otras metricas y corrigio el falso KPM: `kills_per_match` debe mostrarse como `Kills/partida`, no como kills por minuto. - -Esta task amplia la generacion annual para metricas que ya se pueden calcular de forma segura desde los read models materializados durante un proceso interno/CLI. La lectura publica sigue leyendo solo snapshots anuales ya generados. - -Preserve the current product identity: Spanish-speaking HLL Vietnam community, military/Vietnam/tactical/sober visual direction and controlled repository evolution. - -## Steps - -1. Revisar la lectura y generacion anual actual. -2. Confirmar que el esquema permite `metric_value` decimal para ratios. -3. Actualizar la normalizacion de metricas annual soportadas. -4. Generar snapshots independientes por metrica: - - `kills` - - `deaths` - - `teamkills` - - `matches_considered` - - `kd_ratio` - - `kills_per_match` -5. Mantener la lectura publica anual sobre tablas de snapshot, sin fallback runtime. -6. Actualizar frontend para permitir metricas annual soportadas y mostrar `kills_per_match` como `Kills/partida`. -7. Añadir tests de normalizacion, lectura publica y calculo/orden de `kd_ratio` y `kills_per_match`. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `backend/app/rcon_annual_rankings.py` -- `backend/app/payloads.py` -- `frontend/assets/js/ranking.js` - -## Expected Files to Modify - -- `backend/app/rcon_annual_rankings.py` -- `backend/app/rcon_admin_log_materialization.py` -- `backend/app/postgres_rcon_storage.py` -- `backend/tests/test_annual_ranking_payload.py` -- `frontend/ranking.html` -- `frontend/assets/js/ranking.js` -- `ai/tasks/done/TASK-217-add-annual-ranking-snapshots-for-supported-metrics.md` - -## Constraints - -- Keep the change minimal. -- Preserve HLL Vietnam project identity. -- Do not introduce unnecessary frameworks or dependencies. -- No ejecutar `ai-platform run`. -- No hacer push. -- No tocar `frontend/assets/img/weapons/`. -- No tocar SVGs. -- No modificar imagenes fisicas. -- No tocar `ai/system-metrics.md`. -- No reactivar Elo/MMR. -- No reintroducir Comunidad Hispana #03. -- No implementar KPM real en esta task. -- No mostrar `kills_per_match` como KPM. -- No exponer metricas annual sin snapshot anual propio. -- No usar el snapshot top kills para representar otras metricas. -- La lectura publica annual debe leer solo `rcon_annual_ranking_snapshots` y `rcon_annual_ranking_snapshot_items`. - -## Validation - -Before completing the task ensure: - -- `node --check frontend/assets/js/ranking.js` -- `python -m compileall backend\app\rcon_annual_rankings.py backend\app\payloads.py backend\tests\test_annual_ranking_payload.py` -- `python -m unittest backend.tests.test_annual_ranking_payload` -- Medicion directa de `build_global_ranking_payload` annual para metricas soportadas si el entorno local tiene datos. -- `git diff --name-only` matches the expected scope. -- No unrelated files were modified. - -## Outcome - -Archivos modificados por esta task: - -- `backend/app/rcon_annual_rankings.py` -- `backend/app/rcon_admin_log_materialization.py` -- `backend/app/postgres_rcon_storage.py` -- `backend/tests/test_annual_ranking_payload.py` -- `frontend/ranking.html` -- `frontend/assets/js/ranking.js` -- `ai/tasks/done/TASK-217-add-annual-ranking-snapshots-for-supported-metrics.md` - -Metricas anuales soportadas: - -- `kills` -- `deaths` -- `teamkills` -- `matches_considered` -- `kd_ratio` -- `kills_per_match` - -Cambios de backend: - -- `_normalize_metric()` acepta solo las seis metricas anuales soportadas. -- La generacion anual calcula y ordena snapshots independientes por metrica real. -- `kd_ratio` se calcula como `kills / deaths` sobre agregados. -- `kills_per_match` se calcula como `kills / matches_considered` y sigue siendo `Kills/partida`, no KPM. -- La lectura publica anual no cambia de modelo: sigue usando `rcon_annual_ranking_snapshots` y `rcon_annual_ranking_snapshot_items`. -- No se introdujo fallback runtime ni lectura publica sobre `rcon_match_player_stats`. -- Se agregaron tests de normalizacion, rechazo de metrica no soportada, lectura publica sin inicializar storage y orden/calculo para `kd_ratio` y `kills_per_match`. - -Cambios de esquema: - -- Si hubo cambios de esquema. -- `rcon_annual_ranking_snapshots.metric` ahora permite: - - `kills` - - `deaths` - - `teamkills` - - `matches_considered` - - `kd_ratio` - - `kills_per_match` -- `rcon_annual_ranking_snapshot_items.metric_value` pasa de entero a valor decimal: - - SQLite: `REAL` - - PostgreSQL: `DOUBLE PRECISION` -- La inicializacion PostgreSQL incluye una migracion idempotente para ajustar `metric_value` y reemplazar el `CHECK` antiguo. - -Cambios de frontend: - -- Annual permite seleccionar las metricas soportadas. -- No se muestra KPM. -- `kills_per_match` se muestra como `Kills/partida`. -- Se renombraron identificadores internos heredados de KPM a KPP. -- Annual mantiene `2026` interno y no muestra input de año. -- Si falta un snapshot anual, la UI muestra `Snapshot anual no disponible para esta metrica.` sin fallback ni bloqueo. - -Comandos de produccion para generar snapshots anuales 2026: - -```bash -for server in all-servers comunidad-hispana-01 comunidad-hispana-02; do - for metric in kills deaths teamkills matches_considered kd_ratio kills_per_match; do - docker compose exec backend python -m app.rcon_annual_rankings generate \ - --year 2026 \ - --server-key "$server" \ - --metric "$metric" \ - --limit 30 \ - --replace-existing - done -done -``` - -Validaciones ejecutadas: - -- `node --check frontend/assets/js/ranking.js` -- `$env:PYTHONPATH='backend'; python -m compileall backend\app\rcon_annual_rankings.py backend\app\payloads.py backend\tests\test_annual_ranking_payload.py backend\app\postgres_rcon_storage.py backend\app\rcon_admin_log_materialization.py` -- `$env:PYTHONPATH='backend'; python -m unittest backend.tests.test_annual_ranking_payload` -- Busqueda en `frontend/ranking.html` y `frontend/assets/js/ranking.js` para confirmar que no aparecen `KPM`, `Actualizar ranking`, `ranking-year`, `El ranking expone`, `Kills listo`, `listo en` ni `annualMetric`. -- Medicion directa con `build_global_ranking_payload(timeframe="annual", year=2026)` para las seis metricas soportadas. - -Tiempos obtenidos en lectura directa local: - -- `kills`: `1.66 ms`, `snapshot_status=ready`, `read_model=rcon-annual-ranking-snapshot`, `fallback_used=False`, `items=20`. -- `deaths`: `1.17 ms`, `snapshot_status=missing`, `read_model=rcon-annual-ranking-snapshot`, `fallback_used=False`, `items=0`. -- `teamkills`: `1.10 ms`, `snapshot_status=missing`, `read_model=rcon-annual-ranking-snapshot`, `fallback_used=False`, `items=0`. -- `matches_considered`: `1.09 ms`, `snapshot_status=missing`, `read_model=rcon-annual-ranking-snapshot`, `fallback_used=False`, `items=0`. -- `kd_ratio`: `1.11 ms`, `snapshot_status=missing`, `read_model=rcon-annual-ranking-snapshot`, `fallback_used=False`, `items=0`. -- `kills_per_match`: `1.10 ms`, `snapshot_status=missing`, `read_model=rcon-annual-ranking-snapshot`, `fallback_used=False`, `items=0`. - -Confirmacion de exclusiones: - -- No se ejecuto `ai-platform run`. -- No se hizo push. -- No se hizo commit. -- No se tocaron assets de armas. -- No se tocaron SVGs. -- No se modificaron imagenes fisicas. -- No se toco `ai/system-metrics.md`. -- No se reactivo Elo/MMR. -- No se reintrodujo Comunidad Hispana #03. -- No se incluyeron cambios previos no relacionados. - -## Change Budget - -- Archivos modificados por la task: 7. -- El cambio supera el objetivo preferente de 5 archivos porque incluye schema SQLite/PostgreSQL, generador, test, frontend y documentacion de task. -- No se implemento KPM real; queda fuera de alcance hasta materializar tiempo jugado real por jugador. diff --git a/ai/tasks/done/TASK-218-design-player-active-seconds-for-real-kpm.md b/ai/tasks/done/TASK-218-design-player-active-seconds-for-real-kpm.md deleted file mode 100644 index 74fffc6..0000000 --- a/ai/tasks/done/TASK-218-design-player-active-seconds-for-real-kpm.md +++ /dev/null @@ -1,170 +0,0 @@ ---- -id: TASK-218 -title: Design player active seconds for real KPM -status: done -type: documentation -team: Arquitecto de Base de Datos -supporting_teams: - - Backend Senior - - Arquitecto Python -roadmap_item: foundation -priority: high ---- - -# TASK-218 - Design player active seconds for real KPM - -## Goal - -Analizar y disenar como calcular KPM real en HLL Vietnam sin implementar cambios funcionales todavia. - -KPM real se define como: - -```text -kills / minutos_jugados_reales -``` - -No debe confundirse con `kills_per_match`, `Kills/partida` ni kills divididas por duracion completa de partida cuando el jugador no estuvo toda la partida. - -## Context - -`TASK-216` confirmo que hoy no existe tiempo jugado real por jugador materializado para ranking publico. - -Campos encontrados: - -- `rcon_player_profile_snapshots.play_time`: texto de perfil, no normalizado y no por jugador/partida. -- `rcon_match_player_stats.first_seen_server_time` y `last_seen_server_time`: presencia observada por eventos dentro de partida. -- `rcon_materialized_matches.started_at`, `ended_at`, `started_server_time` y `ended_server_time`: duracion de partida, no tiempo por jugador. - -`TASK-217` dejo `kills_per_match` como `Kills/partida` y no implemento KPM real. - -Esta task produce un diseno tecnico accionable para crear `player_active_seconds` o `rcon_match_player_presence` en tasks futuras, sin modificar codigo funcional ni esquema real. - -Preserve the current product identity: Spanish-speaking HLL Vietnam community, military/Vietnam/tactical/sober visual direction and controlled repository evolution. - -## Steps - -1. Revisar fuentes de AdminLog, materializacion, read models y snapshots. -2. Evaluar eventos disponibles para presencia real o observada. -3. Clasificar calidad de datos: `exact`, `observed`, `estimated`, `unknown`. -4. Proponer opciones de modelo de datos. -5. Recomendar una estrategia de backfill y propagacion a read models. -6. Documentar plan de implementacion dividido en tasks. -7. Validar que solo se crearon documentos. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `backend/app/rcon_admin_log_storage.py` -- `backend/app/rcon_admin_log_materialization.py` -- `backend/app/rcon_admin_log_parser.py` - -Tambien se revisaron: - -- `backend/app/postgres_rcon_storage.py` -- `backend/app/rcon_historical_player_stats.py` -- `backend/app/rcon_historical_leaderboards.py` -- `backend/app/rcon_annual_rankings.py` -- `backend/app/historical_runner.py` -- `backend/app/payloads.py` -- `docs/PERFORMANCE_PUBLIC_QUERY_AUDIT.md` -- `ai/tasks/done/TASK-216-clean-ranking-ui-and-fix-kpm-metric.md` -- `ai/tasks/done/TASK-217-add-annual-ranking-snapshots-for-supported-metrics.md` - -## Expected Files to Modify - -- `docs/REAL_KPM_PLAYER_ACTIVE_SECONDS_DESIGN.md` -- `ai/tasks/done/TASK-218-design-player-active-seconds-for-real-kpm.md` - -## Constraints - -- Keep the change minimal. -- Preserve HLL Vietnam project identity. -- Do not introduce unnecessary frameworks or dependencies. -- Do not implement backend functionality. -- Do not change endpoints. -- Do not change frontend. -- Do not change backend functional code. -- Do not change real schema yet. -- No ejecutar `ai-platform run`. -- No hacer push. -- No tocar `frontend/assets/img/weapons/`. -- No tocar SVGs. -- No modificar imagenes fisicas. -- No tocar `ai/system-metrics.md`. -- No reactivar Elo/MMR. -- No reintroducir Comunidad Hispana #03. -- No incluir cambios previos no relacionados. - -## Validation - -Before completing the task ensure: - -- `git status --short --untracked-files=all` -- `git diff --name-only` -- Confirmar que solo se crean/modifican: - - `docs/REAL_KPM_PLAYER_ACTIVE_SECONDS_DESIGN.md` - - `ai/tasks/done/TASK-218-design-player-active-seconds-for-real-kpm.md` - -## Outcome - -Archivos creados: - -- `docs/REAL_KPM_PLAYER_ACTIVE_SECONDS_DESIGN.md` -- `ai/tasks/done/TASK-218-design-player-active-seconds-for-real-kpm.md` - -Conclusion: - -- No se puede calcular KPM real publico hoy. -- La fuente recomendada para `player_active_seconds` es AdminLog con `connected`/`disconnected` cuando sea posible y ventana observada por eventos como fallback etiquetado. -- El modelo recomendado es Opcion C: - - crear `rcon_match_player_presence` como detalle auditable por jugador/partida; - - denormalizar `player_active_seconds` y `playtime_quality` en `rcon_match_player_stats` para agregaciones rapidas. -- KPM futuro debe calcularse en generacion de read models/snapshots como `kills / (player_active_seconds / 60)`, nunca en frontend y nunca usando `kills_per_match`. - -Plan de implementacion propuesto: - -1. `TASK-219-create-rcon-match-player-presence-schema` -2. `TASK-220-materialize-player-presence-from-adminlog` -3. `TASK-221-backfill-player-active-seconds` -4. `TASK-222-denormalize-player-active-seconds-into-match-stats` -5. `TASK-223-extend-player-period-stats-with-kpm` -6. `TASK-224-add-kpm-ranking-snapshots` -7. `TASK-225-expose-real-kpm-in-api-payloads` -8. `TASK-226-show-real-kpm-in-ranking-ui` -9. `TASK-227-validate-kpm-quality-and-performance` - -Riesgos principales: - -- Cobertura incompleta de eventos `connected`/`disconnected`. -- Presencia observada por eventos puede subestimar tiempo activo. -- Duracion completa de partida no representa tiempo por jugador y debe quedar `estimated`. -- Mezclar calidades sin metadata haria KPM enganoso. -- Backfill masivo puede competir con lecturas publicas si no se agenda bien. - -Validacion ejecutada: - -- `git status --short --untracked-files=all` -- `git diff --name-only` - -Confirmacion de exclusiones: - -- No se ejecuto `ai-platform run`. -- No se hizo push. -- No se tocaron assets de armas. -- No se tocaron SVGs. -- No se modificaron imagenes fisicas. -- No se toco `ai/system-metrics.md`. -- No se reactivo Elo/MMR. -- No se reintrodujo Comunidad Hispana #03. -- No se modifico frontend. -- No se modifico backend funcional. -- No se modificaron tests. -- No se modifico esquema real. -- No se incluyeron cambios previos no relacionados. - -## Change Budget - -- Archivos modificados por esta task: 2. -- Sin cambios funcionales. diff --git a/ai/tasks/done/TASK-219-restore-bxb-clan-logo-standard-size.md b/ai/tasks/done/TASK-219-restore-bxb-clan-logo-standard-size.md deleted file mode 100644 index 2fa3941..0000000 --- a/ai/tasks/done/TASK-219-restore-bxb-clan-logo-standard-size.md +++ /dev/null @@ -1,86 +0,0 @@ ---- -id: TASK-219 -title: Restore BxB clan logo standard size -status: done -type: frontend -team: Frontend Senior -supporting_teams: [] -roadmap_item: foundation -priority: medium ---- - -# TASK-219 - Restore BxB clan logo standard size - -## Goal - -Restore the visual size of the BxB logo on the index page so it is equivalent to the other clan logos. - -## Context - -TASK-210 gave BxB a special larger visual treatment. The current request is to return BxB to the original or equivalent standard clan logo sizing without modifying the physical PNG or unrelated assets. - -Preserve the current product identity: Spanish-speaking HLL Vietnam community, military/Vietnam/tactical/sober visual direction and controlled repository evolution. - -## Steps - -1. Inspect the listed files first. -2. Locate the BxB-specific clan card and logo rules. -3. Remove or neutralize only the CSS treatment that makes BxB larger than the standard clan logos. -4. Validate the local index page visually and confirm the change scope. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `ai/orchestrator/frontend-senior.md` -- `frontend/index.html` -- `frontend/assets/css/styles.css` -- `frontend/assets/js/main.js` - -## Expected Files to Modify - -- `frontend/assets/css/styles.css` -- `ai/tasks/in-progress/TASK-219-restore-bxb-clan-logo-standard-size.md` - -## Constraints - -- Keep the change minimal. -- Prefer CSS-only. -- Do not modify physical images. -- Do not touch `frontend/assets/img/clans/`. -- Do not touch weapon assets or SVGs. -- Do not touch backend files or endpoints. -- Do not touch `ai/system-metrics.md`. -- Do not reactivate Elo/MMR. -- Do not reintroduce Comunidad Hispana #03. -- Do not introduce frameworks or dependencies. - -## Validation - -Before completing the task ensure: - -- Inspect the local `frontend/index.html` page visually. -- Confirm BxB has a standard or equivalent logo size compared with the other clan logos. -- Run `node --check frontend/assets/js/main.js` only if JavaScript changes are made. -- Review `git diff --name-only`. -- Confirm changed files match the expected scope. -- Confirm backend, endpoints, assets, SVGs and `ai/system-metrics.md` were not modified by this task. - -## Outcome - -Completed. - -- Removed the BxB-specific clan brand grid override that gave the logo column a wider range than standard clan cards. -- Removed the BxB-specific logo container and image sizing overrides that increased its visual height. -- Kept the existing BxB classes in JavaScript untouched; they no longer enlarge the logo because there is no matching size override in CSS. -- Validated `frontend/index.html` locally with a Chrome headless screenshot opened from the file system. BxB now appears in a standard-size logo container comparable to the other clan cards. -- JavaScript was not modified, so `node --check frontend/assets/js/main.js` was not required. -- `git diff --name-only` was reviewed. The task change is limited to `frontend/assets/css/styles.css` plus this task file; pre-existing unrelated changes are present in `ai/system-metrics.md`, clan image assets and weapon SVG/assets. -- Confirmed this task did not modify backend files, endpoints, physical images, `frontend/assets/img/clans/`, weapon assets, SVGs or `ai/system-metrics.md`. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-220-schedule-public-snapshot-refreshes.md b/ai/tasks/done/TASK-220-schedule-public-snapshot-refreshes.md deleted file mode 100644 index 1e4708d..0000000 --- a/ai/tasks/done/TASK-220-schedule-public-snapshot-refreshes.md +++ /dev/null @@ -1,140 +0,0 @@ ---- -id: TASK-220 -title: Schedule public snapshot refreshes -status: done -type: backend -team: Backend Senior -supporting_teams: ["Arquitecto Python"] -roadmap_item: foundation -priority: high ---- - -# TASK-220 - Schedule public snapshot refreshes - -## Goal - -Configure automatic regeneration of public snapshots and read models at appropriate times, so public pages do not depend on heavy runtime calculations. - -## Context - -Public historical, ranking and stats pages should read precomputed data. Heavy regeneration should happen inside the internal runner during low-load windows, while weekly/monthly ranking and recent matches stay fresh at shorter intervals. - -Preserve the current product identity: Spanish-speaking HLL Vietnam community, military/Vietnam/tactical/sober visual direction and controlled repository evolution. - -## Steps - -1. Inspect the listed files first. -2. Document how the current refresh paths work. -3. Add environment-driven scheduling for daily full refresh, frequent ranking refresh and recent match snapshot refresh. -4. Keep refreshes idempotent and non-overlapping. -5. Document Portainer configuration and manual emergency commands. -6. Validate Python compilation and scheduler helpers. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `ai/orchestrator/backend-senior.md` -- `ai/orchestrator/python-architect.md` -- `backend/app/historical_runner.py` -- `backend/app/rcon_historical_leaderboards.py` -- `backend/app/rcon_annual_rankings.py` -- `backend/app/rcon_historical_player_stats.py` -- `backend/app/historical_snapshot_storage.py` -- `backend/app/historical_snapshots.py` -- `backend/app/payloads.py` -- `backend/app/config.py` -- `backend/app/main.py` -- `docker-compose.yml` -- `README.md` -- `docs/PERFORMANCE_PUBLIC_QUERY_AUDIT.md` - -## Expected Files to Modify - -- `backend/app/config.py` -- `backend/app/historical_runner.py` -- `backend/app/historical_snapshots.py` -- `backend/app/routes.py` -- `backend/tests/test_historical_snapshot_refresh.py` -- `docker-compose.yml` -- `docs/public-snapshot-refresh-schedule.md` -- `ai/tasks/in-progress/TASK-220-schedule-public-snapshot-refreshes.md` - -## Constraints - -- Do not execute `ai-platform run`. -- Do not push or commit. -- Do not touch frontend except documentation if unavoidable. -- Do not touch weapon assets, SVGs or physical images. -- Do not touch `ai/system-metrics.md`. -- Do not reactivate Elo/MMR. -- Do not reintroduce Comunidad Hispana #03. -- Keep public requests on read models/snapshots for rankings. -- Prefer the internal runner over host cron. - -## Validation - -Before completing the task ensure: - -- Run `python -m compileall` for modified backend modules. -- Run relevant existing backend tests if applicable. -- Validate scheduler helper behavior for the next 06:00 Europe/Madrid. -- Confirm public route modules still compile. -- Review `git diff --name-only`. -- Confirm no frontend, weapon assets, SVGs, physical images or `ai/system-metrics.md` were modified by this task. - -## Outcome - -Completed. - -Current-state analysis: - -- `ranking_snapshots` weekly/monthly were generated by `refresh_ranking_snapshots()` and invoked from `historical_runner` once per historical runner cycle. Compose forced `--hourly`, so public rankings could wait up to an hour despite the code recommending 5-15 minute freshness. -- Annual ranking snapshots existed through `generate_annual_ranking_snapshot()` but were only manual/CLI-driven, not part of the runner schedule. -- `player_search_index` and `player_period_stats` were refreshed from `historical_runner` once per runner cycle. -- Recent matches were included in full/priority historical snapshots, but there was no dedicated short-cadence refresh. RCON capture exposed `materialized_matches_inserted`, which can be used as a finished-match hook. -- `historical_runner` already existed and is the right place for internal scheduling; no host cron is required. -- Public historical snapshot leaderboard routes in RCON mode were using a runtime materialized fast path despite being snapshot endpoints. - -Implemented strategy: - -- Added public refresh env configuration with safe defaults. -- Kept the internal runner as scheduler and removed the Compose `--hourly` override so the runner can tick at the shortest public interval while still throttling the heavier historical cycle separately. -- Added daily public full refresh logic, due once per local day after `06:00 Europe/Madrid`. -- Added frequent weekly/monthly ranking snapshot refresh at `HLL_PUBLIC_RANKING_REFRESH_INTERVAL_SECONDS`. -- Added recent-match-only snapshot generation and scheduled it at `HLL_PUBLIC_RECENT_MATCHES_REFRESH_INTERVAL_SECONDS`. -- Added immediate recent-match refresh when RCON capture reports newly materialized finished matches. -- Added structured start/end logs, durations and per-step results. Per-step failures are captured without stopping neighboring refreshes or the runner. -- Added in-process non-overlap guards for public refresh classes. -- Changed public historical leaderboard snapshot routes to read persisted snapshots instead of the RCON runtime fast path. -- Documented Portainer configuration and emergency commands in `docs/public-snapshot-refresh-schedule.md`. - -Validation: - -- `python -m compileall backend/app/config.py backend/app/historical_runner.py backend/app/historical_snapshots.py backend/app/routes.py` -- `python -m compileall backend/app backend/tests` -- `$env:PYTHONPATH='backend'; python -m unittest backend.tests.test_historical_snapshot_refresh` -- `$env:PYTHONPATH='backend'; python -m unittest backend.tests.test_annual_ranking_payload` -- Dry-run scheduler helper check: - - `2026-06-10T03:30:00Z` -> next refresh `2026-06-10T04:00:00Z` (`06:00 Europe/Madrid`) - - `2026-06-10T05:00:00Z` -> next refresh `2026-06-11T04:00:00Z` -- Route dry-run with patched builder confirmed `/api/historical/snapshots/leaderboard` resolves through `build_leaderboard_snapshot_payload`. -- `git diff --name-only` reviewed. - -Exclusions: - -- Did not execute `ai-platform run`. -- Did not push or commit. -- Did not modify frontend files as part of this task. -- Did not modify physical images, weapon assets, SVGs or `ai/system-metrics.md`. -- Did not reactivate Elo/MMR. -- Did not reintroduce Comunidad Hispana #03. - -Note: the worktree still contains pre-existing unrelated changes in `ai/system-metrics.md`, `frontend/assets/css/styles.css`, clan image files and weapon/SVG assets. They were not touched by this task. - -## Change Budget - -- Prefer fewer than 5 modified files when feasible. -- Prefer changes under 200 lines when feasible. -- Split follow-up tasks if scope grows. diff --git a/ai/tasks/done/TASK-221-fix-historico-loading-and-recent-matches-performance.md b/ai/tasks/done/TASK-221-fix-historico-loading-and-recent-matches-performance.md deleted file mode 100644 index 489e247..0000000 --- a/ai/tasks/done/TASK-221-fix-historico-loading-and-recent-matches-performance.md +++ /dev/null @@ -1,133 +0,0 @@ ---- -id: TASK-221 -title: Fix Historico loading and recent matches performance -status: in-progress -type: frontend -team: Frontend Senior -supporting_teams: ["Backend Senior"] -roadmap_item: foundation -priority: high ---- - -# TASK-221 - Fix Historico loading and recent matches performance - -## Goal - -Make the Historico screen load weekly/monthly tops and recent matches quickly from snapshots/read models, without blank limbo states or public-request heavy calculations. - -## Context - -The Historico page currently shows slow weekly/monthly top loading and recent matches can stay visually empty for several seconds. These public views should read precomputed snapshots or simple read models, and latest matches should be refreshed by the runner when matches finish or by short polling. - -Preserve the current product identity: Spanish-speaking HLL Vietnam community, military/Vietnam/tactical/sober visual direction and controlled repository evolution. - -## Steps - -1. Inventory the exact frontend endpoints and backend functions used by Historico. -2. Identify frontend loading states that produce blank UI or unnecessary waits. -3. Ensure weekly/monthly top endpoints use snapshot-only public reads. -4. Ensure recent matches endpoint avoids RCON, scoreboard and heavy recalculation in public requests. -5. Validate frontend syntax, backend compilation and relevant tests. - -## Files to Read First - -- `AGENTS.md` -- `ai/repo-context.md` -- `ai/architecture-index.md` -- `ai/orchestrator/frontend-senior.md` -- `ai/orchestrator/backend-senior.md` -- `frontend/historico.html` -- `frontend/assets/js/historico.js` -- `frontend/assets/css/historico.css` -- `backend/app/routes.py` -- `backend/app/payloads.py` -- `backend/app/historical_snapshot_storage.py` -- `backend/app/historical_snapshots.py` -- `backend/app/rcon_historical_read_model.py` -- `backend/app/postgres_rcon_storage.py` - -## Expected Files to Modify - -- `frontend/assets/js/historico.js` -- `frontend/assets/js/historico-recent-live.js` -- `backend/app/payloads.py` -- `backend/tests/test_historical_snapshot_refresh.py` -- `ai/tasks/in-progress/TASK-221-fix-historico-loading-and-recent-matches-performance.md` - -## Constraints - -- Do not execute `ai-platform run`. -- Do not push or commit. -- Do not touch weapon assets, SVGs or physical images. -- Do not touch `ai/system-metrics.md`. -- Do not reactivate Elo/MMR. -- Do not reintroduce Comunidad Hispana #03. -- Do not include unrelated prior changes. - -## Validation - -- `node --check frontend/assets/js/historico.js` -- `python -m compileall` for modified backend modules. -- Relevant backend tests. -- Measure or provide measurement commands for weekly top, monthly top and recent matches. -- Confirm public requests do not use RCON, scoreboard fallback or runtime leaderboard aggregation. -- Confirm no protected files/assets were touched by this task. - -## Outcome - -Done. - -Inventory: - -- Weekly top: `GET /api/historical/snapshots/leaderboard?server=&timeframe=weekly&metric=&limit=10`, called from `frontend/assets/js/historico.js`. Backend route: `routes.resolve_get_payload` -> `build_leaderboard_snapshot_payload`. Expected data: precomputed historical snapshot via `historical_snapshot_storage.get_historical_snapshot`, stored in `displayed_historical_snapshots` on PostgreSQL or JSON fallback. Public request must not call RCON, scoreboard, storage initialization or runtime leaderboard aggregation. -- Monthly top: `GET /api/historical/snapshots/leaderboard?server=&timeframe=monthly&metric=&limit=10`, same frontend/backend path as weekly with `timeframe=monthly`. Expected data: same precomputed snapshot path. -- Recent matches primary snapshot: `GET /api/historical/snapshots/recent-matches?server=&limit=100`, called from `frontend/assets/js/historico.js`. Backend route: `build_recent_historical_matches_snapshot_payload`. Expected data: precomputed `recent-matches` snapshot via `displayed_historical_snapshots` or JSON fallback. Generated out of band from materialized RCON matches. -- Recent matches live updater: before this task `frontend/assets/js/historico-recent-live.js` also called `GET /api/historical/recent-matches?server=&limit=100`. Backend route: `build_recent_historical_matches_payload`, which can use the RCON historical read model and public scoreboard fallback. It now calls `GET /api/historical/snapshots/recent-matches?server=&limit=100`. -- Server summary: `GET /api/historical/snapshots/server-summary?server=`, called from `frontend/assets/js/historico.js`. Backend route: `build_historical_server_summary_snapshot_payload`, using precomputed snapshots only. - -Cause: - -- The public leaderboard snapshot builder could still runtime-enrich items missing `total_time_seconds` by calling `_load_runtime_leaderboard_items`, which delegates to weekly/monthly runtime leaderboard builders. -- The public recent-matches snapshot builder could complete a partial snapshot by calling `list_recent_historical_matches`, adding scoreboard/RCON-backed work to a public request. -- `historico-recent-live.js` was overwriting the same recent-matches panel from `/api/historical/recent-matches`, bypassing the snapshot path used by `historico.js`. -- The initial recent-matches render cleared the list before data arrived, and on errors it could leave loading placeholders visible. - -Implemented strategy: - -- Leaderboard snapshot public requests now return only persisted snapshot items and mark runtime enrichment as disabled on the public snapshot path. -- Recent-matches snapshot public requests now return only persisted snapshot items; no public scoreboard/RCON completion is attempted. -- The live recent-matches frontend updater now reads `/api/historical/snapshots/recent-matches` and polls every 60 seconds, relying on the runner/snapshot refresh to pick up finished matches. -- The recent-matches panel now renders compact loading placeholders instead of a blank area, and clears them on error. - -Timing: - -- HTTP endpoint measurement was not possible because `http://127.0.0.1:8000/health` timed out in the local environment. -- In-process snapshot payload timing with mocked persisted snapshots: - - weekly snapshot payload: `0.009 ms` average over 1000 calls - - monthly snapshot payload: `0.007 ms` average over 1000 calls - - recent matches snapshot payload: `0.006 ms` average over 1000 calls -- Commands to measure real endpoints when the backend is running: - - `Measure-Command { Invoke-WebRequest -UseBasicParsing "http://127.0.0.1:8000/api/historical/snapshots/leaderboard?server=all-servers&timeframe=weekly&metric=kills&limit=10" }` - - `Measure-Command { Invoke-WebRequest -UseBasicParsing "http://127.0.0.1:8000/api/historical/snapshots/leaderboard?server=all-servers&timeframe=monthly&metric=kills&limit=10" }` - - `Measure-Command { Invoke-WebRequest -UseBasicParsing "http://127.0.0.1:8000/api/historical/snapshots/recent-matches?server=all-servers&limit=100" }` - -Validation: - -- `node --check frontend/assets/js/historico.js` -- `node --check frontend/assets/js/historico-recent-live.js` -- `python -m compileall backend/app/payloads.py` -- `$env:PYTHONPATH='backend'; python -m unittest backend.tests.test_historical_snapshot_refresh` -- Local visual inspection with Chrome headless against `frontend/historico.html`. Browser plugin invocation failed because `iab` was unavailable; Playwright CLI was present but browser binaries were not installed, so Chrome headless was used. With backend unavailable, Historico showed compact error states and no blank recent-matches limbo. - -Exclusions: - -- Did not execute `ai-platform run`. -- Did not push or commit. -- This task did not touch weapon assets, SVGs, physical images or `ai/system-metrics.md`. -- Did not reactivate Elo/MMR. -- Did not reintroduce Comunidad Hispana #03. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. diff --git a/ai/tasks/done/TASK-222-fix-historical-match-detail-backend-url-and-false-kpm.md b/ai/tasks/done/TASK-222-fix-historical-match-detail-backend-url-and-false-kpm.md deleted file mode 100644 index 4bb68eb..0000000 --- a/ai/tasks/done/TASK-222-fix-historical-match-detail-backend-url-and-false-kpm.md +++ /dev/null @@ -1,154 +0,0 @@ ---- -id: TASK-222 -title: Fix historical match detail backend URL and false KPM -status: done -type: frontend -team: Frontend Senior -supporting_teams: - - Backend Senior -roadmap_item: foundation -priority: high ---- - -# TASK-222 - Fix historical match detail backend URL and false KPM - -## Goal - -Corregir `frontend/historico-partida.html` para que el detalle de una partida historica no intente conectar con `127.0.0.1:8000` en produccion y eliminar el KPM falso calculado con la duracion total de la partida. - -## Context - -La pagina de detalle historico lee `/api/historical/matches/detail?server=&match=`. En produccion, el frontend no debe usar `http://127.0.0.1:8000` como backend por defecto porque eso apunta al PC del usuario. Ademas, la tabla de jugadores mostraba KPM calculado como `kills / duration_seconds` de la partida completa, lo que no representa tiempo real jugado por jugador. - -Preserve the current product identity: Spanish-speaking HLL Vietnam community, military/Vietnam/tactical/sober visual direction and controlled repository evolution. - -## Steps - -1. Leer primero los archivos listados y confirmar el fallback de backend y el uso de KPM. -2. Corregir la resolucion de URL de backend en `historico-partida.js` sin ampliar el alcance a otros modulos. -3. Confirmar que el detalle sigue llamando a `/api/historical/matches/detail?server=&match=`. -4. Eliminar de `historico-partida` la exposicion de KPM si no existe `player_active_seconds` real. -5. Validar sintaxis y revisar el alcance del diff. - -## Files to Read First - -- `ai/architecture-index.md` -- `ai/repo-context.md` -- `ai/orchestrator/frontend-senior.md` -- `frontend/historico-partida.html` -- `frontend/assets/js/historico-partida.js` -- `docs/REAL_KPM_PLAYER_ACTIVE_SECONDS_DESIGN.md` - -Tambien se revisaron: - -- `frontend/assets/js/historico.js` -- `frontend/assets/js/historico-recent-live.js` -- `frontend/assets/js/ranking.js` -- `frontend/assets/js/config.js` -- `frontend/assets/css/historico.css` -- `ai/tasks/done/TASK-216-clean-ranking-ui-and-fix-kpm-metric.md` - -## Expected Files to Modify - -- `frontend/historico-partida.html` -- `frontend/assets/js/historico-partida.js` -- `ai/tasks/done/TASK-222-fix-historical-match-detail-backend-url-and-false-kpm.md` - -## Constraints - -- Keep the change minimal. -- Preserve HLL Vietnam project identity. -- Do not introduce unnecessary frameworks or dependencies. -- Do not implement backend functionality unless frontend diagnosis proves it is necessary. -- No ejecutar `ai-platform run`. -- No hacer push. -- No tocar assets de armas. -- No tocar SVGs. -- No modificar imagenes fisicas. -- No tocar `ai/system-metrics.md`. -- No reactivar Elo/MMR. -- No reintroducir Comunidad Hispana #03. -- No incluir cambios previos no relacionados. -- Mantener compatibilidad con desarrollo local si existe `data-backend-base-url`. -- No publicar KPM sin `player_active_seconds` real. - -## Validation - -Before completing the task ensure: - -- `node --check frontend/assets/js/historico-partida.js` -- Si se tocan otros JS, `node --check` tambien. -- Validar por navegador o inspeccion que el detalle no intenta `127.0.0.1`. -- Confirmar que la llamada de detalle usa `/api/historical/matches/detail?server=&match=`. -- Validar que no queda texto KPM falso en `historico-partida`. -- `git diff --name-only` matches the expected scope, except pre-existing unrelated changes. -- Confirmar que no se tocaron backend, assets de armas, SVGs, imagenes fisicas ni `ai/system-metrics.md`. - -## Outcome - -Archivos modificados por esta task: - -- `frontend/historico-partida.html` -- `frontend/assets/js/historico-partida.js` -- `ai/tasks/done/TASK-222-fix-historical-match-detail-backend-url-and-false-kpm.md` - -Causa exacta corregida: - -- `frontend/historico-partida.html` tenia `data-backend-base-url="http://127.0.0.1:8000"`. -- `frontend/assets/js/historico-partida.js` usaba `document.body.dataset.backendBaseUrl || "http://127.0.0.1:8000"`. -- En produccion, esa combinacion podia construir llamadas contra el localhost del usuario. La pagina de detalle ya no define localhost en el HTML y el JS resuelve primero `data-backend-base-url` si existe, luego `window.HLL_FRONTEND_CONFIG.backendBaseUrl`, y si no hay configuracion usa URL relativa para `/api`. - -Endpoint de detalle: - -- Se confirmo que `historico-partida.js` mantiene la llamada a `/api/historical/matches/detail?server=&match=`. -- El backend local no estaba escuchando en `http://127.0.0.1:8000`, por lo que no se pudo obtener una respuesta real del endpoint local. -- No se toco backend porque el fallo confirmado en esta task era frontend y no hubo evidencia de error backend. - -Decision sobre KPM falso: - -- Se elimino KPM del detalle de partida hasta que exista `player_active_seconds` real. -- Se quitaron la opcion de orden `KPM`, la cabecera de columna `KPM`, la celda por jugador, el chip del panel ampliado y las funciones `formatKpm`/`getKpmValue`. -- `duration_seconds` permanece solo para mostrar la duracion de la partida en el marcador, no para calcular rendimiento por jugador. -- No se toco la logica de ranking `Kills/partida` corregida en `TASK-216`. - -Otros fallbacks localhost detectados: - -- Siguen existiendo paginas publicas con `data-backend-base-url="http://127.0.0.1:8000"` o JS que lee ese dataset en `stats`, `historico`, `ranking`, `partida-actual`, `index` y `historico-recent-live`. -- No se corrigieron en esta task para no ampliar alcance. `frontend/assets/js/config.js` ya tiene una capa de reescritura defensiva, pero esos puntos quedan como deuda de endurecimiento fuera de esta causa directa. - -Validaciones ejecutadas: - -- `node --check frontend/assets/js/historico-partida.js` -- `rg -n "KPM|getKpmValue|formatKpm|kpm|kills_per_minute|player_active_seconds" frontend/historico-partida.html frontend/assets/js/historico-partida.js` -- `rg -n "api/historical/matches/detail|server=|match=" frontend/assets/js/historico-partida.js` -- `Invoke-WebRequest -UseBasicParsing -Uri 'http://127.0.0.1:8000/api/historical/matches/detail?server=all-servers&match=__validation__' -TimeoutSec 5` -- `git diff --name-only` -- `git status --short -- ai/tasks/pending ai/tasks/in-progress ai/tasks/done frontend/historico-partida.html frontend/assets/js/historico-partida.js backend frontend/assets/img/weapons ai/system-metrics.md` - -Resultado de validaciones: - -- `node --check` paso sin errores. -- No queda texto ni funcion KPM en `historico-partida.html` ni `historico-partida.js`. -- La llamada de detalle conserva el endpoint esperado. -- La prueba HTTP local fallo con `No es posible conectar con el servidor remoto`; se documenta como backend local no disponible, no como fallo del endpoint. -- El navegador integrado no estaba disponible en esta sesion (`iab` no expuesto), asi que la validacion de red en navegador no pudo ejecutarse. La URL construida queda relativa cuando no hay backend configurado, por lo que ya no apunta a `127.0.0.1`. - -Confirmacion de exclusiones: - -- No se ejecuto `ai-platform run`. -- No se hizo push. -- No se hizo commit. -- No se toco backend. -- No se tocaron assets de armas. -- No se tocaron SVGs. -- No se modificaron imagenes fisicas. -- No se toco `ai/system-metrics.md`. -- No se reactivo Elo/MMR. -- No se reintrodujo Comunidad Hispana #03. -- No se incluyeron cambios previos no relacionados. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-223-optimize-historical-match-detail-payload.md b/ai/tasks/done/TASK-223-optimize-historical-match-detail-payload.md deleted file mode 100644 index c0f131d..0000000 --- a/ai/tasks/done/TASK-223-optimize-historical-match-detail-payload.md +++ /dev/null @@ -1,183 +0,0 @@ ---- -id: TASK-223 -title: Optimize historical match detail payload -status: done -type: backend -team: Backend Senior -supporting_teams: - - Frontend Senior -roadmap_item: foundation -priority: high ---- - -# TASK-223 - Optimize historical match detail payload - -## Goal - -Corregir la lentitud extrema de `/api/historical/matches/detail` para la partida historica RCON `comunidad-hispana-01:1781023156:1781028555:purpleheartlanewarfare`, que tarda alrededor de 55 segundos dentro del backend con 140 jugadores y provoca timeout/error publico. - -## Context - -La evidencia indica que el payload no es grande: unos 150 KB para 140 jugadores. La lentitud se produce durante la construccion del detalle, probablemente por enriquecimiento costoso o patron N+1 de perfiles/jugadores. - -Preserve the current product identity: Spanish-speaking HLL Vietnam community, military/Vietnam/tactical/sober visual direction and controlled repository evolution. - -## Steps - -1. Perfilar `build_historical_match_detail_payload()` o `get_rcon_historical_match_detail()` para la partida problematica antes de cambiar codigo. -2. Identificar funciones lentas y confirmar si `profile_summary`, enlaces externos, `top_weapons`, `most_killed`, `death_by`, victims o nemesis generan trabajo por jugador. -3. Optimizar el detalle inicial para que sirva metadata, marcador y lista basica de jugadores sin enriquecimiento historico global pesado. -4. Mantener en el payload inicial las estadisticas de la partida que ya vengan del read model: kills, deaths, teamkills, KD, armas, abatidos y muertes por rival si no requieren queries extra. -5. Si `profile_summary` resulta costoso, quitarlo o hacerlo opcional en el detalle inicial y dejarlo para endpoint diferido futuro. -6. Confirmar que `historico-partida.js` sigue funcionando sin `profile_summary`. -7. Validar backend, frontend si se toca, endpoint interno y endpoint publico cuando sea posible. - -## Files to Read First - -- `ai/architecture-index.md` -- `ai/repo-context.md` -- `ai/orchestrator/backend-senior.md` -- `backend/app/rcon_historical_read_model.py` -- `backend/app/payloads.py` -- `frontend/assets/js/historico-partida.js` -- `ai/tasks/done/TASK-222-fix-historical-match-detail-backend-url-and-false-kpm.md` -- `docs/PERFORMANCE_PUBLIC_QUERY_AUDIT.md` - -## Expected Files to Modify - -- `backend/app/rcon_historical_read_model.py` -- `backend/tests/test_rcon_materialization_pipeline.py` -- `ai/tasks/done/TASK-223-optimize-historical-match-detail-payload.md` - -## Constraints - -- Keep the change minimal. -- Preserve HLL Vietnam project identity. -- Do not introduce unnecessary frameworks or dependencies. -- Do not run `ai-platform run`. -- Do not push. -- Do not touch weapon assets. -- Do not touch SVGs. -- Do not modify physical images. -- Do not touch `ai/system-metrics.md`. -- Do not reactivate Elo/MMR. -- Do not reintroduce Comunidad Hispana #03. -- Do not include unrelated previous changes. -- Do not introduce runtime RCON or scoreboard queries in the public request. -- Do not reintroduce false KPM. - -## Validation - -Before completing the task ensure: - -- Profiling output before and after the backend change is recorded in the outcome. -- `python -m compileall backend/app` if backend is touched. -- Relevant backend tests run, or a small focused test is added if coverage is missing. -- `node --check frontend/assets/js/historico-partida.js` if frontend is touched. -- The problematic internal endpoint is measured and returns under 1 second if the local environment can reach the same data. -- The public endpoint is checked for 200/found=true if publicly reachable from the current environment. -- Visual validation confirms the detail page renders marcador, mapa and players and does not show KPM if a browser target is available. -- `git diff --name-only` matches expected scope, except pre-existing unrelated changes. -- Confirm excluded files/assets were not touched. - -## Outcome - -Archivos modificados por esta task: - -- `backend/app/rcon_historical_read_model.py` -- `backend/tests/test_rcon_materialization_pipeline.py` -- `ai/tasks/done/TASK-223-optimize-historical-match-detail-payload.md` - -Causa encontrada: - -- En el path RCON materializado, `_build_materialized_detail_item()` cargaba siempre `get_latest_rcon_player_profile_summaries()` para todos los jugadores de la partida antes de devolver el detalle inicial. -- Ese enriquecimiento no pertenece al detalle basico de partida: trae historico global de perfil por jugador (`sessions`, `matches_played`, `favorite_weapons`, `victims`, `nemesis`, `averages`, `sanctions`) y parsea esos JSON para cada perfil devuelto. -- No se encontro N+1 en Python para `top_weapons`, `most_killed` o `death_by`: salen de JSON ya materializado en `rcon_match_player_stats` para esa partida. -- `external_profile_links` es barato: se deriva localmente desde `player_id` con `build_external_player_profile_fields()`, sin consulta extra. -- El patron lento confirmado por codigo queda en `profile_summary`, no en el tamano del payload ni en la renderizacion frontend. - -Profiling ejecutado: - -- Comando de perfil solicitado contra `build_historical_match_detail_payload()` para `comunidad-hispana-01:1781023156:1781028555:purpleheartlanewarfare`. -- En este entorno no estaba configurada la misma base PostgreSQL de produccion y Docker no estaba disponible (`docker compose ps` no pudo conectar con Docker Desktop), por lo que el perfil local cayo a fallback SQLite con `found=false`. -- Antes del cambio, perfil local disponible: - - `seconds`: 5.333 - - `found`: false - - `players`: 0 - - `source`: `historical-crcon-storage` - - `fallback_used`: true - - cuello local no representativo: `historical_storage.initialize_historical_storage()` y normalizacion SQLite legacy. -- Despues del cambio, perfil local disponible: - - `seconds`: 3.644 - - `found`: false - - `players`: 0 - - `source`: `historical-crcon-storage` - - `fallback_used`: true - - sigue sin ser medicion representativa de la partida RCON porque no alcanza el read model real. -- Evidencia inicial de produccion recibida para el caso real: - - `seconds`: 55.137 - - `http`: 200 - - `bytes`: 150813 - - `players`: 140 - - `source`: `rcon-historical-competitive-read-model` - - `fallback_used`: false - -Solucion aplicada: - -- El detalle inicial RCON ya no llama a `get_latest_rcon_player_profile_summaries()`. -- `_build_player_row()` ahora devuelve solo datos propios de la partida: - - `player_name` - - `team` - - `kills` - - `deaths` - - `teamkills` - - `kd_ratio` - - `top_weapons` - - `most_killed` - - `death_by` - - `external_profile_links` derivados localmente -- `profile_summary` queda diferido para una futura ruta lazy por jugador si se necesita mostrar historico global al expandir una fila. - -Frontend: - -- No se modifico `frontend/assets/js/historico-partida.js`. -- La UI ya no dependia de `profile_summary`; renderiza tabla y panel expandible con datos de partida, enlaces externos y mensajes `No disponible` cuando faltan listas ampliadas. -- No se reintrodujo KPM. -- La llamada relativa `/api/historical/matches/detail` se mantiene intacta. - -Validaciones ejecutadas: - -- `python -m compileall backend/app` -- `python -m unittest tests.test_rcon_materialization_pipeline.RconMaterializationPipelineTests.test_match_detail_omits_profile_summary_when_snapshot_exists` -- `python -m unittest tests.test_rcon_materialization_pipeline` -- Perfil local con `cProfile` antes y despues, documentado arriba. -- `Invoke-WebRequest` contra `http://127.0.0.1:8000/api/historical/matches/detail?...` fallo con `No es posible conectar con el servidor remoto`; no habia backend local escuchando. -- `docker compose ps` fallo porque Docker Desktop no estaba disponible en esta sesion. -- `git diff --name-only` revisado. - -Resultado de validaciones: - -- `compileall` paso. -- La suite `tests.test_rcon_materialization_pipeline` paso: 9 tests OK. -- La suite emite `ResourceWarning` de conexiones SQLite no cerradas ya existentes en esos tests, pero no falla. -- No se pudo validar el endpoint publico real ni visualmente por falta de URL publica absoluta/backend activo en este entorno. - -Confirmacion de exclusiones: - -- No se ejecuto `ai-platform run`. -- No se hizo push. -- No se hizo commit. -- No se tocaron assets de armas. -- No se tocaron SVGs. -- No se modificaron imagenes fisicas. -- No se toco `ai/system-metrics.md`. -- No se reactivo Elo/MMR. -- No se reintrodujo Comunidad Hispana #03. -- No se toco backend de rankings/snapshots. -- No se incluyeron cambios previos no relacionados. `git status` muestra cambios preexistentes en `ai/system-metrics.md`, assets de armas/SVGs y otros archivos no relacionados; esta task los dejo intactos. - -## Change Budget - -- Prefer fewer than 5 modified files. -- Prefer changes under 200 lines when feasible. -- Split the work into follow-up tasks if limits are exceeded. diff --git a/ai/tasks/done/TASK-224-full-application-request-audit.md b/ai/tasks/done/TASK-224-full-application-request-audit.md deleted file mode 100644 index c3e58b4..0000000 --- a/ai/tasks/done/TASK-224-full-application-request-audit.md +++ /dev/null @@ -1,167 +0,0 @@ ---- -id: TASK-224 -title: Full application request audit -status: done -type: research -team: Analista -supporting_teams: - - Backend Senior - - Frontend Senior - - Arquitecto Python - - Arquitecto de Base de Datos -roadmap_item: foundation -priority: high ---- - -# TASK-224 - Full application request audit - -## Goal - -Discover, classify, measure and document all relevant public application requests across frontend and backend/API without applying functional fixes. - -## Context - -Recent public ranking/snapshot optimizations were followed by a regression in `historico-partida.html` and `/api/historical/matches/detail`. Production profiling showed the real bottleneck was storage initialization during a public read path: - -- `get_rcon_historical_match_detail()`: 14.193s -- `get_materialized_rcon_match_detail()`: 14.167s -- `initialize_postgres_rcon_storage()`: 14.147s -- `initialize_rcon_materialized_storage()`: 14.133s -- storage read after initialization: 0.224s -- payload build: 0.014s - -This task audits the complete public request surface to find other endpoints with similar cold-read initialization, DDL/bootstrap, direct live network calls or heavyweight fallback behavior. - -## Steps - -1. Inspect repository context, architecture notes and relevant orchestrator role guidance. -2. Review `backend/app/routes.py` and extract all public GET routes. -3. Review `backend/app/payloads.py` and storage/read-model modules reached by payload builders. -4. Search backend for `initialize_*`, `ensure_*`, DDL, migration, bootstrap, fallback, direct RCON and external HTTP paths. -5. Review public frontend HTML and JavaScript request construction. -6. Create an executable public request audit script using stdlib only. -7. Run the audit against production when available and document measured results. -8. Write the full request matrix and prioritized follow-up tasks. - -## Files to Read First - -- `AGENTS.md` -- `ai/architecture-index.md` -- `ai/repo-context.md` -- `ai/orchestrator/analyst.md` -- `ai/orchestrator/backend-senior.md` -- `ai/orchestrator/frontend-senior.md` -- `backend/app/routes.py` -- `backend/app/payloads.py` -- `frontend/*.html` -- `frontend/assets/js/*.js` - -## Expected Files to Modify - -- `ai/tasks/done/TASK-224-full-application-request-audit.md` -- `docs/FULL_APPLICATION_REQUEST_AUDIT.md` -- `scripts/audit_public_requests.py` -- `tmp/public_request_audit.json` -- `tmp/audit_prod_stdout.txt` -- `tmp/audit_prod_stderr.txt` - -## Constraints - -- Do not run `ai-platform run`. -- Do not commit. -- Do not push. -- Do not apply functional fixes. -- Do not optimize production code except for audit tooling. -- Do not touch weapon assets, clan assets, SVGs or physical images. -- Do not modify `ai/system-metrics.md`. -- Do not reactivate Elo/MMR. -- Do not add unrelated prior changes. - -## Validation - -Executed: - -```powershell -python -m compileall backend\app -python -m py_compile scripts\audit_public_requests.py -cd backend -python -m unittest tests.test_rcon_materialization_pipeline -``` - -Results: - -- `python -m compileall backend\app`: passed. -- `python -m py_compile scripts\audit_public_requests.py`: passed. -- `python -m unittest tests.test_rcon_materialization_pipeline`: passed, 9 tests in 0.588s. Existing tests emitted `ResourceWarning` for unclosed SQLite connections but did not fail. - -Runtime audit: - -- Local backend health check against `http://127.0.0.1:8000/health`: unavailable from host, so local endpoint matrix was not launched. -- Production audit against `https://comunidadhll.devzamode.es`: launched 191 probes and wrote `tmp/public_request_audit.json`. -- Manual player-dependent probes launched after deriving `player_id=76561198092154180` from ranking data. - -Production automatic summary: - -- OK: 77 -- WARNING: 110 -- CRITICAL: 4 -- HTTP 200: 187 -- HTTP 500: 1 -- timeout/error without HTTP status: 3 - -Manual player-dependent summary: - -- OK: 0 -- WARNING: 2 -- CRITICAL: 2 - -Combined measured summary: - -- OK: 77 -- WARNING: 112 -- CRITICAL: 6 - -## Outcome - -Created `docs/FULL_APPLICATION_REQUEST_AUDIT.md` with: - -- Executive summary. -- Backend route inventory. -- Frontend fetch inventory. -- Full request matrix with public backend routes, frontend fetches, static assets and internal runners. -- Endpoint severity tables. -- Initialization-in-read detection. -- Heavy fallback detection. -- Frontend loading/error/timeout audit. -- Top risks and prioritized recommendations. -- Proposed follow-up tasks. -- Exact commands to rerun the audit locally, in production and from the backend container. - -Created `scripts/audit_public_requests.py` with: - -- Configurable base URL and timeout. -- Representative public GET probes. -- HTTP status, elapsed time, response size and JSON metadata extraction. -- Non-fatal endpoint failures. -- JSON output to `tmp/public_request_audit.json` by default. -- Static discovery for backend routes, frontend API literals, `fetch(` occurrences and localhost references. - -Key findings: - -1. `/api/stats/players/search` times out at 30s in production. -2. `/api/stats/players/{player_id}` weekly/monthly times out at 30s in production. -3. `/api/current-match/kills` times out or returns 500. -4. `/api/current-match/players` times out for `comunidad-hispana-01`. -5. `/api/servers` can spend 4.3s refreshing RCON live data during a public GET. -6. `/api/historical/matches/detail` responded OK for the known real match in this audit, but still has a static initialization-in-read chain and needs later hardening. -7. 13 frontend localhost/127.0.0.1 references remain in public HTML/JS, mitigated by `config.js` but still worth hardening. - -Next recommended fix: - -1. Fix `/api/stats/players/search` and `/api/stats/players/{player_id}` first by making the public read path strict read-only, without `initialize_*` or runtime fallback. -2. Fix `/api/current-match/kills` and `/api/current-match/players` next. -3. Harden `/api/historical/matches/detail` after those, unless new profiling shows it regressed again. - -## Change Budget - -Files changed by this task are audit/documentation/support files only. No product logic files were modified. diff --git a/ai/tasks/done/TASK-225-stabilize-critical-public-api-endpoints.md b/ai/tasks/done/TASK-225-stabilize-critical-public-api-endpoints.md deleted file mode 100644 index 336cec4..0000000 --- a/ai/tasks/done/TASK-225-stabilize-critical-public-api-endpoints.md +++ /dev/null @@ -1,140 +0,0 @@ ---- -id: TASK-225 -title: Stabilize critical public API endpoints -status: done -type: backend -team: Backend Senior -supporting_teams: - - Analista - - Arquitecto Python - - Arquitecto de Base de Datos -roadmap_item: foundation -priority: high ---- - -# TASK-225 - Stabilize critical public API endpoints - -## Goal - -Apply focused functional fixes from `docs/FULL_APPLICATION_REQUEST_AUDIT.md` to stabilize the highest-priority public API endpoints that timed out or paid storage initialization/fallback cost during public reads. - -## Context - -`TASK-224` found critical public request issues: - -- `/api/stats/players/search` timed out at 30s. -- `/api/stats/players/{player_id}` weekly/monthly timed out at 30s. -- `/api/current-match/kills` timed out or returned 500. -- `/api/current-match/players` timed out for `comunidad-hispana-01`. -- `/api/servers` could spend about 4.3s refreshing RCON from a public GET. -- `/api/historical/matches/detail` responded OK in the production probe but still had a static `initialize_*` public read path. - -This task prioritizes safe fixes that do not change RCON connection configuration, server hosts, ports, credentials, Docker networking or frontend assets. - -## Steps - -1. Inspect the listed files first. -2. Implement Phase 1 only unless the remaining phases are clearly small and safe. -3. Add focused tests proving public read paths do not initialize storage or fall back to heavy runtime scans. -4. Validate backend compile/tests. -5. Document implemented and deferred phases. - -## Files to Read First - -- `AGENTS.md` -- `ai/architecture-index.md` -- `ai/repo-context.md` -- `docs/FULL_APPLICATION_REQUEST_AUDIT.md` -- `backend/app/rcon_historical_player_stats.py` -- `backend/app/rcon_admin_log_materialization.py` -- `backend/app/rcon_historical_read_model.py` -- `backend/app/payloads.py` -- `backend/tests/test_rcon_materialization_pipeline.py` - -## Expected Files to Modify - -- `backend/app/rcon_historical_player_stats.py` -- `backend/app/rcon_admin_log_materialization.py` -- `backend/app/rcon_historical_read_model.py` -- `backend/app/postgres_rcon_storage.py` -- `backend/app/payloads.py` -- `backend/tests/test_rcon_materialization_pipeline.py` -- `scripts/audit_public_requests.py` -- `docs/FULL_APPLICATION_REQUEST_AUDIT.md` -- `docs/PERFORMANCE_PUBLIC_QUERY_AUDIT.md` -- `ai/tasks/done/TASK-225-stabilize-critical-public-api-endpoints.md` - -## Constraints - -- Do not run `ai-platform run`. -- Do not commit or push. -- Do not touch RCON hosts, ports, credentials, environment variables, Docker networking or server connection configuration. -- Do not change `27001` or backend/RCON `127.0.0.1`. -- Do not touch frontend assets, weapon assets, clan assets, SVGs or physical images. -- Do not modify `ai/system-metrics.md`. -- Do not reactivate Elo/MMR. -- Do not reintroduce Comunidad Hispana #03. - -## Validation - -Required before completion: - -- `python -m compileall backend/app` -- `python -m unittest tests.test_rcon_materialization_pipeline` -- Relevant focused tests for player search, player detail and historical match detail read-only behavior -- Partial runtime measurement if a backend is available - -## Outcome - -Completed Phase 1 only. Phase 2 and Phase 3 were deferred because they touch RCON-live behavior, `/api/servers`, or public frontend references and should be handled separately after the non-RCON public read paths are redeployed and measured. - -Implemented: - -- `/api/stats/players/search` now reads `player_search_index` strictly. It no longer initializes player search storage or falls back to runtime scans in the public helper. Missing/empty read model returns a controlled empty payload with `fallback_used: false`. -- `/api/stats/players/{player_id}` weekly/monthly now reads `player_period_stats` strictly. Missing read model or missing player-period data returns a controlled zero-stat payload with `fallback_used: false`. -- `/api/historical/matches/detail` now uses `get_materialized_rcon_match_detail(..., ensure_storage=False)` in the public RCON read path. The materialized detail helper can read without calling `initialize_rcon_materialized_storage()` or `initialize_postgres_rcon_storage()`. Missing storage/tables return `None`, and the RCON public payload returns `found: false`, `fallback_used: false` instead of falling through to legacy fallback. -- `connect_postgres_compat()` now accepts `initialize=False` for read-only public paths while preserving the previous initializing default for existing write/materialization callers. -- `scripts/audit_public_requests.py` now supports `--filter` and `--player-id` for partial endpoint measurement. -- Documentation was updated in `docs/FULL_APPLICATION_REQUEST_AUDIT.md` and `docs/PERFORMANCE_PUBLIC_QUERY_AUDIT.md`. - -Not implemented: - -- Phase 2A `/api/current-match/kills` and `/api/current-match/players`: deferred. These depend on RCON-live behavior and must be hardened without changing RCON host/port/configuration. -- Phase 2B `/api/servers`: deferred. It needs a separate read/cache change to avoid mixing server freshness decisions into the stats/read-model fix. -- Phase 3 frontend localhost cleanup: deferred because the user requested no frontend changes in this implementation pass. -- Phase 3B historical snapshot missing/fallback generation: deferred because it likely belongs to scheduler/generation design, not this hot-path stabilization. - -Validation performed: - -- `python -m compileall backend\app`: OK. -- `python -m py_compile scripts\audit_public_requests.py`: OK. -- `cd backend; python -m unittest tests.test_rcon_materialization_pipeline`: OK, 12 tests. The suite still emits pre-existing SQLite `ResourceWarning` messages. -- `cd backend; python -m unittest tests.test_current_match_payload tests.test_rcon_admin_log_storage tests.test_historical_snapshot_refresh`: OK, 13 tests. -- Partial audit script selection against `http://127.0.0.1:8000`: - - `--filter stats-player-search`: selected 1 probe, failed because no local backend was listening. - - `--player-id 76561198092154180 --filter stats-player-profile`: selected weekly/monthly probes, failed because no local backend was listening. - - `--filter historical-match-detail`: selected 1 probe, failed because no local backend was listening. - -Commands to run after redeploy: - -```powershell -python scripts\audit_public_requests.py --base-url https://comunidadhll.devzamode.es --timeout 30 --filter stats-player-search --output tmp\task225_prod_player_search_audit.json -python scripts\audit_public_requests.py --base-url https://comunidadhll.devzamode.es --timeout 30 --player-id 76561198092154180 --filter stats-player-profile --output tmp\task225_prod_player_profile_audit.json -python scripts\audit_public_requests.py --base-url https://comunidadhll.devzamode.es --timeout 30 --filter historical-match-detail --output tmp\task225_prod_match_detail_audit.json -``` - -Restrictions confirmed: - -- Did not run `ai-platform run`. -- Did not commit or push. -- Did not modify frontend files. -- Did not touch weapon assets, clan assets, SVGs or physical images. -- Did not modify `ai/system-metrics.md`. -- Did not change `27001`. -- Did not change RCON hosts, ports, credentials, environment variables, Docker networking or server configuration. -- Did not reactivate Elo/MMR. -- Did not reintroduce Comunidad Hispana #03. - -## Change Budget - -Prefer Phase 1 only if Phase 2/3 would increase production risk or require touching frontend/configuration. diff --git a/ai/tasks/done/TASK-226-harden-current-match-and-servers-public-endpoints.md b/ai/tasks/done/TASK-226-harden-current-match-and-servers-public-endpoints.md deleted file mode 100644 index c8b6fa3..0000000 --- a/ai/tasks/done/TASK-226-harden-current-match-and-servers-public-endpoints.md +++ /dev/null @@ -1,136 +0,0 @@ ---- -id: TASK-226 -title: Harden current-match and servers public endpoints -status: done -type: backend -team: Backend Senior -supporting_teams: - - Analista - - Arquitecto Python -roadmap_item: foundation -priority: high ---- - -# TASK-226 - Harden current-match and servers public endpoints - -## Goal - -Harden the public endpoints still affected by RCON/live dependencies after `TASK-225`: - -- `/api/current-match/kills` -- `/api/current-match/players` -- `/api/servers` - -The objective is not to redesign RCON connectivity. Public HTTP reads must not hang indefinitely or return uncontrolled 500 responses when live RCON/AdminLog data is slow, unavailable or missing. - -## Context - -`TASK-225` stabilized: - -- `/api/stats/players/search` -- `/api/stats/players/{player_id}` -- `/api/historical/matches/detail` - -Production validation after `TASK-225` showed those endpoints responding OK without fallback. Remaining audit debt was RCON/live: - -- `/api/current-match/kills` timed out or returned 500. -- `/api/current-match/players` timed out for `comunidad-hispana-01`. -- `/api/servers` could spend about 4.3s refreshing RCON from a public GET. - -RCON timeout in the current test environment must not be interpreted automatically as wrong configuration. Backend/RCON `127.0.0.1`, hosts, ports and `27001` may be correct in final production and must not be changed in this task. - -## Steps - -1. Inspect public route and payload chains. -2. Make current-match AdminLog reads public read-only and controlled. -3. Make `/api/servers` return configuration/cache/snapshot data without live refresh in the request. -4. Add focused tests for controlled degradation and no public live refresh. -5. Validate and document the outcome. - -## Files to Read First - -- `ai/architecture-index.md` -- `ai/repo-context.md` -- `ai/orchestrator/backend-senior.md` -- `backend/app/routes.py` -- `backend/app/payloads.py` -- `backend/app/rcon_admin_log_storage.py` -- `backend/app/rcon_client.py` -- `backend/app/providers/rcon_provider.py` -- `docs/FULL_APPLICATION_REQUEST_AUDIT.md` -- `docs/PERFORMANCE_PUBLIC_QUERY_AUDIT.md` - -## Expected Files to Modify - -- `backend/app/payloads.py` -- `backend/app/rcon_admin_log_storage.py` -- `backend/tests/test_current_match_payload.py` -- `docs/FULL_APPLICATION_REQUEST_AUDIT.md` -- `docs/PERFORMANCE_PUBLIC_QUERY_AUDIT.md` -- `ai/tasks/done/TASK-226-harden-current-match-and-servers-public-endpoints.md` - -## Constraints - -- Do not run `ai-platform run`. -- Do not commit or push. -- Do not touch RCON hosts, ports, credentials, environment variables, Docker networking or server connection configuration. -- Do not change `27001`. -- Do not replace backend/RCON `127.0.0.1`; it may be correct in production. -- Do not touch frontend assets, weapon assets, clan assets, SVGs or physical images. -- Do not modify `frontend/assets/img/weapons/` or `frontend/assets/img/clans/`. -- Do not modify `ai/system-metrics.md`. -- Do not reactivate Elo/MMR. -- Do not reintroduce Comunidad Hispana #03. - -## Validation - -Required: - -- `python -m compileall backend/app` -- `python -m unittest tests.test_current_match_payload` -- current-match related tests if present -- payload related tests if present -- partial production audit if possible: - - `python scripts/audit_public_requests.py --base-url https://comunidadhll.devzamode.es --timeout 30 --filter current-match --output tmp/task226_current_match_audit.json` - - `python scripts/audit_public_requests.py --base-url https://comunidadhll.devzamode.es --timeout 30 --filter servers --output tmp/task226_servers_audit.json` - -## Outcome - -Implemented: - -- `/api/current-match/kills` now calls AdminLog storage in read-only mode with `ensure_storage=False`. If the AdminLog read model is missing, slow or raises, the public payload returns `status: ok`, `items: []`, `confidence: unavailable`, and source metadata with `fallback_used: true` and an `admin-log-*` reason. -- `/api/current-match/players` uses the same read-only/degrade pattern and returns an empty controlled current-match player stats payload instead of propagating storage exceptions as uncontrolled 500s. -- `rcon_admin_log_storage` gained read-only SQLite opening for current-match public reads so missing local storage does not create files or initialize schemas during GET handling. -- `/api/servers` no longer calls `_try_collect_real_time_snapshot()` from the public payload builder. It serves persisted snapshots only, marks stale/fresh state, and returns `refresh_status: "cache-only"`. -- Focused unit tests were added under `backend/tests/test_current_match_payload.py` for kill feed degradation, player stats degradation, and ensuring `/api/servers` does not trigger live refresh in a public GET. - -Not changed: - -- RCON hosts, ports, credentials, environment variables and server configuration. -- `27001`. -- Frontend JS, because existing `partida-actual.js` catches endpoint errors and clears loading states for kills/players. -- Assets, SVGs and physical images. -- Elo/MMR and Comunidad Hispana #03. - -Validation performed: - -- `python -m compileall backend/app`: OK. -- `cd backend; python -m unittest tests.test_current_match_payload`: OK, 3 tests from `CurrentMatchPublicEndpointHardeningTests`. -- Related current-match tests: no previous test modules were present in this repo checkout. -- Related payload tests: no previous payload-specific test modules were present in this repo checkout. -- `python scripts/audit_public_requests.py --base-url https://comunidadhll.devzamode.es --timeout 30 --filter current-match --output tmp/task226_current_match_audit.json`: executed against current production deployment. It still shows the pre-deploy failures: kills CH01 timeout 30054.96 ms, players CH01 timeout 30024.09 ms, kills CH02 timeout 30068.39 ms, players CH02 500 in 7497.46 ms. Re-run after deployment is required. -- `python scripts/audit_public_requests.py --base-url https://comunidadhll.devzamode.es --timeout 30 --filter servers --output tmp/task226_servers_audit.json`: executed against current production deployment. `/api/servers` still measured 200 in 4249.71 ms, consistent with pre-deploy live refresh behavior. Re-run after deployment is required. - -Risks: - -- `/api/current-match` still has direct RCON sample behavior by design and remains separate architectural debt. -- `/api/servers` freshness now depends on an external runner/cache refresh path being active. -- Production latency must be confirmed after deploy because local tests validate behavior, not live infrastructure timing. - -## Recovery Note - -During recovery, an accidental root-level `tests/` package left by the interrupted session was folded into the existing backend test module and removed from the task scope. The repository convention for this coverage is `backend/tests`. - -## Change Budget - -The task intentionally exceeds five files only because it includes required tests, documentation and the done-task record. Product/frontend assets and configuration remain untouched. diff --git a/ai/tasks/done/TASK-227-fix-current-match-kills-and-players-timeouts.md b/ai/tasks/done/TASK-227-fix-current-match-kills-and-players-timeouts.md deleted file mode 100644 index 012d913..0000000 --- a/ai/tasks/done/TASK-227-fix-current-match-kills-and-players-timeouts.md +++ /dev/null @@ -1,162 +0,0 @@ ---- -id: TASK-227 -title: Fix current-match kills and players timeouts -status: done -type: backend -team: Backend Senior -supporting_teams: [] -roadmap_item: foundation -priority: high ---- - -# TASK-227 - Fix current-match kills and players timeouts - -## Goal - -Corregir especificamente los endpoints publicos secundarios de partida actual que seguian bloqueando tras `TASK-226`: - -- `/api/current-match/kills` -- `/api/current-match/players` - -El objetivo no es reconectar RCON ni cambiar configuracion, sino evitar que estos endpoints publicos entren en inicializacion o lecturas bloqueantes y asegurar degradacion JSON controlada cuando el read model no este disponible. - -## Context - -Validacion real tras `TASK-226` contra produccion: - -```powershell -python .\scripts\audit_public_requests.py --base-url https://comunidadhll.devzamode.es --timeout 30 --filter current-match --output tmp\task226_current_match_audit_after.json -``` - -Resultados relevantes: - -- `current-match-comunidad-hispana-01`: OK 200, 2314 ms. -- `current-match-kills-comunidad-hispana-01`: CRITICAL, timeout 30026 ms. -- `current-match-players-comunidad-hispana-01`: CRITICAL, timeout 30079 ms. -- `current-match-comunidad-hispana-02`: OK 200, 2265 ms. -- `current-match-kills-comunidad-hispana-02`: CRITICAL, timeout 30050 ms. -- `current-match-players-comunidad-hispana-02`: CRITICAL, 200 pero 26095 ms, `fallback=True`. - -Tambien se valido que `/api/servers` ya esta OK en unos 82 ms y que `TASK-225` sigue OK para player search/profile y historical match detail. Esta task no toca esas rutas. - -## Files Read First - -- `ai/architecture-index.md` -- `ai/repo-context.md` -- `ai/orchestrator/backend-senior.md` -- `backend/README.md` -- `backend/app/routes.py` -- `backend/app/payloads.py` -- `backend/app/rcon_admin_log_storage.py` -- `backend/app/postgres_rcon_storage.py` -- `backend/tests/test_current_match_payload.py` - -## Call Chain Analysis - -Rutas exactas en `backend/app/routes.py`: - -- `/api/current-match/kills` valida `server`, `limit`, `since_event_id` y llama `build_current_match_kill_feed_payload(server_slug=..., limit=..., since_event_id=...)`. -- `/api/current-match/players` valida `server` y llama `build_current_match_player_stats_payload(server_slug=...)`. -- `/api/current-match` general llama `build_current_match_payload(server_slug=...)`. - -Cadena del endpoint general: - -1. `resolve_get_payload("/api/current-match?...")` -2. `build_current_match_payload()` -3. `_query_current_match_rcon_sample()` intenta una muestra RCON de sesion. -4. Si falla, cae a `build_servers_payload()`. -5. Tras `TASK-226`, `build_servers_payload()` es cache/snapshot-only y no refresca RCON/A2S en el GET publico. - -Cadena de kills: - -1. `resolve_get_payload("/api/current-match/kills?...")` -2. `build_current_match_kill_feed_payload()` -3. `list_current_match_kill_feed(server_key=origin.slug, ensure_storage=False)` -4. En PostgreSQL, el codigo llamaba `connect_postgres_compat()` sin argumentos. -5. `connect_postgres_compat()` tiene `initialize=True` por defecto. -6. `initialize_postgres_rcon_storage()` ejecutaba bootstrap/DDL antes de abrir la lectura. - -Cadena de players: - -1. `resolve_get_payload("/api/current-match/players?...")` -2. `build_current_match_player_stats_payload()` -3. `list_current_match_player_stats(server_key=origin.slug, ensure_storage=False)` -4. En PostgreSQL, el codigo llamaba `connect_postgres_compat()` sin argumentos. -5. `connect_postgres_compat()` inicializaba storage por defecto igual que kills. - -## Root Cause - -`TASK-226` paso `ensure_storage=False` desde los payloads publicos, pero en la rama PostgreSQL de `backend/app/rcon_admin_log_storage.py` ese flag no se propagaba a `connect_postgres_compat()`. - -Resultado: en produccion con `HLL_BACKEND_DATABASE_URL`, kills/players seguian ejecutando `initialize_postgres_rcon_storage()` durante el GET publico. Esa inicializacion/DDL en el request path explica la diferencia frente a `/api/current-match` general: el endpoint general no pasa por AdminLog ni por `connect_postgres_compat()` para construir kills/players; usa muestra RCON de sesion y fallback a snapshot de servidores. - -No se encontro necesidad de cambiar hosts RCON, puertos, `27001`, `127.0.0.1`, variables de entorno ni configuracion de servidores. - -## Changes - -- `backend/app/rcon_admin_log_storage.py` - - `list_current_match_kill_feed()` ahora llama `connect_postgres_compat(initialize=ensure_storage)`. - - `list_current_match_player_stats()` ahora llama `connect_postgres_compat(initialize=ensure_storage)`. - - Con `ensure_storage=False`, las lecturas publicas de AdminLog no inicializan PostgreSQL. -- `backend/tests/test_current_match_payload.py` - - Anade tests de regresion para kills y players verificando que la ruta PostgreSQL read-only llama `connect_postgres_compat(initialize=False)`. -- `docs/FULL_APPLICATION_REQUEST_AUDIT.md` - - Documenta el estado post-fix de `TASK-227`. -- `docs/PERFORMANCE_PUBLIC_QUERY_AUDIT.md` - - Actualiza la nota de arquitectura de lectura publica para reflejar la correccion real de PostgreSQL read-only. - -## Validation - -Validaciones ejecutadas: - -```powershell -python -m compileall backend/app -cd backend -python -m unittest tests.test_current_match_payload -cd backend -python -m unittest tests.test_current_match_payload tests.test_rcon_admin_log_storage tests.test_historical_snapshot_refresh -``` - -Resultados: - -- `python -m compileall backend/app`: OK. -- `cd backend; python -m unittest tests.test_current_match_payload`: OK, 5 tests. -- `cd backend; python -m unittest tests.test_current_match_payload tests.test_rcon_admin_log_storage tests.test_historical_snapshot_refresh`: OK, 18 tests. - -Auditoria HTTP local: - -- No se ejecuto auditoria local porque `http://127.0.0.1:8000/health` no respondio desde el host. - -Comando exacto para validar produccion tras redeploy: - -```powershell -python .\scripts\audit_public_requests.py --base-url https://comunidadhll.devzamode.es --timeout 30 --filter current-match --output tmp\task227_current_match_audit_after.json -``` - -## Outcome - -La ruta publica secundaria de AdminLog queda realmente read-only en PostgreSQL cuando los payloads llaman con `ensure_storage=False`. Si el read model no existe o falla, los payloads ya capturan la excepcion y devuelven `status: ok`, `items: []`, `fallback_used: true` y `fallback_reason` controlado, sin 500 vacio. - -## Constraints Confirmed - -- No se cambio `27001`. -- No se cambiaron hosts ni puertos RCON. -- No se cambio `127.0.0.1`. -- No se cambiaron variables de entorno de servidores. -- No se cambio configuracion de servidores. -- No se toco `/api/servers`. -- No se tocaron player search/profile/historical detail. -- No se reactivo Elo/MMR. -- No se reintrodujo Comunidad Hispana #03. -- No se toco frontend. -- No se tocaron assets, SVGs ni imagenes fisicas. -- No se toco `frontend/assets/img/weapons/`. -- No se toco `frontend/assets/img/clans/`. -- No se toco `ai/system-metrics.md`. -- No se incluyo `tmp/`. - -## Risks - -- Si PostgreSQL esta caido o la apertura de conexion queda bloqueada por red/DNS, el endpoint aun depende del timeout de conexion de PostgreSQL. Esta task elimina el bootstrap/DDL publico identificado, no introduce cambios de configuracion ni pooling. -- `/api/current-match` general sigue con muestra RCON directa por diseno actual; no fue parte de esta task porque la auditoria post-226 lo midio OK en unos 2.3 s. -- La confirmacion final de latencia requiere redeploy y auditoria de produccion. diff --git a/ai/tasks/done/TASK-228-restore-near-real-time-public-server-status.md b/ai/tasks/done/TASK-228-restore-near-real-time-public-server-status.md deleted file mode 100644 index db6327c..0000000 --- a/ai/tasks/done/TASK-228-restore-near-real-time-public-server-status.md +++ /dev/null @@ -1,162 +0,0 @@ ---- -id: TASK-228 -title: Restore near-real-time public server status -status: done -type: backend -team: Backend Senior -supporting_teams: [] -roadmap_item: foundation -priority: high ---- - -# TASK-228 - Restore near-real-time public server status - -## Goal - -Restaurar el comportamiento correcto de la home "Estado actual de servidores" para que `/api/servers` vuelva a servir estado live o casi-live de los servidores cuando la fuente RCON/A2S este disponible: - -- mapa actual -- region/servidor -- jugadores -- estado disponible - -La ruta no debe depender exclusivamente de snapshots historicos ni devolver `items: []` cuando puede consultar live de forma controlada. - -## Context - -Tras `TASK-226`, `/api/servers` respondia rapido pero vacio cuando no existian snapshots: - -- `source: no-snapshot-available` -- `refresh_attempted: false` -- `refresh_status: cache-only` -- `items: []` - -Eso dejaba la home mostrando "Actualizado no disponible" e "Informacion de servidores disponible mas adelante". Ese resultado no es aceptable para una seccion cuyo contrato es estado actual/casi actual. - -## Files Read First - -- `ai/architecture-index.md` -- `ai/repo-context.md` -- `ai/orchestrator/backend-senior.md` -- `backend/README.md` -- `backend/app/routes.py` -- `backend/app/payloads.py` -- `backend/app/data_sources.py` -- `backend/app/providers/rcon_provider.py` -- `backend/app/collector.py` -- `backend/tests/test_current_match_payload.py` - -## Call Chain Analysis - -Cadena frontend/backend: - -1. La home usa `frontend/assets/js/main.js`. -2. Ese JS consulta `/api/servers` para renderizar las tarjetas de estado. -3. `backend/app/routes.py` mapea `/api/servers` a `build_servers_payload()`. -4. `build_servers_payload()` lee `list_latest_snapshots()` como ultimo estado conocido. -5. Antes de `TASK-226`, si no habia cache o estaba stale, llamaba `_try_collect_real_time_snapshot()`. -6. `_try_collect_real_time_snapshot()` usa `get_live_data_source().collect_snapshots(...)`. -7. Con `HLL_BACKEND_LIVE_DATA_SOURCE=rcon`, la fuente efectiva es RCON-first con fallback A2S controlado. - -## Root Cause - -`TASK-226` cambio `build_servers_payload()` a modo `cache-only` estricto: - -- dejo de llamar `_try_collect_real_time_snapshot()` desde `/api/servers`. -- marco `refresh_attempted: false` siempre. -- devolvia `items: []` cuando no habia snapshot persistido. - -Ese cambio arreglo latencia de request, pero rompio el contrato funcional de la home cuando no hay cache caliente. - -## Changes - -- `backend/app/payloads.py` - - Restaura la politica near-real-time: - - si hay snapshot fresco, sirve cache sin refresh. - - si no hay snapshot o esta stale, intenta refresh live. - - si live devuelve items, responde con `real-time-rcon-refresh`, `real-time-a2s-fallback` o equivalente. - - si live falla, devuelve snapshot stale si existe. - - si live falla y no hay snapshot, responde `items: []` con error controlado y metadata de fallback. - - `_try_collect_real_time_snapshot()` captura excepciones y evita 500. - - El refresh publico usa timeout interno corto `PUBLIC_SERVER_STATUS_TIMEOUT_SECONDS = 2.5` sin cambiar variables de entorno ni configuracion RCON. -- `backend/app/data_sources.py` - - Extiende el contrato live para aceptar `timeout_seconds` opcional. - - Propaga ese timeout a RCON-first y A2S cuando la llamada publica lo solicita. -- `backend/app/providers/rcon_provider.py` - - Propaga `timeout_seconds` opcional a `query_live_server_sample()`. - - Las llamadas que no pasan timeout siguen usando `HLL_BACKEND_RCON_TIMEOUT_SECONDS`. -- `backend/tests/test_current_match_payload.py` - - Ajusta el test de `/api/servers` de `cache-only` a near-real-time. - - Cubre refresh live cuando no hay cache. - - Cubre respuesta controlada si live falla sin cache. - - Cubre fallback a snapshot stale si live falla con cache existente. -- `docs/FULL_APPLICATION_REQUEST_AUDIT.md` - - Documenta el estado post-fix de `TASK-228`. -- `docs/PERFORMANCE_PUBLIC_QUERY_AUDIT.md` - - Actualiza `/api/servers` como near-real-time controlado en vez de cache-only. - -## Validation - -Validaciones ejecutadas: - -```powershell -python -m compileall backend/app -cd backend -python -m unittest tests.test_current_match_payload -python -m unittest tests.test_current_match_payload tests.test_rcon_admin_log_storage tests.test_historical_snapshot_refresh -``` - -Resultados: - -- `python -m compileall backend/app`: OK. -- `cd backend; python -m unittest tests.test_current_match_payload`: OK, 7 tests. -- `cd backend; python -m unittest tests.test_current_match_payload tests.test_rcon_admin_log_storage tests.test_historical_snapshot_refresh`: OK, 20 tests. - -Auditoria local: - -- No se ejecuto porque `http://127.0.0.1:8000/health` no respondio desde el host. - -Comandos de validacion de produccion tras redeploy: - -```powershell -$base = "https://comunidadhll.devzamode.es" - -Invoke-WebRequest "$base/api/servers" | - Select-Object -ExpandProperty Content - -Invoke-WebRequest "$base/api/servers/latest" | - Select-Object -ExpandProperty Content - -Invoke-WebRequest "$base/api/servers/history" | - Select-Object -ExpandProperty Content - -python .\scripts\audit_public_requests.py --base-url https://comunidadhll.devzamode.es --timeout 30 --filter servers --output tmp\task228_servers_audit_after.json -``` - -## Outcome - -`/api/servers` vuelve a intentar estado live/casi-live de forma controlada cuando no hay cache o el cache esta vencido. Si RCON/A2S responde, la home recibe items reales. Si RCON/A2S no responde en el entorno de pruebas, el endpoint devuelve JSON controlado y no debe bloquear 30 s ni devolver 500 vacio. - -## Constraints Confirmed - -- No se cambio `27001`. -- No se cambiaron hosts ni puertos RCON. -- No se cambio `127.0.0.1`. -- No se cambiaron variables de entorno de servidores. -- No se cambio configuracion de servidores. -- No se tocaron player search/profile/historical detail. -- No se tocaron current-match/kills ni current-match/players salvo por tests compartidos. -- No se reactivo Elo/MMR. -- No se reintrodujo Comunidad Hispana #03. -- No se toco frontend. -- No se tocaron assets, SVGs ni imagenes fisicas. -- No se toco `frontend/assets/img/weapons/`. -- No se toco `frontend/assets/img/clans/`. -- No se toco `ai/system-metrics.md`. -- No se incluyo `tmp/`. - -## Risks - -- El refresh live sigue siendo sincronico y consulta targets configurados. El timeout publico corto reduce el riesgo de 30 s, pero con varios targets o un servidor que responde parcialmente puede haber latencia acumulada. -- No se persiste el snapshot live desde el GET publico para evitar DDL/inicializaciones pesadas en la lectura publica. `/api/servers/latest` y `/api/servers/history` pueden seguir vacios hasta que un proceso de captura/persistencia actualice almacenamiento. -- La validacion final de que la home muestra servidores requiere redeploy en el entorno donde RCON/live este disponible. diff --git a/ai/tasks/done/TASK-229-fix-legacy-historical-summary-and-recent-matches-timeouts.md b/ai/tasks/done/TASK-229-fix-legacy-historical-summary-and-recent-matches-timeouts.md deleted file mode 100644 index 89b7296..0000000 --- a/ai/tasks/done/TASK-229-fix-legacy-historical-summary-and-recent-matches-timeouts.md +++ /dev/null @@ -1,109 +0,0 @@ ---- -id: TASK-229 -title: Fix legacy historical summary and recent matches timeouts -status: done -type: backend -team: Backend Senior -supporting_teams: [] -roadmap_item: foundation -priority: high ---- - -# TASK-229 - Fix legacy historical summary and recent matches timeouts - -## Goal - -Corregir los endpoints historicos legacy agregados que seguian agotando el timeout de 30 s en produccion: - -- `GET /api/historical/server-summary?server=all-servers` -- `GET /api/historical/recent-matches?server=all-servers&limit=20` - -## Context - -La auditoria posterior a `TASK-228` confirmo que `/api/servers`, `/api/servers/latest` y `/api/servers/history` ya respondian correctamente, pero dos probes legacy de `historico.html legacy` seguian bloqueando: - -- `historical-server-summary-all-servers`: timeout 30024 ms. -- `historical-recent-matches-all-servers`: timeout 30045 ms. - -No se debian tocar `/api/servers`, `/api/current-match/kills` ni `/api/current-match/players`. - -## Files Read First - -- `ai/architecture-index.md` -- `ai/repo-context.md` -- `ai/orchestrator/backend-senior.md` -- `scripts/audit_public_requests.py` -- `backend/app/routes.py` -- `backend/app/payloads.py` -- `backend/app/historical_storage.py` -- `backend/app/postgres_display_storage.py` -- `backend/tests/test_historical_snapshot_refresh.py` - -## Call Chain Analysis - -Cadena de auditoria: - -1. `scripts/audit_public_requests.py` genera `historical-server-summary-all-servers` como `GET /api/historical/server-summary?server=all-servers`. -2. El mismo script genera `historical-recent-matches-all-servers` como `GET /api/historical/recent-matches?server=all-servers&limit=20`. -3. `backend/app/routes.py` mapea esas rutas a `build_historical_server_summary_payload()` y `build_recent_historical_matches_payload()`. -4. Los builders legacy intentaban usar el read model historico RCON y, si no cubria la peticion, caian a storage legacy publico. -5. Para `server=all-servers`, el fallback ejecutaba agregaciones globales: - - SQLite: `list_historical_server_summaries()` llama a `_build_all_servers_summary()` y esta recalcula conteos globales sobre tablas historicas. - - PostgreSQL: `list_scoreboard_server_summaries(server_slug=all-servers)` inicializa display storage y agrega tablas migradas de public-scoreboard. - - Recent matches puede completar desde `list_recent_historical_matches()`, tambien sobre storage legacy. -6. Los endpoints snapshot equivalentes (`/api/historical/snapshots/server-summary` y `/api/historical/snapshots/recent-matches`) ya respondian rapido porque solo leen snapshots precomputados con politica `read-only-fast-path`. - -## Root Cause - -Los endpoints legacy agregados para `all-servers` conservaban fallback runtime hacia CRCON/PostgreSQL display storage. En produccion, cuando el read model RCON no cubria la respuesta o necesitaba completar datos, el request publico entraba en agregaciones globales y/o inicializacion de storage, agotando el timeout de 30 s. - -## Changes - -- `backend/app/payloads.py` - - `build_recent_historical_matches_payload(server_slug="all-servers")` pasa a delegar en `build_recent_historical_matches_snapshot_payload()`. - - `build_historical_server_summary_payload(server_slug="all-servers")` pasa a delegar en `build_historical_server_summary_snapshot_payload()`. - - Ambos wrappers conservan `context` legacy y campos basicos (`items`, `limit`, `server_slug`, `summary_basis`) pero exponen `source: historical-precomputed-snapshots` y `legacy_endpoint_policy: snapshot-read-only-fast-path`. - - Si no existe snapshot, responden JSON controlado con snapshot missing y lista vacia, sin read model RCON ni fallback runtime pesado. -- `backend/tests/test_historical_snapshot_refresh.py` - - Cubre que los dos endpoints legacy `all-servers` usan snapshots. - - Verifica que no llaman a `get_rcon_historical_read_model()`. - - Verifica que no llaman a `list_recent_historical_matches()` ni `list_historical_server_summaries()`. -- `docs/FULL_APPLICATION_REQUEST_AUDIT.md` - - Documenta el estado post-fix de `TASK-229`. -- `docs/PERFORMANCE_PUBLIC_QUERY_AUDIT.md` - - Actualiza la politica de los endpoints legacy agregados. - -## Validation - -Validaciones ejecutadas: - -```powershell -python -m compileall backend/app -cd backend -python -m unittest tests.test_historical_snapshot_refresh -python -m unittest tests.test_current_match_payload tests.test_rcon_admin_log_storage tests.test_historical_snapshot_refresh -``` - -Resultados: - -- `python -m compileall backend/app`: OK. -- `cd backend; python -m unittest tests.test_historical_snapshot_refresh`: OK, 15 tests. -- `cd backend; python -m unittest tests.test_current_match_payload tests.test_rcon_admin_log_storage tests.test_historical_snapshot_refresh`: OK, 22 tests. - -Auditoria de produccion pendiente tras redeploy: - -```powershell -python .\scripts\audit_public_requests.py --base-url https://comunidadhll.devzamode.es --timeout 30 --filter servers --output tmp\task229_servers_recheck_after.json -``` - -## Outcome - -Los endpoints legacy agregados dejan de ejecutar read model RCON o fallback runtime pesado en lectura publica y quedan como wrappers read-only sobre snapshots precomputados. El contrato se mantiene compatible de forma razonable: HTTP 200, `status: ok`, `data.items` y metadata de snapshot/fallback. - -No se cambiaron hosts, puertos, `27001`, variables de entorno ni configuracion de servidores. No se tocaron frontend, assets, SVGs, imagenes fisicas, `ai/system-metrics.md` ni `tmp/`. - -## Change Budget - -- Archivos de codigo modificados: 2. -- Documentacion actualizada: 3 archivos. -- No se creo arquitectura nueva; solo se redirigio el path legacy agregado a read models/snapshots ya existentes. diff --git a/ai/tasks/done/TASK-230-fix-historical-server-summary-single-server-timeout.md b/ai/tasks/done/TASK-230-fix-historical-server-summary-single-server-timeout.md deleted file mode 100644 index f6f3ae1..0000000 --- a/ai/tasks/done/TASK-230-fix-historical-server-summary-single-server-timeout.md +++ /dev/null @@ -1,117 +0,0 @@ ---- -id: TASK-230 -title: Fix historical server summary single server timeout -status: done -type: backend -team: Backend Senior -supporting_teams: [] -roadmap_item: foundation -priority: high ---- - -# TASK-230 - Fix historical server summary single server timeout - -## Goal - -Corregir el ultimo `CRITICAL` restante de la auditoria publica global: - -- `GET /api/historical/server-summary?server=comunidad-hispana-01` - -## Context - -Tras `TASK-229`, los endpoints legacy agregados `all-servers` dejaron de hacer timeout. La auditoria completa posterior mostro un unico `CRITICAL`: - -- `historical-server-summary-comunidad-hispana-01` -- HTTP 200 -- `10120.89 ms` -- `fallback=False` - -Los endpoints relacionados respondian correctamente: - -- `historical-server-summary-comunidad-hispana-02`: `139.37 ms`, OK, `fallback=False`. -- `snapshot-server-summary-comunidad-hispana-01`: `42.14 ms`, WARNING, `fallback=True`. -- `snapshot-server-summary-comunidad-hispana-02`: `55.97 ms`, WARNING, `fallback=True`. -- `historical-server-summary-all-servers`: ya corregido en `TASK-229`. - -## Files Read First - -- `ai/architecture-index.md` -- `ai/repo-context.md` -- `ai/orchestrator/backend-senior.md` -- `backend/README.md` -- `backend/requirements.txt` -- `docs/project-overview.md` -- `docs/decisions.md` -- `scripts/audit_public_requests.py` -- `backend/app/routes.py` -- `backend/app/payloads.py` -- `backend/app/rcon_historical_read_model.py` -- `backend/tests/test_historical_snapshot_refresh.py` - -## Call Chain Analysis - -Cadena de auditoria: - -1. `scripts/audit_public_requests.py` genera `historical-server-summary-comunidad-hispana-01` como `GET /api/historical/server-summary?server=comunidad-hispana-01`. -2. `backend/app/routes.py` mapea `/api/historical/server-summary` a `build_historical_server_summary_payload(server_slug=...)`. -3. Tras `TASK-229`, solo `server=all-servers` usaba snapshot fast-path. -4. `server=comunidad-hispana-01` y `server=comunidad-hispana-02` seguian intentando `get_rcon_historical_read_model().list_server_summaries(...)`. -5. Ese read model llama a `list_rcon_historical_server_summaries()`. -6. `_build_server_summary()` enriquece cada resumen con `list_rcon_historical_recent_activity(server_key=..., limit=1)`. -7. Esa lectura intenta primero `list_materialized_rcon_matches(target_key=..., only_ended=True, limit=1)`, que entra en la capa materializada RCON/AdminLog. -8. En produccion, CH01 tardo ~10 s en esa lectura de actividad aunque termino con `fallback=False`; CH02 uso el mismo path pero respondio rapido. La diferencia observable es el coste de la lectura RCON/materialized para CH01, no un fallback CRCON ni un error de configuracion. -9. El endpoint snapshot equivalente ya respondia rapido porque solo lee snapshots precomputados. - -## Root Cause - -El endpoint legacy por servidor seguia usando el read model RCON runtime para `server-summary`. Aunque la respuesta fuese exitosa y `fallback=False`, el builder hacia una lectura adicional de actividad reciente por servidor para completar `activity.latest_*`. En CH01 esa consulta sobre datos materializados RCON/AdminLog era lenta y elevaba el endpoint a `CRITICAL`. - -## Changes - -- `backend/app/payloads.py` - - `build_historical_server_summary_payload()` usa snapshot fast-path para cualquier `server_slug` explicito, no solo `all-servers`. - - Se extrajo `_build_historical_server_summary_legacy_snapshot_payload()` para conservar `context`, `items`, `summary_basis`, `weekly_ranking_window_days` y `legacy_endpoint_policy`. - - Si no hay snapshot, devuelve JSON controlado con `items: []` y metadata de snapshot missing, sin RCON live ni fallback runtime pesado. -- `backend/tests/test_historical_snapshot_refresh.py` - - Cubre que `comunidad-hispana-01` no entra en `get_rcon_historical_read_model()` ni `list_historical_server_summaries()`. - - Cubre que `comunidad-hispana-02` sigue usando el mismo fast-path. - - Mantiene cobertura de `all-servers` tras `TASK-229`. -- `docs/FULL_APPLICATION_REQUEST_AUDIT.md` - - Documenta el estado post-fix de `TASK-230`. -- `docs/PERFORMANCE_PUBLIC_QUERY_AUDIT.md` - - Actualiza la politica de `/api/historical/server-summary?server=` como wrapper legacy sobre snapshot read-only. - -## Validation - -Validaciones ejecutadas: - -```powershell -python -m compileall backend/app -cd backend -python -m unittest tests.test_historical_snapshot_refresh -python -m unittest tests.test_current_match_payload tests.test_rcon_admin_log_storage tests.test_historical_snapshot_refresh -``` - -Resultados: - -- `python -m compileall backend/app`: OK. -- `cd backend; python -m unittest tests.test_historical_snapshot_refresh`: OK, 17 tests. -- `cd backend; python -m unittest tests.test_current_match_payload tests.test_rcon_admin_log_storage tests.test_historical_snapshot_refresh`: OK, 24 tests. - -Auditoria de produccion pendiente tras redeploy: - -```powershell -python .\scripts\audit_public_requests.py --base-url https://comunidadhll.devzamode.es --timeout 30 --output tmp\full_audit_after_task230.json -``` - -## Outcome - -El endpoint legacy de resumen historico por servidor queda alineado con el path rapido de snapshots ya usado por `historico.html`. CH01, CH02 y `all-servers` evitan RCON live, scoreboard externo, inicializaciones de storage y fallbacks runtime pesados en lectura publica. - -No se cambiaron hosts, puertos, `27001`, variables de entorno ni configuracion de servidores. No se tocaron frontend, assets, SVGs, imagenes fisicas, `ai/system-metrics.md` ni `tmp/`. - -## Change Budget - -- Archivos de codigo modificados: 2. -- Documentacion actualizada: 3 archivos. -- Sin cambios en frontend ni configuracion. diff --git a/ai/tasks/done/TASK-231-fix-historical-recent-matches-single-server-timeouts.md b/ai/tasks/done/TASK-231-fix-historical-recent-matches-single-server-timeouts.md deleted file mode 100644 index 411a8a8..0000000 --- a/ai/tasks/done/TASK-231-fix-historical-recent-matches-single-server-timeouts.md +++ /dev/null @@ -1,121 +0,0 @@ ---- -id: TASK-231 -title: Fix historical recent matches single server timeouts -status: done -type: backend -team: Backend Senior -supporting_teams: [] -roadmap_item: foundation -priority: high ---- - -# TASK-231 - Fix historical recent matches single server timeouts - -## Goal - -Corregir los dos `CRITICAL` restantes de la auditoria publica global: - -- `GET /api/historical/recent-matches?server=comunidad-hispana-01&limit=20` -- `GET /api/historical/recent-matches?server=comunidad-hispana-02&limit=20` - -## Context - -Tras `TASK-230`, la auditoria completa mostro: - -- `launched`: 195 -- `OK`: 78 -- `WARNING`: 115 -- `CRITICAL`: 2 - -Los dos `CRITICAL` restantes eran: - -- `historical-recent-matches-comunidad-hispana-01`: timeout `30032.24 ms`. -- `historical-recent-matches-comunidad-hispana-02`: timeout `30027.15 ms`. - -Los snapshots equivalentes y el legacy agregado ya respondian rapido: - -- `snapshot-recent-matches-comunidad-hispana-01`: `77.50 ms`. -- `snapshot-recent-matches-comunidad-hispana-02`: `51.11 ms`. -- `historical-recent-matches-all-servers`: `50.66 ms`. -- `snapshot-recent-matches-all-servers`: `63.33 ms`. - -## Files Read First - -- `ai/architecture-index.md` -- `ai/repo-context.md` -- `ai/orchestrator/backend-senior.md` -- `scripts/audit_public_requests.py` -- `backend/app/routes.py` -- `backend/app/payloads.py` -- `backend/app/rcon_historical_read_model.py` -- `backend/app/rcon_admin_log_materialization.py` -- `backend/tests/test_historical_snapshot_refresh.py` - -## Call Chain Analysis - -Cadena de auditoria: - -1. `scripts/audit_public_requests.py` genera: - - `historical-recent-matches-comunidad-hispana-01` como `GET /api/historical/recent-matches?server=comunidad-hispana-01&limit=20`. - - `historical-recent-matches-comunidad-hispana-02` como `GET /api/historical/recent-matches?server=comunidad-hispana-02&limit=20`. -2. `backend/app/routes.py` mapea `/api/historical/recent-matches` a `build_recent_historical_matches_payload(limit=..., server_slug=...)`. -3. Tras `TASK-229`, solo `server=all-servers` usaba snapshot fast-path. -4. CH01 y CH02 seguian entrando en `get_rcon_historical_read_model().list_recent_activity(...)`. -5. El read model llama a `list_rcon_historical_recent_activity()`, que intenta primero `list_materialized_rcon_matches(target_key=..., only_ended=True, limit=...)`. -6. Si RCON no cubria o necesitaba completar items, el builder podia entrar tambien en `list_recent_historical_matches()` como fallback legacy CRCON/PostgreSQL display. -7. Los snapshots equivalentes ya respondian rapido porque leen snapshots precomputados y respetan el `limit`. - -## Root Cause - -El fast-path de `TASK-229` para recent-matches estaba limitado a `server=all-servers`. Los scopes por servidor seguian usando el camino runtime RCON/materialized y podian caer al fallback legacy de scoreboard, ambos fuera del contrato de lectura publica rapida. En produccion, CH01 y CH02 agotaban los 30 s en ese path. - -## Changes - -- `backend/app/payloads.py` - - `build_recent_historical_matches_payload()` usa snapshot fast-path para cualquier `server_slug` explicito, no solo `all-servers`. - - Se extrajo `_build_recent_historical_matches_legacy_snapshot_payload()` para conservar `context`, `limit`, `server_slug`, `items`, `historical_data_source`, `coverage_basis` y `legacy_endpoint_policy`. - - Si no hay snapshot, devuelve JSON controlado con `items: []` y metadata de snapshot missing, sin RCON live, sin scoreboard externo y sin fallback runtime pesado. -- `backend/tests/test_historical_snapshot_refresh.py` - - Cubre que `comunidad-hispana-01` no llama a `get_rcon_historical_read_model()` ni a `list_recent_historical_matches()`. - - Cubre que `comunidad-hispana-02` usa el mismo fast-path. - - Mantiene cobertura de `all-servers`. - - Mantiene cobertura del fast-path de `server-summary` de `TASK-230`. -- `docs/FULL_APPLICATION_REQUEST_AUDIT.md` - - Documenta el estado post-fix de `TASK-231`. -- `docs/PERFORMANCE_PUBLIC_QUERY_AUDIT.md` - - Actualiza la politica de `/api/historical/recent-matches?server=` como wrapper legacy sobre snapshot read-only. - -## Validation - -Validaciones ejecutadas: - -```powershell -python -m compileall backend/app -cd backend -python -m unittest tests.test_historical_snapshot_refresh -python -m unittest tests.test_current_match_payload tests.test_rcon_admin_log_storage tests.test_historical_snapshot_refresh -``` - -Resultados: - -- `python -m compileall backend/app`: OK. -- `cd backend; python -m unittest tests.test_historical_snapshot_refresh`: OK, 19 tests. -- `cd backend; python -m unittest tests.test_current_match_payload tests.test_rcon_admin_log_storage tests.test_historical_snapshot_refresh`: OK, 26 tests. - -Auditoria de produccion pendiente tras redeploy: - -```powershell -python .\scripts\audit_public_requests.py --base-url https://comunidadhll.devzamode.es --timeout 30 --output tmp\full_audit_after_task231.json -``` - -## Outcome - -Los endpoints legacy recent-matches por servidor quedan alineados con los snapshots rapidos que ya consume `historico.html`. CH01, CH02 y `all-servers` evitan RCON live, scoreboard externo, inicializaciones de storage y fallbacks runtime pesados en lectura publica. - -No se cambiaron hosts, puertos, `27001`, variables de entorno ni configuracion de servidores. No se tocaron frontend, assets, SVGs, imagenes fisicas, `ai/system-metrics.md` ni `tmp/`. - -## Change Budget - -- Archivos de codigo modificados: 2. -- Documentacion actualizada: 3 archivos. -- Sin cambios en frontend ni configuracion. diff --git a/ai/tasks/done/TASK-232-audit-and-fix-weapon-icon-assets-and-rcon-mapping.md b/ai/tasks/done/TASK-232-audit-and-fix-weapon-icon-assets-and-rcon-mapping.md deleted file mode 100644 index 33cdd9d..0000000 --- a/ai/tasks/done/TASK-232-audit-and-fix-weapon-icon-assets-and-rcon-mapping.md +++ /dev/null @@ -1,125 +0,0 @@ ---- -id: TASK-232 -title: Audit and fix weapon icon assets and RCON mapping -status: done -type: frontend -team: Frontend Senior -supporting_teams: [] -roadmap_item: foundation -priority: high ---- - -# TASK-232 - Audit and fix weapon icon assets and RCON mapping - -## Goal - -Use the current local SVG files from `frontend/assets/img/weapons/black/` for weapon icons shown in current match and historical weapon views, avoid broken/legacy asset references, and document covered and pending RCON names. - -## Context - -The local `black/` weapon icon folder changed substantially: new SVGs were added and several old typo filenames were deleted or renamed. The frontend needed to keep using the local black SVG set and avoid legacy bad-quality or missing paths. - -## Files Read First - -- `ai/architecture-index.md` -- `ai/repo-context.md` -- `ai/orchestrator/frontend-senior.md` -- `frontend/assets/js/current-match-weapon-icons.js` -- `frontend/assets/js/partida-actual.js` -- `frontend/assets/js/historico-partida.js` -- `frontend/partida-actual.html` -- `frontend/historico-partida.html` - -## Expected Files Modified - -- `frontend/assets/js/current-match-weapon-icons.js` -- `frontend/assets/js/partida-actual.js` -- `frontend/assets/js/historico-partida.js` -- `frontend/historico-partida.html` -- `frontend/assets/css/historico.css` -- `scripts/validate-weapon-icon-mapping.js` -- `docs/WEAPON_ICON_MAPPING_AUDIT.md` -- this task file - -## Changes - -1. Removed the operational `weapons/white/` fallback map from `partida-actual.js`. -2. Kept current match kill feed resolution on the shared `black/` runtime resolver. -3. Added aliases for `FG42 x4` variants and `MP 40`. -4. Removed legacy typo alias strings from runtime JS: `flammenwefer41`, `m1 carabine`, `panzerchreck`. -5. Loaded `current-match-weapon-icons.js` in `historico-partida.html`. -6. Rendered local black weapon icons in historical player detail sections for `top_weapons` and `death_by`. -7. Added CSS for historical weapon icon rows. -8. Added `scripts/validate-weapon-icon-mapping.js` to validate declared SVGs, mapped SVGs and forbidden legacy terms. -9. Created `docs/WEAPON_ICON_MAPPING_AUDIT.md`. - -## Asset Inventory - -- Current local SVG count in `frontend/assets/img/weapons/black/`: 123. -- Modified tracked SVGs: 29 existing files. -- Deleted tracked typo/obsolete SVGs: 9 files. -- New/untracked local SVGs: 94 files. -- Duplicate by hash: `lee_enfield_jungle_carbine_black.svg` and `rifle_no5_mk_i_black.svg`. - -Corrected local filenames now used include: - -- `browning_m1919_black.svg` -- `m1_carbine_black.svg` -- `panzerschreck_black.svg` -- `flammenwerfer41_black.svg` -- `mosin_nagant_1891_black.svg` -- `mosin_nagant_9130_black.svg` -- `mosin_nagant_m38_black.svg` - -## RCON/API Names Reviewed - -Production endpoints sampled: - -- `/api/current-match/kills` for `comunidad-hispana-01` -- `/api/current-match/kills` for `comunidad-hispana-02` -- `/api/current-match/players` for `comunidad-hispana-01` -- `/api/current-match/players` for `comunidad-hispana-02` -- `/api/historical/matches/detail?server=comunidad-hispana-01&match=1781023156:1781028555:purpleheartlanewarfare` - -The endpoints responded but did not expose weapon names in the sampled payloads at audit time. Coverage is therefore based on the repository RCON universe already implemented in `CURRENT_MATCH_RCON_WEAPON_ICON_ENTRIES`. - -Representative covered names include `GEWEHR 43`, `KARABINER 98K`, `KARABINER 98K x8`, `FG42`, `FG42 x4`, `M1 GARAND`, `M1 CARBINE`, `BROWNING M1919`, `STG44`, `MP40`, `MG42`, `BAZOOKA`, `PANZERSCHRECK`, `PIAT`, `BOMBING RUN`, `STRAFING RUN`, `SATCHEL`, `PRECISION STRIKE`, `UNKNOWN`, common mines, grenades, trucks, jeeps, half-tracks, tanks and mounted cannons. - -## Pending Without Dedicated Icon - -These names are covered by controlled fallback mappings but still lack dedicated icons: - -- `UNKNOWN` -- `MOLOTOV` -- `No.77` -- `Daimler` -- `GAZ-67` -- `DP-27` -- `FairbairnSykes` -- `122MM HOWITZER [M1938 (M-30)]` -- `150MM HOWITZER [sFH 18]` -- `155MM HOWITZER [M114]` - -## Validation - -Passed: - -```powershell -node --check frontend/assets/js/current-match-weapon-icons.js -node --check frontend/assets/js/partida-actual.js -node --check frontend/assets/js/historico-partida.js -node scripts/validate-weapon-icon-mapping.js -``` - -Also reviewed: - -```powershell -git status --short --untracked-files=all -git diff --name-only -``` - -## Outcome - -The current match kill feed and historical match detail weapon lists now use the shared local black SVG resolver. No runtime mapping points to missing SVGs. The old white-path fallback and legacy typo asset filenames are no longer used by frontend JS. - -No backend, RCON configuration, server ports, `27001`, Elo/MMR, Comunidad Hispana #03, clan assets, `tmp/`, `black - copia/`, `black.zip` or `ai/system-metrics.md` were touched by this task. diff --git a/ai/tasks/done/TASK-233-add-hll-vietnam-release-countdown.md b/ai/tasks/done/TASK-233-add-hll-vietnam-release-countdown.md deleted file mode 100644 index 12e1831..0000000 --- a/ai/tasks/done/TASK-233-add-hll-vietnam-release-countdown.md +++ /dev/null @@ -1,73 +0,0 @@ ---- -id: TASK-233 -title: Add HLL Vietnam release countdown -status: done -type: frontend -team: Frontend Senior -supporting_teams: [] -roadmap_item: foundation -priority: medium ---- - -# TASK-233 - Add HLL Vietnam release countdown - -## Goal - -Add a visible frontend-only countdown to the public home page for the Hell Let Loose Vietnam release date. - -## Context - -The home page is `frontend/index.html` and it loads `frontend/assets/js/main.js`, not `frontend/assets/js/index.js`. The countdown should work without backend support and should not affect other pages if the markup is absent. - -## Files Read First - -- `ai/architecture-index.md` -- `ai/repo-context.md` -- `ai/orchestrator/frontend-senior.md` -- `frontend/index.html` -- `frontend/assets/js/main.js` -- `frontend/assets/css/styles.css` - -## Expected Files Modified - -- `frontend/index.html` -- `frontend/assets/js/main.js` -- `frontend/assets/css/styles.css` -- this task file - -## Changes - -1. Added a semantic countdown block below the main trailer video. -2. Added `data-hll-vietnam-countdown` and `data-countdown-target`. -3. Used target date `2026-08-13T00:00:00+02:00`. -4. Added frontend-only countdown logic in `main.js`. -5. Rendered days, hours, minutes and seconds every second. -6. Stopped the interval when the target date is reached. -7. Prevented negative values by clamping remaining time to zero. -8. Added a final available state message: `Hell Let Loose Vietnam ya esta disponible.` -9. Added responsive CSS integrated with the existing tactical panel style. - -## Design Decision - -The countdown is placed below the video. This keeps it visually tied to the HLL Vietnam trailer while avoiding changes to the public hero or server sections. - -## Validation - -Passed: - -```powershell -node --check frontend/assets/js/main.js -``` - -The implementation is guarded by `if (!root) return;`, so pages without the countdown block do not throw errors if they load the same JS. - -Manual logic review: - -- Target date parsed from `data-countdown-target`. -- Days, hours, minutes and seconds are calculated from remaining seconds. -- Values are clamped with `Math.max(0, ...)`. -- After the target date, the UI shows the available message and the interval is cleared. - -## Outcome - -The public home now shows a responsive countdown below the main video for `2026-08-13T00:00:00+02:00`. No backend file or backend configuration was changed. diff --git a/ai/tasks/done/TASK-234-adjust-hll-vietnam-countdown-copy.md b/ai/tasks/done/TASK-234-adjust-hll-vietnam-countdown-copy.md deleted file mode 100644 index 0047f29..0000000 --- a/ai/tasks/done/TASK-234-adjust-hll-vietnam-countdown-copy.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -id: TASK-234 -title: Adjust HLL Vietnam countdown copy -status: done -type: frontend -team: Frontend Senior -supporting_teams: [] -roadmap_item: foundation -priority: low ---- - -# TASK-234 - Adjust HLL Vietnam countdown copy - -## Goal - -Adjust the public home countdown copy without changing the countdown target, position or behavior. - -## Context - -The home countdown already exists below the main trailer video. The visible copy needed to remove the extra objective line and make the section title explicit. - -## Files Read First - -- `ai/architecture-index.md` -- `ai/repo-context.md` -- `ai/orchestrator/frontend-senior.md` -- `frontend/index.html` -- `frontend/assets/js/main.js` - -## Changes - -1. Changed the countdown heading to `Fecha de lanzamiento de Hell Let Loose Vietnam (13 de agosto)`. -2. Removed the visible `Objetivo: 13 de agosto de 2026.` line from the countdown block. -3. Updated the countdown JS so it no longer restores `Objetivo:` into a status node before the target date. -4. Preserved the target date `2026-08-13T00:00:00+02:00`. -5. Preserved the days, hours, minutes and seconds counter. - -## Validation - -- `node --check frontend/assets/js/main.js` -- Confirmed `Objetivo:` no longer appears in `frontend/index.html` or `frontend/assets/js/main.js`. -- Confirmed the exact heading appears in `frontend/index.html`. -- Confirmed the countdown still uses `window.setInterval(..., 1000)`. - -## Outcome - -The home countdown now presents the release date as the main section title and keeps the existing frontend-only countdown logic. - -No backend, assets, weapon assets, clan assets, SVGs, physical images, `tmp/`, `ai/system-metrics.md`, RCON settings, `27001`, Elo/MMR or Comunidad Hispana #03 handling were changed. diff --git a/ai/tasks/done/TASK-235-align-current-match-page-top-navigation.md b/ai/tasks/done/TASK-235-align-current-match-page-top-navigation.md deleted file mode 100644 index fe8a9f0..0000000 --- a/ai/tasks/done/TASK-235-align-current-match-page-top-navigation.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -id: TASK-235 -title: Align current match page top navigation -status: done -type: frontend -team: Frontend Senior -supporting_teams: [] -roadmap_item: foundation -priority: low ---- - -# TASK-235 - Align current match page top navigation - -## Goal - -Align `partida-actual.html` with the top navigation pattern used by the public pages. - -## Context - -The current match page had the contextual `VOLVER INICIO` button inside the hero, but it did not include the shared `public-nav` bar used by `index.html`, `historico.html`, `stats.html` and `ranking.html`. - -## Files Read First - -- `frontend/index.html` -- `frontend/historico.html` -- `frontend/historico-partida.html` -- `frontend/ranking.html` -- `frontend/stats.html` -- `frontend/partida-actual.html` - -## Pattern Found - -- Public pages use `