chore(voyage): release v5.0.0 — remove bespoke playground + /trekrevise + Handover 8; render produced artifacts to HTML + link, annotate via /playground
The v4.2/v4.3 bespoke playground SPA (~388 KB), the /trekrevise command, Handover 8 (annotation → revision), the supporting lib/ modules (anchor-parser, annotation-digest, markdown-write, revision-guard), the Playwright e2e suite, and the @playwright/test / @axe-core/playwright devDeps are removed. A browser walkthrough found the playground borderline unusable, and it duplicated the official /playground plugin's document-critique / diff-review templates. In their place: scripts/render-artifact.mjs — a small, zero-dependency renderer that turns a brief/plan/review .md into a self-contained, design-system-styled, zero-network .html (frontmatter folded into a <details> block). /trekbrief, /trekplan, and /trekreview call it on their last step and print the file:// link; to annotate, run /playground (document-critique) on the .md and paste the generated prompt back. Resolves the v4.3.1-deferred findings as moot (their target files are deleted). npm test green: 509 tests, 507 pass, 0 fail, 2 skipped. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
0f197f6ff6
commit
916d30f63e
96 changed files with 620 additions and 14716 deletions
|
|
@ -1,6 +1,6 @@
|
|||
# Handover Contracts (voyage-suite local pipeline)
|
||||
|
||||
This document is the single source of truth for the file formats that pass between the four commands of the `trekplan` pipeline. When you fork the plugin or extend a stage, the contracts below tell you what every producer must write and what every consumer is allowed to assume.
|
||||
This document is the single source of truth for the file formats that pass between the commands of the `trekplan` pipeline. There are seven handovers. When you fork the plugin or extend a stage, the contracts below tell you what every producer must write and what every consumer is allowed to assume.
|
||||
|
||||
For each handover, the same headings appear in the same order: **Producer**, **Consumer**, **Path conventions**, **Frontmatter schema**, **Body invariants**, **Validation strategy**, **Versioning**, **Failure modes**.
|
||||
|
||||
|
|
@ -16,7 +16,6 @@ Each artifact carries an explicit version field. Schema bumps are coordinated:
|
|||
| `progress.json` | `schema_version` (top-level) | `"1"` |
|
||||
| `review.md` | `review_version` (frontmatter) | `1.0` |
|
||||
| `.session-state.local.json` | `schema_version` (top-level) | `1` (number) |
|
||||
| `brief.md` / `plan.md` / `review.md` (annotated) | `revision` (frontmatter) | `0` (implicit), `1+` after `/trekrevise` |
|
||||
|
||||
## Breaking-change protocol
|
||||
|
||||
|
|
@ -37,7 +36,6 @@ Each artifact carries an explicit version field. Schema bumps are coordinated:
|
|||
| 5. progress.json (resume) | `lib/validators/progress-validator.mjs` |
|
||||
| 6. review → plan | `lib/validators/review-validator.mjs` |
|
||||
| 7. session-state (multi-session resume) | `lib/validators/session-state-validator.mjs` |
|
||||
| 8. annotation → revision | `lib/parsers/anchor-parser.mjs` + `lib/parsers/annotation-digest.mjs` (parsing) and the existing brief / plan / review validators (forward-compat — additive fields tolerated) |
|
||||
|
||||
Every validator exposes a CLI: `node lib/validators/<name>.mjs --json <path>` returns `{valid, errors[], warnings[], parsed}`. Errors and warnings have stable `code` fields for downstream tooling.
|
||||
|
||||
|
|
@ -440,96 +438,6 @@ The `next-session-prompt-validator` (`lib/validators/next-session-prompt-validat
|
|||
|
||||
---
|
||||
|
||||
## Handover 8 — annotation → revision
|
||||
|
||||
**Handover 8 closes the operator-feedback loop.** Where Handovers 1–4 flow forward (brief → research → plan → execute), Handover 5 makes execute resumable, Handover 6 routes review findings back into planning, and Handover 7 makes multi-session work survivable across fresh chats, **Handover 8 lets a human operator annotate an artifact (brief, plan, or review) inside the playground and feed those annotations back into a revision cycle without losing the original artifact's byte-for-byte content**. The pipeline becomes round-trippable: a single artifact can be annotated, revised, and re-rendered repeatedly, each revision recorded with a deterministic digest in frontmatter.
|
||||
|
||||
**Producer:**
|
||||
- The operator (manual step) — open the artifact in `playground/voyage-playground.html`, drag-select or hover-to-anchor, fill comment + intent in the modal, click "Eksporter batch" to copy the `/trekrevise` invocation to clipboard.
|
||||
- `/trekrevise --project <dir>` (Phase 3 — apply) — consumes the pasted batch, writes anchor comments back into the target artifact, increments `revision:`, appends entries to `source_annotations:`, and computes a fresh `annotation_digest`.
|
||||
|
||||
**Consumer:**
|
||||
- Subsequent `/trekplan --project <dir>` if the revised brief or plan needs further re-planning.
|
||||
- Subsequent `/trekexecute --project <dir>` if the revised plan is ready for execution.
|
||||
- All existing validators (brief, plan, review) — they tolerate the additive frontmatter fields without version bumps.
|
||||
|
||||
**Path conventions:**
|
||||
- The annotated artifact is the same canonical file in `{project_dir}/` (`brief.md`, `plan.md`, `review.md`). Revisions are *in-place* — no `plan-revN.md` shadow files. Audit trail lives in git commits + the `revision:` counter + `source_annotations:` list inside frontmatter.
|
||||
- The playground itself lives at `playground/voyage-playground.html` (single self-contained file with vendored `markdown-it` + `highlight.js` under `playground/lib/`).
|
||||
|
||||
**Frontmatter schema (additive — applies to brief.md, plan.md, review.md):**
|
||||
|
||||
| Field | Type | Required | Allowed values | Notes |
|
||||
|---|---|---|---|---|
|
||||
| `revision` | number | optional | `0`, `1`, `2`, … | Absent = `0` (forward-compat). Incremented by `/trekrevise` on each apply |
|
||||
| `source_annotations` | list | optional | block-style YAML list of dicts | Absent = empty. Audit trail of every annotation that has been folded into this artifact |
|
||||
| `annotation_digest` | string | optional | first 16 hex chars of canonical SHA-256 over the sorted `source_annotations` array | Absent = no annotations applied yet. Deterministic — re-applying the same set yields the same digest |
|
||||
| `revision_reason` | string | optional | free-form text | **Required only** when the revision is non-additive (e.g. removed scope, replaced an SC). Operators are encouraged to fill it for any revision |
|
||||
|
||||
Each entry in `source_annotations` is a YAML dict:
|
||||
|
||||
```yaml
|
||||
source_annotations:
|
||||
- id: ANN-0001
|
||||
target_artifact: plan.md
|
||||
target_anchor: step-3
|
||||
intent: change # change | add | remove | clarify | risk
|
||||
comment: "consider rolling back if cache_creation jumps >10%"
|
||||
line: 412
|
||||
```
|
||||
|
||||
**Anchor format (block-level HTML comments inside the body):**
|
||||
|
||||
```html
|
||||
<!-- voyage:anchor id="ANN-0001" target="plan.md#step-3" line="412" -->
|
||||
```
|
||||
|
||||
Anchors are placed **only at block boundaries** — not in list items, not mid-paragraph, not at line-start collision points where a markdown parser might fold them into surrounding content. The playground enforces this discipline via `validateAnchorPlacement()` in `lib/parsers/anchor-parser.mjs`. Anchors survive markdown rendering as comments (no visible artifact) and round-trip through `parseAnchors → addAnchors → stripAnchors` byte-identically (SC2 contract).
|
||||
|
||||
**Body invariants:**
|
||||
- The artifact's existing required sections remain untouched. `/trekrevise` writes anchor comments only at block boundaries declared by the operator's annotations.
|
||||
- After each apply: byte-identical content outside anchor blocks. Stripping all anchors with `stripAnchors()` MUST yield the artifact's original body modulo the operator's deliberate prose edits.
|
||||
|
||||
**Validation strategy:**
|
||||
|
||||
| Layer | When | What |
|
||||
|---|---|---|
|
||||
| `revision` shape | every read | Number (or absent → treat as `0`). Negative or non-integer rejected by validator |
|
||||
| `source_annotations` shape | every read | Array of dicts; each dict must include `id`, `target_artifact`, `target_anchor`, `intent`. Other fields tolerated (drift-WARN) |
|
||||
| `annotation_digest` shape | every read | 16-char lowercase hex; presence requires `source_annotations` non-empty |
|
||||
| Anchor placement | `/trekrevise` Phase 2 (validate) | `validateAnchorPlacement()` rejects in-list / mid-paragraph / line-start anchors before write |
|
||||
| Round-trip integrity | `/trekrevise` Phase 4 (post-write) | `stripAnchors()` of the just-written file MUST equal the pre-write body |
|
||||
|
||||
The parsers (`lib/parsers/anchor-parser.mjs`, `lib/parsers/annotation-digest.mjs`) are pure functions — no I/O, fully unit-tested. The existing brief / plan / review validators in `lib/validators/` already tolerate the new optional fields (forward-compat — see Step 12 manifest pins).
|
||||
|
||||
**Forward-compat — additive principle:** Artifacts without any of the four new fields validate as `revision: 0` with empty annotations. This means every brief / plan / review written before v4.2 remains valid without migration. Producers (operators using `/trekrevise`) opt into the schema by writing the fields; consumers tolerate their presence or absence equally.
|
||||
|
||||
**Idempotence:** Re-applying the same annotation batch on the same artifact (same anchors, same intents, same comments) yields the same `annotation_digest` and no body diff outside anchor refresh. This is enforced by `computeAnnotationDigest()` canonicalizing the sorted `source_annotations` array before hashing — operators can replay a batch safely, and the test suite pins this with `tests/parsers/annotation-digest.test.mjs`.
|
||||
|
||||
**Versioning:** No `*_version` bump for v4.2 — the four new fields are additive. A future schema break (e.g. removing `target_anchor` in favor of structured pointer) would bump `brief_version` / `plan_version` / `review_version` per the breaking-change protocol.
|
||||
|
||||
**Failure modes:**
|
||||
- `ANNOTATION_PLACEMENT_INVALID` → `/trekrevise` Phase 2 halts; operator re-anchors via playground
|
||||
- `ANNOTATION_DIGEST_DRIFT` → digest computed at apply-time differs from operator's expected digest in the pasted batch; halt with mismatch report (suggests the batch was hand-edited after export)
|
||||
- `ANNOTATION_ROUNDTRIP_FAIL` → post-write `stripAnchors()` does not yield the original body; rollback restores the byte-identical pre-write file from `*.local.bak`
|
||||
- Parser failures from `parseAnchors()` produce `{valid: false, errors: [...]}` and `/trekrevise` halts before any write. The atomic-write pattern (tmp-file + rename) guarantees the canonical file is never partially updated.
|
||||
|
||||
### § Lifecycle
|
||||
|
||||
The annotation cycle has three stages — no persistent state file (unlike Handover 7), only the artifact frontmatter and git history record what happened:
|
||||
|
||||
| Stage | Owner | Action |
|
||||
|---|---|---|
|
||||
| Annotate | Operator + playground UI | Open artifact in `playground/voyage-playground.html`, anchor + comment, click "Eksporter batch" → clipboard contains a `/trekrevise --project <dir> --apply '{...JSON...}'` command |
|
||||
| Apply | `/trekrevise` | Phase 1 parse the pasted batch, Phase 2 validate placement, Phase 3 atomically write anchors + frontmatter (`revision: N+1`, append to `source_annotations`, recompute `annotation_digest`), Phase 4 round-trip integrity check, Phase 5 commit |
|
||||
| Re-render | Playground (next open) | The freshly-revised artifact loads with anchors visible as inline comment markers; operator can iterate or call `/trekplan` / `/trekexecute` on the revised file |
|
||||
|
||||
**Single-iteration MVP (v4.2 scope):** Each operator annotation batch produces one `revision:` increment. Multi-iteration loops (e.g. revise → re-review → revise again without operator intervention) are deferred indefinitely — the brief's SC4 wording is single-revision, and operator validation that multi-iteration is desired has not been collected (see plan Alternatives table). The single-iteration MVP keeps the audit trail unambiguous: one `revision:` bump per `/trekrevise` invocation.
|
||||
|
||||
**Stale-anchor principle:** Unlike `.session-state.local.json`, anchors are durable and intentionally retained — they document *why* a revision happened. There is no `--cleanup` for anchors. Removing them is a manual operator decision, executed via the playground "Strip all anchors" affordance or hand-editing the source. `/trekrevise` does not remove anchors automatically.
|
||||
|
||||
---
|
||||
|
||||
## Stability summary
|
||||
|
||||
| Handover | Validation strength | Owner | Risk |
|
||||
|
|
@ -541,6 +449,5 @@ The annotation cycle has three stages — no persistent state file (unlike Hando
|
|||
| 5. progress.json | shape + resume readiness | this plugin | medium — drift during compaction handled by pre-compact-flush hook (CC v2.1.105+) |
|
||||
| 6. review → plan | strict at write, soft at read | this plugin | low — additive feedback loop; consumer falls back gracefully when source_findings is absent |
|
||||
| 7. session-state (multi-session resume) | required-fields + status enum + drift-WARN extras | this plugin | low — readers tolerate unknown keys; writers are owned by trekexecute Phase 8 + helper command |
|
||||
| 8. annotation → revision | parser-strict at write (placement + round-trip), validator-soft at read (additive fields) | this plugin | low — additive frontmatter; existing artifacts validate as `revision: 0` without migration |
|
||||
|
||||
When extending the plugin or adding a new pipeline stage, follow the same pattern: produce an artifact with a versioned frontmatter (or `schema_version` for JSON), write a validator under `lib/validators/`, add fixtures under `tests/fixtures/`, and add an entry to this document.
|
||||
|
|
|
|||
|
|
@ -1,55 +0,0 @@
|
|||
# Annotation playground — quickstart
|
||||
|
||||
The `/trekrevise` command and the `playground/voyage-playground.html` page
|
||||
let you annotate any voyage artifact (`brief.md`, `plan.md`, or `review.md`)
|
||||
and fold the annotations back in-place with a deterministic audit trail.
|
||||
|
||||
This is **Handover 8** in `docs/HANDOVER-CONTRACTS.md`. For schema details,
|
||||
read that document first.
|
||||
|
||||
## Hands-on with the example fixture
|
||||
|
||||
The plugin ships a canonical fixture at
|
||||
`tests/fixtures/annotation/annotation-example.md` that is the same shape an
|
||||
operator would annotate. Use it to verify your playground works before
|
||||
touching a real project.
|
||||
|
||||
## Seven steps from artifact to revised file
|
||||
|
||||
1. **Open the playground.** Open `plugins/voyage/playground/voyage-playground.html`
|
||||
in any modern browser. No build, no server, no network calls — the page
|
||||
ships vendored `markdown-it` and `highlight.js` under `playground/lib/`.
|
||||
|
||||
2. **Paste the artifact content.** Copy the full body of your `brief.md`,
|
||||
`plan.md`, or `review.md` (including frontmatter) into the textarea on
|
||||
the left. The right pane renders the markdown live. For larger artifacts
|
||||
you can also generate the rendered HTML offline with
|
||||
`node plugins/voyage/scripts/render-artifact.mjs <path> --out /tmp/x.html`.
|
||||
|
||||
3. **Anchor a comment.** Drag-select text inside a paragraph, or hover a
|
||||
block-level element and click the anchor button that appears. The
|
||||
playground refuses anchors inside list items, mid-paragraph, or at
|
||||
line-start collision points — only block boundaries are valid (per the
|
||||
placement discipline in `lib/parsers/anchor-parser.mjs`).
|
||||
|
||||
4. **Fill the modal.** Choose an intent (`change`, `add`, `remove`,
|
||||
`clarify`, or `risk`), write your comment, save. Repeat for every
|
||||
anchor you want in this batch. The sidebar shows your batch growing as
|
||||
a critique-card-list.
|
||||
|
||||
5. **Export the batch.** Click "Eksporter batch". The playground copies a
|
||||
complete `/trekrevise --project <dir> --apply '{...JSON...}'` invocation
|
||||
to your clipboard. The JSON encodes every anchor, intent, and comment.
|
||||
|
||||
6. **Apply via `/trekrevise`.** Paste the command in your Claude Code chat.
|
||||
The command parses + validates the batch, atomically writes anchor
|
||||
comment blocks back into the source artifact, increments `revision:`,
|
||||
appends entries to `source_annotations:`, and recomputes
|
||||
`annotation_digest`. Body content outside anchor blocks remains
|
||||
byte-identical.
|
||||
|
||||
7. **Verify and iterate.** Re-open the revised file in the playground to
|
||||
see anchors as inline comment markers. If you want another revision
|
||||
pass, repeat from step 3 — each batch produces one `revision:` bump.
|
||||
Single-iteration MVP per research-05; multi-iteration loops are
|
||||
deferred.
|
||||
|
|
@ -1,129 +0,0 @@
|
|||
# SC1 10-element Checklist Verification — voyage v4.3 playground
|
||||
|
||||
**Verifisert:** 2026-05-10 (Sesjon 6, Wave 7)
|
||||
**Referanse:** `plugins/llm-security/playground/llm-security-playground.html` (visuell paritet)
|
||||
**Metode:** Static-grep (Group A tester, Step 28) + manuell side-by-side + Playwright pixel-diff (Step 30)
|
||||
**Status:** 8 av 10 PASS ved bokstavelig criteria, 2 redefinert per scope-guardian Assumptions (operatør-sign-off)
|
||||
|
||||
## Sammendrag
|
||||
|
||||
| # | Element | Status | Evidens |
|
||||
|---|---------|--------|---------|
|
||||
| 1 | Header + breadcrumb | PASS | Group A test SC1.1; `app-header__breadcrumb` + `aria-label="Brødsmuler"` |
|
||||
| 2 | Breadcrumb retur-bane | PASS | Group A test SC1.2; `breadcrumb-click` handler i `voyage-playground.html:1830` |
|
||||
| 3 | Theme bootstrap IIFE | PASS | Group A test SC1.3; `data-theme` + `prefers-color-scheme` IIFE i HTML head |
|
||||
| 4 | Onboarding-grid (redefinert) | PASS | Group A test SC1.4 + Group B fleet-grid CSS parity-test (99707f51) verifiserer at vendored DS `components-tier3-supplement.css` `.fleet-grid` block fortsatt har `grid-template-columns: repeat(4, 1fr)` + `gap: var(--space-3)`. Voyage bruker `fleet-grid` + `fleet-tile` istedenfor onboarding-grid (scope-guardian SC-GAP-1, Assumption #21). |
|
||||
| 5 | A11Y-panel | PASS | Group A test SC1.5; `guide-panel--info` + `key-stats` + `findings__items` (Wave 5 Step 22) |
|
||||
| 6 | Screenshots-spor | PASS | Group D test SC1.6; `loadProjectDirectory` leser `docs/screenshots/**/*.png` via `readAsDataURL` (2 MB cap) og `renderScreenshotGallery` mounter en `<figure>`-grid i dashboardet. Erstatter scope-guardian SC-GAP-2 PASS-redef med faktisk inline gallery (v4.3 Step 8, finding 31d28f65). |
|
||||
| 7 | Body typografi | PASS | Group A test SC1.7; `var(--font-size-*)` + `var(--font-family-mono)` brukt gjennomgående |
|
||||
| 8 | Spacing rhythm | PASS | Group A test SC1.8; ≥5 distinkte `var(--space-N)` referanser |
|
||||
| 9 | Color-token fidelity | PASS | Group A test SC1.9; `badge--scope-voyage` + `--color-scope-voyage` brukt |
|
||||
| 10 | Dark-mode parity | PASS | Group A test SC1.10; `data-theme="dark"` default + persistens via `voyage-theme` localStorage |
|
||||
|
||||
**Nettoresultat:** 10/10 verifisert (8 bokstavelig + 2 redefinert med operatør-sign-off i Assumptions #21 og #22). Ingen revisjons-loop til Wave 1-5 utløst.
|
||||
|
||||
## Detaljer per element
|
||||
|
||||
### Element 1 — Header med breadcrumb
|
||||
- **Bokstavelig krav:** sticky topbar med breadcrumb-navigasjon
|
||||
- **Implementering:** `class="app-header__breadcrumb"` + `aria-label="Brødsmuler"` i `renderTopbar` (Step 8)
|
||||
- **Test:** `tests/playground/voyage-playground.test.mjs` — `SC1.1 header — app-shell topbar with breadcrumb`
|
||||
- **Status:** PASS
|
||||
|
||||
### Element 2 — Breadcrumb klikkbar retur-bane
|
||||
- **Bokstavelig krav:** klikk på "Dashboard" i breadcrumb returnerer til hovedoversikt
|
||||
- **Implementering:** `breadcrumb-click` handler renderer dashboard-fleet-grid via `renderDashboard()`
|
||||
- **Test:** `SC1.2 breadcrumb — clickable returns to dashboard`
|
||||
- **Status:** PASS
|
||||
|
||||
### Element 3 — Theme bootstrap IIFE
|
||||
- **Bokstavelig krav:** sync IIFE i `<head>` setter `data-theme` før første paint, leser bruker-pref + OS-pref
|
||||
- **Implementering:** Linje 22-26 i HTML; sjekker `localStorage('voyage-theme')` → `prefers-color-scheme: dark` matchMedia → fallback `dark`
|
||||
- **Test:** `SC1.3 theme bootstrap — IIFE sets data-theme + colorScheme`
|
||||
- **Status:** PASS
|
||||
|
||||
### Element 4 — Onboarding-grid (REDEFINERT)
|
||||
- **Bokstavelig krav:** llm-security har 4 onboarding-tiles (Quickstart / Latest scan / Threats / Roadmap)
|
||||
- **Voyage-tolkning:** voyage-domain har én plugin uten onboarding-flow. Redefinerer onboarding-grid som "fleet-grid + recommendation-card-pattern matcher samme grid-system" (Alternatives Considered, plan.md linje 1081)
|
||||
- **Implementering:** `fleet-grid` med `fleet-tile`-children, én tile per artifact (brief/plan/research/review)
|
||||
- **Test:** `SC1.4 onboarding-grid equivalent — fleet-grid pattern` + Group B `SC1.4 fleet-grid CSS parity vs vendored DS (99707f51)` som verifiserer at `components-tier3-supplement.css` `.fleet-grid` block fortsatt har `grid-template-columns: repeat(4, 1fr)` + `gap: var(--space-3)`
|
||||
- **Status:** PASS (fleet-grid CSS parity verifisert via Group B strukturell test mot vendored DS; scope-guardian SC-GAP-1 lukket via /trekreview Sesjon 13, Assumption #21 operatør-sign-off står)
|
||||
|
||||
### Element 5 — A11Y-panel
|
||||
- **Bokstavelig krav:** tilgjengelighets-panel viser severity-counters + findings-list
|
||||
- **Implementering:** `guide-panel guide-panel--info` container med `key-stats` severity-grid + `findings__items` ordered list. `wireA11yToggle` kobler topbar-button til toggle. Built fra DS-primitives (Wave 5 Step 22)
|
||||
- **Hooks:** `window.__voyage.scheduleRender({ a11yViolations })` populerer panelet fra Playwright-spec
|
||||
- **Test:** `SC1.5 A11Y panel — guide-panel--info + key-stats + findings`
|
||||
- **Status:** PASS
|
||||
|
||||
### Element 6 — Screenshots-spor
|
||||
- **Bokstavelig krav:** llm-security har inline gallery med thumbnail-grid for case-studies
|
||||
- **Voyage-implementering (v4.3 Step 8, finding 31d28f65):** `loadProjectDirectory` detekterer `docs/screenshots/**/*.png` via path-prefix-match, leser dem via `FileReader.readAsDataURL()` med 2 MB per-bilde cap (overskridelse annonseres via aria-live). `renderScreenshotGallery(screenshots)` bygger en `<figure>`-grid med `<img src="<dataUrl>" alt="<filename>">` som mountes under `fleet-grid` i `renderDashboard`. Erstatter den tidligere PASS-redef-tolkningen — voyage har nå et faktisk inline gallery.
|
||||
- **Beholder:** `window.__voyage` hooks fra Wave 5 Step 23 (`navigate`, `scheduleRender`, `getProjectArtifacts`) + `docs/screenshots/README.md` mappe-konvensjon — fortsatt brukt av Playwright-spec og av operatør for manuell screenshot-prosedyre.
|
||||
- **Test:** Group D Playwright-test `SC1.6 inline gallery — data:image PNGs rendered (31d28f65)` injiserer en fixture-artifact via `scheduleRender` og asserter `#voyage-dashboard img[src^="data:image/png"]` count > 0.
|
||||
- **Status:** PASS (inline gallery implementert; scope-guardian SC-GAP-2 lukket).
|
||||
|
||||
### Element 7 — Body typografi
|
||||
- **Bokstavelig krav:** typografi-skala bruker DS-tokens, ikke literal pixel-verdier
|
||||
- **Implementering:** `var(--font-size-{xs,sm,md,lg,xl})` + `var(--font-family-mono)` brukt gjennomgående. Wave 1 Step 5 fjernet literal pixel font-sizes.
|
||||
- **Test:** `SC1.7 body typography — DS font-size + family tokens`
|
||||
- **Note:** En enkelt `font-size: 0.7rem` literal eksisterer i HTML (linje ~361) — dokumentert i Wave 1; ikke blocker.
|
||||
- **Status:** PASS
|
||||
|
||||
### Element 8 — Spacing rhythm
|
||||
- **Bokstavelig krav:** ≥5 distinkte `--space-N` token-referanser for konsistent spacing
|
||||
- **Implementering:** Verifisert via grep-count i Group A test
|
||||
- **Test:** `SC1.8 spacing rhythm — DS --space-N tokens used`
|
||||
- **Status:** PASS
|
||||
|
||||
### Element 9 — Color-token fidelity
|
||||
- **Bokstavelig krav:** voyage-scope tokens definert + brukt
|
||||
- **Implementering:** Wave 0 Step 1 la til `--color-scope-voyage` + `badge--scope-voyage` i DS `base.css`. Brukt i playground via `class="badge badge--scope-voyage"` i topbar.
|
||||
- **Test:** `SC1.9 color-token fidelity — voyage-scope tokens + DS colors`
|
||||
- **Status:** PASS
|
||||
|
||||
### Element 10 — Dark-mode parity
|
||||
- **Bokstavelig krav:** dark mode er førsteklasses borger (ikke lag-på), default-teme følger system-pref
|
||||
- **Implementering:** `<html data-theme="dark">` som default; bootstrap-IIFE respekterer `voyage-theme` localStorage, deretter `prefers-color-scheme: dark`, deretter fallback `dark`
|
||||
- **Test:** `SC1.10 dark-mode parity — explicit dark default + bootstrap`
|
||||
- **Pixel-diff baseline:** `tests/e2e/snapshots/voyage-playground-dark.png` (Step 30 spec)
|
||||
- **Status:** PASS
|
||||
|
||||
## Baseline-screenshots (Playwright)
|
||||
|
||||
Etablert via `npx playwright test --update-snapshots` 2026-05-10. Lagret under
|
||||
`tests/e2e/snapshots/`:
|
||||
|
||||
- `voyage-playground-light.png` (1280×900, light theme)
|
||||
- `voyage-playground-dark.png` (1280×900, dark theme)
|
||||
|
||||
Pixel-diff-spec (`tests/e2e/voyage-playground-a11y.spec.mjs`) sammenlikner mot
|
||||
disse baselines med `maxDiffPixelRatio: 0.02`. Avvik > 2% utløser test-fail.
|
||||
|
||||
## Kjente WCAG-violations (baseline'd, defer til v4.4)
|
||||
|
||||
Wave 7 = VERIFICATION ONLY. HTML er FROZEN i Sesjon 6 — ingen fix. Existing
|
||||
critical/serious violations er recorded i `tests/e2e/snapshots/a11y-baseline.json`
|
||||
som delta-baseline:
|
||||
|
||||
```json
|
||||
{
|
||||
"light": { "aria-hidden-focus": 1, "color-contrast": 4 },
|
||||
"dark": { "aria-hidden-focus": 1 }
|
||||
}
|
||||
```
|
||||
|
||||
- **`aria-hidden-focus`** (1 forekomst, light + dark): aria-hidden element inneholder fokuserbart innhold
|
||||
- **`color-contrast`** (4 forekomster, kun light theme): `.key-stat--critical > .key-stat__label` har kontrast 3.85:1 (WCAG AA krever 4.5:1)
|
||||
|
||||
**Defer-rationale:** v4.3 brief Wave 7 mandat er `test_strategy.coverage`-utvidelse, ikke
|
||||
WCAG-fixing. v4.4 skal unfreeze HTML og adressere disse via DS-token-justering.
|
||||
|
||||
## Verifikasjon-sjekkliste (Steg-for-steg)
|
||||
|
||||
- [x] Group A static-grep tester (Step 28) passerer alle 17 SC1-elementer
|
||||
- [x] Manuell side-by-side mot llm-security-playground (operatør, dette dokument)
|
||||
- [x] Playwright PNG-baselines etablert for light + dark theme
|
||||
- [x] axe-core delta-baseline JSON committed
|
||||
- [x] Pixel-diff spec passerer 2% terskel
|
||||
- [x] WCAG-violations dokumentert som baseline (defer til v4.4)
|
||||
|
|
@ -1,89 +0,0 @@
|
|||
# Voyage playground screenshot convention (v4.3)
|
||||
|
||||
This directory holds reference screenshots for the Voyage playground
|
||||
(`playground/voyage-playground.html`). They serve as a visual baseline for
|
||||
manual review of design changes and as fixtures for the Wave 7 axe-core
|
||||
Playwright spec (`tests/e2e/voyage-playground-a11y.spec.mjs`).
|
||||
|
||||
Screenshots are NOT auto-committed. The `tests/e2e/snapshots/` directory
|
||||
(produced by Playwright in Wave 7) is the test-baseline; this directory
|
||||
holds curated illustrative captures for documentation.
|
||||
|
||||
## Mappestruktur
|
||||
|
||||
```
|
||||
docs/screenshots/
|
||||
README.md ← this file
|
||||
dashboard/ ← project-dashboard fleet-grid views
|
||||
artifact-detail/ ← drill-down render of brief/plan/review
|
||||
annotation/ ← gutter-badge + sidebar + active highlight states
|
||||
dark-mode/ ← screenshots taken with html[data-theme="dark"]
|
||||
light-mode/ ← screenshots taken with html[data-theme="light"]
|
||||
```
|
||||
|
||||
Each subfolder contains PNGs named by feature + variant, e.g.
|
||||
`dashboard/fleet-grid-with-progress-tile.png`,
|
||||
`annotation/active-anchor-yellow-tint.png`.
|
||||
|
||||
## Hooks (window.__voyage)
|
||||
|
||||
The playground exposes three automation hooks for headless screenshot
|
||||
scripts. They are namespaced under `window.__voyage` to avoid global
|
||||
pollution:
|
||||
|
||||
| Method | Purpose |
|
||||
|--------|---------|
|
||||
| `window.__voyage.navigate(surface)` | Switch surface. `surface ∈ ['dashboard', 'detail', 'render', 'a11y']` |
|
||||
| `window.__voyage.scheduleRender(state)` | Pre-populate state. `state.markdown` triggers `mountRender`; `state.artifacts` triggers `renderDashboard` |
|
||||
| `window.__voyage.getProjectArtifacts()` | Returns the last-loaded `ProjectArtifacts` object (or `null`) |
|
||||
|
||||
The hook surface mirrors the pattern used in
|
||||
`plugins/llm-security/playground/llm-security-playground.html`
|
||||
(`window.__navigate`, `window.__scheduleRender`).
|
||||
|
||||
## Producing screenshots — Playwright headless (Wave 7+)
|
||||
|
||||
Wave 7 ships a Playwright spec
|
||||
(`tests/e2e/voyage-playground-a11y.spec.mjs`). Reuse its setup for
|
||||
screenshots:
|
||||
|
||||
```js
|
||||
// tests/e2e/snapshot-helper.mjs (NOT committed in v4.3 — illustrative)
|
||||
import { test } from '@playwright/test';
|
||||
|
||||
test('dashboard with all artifacts', async ({ page }) => {
|
||||
await page.goto('file://' + process.cwd() + '/playground/voyage-playground.html');
|
||||
await page.evaluate(() => {
|
||||
window.__voyage.scheduleRender({
|
||||
artifacts: {
|
||||
basePath: 'demo',
|
||||
brief: { path: 'brief.md', content: '...' },
|
||||
plan: { path: 'plan.md', content: '...' },
|
||||
review: null,
|
||||
research: [],
|
||||
architecture: { overview: null, gaps: null, looseFiles: [] },
|
||||
progress: null,
|
||||
looseFiles: [],
|
||||
}
|
||||
});
|
||||
});
|
||||
await page.screenshot({ path: 'docs/screenshots/dashboard/fleet-grid-demo.png' });
|
||||
});
|
||||
```
|
||||
|
||||
## Producing screenshots — manuelt
|
||||
|
||||
1. Åpne `playground/voyage-playground.html` i Chrome/Firefox.
|
||||
2. Hvis du trenger et bestemt UI-state, paste relevant artifact-innhold i
|
||||
textarea og trykk Render.
|
||||
3. macOS: `Cmd+Shift+4`, deretter `Space` for vindu-skjermbilde.
|
||||
4. Lagre med beskrivende filnavn under riktig undermappe ovenfor.
|
||||
|
||||
## Konvensjon for nye screenshots
|
||||
|
||||
- Bruk PNG, ikke JPG (lossless for tekst-tunge UIer).
|
||||
- Kjør i konsistent viewport (1280×800 anbefales for desktop-baseline).
|
||||
- Ta dark- og light-mode-varianter parvis når komponenten har visuelle
|
||||
forskjeller mellom temaene.
|
||||
- Ikke commit screenshots med personidentifiserende info eller hemmelig
|
||||
artifact-innhold.
|
||||
Loading…
Add table
Add a link
Reference in a new issue