From c874e96879df1c9e2e9c3ac3c80472bac4c8c2ee Mon Sep 17 00:00:00 2001 From: OpenVelo Agent Date: Thu, 23 Jul 2026 04:06:46 +0000 Subject: [PATCH 1/2] docs: update documentation to OKF v0.1 format --- docs/architecture/key-files.md | 5 +++-- docs/guides/challenges-board.md | 9 +++++---- docs/guides/challenges-per-user-state.md | 4 ++-- docs/index.md | 2 +- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/docs/architecture/key-files.md b/docs/architecture/key-files.md index f2ca5af..72df473 100644 --- a/docs/architecture/key-files.md +++ b/docs/architecture/key-files.md @@ -3,7 +3,7 @@ type: architecture title: Key Files Index description: One-line responsibility for important source and contract-test files, including strict event-window validation, the public bootstrap SSE listener, the challenges full-replace import flow, the authenticated player-facing challenges board, and the per-user `solvedByMe` reset on the session boundary. tags: [architecture, key-files, event-window, validation, default-challenge-ip, sse, bootstrap, migrations, challenges, import, board, notifications, per-user, session] -timestamp: 2026-07-23T03:45:00Z +timestamp: 2026-07-23T04:05:00Z --- # Backend @@ -77,7 +77,7 @@ timestamp: 2026-07-23T03:45:00Z | `frontend/src/app/features/challenges/challenges.service.ts` | HTTP service for `/api/v1/challenges/{board,status,:id,:id/solves}` returning typed `ApiErrorEnvelope`s. `getDetail` always requests `?include=solvers` so the modal can render the solvers list in one round-trip; `getBoard` only attaches `include=solvers` when the caller opts in. | | `frontend/src/app/features/challenges/challenges.pure.ts` | Pure types and helpers (`BoardCard`, `SolverRow`, `SolveEventPayload`, `parseSolveEvent`, `mergeSolveEventIntoSolvers`, `messageForSolveError`, `formatDdHhMm`). | | `frontend/src/app/features/challenges/category-column.component.ts` | Renders a single category column (header + cards) on the challenges board. | -| `frontend/src/app/features/challenges/challenge-card.component.ts` | Renders a single challenge card on the board (difficulty, live points, solve count, `✓` when solved by the player). | +| `frontend/src/app/features/challenges/challenge-card.component.ts` | Renders a single challenge card on the board as a semantic ` `, }) export class ChallengeCardComponent { diff --git a/tests/frontend/challenge-card-accessibility.spec.ts b/tests/frontend/challenge-card-accessibility.spec.ts new file mode 100644 index 0000000..d31ff12 --- /dev/null +++ b/tests/frontend/challenge-card-accessibility.spec.ts @@ -0,0 +1,64 @@ +import { readFileSync } from 'node:fs'; +import { resolve } from 'node:path'; + +const sourcePath = resolve( + __dirname, + '../../frontend/src/app/features/challenges/challenge-card.component.ts', +); +const templatePath = resolve( + __dirname, + '../../frontend/src/app/features/challenges/challenge-card.component.ts', +); +const source = readFileSync(sourcePath, 'utf8'); + +describe('ChallengeCardComponent — per-card solved accessibility contract', () => { + function extractTemplate(src: string): string { + const match = src.match(/template:\s*`([\s\S]*?)`,?\s*\n\s*\}/); + return match ? match[1] : ''; + } + + const template = extractTemplate(source); + + it('wraps the card in a native