Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
035c232
feat: add library completion status
Ayerdi Aug 31, 2026
b9a9382
feat: add per-game library preferences
Ayerdi Aug 31, 2026
616693a
feat: persist per-game library preferences
Ayerdi Aug 31, 2026
47b73fb
feat: add library preferences schema v8
Ayerdi Aug 31, 2026
1732ee5
feat: add library search and filter toolbar
Ayerdi Aug 31, 2026
41769f0
feat: wire library toolbar scopes
Ayerdi Aug 31, 2026
405cce0
feat: add library search filters and organization
Ayerdi Aug 31, 2026
7c02cb7
test: cover library preference persistence
Ayerdi Aug 31, 2026
18ef3b2
test: validate library preferences schema v8
Ayerdi Aug 31, 2026
f817225
test: cover library search and filters
Ayerdi Aug 31, 2026
bb79e1b
fix: disambiguate WPF brush
Ayerdi Aug 31, 2026
6825011
fix: serialize library preference mutations safely
Ayerdi Aug 31, 2026
dbdf4d9
feat: align library status with gestor juegos
Ayerdi Aug 31, 2026
c358c2f
feat: expose paused library status
Ayerdi Aug 31, 2026
d846a70
fix: validate all supported library statuses
Ayerdi Aug 31, 2026
394ea02
feat: add paused library filtering
Ayerdi Aug 31, 2026
afb96c9
feat: add backend-neutral external game identity
Ayerdi Aug 31, 2026
eb64ac5
feat: persist external game identities
Ayerdi Aug 31, 2026
634696f
feat: store optional external catalogue identities
Ayerdi Aug 31, 2026
006c026
test: cover library compatibility schema
Ayerdi Aug 31, 2026
9cc3cce
test: cover external identity persistence
Ayerdi Aug 31, 2026
1a1df5b
test: migrate restored backups through library v8
Ayerdi Aug 31, 2026
a68b0d9
test: cover paused library compatibility
Ayerdi Aug 31, 2026
66d4d7d
test: roundtrip paused library status
Ayerdi Aug 31, 2026
417036f
docs: align gestor juegos integration boundary
Ayerdi Aug 31, 2026
22d36ad
docs: define gestor juegos compatibility contract
Ayerdi Aug 31, 2026
2ed7a07
fix: keep generic external ids exact
Ayerdi Aug 31, 2026
066f16b
fix: compare external identity values exactly
Ayerdi Aug 31, 2026
05aa1af
test: keep external id semantics provider-defined
Ayerdi Aug 31, 2026
7ae7dac
test: map discovered games to external identities
Ayerdi Aug 31, 2026
cd9467a
docs: clarify gestor completion semantics
Ayerdi Aug 31, 2026
a08bd16
fix: open library context menu through WPF hook
Ayerdi Sep 1, 2026
0f34d97
refactor: simplify library context menu target lookup
Ayerdi Sep 1, 2026
16169a7
fix: theme combo box popup for dark UI
Ayerdi Sep 1, 2026
050d8e7
fix: apply dark combo box style to library filter
Ayerdi Sep 1, 2026
b123f75
feat: add explicit library organizer view
Ayerdi Sep 1, 2026
2502260
feat: wire explicit library organizer actions
Ayerdi Sep 1, 2026
320c634
feat: expose library organizer action
Ayerdi Sep 1, 2026
3a17bdd
feat: wire library organizer entry point
Ayerdi Sep 1, 2026
2115e0a
feat: integrate dedicated library organizer mode
Ayerdi Sep 1, 2026
36da975
fix: quote organizer binding formats
Ayerdi Sep 1, 2026
9c9b2c9
refactor: reuse library search in organizer
Ayerdi Sep 1, 2026
519a66e
fix: import WPF collection view contract
Ayerdi Sep 1, 2026
a4b88c4
fix: disambiguate WPF organizer combo box
Ayerdi Sep 1, 2026
c406840
docs: clarify explicit library organization UX
Ayerdi Sep 1, 2026
dbc7a7f
chore: sync agent guidance from main
Ayerdi Sep 1, 2026
efb8eab
chore: sync engineering constitution from main
Ayerdi Sep 1, 2026
4f70b95
feat: add library status display binding
Ayerdi Sep 1, 2026
ece3d97
feat: refresh visible library status from preferences
Ayerdi Sep 1, 2026
7291a94
feat: show library status beside game title
Ayerdi Sep 1, 2026
15079cd
test: cover library status labels
Ayerdi Sep 1, 2026
63cfd9e
fix: keep combo selection text readable in dark theme
Ayerdi Sep 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 54 additions & 64 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,86 +1,76 @@
# AGENTS.md — maintaining GameHours
# AGENTS.md — GameHours

## Goal
Before planning, reviewing or modifying GameHours, read this file and `docs/CONSTITUTION.md`.

GameHours measures and reconstructs Windows game playtime independently of launchers. It is local-first and is intended to become the tracking subsystem of the Gestor de Juegos desktop application without coupling the tracking core to that backend.
## Project

## Planning sources
GameHours is a local-first Windows desktop application that measures and reconstructs videogame activity independently of launchers.

- `docs/ROADMAP.md` is the canonical **forward product roadmap** after the merge of `desktop-foundation`.
- `docs/REFERENCE-PROJECTS.md` records mature external projects/source files worth studying and the license/attribution boundary for using them.
- `docs/EXECUTION-PLAN.md` preserves detailed operational plans, completed foundation evidence and any explicitly opened implementation batch. Pre-merge "next"/candidate sections in that historical document are **not automatically authorized post-foundation work** unless they are deliberately reopened and aligned with `docs/ROADMAP.md`.
- A roadmap item is direction, not blanket implementation authorization. Open one small vertical slice at a time with explicit scope, tests, validation and exclusions.
Stack: .NET 8, C#, WPF and SQLite.

## Non-negotiable design rules
GameHours must remain useful without an account, backend or Internet connection. External integrations are optional.

1. **Exact and reconstructed time stay distinguishable.** Never label SRUM/UserAssist evidence as exact process runtime.
2. **No double counting.** Baseline evidence ends at the tracking cutover. Gap recovery must not overlap measured sessions.
3. **Path outranks filename.** Two executables with the same filename may belong to different roles or games.
4. **Helpers are not game time by default.** Launchers, crash reporters and helper processes need explicit resolution/grouping rules.
5. **Local-first.** Tracking and persistence work without network access.
6. **Privacy-minimal sync.** Raw SRUM, registry values, PIDs, Windows usernames and full paths are not uploaded by default.
7. **Idempotent persistence/sync.** Client-generated UUIDs identify sessions/evidence so retries cannot duplicate time.
8. **Events are not enough.** The production monitor keeps periodic reconciliation as a fallback for missed process events.
9. **No silent data repair.** Never repair or mutate the live SRUM database. Read from safe copies/imports only.
10. **Tests accompany timeline changes.** Any change to cutover, overlap or duration rules requires focused tests.
Before significant work, also read:

## Projects
- `docs/ROADMAP.md`
- the active spec/plan for the task, if one exists.

- `GameHours.Core`: domain models, timeline policy and interfaces. No Windows/SQLite/backend dependencies.
- `GameHours.Windows`: Windows-specific discovery and monitoring.
- `GameHours.Storage`: SQLite schema and repositories.
- `GameHours.Sync`: normalized sync contracts/client boundary.
- `GameHours.App`: development host now; future desktop shell.
- `tests/GameHours.Tests`: unit/integration tests using temporary SQLite databases.
Before repeating prior investigation, check `docs/VERIFIED-FINDINGS.md` and `docs/REFERENCE-PROJECTS.md`.

## Architecture

- `GameHours.Core`: neutral domain models and interfaces.
- `GameHours.Windows`: Windows discovery, monitoring and platform integration.
- `GameHours.Storage`: SQLite schema, migrations and repositories.
- `GameHours.Desktop`: WPF desktop product and composition.
- `GameHours.Portability`: backup, restore and import/export.
- `GameHours.AchievementProbe`: isolated achievement probing.
- `GameHours.Update`: update/package boundaries.
- `GameHours.Sync`: optional normalized integration contracts.

Do not introduce WPF, Windows, SQLite or backend dependencies into `GameHours.Core`.

## Commands

```powershell
dotnet restore GameHours.sln
dotnet build GameHours.sln -c Release
dotnet test GameHours.sln -c Release
```
Restore:

`dotnet restore GameHours.sln --locked-mode`

Build:

`dotnet build GameHours.sln -c Release --no-restore`

## Efficient subagent policy
Tests:

Use the project-scoped agents in `.codex/agents/` automatically when their role matches the work. The goal is to reduce primary-context pollution and total cost, not to maximize agent count.
`dotnet test GameHours.sln -c Release --no-build`

- Keep the primary agent on `gpt-5.6-sol` with `medium` reasoning for requirements, architecture, integration, external actions and the final decision.
- Use `gamehours_mapper` for bounded read-only codebase questions before expensive exploration in the primary thread.
- Use `gamehours_worker` for a clearly owned implementation slice and `gamehours_storage_worker` for SQLite, migrations, restore or portability. Never assign overlapping file ownership to concurrent workers.
- Use `gamehours_test_runner` for lengthy or independent local validation and failure reproduction.
- Use `gamehours_supervisor` after non-trivial or high-risk implementation involving architecture, persistent data, concurrency, security or broad diffs. It reviews; it does not reimplement the worker's task.
- Always delegate GitHub Actions, PR checks and CI observation to `ci_monitor`. The primary agent retains rerun, merge, cancellation, deployment and rollback decisions.
- Choose the cheapest capable role. Do not spawn every agent mechanically, do not delegate trivial one- or two-step work, and do not duplicate the same investigation in multiple agents.
- Run independent read-heavy tasks in parallel when useful. Serialize write-heavy tasks that touch related files.
- Give every worker a concrete objective, explicit file ownership, constraints, expected evidence and a reminder that other agents may be editing the shared worktree.
- Spawn custom project agents with `fork_turns="none"` and pass a compact, self-contained briefing. Do not copy the full parent history unless a task demonstrably requires it.
- The primary agent reviews and integrates all worker output, runs proportionate final validation, and remains responsible for the final diff.
Publish smoke:

## Verified design state
`dotnet publish src/GameHours.Desktop/GameHours.Desktop.csproj -c Release -r win-x64 --self-contained true --no-restore -o artifacts/desktop-smoke`

As of 2026-08-20:
## Conventions

- SRUM `AppResourceUseInfo.FaceTime` was successfully extracted from a copied SRUDB and matched the user's recalled playtime much better than UserAssist for the test game.
- UserAssist v5 focus fields parsed structurally, but the last-run value became stale and therefore it is secondary evidence.
- A live process session was detected entirely through one-second reconciliation when WMI events were missed; measured duration was 65.180 seconds.
- The tested game exposed two executable paths with the same filename (helper/root executable and the real game binary), proving that filename-only identity is insufficient.
Code and identifiers are in English. User-facing UI/messages are in Spanish unless a feature explicitly requires localization.

See `docs/VERIFIED-FINDINGS.md` for details.
Reuse existing GameHours components, styles and abstractions before creating new ones.

## Do not assume
## Rules

- SRUM foreground time equals process lifetime.
- `FocusCount` in UserAssist equals launch count.
- a process event will always arrive.
- one executable filename uniquely identifies a game.
- a Steam counter and GameHours counter can safely be added.
- backend availability during play.
- Research before relevant technical, architectural, performance or UX decisions.
- Prefer the simplest correct solution; avoid speculative abstractions and dependencies.
- Fix root causes using evidence rather than layering patches.
- Never mix exact measured time with reconstructed historical estimates or double-count evidence.
- Never mutate the live SRUM database.
- Do not invent timestamps, achievements, metadata or identity.
- Keep GameHours functional offline; optional integrations must remain decoupled from authoritative tracking.
- Meaningful UI changes must respect the GameHours design and be visually verified on Windows when automation cannot prove the result.
- Do not merge, release, deploy or perform other irreversible external actions without explicit human authorization.

## Pull-request checklist
## When finishing a task

- `dotnet build GameHours.sln -c Release`
- `dotnet test GameHours.sln -c Release`
- no machine-specific paths, usernames or secrets committed;
- timeline rules unchanged or explicitly tested/documented;
- SQLite migrations remain forward-only and additive where practical.
- Review the final diff for dead code, duplication, debug output, temporary logs and stale comments.
- Run validation proportional to the change; code PRs should pass build and relevant tests before being considered ready.
- Add regression tests where behavior could recur.
- Never weaken valid tests merely to obtain green CI.
- State clearly what is only implemented, what compiled, what passed automated tests/CI and what was manually or real-machine verified.
- If something could not be verified, say so.
71 changes: 71 additions & 0 deletions docs/CONSTITUTION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# GameHours Constitution

These principles are non-negotiable. Every specification, plan, implementation and review must respect them.

## 1. Research before deciding

Understand the existing behavior and code before changing it. For relevant technical, architectural, performance or UX decisions, check whether GameHours, .NET/WPF/Windows or an established solution already solves the problem. Prefer official documentation and reliable primary sources; inspect mature open-source implementations when they add useful evidence.

Do not implement the first plausible solution merely because it works.

## 2. Simplicity and reuse first

Prefer the smallest clear solution that correctly solves the real problem. Reuse existing GameHours components and platform capabilities before adding code, abstractions or dependencies.

Avoid duplicate logic, speculative frameworks, unnecessary state, hidden side effects and broad refactors unrelated to the task. Fewer lines are only better when clarity and maintainability are preserved.

## 3. Evidence and root cause over assumptions

For bugs or unexpected behavior: characterize the failure, gather evidence, identify the owning layer and fix the root cause there. Logs, tests, metrics, runtime behavior and the actual code outrank hypotheses or stale documentation.

Do not accumulate patches around a structural problem. If evidence disproves an earlier assumption, discard the assumption.

## 4. Preserve data truth and provenance

GameHours must never fabricate precision.

Measured runtime, reconstructed historical evidence, focused/active telemetry, achievements, timestamps and external metadata must preserve their source and confidence. Never double-count time, present estimated evidence as exact, invent unlock times or silently overwrite authoritative local history with external snapshots.

The live SRUM database is read-only evidence: never repair or mutate it. Use safe copies/imports.

## 5. Local-first and optional integrations

Core tracking, persistence and the useful desktop experience must work without an account, backend or Internet connection.

External systems such as Gestor de Juegos, online metadata providers or save engines are optional adapters behind GameHours-owned boundaries. They may enrich the product but must not become runtime dependencies of authoritative tracking or replace GameHours identities and evidence.

Privacy follows the same rule: collect, persist and transmit only what the feature actually needs.

## 6. Measure performance before optimizing

For meaningful performance work follow:

`measure -> locate -> optimize -> measure again`

Prefer avoiding unnecessary work over making unnecessary work slightly faster. Pay particular attention to startup, the WPF UI thread, periodic polling, process enumeration, filesystem/database access, image work and repeated scans.

Do not add caches, workers, timers or concurrency without a demonstrated reason.

## 7. Product quality includes UX

A feature is not complete merely because the code is correct. GameHours should feel coherent, modern, responsive, clear and deliberate.

Reuse the existing visual language and components. Consider hierarchy, spacing, density, focus/keyboard behavior, hover/disabled states, loading, errors, empty states and destructive actions. Do not leave default WPF/Windows styling visible when it conflicts with the GameHours design.

Meaningful visual or interaction changes require real Windows verification when automated tests cannot establish the result.

## 8. Validate before claiming completion

Compilation is not verification. Use tests and validation proportional to the risk of the change, including focused regression tests, the full suite when reasonable, CI, packaging/persistence checks and real-machine verification where appropriate.

Never remove, skip or weaken a valid test merely to obtain a green result. Always distinguish between implemented, compiled, automated-tests-passed, CI-passed and manually/real-machine verified. If something could not be verified, say so explicitly.

## Working interpretation

For substantial product or architectural work, use a lightweight Spec-Driven flow appropriate to the change:

`specification -> clarification -> technical plan -> small tasks -> implementation -> validation`

Do not create documentation for its own sake. Small, obvious fixes do not need heavyweight specs. The code, tests, current specification and observed behavior should remain aligned; when implementation reveals a durable decision that changes the specification or plan, update the relevant document.

Human review remains part of the loop. The agent accelerates engineering; it does not replace engineering judgment.
Loading