diff --git a/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/accepted-state.json b/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/accepted-state.json new file mode 100644 index 00000000..6121faaf --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/accepted-state.json @@ -0,0 +1,55 @@ +{ + "schema_version": 1, + "workflow_version": 2, + "workflow_origin_version": 2, + "id": "add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer", + "slug": "add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer", + "title": "Add matching X Y Z axis rotation gizmos and precise camera steps to Sculpt and the viewer", + "description": "Add matching X Y Z axis rotation gizmos and precise camera steps to Sculpt and the viewer", + "kind": "feature", + "state": "accepted", + "canonical_applied": true, + "base_commit": "fefd8316adfff3af8bdb87d26b4a417650540b56", + "created_at": 1791644309, + "updated_at": 1791655945, + "affected_specs": [ + "ThreeMDViewer" + ], + "affected_paths": [ + "web/viewer.html", + "uitests/viewer.spec.mjs", + "hi/tools.md", + "specs/ThreeMDViewer", + "apps/sculpt/Sources/RookSculpture/SculptureProjection.swift", + "apps/sculpt/Sources/RookApp/SculptureViewport.swift", + "apps/sculpt/Sources/RookRendering/SculptureLiveVoxelView.swift", + "apps/sculpt/Sources/RookRendering/SculptureVoxelGeometry.swift", + "apps/sculpt/Tests", + "apps/sculpt/hi", + "apps/sculpt/specs" + ], + "no_spec_change": false, + "no_spec_change_rationale": null, + "acceptance_criteria": [ + "Both volume views show a small sphere with colored X, Y and Z rotation rings and accessible axis buttons. Choosing an axis constrains dragging and step buttons to rotation around that document axis; Free restores unconstrained orbit.", + "Three-axis rotation preserves an orthonormal camera orientation and supports Z rotation without changing model cells, slice, Undo, files, or installed geometry. Native and browser use the same document-axis convention, including row Y and plane Z.", + "Both views offer an editable rotation step in degrees (default 15 degrees) with minus and plus nudges, and an editable pan step in cells (default 0.25) with directional nudges. Values must be finite and positive; invalid input leaves the current camera unchanged. Fit resets the default pose and pan.", + "Tests compare shared asymmetric projection and picking cases including Z rotation, full X/Y/Z turns, negative nudges and exact inverse steps; native live and scalar renderers agree. Camera controls remain usable on narrow screens and have keyboard labels and focus indication.", + "Synchronize viewer and Sculpt contracts and intent, record actual current tests, complete verified lifecycle closure under Leif’s approved PR 93 camera scope, and preserve storage, rendering budgets, parser APIs, releases and trust policy." + ], + "selected_artifacts": [ + "context", + "requirements", + "plan", + "tasks", + "testing", + "docs", + "design", + "research" + ], + "dependencies": [], + "answers": { + "architecture_risk": "yes", + "public_contract": "yes" + } +} diff --git a/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/approvals.json b/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/approvals.json new file mode 100644 index 00000000..7d4ed887 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/approvals.json @@ -0,0 +1,60 @@ +{ + "approvals": [ + { + "gate": "definition", + "actor": "user:0xLeif", + "timestamp": 1791653015, + "digest": "4b6d4eb372c26f296d08a35c4242b772ba7f537d690b3ac81723034860824618", + "note": "Leif directly replied continue after the complete Slice and matching X/Y/Z camera definitions were presented together for approval and verified closure. This is scope approval, not human diff review or signed provenance.", + "approved_scope": { + "schema_version": 1, + "change_id": "add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer", + "title": "Add matching X Y Z axis rotation gizmos and precise camera steps to Sculpt and the viewer", + "description": "Add matching X Y Z axis rotation gizmos and precise camera steps to Sculpt and the viewer", + "kind": "feature", + "affected_specs": [ + "ThreeMDViewer" + ], + "affected_paths": [ + "apps/sculpt/Sources/RookApp/SculptureViewport.swift", + "apps/sculpt/Sources/RookRendering/SculptureLiveVoxelView.swift", + "apps/sculpt/Sources/RookRendering/SculptureVoxelGeometry.swift", + "apps/sculpt/Sources/RookSculpture/SculptureProjection.swift", + "apps/sculpt/Tests", + "apps/sculpt/hi", + "apps/sculpt/specs", + "hi/tools.md", + "specs/ThreeMDViewer", + "uitests/viewer.spec.mjs", + "web/viewer.html" + ], + "no_spec_change": false, + "no_spec_change_rationale": null, + "acceptance_criteria": [ + "Both views offer an editable rotation step in degrees (default 15 degrees) with minus and plus nudges, and an editable pan step in cells (default 0.25) with directional nudges. Values must be finite and positive; invalid input leaves the current camera unchanged. Fit resets the default pose and pan.", + "Both volume views show a small sphere with colored X, Y and Z rotation rings and accessible axis buttons. Choosing an axis constrains dragging and step buttons to rotation around that document axis; Free restores unconstrained orbit.", + "Synchronize viewer and Sculpt contracts and intent, record actual current tests, complete verified lifecycle closure under Leif’s approved PR 93 camera scope, and preserve storage, rendering budgets, parser APIs, releases and trust policy.", + "Tests compare shared asymmetric projection and picking cases including Z rotation, full X/Y/Z turns, negative nudges and exact inverse steps; native live and scalar renderers agree. Camera controls remain usable on narrow screens and have keyboard labels and focus indication.", + "Three-axis rotation preserves an orthonormal camera orientation and supports Z rotation without changing model cells, slice, Undo, files, or installed geometry. Native and browser use the same document-axis convention, including row Y and plane Z." + ], + "dependencies": [], + "supersedes": [], + "answers": { + "architecture_risk": "yes", + "public_contract": "yes" + } + }, + "approved_delta_digests": { + "ThreeMDViewer": "41ce28706a4b04ba3801ad8ef3e98217bdaaf285333d2b519f476919f2767a08" + } + }, + { + "gate": "finalization", + "actor": "specsync:finalization", + "timestamp": 1791655945, + "digest": "97d2b14dc39e8ae4fc624f05df89f8af6d26f2dda73159226b4dcd2c0639793d", + "note": "Same-PR finalization closing digest" + } + ], + "reopenings": [] +} diff --git a/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/change.md b/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/change.md new file mode 100644 index 00000000..d5c8d9cf --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/change.md @@ -0,0 +1,28 @@ +--- +id: add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer +state: archived +type: feature +base_commit: fefd8316adfff3af8bdb87d26b4a417650540b56 +--- + +# Add matching X Y Z axis rotation gizmos and precise camera steps to Sculpt and the viewer + +## Intent + +Add matching X Y Z axis rotation gizmos and precise camera steps to Sculpt and the viewer + +## Affected Canonical Specs + +- `ThreeMDViewer` + +## Acceptance Criteria + +- Both volume views show a small sphere with colored X, Y and Z rotation rings and accessible axis buttons. Choosing an axis constrains dragging and step buttons to rotation around that document axis; Free restores unconstrained orbit. +- Three-axis rotation preserves an orthonormal camera orientation and supports Z rotation without changing model cells, slice, Undo, files, or installed geometry. Native and browser use the same document-axis convention, including row Y and plane Z. +- Both views offer an editable rotation step in degrees (default 15 degrees) with minus and plus nudges, and an editable pan step in cells (default 0.25) with directional nudges. Values must be finite and positive; invalid input leaves the current camera unchanged. Fit resets the default pose and pan. +- Tests compare shared asymmetric projection and picking cases including Z rotation, full X/Y/Z turns, negative nudges and exact inverse steps; native live and scalar renderers agree. Camera controls remain usable on narrow screens and have keyboard labels and focus indication. +- Synchronize viewer and Sculpt contracts and intent, record actual current tests, complete verified lifecycle closure under Leif’s approved PR 93 camera scope, and preserve storage, rendering budgets, parser APIs, releases and trust policy. + +## No-spec Rationale + +Not applicable diff --git a/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/context.md b/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/context.md new file mode 100644 index 00000000..31a54064 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/context.md @@ -0,0 +1,8 @@ +--- +change: add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer +artifact: context +--- + +# Context + +Leif directly requested a Unity/Godot-style three-axis rotation sphere and precise movement. This is a new addition to the approved full orbit and pan work. The user wants matching native Sculpt and browser behavior. This definition is pending human approval; no implementation, verification, acceptance or archive is claimed. diff --git a/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/deltas/ThreeMDViewer.md b/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/deltas/ThreeMDViewer.md new file mode 100644 index 00000000..abdf67d0 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/deltas/ThreeMDViewer.md @@ -0,0 +1,15 @@ +# ThreeMDViewer delta + +## ADDED + +### REQUIREMENT REQ-ThreeMDViewer-007 + +The viewer and Sculpt volume view SHALL provide matched document-axis rotation constraints and numerical rotation/pan steps alongside the camera sphere. + +Acceptance Criteria: + +- Both volume views show a small sphere with colored X, Y and Z rotation rings and accessible axis buttons. Choosing an axis constrains dragging and step buttons to rotation around that document axis; Free restores unconstrained orbit. +- Three-axis rotation preserves an orthonormal camera orientation and supports Z rotation without changing model cells, slice, Undo, files, or installed geometry. Native and browser use the same document-axis convention, including row Y and plane Z. +- Both views offer an editable rotation step in degrees (default 15 degrees) with minus and plus nudges, and an editable pan step in cells (default 0.25) with directional nudges. Values must be finite and positive; invalid input leaves the current camera unchanged. Fit resets the default pose and pan. +- Tests compare shared asymmetric projection and picking cases including Z rotation, full X/Y/Z turns, negative nudges and exact inverse steps; native live and scalar renderers agree. Camera controls remain usable on narrow screens and have keyboard labels and focus indication. +- Synchronize viewer and Sculpt contracts and intent, record actual current tests, and complete verified lifecycle closure only under Leif’s explicit approval of this new definition. Leif retains PR merge authority. Preserve storage, rendering budgets, parser APIs, releases and trust policy. diff --git a/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/design.md b/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/design.md new file mode 100644 index 00000000..1a5351e0 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/design.md @@ -0,0 +1,8 @@ +--- +change: add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer +artifact: design +--- + +# Design + +Show a compact orientation sphere with red X, green Y and blue Z rings. Click a ring or its labeled axis button to constrain rotation. Free restores ordinary orbit. Degree-step minus/plus buttons rotate only the selected axis; directional buttons use the cell-valued pan step. The controls use native SwiftUI and browser SVG, fit the existing stage design and remain accessible by keyboard. Default steps are 15 degrees and 0.25 cells. Preserve browser controls below the drawing and compact phone layout. diff --git a/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/docs.md b/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/docs.md new file mode 100644 index 00000000..8636199d --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/docs.md @@ -0,0 +1,8 @@ +--- +change: add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer +artifact: docs +--- + +# Docs + +Document the matching sphere, constrained drag, degree nudges, cell pan steps and reset behavior in ThreeMDViewer, RookSculpture, RookRendering, RookApp and current intent. Keep historical lifecycle records intact. Retain actual verification receipts; current approval and finalization are pending. diff --git a/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/finalization.json b/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/finalization.json new file mode 100644 index 00000000..992b161f --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/finalization.json @@ -0,0 +1,12 @@ +{ + "schema_version": 2, + "change_id": "add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer", + "implementation_commit": "60055f7806a4d46964b766672784be45713e3c3a", + "implementation_tree": "9970ef31ab167b4c3429cc3aa17af3651c830918", + "contract_digest": "4b6d4eb372c26f296d08a35c4242b772ba7f537d690b3ac81723034860824618", + "workspace_digest": "fde013fc78a6110e0c0b88de16f5f6e7522e6561a06c0a5c5fd273d884ed5278", + "closing_digest": "97d2b14dc39e8ae4fc624f05df89f8af6d26f2dda73159226b4dcd2c0639793d", + "review_digest": "cf186ff11b71dbf0169c2d3aeaa61edefc6e214954bf82620c6ad53d5759d410", + "finalization_digest": "1225a89a0f4a47068497828dd6ef78edf4902c37edde6c9670427d91af38c098", + "timestamp": 1791655945 +} diff --git a/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/lesson-bundle.md b/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/lesson-bundle.md new file mode 100644 index 00000000..9ceb8b70 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/lesson-bundle.md @@ -0,0 +1,54 @@ +# Lesson bundle — add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer + +Material for folding this change's lessons into the affected specs' `context.md`. +Synthesise from what actually happened below; do not restate the change description. + +## What this change was + +- **Title**: Add matching X Y Z axis rotation gizmos and precise camera steps to Sculpt and the viewer +- **Kind**: Feature +- **Specs**: ThreeMDViewer +- **Paths**: web/viewer.html, uitests/viewer.spec.mjs, hi/tools.md, specs/ThreeMDViewer, apps/sculpt/Sources/RookSculpture/SculptureProjection.swift, apps/sculpt/Sources/RookApp/SculptureViewport.swift, apps/sculpt/Sources/RookRendering/SculptureLiveVoxelView.swift, apps/sculpt/Sources/RookRendering/SculptureVoxelGeometry.swift, apps/sculpt/Tests, apps/sculpt/hi, apps/sculpt/specs +- **Acceptance**: Both volume views show a small sphere with colored X, Y and Z rotation rings and accessible axis buttons. Choosing an axis constrains dragging and step buttons to rotation around that document axis; Free restores unconstrained orbit. +- **Acceptance**: Three-axis rotation preserves an orthonormal camera orientation and supports Z rotation without changing model cells, slice, Undo, files, or installed geometry. Native and browser use the same document-axis convention, including row Y and plane Z. +- **Acceptance**: Both views offer an editable rotation step in degrees (default 15 degrees) with minus and plus nudges, and an editable pan step in cells (default 0.25) with directional nudges. Values must be finite and positive; invalid input leaves the current camera unchanged. Fit resets the default pose and pan. +- **Acceptance**: Tests compare shared asymmetric projection and picking cases including Z rotation, full X/Y/Z turns, negative nudges and exact inverse steps; native live and scalar renderers agree. Camera controls remain usable on narrow screens and have keyboard labels and focus indication. +- **Acceptance**: Synchronize viewer and Sculpt contracts and intent, record actual current tests, complete verified lifecycle closure under Leif’s approved PR 93 camera scope, and preserve storage, rendering budgets, parser APIs, releases and trust policy. + +## Evidence + +- Verification commit: `60055f7806a4d46964b766672784be45713e3c3a` +- Base commit: `fefd8316adfff3af8bdb87d26b4a417650540b56` +- Verified by: `specsync check --spec ThreeMDViewer --strict` + +## From the change's context.md + +# Context + +Leif directly requested a Unity/Godot-style three-axis rotation sphere and precise movement. This is a new addition to the approved full orbit and pan work. The user wants matching native Sculpt and browser behavior. This definition is pending human approval; no implementation, verification, acceptance or archive is claimed. + +## From the change's design.md + +# Design + +Show a compact orientation sphere with red X, green Y and blue Z rings. Click a ring or its labeled axis button to constrain rotation. Free restores ordinary orbit. Degree-step minus/plus buttons rotate only the selected axis; directional buttons use the cell-valued pan step. The controls use native SwiftUI and browser SVG, fit the existing stage design and remain accessible by keyboard. Default steps are 15 degrees and 0.25 cells. Preserve browser controls below the drawing and compact phone layout. + +## From the change's testing.md + +# Testing + +Test each document axis with positive, negative and full-turn rotations, including Z roll and pole crossings. Compare native live, scalar and browser projected points and nearest cube hits. Assert inverse steps restore the same basis, invalid inputs do not mutate the camera, camera adjustments preserve document and geometry, and mobile and keyboard controls stay usable. Run the relevant native and Chromium/WebKit regressions and current trust gate after implementation. + +## Execution evidence + +Implementation commit 8e9a0c4 has 226 passing macOS browser tests, 637 passing configured native tests and 11 passing final native parity tests. Expanded browser fixtures and phone checks each passed 4 cases. Pinned Trust passed; actual unsigned agent:codex provenance was recorded and fails the unchanged permitted-signature/reviewer policy as expected. Linux CI passed 218 functional tests with 8 existing platform-snapshot skips and no retries; all macOS snapshots passed. Current receipts are in docs/evidence/viewer-slice; final lifecycle receipts are separate. Source and visual verification are distinct from Leif’s diff review. + +## Requirement evidence + +| ID | Canonical | Evidence | +| --- | --- | --- | +| REQ-ThreeMDViewer-007 | REQ-ThreeMDViewer-007 | Independent shared camera-parity.json matrix/projection values compared with browser GPU uniforms and nearest picks, native scalar/live basis and picks, full-turn/inverse normalization, ASCII Z picking and mesh installation reuse. Browser precise-input and phone tests pass; native/UI screenshots and logs are in docs/evidence/viewer-slice. | + +## Where these lessons go + +- `specs/ThreeMDViewer/context.md` diff --git a/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/plan.md b/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/plan.md new file mode 100644 index 00000000..6e1e2332 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/plan.md @@ -0,0 +1,8 @@ +--- +change: add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer +artifact: plan +--- + +# Plan + +Add a session-only third camera rotation component and document-axis rotation math. Apply the same orientation to native scalar, ASCII and GPU projection and browser view/picking. Add colored projected sphere rings, accessible X/Y/Z and Free controls, degree steps and cell pan steps in both viewports. Verify shared numerical projection and nearest-hit cases with preserved geometry and source. Update specs and intent before delivering the existing feature PR. diff --git a/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/requirements.md b/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/requirements.md new file mode 100644 index 00000000..87a105b4 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/requirements.md @@ -0,0 +1,18 @@ +--- +change: add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer +artifact: requirements +--- + +# Requirements + +### REQ-ThreeMDViewer-007 + +The viewer and Sculpt volume view SHALL provide matched document-axis rotation constraints and numerical rotation/pan steps alongside the camera sphere. + +Acceptance Criteria: + +- Both volume views show a small sphere with colored X, Y and Z rotation rings and accessible axis buttons. Choosing an axis constrains dragging and step buttons to rotation around that document axis; Free restores unconstrained orbit. +- Three-axis rotation preserves an orthonormal camera orientation and supports Z rotation without changing model cells, slice, Undo, files, or installed geometry. Native and browser use the same document-axis convention, including row Y and plane Z. +- Both views offer an editable rotation step in degrees (default 15 degrees) with minus and plus nudges, and an editable pan step in cells (default 0.25) with directional nudges. Values must be finite and positive; invalid input leaves the current camera unchanged. Fit resets the default pose and pan. +- Tests compare shared asymmetric projection and picking cases including Z rotation, full X/Y/Z turns, negative nudges and exact inverse steps; native live and scalar renderers agree. Camera controls remain usable on narrow screens and have keyboard labels and focus indication. +- Synchronize viewer and Sculpt contracts and intent, record actual current tests, and complete verified lifecycle closure only under Leif’s explicit approval of this new definition. Leif retains PR merge authority. Preserve storage, rendering budgets, parser APIs, releases and trust policy. diff --git a/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/research.md b/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/research.md new file mode 100644 index 00000000..b1d34921 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/research.md @@ -0,0 +1,8 @@ +--- +change: add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer +artifact: research +--- + +# Research + +Native document coordinates map X to horizontal, Y to downward grid rows and Z to plane depth. Native render Y is inverted, and native yaw is the negative of browser yaw for the same pose. Existing two-angle cameras cannot represent independent document-Z rotation, so a third session-only angle and orthonormal basis are needed. Use explicit document-axis rotation to avoid relabeling camera yaw/pitch as world axes. Storage codecs never encode camera state. diff --git a/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/review-attempts.json b/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/review-attempts.json new file mode 100644 index 00000000..d834c3a1 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/review-attempts.json @@ -0,0 +1,21 @@ +{ + "schema_version": 1, + "reviews": [ + { + "schema_version": 2, + "change_id": "add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer", + "reviewer": "agent:codex", + "provenance": { + "schema_version": 1, + "provider": "github_actions_check", + "required_check": "SpecSync scoped review" + }, + "verdict": "pass", + "implementation_commit": "60055f7806a4d46964b766672784be45713e3c3a", + "contract_digest": "4b6d4eb372c26f296d08a35c4242b772ba7f537d690b3ac81723034860824618", + "execution_digest": "da242228adc07b4a8a41fc7d90d24f0e9d3d8dd459769a1a72c8cd55aa49ff8f", + "workspace_digest": "fde013fc78a6110e0c0b88de16f5f6e7522e6561a06c0a5c5fd273d884ed5278", + "timestamp": 1791655905 + } + ] +} diff --git a/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/review.json b/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/review.json new file mode 100644 index 00000000..748cd375 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/review.json @@ -0,0 +1,16 @@ +{ + "schema_version": 2, + "change_id": "add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer", + "reviewer": "agent:codex", + "provenance": { + "schema_version": 1, + "provider": "github_actions_check", + "required_check": "SpecSync scoped review" + }, + "verdict": "pass", + "implementation_commit": "60055f7806a4d46964b766672784be45713e3c3a", + "contract_digest": "4b6d4eb372c26f296d08a35c4242b772ba7f537d690b3ac81723034860824618", + "execution_digest": "da242228adc07b4a8a41fc7d90d24f0e9d3d8dd459769a1a72c8cd55aa49ff8f", + "workspace_digest": "fde013fc78a6110e0c0b88de16f5f6e7522e6561a06c0a5c5fd273d884ed5278", + "timestamp": 1791655905 +} diff --git a/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/state.json b/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/state.json new file mode 100644 index 00000000..306eb1da --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/state.json @@ -0,0 +1,55 @@ +{ + "schema_version": 1, + "workflow_version": 2, + "workflow_origin_version": 2, + "id": "add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer", + "slug": "add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer", + "title": "Add matching X Y Z axis rotation gizmos and precise camera steps to Sculpt and the viewer", + "description": "Add matching X Y Z axis rotation gizmos and precise camera steps to Sculpt and the viewer", + "kind": "feature", + "state": "archived", + "canonical_applied": true, + "base_commit": "fefd8316adfff3af8bdb87d26b4a417650540b56", + "created_at": 1791644309, + "updated_at": 1791656000, + "affected_specs": [ + "ThreeMDViewer" + ], + "affected_paths": [ + "web/viewer.html", + "uitests/viewer.spec.mjs", + "hi/tools.md", + "specs/ThreeMDViewer", + "apps/sculpt/Sources/RookSculpture/SculptureProjection.swift", + "apps/sculpt/Sources/RookApp/SculptureViewport.swift", + "apps/sculpt/Sources/RookRendering/SculptureLiveVoxelView.swift", + "apps/sculpt/Sources/RookRendering/SculptureVoxelGeometry.swift", + "apps/sculpt/Tests", + "apps/sculpt/hi", + "apps/sculpt/specs" + ], + "no_spec_change": false, + "no_spec_change_rationale": null, + "acceptance_criteria": [ + "Both volume views show a small sphere with colored X, Y and Z rotation rings and accessible axis buttons. Choosing an axis constrains dragging and step buttons to rotation around that document axis; Free restores unconstrained orbit.", + "Three-axis rotation preserves an orthonormal camera orientation and supports Z rotation without changing model cells, slice, Undo, files, or installed geometry. Native and browser use the same document-axis convention, including row Y and plane Z.", + "Both views offer an editable rotation step in degrees (default 15 degrees) with minus and plus nudges, and an editable pan step in cells (default 0.25) with directional nudges. Values must be finite and positive; invalid input leaves the current camera unchanged. Fit resets the default pose and pan.", + "Tests compare shared asymmetric projection and picking cases including Z rotation, full X/Y/Z turns, negative nudges and exact inverse steps; native live and scalar renderers agree. Camera controls remain usable on narrow screens and have keyboard labels and focus indication.", + "Synchronize viewer and Sculpt contracts and intent, record actual current tests, complete verified lifecycle closure under Leif’s approved PR 93 camera scope, and preserve storage, rendering budgets, parser APIs, releases and trust policy." + ], + "selected_artifacts": [ + "context", + "requirements", + "plan", + "tasks", + "testing", + "docs", + "design", + "research" + ], + "dependencies": [], + "answers": { + "architecture_risk": "yes", + "public_contract": "yes" + } +} diff --git a/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/tasks.md b/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/tasks.md new file mode 100644 index 00000000..29b3dcc4 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/tasks.md @@ -0,0 +1,13 @@ +--- +change: add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer +artifact: tasks +--- + +# Tasks + +- [x] Approve the axis and precision definition. +- [x] Implement matched three-axis orientation. +- [x] Add native and browser sphere/constraint/step controls. +- [x] Verify numerical, picking, geometry and input parity. +- [x] Synchronize contracts and intent. +- [x] Record current verification and prepare approved lifecycle closure. diff --git a/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/testing.md b/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/testing.md new file mode 100644 index 00000000..ae615e6f --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/testing.md @@ -0,0 +1,18 @@ +--- +change: add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer +artifact: testing +--- + +# Testing + +Test each document axis with positive, negative and full-turn rotations, including Z roll and pole crossings. Compare native live, scalar and browser projected points and nearest cube hits. Assert inverse steps restore the same basis, invalid inputs do not mutate the camera, camera adjustments preserve document and geometry, and mobile and keyboard controls stay usable. Run the relevant native and Chromium/WebKit regressions and current trust gate after implementation. + +## Execution evidence + +Implementation commit 8e9a0c4 has 226 passing macOS browser tests, 637 passing configured native tests and 11 passing final native parity tests. Expanded browser fixtures and phone checks each passed 4 cases. Pinned Trust passed; actual unsigned agent:codex provenance was recorded and fails the unchanged permitted-signature/reviewer policy as expected. Linux CI passed 218 functional tests with 8 existing platform-snapshot skips and no retries; all macOS snapshots passed. Current receipts are in docs/evidence/viewer-slice; final lifecycle receipts are separate. Source and visual verification are distinct from Leif’s diff review. + +## Requirement evidence + +| ID | Canonical | Evidence | +| --- | --- | --- | +| REQ-ThreeMDViewer-007 | REQ-ThreeMDViewer-007 | Independent shared camera-parity.json matrix/projection values compared with browser GPU uniforms and nearest picks, native scalar/live basis and picks, full-turn/inverse normalization, ASCII Z picking and mesh installation reuse. Browser precise-input and phone tests pass; native/UI screenshots and logs are in docs/evidence/viewer-slice. | diff --git a/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/verification-attempts.json b/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/verification-attempts.json new file mode 100644 index 00000000..d4a6a36a --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/verification-attempts.json @@ -0,0 +1,1291 @@ +{ + "schema_version": 1, + "attempts": [ + { + "timestamp": 1791655587, + "commit": "879ea2515e5a5a9e04ab6672228d9013ae4a4d82", + "contract_digest": "4b6d4eb372c26f296d08a35c4242b772ba7f537d690b3ac81723034860824618", + "execution_digest": "1db450eb32b21efdee8b19e0d917a868a30bbea5a3339a8312faa1e2c95bacb8", + "workspace_digest": "8585efd5a1f8279d68999fda90ab46f7caccdbb47824face80247500c2aef591", + "passed": true, + "commands": [ + { + "command": "specsync check --spec ThreeMDViewer --strict", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [ + "REQ-ThreeMDViewer-007" + ] + }, + { + "timestamp": 1791655607, + "commit": "3dce9ac0825a9f4c931670540e56d60859249901", + "contract_digest": "4b6d4eb372c26f296d08a35c4242b772ba7f537d690b3ac81723034860824618", + "execution_digest": "1db450eb32b21efdee8b19e0d917a868a30bbea5a3339a8312faa1e2c95bacb8", + "workspace_digest": "8585efd5a1f8279d68999fda90ab46f7caccdbb47824face80247500c2aef591", + "passed": true, + "commands": [ + { + "command": "specsync check --spec ThreeMDViewer --strict", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [ + "REQ-ThreeMDViewer-007" + ] + }, + { + "timestamp": 1791655864, + "commit": "06a806db5100c0b3c0807819bc7c10ad453351e5", + "contract_digest": "4b6d4eb372c26f296d08a35c4242b772ba7f537d690b3ac81723034860824618", + "execution_digest": "da242228adc07b4a8a41fc7d90d24f0e9d3d8dd459769a1a72c8cd55aa49ff8f", + "workspace_digest": "fde013fc78a6110e0c0b88de16f5f6e7522e6561a06c0a5c5fd273d884ed5278", + "passed": true, + "commands": [ + { + "command": "specsync check --spec ThreeMDViewer --strict", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [ + "REQ-ThreeMDViewer-007" + ] + }, + { + "timestamp": 1791655884, + "commit": "deb44c9222f5ef7593ad19e3786f31aa26d880c9", + "contract_digest": "4b6d4eb372c26f296d08a35c4242b772ba7f537d690b3ac81723034860824618", + "execution_digest": "da242228adc07b4a8a41fc7d90d24f0e9d3d8dd459769a1a72c8cd55aa49ff8f", + "workspace_digest": "fde013fc78a6110e0c0b88de16f5f6e7522e6561a06c0a5c5fd273d884ed5278", + "passed": true, + "commands": [ + { + "command": "specsync check --spec ThreeMDViewer --strict", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [ + "REQ-ThreeMDViewer-007" + ] + }, + { + "timestamp": 1791655884, + "commit": "60055f7806a4d46964b766672784be45713e3c3a", + "contract_digest": "4b6d4eb372c26f296d08a35c4242b772ba7f537d690b3ac81723034860824618", + "execution_digest": "da242228adc07b4a8a41fc7d90d24f0e9d3d8dd459769a1a72c8cd55aa49ff8f", + "workspace_digest": "fde013fc78a6110e0c0b88de16f5f6e7522e6561a06c0a5c5fd273d884ed5278", + "acceptance_input_digest": "75c60a31bc1b305db3d7f15f76d65654d7a80eea3669ed8ed768701654a163a0", + "acceptance_manifest": { + "schema_version": 1, + "entries": [ + { + "path": "apps/sculpt/Sources/RookApp/SculptureViewport.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "8d5ab6c914e03d60dadc58a3e8b6d4f595a261b1e032c46cc0cdbd0597757e45", + "entry_digest": "24442eef4a7215ed811720b44e4f3014ac30df390846447f342ebe7b9d94ff1d", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Sources/RookRendering/SculptureLiveVoxelView.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "610272100afb40b290302e64c8cf72544b67f3c2cee3543b292f796531c9750e", + "entry_digest": "210439bcd02c86c1940dbec87538b50db5a465257538913389cb8d82d767fe6c", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Sources/RookRendering/SculptureVoxelGeometry.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "24c096ecd359193366e02097643561e28fb3ff422e1fafda1661dbf0f706eb86", + "entry_digest": "b2ff90dc0d60eeb4fdc2983e7c2a13382859ab24164d5d355787aaf98bbe6807", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Sources/RookSculpture/SculptureProjection.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "d98745e56609642d7c65369aa67f251d82c3c6089199cd6a2bcc9b1fc928c8d4", + "entry_digest": "22f5d1bb30035cd28eea2c7ed2df463a4ecd679601edeacc7f3e591b9485e267", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests", + "kind": "non_file", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "094f12e742e15c4721c78566d011dd8f2dacfdf163828f9b9e12e6dbbfab2764", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/AppearanceTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "bb460ca170501c02f7e413b1c85c41f0decef55aba4ea735f32c226c36e894e5", + "entry_digest": "ff7f1cf01c86f9e9c1964067854027d5bd8ef674a0894206b189c97a0520df23", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/LayerGridGeometryTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "6645f57ab9861bcab490fd53808b6a178c57ae6833e51f4575c31c95f641ef46", + "entry_digest": "abc7fbc1e12be39495e89853bcdaab5cec35152d1d0e48d8c1828c3755e6ded1", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/LayerGridScrollPresentationTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "1533740a7d0e2347a50bc5ac3ac8ba08037dbc8ac7e3b3c50c022b53f49a765c", + "entry_digest": "a5134e75f1746ab129d9f84012691cc39727df27949a5bce4c6e65ba6d75fa16", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureCanvasPointerTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "2eeb532f40db634a0674a94857aed000224be0526de24fc72a000a2570991883", + "entry_digest": "7e2b1210b7a3eb39e7ebcd1a03d4307a65b2fff0f6181e1ba4be83eb0bc2d5cb", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureCommandFocusTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "25fb256f29a8991b87e65f09b8caad37711390bf5c7f31da242bbffc13001576", + "entry_digest": "29bbd13e54d55add0704a17c81ad8da3609d7edac595fd6d499105e2e038d9ed", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureCompositionEditorTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "19bb8062f643d384cdee5e768ed856c9d6b7331980d5987164adbb2973027e3f", + "entry_digest": "d733318c97c4ee44e5ae4376cecff5a69567703d854230b84167bbad055aaad2", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureEditorPresentationTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "ded50853676c0ad3bd625c55d4aaca9769c8e803a04f38ada6c59ae2f49fb095", + "entry_digest": "c75be12388c9fd7c9406e1c524e6d6a339092527fd75575a70927918d22f385d", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureExportJobTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "0101679374acf6525820313028313573b49605c068286d1923b7c3d6986ed675", + "entry_digest": "54c858f1e9b793276d3fa7f1b6f2d4249830ab1229f46f3fed4f48e406706616", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureGalleryBrowserTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "59dcb942153a452120eeabe743a971fa707032ed422b24db19876238f3747b6b", + "entry_digest": "2280e89bb09b6dc17012fea72e1a3bda59c7e1d0504039430317ece2ee21a115", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureGraphSaveJobTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "b3c9b2b8bbf482a27161aef9d1ad0bd161353678319ecfc7e833655b6673276c", + "entry_digest": "62c72b46d143f2d230e7e291b4c5c4f5517666e1459fe3181f507c65624db824", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureInsertionDiscoveryTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "18c78362b45c16063ca9cf888e6376ec1bc56872a2e95261257f7fbe7b363f9b", + "entry_digest": "9057cc0eecaffe749a2c592b04ee299624a3a791c8f6e89e9952ca49b3a5187f", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureInsertionDraftTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "5efc2d96cdbd08514532647eaa7ca762152f211e99665955f0d081f1478a0d72", + "entry_digest": "c93a1807c59024d7836c48968f603168ae5abf5c18754ce75638beb38999d446", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureInsertionRepairTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "6b0fa86e435c43766b7ede2207afc87f460236138c8deaf5b267ac016214a2b1", + "entry_digest": "854eb3a494a8844e8db408b7ea4f42304e8863fea8122776957f6d90da0585c4", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureLinkedConfinementTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "5b1ec9e5b39bdd52833a9003a62cf63f5c1e88896fce4962120345af7f868849", + "entry_digest": "26d045fd6441c6c932b8497303ba52a107129baedddf46c32d26db5eb2cc8800", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureLinkedInsertionTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "e8947fbf69251f81c231f8c2936cfdf8558d8240399ab16369c7bee07b78b2de", + "entry_digest": "80649740dee2b7daf7858ad82f009827d83084e20672f2e08768b08df523e563", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureLinkedPresentationTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "d703a36c7eaac77ef95251a924e5f2275a9d1fc2874d053816590d700bb79bb4", + "entry_digest": "bc53d1a4d3030610a40da15cef40c1e4fb4ec8492dc278ac44c285e940ef9797", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureLinkedSessionTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "afb46a2e240b948ea168b80d3b918090908db29b0e42d14fa17e689862dfb9b0", + "entry_digest": "9de38710e6bcac83215b68343eaa1fdec0e42ca5310fd9899ce9d3edee188e16", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureLinkedTestProject.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "c8e07629a75cb25558958ac0ab6de0a383f3962f4f9ef9d53623de8a790251c5", + "entry_digest": "39ca31385c1dc4f6ce086f4edefa4a2fdaf229d7212db2819ec4c0dd886a5db5", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureMeshRevisionTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "49950faf4516bdbb9f46d1d6382b12e50f2e1e50cb19b24786b9f24b17ef237d", + "entry_digest": "7ba09620fe295e049072120b8295ff92f7b1637701d435a4a3318a8a9ee6aaee", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculpturePortableInterchangeTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "e33d0ecc55db21dea1e7a22c4c53d08d964bf65cfac4482113228328ba5202e2", + "entry_digest": "bfb5e8f52204376972583ec77fed86a25f79cc65a3d865b68c372b8c6036463c", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureReferenceEditorPresentationTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "6f8f32bafce36b5b50625c5959a3f52b64b1ff87d10200423e4a813e3c15facf", + "entry_digest": "c63963edb0b237f7d076eb1da498122467f07c129f8a294dbb953cec825681d1", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureReferenceSaveSessionTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "4f19a8645355e5537b3de91c5d7ce9334cdc20da7cbc334da464b69098c492e5", + "entry_digest": "5fc3bec2792e589ede91c109f0c279256616ca736c99afdcd3d333d20fd53bf7", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureSaveJobTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "49808899eefe4ed5e8e0a1ce701749f6d4ef82ff540bff5473c1b5dd634a37c7", + "entry_digest": "3f5101a4313935905c0ce901ce18506f3ebadfa5412b4c770a7c2207dc68c4ab", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureSharedModelDraftTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "03fc1f9626cd365c84421b581d27b42f842908a09d4cc014939f5dda34cc352f", + "entry_digest": "c4a4e09309acd95d18e227ae25e495f2e44c4ed5f40801e34b347d893297be3f", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureSharedModelPresentationTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "0e4a7bc7a44619ecd9a001c21e2a29adfdf3b9da9d5a1bfdc7ac0c06a889f336", + "entry_digest": "9b37c492d9734c1aecfde57c7f41568d518020cad3e65e42d3e7d2aa6c9266aa", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureVoxelWorkspaceTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "085c78d6a0f10a7a63859feb3783dea5a21ff651bd8641618f29bdd0c9c020ab", + "entry_digest": "cb4638941514ef448fce96171889541f28e5cb2fb1d455b0ea8e8b22ac633a30", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureWorkspaceTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "f420db050af7dea627b63e3b33e113377e3919b69d24b7d4e5a97a6bcd06c681", + "entry_digest": "997ec23ca0eacd6cd532071f3da63de1da66eb5a0f11ba6902520e84b68c637b", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureWorldEditorTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "51707a0e3b30bdb26826e1f0119b1725d39d735df5e7a3de255fe56e294b7922", + "entry_digest": "5b5b3030f6d5fd568e07c8153d7c155e2ec1a224a582b35f54013f6f567f64e4", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SliceGridRenderingTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "f0d9c2da996754a881e260ac2a7b5b5b81406f5cf97ec857bf92e62edaea9cf0", + "entry_digest": "82df33fc6af7c834ad6b35e2edd38724ca63c5201ee0bc7200ddec753e63757c", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookCoreTests/AppAppearanceTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "96b116fa629f3753d8b42934a811c1428f31636e2856db12bd9f583a9126c368", + "entry_digest": "556583436e1058dc662eef44661aae7333461f13160a1f06a9e1ca9f5fbc006e", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookRenderingTests/AnimationExportTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "703d05088f785075738fd195c924270259f2a471566e1b5872881117239fc942", + "entry_digest": "29b0fb1b5fc6a8d6e710a872bf02d19848f68b1d0fdca7a7e06a4e4f2f5042d8", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookRenderingTests/CameraParityTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "97c1b35abd129f1f8fc3a2e3fec0ede9b4416b5a0bdd0c53eb55877dca353c6d", + "entry_digest": "7d2c516df02831b4c7701e5d5d3fd31791d99cb6d7b456bd177db175f8fd9c2b", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookRenderingTests/CubeExportTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "6bff8220f252746e5591956209d228de11b97b8b46e98d0ea09ae13f93c3e324", + "entry_digest": "d76039bb23eb138a74b6e89671c99768c725e12b1760b8582aa64942ddb9665a", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookRenderingTests/ExampleArtifactTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "affec5f8e6b1f6cb461373dc77d8b1029cafecf2afdb13c1936f15744d055e4b", + "entry_digest": "800fb1804c6303bef36f066056b3cff1fc272c25d83cd619dd9319e463a0b683", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookRenderingTests/PreparedVoxelProjectionTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "0e828abc9fdfd275524439149a7767457afec885207c9483d64e876e9a4feaf8", + "entry_digest": "af9ffdfd90d0fdaaa3393c432448e3f955318e2754321f66e3c640362f93a9f0", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookRenderingTests/RenderingTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "1b8c55e9add54a5fac3a8ac21d8179603cb15927404f232df6d680032c4766c2", + "entry_digest": "a47c2aecc5415e209d1e3720b8c5dcaf6791c455392ab433f8ade9e5dc344446", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookRenderingTests/SculptureBlockPerformanceTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "80952a163fead38bdc3c122987ec343279450baba2045bafa0dee29c04880f80", + "entry_digest": "d2d47846653eda352f0657b6b77efe4e81399f8dca22ed76eab66820de26f08a", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookRenderingTests/SculptureLiveVoxelTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "301eee13272a74edc54634032d98573c3de42f08ccf201e0896ca8b9b2a81508", + "entry_digest": "26dac0d2c1249e4886f72342f35eb5511f4859400f5c984067e4a1189109db03", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookRenderingTests/SculptureLiveWorldTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "c9323f4b9e474df331ec909a8ba1090e06cf914270025b1e3bf2e01c8e3b0f83", + "entry_digest": "6eb27aa90a9062780d33fac6711f7ac16a4dbb6ace06a1f6d86bc378a5f4e457", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookRenderingTests/SculptureSolarPerformanceTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "3c1ce44b4fc58cfff129459392f6ebb110a2323a96578ef79036b8d4950c3645", + "entry_digest": "46fdaacde44d35048586a3ba1acd65919c8a7a4fb5e72555d3813025fe31b272", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookRenderingTests/SculptureVolumeStudyRenderingTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "2d0c4125cfac669af2c11ddcd8fdd0cf723a2421b69f50d5ed12619a9821a2c9", + "entry_digest": "ba80497b582a3908e9024b78127f6865ee750cbe1ee25561be1614f43173fa57", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookRenderingTests/SculptureVoxelMeshBuffersTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "a449d8911a0232f7a715f55fcb5ba82cff55c7be66ef02f6dced56bb7437dfc3", + "entry_digest": "885e360f6eaa18e98b43c748e609041f84f03ebcb3a64fa94923b13effaaf8af", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookRenderingTests/SculptureVoxelSurfaceTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "aac13532d28070b1e21e403221dcc2f62c42782061ddd9e909cefe86c254d321", + "entry_digest": "d1ec3dde38b4b6aa75ba70301955515676a5d715c4bffcc89bfc06624dde8b1f", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookRenderingTests/SculptureWorldCoarseMeshTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "b902837a81e045b0eec168bedb1ac31a53aec17482717ad74059d38ddb75c647", + "entry_digest": "64109be91cf7d5498bbfb5c01e9656784d1aad6459cc69d482df9b78b6b3a923", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookRenderingTests/SculptureWorldExplorationRenderingTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "041f2376b73e99842c64c067c47616ac9f01012b32d1a00109deb58eb520dfe6", + "entry_digest": "fe16e247d815121af27028365a94c54aec3f0211dc991d06129e70f0239dea41", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookRenderingTests/SculptureWorldNavigationTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "f0ce519cf2563b7d14df724921e84090ec746ca4fbc3e907242c467ef95a911f", + "entry_digest": "7ea1cb8275ea18f230130886f854953ff3adaf3dda094a01132083f76c33f4e0", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookRenderingTests/VoxelRenderingTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "4a5ac9a9df5b4185d26a49b5aa5833f0461f9cdde5f0361298300a61d482436f", + "entry_digest": "b36ce9ef6c19677100d1a413fa26ce6741327f0bd425ddb1051656f6e7990ffb", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/OBJExportTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "60732ad89b9f8d2550c20181cfbe94eeaf681c0601ab875fada89a0f77db0e71", + "entry_digest": "faec44c55bb5684ae1264f305072c6d0b02af31e19723249e3b335171e5e5069", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/SculptureBinaryCodecTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "70f74e67f0b717f3b95356432f7ff711d4a534e2bd50edeeea97a4d1210aac03", + "entry_digest": "c2b4b21c418ab6ebcd567ef6e7eb9a6325c8cc8d78c7c5856e4f67ffca9c86ce", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/SculptureBlockWorldExamplesTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "039d7c47a0cbe841055b268fe9289666d71087a1fe3562820239b3638454f936", + "entry_digest": "e44b57919db2694e078de25a2f0c0441dceb248897d095e1201e979404454e8c", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/SculptureCommandTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "02e10f73e64ac659180fc45f5725b8b1432e81b31dd4765490df53d67cfec586", + "entry_digest": "06201a7a1e9c66820e60093a62d12337396f83d13ce3130636f6fd76e22ac34c", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/SculptureComplexExamplesTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "c4a3434d8a1d19d8895ce9dd72afa8411618784834d745f3c6eb286c81c654b6", + "entry_digest": "e0648397808adfe1708087ca7982d1e46e1276bde43132860f3b0bc90bd7f425", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/SculptureCompositionExampleTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "ef520f1abb6f4a954d1aafe9b204048c950a188193186b7691cc7f5bcaa51044", + "entry_digest": "ea402f3bd20ed0fbc695eb258ecbac1c82fc14617c09ced252208e45b7d32611", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/SculptureCompositionTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "6e8688d42e9ce3e615266bbb70aa4a711b8ec0be9260d2f97a9a3a64cb2763fa", + "entry_digest": "36805828906c5d3f39c3c719e21cfff1fa0d45c6057dc9bbceefaae7de3a5312", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/SculptureExamplesTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "a4d8dcff1c2a6152c99c1ed525df5cff9b6b32d6a010f7eca6ea71fe1a47e149", + "entry_digest": "d26f325afaab4a53e5d7756e3cbbac67e68ec10c57da46da92d203af965a1c94", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/SculptureGalleryCatalogTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "5e1251834b5ed01919fca0cac7c94e6b6123e977852139e15310d297362ddd0a", + "entry_digest": "651bf5db79ef27172893e498e55f076f41f96e310f2cda6dc01ef7624e7db90b", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/SculptureInsertionPlanTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "46877cd8e7728cf48edfb215119272203beb8952197665f486b519d813221cd2", + "entry_digest": "30b6c21094328b585abe448848e2b27a54f46ba0b7920b2d094870430b4cff14", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/SculptureLinkedBundleTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "3bcedcc807cdff72bba12f67d1328ef51c56c808f815b30db2e454ae88d7e981", + "entry_digest": "b608a8af9a7a8673ce114f160955a1ac43b30d9c108427bc8fe093ab99738397", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/SculptureLinkedCodecTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "708db8b0466433baebdd602b998c1fd92f6bc19e2c01f06ae887bf5499025374", + "entry_digest": "14087dd5c9b94d167d3d7b627cbc91eb5cec0e62236304f9445797d3d0eadb98", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/SculptureLinkedResolverTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "1bf28714d53e7bdd2ac1618523db00ea52c25fb6ebdcbe671f195ed7e66ed8b3", + "entry_digest": "be31783934613156e9ba6f5ffd07d43a4b674e3f5103b22972d474d85ba28579", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/SculptureLinkedTestProject.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "7c58688450b2a2ec05e8a02760ac3900bda0529afd74801ee4947c83c271dd06", + "entry_digest": "35270a4af37492c0f17970b7e22d60c758369a0afec6e5da4c3bf4804fbba200", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/SculptureMathExamplesTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "f5484b9a660e60b56ee8f5b120a89772d8e0d00a47847282de20c2400903cbff", + "entry_digest": "1f3d00d56343e9032c909098ff307eb2af3b2daefbfb0fa0f2572652d89e2c1f", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/SculptureModelEditingTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "e7b42d35b25e6e300c2902865a5ac14243424b399b32b5f6758cba1cbea73d02", + "entry_digest": "1152d93baba36cc36bf9cf58cea1edb415b68eac388d9045b34779392311ec9b", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/SculptureSceneInsertionTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "8fd2a64110e1b16d3a0d4aa659654a8917d1c2e30d8979fdc6d8e7f4a01d536a", + "entry_digest": "cfbebbcc9c640c3fe802fe7f35c9d83f2fd28f5290ffdcc005c1af03192cc42b", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/SculptureSolarSystemTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "92196a47f8019ac8b401d26ce870a23625129715ab662255e9f012ddfe01100a", + "entry_digest": "f4750ff963ee8985923b6cbfbcc080cc86c8563f3d212ffa776b69d66a1ecc5e", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/SculptureTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "f2c0ad80603214526f465de7c3b163f61b06a6a9c6ef6cc95ccf389938ef420a", + "entry_digest": "90f35c1f483a6bf2c617076a7357e5423ef44faf8bd00fe7166b3da1e0f1bdb2", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/SculptureThreeMDTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "cbbd5b3524e3352d7af5ac9329bea74733625fd6bdf59a94c2f2d50a699fd7db", + "entry_digest": "56ea7a30fbec0e5388795f57f521d6dc488e39b4eab3d743886a7911d7c7d0b9", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/SculptureVolumeStudyExamplesTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "26c2c59c4356ed520057f2400140121015b6dc764536047db4a3e48fd7de213b", + "entry_digest": "5e640a40b56fcfc3e636f88b12e747ea717a8721581452f2788d12f65db50df2", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/SculptureWorldTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "ba5da7db4d78930c8c3de11067c9f3b3f15f579ae8683acf3c400b73e6ae78fc", + "entry_digest": "47ec1e0a3d8cee47068cae4f424d533cedb8d26c830138fe84d7132dfd2b94b3", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookToolTests/SculptureCommandToolTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "db678464dfb484dc5e18c35b3ba87d27e4a416894f7da0328e95f460efdeff7d", + "entry_digest": "70a2958f4e3aea91ca3372d237a29cc73f466ed6f03c809c7f4062643c51c6d7", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookToolTests/SculptureInsertToolTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "7858f7a64fc90e7209239a3a484ccd72e9c37559bc706e7d3c423aeb48cf05e3", + "entry_digest": "7380b1022f8246a0e0a5cdaa542e1009619081783feeb7c6160b02c0df63bd62", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookToolTests/SculptureLinkedInputTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "7f12f1bda9a5cef9400e254f6cb83c42e8c33de082ad9ef9e3e4dbd895bc6e78", + "entry_digest": "b07535e693f420d76018263ad8264478d9433f433f36ec00c73832e9fd14f097", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookToolTests/SculptureMathExampleExportTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "62eb5b7b9297c274e6d8cb34f26b13a35a06efea25c713bf9e7b35b889fc99af", + "entry_digest": "44e9cef15854aedfb6451c5fefdc876b7ecfb39993297cafd835a4fbb361d345", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookToolTests/SculpturePortableToolTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "93fe986fecb606b1efc64ccdfc1e5c6a6c9c42805cd8c85a3b81656265e6b37f", + "entry_digest": "9038516bee6cc12abf8effccaab28b84b1be76cb7d62d606796cc0bea7a96466", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookToolTests/SculptureReferenceModelToolTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "f9f9d80ed84ac2593de24f81d757d6520c06a805e0c8e59c82ef2629fa02b424", + "entry_digest": "dfbe8fe8b77a41a921880178e874657bbca35a5ae953fb251c18dc50a2fe32ac", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookToolTests/SculptureVolumeStudyTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "8a8396041daabd97bdd52c695b165d3bd365106b79d891f90982440f302c466b", + "entry_digest": "e912b7d78aaee2840f25472293b007f6c207e1c7c06d3ee6e8cf2237d5a69c30", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookToolTests/SculptureVolumeStudyWorldExportTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "421c70bb22e030ba15953f1f0c43a7511c80b8e35db9dab1e2c8d891881454a8", + "entry_digest": "937f9e8403bcf017ca424ac3848e39d61231e74cd3273ca33c1a07590b12dd7a", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookToolTests/SculptureWorldToolTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "833b235acca092fd2dca1f7bb5ed4f0493cb8cb53120fe59d97fe441520eabda", + "entry_digest": "e6af00f53db1883e3972a2cbbb81a807c583e169dd985c91ec792bf0dd8495db", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookToolingTests/NativeToolsTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "9058e47f3ed1b6bd6742067d0418aead0d180b10ce2acaef5d76d76a1de7f617", + "entry_digest": "9ab8dc927319357c20902e50fe1faa16fa6c0d74486069e6b7deef7a72a8e906", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookVerificationTests/RunnerTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "a13fa9e4c75fbb6024eb8a962248b05602d752c44e52eb38f6a3085e9a8a1d34", + "entry_digest": "0bf2794629b02e647ce705a09a0752b877d6c8ec18c27e899c1c5c1c2c58a500", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookVerificationTests/SwiftTestLogTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "d81d429bb0f794b33c8858dcc47c8735d452cff72281b1a04bd55c974f5ad904", + "entry_digest": "dc62c3d4c6032f34439560e68ce01085f2e198319832859089b2f2b55999f8dd", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/hi", + "kind": "non_file", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "5b1180aa1683357d4fbdc6f70c7a6f099ba574be8eeacb6122c34f3fbd6e5a3d", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/hi/AGENTS.md", + "kind": "file", + "mode": 33188, + "payload_digest": "a7c2b4f3e362bf812e2d342e821615c65cf67ba782d03a07a6627bc04b5c9252", + "entry_digest": "1722750a8a857e473be446b70ff76dac1d842fdf4ff493b14d06a4a22a9bb40a", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/hi/CLAUDE.md", + "kind": "symlink", + "mode": 40960, + "payload_digest": "a54ff182c7e8acf56acfd6e4b9c3ff41e2c41a31c9b211b2deb9df75d9a478f9", + "entry_digest": "2e936d4157c977b650afd28e14fc3706e93690ec69f2a1cd258a8a0033db5ac0", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/hi/composition.md", + "kind": "file", + "mode": 33188, + "payload_digest": "4192061cfc0862a5287229adac316bdfdca78c326a1ecc0a9884843e683afd43", + "entry_digest": "ccce7bef24717df3e210139e37c06279fa50bdf023409d9f696be23f60c03d0b", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/hi/cubes.md", + "kind": "file", + "mode": 33188, + "payload_digest": "87717022e44982d6ca2c7b737c614a5e836a63f87fda234949e6b2ff21849e0c", + "entry_digest": "923d5bb8afcf10e3fed111038afa5196f69068226804bf328152429336aa17b8", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/hi/export.md", + "kind": "file", + "mode": 33188, + "payload_digest": "88a062b3c77f0612fd9a8b4c531b31d7df0fa3023aa9eb78739668bf0fc9a63d", + "entry_digest": "fafdb5908519d66ff163f83e8e83ba4e53ee12c2a44219ab2a0ad96222a2168a", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/hi/gallery.md", + "kind": "file", + "mode": 33188, + "payload_digest": "3091b9b84faf7b8d76e0c98ab633d043d2614dce43b02bacfc47a2d87ee7d3a3", + "entry_digest": "dcc0b0a9ca005f63b81ada36d8a594c9b6baffde5ed4ec08fc083de3abe50e58", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/hi/local.md", + "kind": "file", + "mode": 33188, + "payload_digest": "5289ba2802b24f18a6afe990ddb4276faf2297c6cae75a964c9905c189f99033", + "entry_digest": "36bf50f6d883038c37dbec78d697784287e22046eff83e585ba5dc6c5b5f816c", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/hi/render.md", + "kind": "file", + "mode": 33188, + "payload_digest": "b0923791421fc00c64725b77e0dce6dd223cf950e1fe40bbab7fe71160b63338", + "entry_digest": "9a3d081a42bc70cd32d2ad397e38bc6e4bd350df2b3124d076eb36228294e7d0", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/hi/sculpture.md", + "kind": "file", + "mode": 33188, + "payload_digest": "7116a830b65f7af632d2b2d2aa77e567631c2a33a7fcb5d3b9cd3a3d57082271", + "entry_digest": "caea0e7869eae9c61e45f6cdca43df6afbc1b81cc333ca602744fc342db91f2d", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/hi/shell.md", + "kind": "file", + "mode": 33188, + "payload_digest": "d8fb4017d5a6dad0adc64617d8d7289001dc0cdac3e33e1ceb9f1f644fda49f5", + "entry_digest": "fbbea37430b6614be789611f97c9f2e5337cdc8df825e4945cd078e988359987", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/hi/slice.md", + "kind": "file", + "mode": 33188, + "payload_digest": "295ed1d6feff3b478fb6a7f751feb35cee475ab60d94e214bc04d3f639c2e546", + "entry_digest": "357fdb9cb2e2b1e44d3cd2372ba1cad4cc6b1ede97d0003be1221473c5e98bfb", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/hi/world.md", + "kind": "file", + "mode": 33188, + "payload_digest": "663559da5bb02db3413f545de91e81ffd7ab5c3890158aeaec964d819c1ded5a", + "entry_digest": "6b2354660f0978b98ab1c58356d2fc585763ac09e078b5f988e14f6493255e74", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/specs", + "kind": "non_file", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "f4fb94115c0cd72e416a30a3a454bbbda63ac0989744dd1fa148551cef9875ef", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/specs/RookApp/RookApp.spec.md", + "kind": "file", + "mode": 33188, + "payload_digest": "328f0e0ec49767f115960ba7a09b1395626ef6dd78cdb76f79ffc61d3b381859", + "entry_digest": "9b423979478d8e5435ad55cefb13fd9f1cb745b718a28367a176d282ab385f26", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/specs/RookApp/requirements.md", + "kind": "file", + "mode": 33188, + "payload_digest": "a998087ec9c46dec9d5e3f6e3f4c2680966f67d766be19fe3a7a1c9ae9fec9d3", + "entry_digest": "29b6f5ed8b2d484afc100b05e971236b61d7e4ee48637788c1799a205da5236e", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/specs/RookCore/RookCore.spec.md", + "kind": "file", + "mode": 33188, + "payload_digest": "edd8f788a56817afc8eb2d477a0a75f3bc37135d205b1f6e9665d03ff0b74344", + "entry_digest": "729f1a3b27ad303e7b38f7aa49372a4ef57113a9014060cbff46c2cc2fd6a810", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/specs/RookCore/requirements.md", + "kind": "file", + "mode": 33188, + "payload_digest": "80305947b009aeab89c4fae62bc8ef48cb0c6c95cfbd351cea9e2fc0f47a0b21", + "entry_digest": "c5d7038b613041d8fabe4e2dc47fc2fc08efe5774e9551e50648763eca8d2cf8", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/specs/RookDevelopment/RookDevelopment.spec.md", + "kind": "file", + "mode": 33188, + "payload_digest": "b2c021c8fa8d74dc2197bd5ef8754e4f3eadb091c743831ad643b7867588c9d0", + "entry_digest": "319c60159eecb9efbd78bb2a137c83b5e0d6357cdb6e72aa96ff86e80a7d3adb", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/specs/RookDevelopment/requirements.md", + "kind": "file", + "mode": 33188, + "payload_digest": "0efd07ebb2fa2d12769429f782dd1d2d70362adbeca2a82234251c6aa55abe90", + "entry_digest": "a11e80095e0bb66c0baba88236129a1ebef28c54ea2f454e2362c70467a6f960", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/specs/RookRendering/RookRendering.spec.md", + "kind": "file", + "mode": 33188, + "payload_digest": "3eaeae84bde150f19ca189a04310b28dda74cfb90d55430c8835f07b1ee1008d", + "entry_digest": "65bb892edfa4ca765ffc6556cc977b0af8cd62ccfed702f5c71266ac30debb37", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/specs/RookRendering/requirements.md", + "kind": "file", + "mode": 33188, + "payload_digest": "9360c435f8fb30b54a7fa3e411a6d8f5347e089ea9038a80734fc821b49dcdcf", + "entry_digest": "17c88752e827fc1622f4a732707fcb86865a43baf1ef6630541f2b0c584f6521", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/specs/RookSculpture/RookSculpture.spec.md", + "kind": "file", + "mode": 33188, + "payload_digest": "a89be62701494e3b6c7ffbde27888091fe3c0d7d81fb91813fe697686d0381ae", + "entry_digest": "33ea611aec1446b7377f396832436a2f23db9075d8466462a978d6b04554d412", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/specs/RookSculpture/requirements.md", + "kind": "file", + "mode": 33188, + "payload_digest": "fddb51105fb11306fc54c53f1c74771fde301812c8a3da5a253108ec89b5000d", + "entry_digest": "3d9dd7140bc5cfe762961be8d7cd0c7fa5369d44dd46ea208384221979a0fa5f", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "hi/tools.md", + "kind": "file", + "mode": 33188, + "payload_digest": "cd530f076ed449b2dcd994f9178fcb104f4460e44a12042200b42bf6ca6d6306", + "entry_digest": "a13f216eb32a3671d7563024082ab76eb471bdd7a2ddb3c3398b672b05354a70", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "specs/ThreeMDViewer", + "kind": "non_file", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "b53a01354acef7fb830687d9789c70f85c60f43e94da4a2dd0816c771a3bf773", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/ThreeMDViewer.spec.md", + "kind": "file", + "mode": 33188, + "payload_digest": "3b3b09952c692c501a98d6520fb8a82f5126ab9b05d64f6634b50cbae3620ae6", + "entry_digest": "64224b139df2b01fdd0db61c4817d9a836030dbf2667bda60529f6a61be627b4", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/context.md", + "kind": "file", + "mode": 33188, + "payload_digest": "a0011f2d32b7dce6370e015fefcf09acbcf52578e82a97e56def17e0e0fbed52", + "entry_digest": "e020a4426da69e6b24dd3025c95afd9a88cf073bca235f86ad9104e1de81c7f7", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/requirements.md", + "kind": "file", + "mode": 33188, + "payload_digest": "96612855952a65a5e6b623e2b5d21e9dd8f4ea88c92c0e8ef392e3b826b81f94", + "entry_digest": "5caf30173677b31dcf1119406f03f7dd5a1721487ef58ceacb8d22ed07244d4d", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/tasks.md", + "kind": "file", + "mode": 33188, + "payload_digest": "4b0a856509eb4b4c0c875e4b74844c45ce162acf255ce69bf88f86d82feae603", + "entry_digest": "3767a753d3d8c88a88e61820f68b82317f5cd533b57cec5ddc798c7d33ef2656", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/testing.md", + "kind": "file", + "mode": 33188, + "payload_digest": "e224b1bc77ea1679aa4cbd34f182846717be905bec43bff555d19f0ba5f75b15", + "entry_digest": "fee23d7cfc7097bb6cda3f52a2a0efd8ae2030ec4c32059529bccb53252bc7e1", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "uitests/viewer.spec.mjs", + "kind": "file", + "mode": 33188, + "payload_digest": "52dd2553472620fd956815792cb22c70980c8d70ea4563eac487ec5eb4f28093", + "entry_digest": "05c24eeea687cd37e72eaa5382b93877334fb1cb53ab1b80babe625a09d0393b", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "web/viewer.html", + "kind": "file", + "mode": 33188, + "payload_digest": "457af08a02075688bdec1285f820bd6e6ff48e54c392a6239d3a0519a21197b2", + "entry_digest": "91188b507e047ae68fe1e96a1980f5b33206532a2cabafec98e7d7883e0b70e4", + "owners": [ + "ThreeMDViewer" + ] + } + ] + }, + "passed": true, + "commands": [ + { + "command": "specsync check --spec ThreeMDViewer --strict", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [ + "REQ-ThreeMDViewer-007" + ] + } + ] +} diff --git a/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/verification.json b/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/verification.json new file mode 100644 index 00000000..8456a070 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/verification.json @@ -0,0 +1,1214 @@ +{ + "timestamp": 1791655884, + "commit": "60055f7806a4d46964b766672784be45713e3c3a", + "contract_digest": "4b6d4eb372c26f296d08a35c4242b772ba7f537d690b3ac81723034860824618", + "execution_digest": "da242228adc07b4a8a41fc7d90d24f0e9d3d8dd459769a1a72c8cd55aa49ff8f", + "workspace_digest": "fde013fc78a6110e0c0b88de16f5f6e7522e6561a06c0a5c5fd273d884ed5278", + "acceptance_input_digest": "75c60a31bc1b305db3d7f15f76d65654d7a80eea3669ed8ed768701654a163a0", + "acceptance_manifest": { + "schema_version": 1, + "entries": [ + { + "path": "apps/sculpt/Sources/RookApp/SculptureViewport.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "8d5ab6c914e03d60dadc58a3e8b6d4f595a261b1e032c46cc0cdbd0597757e45", + "entry_digest": "24442eef4a7215ed811720b44e4f3014ac30df390846447f342ebe7b9d94ff1d", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Sources/RookRendering/SculptureLiveVoxelView.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "610272100afb40b290302e64c8cf72544b67f3c2cee3543b292f796531c9750e", + "entry_digest": "210439bcd02c86c1940dbec87538b50db5a465257538913389cb8d82d767fe6c", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Sources/RookRendering/SculptureVoxelGeometry.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "24c096ecd359193366e02097643561e28fb3ff422e1fafda1661dbf0f706eb86", + "entry_digest": "b2ff90dc0d60eeb4fdc2983e7c2a13382859ab24164d5d355787aaf98bbe6807", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Sources/RookSculpture/SculptureProjection.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "d98745e56609642d7c65369aa67f251d82c3c6089199cd6a2bcc9b1fc928c8d4", + "entry_digest": "22f5d1bb30035cd28eea2c7ed2df463a4ecd679601edeacc7f3e591b9485e267", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests", + "kind": "non_file", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "094f12e742e15c4721c78566d011dd8f2dacfdf163828f9b9e12e6dbbfab2764", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/AppearanceTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "bb460ca170501c02f7e413b1c85c41f0decef55aba4ea735f32c226c36e894e5", + "entry_digest": "ff7f1cf01c86f9e9c1964067854027d5bd8ef674a0894206b189c97a0520df23", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/LayerGridGeometryTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "6645f57ab9861bcab490fd53808b6a178c57ae6833e51f4575c31c95f641ef46", + "entry_digest": "abc7fbc1e12be39495e89853bcdaab5cec35152d1d0e48d8c1828c3755e6ded1", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/LayerGridScrollPresentationTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "1533740a7d0e2347a50bc5ac3ac8ba08037dbc8ac7e3b3c50c022b53f49a765c", + "entry_digest": "a5134e75f1746ab129d9f84012691cc39727df27949a5bce4c6e65ba6d75fa16", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureCanvasPointerTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "2eeb532f40db634a0674a94857aed000224be0526de24fc72a000a2570991883", + "entry_digest": "7e2b1210b7a3eb39e7ebcd1a03d4307a65b2fff0f6181e1ba4be83eb0bc2d5cb", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureCommandFocusTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "25fb256f29a8991b87e65f09b8caad37711390bf5c7f31da242bbffc13001576", + "entry_digest": "29bbd13e54d55add0704a17c81ad8da3609d7edac595fd6d499105e2e038d9ed", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureCompositionEditorTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "19bb8062f643d384cdee5e768ed856c9d6b7331980d5987164adbb2973027e3f", + "entry_digest": "d733318c97c4ee44e5ae4376cecff5a69567703d854230b84167bbad055aaad2", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureEditorPresentationTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "ded50853676c0ad3bd625c55d4aaca9769c8e803a04f38ada6c59ae2f49fb095", + "entry_digest": "c75be12388c9fd7c9406e1c524e6d6a339092527fd75575a70927918d22f385d", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureExportJobTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "0101679374acf6525820313028313573b49605c068286d1923b7c3d6986ed675", + "entry_digest": "54c858f1e9b793276d3fa7f1b6f2d4249830ab1229f46f3fed4f48e406706616", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureGalleryBrowserTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "59dcb942153a452120eeabe743a971fa707032ed422b24db19876238f3747b6b", + "entry_digest": "2280e89bb09b6dc17012fea72e1a3bda59c7e1d0504039430317ece2ee21a115", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureGraphSaveJobTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "b3c9b2b8bbf482a27161aef9d1ad0bd161353678319ecfc7e833655b6673276c", + "entry_digest": "62c72b46d143f2d230e7e291b4c5c4f5517666e1459fe3181f507c65624db824", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureInsertionDiscoveryTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "18c78362b45c16063ca9cf888e6376ec1bc56872a2e95261257f7fbe7b363f9b", + "entry_digest": "9057cc0eecaffe749a2c592b04ee299624a3a791c8f6e89e9952ca49b3a5187f", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureInsertionDraftTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "5efc2d96cdbd08514532647eaa7ca762152f211e99665955f0d081f1478a0d72", + "entry_digest": "c93a1807c59024d7836c48968f603168ae5abf5c18754ce75638beb38999d446", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureInsertionRepairTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "6b0fa86e435c43766b7ede2207afc87f460236138c8deaf5b267ac016214a2b1", + "entry_digest": "854eb3a494a8844e8db408b7ea4f42304e8863fea8122776957f6d90da0585c4", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureLinkedConfinementTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "5b1ec9e5b39bdd52833a9003a62cf63f5c1e88896fce4962120345af7f868849", + "entry_digest": "26d045fd6441c6c932b8497303ba52a107129baedddf46c32d26db5eb2cc8800", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureLinkedInsertionTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "e8947fbf69251f81c231f8c2936cfdf8558d8240399ab16369c7bee07b78b2de", + "entry_digest": "80649740dee2b7daf7858ad82f009827d83084e20672f2e08768b08df523e563", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureLinkedPresentationTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "d703a36c7eaac77ef95251a924e5f2275a9d1fc2874d053816590d700bb79bb4", + "entry_digest": "bc53d1a4d3030610a40da15cef40c1e4fb4ec8492dc278ac44c285e940ef9797", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureLinkedSessionTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "afb46a2e240b948ea168b80d3b918090908db29b0e42d14fa17e689862dfb9b0", + "entry_digest": "9de38710e6bcac83215b68343eaa1fdec0e42ca5310fd9899ce9d3edee188e16", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureLinkedTestProject.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "c8e07629a75cb25558958ac0ab6de0a383f3962f4f9ef9d53623de8a790251c5", + "entry_digest": "39ca31385c1dc4f6ce086f4edefa4a2fdaf229d7212db2819ec4c0dd886a5db5", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureMeshRevisionTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "49950faf4516bdbb9f46d1d6382b12e50f2e1e50cb19b24786b9f24b17ef237d", + "entry_digest": "7ba09620fe295e049072120b8295ff92f7b1637701d435a4a3318a8a9ee6aaee", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculpturePortableInterchangeTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "e33d0ecc55db21dea1e7a22c4c53d08d964bf65cfac4482113228328ba5202e2", + "entry_digest": "bfb5e8f52204376972583ec77fed86a25f79cc65a3d865b68c372b8c6036463c", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureReferenceEditorPresentationTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "6f8f32bafce36b5b50625c5959a3f52b64b1ff87d10200423e4a813e3c15facf", + "entry_digest": "c63963edb0b237f7d076eb1da498122467f07c129f8a294dbb953cec825681d1", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureReferenceSaveSessionTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "4f19a8645355e5537b3de91c5d7ce9334cdc20da7cbc334da464b69098c492e5", + "entry_digest": "5fc3bec2792e589ede91c109f0c279256616ca736c99afdcd3d333d20fd53bf7", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureSaveJobTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "49808899eefe4ed5e8e0a1ce701749f6d4ef82ff540bff5473c1b5dd634a37c7", + "entry_digest": "3f5101a4313935905c0ce901ce18506f3ebadfa5412b4c770a7c2207dc68c4ab", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureSharedModelDraftTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "03fc1f9626cd365c84421b581d27b42f842908a09d4cc014939f5dda34cc352f", + "entry_digest": "c4a4e09309acd95d18e227ae25e495f2e44c4ed5f40801e34b347d893297be3f", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureSharedModelPresentationTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "0e4a7bc7a44619ecd9a001c21e2a29adfdf3b9da9d5a1bfdc7ac0c06a889f336", + "entry_digest": "9b37c492d9734c1aecfde57c7f41568d518020cad3e65e42d3e7d2aa6c9266aa", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureVoxelWorkspaceTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "085c78d6a0f10a7a63859feb3783dea5a21ff651bd8641618f29bdd0c9c020ab", + "entry_digest": "cb4638941514ef448fce96171889541f28e5cb2fb1d455b0ea8e8b22ac633a30", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureWorkspaceTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "f420db050af7dea627b63e3b33e113377e3919b69d24b7d4e5a97a6bcd06c681", + "entry_digest": "997ec23ca0eacd6cd532071f3da63de1da66eb5a0f11ba6902520e84b68c637b", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureWorldEditorTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "51707a0e3b30bdb26826e1f0119b1725d39d735df5e7a3de255fe56e294b7922", + "entry_digest": "5b5b3030f6d5fd568e07c8153d7c155e2ec1a224a582b35f54013f6f567f64e4", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookAppTests/SliceGridRenderingTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "f0d9c2da996754a881e260ac2a7b5b5b81406f5cf97ec857bf92e62edaea9cf0", + "entry_digest": "82df33fc6af7c834ad6b35e2edd38724ca63c5201ee0bc7200ddec753e63757c", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookCoreTests/AppAppearanceTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "96b116fa629f3753d8b42934a811c1428f31636e2856db12bd9f583a9126c368", + "entry_digest": "556583436e1058dc662eef44661aae7333461f13160a1f06a9e1ca9f5fbc006e", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookRenderingTests/AnimationExportTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "703d05088f785075738fd195c924270259f2a471566e1b5872881117239fc942", + "entry_digest": "29b0fb1b5fc6a8d6e710a872bf02d19848f68b1d0fdca7a7e06a4e4f2f5042d8", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookRenderingTests/CameraParityTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "97c1b35abd129f1f8fc3a2e3fec0ede9b4416b5a0bdd0c53eb55877dca353c6d", + "entry_digest": "7d2c516df02831b4c7701e5d5d3fd31791d99cb6d7b456bd177db175f8fd9c2b", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookRenderingTests/CubeExportTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "6bff8220f252746e5591956209d228de11b97b8b46e98d0ea09ae13f93c3e324", + "entry_digest": "d76039bb23eb138a74b6e89671c99768c725e12b1760b8582aa64942ddb9665a", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookRenderingTests/ExampleArtifactTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "affec5f8e6b1f6cb461373dc77d8b1029cafecf2afdb13c1936f15744d055e4b", + "entry_digest": "800fb1804c6303bef36f066056b3cff1fc272c25d83cd619dd9319e463a0b683", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookRenderingTests/PreparedVoxelProjectionTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "0e828abc9fdfd275524439149a7767457afec885207c9483d64e876e9a4feaf8", + "entry_digest": "af9ffdfd90d0fdaaa3393c432448e3f955318e2754321f66e3c640362f93a9f0", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookRenderingTests/RenderingTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "1b8c55e9add54a5fac3a8ac21d8179603cb15927404f232df6d680032c4766c2", + "entry_digest": "a47c2aecc5415e209d1e3720b8c5dcaf6791c455392ab433f8ade9e5dc344446", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookRenderingTests/SculptureBlockPerformanceTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "80952a163fead38bdc3c122987ec343279450baba2045bafa0dee29c04880f80", + "entry_digest": "d2d47846653eda352f0657b6b77efe4e81399f8dca22ed76eab66820de26f08a", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookRenderingTests/SculptureLiveVoxelTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "301eee13272a74edc54634032d98573c3de42f08ccf201e0896ca8b9b2a81508", + "entry_digest": "26dac0d2c1249e4886f72342f35eb5511f4859400f5c984067e4a1189109db03", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookRenderingTests/SculptureLiveWorldTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "c9323f4b9e474df331ec909a8ba1090e06cf914270025b1e3bf2e01c8e3b0f83", + "entry_digest": "6eb27aa90a9062780d33fac6711f7ac16a4dbb6ace06a1f6d86bc378a5f4e457", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookRenderingTests/SculptureSolarPerformanceTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "3c1ce44b4fc58cfff129459392f6ebb110a2323a96578ef79036b8d4950c3645", + "entry_digest": "46fdaacde44d35048586a3ba1acd65919c8a7a4fb5e72555d3813025fe31b272", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookRenderingTests/SculptureVolumeStudyRenderingTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "2d0c4125cfac669af2c11ddcd8fdd0cf723a2421b69f50d5ed12619a9821a2c9", + "entry_digest": "ba80497b582a3908e9024b78127f6865ee750cbe1ee25561be1614f43173fa57", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookRenderingTests/SculptureVoxelMeshBuffersTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "a449d8911a0232f7a715f55fcb5ba82cff55c7be66ef02f6dced56bb7437dfc3", + "entry_digest": "885e360f6eaa18e98b43c748e609041f84f03ebcb3a64fa94923b13effaaf8af", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookRenderingTests/SculptureVoxelSurfaceTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "aac13532d28070b1e21e403221dcc2f62c42782061ddd9e909cefe86c254d321", + "entry_digest": "d1ec3dde38b4b6aa75ba70301955515676a5d715c4bffcc89bfc06624dde8b1f", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookRenderingTests/SculptureWorldCoarseMeshTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "b902837a81e045b0eec168bedb1ac31a53aec17482717ad74059d38ddb75c647", + "entry_digest": "64109be91cf7d5498bbfb5c01e9656784d1aad6459cc69d482df9b78b6b3a923", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookRenderingTests/SculptureWorldExplorationRenderingTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "041f2376b73e99842c64c067c47616ac9f01012b32d1a00109deb58eb520dfe6", + "entry_digest": "fe16e247d815121af27028365a94c54aec3f0211dc991d06129e70f0239dea41", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookRenderingTests/SculptureWorldNavigationTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "f0ce519cf2563b7d14df724921e84090ec746ca4fbc3e907242c467ef95a911f", + "entry_digest": "7ea1cb8275ea18f230130886f854953ff3adaf3dda094a01132083f76c33f4e0", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookRenderingTests/VoxelRenderingTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "4a5ac9a9df5b4185d26a49b5aa5833f0461f9cdde5f0361298300a61d482436f", + "entry_digest": "b36ce9ef6c19677100d1a413fa26ce6741327f0bd425ddb1051656f6e7990ffb", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/OBJExportTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "60732ad89b9f8d2550c20181cfbe94eeaf681c0601ab875fada89a0f77db0e71", + "entry_digest": "faec44c55bb5684ae1264f305072c6d0b02af31e19723249e3b335171e5e5069", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/SculptureBinaryCodecTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "70f74e67f0b717f3b95356432f7ff711d4a534e2bd50edeeea97a4d1210aac03", + "entry_digest": "c2b4b21c418ab6ebcd567ef6e7eb9a6325c8cc8d78c7c5856e4f67ffca9c86ce", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/SculptureBlockWorldExamplesTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "039d7c47a0cbe841055b268fe9289666d71087a1fe3562820239b3638454f936", + "entry_digest": "e44b57919db2694e078de25a2f0c0441dceb248897d095e1201e979404454e8c", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/SculptureCommandTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "02e10f73e64ac659180fc45f5725b8b1432e81b31dd4765490df53d67cfec586", + "entry_digest": "06201a7a1e9c66820e60093a62d12337396f83d13ce3130636f6fd76e22ac34c", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/SculptureComplexExamplesTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "c4a3434d8a1d19d8895ce9dd72afa8411618784834d745f3c6eb286c81c654b6", + "entry_digest": "e0648397808adfe1708087ca7982d1e46e1276bde43132860f3b0bc90bd7f425", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/SculptureCompositionExampleTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "ef520f1abb6f4a954d1aafe9b204048c950a188193186b7691cc7f5bcaa51044", + "entry_digest": "ea402f3bd20ed0fbc695eb258ecbac1c82fc14617c09ced252208e45b7d32611", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/SculptureCompositionTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "6e8688d42e9ce3e615266bbb70aa4a711b8ec0be9260d2f97a9a3a64cb2763fa", + "entry_digest": "36805828906c5d3f39c3c719e21cfff1fa0d45c6057dc9bbceefaae7de3a5312", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/SculptureExamplesTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "a4d8dcff1c2a6152c99c1ed525df5cff9b6b32d6a010f7eca6ea71fe1a47e149", + "entry_digest": "d26f325afaab4a53e5d7756e3cbbac67e68ec10c57da46da92d203af965a1c94", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/SculptureGalleryCatalogTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "5e1251834b5ed01919fca0cac7c94e6b6123e977852139e15310d297362ddd0a", + "entry_digest": "651bf5db79ef27172893e498e55f076f41f96e310f2cda6dc01ef7624e7db90b", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/SculptureInsertionPlanTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "46877cd8e7728cf48edfb215119272203beb8952197665f486b519d813221cd2", + "entry_digest": "30b6c21094328b585abe448848e2b27a54f46ba0b7920b2d094870430b4cff14", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/SculptureLinkedBundleTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "3bcedcc807cdff72bba12f67d1328ef51c56c808f815b30db2e454ae88d7e981", + "entry_digest": "b608a8af9a7a8673ce114f160955a1ac43b30d9c108427bc8fe093ab99738397", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/SculptureLinkedCodecTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "708db8b0466433baebdd602b998c1fd92f6bc19e2c01f06ae887bf5499025374", + "entry_digest": "14087dd5c9b94d167d3d7b627cbc91eb5cec0e62236304f9445797d3d0eadb98", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/SculptureLinkedResolverTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "1bf28714d53e7bdd2ac1618523db00ea52c25fb6ebdcbe671f195ed7e66ed8b3", + "entry_digest": "be31783934613156e9ba6f5ffd07d43a4b674e3f5103b22972d474d85ba28579", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/SculptureLinkedTestProject.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "7c58688450b2a2ec05e8a02760ac3900bda0529afd74801ee4947c83c271dd06", + "entry_digest": "35270a4af37492c0f17970b7e22d60c758369a0afec6e5da4c3bf4804fbba200", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/SculptureMathExamplesTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "f5484b9a660e60b56ee8f5b120a89772d8e0d00a47847282de20c2400903cbff", + "entry_digest": "1f3d00d56343e9032c909098ff307eb2af3b2daefbfb0fa0f2572652d89e2c1f", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/SculptureModelEditingTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "e7b42d35b25e6e300c2902865a5ac14243424b399b32b5f6758cba1cbea73d02", + "entry_digest": "1152d93baba36cc36bf9cf58cea1edb415b68eac388d9045b34779392311ec9b", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/SculptureSceneInsertionTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "8fd2a64110e1b16d3a0d4aa659654a8917d1c2e30d8979fdc6d8e7f4a01d536a", + "entry_digest": "cfbebbcc9c640c3fe802fe7f35c9d83f2fd28f5290ffdcc005c1af03192cc42b", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/SculptureSolarSystemTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "92196a47f8019ac8b401d26ce870a23625129715ab662255e9f012ddfe01100a", + "entry_digest": "f4750ff963ee8985923b6cbfbcc080cc86c8563f3d212ffa776b69d66a1ecc5e", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/SculptureTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "f2c0ad80603214526f465de7c3b163f61b06a6a9c6ef6cc95ccf389938ef420a", + "entry_digest": "90f35c1f483a6bf2c617076a7357e5423ef44faf8bd00fe7166b3da1e0f1bdb2", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/SculptureThreeMDTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "cbbd5b3524e3352d7af5ac9329bea74733625fd6bdf59a94c2f2d50a699fd7db", + "entry_digest": "56ea7a30fbec0e5388795f57f521d6dc488e39b4eab3d743886a7911d7c7d0b9", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/SculptureVolumeStudyExamplesTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "26c2c59c4356ed520057f2400140121015b6dc764536047db4a3e48fd7de213b", + "entry_digest": "5e640a40b56fcfc3e636f88b12e747ea717a8721581452f2788d12f65db50df2", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookSculptureTests/SculptureWorldTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "ba5da7db4d78930c8c3de11067c9f3b3f15f579ae8683acf3c400b73e6ae78fc", + "entry_digest": "47ec1e0a3d8cee47068cae4f424d533cedb8d26c830138fe84d7132dfd2b94b3", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookToolTests/SculptureCommandToolTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "db678464dfb484dc5e18c35b3ba87d27e4a416894f7da0328e95f460efdeff7d", + "entry_digest": "70a2958f4e3aea91ca3372d237a29cc73f466ed6f03c809c7f4062643c51c6d7", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookToolTests/SculptureInsertToolTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "7858f7a64fc90e7209239a3a484ccd72e9c37559bc706e7d3c423aeb48cf05e3", + "entry_digest": "7380b1022f8246a0e0a5cdaa542e1009619081783feeb7c6160b02c0df63bd62", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookToolTests/SculptureLinkedInputTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "7f12f1bda9a5cef9400e254f6cb83c42e8c33de082ad9ef9e3e4dbd895bc6e78", + "entry_digest": "b07535e693f420d76018263ad8264478d9433f433f36ec00c73832e9fd14f097", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookToolTests/SculptureMathExampleExportTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "62eb5b7b9297c274e6d8cb34f26b13a35a06efea25c713bf9e7b35b889fc99af", + "entry_digest": "44e9cef15854aedfb6451c5fefdc876b7ecfb39993297cafd835a4fbb361d345", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookToolTests/SculpturePortableToolTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "93fe986fecb606b1efc64ccdfc1e5c6a6c9c42805cd8c85a3b81656265e6b37f", + "entry_digest": "9038516bee6cc12abf8effccaab28b84b1be76cb7d62d606796cc0bea7a96466", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookToolTests/SculptureReferenceModelToolTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "f9f9d80ed84ac2593de24f81d757d6520c06a805e0c8e59c82ef2629fa02b424", + "entry_digest": "dfbe8fe8b77a41a921880178e874657bbca35a5ae953fb251c18dc50a2fe32ac", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookToolTests/SculptureVolumeStudyTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "8a8396041daabd97bdd52c695b165d3bd365106b79d891f90982440f302c466b", + "entry_digest": "e912b7d78aaee2840f25472293b007f6c207e1c7c06d3ee6e8cf2237d5a69c30", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookToolTests/SculptureVolumeStudyWorldExportTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "421c70bb22e030ba15953f1f0c43a7511c80b8e35db9dab1e2c8d891881454a8", + "entry_digest": "937f9e8403bcf017ca424ac3848e39d61231e74cd3273ca33c1a07590b12dd7a", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookToolTests/SculptureWorldToolTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "833b235acca092fd2dca1f7bb5ed4f0493cb8cb53120fe59d97fe441520eabda", + "entry_digest": "e6af00f53db1883e3972a2cbbb81a807c583e169dd985c91ec792bf0dd8495db", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookToolingTests/NativeToolsTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "9058e47f3ed1b6bd6742067d0418aead0d180b10ce2acaef5d76d76a1de7f617", + "entry_digest": "9ab8dc927319357c20902e50fe1faa16fa6c0d74486069e6b7deef7a72a8e906", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookVerificationTests/RunnerTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "a13fa9e4c75fbb6024eb8a962248b05602d752c44e52eb38f6a3085e9a8a1d34", + "entry_digest": "0bf2794629b02e647ce705a09a0752b877d6c8ec18c27e899c1c5c1c2c58a500", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/Tests/RookVerificationTests/SwiftTestLogTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "d81d429bb0f794b33c8858dcc47c8735d452cff72281b1a04bd55c974f5ad904", + "entry_digest": "dc62c3d4c6032f34439560e68ce01085f2e198319832859089b2f2b55999f8dd", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/hi", + "kind": "non_file", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "5b1180aa1683357d4fbdc6f70c7a6f099ba574be8eeacb6122c34f3fbd6e5a3d", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/hi/AGENTS.md", + "kind": "file", + "mode": 33188, + "payload_digest": "a7c2b4f3e362bf812e2d342e821615c65cf67ba782d03a07a6627bc04b5c9252", + "entry_digest": "1722750a8a857e473be446b70ff76dac1d842fdf4ff493b14d06a4a22a9bb40a", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/hi/CLAUDE.md", + "kind": "symlink", + "mode": 40960, + "payload_digest": "a54ff182c7e8acf56acfd6e4b9c3ff41e2c41a31c9b211b2deb9df75d9a478f9", + "entry_digest": "2e936d4157c977b650afd28e14fc3706e93690ec69f2a1cd258a8a0033db5ac0", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/hi/composition.md", + "kind": "file", + "mode": 33188, + "payload_digest": "4192061cfc0862a5287229adac316bdfdca78c326a1ecc0a9884843e683afd43", + "entry_digest": "ccce7bef24717df3e210139e37c06279fa50bdf023409d9f696be23f60c03d0b", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/hi/cubes.md", + "kind": "file", + "mode": 33188, + "payload_digest": "87717022e44982d6ca2c7b737c614a5e836a63f87fda234949e6b2ff21849e0c", + "entry_digest": "923d5bb8afcf10e3fed111038afa5196f69068226804bf328152429336aa17b8", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/hi/export.md", + "kind": "file", + "mode": 33188, + "payload_digest": "88a062b3c77f0612fd9a8b4c531b31d7df0fa3023aa9eb78739668bf0fc9a63d", + "entry_digest": "fafdb5908519d66ff163f83e8e83ba4e53ee12c2a44219ab2a0ad96222a2168a", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/hi/gallery.md", + "kind": "file", + "mode": 33188, + "payload_digest": "3091b9b84faf7b8d76e0c98ab633d043d2614dce43b02bacfc47a2d87ee7d3a3", + "entry_digest": "dcc0b0a9ca005f63b81ada36d8a594c9b6baffde5ed4ec08fc083de3abe50e58", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/hi/local.md", + "kind": "file", + "mode": 33188, + "payload_digest": "5289ba2802b24f18a6afe990ddb4276faf2297c6cae75a964c9905c189f99033", + "entry_digest": "36bf50f6d883038c37dbec78d697784287e22046eff83e585ba5dc6c5b5f816c", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/hi/render.md", + "kind": "file", + "mode": 33188, + "payload_digest": "b0923791421fc00c64725b77e0dce6dd223cf950e1fe40bbab7fe71160b63338", + "entry_digest": "9a3d081a42bc70cd32d2ad397e38bc6e4bd350df2b3124d076eb36228294e7d0", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/hi/sculpture.md", + "kind": "file", + "mode": 33188, + "payload_digest": "7116a830b65f7af632d2b2d2aa77e567631c2a33a7fcb5d3b9cd3a3d57082271", + "entry_digest": "caea0e7869eae9c61e45f6cdca43df6afbc1b81cc333ca602744fc342db91f2d", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/hi/shell.md", + "kind": "file", + "mode": 33188, + "payload_digest": "d8fb4017d5a6dad0adc64617d8d7289001dc0cdac3e33e1ceb9f1f644fda49f5", + "entry_digest": "fbbea37430b6614be789611f97c9f2e5337cdc8df825e4945cd078e988359987", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/hi/slice.md", + "kind": "file", + "mode": 33188, + "payload_digest": "295ed1d6feff3b478fb6a7f751feb35cee475ab60d94e214bc04d3f639c2e546", + "entry_digest": "357fdb9cb2e2b1e44d3cd2372ba1cad4cc6b1ede97d0003be1221473c5e98bfb", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/hi/world.md", + "kind": "file", + "mode": 33188, + "payload_digest": "663559da5bb02db3413f545de91e81ffd7ab5c3890158aeaec964d819c1ded5a", + "entry_digest": "6b2354660f0978b98ab1c58356d2fc585763ac09e078b5f988e14f6493255e74", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/specs", + "kind": "non_file", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "f4fb94115c0cd72e416a30a3a454bbbda63ac0989744dd1fa148551cef9875ef", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/specs/RookApp/RookApp.spec.md", + "kind": "file", + "mode": 33188, + "payload_digest": "328f0e0ec49767f115960ba7a09b1395626ef6dd78cdb76f79ffc61d3b381859", + "entry_digest": "9b423979478d8e5435ad55cefb13fd9f1cb745b718a28367a176d282ab385f26", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/specs/RookApp/requirements.md", + "kind": "file", + "mode": 33188, + "payload_digest": "a998087ec9c46dec9d5e3f6e3f4c2680966f67d766be19fe3a7a1c9ae9fec9d3", + "entry_digest": "29b6f5ed8b2d484afc100b05e971236b61d7e4ee48637788c1799a205da5236e", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/specs/RookCore/RookCore.spec.md", + "kind": "file", + "mode": 33188, + "payload_digest": "edd8f788a56817afc8eb2d477a0a75f3bc37135d205b1f6e9665d03ff0b74344", + "entry_digest": "729f1a3b27ad303e7b38f7aa49372a4ef57113a9014060cbff46c2cc2fd6a810", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/specs/RookCore/requirements.md", + "kind": "file", + "mode": 33188, + "payload_digest": "80305947b009aeab89c4fae62bc8ef48cb0c6c95cfbd351cea9e2fc0f47a0b21", + "entry_digest": "c5d7038b613041d8fabe4e2dc47fc2fc08efe5774e9551e50648763eca8d2cf8", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/specs/RookDevelopment/RookDevelopment.spec.md", + "kind": "file", + "mode": 33188, + "payload_digest": "b2c021c8fa8d74dc2197bd5ef8754e4f3eadb091c743831ad643b7867588c9d0", + "entry_digest": "319c60159eecb9efbd78bb2a137c83b5e0d6357cdb6e72aa96ff86e80a7d3adb", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/specs/RookDevelopment/requirements.md", + "kind": "file", + "mode": 33188, + "payload_digest": "0efd07ebb2fa2d12769429f782dd1d2d70362adbeca2a82234251c6aa55abe90", + "entry_digest": "a11e80095e0bb66c0baba88236129a1ebef28c54ea2f454e2362c70467a6f960", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/specs/RookRendering/RookRendering.spec.md", + "kind": "file", + "mode": 33188, + "payload_digest": "3eaeae84bde150f19ca189a04310b28dda74cfb90d55430c8835f07b1ee1008d", + "entry_digest": "65bb892edfa4ca765ffc6556cc977b0af8cd62ccfed702f5c71266ac30debb37", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/specs/RookRendering/requirements.md", + "kind": "file", + "mode": 33188, + "payload_digest": "9360c435f8fb30b54a7fa3e411a6d8f5347e089ea9038a80734fc821b49dcdcf", + "entry_digest": "17c88752e827fc1622f4a732707fcb86865a43baf1ef6630541f2b0c584f6521", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/specs/RookSculpture/RookSculpture.spec.md", + "kind": "file", + "mode": 33188, + "payload_digest": "a89be62701494e3b6c7ffbde27888091fe3c0d7d81fb91813fe697686d0381ae", + "entry_digest": "33ea611aec1446b7377f396832436a2f23db9075d8466462a978d6b04554d412", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "apps/sculpt/specs/RookSculpture/requirements.md", + "kind": "file", + "mode": 33188, + "payload_digest": "fddb51105fb11306fc54c53f1c74771fde301812c8a3da5a253108ec89b5000d", + "entry_digest": "3d9dd7140bc5cfe762961be8d7cd0c7fa5369d44dd46ea208384221979a0fa5f", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "hi/tools.md", + "kind": "file", + "mode": 33188, + "payload_digest": "cd530f076ed449b2dcd994f9178fcb104f4460e44a12042200b42bf6ca6d6306", + "entry_digest": "a13f216eb32a3671d7563024082ab76eb471bdd7a2ddb3c3398b672b05354a70", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "specs/ThreeMDViewer", + "kind": "non_file", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "b53a01354acef7fb830687d9789c70f85c60f43e94da4a2dd0816c771a3bf773", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/ThreeMDViewer.spec.md", + "kind": "file", + "mode": 33188, + "payload_digest": "3b3b09952c692c501a98d6520fb8a82f5126ab9b05d64f6634b50cbae3620ae6", + "entry_digest": "64224b139df2b01fdd0db61c4817d9a836030dbf2667bda60529f6a61be627b4", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/context.md", + "kind": "file", + "mode": 33188, + "payload_digest": "a0011f2d32b7dce6370e015fefcf09acbcf52578e82a97e56def17e0e0fbed52", + "entry_digest": "e020a4426da69e6b24dd3025c95afd9a88cf073bca235f86ad9104e1de81c7f7", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/requirements.md", + "kind": "file", + "mode": 33188, + "payload_digest": "96612855952a65a5e6b623e2b5d21e9dd8f4ea88c92c0e8ef392e3b826b81f94", + "entry_digest": "5caf30173677b31dcf1119406f03f7dd5a1721487ef58ceacb8d22ed07244d4d", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/tasks.md", + "kind": "file", + "mode": 33188, + "payload_digest": "4b0a856509eb4b4c0c875e4b74844c45ce162acf255ce69bf88f86d82feae603", + "entry_digest": "3767a753d3d8c88a88e61820f68b82317f5cd533b57cec5ddc798c7d33ef2656", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/testing.md", + "kind": "file", + "mode": 33188, + "payload_digest": "e224b1bc77ea1679aa4cbd34f182846717be905bec43bff555d19f0ba5f75b15", + "entry_digest": "fee23d7cfc7097bb6cda3f52a2a0efd8ae2030ec4c32059529bccb53252bc7e1", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "uitests/viewer.spec.mjs", + "kind": "file", + "mode": 33188, + "payload_digest": "52dd2553472620fd956815792cb22c70980c8d70ea4563eac487ec5eb4f28093", + "entry_digest": "05c24eeea687cd37e72eaa5382b93877334fb1cb53ab1b80babe625a09d0393b", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "web/viewer.html", + "kind": "file", + "mode": 33188, + "payload_digest": "457af08a02075688bdec1285f820bd6e6ff48e54c392a6239d3a0519a21197b2", + "entry_digest": "91188b507e047ae68fe1e96a1980f5b33206532a2cabafec98e7d7883e0b70e4", + "owners": [ + "ThreeMDViewer" + ] + } + ] + }, + "passed": true, + "commands": [ + { + "command": "specsync check --spec ThreeMDViewer --strict", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [ + "REQ-ThreeMDViewer-007" + ] +} diff --git a/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/accepted-state.json b/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/accepted-state.json new file mode 100644 index 00000000..1ccd903e --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/accepted-state.json @@ -0,0 +1,45 @@ +{ + "schema_version": 1, + "workflow_version": 2, + "workflow_origin_version": 2, + "id": "bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference", + "slug": "bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference", + "title": "Bring Sculpt slice editing to the browser with a visual grid, drawing tools, undo and live 3D reference", + "description": "Bring Sculpt slice editing to the browser with a visual grid, drawing tools, undo and live 3D reference", + "kind": "feature", + "state": "accepted", + "canonical_applied": true, + "base_commit": "fa61988c163583e5e03cbe00f301b036f37dd7b2", + "created_at": 1791652000, + "updated_at": 1791655783, + "affected_specs": [ + "ThreeMDViewer" + ], + "affected_paths": [ + "web/viewer.html", + "uitests/viewer.spec.mjs", + "apps/sculpt/Tests/RookAppTests/SculptureWorkspaceTests.swift", + "docs/evidence/viewer-slice", + "hi/tools.md" + ], + "no_spec_change": false, + "no_spec_change_rationale": null, + "acceptance_criteria": [ + "Add a Sculpt-style Slice workspace with thumbnails, an editable grid, Draw Erase Fill, the native glyph palette, square brush sizes 1 3 5, gap-free strokes, one undo step per drag, redo, keyboard cell controls, previous-slice overlay, grid zoom and live 3D reference; preserve exact source outside edited grid cells and existing drafts downloads and camera behavior; verify shared native/browser edit fixtures and Chromium WebKit desktop phone interaction checks." + ], + "selected_artifacts": [ + "context", + "requirements", + "plan", + "tasks", + "testing", + "docs", + "design", + "research" + ], + "dependencies": [], + "answers": { + "architecture_risk": "yes", + "public_contract": "yes" + } +} diff --git a/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/approvals.json b/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/approvals.json new file mode 100644 index 00000000..14d0aaf4 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/approvals.json @@ -0,0 +1,50 @@ +{ + "approvals": [ + { + "gate": "definition", + "actor": "user:0xLeif", + "timestamp": 1791653000, + "digest": "c0b8195b500e020a9703bb7edd72d722e7f379c81edd26658c5b1473356c2d6f", + "note": "Leif directly replied continue after being presented the complete Slice and axis-control definitions and their approval prompt. This records definition and conditional verified-closure authorization, not a diff review or signature.", + "approved_scope": { + "schema_version": 1, + "change_id": "bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference", + "title": "Bring Sculpt slice editing to the browser with a visual grid, drawing tools, undo and live 3D reference", + "description": "Bring Sculpt slice editing to the browser with a visual grid, drawing tools, undo and live 3D reference", + "kind": "feature", + "affected_specs": [ + "ThreeMDViewer" + ], + "affected_paths": [ + "apps/sculpt/Tests/RookAppTests/SculptureWorkspaceTests.swift", + "docs/evidence/viewer-slice", + "hi/tools.md", + "uitests/viewer.spec.mjs", + "web/viewer.html" + ], + "no_spec_change": false, + "no_spec_change_rationale": null, + "acceptance_criteria": [ + "Add a Sculpt-style Slice workspace with thumbnails, an editable grid, Draw Erase Fill, the native glyph palette, square brush sizes 1 3 5, gap-free strokes, one undo step per drag, redo, keyboard cell controls, previous-slice overlay, grid zoom and live 3D reference; preserve exact source outside edited grid cells and existing drafts downloads and camera behavior; verify shared native/browser edit fixtures and Chromium WebKit desktop phone interaction checks." + ], + "dependencies": [], + "supersedes": [], + "answers": { + "architecture_risk": "yes", + "public_contract": "yes" + } + }, + "approved_delta_digests": { + "ThreeMDViewer": "5da4b8303d240d01a794275be3f3e806b949aef6525dccdd19e2c4cf9b9cca9e" + } + }, + { + "gate": "finalization", + "actor": "specsync:finalization", + "timestamp": 1791655783, + "digest": "81add2ee28a6a48eb29571e64c50b2f5a19e4e2c9f085554f3a00a71a731a620", + "note": "Same-PR finalization closing digest" + } + ], + "reopenings": [] +} diff --git a/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/change.md b/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/change.md new file mode 100644 index 00000000..c30006f9 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/change.md @@ -0,0 +1,24 @@ +--- +id: bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference +state: archived +type: feature +base_commit: fa61988c163583e5e03cbe00f301b036f37dd7b2 +--- + +# Bring Sculpt slice editing to the browser with a visual grid, drawing tools, undo and live 3D reference + +## Intent + +Bring Sculpt slice editing to the browser with a visual grid, drawing tools, undo and live 3D reference + +## Affected Canonical Specs + +- `ThreeMDViewer` + +## Acceptance Criteria + +- Add a Sculpt-style Slice workspace with thumbnails, an editable grid, Draw Erase Fill, the native glyph palette, square brush sizes 1 3 5, gap-free strokes, one undo step per drag, redo, keyboard cell controls, previous-slice overlay, grid zoom and live 3D reference; preserve exact source outside edited grid cells and existing drafts downloads and camera behavior; verify shared native/browser edit fixtures and Chromium WebKit desktop phone interaction checks. + +## No-spec Rationale + +Not applicable diff --git a/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/context.md b/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/context.md new file mode 100644 index 00000000..afcdd241 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/context.md @@ -0,0 +1,12 @@ +--- +change: bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference +artifact: context +--- + +# Context + +Leif asked to keep making the browser as good as Sculpt.3md after showing the native Slice workspace and hearing the current camera/editor distinction. This definition ports the central slice-authoring loop. The current viewer and camera changes are archived in PR 93; the new feature is an unapproved definition, not a retroactive expansion of those records. + +Sources of truth are SculptureEditor.sliceWorkspace/drawingTools, LayerGrid, SculptureWorkspace.paint/line/floodFill/undo/redo and Sculpture.palette. The screenshot shows a 9 by 7 scene with five slices, a teal selected cell and a small 3D reference. Native behavior is reused as the oracle through shared fixtures rather than reimplemented in the native app. + +The page owns exact source, parsed document, active file/entry drafts and the single GPU stage. Native tests receive an additive fixture assertion in their existing workspace test file. Library, parser, bundles, format, releases and native editing behavior stay unchanged. X/Y/Z camera controls have a separate complete draft; neither definition is approved yet. Leif retains merge authority. Actual implementation/review actors are agent:codex, never a different agent or an independent human. diff --git a/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/deltas/ThreeMDViewer.md b/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/deltas/ThreeMDViewer.md new file mode 100644 index 00000000..a118cf56 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/deltas/ThreeMDViewer.md @@ -0,0 +1,29 @@ +# ThreeMDViewer delta + +## MODIFIED + +### REQUIREMENT REQ-ThreeMDViewer-003 + +The viewer page SHALL show Edit, Preview, Cubes, and Slice in one panel. Exactly one main view SHALL be visible; Slice SHALL include a live 3D reference within its workspace. Cubes SHALL be the default, and the opening document SHALL be a small sculpture whose cubes are inside the window. Files SHALL stay in the column beside that panel. Below 900px, Files and the document SHALL take turns, and the document panel SHALL still switch Edit, Preview, Cubes, and Slice. Choosing Preview SHALL render the live plane view. The workspace SHALL keep infrequent export and conversion actions in the Document disclosure, show insert tools only in Edit, and show the document title in every view. Tabs and the single-row plane outline SHALL provide one tab stop per group, with arrow, Home, and End navigation. File and composition-entry navigation SHALL preserve current edits, caret, and selected plane within the open collection. Edited documents SHALL be identified in every view. Opened files SHALL support filtering and keyboard navigation. Choosing a file or search result on a narrow screen SHALL reveal the document. Search and packing SHALL use current drafts. Failed local opens SHALL preserve the current collection. Explicit document navigation SHALL replace a stale source query with the current document hash. The Slice workspace SHALL preserve the current selected plane, camera and source when entering or leaving the view. + +Acceptance Criteria: + +- Existing default Cubes, Files navigation and Edit/Preview behavior remain; Slice is the additional main workspace and retains current selection, camera and draft. +- Existing draft, composition, phone and disclosure checks continue to pass alongside Slice tests. + +## ADDED + +### REQUIREMENT REQ-ThreeMDViewer-008 + +The browser SHALL offer a Sculpt-style Slice workspace that edits bounded character grids in the current document, preserves the surrounding source, and produces the same supported cell edits as Sculpt. + +Acceptance Criteria: + +- Add Slice beside Edit, Preview and Cubes while keeping Cubes as the default. Slice presents selectable thumbnails, a large editable grid, current one-based X/Y and slice coordinates, an interactive live 3D reference, and Expand back to Cubes. Selection and camera survive view switches; the reference reuses the existing WebGL context. +- Draw, Erase and Fill use the native palette # @ * + o x : = - and period for erased cells. Square brushes of size 1, 3 and 5 clip to the grid. Fast pointer movement follows the same integer line interpolation as SculptureWorkspace, with no gaps. Fill uses four-neighbor connectivity on the selected slice and ignores brush size. +- A drag is one undo step; no-op edits add no history. Undo and redo restore exact source and synchronize the grid and reference. Source typing and visual edits use coherent history, retained with each draft and shared by linked file/entry views. A new edit clears redo. History is bounded to 100 entries per draft and an 8 MiB collection budget without dropping the current source. Pointer release, cancel, lost capture or navigation finish the current accepted stroke and prevent late writes into another document. +- Arrow keys move the selected cell within bounds; Space applies the current tool. Explicit X/Y controls and Apply support precise keyboard editing. Grid zoom offers Fit, 2x, 4x, 8x and 16x with internal scrolling. Show previous slice overlays occupied cells only behind empty current cells, is unavailable on the first slice, and never mutates source. +- Eligible documents contain complete rectangular fenced ASCII grids with common dimensions, the native palette and period/space empty cells. Empty grids remain editable. Keep the viewer limits of 64 columns, 64 rows, 4000 occupied cells and 12 distinct render glyphs; visual editing additionally limits eligible documents to 256 slices and 1.5 MiB of source. Prose, invalid, ragged, tabbed, unsupported-glyph or over-budget documents retain Edit/Preview/Cubes as appropriate and explain why Slice editing is unavailable. A proposed edit that exceeds a limit is rejected without committing a partial transaction or adding undo history. +- Source edits replace only targeted grid characters, preserving frontmatter, plane coordinates, labels, other body content, fence markers and newline style byte for byte. Visual edits immediately participate in Edited markers, source download, kind 2 export, search and packing. They do not write original files, persist browser storage or rewrite a composition profile. +- Slice remains usable at 390x844 and 320x740 with touch targets, visible keyboard focus, named controls, an accessible selected-cell description and no page overflow. The 2D editor works without WebGL2; the reference explains GPU unavailability and preserves edits. The existing camera, file, composition, export and accessibility regressions continue to pass. +- Shared asymmetric edit fixtures verify native/browser Draw, Erase, Fill, clipped brushes, sparse diagonal input and undo/redo against independently specified final cells. Chromium and WebKit tests exercise actual pointer and keyboard flows, exact source preservation, empty grids, history boundaries, composition switching, downloads and phone layout. Evidence distinguishes automated checks, agent visual inspection, local Trust, remote CI and provenance limitations. diff --git a/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/design.md b/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/design.md new file mode 100644 index 00000000..8ae17e9b --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/design.md @@ -0,0 +1,29 @@ +--- +change: bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference +artifact: design +--- + +# Slice workspace design + +Use the supplied Sculpt screenshot as the visual reference and the current CorvidLabs tokens as the browser identity. The main hierarchy is document title, view selector, Slice canvas and tools. The editable grid gets the largest area; the small reference answers where the selected slice sits in the volume. No new page theme or decorative cards. + +Color uses existing paper/ink/surface/hairline/accent tokens, with the fixed cube background #11161a, teal cell selection near #39cbbb, quieter previous-layer glyphs and gold selected-slice cube edges #ffca70. Schibsted Grotesk remains the UI face; Spline Sans Mono serves grid glyphs and source. Browser light/dark themes remain supported. + +Desktop arrangement inside the existing document panel: + +```text +Document title Edited +Edit Preview Cubes Slice +Slices Slice 1 X 7 Y 4 +[thumb] 1 Fit 2x 4x 8x 16x 3D reference Expand +[thumb] 2 +----------------+ [current GPU stage] +[thumb] 3 | editable cells | Draw Erase Fill +[thumb] 4 | | # @ * + o x : = - +[thumb] 5 +----------------+ Size 1 3 5 +9 x 7 cells Show previous slice Selected cell / Apply + keyboard hint Undo Redo +``` + +Files remain the existing outer navigation. Slice thumbnails are compact inner navigation; on phones they become a horizontal scroll strip. The reference and tools flow below the grid at narrow widths, with the reference collapsible so it does not crowd drawing. Grid zoom scrolls inside the editor; it never widens the page. Tools keep large touch targets, pressed state and visible focus. One grid focus target plus coordinate controls avoids thousands of cell tab stops. + +The subject-specific decision is the glyph grid beside its volumetric context. Review against the screenshot: no hero content, new gradients, overlaid toolbars or generic dashboard cards. Expand moves the same GPU view back to Cubes; edits and camera are preserved. diff --git a/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/docs.md b/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/docs.md new file mode 100644 index 00000000..fa01cff2 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/docs.md @@ -0,0 +1,12 @@ +--- +change: bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference +artifact: docs +--- + +# Documentation and delivery + +Update ThreeMDViewer purpose, REQ-ThreeMDViewer-003, new REQ-ThreeMDViewer-008, relevant invariants, out-of-scope text, requirements/tasks/context/testing and VIEWER-6 after implementation under approval. Preserve archived records and the established camera contract. + +Capture actual desktop and phone Slice workspaces and the edited live reference in docs/evidence/viewer-slice. Explain which inputs support visual editing, period erasure, source preservation, per-draft history bounds and session-only drafts. Describe unsupported content through product guidance, not parser implementation details. + +Keep the browser and native test receipts distinct, record the exact source commit and report retries/skips. Feature PR prose must lead with the editing behavior and distinguish local checks, remote CI, actual agent review and unsigned provenance. Approval, successful verification and supported lifecycle closure are separately recorded. Leif retains merge authority; no release, deployment, policy change or original-file write is included. diff --git a/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/finalization.json b/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/finalization.json new file mode 100644 index 00000000..5e4ce8f0 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/finalization.json @@ -0,0 +1,12 @@ +{ + "schema_version": 2, + "change_id": "bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference", + "implementation_commit": "6e8d0bb72dec11684d501cf5cbdc25b2f276b853", + "implementation_tree": "87451f2cfbbdf4b72ad4e767612aa45e91478c81", + "contract_digest": "c0b8195b500e020a9703bb7edd72d722e7f379c81edd26658c5b1473356c2d6f", + "workspace_digest": "fde013fc78a6110e0c0b88de16f5f6e7522e6561a06c0a5c5fd273d884ed5278", + "closing_digest": "81add2ee28a6a48eb29571e64c50b2f5a19e4e2c9f085554f3a00a71a731a620", + "review_digest": "855b061f32615f8397bb99951a89b1b7d0a691fc1508e574abe41b268a242ca6", + "finalization_digest": "0caf17781aef4d755beecc9b6930d254942651a5365545cae8df19c5ed4bee94", + "timestamp": 1791655783 +} diff --git a/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/lesson-bundle.md b/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/lesson-bundle.md new file mode 100644 index 00000000..8f091e48 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/lesson-bundle.md @@ -0,0 +1,84 @@ +# Lesson bundle — bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference + +Material for folding this change's lessons into the affected specs' `context.md`. +Synthesise from what actually happened below; do not restate the change description. + +## What this change was + +- **Title**: Bring Sculpt slice editing to the browser with a visual grid, drawing tools, undo and live 3D reference +- **Kind**: Feature +- **Specs**: ThreeMDViewer +- **Paths**: web/viewer.html, uitests/viewer.spec.mjs, apps/sculpt/Tests/RookAppTests/SculptureWorkspaceTests.swift, docs/evidence/viewer-slice, hi/tools.md +- **Acceptance**: Add a Sculpt-style Slice workspace with thumbnails, an editable grid, Draw Erase Fill, the native glyph palette, square brush sizes 1 3 5, gap-free strokes, one undo step per drag, redo, keyboard cell controls, previous-slice overlay, grid zoom and live 3D reference; preserve exact source outside edited grid cells and existing drafts downloads and camera behavior; verify shared native/browser edit fixtures and Chromium WebKit desktop phone interaction checks. + +## Evidence + +- Verification commit: `6e8d0bb72dec11684d501cf5cbdc25b2f276b853` +- Base commit: `fa61988c163583e5e03cbe00f301b036f37dd7b2` +- Verified by: `specsync check --spec ThreeMDViewer --strict` + +## From the change's context.md + +# Context + +Leif asked to keep making the browser as good as Sculpt.3md after showing the native Slice workspace and hearing the current camera/editor distinction. This definition ports the central slice-authoring loop. The current viewer and camera changes are archived in PR 93; the new feature is an unapproved definition, not a retroactive expansion of those records. + +Sources of truth are SculptureEditor.sliceWorkspace/drawingTools, LayerGrid, SculptureWorkspace.paint/line/floodFill/undo/redo and Sculpture.palette. The screenshot shows a 9 by 7 scene with five slices, a teal selected cell and a small 3D reference. Native behavior is reused as the oracle through shared fixtures rather than reimplemented in the native app. + +The page owns exact source, parsed document, active file/entry drafts and the single GPU stage. Native tests receive an additive fixture assertion in their existing workspace test file. Library, parser, bundles, format, releases and native editing behavior stay unchanged. X/Y/Z camera controls have a separate complete draft; neither definition is approved yet. Leif retains merge authority. Actual implementation/review actors are agent:codex, never a different agent or an independent human. + +## From the change's design.md + +# Slice workspace design + +Use the supplied Sculpt screenshot as the visual reference and the current CorvidLabs tokens as the browser identity. The main hierarchy is document title, view selector, Slice canvas and tools. The editable grid gets the largest area; the small reference answers where the selected slice sits in the volume. No new page theme or decorative cards. + +Color uses existing paper/ink/surface/hairline/accent tokens, with the fixed cube background #11161a, teal cell selection near #39cbbb, quieter previous-layer glyphs and gold selected-slice cube edges #ffca70. Schibsted Grotesk remains the UI face; Spline Sans Mono serves grid glyphs and source. Browser light/dark themes remain supported. + +Desktop arrangement inside the existing document panel: + +```text +Document title Edited +Edit Preview Cubes Slice +Slices Slice 1 X 7 Y 4 +[thumb] 1 Fit 2x 4x 8x 16x 3D reference Expand +[thumb] 2 +----------------+ [current GPU stage] +[thumb] 3 | editable cells | Draw Erase Fill +[thumb] 4 | | # @ * + o x : = - +[thumb] 5 +----------------+ Size 1 3 5 +9 x 7 cells Show previous slice Selected cell / Apply + keyboard hint Undo Redo +``` + +Files remain the existing outer navigation. Slice thumbnails are compact inner navigation; on phones they become a horizontal scroll strip. The reference and tools flow below the grid at narrow widths, with the reference collapsible so it does not crowd drawing. Grid zoom scrolls inside the editor; it never widens the page. Tools keep large touch targets, pressed state and visible focus. One grid focus target plus coordinate controls avoids thousands of cell tab stops. + +The subject-specific decision is the glyph grid beside its volumetric context. Review against the screenshot: no hero content, new gradients, overlaid toolbars or generic dashboard cards. Expand moves the same GPU view back to Cubes; edits and camera are preserved. + +## From the change's testing.md + +# Verification + +Shared fixtures under docs/evidence/viewer-slice state initial rectangular native-compatible cells, tool/glyph/size, integer sampled path, selected slice and independently written final rows. Include an asymmetric 9x7x5 case, horizontal/diagonal strokes, repeated points, starts on unchanged cells, size-3/5 corner clipping, erase, four-neighbor fill without crossing diagonals or slice boundaries, no-op fill, and undo/redo. Native SculptureWorkspaceTests run the real workspace; browser tests use actual pointer/key actions. + +Exact-source cases include frontmatter, distinct z positions and labels, body prose around a closed fence, CRLF, space/period empties, and another untouched plane. Require exact non-target bytes after drawing and exact restoration after undo. Invalid/ragged/tabbed/unsupported grids and all budget boundaries keep their source. Empty native-compatible grids must enter Slice and accept drawing. + +History checks mix source typing, insert tools, grid strokes and undo/redo; switch between two files and linked entry/file views; use canceled/lost pointers; exercise trimming and redo invalidation; export/search/pack during pending redraw. No late event may write into a newly activated document. Source download and kind 2 decoding must contain the final edit. + +Chromium/WebKit checks cover desktop and 390x844/320x740 layouts, primary touch drawing, keyboard cell movement and Space, explicit X/Y validation, every zoom option and previous-slice visibility. Require internal grid scrolling, visible controls and meaningful accessibility names. GPU-unavailable Slice editing remains usable. Existing one-context, no camera-only geometry upload, nearest picking and pole-crossing tests run unchanged. + +Run the complete viewer suite on macOS and the complete UI suite in the existing Linux Playwright environment. Run the focused native workspace fixture selection and broaden native tests only if behavior or failures warrant it. Run strict root and nested app specs with full configured coverage, root/native Hi and pinned Trust 1.2.2 with Fledge 1.7.2. Record actual actor, tested source commit, retries/skips and unchanged provenance limits. Actual execution evidence is recorded under docs/evidence/viewer-slice. No independent human review or permitted signature is claimed. + +## Execution evidence + +Implementation commit 8e9a0c4 has 226 passing macOS browser tests, 637 passing configured native tests and 11 passing final native parity tests. Expanded browser fixtures and phone checks each passed 4 cases. Pinned Trust passed; actual unsigned agent:codex provenance was recorded and fails the unchanged permitted-signature/reviewer policy as expected. Linux CI passed 218 functional tests with 8 existing platform-snapshot skips and no retries; all macOS snapshots passed. Current receipts are in docs/evidence/viewer-slice; final lifecycle receipts are separate. Source and visual verification are distinct from Leif’s diff review. + +## Requirement evidence + +| ID | Canonical | Evidence | +| --- | --- | --- | +| REQ-ThreeMDViewer-003 | REQ-ThreeMDViewer-003 | Actual four-view layout in web/viewer.html; full Chromium/WebKit viewer regressions and desktop/phone screenshots in docs/evidence/viewer-slice. | +| REQ-ThreeMDViewer-008 | REQ-ThreeMDViewer-008 | Shared slice-parity.json cases run by browser pointer gestures and native browserSliceFixturesMatchNativeWorkspaceToolsAndWholeStrokeHistory. Source preservation, bounded history, navigation, keyboard, downloads, GPU refusal and phone tests pass; actual logs are in docs/evidence/viewer-slice. | + +## Where these lessons go + +- `specs/ThreeMDViewer/context.md` diff --git a/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/plan.md b/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/plan.md new file mode 100644 index 00000000..3c025cc9 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/plan.md @@ -0,0 +1,16 @@ +--- +change: bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference +artifact: plan +--- + +# Plan + +1. Obtain definition approval, then start this change through SpecSync 6. Record the actual approval without claiming a reviewed diff or a signature. +2. Add an eligibility/source-span adapter in the page. Cache rectangular grids and exact character offsets by source revision. All mutations are reversible source transactions; unsupported content remains readable through the existing views. +3. Implement shared stroke interpolation, clipped brushes and four-neighbor fill. Establish coherent per-draft history across typing and grid edits, including linked entry/file state. Bound history memory, reject over-budget transactions atomically and end strokes before navigation/export. +4. Add the Slice view with thumbnails, grid canvas, selected-cell controls, zoom/scroll, previous-slice overlay and native-style tools. Reparent the existing GPU canvas for the small reference and Expand; preserve camera, bitmap/context and geometry on view-only changes. Coalesce live-reference source updates per animation frame and flush pending edits before navigation or export. +5. Add independently specified edit fixtures and run the actual native workspace and browser interactions against them. Extend source, file/history, phone, pointer-cancel and GPU-unavailable regressions. +6. Update canonical viewer requirements, purpose, bounded-editing exclusions, companions and VIEWER-6 to describe the implemented feature. Run current browser/native selections, strict root/native specs, intent checks and pinned Trust. Record actual provenance under unchanged policy. +7. Present evidence and use supported scoped review/finalization only under explicit verified-closure approval. Update the feature PR with the resulting behavior and exact validation; Leif merges it. + +Structural slice actions, volume resizing, direct 3D paint and export-format expansion follow this central editing loop in later definitions. Axis gizmo work may proceed separately only when its existing definition is approved. diff --git a/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/requirements.md b/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/requirements.md new file mode 100644 index 00000000..5754c555 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/requirements.md @@ -0,0 +1,21 @@ +--- +change: bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference +artifact: requirements +--- + +# Requirements + +### REQ-ThreeMDViewer-008 + +The browser SHALL offer a Sculpt-style Slice workspace that edits bounded character grids in the current document, preserves the surrounding source, and produces the same supported cell edits as Sculpt. + +Acceptance Criteria: + +- Add Slice beside Edit, Preview and Cubes while keeping Cubes as the default. Slice presents selectable thumbnails, a large editable grid, current one-based X/Y and slice coordinates, an interactive live 3D reference, and Expand back to Cubes. Selection and camera survive view switches; the reference reuses the existing WebGL context. +- Draw, Erase and Fill use the native palette # @ * + o x : = - and period for erased cells. Square brushes of size 1, 3 and 5 clip to the grid. Fast pointer movement follows the same integer line interpolation as SculptureWorkspace, with no gaps. Fill uses four-neighbor connectivity on the selected slice and ignores brush size. +- A drag is one undo step; no-op edits add no history. Undo and redo restore exact source and synchronize the grid and reference. Source typing and visual edits use coherent history, retained with each draft and shared by linked file/entry views. A new edit clears redo. History is bounded to 100 entries per draft and an 8 MiB collection budget without dropping the current source. Pointer release, cancel, lost capture or navigation finish the current accepted stroke and prevent late writes into another document. +- Arrow keys move the selected cell within bounds; Space applies the current tool. Explicit X/Y controls and Apply support precise keyboard editing. Grid zoom offers Fit, 2x, 4x, 8x and 16x with internal scrolling. Show previous slice overlays occupied cells only behind empty current cells, is unavailable on the first slice, and never mutates source. +- Eligible documents contain complete rectangular fenced ASCII grids with common dimensions, the native palette and period/space empty cells. Empty grids remain editable. Keep the viewer limits of 64 columns, 64 rows, 4000 occupied cells and 12 distinct render glyphs; visual editing additionally limits eligible documents to 256 slices and 1.5 MiB of source. Prose, invalid, ragged, tabbed, unsupported-glyph or over-budget documents retain Edit/Preview/Cubes as appropriate and explain why Slice editing is unavailable. A proposed edit that exceeds a limit is rejected without committing a partial transaction or adding undo history. +- Source edits replace only targeted grid characters, preserving frontmatter, plane coordinates, labels, other body content, fence markers and newline style byte for byte. Visual edits immediately participate in Edited markers, source download, kind 2 export, search and packing. They do not write original files, persist browser storage or rewrite a composition profile. +- Slice remains usable at 390x844 and 320x740 with touch targets, visible keyboard focus, named controls, an accessible selected-cell description and no page overflow. The 2D editor works without WebGL2; the reference explains GPU unavailability and preserves edits. The existing camera, file, composition, export and accessibility regressions continue to pass. +- Shared asymmetric edit fixtures verify native/browser Draw, Erase, Fill, clipped brushes, sparse diagonal input and undo/redo against independently specified final cells. Chromium and WebKit tests exercise actual pointer and keyboard flows, exact source preservation, empty grids, history boundaries, composition switching, downloads and phone layout. Evidence distinguishes automated checks, agent visual inspection, local Trust, remote CI and provenance limitations. diff --git a/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/research.md b/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/research.md new file mode 100644 index 00000000..eac988e5 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/research.md @@ -0,0 +1,15 @@ +--- +change: bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference +artifact: research +--- + +# Native parity findings + +- Sculpture.palette is #@*+ox:=- and Sculpture.empty is period (46). Native editing uses byte glyphs. Visual browser editing therefore accepts the native ASCII palette; other browser-readable glyphs remain available through source/preview. +- SculptureWorkspace.paint interpolates integer points using the same error-based line algorithm. Brush radius is size/2 clamped to 0...2, with square clipping to bounds. Fill is applied only at stroke start and ignores size. rememberStroke captures the pre-stroke snapshot lazily on the first actual change, so unchanged starts and no-ops behave correctly. +- Native undo/redo restore sculpture snapshots, clamp selection and clear redo on a new remembered edit. Native history retains 100 states. Browser history must also preserve exact source and coordinate with source typing, not rely on hidden-textarea programmatic writes that discard undo state. +- Native Show previous slice draws only behind empty current cells. The screenshot's 3D reference is the existing SculptureViewport at 170-point height, with Expand returning to the volume view. +- The browser currently reads the first code fence into gridOf, skips all-empty grids, treats dot/space/tab as empty and caps visual volume at 4000 occupied cells. The write adapter must distinguish safely editable complete rectangular native-compatible fences from readable-only content and must retain empty grids. +- Existing renderer geometry is cached per parsed document. Camera/selection updates reuse it. The small reference should reuse the same context, with actual source edits as the only new reason to rebuild geometry. + +Structural actions need a separately defined source-coordinate policy before add/duplicate/remove can match native fixed-index layers. They follow this first authoring pass. No external engine/library is required to render this interface. diff --git a/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/review-attempts.json b/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/review-attempts.json new file mode 100644 index 00000000..85c44894 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/review-attempts.json @@ -0,0 +1,21 @@ +{ + "schema_version": 1, + "reviews": [ + { + "schema_version": 2, + "change_id": "bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference", + "reviewer": "agent:codex", + "provenance": { + "schema_version": 1, + "provider": "github_actions_check", + "required_check": "SpecSync scoped review" + }, + "verdict": "pass", + "implementation_commit": "6e8d0bb72dec11684d501cf5cbdc25b2f276b853", + "contract_digest": "c0b8195b500e020a9703bb7edd72d722e7f379c81edd26658c5b1473356c2d6f", + "execution_digest": "8c0c3460123946ea2d50872aab0d8775180c71215745e6aad70feea619be0636", + "workspace_digest": "fde013fc78a6110e0c0b88de16f5f6e7522e6561a06c0a5c5fd273d884ed5278", + "timestamp": 1791655744 + } + ] +} diff --git a/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/review.json b/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/review.json new file mode 100644 index 00000000..b83a1970 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/review.json @@ -0,0 +1,16 @@ +{ + "schema_version": 2, + "change_id": "bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference", + "reviewer": "agent:codex", + "provenance": { + "schema_version": 1, + "provider": "github_actions_check", + "required_check": "SpecSync scoped review" + }, + "verdict": "pass", + "implementation_commit": "6e8d0bb72dec11684d501cf5cbdc25b2f276b853", + "contract_digest": "c0b8195b500e020a9703bb7edd72d722e7f379c81edd26658c5b1473356c2d6f", + "execution_digest": "8c0c3460123946ea2d50872aab0d8775180c71215745e6aad70feea619be0636", + "workspace_digest": "fde013fc78a6110e0c0b88de16f5f6e7522e6561a06c0a5c5fd273d884ed5278", + "timestamp": 1791655744 +} diff --git a/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/state.json b/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/state.json new file mode 100644 index 00000000..ce947dc6 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/state.json @@ -0,0 +1,45 @@ +{ + "schema_version": 1, + "workflow_version": 2, + "workflow_origin_version": 2, + "id": "bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference", + "slug": "bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference", + "title": "Bring Sculpt slice editing to the browser with a visual grid, drawing tools, undo and live 3D reference", + "description": "Bring Sculpt slice editing to the browser with a visual grid, drawing tools, undo and live 3D reference", + "kind": "feature", + "state": "archived", + "canonical_applied": true, + "base_commit": "fa61988c163583e5e03cbe00f301b036f37dd7b2", + "created_at": 1791652000, + "updated_at": 1791655837, + "affected_specs": [ + "ThreeMDViewer" + ], + "affected_paths": [ + "web/viewer.html", + "uitests/viewer.spec.mjs", + "apps/sculpt/Tests/RookAppTests/SculptureWorkspaceTests.swift", + "docs/evidence/viewer-slice", + "hi/tools.md" + ], + "no_spec_change": false, + "no_spec_change_rationale": null, + "acceptance_criteria": [ + "Add a Sculpt-style Slice workspace with thumbnails, an editable grid, Draw Erase Fill, the native glyph palette, square brush sizes 1 3 5, gap-free strokes, one undo step per drag, redo, keyboard cell controls, previous-slice overlay, grid zoom and live 3D reference; preserve exact source outside edited grid cells and existing drafts downloads and camera behavior; verify shared native/browser edit fixtures and Chromium WebKit desktop phone interaction checks." + ], + "selected_artifacts": [ + "context", + "requirements", + "plan", + "tasks", + "testing", + "docs", + "design", + "research" + ], + "dependencies": [], + "answers": { + "architecture_risk": "yes", + "public_contract": "yes" + } +} diff --git a/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/tasks.md b/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/tasks.md new file mode 100644 index 00000000..c331b90e --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/tasks.md @@ -0,0 +1,19 @@ +--- +change: bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference +artifact: tasks +--- + +# Tasks + +- [x] Inspect Sculpt's Slice UI, native stroke/history semantics and current viewer contracts. +- [x] Define the browser slice editing loop, exact-source guarantees, bounded history and shared parity evidence. +- [x] Record Leif's definition approval and start the change. +- [x] Implement eligibility and exact source-span mutations, including completely empty grids. +- [x] Implement Draw/Erase/Fill, interpolation, clipped brushes and coherent bounded draft history. +- [x] Build Slice thumbnails, grid/coordinates, zoom, previous-slice overlay, native-style tools and the live reference. +- [x] Verify shared native/browser edit fixtures and preserve existing camera/file/export behavior. +- [x] Verify desktop, phone, keyboard, touch, canceled-pointer and GPU-unavailable behavior. +- [x] Synchronize canonical contracts and human intent with the resulting implementation. +- [x] Run pinned Trust, record actual provenance and present verification evidence. + +Lifecycle acceptance/archive and PR update require the recorded verified-closure authority and passing current verification. Scope approval is not an independent review or a permitted signature. diff --git a/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/testing.md b/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/testing.md new file mode 100644 index 00000000..947163cd --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/testing.md @@ -0,0 +1,27 @@ +--- +change: bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference +artifact: testing +--- + +# Verification + +Shared fixtures under docs/evidence/viewer-slice state initial rectangular native-compatible cells, tool/glyph/size, integer sampled path, selected slice and independently written final rows. Include an asymmetric 9x7x5 case, horizontal/diagonal strokes, repeated points, starts on unchanged cells, size-3/5 corner clipping, erase, four-neighbor fill without crossing diagonals or slice boundaries, no-op fill, and undo/redo. Native SculptureWorkspaceTests run the real workspace; browser tests use actual pointer/key actions. + +Exact-source cases include frontmatter, distinct z positions and labels, body prose around a closed fence, CRLF, space/period empties, and another untouched plane. Require exact non-target bytes after drawing and exact restoration after undo. Invalid/ragged/tabbed/unsupported grids and all budget boundaries keep their source. Empty native-compatible grids must enter Slice and accept drawing. + +History checks mix source typing, insert tools, grid strokes and undo/redo; switch between two files and linked entry/file views; use canceled/lost pointers; exercise trimming and redo invalidation; export/search/pack during pending redraw. No late event may write into a newly activated document. Source download and kind 2 decoding must contain the final edit. + +Chromium/WebKit checks cover desktop and 390x844/320x740 layouts, primary touch drawing, keyboard cell movement and Space, explicit X/Y validation, every zoom option and previous-slice visibility. Require internal grid scrolling, visible controls and meaningful accessibility names. GPU-unavailable Slice editing remains usable. Existing one-context, no camera-only geometry upload, nearest picking and pole-crossing tests run unchanged. + +Run the complete viewer suite on macOS and the complete UI suite in the existing Linux Playwright environment. Run the focused native workspace fixture selection and broaden native tests only if behavior or failures warrant it. Run strict root and nested app specs with full configured coverage, root/native Hi and pinned Trust 1.2.2 with Fledge 1.7.2. Record actual actor, tested source commit, retries/skips and unchanged provenance limits. Actual execution evidence is recorded under docs/evidence/viewer-slice. No independent human review or permitted signature is claimed. + +## Execution evidence + +Implementation commit 8e9a0c4 has 226 passing macOS browser tests, 637 passing configured native tests and 11 passing final native parity tests. Expanded browser fixtures and phone checks each passed 4 cases. Pinned Trust passed; actual unsigned agent:codex provenance was recorded and fails the unchanged permitted-signature/reviewer policy as expected. Linux CI passed 218 functional tests with 8 existing platform-snapshot skips and no retries; all macOS snapshots passed. Current receipts are in docs/evidence/viewer-slice; final lifecycle receipts are separate. Source and visual verification are distinct from Leif’s diff review. + +## Requirement evidence + +| ID | Canonical | Evidence | +| --- | --- | --- | +| REQ-ThreeMDViewer-003 | REQ-ThreeMDViewer-003 | Actual four-view layout in web/viewer.html; full Chromium/WebKit viewer regressions and desktop/phone screenshots in docs/evidence/viewer-slice. | +| REQ-ThreeMDViewer-008 | REQ-ThreeMDViewer-008 | Shared slice-parity.json cases run by browser pointer gestures and native browserSliceFixturesMatchNativeWorkspaceToolsAndWholeStrokeHistory. Source preservation, bounded history, navigation, keyboard, downloads, GPU refusal and phone tests pass; actual logs are in docs/evidence/viewer-slice. | diff --git a/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/verification-attempts.json b/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/verification-attempts.json new file mode 100644 index 00000000..da1fc9f9 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/verification-attempts.json @@ -0,0 +1,346 @@ +{ + "schema_version": 1, + "attempts": [ + { + "timestamp": 1791655435, + "commit": "c86a777aa255ae3f36341ab2b684dc3896f5606c", + "contract_digest": "c0b8195b500e020a9703bb7edd72d722e7f379c81edd26658c5b1473356c2d6f", + "execution_digest": "0e3d8c1d90dec9447ee91fa201b2093285994023df80a25e3a96809c7388e494", + "workspace_digest": "8585efd5a1f8279d68999fda90ab46f7caccdbb47824face80247500c2aef591", + "passed": true, + "commands": [ + { + "command": "specsync check --spec ThreeMDViewer --strict", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [ + "REQ-ThreeMDViewer-003", + "REQ-ThreeMDViewer-008" + ] + }, + { + "timestamp": 1791655458, + "commit": "3dd9cc9759ebf257633eea07a262f099135bc94b", + "contract_digest": "c0b8195b500e020a9703bb7edd72d722e7f379c81edd26658c5b1473356c2d6f", + "execution_digest": "0e3d8c1d90dec9447ee91fa201b2093285994023df80a25e3a96809c7388e494", + "workspace_digest": "8585efd5a1f8279d68999fda90ab46f7caccdbb47824face80247500c2aef591", + "passed": true, + "commands": [ + { + "command": "specsync check --spec ThreeMDViewer --strict", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [ + "REQ-ThreeMDViewer-003", + "REQ-ThreeMDViewer-008" + ] + }, + { + "timestamp": 1791655680, + "commit": "8a72e4759bd904ba98d5a5ad72776012a98ce37d", + "contract_digest": "c0b8195b500e020a9703bb7edd72d722e7f379c81edd26658c5b1473356c2d6f", + "execution_digest": "8c0c3460123946ea2d50872aab0d8775180c71215745e6aad70feea619be0636", + "workspace_digest": "fde013fc78a6110e0c0b88de16f5f6e7522e6561a06c0a5c5fd273d884ed5278", + "passed": true, + "commands": [ + { + "command": "specsync check --spec ThreeMDViewer --strict", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [ + "REQ-ThreeMDViewer-003", + "REQ-ThreeMDViewer-008" + ] + }, + { + "timestamp": 1791655699, + "commit": "0f32c12ab9f932c428f319d0bf38a02f3cf6f1da", + "contract_digest": "c0b8195b500e020a9703bb7edd72d722e7f379c81edd26658c5b1473356c2d6f", + "execution_digest": "8c0c3460123946ea2d50872aab0d8775180c71215745e6aad70feea619be0636", + "workspace_digest": "fde013fc78a6110e0c0b88de16f5f6e7522e6561a06c0a5c5fd273d884ed5278", + "passed": true, + "commands": [ + { + "command": "specsync check --spec ThreeMDViewer --strict", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [ + "REQ-ThreeMDViewer-003", + "REQ-ThreeMDViewer-008" + ] + }, + { + "timestamp": 1791655699, + "commit": "6e8d0bb72dec11684d501cf5cbdc25b2f276b853", + "contract_digest": "c0b8195b500e020a9703bb7edd72d722e7f379c81edd26658c5b1473356c2d6f", + "execution_digest": "8c0c3460123946ea2d50872aab0d8775180c71215745e6aad70feea619be0636", + "workspace_digest": "fde013fc78a6110e0c0b88de16f5f6e7522e6561a06c0a5c5fd273d884ed5278", + "acceptance_input_digest": "7d9ae9868a12971e4916906777f48079ba9be68815774ac81be3530a50a39d7d", + "acceptance_manifest": { + "schema_version": 1, + "entries": [ + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureWorkspaceTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "f420db050af7dea627b63e3b33e113377e3919b69d24b7d4e5a97a6bcd06c681", + "entry_digest": "997ec23ca0eacd6cd532071f3da63de1da66eb5a0f11ba6902520e84b68c637b", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-slice", + "kind": "non_file", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "6e52461b16415b74502ade3fb4a9296404661b2d8b9daeb46ccb0ef6236e14f3", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-slice/README.md", + "kind": "file", + "mode": 33188, + "payload_digest": "13d95dffe97a3c30e9dee6f1efcb54e4a4488ea752cf0fd4e5b29f65a060d188", + "entry_digest": "b9bc66178406fb257aa5f3e4877d5d0321add9985f5c3007a834044836661d6c", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-slice/attestation-implementation.json", + "kind": "file", + "mode": 33188, + "payload_digest": "468b5420dfa05a8dc8197da78f3e655f1958010dfbd7c3f501fdb6600cb9392e", + "entry_digest": "1a5090b3eea320641a477feff6a3f738912ff39e7061f3a02dd5c6366adea4e0", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-slice/browser-desktop.png", + "kind": "file", + "mode": 33188, + "payload_digest": "1c0d118ecf45577588d8c38b87bd0e47e64cd754fe5a062bd8cc3c0fa613ded0", + "entry_digest": "1baba7229c0e086399d741f9feaee4b9cc02f660553971c505b66c5790adc626", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-slice/browser-fixtures.log", + "kind": "file", + "mode": 33188, + "payload_digest": "f10d4be8edc27c9a524edcd81e46ee140dd0b4df6d9cdb85ae0140fb4b6635c8", + "entry_digest": "e76d66ef8b3b40781d0204528348e076f0eabbe6cb24bde98bbde1b142e94703", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-slice/browser-phone.png", + "kind": "file", + "mode": 33188, + "payload_digest": "8aff87748688950f14cafc08eb1686f0374928c9802fb3353c817ba43bdec8b4", + "entry_digest": "96a3bcca297f2d2e33fb2b160493447090f34abf38307903a35a143ba4b2802d", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-slice/linux-ci.log", + "kind": "file", + "mode": 33188, + "payload_digest": "38881c05504ec22f137a00375d44dbf1be2b0de44179cdd2c1fbfe522d447911", + "entry_digest": "545f9effeb5f9152d2d3a8b00b1ccd73fd14a84a80ed61cc4ab2631dae0e0b6d", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-slice/mac-browser.log", + "kind": "file", + "mode": 33188, + "payload_digest": "8ebaa89f01dd7d5788af9c59c56c8b9c3ff95e49b1da0e03650d668d1b438238", + "entry_digest": "a27a45c3fe71298b77664fc463109ead0c736995273d468694b29b4cb4dfe877", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-slice/native-full.log", + "kind": "file", + "mode": 33188, + "payload_digest": "b9e5a3a50d6312dc11270f7f9301d866e93f68a47564fce94561defa120283fd", + "entry_digest": "6f297fd464f56f2d3b13a8cd35833a13eea22a06e76c651e272674021d61aaec", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-slice/native-parity.log", + "kind": "file", + "mode": 33188, + "payload_digest": "bcc8b1c69e429ffad87ee12c09e236ec8fd294c578ae6f490d8e956b26b4b2ee", + "entry_digest": "667d6ed3703135b5b3d6e506b2260b74571af18643bb88d1e90c26e6a83bd1ba", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-slice/phone.log", + "kind": "file", + "mode": 33188, + "payload_digest": "d1403a073d5817356c3768ed70aa4e1b5dbc71f71da444bef8fbe9a2d64ff98d", + "entry_digest": "b31bf683f4d3247f6a8c7a6f0a53ea82cbfa84cef0aedb1bad1c9ba7fcd594db", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-slice/provenance-implementation.json", + "kind": "file", + "mode": 33188, + "payload_digest": "da4afbc0b7f1c965477d18c3695e3490cc9702a66b64dd21322d5888ba3672a4", + "entry_digest": "cd75a22b45046443d0af903924a889ce6fbb35717ab7fa5715e34e1fa2a762a4", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-slice/sculpt-axis.png", + "kind": "file", + "mode": 33188, + "payload_digest": "e2e207fd6f7e300bf39da0b9d46351f778de6c80e1899292dc2ae528474c818b", + "entry_digest": "05b92d61249cd8588ead868c6cb6ce9b19a1bed90031efdf746e02d5be461baf", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-slice/slice-parity.json", + "kind": "file", + "mode": 33188, + "payload_digest": "e62169ce9cebe521a5cdb0e202c522010d38875c0968d5906e0c8244224b0bbb", + "entry_digest": "3b5d98993c5c88fee47ca5302a6ed1357a3fdacd833f8d7e875a3d1e5b2a2ced", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-slice/trust-implementation.log", + "kind": "file", + "mode": 33188, + "payload_digest": "263cde4e72f922ab16278ece04a6d90178b08afbf6012c6fb7b3d58a3914f236", + "entry_digest": "ea4a45ca2723e4279d40d76807713cbebf38630c22b8cf4c7a9932e030eb42f4", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "hi/tools.md", + "kind": "file", + "mode": 33188, + "payload_digest": "cd530f076ed449b2dcd994f9178fcb104f4460e44a12042200b42bf6ca6d6306", + "entry_digest": "a13f216eb32a3671d7563024082ab76eb471bdd7a2ddb3c3398b672b05354a70", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "specs/ThreeMDViewer/ThreeMDViewer.spec.md", + "kind": "file", + "mode": 33188, + "payload_digest": "3b3b09952c692c501a98d6520fb8a82f5126ab9b05d64f6634b50cbae3620ae6", + "entry_digest": "64224b139df2b01fdd0db61c4817d9a836030dbf2667bda60529f6a61be627b4", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/context.md", + "kind": "file", + "mode": 33188, + "payload_digest": "a0011f2d32b7dce6370e015fefcf09acbcf52578e82a97e56def17e0e0fbed52", + "entry_digest": "e020a4426da69e6b24dd3025c95afd9a88cf073bca235f86ad9104e1de81c7f7", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/requirements.md", + "kind": "file", + "mode": 33188, + "payload_digest": "96612855952a65a5e6b623e2b5d21e9dd8f4ea88c92c0e8ef392e3b826b81f94", + "entry_digest": "5caf30173677b31dcf1119406f03f7dd5a1721487ef58ceacb8d22ed07244d4d", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/tasks.md", + "kind": "file", + "mode": 33188, + "payload_digest": "4b0a856509eb4b4c0c875e4b74844c45ce162acf255ce69bf88f86d82feae603", + "entry_digest": "3767a753d3d8c88a88e61820f68b82317f5cd533b57cec5ddc798c7d33ef2656", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/testing.md", + "kind": "file", + "mode": 33188, + "payload_digest": "e224b1bc77ea1679aa4cbd34f182846717be905bec43bff555d19f0ba5f75b15", + "entry_digest": "fee23d7cfc7097bb6cda3f52a2a0efd8ae2030ec4c32059529bccb53252bc7e1", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "uitests/viewer.spec.mjs", + "kind": "file", + "mode": 33188, + "payload_digest": "52dd2553472620fd956815792cb22c70980c8d70ea4563eac487ec5eb4f28093", + "entry_digest": "05c24eeea687cd37e72eaa5382b93877334fb1cb53ab1b80babe625a09d0393b", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "web/viewer.html", + "kind": "file", + "mode": 33188, + "payload_digest": "457af08a02075688bdec1285f820bd6e6ff48e54c392a6239d3a0519a21197b2", + "entry_digest": "91188b507e047ae68fe1e96a1980f5b33206532a2cabafec98e7d7883e0b70e4", + "owners": [ + "ThreeMDViewer" + ] + } + ] + }, + "passed": true, + "commands": [ + { + "command": "specsync check --spec ThreeMDViewer --strict", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [ + "REQ-ThreeMDViewer-003", + "REQ-ThreeMDViewer-008" + ] + } + ] +} diff --git a/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/verification.json b/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/verification.json new file mode 100644 index 00000000..c0ca5d92 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/verification.json @@ -0,0 +1,265 @@ +{ + "timestamp": 1791655699, + "commit": "6e8d0bb72dec11684d501cf5cbdc25b2f276b853", + "contract_digest": "c0b8195b500e020a9703bb7edd72d722e7f379c81edd26658c5b1473356c2d6f", + "execution_digest": "8c0c3460123946ea2d50872aab0d8775180c71215745e6aad70feea619be0636", + "workspace_digest": "fde013fc78a6110e0c0b88de16f5f6e7522e6561a06c0a5c5fd273d884ed5278", + "acceptance_input_digest": "7d9ae9868a12971e4916906777f48079ba9be68815774ac81be3530a50a39d7d", + "acceptance_manifest": { + "schema_version": 1, + "entries": [ + { + "path": "apps/sculpt/Tests/RookAppTests/SculptureWorkspaceTests.swift", + "kind": "file", + "mode": 33188, + "payload_digest": "f420db050af7dea627b63e3b33e113377e3919b69d24b7d4e5a97a6bcd06c681", + "entry_digest": "997ec23ca0eacd6cd532071f3da63de1da66eb5a0f11ba6902520e84b68c637b", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-slice", + "kind": "non_file", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "6e52461b16415b74502ade3fb4a9296404661b2d8b9daeb46ccb0ef6236e14f3", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-slice/README.md", + "kind": "file", + "mode": 33188, + "payload_digest": "13d95dffe97a3c30e9dee6f1efcb54e4a4488ea752cf0fd4e5b29f65a060d188", + "entry_digest": "b9bc66178406fb257aa5f3e4877d5d0321add9985f5c3007a834044836661d6c", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-slice/attestation-implementation.json", + "kind": "file", + "mode": 33188, + "payload_digest": "468b5420dfa05a8dc8197da78f3e655f1958010dfbd7c3f501fdb6600cb9392e", + "entry_digest": "1a5090b3eea320641a477feff6a3f738912ff39e7061f3a02dd5c6366adea4e0", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-slice/browser-desktop.png", + "kind": "file", + "mode": 33188, + "payload_digest": "1c0d118ecf45577588d8c38b87bd0e47e64cd754fe5a062bd8cc3c0fa613ded0", + "entry_digest": "1baba7229c0e086399d741f9feaee4b9cc02f660553971c505b66c5790adc626", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-slice/browser-fixtures.log", + "kind": "file", + "mode": 33188, + "payload_digest": "f10d4be8edc27c9a524edcd81e46ee140dd0b4df6d9cdb85ae0140fb4b6635c8", + "entry_digest": "e76d66ef8b3b40781d0204528348e076f0eabbe6cb24bde98bbde1b142e94703", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-slice/browser-phone.png", + "kind": "file", + "mode": 33188, + "payload_digest": "8aff87748688950f14cafc08eb1686f0374928c9802fb3353c817ba43bdec8b4", + "entry_digest": "96a3bcca297f2d2e33fb2b160493447090f34abf38307903a35a143ba4b2802d", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-slice/linux-ci.log", + "kind": "file", + "mode": 33188, + "payload_digest": "38881c05504ec22f137a00375d44dbf1be2b0de44179cdd2c1fbfe522d447911", + "entry_digest": "545f9effeb5f9152d2d3a8b00b1ccd73fd14a84a80ed61cc4ab2631dae0e0b6d", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-slice/mac-browser.log", + "kind": "file", + "mode": 33188, + "payload_digest": "8ebaa89f01dd7d5788af9c59c56c8b9c3ff95e49b1da0e03650d668d1b438238", + "entry_digest": "a27a45c3fe71298b77664fc463109ead0c736995273d468694b29b4cb4dfe877", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-slice/native-full.log", + "kind": "file", + "mode": 33188, + "payload_digest": "b9e5a3a50d6312dc11270f7f9301d866e93f68a47564fce94561defa120283fd", + "entry_digest": "6f297fd464f56f2d3b13a8cd35833a13eea22a06e76c651e272674021d61aaec", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-slice/native-parity.log", + "kind": "file", + "mode": 33188, + "payload_digest": "bcc8b1c69e429ffad87ee12c09e236ec8fd294c578ae6f490d8e956b26b4b2ee", + "entry_digest": "667d6ed3703135b5b3d6e506b2260b74571af18643bb88d1e90c26e6a83bd1ba", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-slice/phone.log", + "kind": "file", + "mode": 33188, + "payload_digest": "d1403a073d5817356c3768ed70aa4e1b5dbc71f71da444bef8fbe9a2d64ff98d", + "entry_digest": "b31bf683f4d3247f6a8c7a6f0a53ea82cbfa84cef0aedb1bad1c9ba7fcd594db", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-slice/provenance-implementation.json", + "kind": "file", + "mode": 33188, + "payload_digest": "da4afbc0b7f1c965477d18c3695e3490cc9702a66b64dd21322d5888ba3672a4", + "entry_digest": "cd75a22b45046443d0af903924a889ce6fbb35717ab7fa5715e34e1fa2a762a4", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-slice/sculpt-axis.png", + "kind": "file", + "mode": 33188, + "payload_digest": "e2e207fd6f7e300bf39da0b9d46351f778de6c80e1899292dc2ae528474c818b", + "entry_digest": "05b92d61249cd8588ead868c6cb6ce9b19a1bed90031efdf746e02d5be461baf", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-slice/slice-parity.json", + "kind": "file", + "mode": 33188, + "payload_digest": "e62169ce9cebe521a5cdb0e202c522010d38875c0968d5906e0c8244224b0bbb", + "entry_digest": "3b5d98993c5c88fee47ca5302a6ed1357a3fdacd833f8d7e875a3d1e5b2a2ced", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-slice/trust-implementation.log", + "kind": "file", + "mode": 33188, + "payload_digest": "263cde4e72f922ab16278ece04a6d90178b08afbf6012c6fb7b3d58a3914f236", + "entry_digest": "ea4a45ca2723e4279d40d76807713cbebf38630c22b8cf4c7a9932e030eb42f4", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "hi/tools.md", + "kind": "file", + "mode": 33188, + "payload_digest": "cd530f076ed449b2dcd994f9178fcb104f4460e44a12042200b42bf6ca6d6306", + "entry_digest": "a13f216eb32a3671d7563024082ab76eb471bdd7a2ddb3c3398b672b05354a70", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "specs/ThreeMDViewer/ThreeMDViewer.spec.md", + "kind": "file", + "mode": 33188, + "payload_digest": "3b3b09952c692c501a98d6520fb8a82f5126ab9b05d64f6634b50cbae3620ae6", + "entry_digest": "64224b139df2b01fdd0db61c4817d9a836030dbf2667bda60529f6a61be627b4", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/context.md", + "kind": "file", + "mode": 33188, + "payload_digest": "a0011f2d32b7dce6370e015fefcf09acbcf52578e82a97e56def17e0e0fbed52", + "entry_digest": "e020a4426da69e6b24dd3025c95afd9a88cf073bca235f86ad9104e1de81c7f7", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/requirements.md", + "kind": "file", + "mode": 33188, + "payload_digest": "96612855952a65a5e6b623e2b5d21e9dd8f4ea88c92c0e8ef392e3b826b81f94", + "entry_digest": "5caf30173677b31dcf1119406f03f7dd5a1721487ef58ceacb8d22ed07244d4d", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/tasks.md", + "kind": "file", + "mode": 33188, + "payload_digest": "4b0a856509eb4b4c0c875e4b74844c45ce162acf255ce69bf88f86d82feae603", + "entry_digest": "3767a753d3d8c88a88e61820f68b82317f5cd533b57cec5ddc798c7d33ef2656", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/testing.md", + "kind": "file", + "mode": 33188, + "payload_digest": "e224b1bc77ea1679aa4cbd34f182846717be905bec43bff555d19f0ba5f75b15", + "entry_digest": "fee23d7cfc7097bb6cda3f52a2a0efd8ae2030ec4c32059529bccb53252bc7e1", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "uitests/viewer.spec.mjs", + "kind": "file", + "mode": 33188, + "payload_digest": "52dd2553472620fd956815792cb22c70980c8d70ea4563eac487ec5eb4f28093", + "entry_digest": "05c24eeea687cd37e72eaa5382b93877334fb1cb53ab1b80babe625a09d0393b", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "web/viewer.html", + "kind": "file", + "mode": 33188, + "payload_digest": "457af08a02075688bdec1285f820bd6e6ff48e54c392a6239d3a0519a21197b2", + "entry_digest": "91188b507e047ae68fe1e96a1980f5b33206532a2cabafec98e7d7883e0b70e4", + "owners": [ + "ThreeMDViewer" + ] + } + ] + }, + "passed": true, + "commands": [ + { + "command": "specsync check --spec ThreeMDViewer --strict", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [ + "REQ-ThreeMDViewer-003", + "REQ-ThreeMDViewer-008" + ] +} diff --git a/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/accepted-state.json b/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/accepted-state.json new file mode 100644 index 00000000..3f209d97 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/accepted-state.json @@ -0,0 +1,58 @@ +{ + "schema_version": 1, + "workflow_version": 2, + "workflow_origin_version": 2, + "id": "keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan", + "slug": "keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan", + "title": "Keep Sculpt and web cube cameras in parity with unrestricted orbit and screen-space pan", + "description": "Keep Sculpt and web cube cameras in parity with unrestricted orbit and screen-space pan", + "kind": "feature", + "state": "accepted", + "canonical_applied": true, + "base_commit": "fefd8316adfff3af8bdb87d26b4a417650540b56", + "created_at": 1791643666, + "updated_at": 1791649769, + "affected_specs": [ + "ThreeMDViewer" + ], + "affected_paths": [ + "[\"web/viewer.html\"", + "\"uitests/viewer.spec.mjs\"", + "\"hi/tools.md\"", + "\"specs/ThreeMDViewer\"", + "\"apps/sculpt/Sources/RookSculpture/SculptureProjection.swift\"", + "\"apps/sculpt/Sources/RookRendering/SculptureVoxelGeometry.swift\"", + "\"apps/sculpt/Sources/RookRendering/SculptureLiveVoxelView.swift\"", + "\"apps/sculpt/Sources/RookApp/SculptureCanvasPointer.swift\"", + "\"apps/sculpt/Sources/RookApp/SculptureViewport.swift\"", + "\"apps/sculpt/Sources/RookApp/SculptureEditor.swift\"", + "\"apps/sculpt/Tests\"", + "\"apps/sculpt/specs\"", + "\"apps/sculpt/hi\"", + "\"docs/evidence/viewer-camera\"]" + ], + "no_spec_change": false, + "no_spec_change_rationale": null, + "acceptance_criteria": [ + "Both the web cube viewer and Sculpt volume canvas orbit through complete horizontal and vertical turns, using the same continuous camera basis at the poles and upside down. Drag sensitivity is 0.008 radians per point; web yaw is the negative of native yaw to account for its coordinate convention.", + "Both volume cameras support screen-space pan without changing the document, mesh, slice, paint history or geometry revision. Native Shift-left, middle and right dragging pan; an explicit Pan button works in Orbit. Native scroll zoom and trackpad magnification respond proportionally. Browser Pan, modified mouse dragging and two-finger pan/pinch provide the equivalent controls.", + "Zoom stays between 0.5 and 2 in both views. Fit restores the default matched pose (native yaw -0.6 / web yaw 0.6, pitch 0.35), zoom 1 and zero pan. The native CPU cube/ASCII projection, live GPU camera and picking all honor the same orbit and pan.", + "Shared asymmetric fixture receipts compare camera bases and screen projections across native and browser views, including pole crossings, upside-down and panned cameras. Picking chooses the nearest cube after those movements and camera changes reuse geometry. Mac native regressions and browser Chromium/WebKit regressions cover the controls.", + "Keep native painting, stroke freezing, CPU/export budgets and the browser one-draw cube mesh, colors, axes and bounded grid behavior. Keep app and viewer specifications and human intent synchronized. Sparse-world Explore, storage formats, parser APIs, package releases and trust policies remain outside this camera change." + ], + "selected_artifacts": [ + "context", + "requirements", + "plan", + "tasks", + "testing", + "docs", + "design", + "research" + ], + "dependencies": [], + "answers": { + "architecture_risk": "yes", + "public_contract": "yes" + } +} diff --git a/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/approvals.json b/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/approvals.json new file mode 100644 index 00000000..c5cd17dd --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/approvals.json @@ -0,0 +1,63 @@ +{ + "approvals": [ + { + "gate": "definition", + "actor": "user:0xLeif", + "timestamp": 1791644304, + "digest": "c2c55f58dfdb8194f5d97358776f7e3321fbbb3fc6a127b3a990cc625f0cfcab", + "note": "Leif explicitly selected Approve camera parity and verified closure on 2026-10-10. This records that approval only; the subsequently requested axis gizmo will have its own defined scope.", + "approved_scope": { + "schema_version": 1, + "change_id": "keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan", + "title": "Keep Sculpt and web cube cameras in parity with unrestricted orbit and screen-space pan", + "description": "Keep Sculpt and web cube cameras in parity with unrestricted orbit and screen-space pan", + "kind": "feature", + "affected_specs": [ + "ThreeMDViewer" + ], + "affected_paths": [ + "\"apps/sculpt/Sources/RookApp/SculptureCanvasPointer.swift\"", + "\"apps/sculpt/Sources/RookApp/SculptureEditor.swift\"", + "\"apps/sculpt/Sources/RookApp/SculptureViewport.swift\"", + "\"apps/sculpt/Sources/RookRendering/SculptureLiveVoxelView.swift\"", + "\"apps/sculpt/Sources/RookRendering/SculptureVoxelGeometry.swift\"", + "\"apps/sculpt/Sources/RookSculpture/SculptureProjection.swift\"", + "\"apps/sculpt/Tests\"", + "\"apps/sculpt/hi\"", + "\"apps/sculpt/specs\"", + "\"docs/evidence/viewer-camera\"]", + "\"hi/tools.md\"", + "\"specs/ThreeMDViewer\"", + "\"uitests/viewer.spec.mjs\"", + "[\"web/viewer.html\"" + ], + "no_spec_change": false, + "no_spec_change_rationale": null, + "acceptance_criteria": [ + "Both the web cube viewer and Sculpt volume canvas orbit through complete horizontal and vertical turns, using the same continuous camera basis at the poles and upside down. Drag sensitivity is 0.008 radians per point; web yaw is the negative of native yaw to account for its coordinate convention.", + "Both volume cameras support screen-space pan without changing the document, mesh, slice, paint history or geometry revision. Native Shift-left, middle and right dragging pan; an explicit Pan button works in Orbit. Native scroll zoom and trackpad magnification respond proportionally. Browser Pan, modified mouse dragging and two-finger pan/pinch provide the equivalent controls.", + "Keep native painting, stroke freezing, CPU/export budgets and the browser one-draw cube mesh, colors, axes and bounded grid behavior. Keep app and viewer specifications and human intent synchronized. Sparse-world Explore, storage formats, parser APIs, package releases and trust policies remain outside this camera change.", + "Shared asymmetric fixture receipts compare camera bases and screen projections across native and browser views, including pole crossings, upside-down and panned cameras. Picking chooses the nearest cube after those movements and camera changes reuse geometry. Mac native regressions and browser Chromium/WebKit regressions cover the controls.", + "Zoom stays between 0.5 and 2 in both views. Fit restores the default matched pose (native yaw -0.6 / web yaw 0.6, pitch 0.35), zoom 1 and zero pan. The native CPU cube/ASCII projection, live GPU camera and picking all honor the same orbit and pan." + ], + "dependencies": [], + "supersedes": [], + "answers": { + "architecture_risk": "yes", + "public_contract": "yes" + } + }, + "approved_delta_digests": { + "ThreeMDViewer": "8232bf97020dfd9d2395186bed985f2972ef59b6d46d94d61efcb68fe110f8c2" + } + }, + { + "gate": "finalization", + "actor": "specsync:finalization", + "timestamp": 1791649769, + "digest": "2684681bd1cb31b3eefa62fb43edb698ddf4ae64d7a91cd828afa886bcecfb17", + "note": "Same-PR finalization closing digest" + } + ], + "reopenings": [] +} diff --git a/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/change.md b/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/change.md new file mode 100644 index 00000000..fa33ddc5 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/change.md @@ -0,0 +1,28 @@ +--- +id: keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan +state: archived +type: feature +base_commit: fefd8316adfff3af8bdb87d26b4a417650540b56 +--- + +# Keep Sculpt and web cube cameras in parity with unrestricted orbit and screen-space pan + +## Intent + +Keep Sculpt and web cube cameras in parity with unrestricted orbit and screen-space pan + +## Affected Canonical Specs + +- `ThreeMDViewer` + +## Acceptance Criteria + +- Both the web cube viewer and Sculpt volume canvas orbit through complete horizontal and vertical turns, using the same continuous camera basis at the poles and upside down. Drag sensitivity is 0.008 radians per point; web yaw is the negative of native yaw to account for its coordinate convention. +- Both volume cameras support screen-space pan without changing the document, mesh, slice, paint history or geometry revision. Native Shift-left, middle and right dragging pan; an explicit Pan button works in Orbit. Native scroll zoom and trackpad magnification respond proportionally. Browser Pan, modified mouse dragging and two-finger pan/pinch provide the equivalent controls. +- Zoom stays between 0.5 and 2 in both views. Fit restores the default matched pose (native yaw -0.6 / web yaw 0.6, pitch 0.35), zoom 1 and zero pan. The native CPU cube/ASCII projection, live GPU camera and picking all honor the same orbit and pan. +- Shared asymmetric fixture receipts compare camera bases and screen projections across native and browser views, including pole crossings, upside-down and panned cameras. Picking chooses the nearest cube after those movements and camera changes reuse geometry. Mac native regressions and browser Chromium/WebKit regressions cover the controls. +- Keep native painting, stroke freezing, CPU/export budgets and the browser one-draw cube mesh, colors, axes and bounded grid behavior. Keep app and viewer specifications and human intent synchronized. Sparse-world Explore, storage formats, parser APIs, package releases and trust policies remain outside this camera change. + +## No-spec Rationale + +Not applicable diff --git a/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/context.md b/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/context.md new file mode 100644 index 00000000..78becc6d --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/context.md @@ -0,0 +1,12 @@ +--- +change: keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan +artifact: context +--- + +# Context + +Leif requested full 360-degree rotation and easier movement, then explicitly requested parity with Rook / Sculpt.3md. The viewer camera preview is prepared locally. Native source still has a vertical clamp and lacks volume pan. This draft extends the earlier viewer-only scope to the native volume camera. Human definition approval, native implementation, verification and closure remain pending. + +Actor: agent:codex. No independent human diff review or signed provenance is claimed. + +Current implementation and shared fixture receipts are in `docs/evidence/viewer-camera/`. Live pan and Fit preserved the native scene and slice. Default utility-camera framing preserves historical example images. Final full suites, Trust and lifecycle closure remain pending; the separate gizmo definition is not approved. diff --git a/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/deltas/ThreeMDViewer.md b/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/deltas/ThreeMDViewer.md new file mode 100644 index 00000000..6b7d1fd9 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/deltas/ThreeMDViewer.md @@ -0,0 +1,15 @@ +# ThreeMDViewer delta + +## ADDED + +### REQUIREMENT REQ-ThreeMDViewer-006 + +The browser and Sculpt volume camera SHALL expose the same full-turn orbit, screen-space pan, bounded proportional zoom, default Fit pose and camera-correct nearest-cube picking, with matched camera basis and documented coordinate conversion. + +Acceptance Criteria: + +- Both the web cube viewer and Sculpt volume canvas orbit through complete horizontal and vertical turns, using the same continuous camera basis at the poles and upside down. Drag sensitivity is 0.008 radians per point; web yaw is the negative of native yaw to account for its coordinate convention. +- Both volume cameras support screen-space pan without changing the document, mesh, slice, paint history or geometry revision. Native Shift-left, middle and right dragging pan; an explicit Pan button works in Orbit. Native scroll zoom and trackpad magnification respond proportionally. Browser Pan, modified mouse dragging and two-finger pan/pinch provide the equivalent controls. +- Zoom stays between 0.5 and 2 in both views. Fit restores the default matched pose (native yaw -0.6 / web yaw 0.6, pitch 0.35), zoom 1 and zero pan. The native CPU cube/ASCII projection, live GPU camera and picking all honor the same orbit and pan. +- Shared asymmetric fixture receipts compare camera bases and screen projections across native and browser views, including pole crossings, upside-down and panned cameras. Picking chooses the nearest cube after those movements and camera changes reuse geometry. Mac native regressions and browser Chromium/WebKit regressions cover the controls. +- Keep native painting, stroke freezing, CPU/export budgets and the browser one-draw cube mesh, colors, axes and bounded grid behavior. Keep app and viewer specifications and human intent synchronized. Sparse-world Explore, storage formats, parser APIs, package releases and trust policies remain outside this camera change. diff --git a/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/design.md b/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/design.md new file mode 100644 index 00000000..168aa7b0 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/design.md @@ -0,0 +1,8 @@ +--- +change: keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan +artifact: design +--- + +# Design + +Keep the current stage colors, glyph fills, edges and selected-slice gold. Orbit and Pan are camera tools in the existing control strip. Browser controls stay below the drawing and keep phone touch targets usable. Native Shift, middle and right dragging provide pan even while Paint is selected; such gestures must never paint. A native Pan toggle applies to the Orbit canvas. Use native local points and browser CSS pixels. Both cameras use 0.008 radians per drag point, zoom 0.5 through 2, and default pitch 0.35. Native yaw -0.6 maps to browser yaw +0.6. Native ASCII and exports follow the same session camera. diff --git a/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/docs.md b/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/docs.md new file mode 100644 index 00000000..0f34839b --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/docs.md @@ -0,0 +1,8 @@ +--- +change: keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan +artifact: docs +--- + +# Docs + +Update ThreeMDViewer and native RookSculpture, RookRendering and RookApp camera contracts. Update VIEWER-6 and native rendering intent for full orbit and pan after human definition approval. Keep file formats, library APIs, package versions, parser fixtures and provenance policies unchanged. Evidence belongs under docs/evidence/viewer-camera. diff --git a/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/finalization.json b/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/finalization.json new file mode 100644 index 00000000..ef28fa2d --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/finalization.json @@ -0,0 +1,12 @@ +{ + "schema_version": 2, + "change_id": "keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan", + "implementation_commit": "2cb08248efb492b03de8a2bb300b00383f732945", + "implementation_tree": "7294f5f1d0ec7267960d55e9f263ea1a376284e1", + "contract_digest": "c2c55f58dfdb8194f5d97358776f7e3321fbbb3fc6a127b3a990cc625f0cfcab", + "workspace_digest": "94bd7478dfb8735a51286b1c04445028dc910df8754b57775bc06773797a4420", + "closing_digest": "2684681bd1cb31b3eefa62fb43edb698ddf4ae64d7a91cd828afa886bcecfb17", + "review_digest": "9146e34b065322e28f32227c7074ec5e9d32296c5d7858eef602beb34e24fcc1", + "finalization_digest": "fe89dd6540b16789696102efc62365f285aafcd7b44ab7dc6a03290d58c55076", + "timestamp": 1791649769 +} diff --git a/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/lesson-bundle.md b/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/lesson-bundle.md new file mode 100644 index 00000000..22e53734 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/lesson-bundle.md @@ -0,0 +1,58 @@ +# Lesson bundle — keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan + +Material for folding this change's lessons into the affected specs' `context.md`. +Synthesise from what actually happened below; do not restate the change description. + +## What this change was + +- **Title**: Keep Sculpt and web cube cameras in parity with unrestricted orbit and screen-space pan +- **Kind**: Feature +- **Specs**: ThreeMDViewer +- **Paths**: ["web/viewer.html", "uitests/viewer.spec.mjs", "hi/tools.md", "specs/ThreeMDViewer", "apps/sculpt/Sources/RookSculpture/SculptureProjection.swift", "apps/sculpt/Sources/RookRendering/SculptureVoxelGeometry.swift", "apps/sculpt/Sources/RookRendering/SculptureLiveVoxelView.swift", "apps/sculpt/Sources/RookApp/SculptureCanvasPointer.swift", "apps/sculpt/Sources/RookApp/SculptureViewport.swift", "apps/sculpt/Sources/RookApp/SculptureEditor.swift", "apps/sculpt/Tests", "apps/sculpt/specs", "apps/sculpt/hi", "docs/evidence/viewer-camera"] +- **Acceptance**: Both the web cube viewer and Sculpt volume canvas orbit through complete horizontal and vertical turns, using the same continuous camera basis at the poles and upside down. Drag sensitivity is 0.008 radians per point; web yaw is the negative of native yaw to account for its coordinate convention. +- **Acceptance**: Both volume cameras support screen-space pan without changing the document, mesh, slice, paint history or geometry revision. Native Shift-left, middle and right dragging pan; an explicit Pan button works in Orbit. Native scroll zoom and trackpad magnification respond proportionally. Browser Pan, modified mouse dragging and two-finger pan/pinch provide the equivalent controls. +- **Acceptance**: Zoom stays between 0.5 and 2 in both views. Fit restores the default matched pose (native yaw -0.6 / web yaw 0.6, pitch 0.35), zoom 1 and zero pan. The native CPU cube/ASCII projection, live GPU camera and picking all honor the same orbit and pan. +- **Acceptance**: Shared asymmetric fixture receipts compare camera bases and screen projections across native and browser views, including pole crossings, upside-down and panned cameras. Picking chooses the nearest cube after those movements and camera changes reuse geometry. Mac native regressions and browser Chromium/WebKit regressions cover the controls. +- **Acceptance**: Keep native painting, stroke freezing, CPU/export budgets and the browser one-draw cube mesh, colors, axes and bounded grid behavior. Keep app and viewer specifications and human intent synchronized. Sparse-world Explore, storage formats, parser APIs, package releases and trust policies remain outside this camera change. + +## Evidence + +- Verification commit: `2cb08248efb492b03de8a2bb300b00383f732945` +- Base commit: `fefd8316adfff3af8bdb87d26b4a417650540b56` +- Verified by: `specsync check --spec ThreeMDViewer` + +## From the change's context.md + +# Context + +Leif requested full 360-degree rotation and easier movement, then explicitly requested parity with Rook / Sculpt.3md. The viewer camera preview is prepared locally. Native source still has a vertical clamp and lacks volume pan. This draft extends the earlier viewer-only scope to the native volume camera. Human definition approval, native implementation, verification and closure remain pending. + +Actor: agent:codex. No independent human diff review or signed provenance is claimed. + +Current implementation and shared fixture receipts are in `docs/evidence/viewer-camera/`. Live pan and Fit preserved the native scene and slice. Default utility-camera framing preserves historical example images. Final full suites, Trust and lifecycle closure remain pending; the separate gizmo definition is not approved. + +## From the change's design.md + +# Design + +Keep the current stage colors, glyph fills, edges and selected-slice gold. Orbit and Pan are camera tools in the existing control strip. Browser controls stay below the drawing and keep phone touch targets usable. Native Shift, middle and right dragging provide pan even while Paint is selected; such gestures must never paint. A native Pan toggle applies to the Orbit canvas. Use native local points and browser CSS pixels. Both cameras use 0.008 radians per drag point, zoom 0.5 through 2, and default pitch 0.35. Native yaw -0.6 maps to browser yaw +0.6. Native ASCII and exports follow the same session camera. + +## From the change's testing.md + +# Testing + +Browser regressions cover complete turns and finite matrices through both poles, screen-space pan with unchanged yaw/pitch/source/slice, mouse-button/modifier controls, proportional wheel input, touch pinch/pan and cancellation, translated nearest-cube picking, Fit, bounded zoom, no camera geometry upload, and 320-pixel phone layout. Native regressions cover finite sanitized camera inputs, scalar/prepared/live projection agreement across matching full-turn/panned cases, geometry reuse and native pointer forwarding. Retain actual verification receipts; no current camera suite result or final Trust verdict is claimed yet. + +Current camera implementation: Mac Chromium/WebKit viewer 106 passed; Linux projection/phone selection 4 passed; native camera/input and unchanged math preview selection 23 passed in four suites. Root/native strict specs and Hi pass. Full current Linux/native runs and pinned Trust remain pending. See `docs/evidence/viewer-camera/README.md`. The separately requested axis gizmo remains an unapproved draft. + +## Requirement evidence + +| Requirement | Canonical | Evidence | +| --- | --- | --- | +| REQ-ThreeMDViewer-006 | REQ-ThreeMDViewer-006 | `uitests/viewer.spec.mjs` full camera turns, pan tools, two-finger gesture and shared native parity fixture tests; `apps/sculpt/Tests/RookRenderingTests/CameraParityTests.swift`, `apps/sculpt/Tests/RookRenderingTests/SculptureLiveVoxelTests.swift` and `apps/sculpt/Tests/RookAppTests/SculptureCanvasPointerTests.swift`; shared `docs/evidence/viewer-camera/camera-parity.json` and actual receipts in `docs/evidence/viewer-camera/README.md`. | + +Full native CI selection completed: 635 tests in 54 suites passed. Full Linux UI completed: 197 passed and one heavy-use WebKit test passed on retry, with eight existing skips; the heavy-use test passed alone on recheck. No new skips or relaxed assertions. Current camera implementation source matches commit c94e075164664cf724115f0a7e02cc53905a3114. Final pinned Trust, review and archive remain pending. + +## Where these lessons go + +- `specs/ThreeMDViewer/context.md` diff --git a/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/plan.md b/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/plan.md new file mode 100644 index 00000000..d736b9bb --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/plan.md @@ -0,0 +1,12 @@ +--- +change: keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan +artifact: plan +--- + +# Plan + +1. Keep the existing bounded cube meshes and native editing semantics. +2. Add session-only native pan coordinates and finite normalized camera inputs; share those inputs across ASCII, CPU cube projection and GPU camera transforms. +3. Add volume Pan and modified mouse dragging through the existing native pointer bridge, plus native scroll and magnification. Fit resets the camera. Match browser sensitivity, zoom bounds and pose. +4. Compare shared asymmetric projection cases and pole/pan picking. Run browser and native tests, synchronize contracts and intent, and record actual evidence. +5. Complete each approved lifecycle record with current verification and truthful agent review; publish only the existing feature PR. Leif retains merge authority. diff --git a/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/requirements.md b/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/requirements.md new file mode 100644 index 00000000..9222bb6d --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/requirements.md @@ -0,0 +1,18 @@ +--- +change: keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan +artifact: requirements +--- + +# Requirements + +### REQ-ThreeMDViewer-006 + +The browser and Sculpt volume camera SHALL expose the same full-turn orbit, screen-space pan, bounded proportional zoom, default Fit pose and camera-correct nearest-cube picking, with matched camera basis and documented coordinate conversion. + +Acceptance Criteria: + +- Both the web cube viewer and Sculpt volume canvas orbit through complete horizontal and vertical turns, using the same continuous camera basis at the poles and upside down. Drag sensitivity is 0.008 radians per point; web yaw is the negative of native yaw to account for its coordinate convention. +- Both volume cameras support screen-space pan without changing the document, mesh, slice, paint history or geometry revision. Native Shift-left, middle and right dragging pan; an explicit Pan button works in Orbit. Native scroll zoom and trackpad magnification respond proportionally. Browser Pan, modified mouse dragging and two-finger pan/pinch provide the equivalent controls. +- Zoom stays between 0.5 and 2 in both views. Fit restores the default matched pose (native yaw -0.6 / web yaw 0.6, pitch 0.35), zoom 1 and zero pan. The native CPU cube/ASCII projection, live GPU camera and picking all honor the same orbit and pan. +- Shared asymmetric fixture receipts compare camera bases and screen projections across native and browser views, including pole crossings, upside-down and panned cameras. Picking chooses the nearest cube after those movements and camera changes reuse geometry. Mac native regressions and browser Chromium/WebKit regressions cover the controls. +- Keep native painting, stroke freezing, CPU/export budgets and the browser one-draw cube mesh, colors, axes and bounded grid behavior. Keep app and viewer specifications and human intent synchronized. Sparse-world Explore, storage formats, parser APIs, package releases and trust policies remain outside this camera change. diff --git a/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/research.md b/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/research.md new file mode 100644 index 00000000..a67aa233 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/research.md @@ -0,0 +1,8 @@ +--- +change: keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan +artifact: research +--- + +# Research + +Inspected SculptureProjection.swift, SculptureVoxelGeometry.swift, SculptureLiveVoxelView.swift and SculptureViewport.swift. Native pitch is clamped to +/-1.4 and browser pitch was clamped to +/-1.2. Native and browser yaw have opposite signs due to coordinate conventions. Native distance is three volume extents and scale is 0.68 of the smaller viewport dimension per extent. The browser retains its fit margin for small cubes. World Explore has intentional upright navigation and is excluded from this volume-camera change. The native live and scalar render paths must move together so painting and exports remain consistent. diff --git a/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/review-attempts.json b/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/review-attempts.json new file mode 100644 index 00000000..babff0e7 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/review-attempts.json @@ -0,0 +1,21 @@ +{ + "schema_version": 1, + "reviews": [ + { + "schema_version": 2, + "change_id": "keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan", + "reviewer": "agent:codex", + "provenance": { + "schema_version": 1, + "provider": "github_actions_check", + "required_check": "SpecSync scoped review" + }, + "verdict": "pass", + "implementation_commit": "2cb08248efb492b03de8a2bb300b00383f732945", + "contract_digest": "c2c55f58dfdb8194f5d97358776f7e3321fbbb3fc6a127b3a990cc625f0cfcab", + "execution_digest": "2bb9d898086382e584700b0f1790c04fa97f14a030ffa1d3bc9df50113287a57", + "workspace_digest": "94bd7478dfb8735a51286b1c04445028dc910df8754b57775bc06773797a4420", + "timestamp": 1791649644 + } + ] +} diff --git a/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/review.json b/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/review.json new file mode 100644 index 00000000..f8b0fb9f --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/review.json @@ -0,0 +1,16 @@ +{ + "schema_version": 2, + "change_id": "keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan", + "reviewer": "agent:codex", + "provenance": { + "schema_version": 1, + "provider": "github_actions_check", + "required_check": "SpecSync scoped review" + }, + "verdict": "pass", + "implementation_commit": "2cb08248efb492b03de8a2bb300b00383f732945", + "contract_digest": "c2c55f58dfdb8194f5d97358776f7e3321fbbb3fc6a127b3a990cc625f0cfcab", + "execution_digest": "2bb9d898086382e584700b0f1790c04fa97f14a030ffa1d3bc9df50113287a57", + "workspace_digest": "94bd7478dfb8735a51286b1c04445028dc910df8754b57775bc06773797a4420", + "timestamp": 1791649644 +} diff --git a/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/state.json b/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/state.json new file mode 100644 index 00000000..2055d8c3 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/state.json @@ -0,0 +1,58 @@ +{ + "schema_version": 1, + "workflow_version": 2, + "workflow_origin_version": 2, + "id": "keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan", + "slug": "keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan", + "title": "Keep Sculpt and web cube cameras in parity with unrestricted orbit and screen-space pan", + "description": "Keep Sculpt and web cube cameras in parity with unrestricted orbit and screen-space pan", + "kind": "feature", + "state": "archived", + "canonical_applied": true, + "base_commit": "fefd8316adfff3af8bdb87d26b4a417650540b56", + "created_at": 1791643666, + "updated_at": 1791649840, + "affected_specs": [ + "ThreeMDViewer" + ], + "affected_paths": [ + "[\"web/viewer.html\"", + "\"uitests/viewer.spec.mjs\"", + "\"hi/tools.md\"", + "\"specs/ThreeMDViewer\"", + "\"apps/sculpt/Sources/RookSculpture/SculptureProjection.swift\"", + "\"apps/sculpt/Sources/RookRendering/SculptureVoxelGeometry.swift\"", + "\"apps/sculpt/Sources/RookRendering/SculptureLiveVoxelView.swift\"", + "\"apps/sculpt/Sources/RookApp/SculptureCanvasPointer.swift\"", + "\"apps/sculpt/Sources/RookApp/SculptureViewport.swift\"", + "\"apps/sculpt/Sources/RookApp/SculptureEditor.swift\"", + "\"apps/sculpt/Tests\"", + "\"apps/sculpt/specs\"", + "\"apps/sculpt/hi\"", + "\"docs/evidence/viewer-camera\"]" + ], + "no_spec_change": false, + "no_spec_change_rationale": null, + "acceptance_criteria": [ + "Both the web cube viewer and Sculpt volume canvas orbit through complete horizontal and vertical turns, using the same continuous camera basis at the poles and upside down. Drag sensitivity is 0.008 radians per point; web yaw is the negative of native yaw to account for its coordinate convention.", + "Both volume cameras support screen-space pan without changing the document, mesh, slice, paint history or geometry revision. Native Shift-left, middle and right dragging pan; an explicit Pan button works in Orbit. Native scroll zoom and trackpad magnification respond proportionally. Browser Pan, modified mouse dragging and two-finger pan/pinch provide the equivalent controls.", + "Zoom stays between 0.5 and 2 in both views. Fit restores the default matched pose (native yaw -0.6 / web yaw 0.6, pitch 0.35), zoom 1 and zero pan. The native CPU cube/ASCII projection, live GPU camera and picking all honor the same orbit and pan.", + "Shared asymmetric fixture receipts compare camera bases and screen projections across native and browser views, including pole crossings, upside-down and panned cameras. Picking chooses the nearest cube after those movements and camera changes reuse geometry. Mac native regressions and browser Chromium/WebKit regressions cover the controls.", + "Keep native painting, stroke freezing, CPU/export budgets and the browser one-draw cube mesh, colors, axes and bounded grid behavior. Keep app and viewer specifications and human intent synchronized. Sparse-world Explore, storage formats, parser APIs, package releases and trust policies remain outside this camera change." + ], + "selected_artifacts": [ + "context", + "requirements", + "plan", + "tasks", + "testing", + "docs", + "design", + "research" + ], + "dependencies": [], + "answers": { + "architecture_risk": "yes", + "public_contract": "yes" + } +} diff --git a/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/tasks.md b/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/tasks.md new file mode 100644 index 00000000..3aa57a84 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/tasks.md @@ -0,0 +1,14 @@ +--- +change: keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan +artifact: tasks +--- + +# Tasks + +- [x] Approve the complete cross-app camera definition. +- [x] Match native and browser orbit, pan, zoom and Fit behavior. +- [x] Verify projection and picking parity through poles and panning. +- [x] Run relevant native and browser regressions and record evidence. +- [x] Synchronize contracts and human intent. + +Lifecycle verification, truthful scoped review and the authorized archive remain pending. These are subsequent tool gates; no completion is claimed here. diff --git a/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/testing.md b/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/testing.md new file mode 100644 index 00000000..79aac3c0 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/testing.md @@ -0,0 +1,18 @@ +--- +change: keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan +artifact: testing +--- + +# Testing + +Browser regressions cover complete turns and finite matrices through both poles, screen-space pan with unchanged yaw/pitch/source/slice, mouse-button/modifier controls, proportional wheel input, touch pinch/pan and cancellation, translated nearest-cube picking, Fit, bounded zoom, no camera geometry upload, and 320-pixel phone layout. Native regressions cover finite sanitized camera inputs, scalar/prepared/live projection agreement across matching full-turn/panned cases, geometry reuse and native pointer forwarding. Retain actual verification receipts; no current camera suite result or final Trust verdict is claimed yet. + +Current camera implementation: Mac Chromium/WebKit viewer 106 passed; Linux projection/phone selection 4 passed; native camera/input and unchanged math preview selection 23 passed in four suites. Root/native strict specs and Hi pass. Full current Linux/native runs and pinned Trust remain pending. See `docs/evidence/viewer-camera/README.md`. The separately requested axis gizmo remains an unapproved draft. + +## Requirement evidence + +| Requirement | Canonical | Evidence | +| --- | --- | --- | +| REQ-ThreeMDViewer-006 | REQ-ThreeMDViewer-006 | `uitests/viewer.spec.mjs` full camera turns, pan tools, two-finger gesture and shared native parity fixture tests; `apps/sculpt/Tests/RookRenderingTests/CameraParityTests.swift`, `apps/sculpt/Tests/RookRenderingTests/SculptureLiveVoxelTests.swift` and `apps/sculpt/Tests/RookAppTests/SculptureCanvasPointerTests.swift`; shared `docs/evidence/viewer-camera/camera-parity.json` and actual receipts in `docs/evidence/viewer-camera/README.md`. | + +Full native CI selection completed: 635 tests in 54 suites passed. Full Linux UI completed: 197 passed and one heavy-use WebKit test passed on retry, with eight existing skips; the heavy-use test passed alone on recheck. No new skips or relaxed assertions. Current camera implementation source matches commit c94e075164664cf724115f0a7e02cc53905a3114. Final pinned Trust, review and archive remain pending. diff --git a/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/verification-attempts.json b/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/verification-attempts.json new file mode 100644 index 00000000..87b63300 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/verification-attempts.json @@ -0,0 +1,309 @@ +{ + "schema_version": 1, + "attempts": [ + { + "timestamp": 1791647422, + "commit": "1fc3cc740e20fe70ad96ef6e9db307c6ec8eb174", + "contract_digest": "c2c55f58dfdb8194f5d97358776f7e3321fbbb3fc6a127b3a990cc625f0cfcab", + "execution_digest": "5acb1a7045491a5ff67a0ebe1a535f2a2888b2d2b7a5303fcbe4d72658235264", + "workspace_digest": "ef8a0fc2fa7139e0ccf26ac905fa04ce3affe65d3822c8176054d6fa23b96005", + "passed": true, + "commands": [ + { + "command": "specsync check --spec ThreeMDViewer", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [ + "REQ-ThreeMDViewer-006" + ] + }, + { + "timestamp": 1791647446, + "commit": "9cd91be9c8c9951f8a89b422a2fe935035b4df40", + "contract_digest": "c2c55f58dfdb8194f5d97358776f7e3321fbbb3fc6a127b3a990cc625f0cfcab", + "execution_digest": "5acb1a7045491a5ff67a0ebe1a535f2a2888b2d2b7a5303fcbe4d72658235264", + "workspace_digest": "ef8a0fc2fa7139e0ccf26ac905fa04ce3affe65d3822c8176054d6fa23b96005", + "passed": true, + "commands": [ + { + "command": "specsync check --spec ThreeMDViewer", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [ + "REQ-ThreeMDViewer-006" + ] + }, + { + "timestamp": 1791648091, + "commit": "fbfb7a5a97f155744383b3282ec00f363c4ee874", + "contract_digest": "c2c55f58dfdb8194f5d97358776f7e3321fbbb3fc6a127b3a990cc625f0cfcab", + "execution_digest": "2bb9d898086382e584700b0f1790c04fa97f14a030ffa1d3bc9df50113287a57", + "workspace_digest": "1fe89875c5f9e17b3f56b2e358519c256a4f2c83f55f5d95221dabd8b5a8ce0c", + "passed": true, + "commands": [ + { + "command": "specsync check --spec ThreeMDViewer --strict", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [ + "REQ-ThreeMDViewer-006" + ] + }, + { + "timestamp": 1791649340, + "commit": "78adcebf93640b18771d17b9726afeb6e15c845a", + "contract_digest": "c2c55f58dfdb8194f5d97358776f7e3321fbbb3fc6a127b3a990cc625f0cfcab", + "execution_digest": "2bb9d898086382e584700b0f1790c04fa97f14a030ffa1d3bc9df50113287a57", + "workspace_digest": "94bd7478dfb8735a51286b1c04445028dc910df8754b57775bc06773797a4420", + "passed": true, + "commands": [ + { + "command": "specsync check --spec ThreeMDViewer", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [ + "REQ-ThreeMDViewer-006" + ] + }, + { + "timestamp": 1791649364, + "commit": "761bdf4d1b782c0a68c4210d4f5b1366bed0f867", + "contract_digest": "c2c55f58dfdb8194f5d97358776f7e3321fbbb3fc6a127b3a990cc625f0cfcab", + "execution_digest": "2bb9d898086382e584700b0f1790c04fa97f14a030ffa1d3bc9df50113287a57", + "workspace_digest": "94bd7478dfb8735a51286b1c04445028dc910df8754b57775bc06773797a4420", + "passed": true, + "commands": [ + { + "command": "specsync check --spec ThreeMDViewer", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [ + "REQ-ThreeMDViewer-006" + ] + }, + { + "timestamp": 1791649364, + "commit": "2cb08248efb492b03de8a2bb300b00383f732945", + "contract_digest": "c2c55f58dfdb8194f5d97358776f7e3321fbbb3fc6a127b3a990cc625f0cfcab", + "execution_digest": "2bb9d898086382e584700b0f1790c04fa97f14a030ffa1d3bc9df50113287a57", + "workspace_digest": "94bd7478dfb8735a51286b1c04445028dc910df8754b57775bc06773797a4420", + "acceptance_input_digest": "1a57b9d7ce82cfa977d3d8769e3950e3ee1cf8e17af2cc9e24b000d945c30aef", + "acceptance_manifest": { + "schema_version": 1, + "entries": [ + { + "path": "\"apps/sculpt/Sources/RookApp/SculptureCanvasPointer.swift\"", + "kind": "missing", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "c4ba82a18d4d935812536f149be4aa0b5615e431cdd806c5618bf7d03545f120", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "\"apps/sculpt/Sources/RookApp/SculptureEditor.swift\"", + "kind": "missing", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "45a705552c723e5d3c62e35ff1f91e155943a3cd887b17ac36f0c5b8d2120b86", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "\"apps/sculpt/Sources/RookApp/SculptureViewport.swift\"", + "kind": "missing", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "0a5bbf6f8aef29d5ace9b35066576156f996102ad9770cb9e40e2a6c65061616", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "\"apps/sculpt/Sources/RookRendering/SculptureLiveVoxelView.swift\"", + "kind": "missing", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "7ae6181860cec53e573e3f42fd1432ec51aa33cf410c416a436ceb81f5e6e7f0", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "\"apps/sculpt/Sources/RookRendering/SculptureVoxelGeometry.swift\"", + "kind": "missing", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "64700adc1884bc2d37af3dbc29ec024a32f1d5df89691296f45e33790a8aabd9", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "\"apps/sculpt/Sources/RookSculpture/SculptureProjection.swift\"", + "kind": "missing", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "c82d81d1768efa3a8e32bfaccf6e601e2214cb0dcfe0d614f38a2ce514989404", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "\"apps/sculpt/Tests\"", + "kind": "missing", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "5f7933e46330edbd7ab99ab287e0eaee835e563d4d7e892636373e526c2f76f1", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "\"apps/sculpt/hi\"", + "kind": "missing", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "3243eb22a46bf2b39b571a6d2b86d90f807280529da5e13e1ad5a5f2a149563c", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "\"apps/sculpt/specs\"", + "kind": "missing", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "96c94711df54f292a1bb3cce4402e5524586ac7e9544498719133db7d3ab006f", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "\"docs/evidence/viewer-camera\"]", + "kind": "missing", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "363103111f6f1dfe638e03b0253eb25d568542b943f8b303efb5037590600f8a", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "\"hi/tools.md\"", + "kind": "missing", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "a6adf830b1bbe4b6c7a1709d3b873f36295782746f1814837845046864e7f402", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "\"specs/ThreeMDViewer\"", + "kind": "missing", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "e091bda9c951f304c4db8c40cb26760645c0d559ce2b0cff41a0a4c2201a92a0", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "\"uitests/viewer.spec.mjs\"", + "kind": "missing", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "9cfdec9d3b12ce5e5e37f86cb59f272fbf41d0dd7e3a093da5df6acfaec7ef38", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "[\"web/viewer.html\"", + "kind": "missing", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "4d154a3745b205f5afbe72d25471d40d225a9ec35bd838d5c84961d54a830ffa", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "specs/ThreeMDViewer/ThreeMDViewer.spec.md", + "kind": "file", + "mode": 33188, + "payload_digest": "5179c246eb258124753ca8d43972397d7e4f4e127f328b08e850de0a384c85ae", + "entry_digest": "a37f342f975c33eb5ca5fbc7cdef521c1acbe4a5c2a1b5696148da3d4d92ecb4", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/context.md", + "kind": "file", + "mode": 33188, + "payload_digest": "a7ab898f969d9ff40b61db395ce087ae405c91ee030eac801841b61f5620b1a2", + "entry_digest": "ebb8aad85405c195091c5abe00fd981bc7b136341b46118384e1d34ea35a965f", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/requirements.md", + "kind": "file", + "mode": 33188, + "payload_digest": "85322d8b84eff25c4d066df2c18d0151f91840366b142063b01f394d52a418ee", + "entry_digest": "7a0a9b1a29b3873df944466ee2b1171c8130aac2caa2ce4727aff1d154b53f6a", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/tasks.md", + "kind": "file", + "mode": 33188, + "payload_digest": "6f50ec382d73d01804ec0a8b9712a3df6f4c3106d831e380151ddd08ca079dcb", + "entry_digest": "79d6c9552eb5eb74e8bea36ab47c5a85baceab186fa2543e267507b89e900848", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/testing.md", + "kind": "file", + "mode": 33188, + "payload_digest": "77e9e80d5ece361fbbeab6965779db0d043476558b73091ea06f4c5f01142f13", + "entry_digest": "fd7665984f3453381ff2b848e3507cdead5297842b8f6faffa9e67e1587ba6e8", + "owners": [ + "ThreeMDViewer" + ] + } + ] + }, + "passed": true, + "commands": [ + { + "command": "specsync check --spec ThreeMDViewer", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [ + "REQ-ThreeMDViewer-006" + ] + } + ] +} diff --git a/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/verification.json b/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/verification.json new file mode 100644 index 00000000..66a47480 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan/verification.json @@ -0,0 +1,214 @@ +{ + "timestamp": 1791649364, + "commit": "2cb08248efb492b03de8a2bb300b00383f732945", + "contract_digest": "c2c55f58dfdb8194f5d97358776f7e3321fbbb3fc6a127b3a990cc625f0cfcab", + "execution_digest": "2bb9d898086382e584700b0f1790c04fa97f14a030ffa1d3bc9df50113287a57", + "workspace_digest": "94bd7478dfb8735a51286b1c04445028dc910df8754b57775bc06773797a4420", + "acceptance_input_digest": "1a57b9d7ce82cfa977d3d8769e3950e3ee1cf8e17af2cc9e24b000d945c30aef", + "acceptance_manifest": { + "schema_version": 1, + "entries": [ + { + "path": "\"apps/sculpt/Sources/RookApp/SculptureCanvasPointer.swift\"", + "kind": "missing", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "c4ba82a18d4d935812536f149be4aa0b5615e431cdd806c5618bf7d03545f120", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "\"apps/sculpt/Sources/RookApp/SculptureEditor.swift\"", + "kind": "missing", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "45a705552c723e5d3c62e35ff1f91e155943a3cd887b17ac36f0c5b8d2120b86", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "\"apps/sculpt/Sources/RookApp/SculptureViewport.swift\"", + "kind": "missing", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "0a5bbf6f8aef29d5ace9b35066576156f996102ad9770cb9e40e2a6c65061616", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "\"apps/sculpt/Sources/RookRendering/SculptureLiveVoxelView.swift\"", + "kind": "missing", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "7ae6181860cec53e573e3f42fd1432ec51aa33cf410c416a436ceb81f5e6e7f0", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "\"apps/sculpt/Sources/RookRendering/SculptureVoxelGeometry.swift\"", + "kind": "missing", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "64700adc1884bc2d37af3dbc29ec024a32f1d5df89691296f45e33790a8aabd9", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "\"apps/sculpt/Sources/RookSculpture/SculptureProjection.swift\"", + "kind": "missing", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "c82d81d1768efa3a8e32bfaccf6e601e2214cb0dcfe0d614f38a2ce514989404", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "\"apps/sculpt/Tests\"", + "kind": "missing", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "5f7933e46330edbd7ab99ab287e0eaee835e563d4d7e892636373e526c2f76f1", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "\"apps/sculpt/hi\"", + "kind": "missing", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "3243eb22a46bf2b39b571a6d2b86d90f807280529da5e13e1ad5a5f2a149563c", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "\"apps/sculpt/specs\"", + "kind": "missing", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "96c94711df54f292a1bb3cce4402e5524586ac7e9544498719133db7d3ab006f", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "\"docs/evidence/viewer-camera\"]", + "kind": "missing", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "363103111f6f1dfe638e03b0253eb25d568542b943f8b303efb5037590600f8a", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "\"hi/tools.md\"", + "kind": "missing", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "a6adf830b1bbe4b6c7a1709d3b873f36295782746f1814837845046864e7f402", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "\"specs/ThreeMDViewer\"", + "kind": "missing", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "e091bda9c951f304c4db8c40cb26760645c0d559ce2b0cff41a0a4c2201a92a0", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "\"uitests/viewer.spec.mjs\"", + "kind": "missing", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "9cfdec9d3b12ce5e5e37f86cb59f272fbf41d0dd7e3a093da5df6acfaec7ef38", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "[\"web/viewer.html\"", + "kind": "missing", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "4d154a3745b205f5afbe72d25471d40d225a9ec35bd838d5c84961d54a830ffa", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "specs/ThreeMDViewer/ThreeMDViewer.spec.md", + "kind": "file", + "mode": 33188, + "payload_digest": "5179c246eb258124753ca8d43972397d7e4f4e127f328b08e850de0a384c85ae", + "entry_digest": "a37f342f975c33eb5ca5fbc7cdef521c1acbe4a5c2a1b5696148da3d4d92ecb4", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/context.md", + "kind": "file", + "mode": 33188, + "payload_digest": "a7ab898f969d9ff40b61db395ce087ae405c91ee030eac801841b61f5620b1a2", + "entry_digest": "ebb8aad85405c195091c5abe00fd981bc7b136341b46118384e1d34ea35a965f", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/requirements.md", + "kind": "file", + "mode": 33188, + "payload_digest": "85322d8b84eff25c4d066df2c18d0151f91840366b142063b01f394d52a418ee", + "entry_digest": "7a0a9b1a29b3873df944466ee2b1171c8130aac2caa2ce4727aff1d154b53f6a", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/tasks.md", + "kind": "file", + "mode": 33188, + "payload_digest": "6f50ec382d73d01804ec0a8b9712a3df6f4c3106d831e380151ddd08ca079dcb", + "entry_digest": "79d6c9552eb5eb74e8bea36ab47c5a85baceab186fa2543e267507b89e900848", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/testing.md", + "kind": "file", + "mode": 33188, + "payload_digest": "77e9e80d5ece361fbbeab6965779db0d043476558b73091ea06f4c5f01142f13", + "entry_digest": "fd7665984f3453381ff2b848e3507cdead5297842b8f6faffa9e67e1587ba6e8", + "owners": [ + "ThreeMDViewer" + ] + } + ] + }, + "passed": true, + "commands": [ + { + "command": "specsync check --spec ThreeMDViewer", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [ + "REQ-ThreeMDViewer-006" + ] +} diff --git a/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/accepted-state.json b/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/accepted-state.json new file mode 100644 index 00000000..59a089ec --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/accepted-state.json @@ -0,0 +1,47 @@ +{ + "schema_version": 1, + "workflow_version": 2, + "workflow_origin_version": 2, + "id": "put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below", + "slug": "put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below", + "title": "Put Edit and Preview in the same viewer panel and toggle them like GitHub. Files stay on the left. Edit shows first. Below 900px, Files and the document take turns, and the document panel still switches Edit and Preview.", + "description": "Put Edit and Preview in the same viewer panel and toggle them like GitHub. Files stay on the left. Edit shows first. Below 900px, Files and the document take turns, and the document panel still switches Edit and Preview.", + "kind": "feature", + "state": "accepted", + "canonical_applied": true, + "base_commit": "e18f35e2c0c2c11c202342c5bf84b514ee12fe58", + "created_at": 1791595505, + "updated_at": 1791651086, + "affected_specs": [ + "ThreeMDViewer" + ], + "affected_paths": [ + "web/viewer.html", + "uitests/viewer.spec.mjs", + "hi/tools.md", + "specs/ThreeMDViewer" + ], + "no_spec_change": false, + "no_spec_change_rationale": null, + "acceptance_criteria": [ + "Files stay beside one document panel on desktop; Edit, Preview, and Cubes switch with exactly one visible. Cubes opens first with the framed small sculpture. Below 900px Files and the document take turns.", + "The page WebGL2 stage preserves Sculpt-style full outward-wound cubes, neighbor-face suppression, glyph fill and gold selected-slice edges, document axes, rendering caps, cached geometry, and one instanced draw. Camera and slice controls work with pointer and keyboard input.", + "The compact workspace keeps document identity and edited state visible, groups exports under Document, shows insert tools in Edit, and offers Preview for nongrid documents or unavailable WebGL2. Camera controls remain below the drawing with usable phone framing.", + "File and composition-entry switches preserve edits including invalid and empty drafts, caret, and selected plane. Linked entries share the corresponding file draft. File filtering and keyboard navigation retain focus; narrow-screen file and search opens reveal the document.", + "Local and public GitHub open, search, sections, pack, and text/kind 2 export remain available. Search and packing use current drafts. Failed local opens preserve the collection. Explicit navigation clears stale source queries in favor of the current hash. Drafts last until refresh or opening another collection.", + "The element and open-document bundles, Sculpt app, library APIs, format, package versions, fixtures, and trust policies remain unchanged. Complete verified SpecSync closure on the existing feature PR under Leif's 2026-10-10 approval; Leif retains merge authority." + ], + "selected_artifacts": [ + "context", + "requirements", + "plan", + "tasks", + "testing", + "docs" + ], + "dependencies": [], + "answers": { + "architecture_risk": "no", + "public_contract": "yes" + } +} diff --git a/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/approvals.json b/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/approvals.json new file mode 100644 index 00000000..4068b52f --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/approvals.json @@ -0,0 +1,138 @@ +{ + "approvals": [ + { + "gate": "definition", + "actor": "user:0xLeif", + "timestamp": 1791642355, + "digest": "3b63dbbb2bbe4105992cc11edf9c9e5af29cf072884081c8329b2389d8116e6d", + "note": "Recorded by agent:codex from Leif’s explicit “I approve” on 2026-10-10, after final viewer behavior, PR 93, and approval/verification/acceptance/archive steps were presented. Authorizes current final scope and verified closure; does not claim backdated approval, human diff review, independent review, signed provenance, or merge authority.", + "approved_scope": { + "schema_version": 1, + "change_id": "put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below", + "title": "Put Edit and Preview in the same viewer panel and toggle them like GitHub. Files stay on the left. Edit shows first. Below 900px, Files and the document take turns, and the document panel still switches Edit and Preview.", + "description": "Put Edit and Preview in the same viewer panel and toggle them like GitHub. Files stay on the left. Edit shows first. Below 900px, Files and the document take turns, and the document panel still switches Edit and Preview.", + "kind": "feature", + "affected_specs": [ + "ThreeMDViewer" + ], + "affected_paths": [ + "hi/tools.md", + "specs/ThreeMDViewer", + "uitests/viewer.spec.mjs", + "web/viewer.html" + ], + "no_spec_change": false, + "no_spec_change_rationale": null, + "acceptance_criteria": [ + "File and composition-entry switches preserve edits including invalid and empty drafts, caret, and selected plane. Linked entries share the corresponding file draft. File filtering and keyboard navigation retain focus; narrow-screen file and search opens reveal the document.", + "Files stay beside one document panel on desktop; Edit, Preview, and Cubes switch with exactly one visible. Cubes opens first with the framed small sculpture. Below 900px Files and the document take turns.", + "Local and public GitHub open, search, sections, pack, and text/kind 2 export remain available. Search and packing use current drafts. Failed local opens preserve the collection. Explicit navigation clears stale source queries in favor of the current hash. Drafts last until refresh or opening another collection.", + "The compact workspace keeps document identity and edited state visible, groups exports under Document, shows insert tools in Edit, and offers Preview for nongrid documents or unavailable WebGL2. Camera controls remain below the drawing with usable phone framing.", + "The element and open-document bundles, Sculpt app, library APIs, format, package versions, fixtures, and trust policies remain unchanged. Complete verified SpecSync closure on the existing feature PR under Leif's 2026-10-10 approval; Leif retains merge authority.", + "The page WebGL2 stage preserves Sculpt-style full outward-wound cubes, neighbor-face suppression, glyph fill and gold selected-slice edges, document axes, rendering caps, cached geometry, and one instanced draw. Camera and slice controls work with pointer and keyboard input." + ], + "dependencies": [], + "supersedes": [], + "answers": { + "architecture_risk": "no", + "public_contract": "yes" + } + }, + "approved_delta_digests": { + "ThreeMDViewer": "f438551c5a5af59e2bab5ed4a52950750aead6e8efac276b849e298626211629" + } + }, + { + "gate": "definition", + "actor": "user:0xLeif", + "timestamp": 1791643070, + "digest": "3b63dbbb2bbe4105992cc11edf9c9e5af29cf072884081c8329b2389d8116e6d", + "note": "Refresh under Leif’s explicit 2026-10-10 approval of final viewer scope and closure after verification. The delta retains the existing full-face, glyph/selection, geometry reuse, nearest-slice, axes, empty-cell, and rendering-cap acceptance criteria; no implementation or scope expansion. Recorded by agent:codex without claiming human diff review or independent review.", + "approved_scope": { + "schema_version": 1, + "change_id": "put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below", + "title": "Put Edit and Preview in the same viewer panel and toggle them like GitHub. Files stay on the left. Edit shows first. Below 900px, Files and the document take turns, and the document panel still switches Edit and Preview.", + "description": "Put Edit and Preview in the same viewer panel and toggle them like GitHub. Files stay on the left. Edit shows first. Below 900px, Files and the document take turns, and the document panel still switches Edit and Preview.", + "kind": "feature", + "affected_specs": [ + "ThreeMDViewer" + ], + "affected_paths": [ + "hi/tools.md", + "specs/ThreeMDViewer", + "uitests/viewer.spec.mjs", + "web/viewer.html" + ], + "no_spec_change": false, + "no_spec_change_rationale": null, + "acceptance_criteria": [ + "File and composition-entry switches preserve edits including invalid and empty drafts, caret, and selected plane. Linked entries share the corresponding file draft. File filtering and keyboard navigation retain focus; narrow-screen file and search opens reveal the document.", + "Files stay beside one document panel on desktop; Edit, Preview, and Cubes switch with exactly one visible. Cubes opens first with the framed small sculpture. Below 900px Files and the document take turns.", + "Local and public GitHub open, search, sections, pack, and text/kind 2 export remain available. Search and packing use current drafts. Failed local opens preserve the collection. Explicit navigation clears stale source queries in favor of the current hash. Drafts last until refresh or opening another collection.", + "The compact workspace keeps document identity and edited state visible, groups exports under Document, shows insert tools in Edit, and offers Preview for nongrid documents or unavailable WebGL2. Camera controls remain below the drawing with usable phone framing.", + "The element and open-document bundles, Sculpt app, library APIs, format, package versions, fixtures, and trust policies remain unchanged. Complete verified SpecSync closure on the existing feature PR under Leif's 2026-10-10 approval; Leif retains merge authority.", + "The page WebGL2 stage preserves Sculpt-style full outward-wound cubes, neighbor-face suppression, glyph fill and gold selected-slice edges, document axes, rendering caps, cached geometry, and one instanced draw. Camera and slice controls work with pointer and keyboard input." + ], + "dependencies": [], + "supersedes": [], + "answers": { + "architecture_risk": "no", + "public_contract": "yes" + } + }, + "approved_delta_digests": { + "ThreeMDViewer": "ce7ad2df8d6321f7adf3b91e164f3422853fa9233b6244e3accf76894da04edc" + } + }, + { + "gate": "definition", + "actor": "user:0xLeif", + "timestamp": 1791644175, + "digest": "3b63dbbb2bbe4105992cc11edf9c9e5af29cf072884081c8329b2389d8116e6d", + "note": "Leif explicitly selected Approve camera parity and verified closure in this chat on 2026-10-10. This approves the updated browser camera definition and verified closure on PR 93, not human diff review or independent signed approval.", + "approved_scope": { + "schema_version": 1, + "change_id": "put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below", + "title": "Put Edit and Preview in the same viewer panel and toggle them like GitHub. Files stay on the left. Edit shows first. Below 900px, Files and the document take turns, and the document panel still switches Edit and Preview.", + "description": "Put Edit and Preview in the same viewer panel and toggle them like GitHub. Files stay on the left. Edit shows first. Below 900px, Files and the document take turns, and the document panel still switches Edit and Preview.", + "kind": "feature", + "affected_specs": [ + "ThreeMDViewer" + ], + "affected_paths": [ + "hi/tools.md", + "specs/ThreeMDViewer", + "uitests/viewer.spec.mjs", + "web/viewer.html" + ], + "no_spec_change": false, + "no_spec_change_rationale": null, + "acceptance_criteria": [ + "File and composition-entry switches preserve edits including invalid and empty drafts, caret, and selected plane. Linked entries share the corresponding file draft. File filtering and keyboard navigation retain focus; narrow-screen file and search opens reveal the document.", + "Files stay beside one document panel on desktop; Edit, Preview, and Cubes switch with exactly one visible. Cubes opens first with the framed small sculpture. Below 900px Files and the document take turns.", + "Local and public GitHub open, search, sections, pack, and text/kind 2 export remain available. Search and packing use current drafts. Failed local opens preserve the collection. Explicit navigation clears stale source queries in favor of the current hash. Drafts last until refresh or opening another collection.", + "The compact workspace keeps document identity and edited state visible, groups exports under Document, shows insert tools in Edit, and offers Preview for nongrid documents or unavailable WebGL2. Camera controls remain below the drawing with usable phone framing.", + "The element and open-document bundles, Sculpt app, library APIs, format, package versions, fixtures, and trust policies remain unchanged. Complete verified SpecSync closure on the existing feature PR under Leif's 2026-10-10 approval; Leif retains merge authority.", + "The page WebGL2 stage preserves Sculpt-style full outward-wound cubes, neighbor-face suppression, glyph fill and gold selected-slice edges, document axes, rendering caps, cached geometry, and one instanced draw. Camera and slice controls work with pointer and keyboard input." + ], + "dependencies": [], + "supersedes": [], + "answers": { + "architecture_risk": "no", + "public_contract": "yes" + } + }, + "approved_delta_digests": { + "ThreeMDViewer": "cf44c32b17eb1bcefa805a200886063197982f4de2b0540d4b1b6e031d4b50b3" + } + }, + { + "gate": "finalization", + "actor": "specsync:finalization", + "timestamp": 1791651086, + "digest": "c9fe3ea1761918c78195b8c9180169f787156e7d6b437505e9dd64d0152f4406", + "note": "Same-PR finalization closing digest" + } + ], + "reopenings": [] +} diff --git a/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/change.md b/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/change.md new file mode 100644 index 00000000..24d6a94e --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/change.md @@ -0,0 +1,29 @@ +--- +id: put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below +state: archived +type: feature +base_commit: e18f35e2c0c2c11c202342c5bf84b514ee12fe58 +--- + +# Put Edit and Preview in the same viewer panel and toggle them like GitHub. Files stay on the left. Edit shows first. Below 900px, Files and the document take turns, and the document panel still switches Edit and Preview. + +## Intent + +Put Edit and Preview in the same viewer panel and toggle them like GitHub. Files stay on the left. Edit shows first. Below 900px, Files and the document take turns, and the document panel still switches Edit and Preview. + +## Affected Canonical Specs + +- `ThreeMDViewer` + +## Acceptance Criteria + +- Files stay beside one document panel on desktop; Edit, Preview, and Cubes switch with exactly one visible. Cubes opens first with the framed small sculpture. Below 900px Files and the document take turns. +- The page WebGL2 stage preserves Sculpt-style full outward-wound cubes, neighbor-face suppression, glyph fill and gold selected-slice edges, document axes, rendering caps, cached geometry, and one instanced draw. Camera and slice controls work with pointer and keyboard input. +- The compact workspace keeps document identity and edited state visible, groups exports under Document, shows insert tools in Edit, and offers Preview for nongrid documents or unavailable WebGL2. Camera controls remain below the drawing with usable phone framing. +- File and composition-entry switches preserve edits including invalid and empty drafts, caret, and selected plane. Linked entries share the corresponding file draft. File filtering and keyboard navigation retain focus; narrow-screen file and search opens reveal the document. +- Local and public GitHub open, search, sections, pack, and text/kind 2 export remain available. Search and packing use current drafts. Failed local opens preserve the collection. Explicit navigation clears stale source queries in favor of the current hash. Drafts last until refresh or opening another collection. +- The element and open-document bundles, Sculpt app, library APIs, format, package versions, fixtures, and trust policies remain unchanged. Complete verified SpecSync closure on the existing feature PR under Leif's 2026-10-10 approval; Leif retains merge authority. + +## No-spec Rationale + +Not applicable diff --git a/.specsync/changes/put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/context.md b/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/context.md similarity index 54% rename from .specsync/changes/put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/context.md rename to .specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/context.md index 56ca35b0..c84cf3bf 100644 --- a/.specsync/changes/put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/context.md +++ b/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/context.md @@ -11,16 +11,22 @@ The hosted page shipped in PR 90 and the ThreeMDViewer spec shipped in PR 91. Th ## What a later session needs -- Branch `0xleif/viewer/edit-preview` in `/Users/leif/Development/_CorvidLabs/3md-edit-preview`, based on `e18f35e`. Do not push to main. Do not merge. +- PR 92 merged; follow-up PR 93 uses branch `leif/viewer-draft-navigation` in `/Users/leif/Development/_CorvidLabs/3md-edit-preview`, based on `e18f35e`. Do not push to main. Do not merge. - Files stay on the left. Edit, Preview, and Cubes share `.pane.stage`. Default is Cubes. Below 900px, `.fileswitch` swaps Files and the document. - Choosing Preview calls `lab.render()` so the element measures the panel. The element still receives source while Edit is showing. - Cubes is the first view of that panel, and the opening document is a small sculpture so the cubes are in the window. It reads the parsed planes and draws a fenced character grid as lit WebGL2 cubes. Orbit and zoom move the camera. The page does not offer a render-mode switch and does not autoplay. Preview stays on one plane. The element bundle is not a voxel engine and is not rebuilt. - The element bundle is not rebuilt. Do not bump versions or move tag `v2.2.1`. -- Definition approval is still open. Do not self-approve, finalize, or archive. +- Leif approved the final scope and verified lifecycle closure on 2026-10-10. Record this approval at the current time; earlier implementation was kept in draft. - Do not finalize the kind 2, GDScript, storage-ceiling, or 2.1 docs-coverage changes. The cube parity follow-up uses the live Sculpt view as reference: 0.5 lit glyph fill, 0.4 glyph edges, 0.8 gold selected-slice edges, matching background and axes, full outward-wound cubes, neighbor-face suppression, and one instanced draw. Geometry is cached per document. Camera and selection changes use uniforms. The input caps stay 64 by 64 and 4000 cells. Sculpt app edits, painting, large worlds, and OBJ export stay out of scope. ## Continuing UI and UX pass -Leif requested continued UI and UX work on 2026-10-09. Preserve the current draft lifecycle and all earlier cube-stage and publication limits. The compact layout keeps the existing CorvidLabs tokens and typography; the stage is the focus. +Leif requested continued UI and UX work on 2026-10-09. Preserve the cube-stage and publication limits. The draft lifecycle restriction was superseded by Leif's explicit 2026-10-10 approval of verified closure. The compact layout keeps the existing CorvidLabs tokens and typography; the stage is the focus. + +## Full camera movement request + +On 2026-10-10 Leif reported, "I can't rotate it fully 360 and easiy move it etc..." The same viewer fix now includes full horizontal and vertical orbit, stable orientation across the poles, visible Orbit/Pan tools, Shift/right/middle drag panning, Shift-arrow panning, two-finger pan and pinch zoom, and proportional wheel zoom. Fit resets camera position without changing the source or selected slice. Camera input keeps cached geometry and the single-draw renderer. These changes are pending implementation and verification; archiving remains pending. + +Current implementation and shared fixture receipts are in `docs/evidence/viewer-camera/`. Live pan and Fit preserved the native scene and slice. Default utility-camera framing preserves historical example images. Final full suites, Trust and lifecycle closure remain pending; the separate gizmo definition is not approved. diff --git a/.specsync/changes/put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/deltas/ThreeMDViewer.md b/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/deltas/ThreeMDViewer.md similarity index 52% rename from .specsync/changes/put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/deltas/ThreeMDViewer.md rename to .specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/deltas/ThreeMDViewer.md index be7876df..a9eb7dd3 100644 --- a/.specsync/changes/put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/deltas/ThreeMDViewer.md +++ b/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/deltas/ThreeMDViewer.md @@ -1,10 +1,10 @@ # Edit and Preview share one panel -## ADDED +## MODIFIED ### REQUIREMENT REQ-ThreeMDViewer-003 -The viewer page SHALL show Edit, Preview, and Cubes in one panel. Exactly one of them SHALL be visible. Cubes SHALL be the default, and the opening document SHALL be a small sculpture whose cubes are inside the window. Files SHALL stay in the column beside that panel. Below 900px, Files and the document SHALL take turns, and the document panel SHALL still switch Edit, Preview, and Cubes. Choosing Preview SHALL render the live plane view. The workspace SHALL keep infrequent export and conversion actions in the Document disclosure, show insert tools only in Edit, and show the document title in every view. Tabs and the single-row plane outline SHALL provide one tab stop per group, with arrow, Home, and End navigation. +The viewer page SHALL show Edit, Preview, and Cubes in one panel. Exactly one of them SHALL be visible. Cubes SHALL be the default, and the opening document SHALL be a small sculpture whose cubes are inside the window. Files SHALL stay in the column beside that panel. Below 900px, Files and the document SHALL take turns, and the document panel SHALL still switch Edit, Preview, and Cubes. Choosing Preview SHALL render the live plane view. The workspace SHALL keep infrequent export and conversion actions in the Document disclosure, show insert tools only in Edit, and show the document title in every view. Tabs and the single-row plane outline SHALL provide one tab stop per group, with arrow, Home, and End navigation. File and composition-entry navigation SHALL preserve current edits, caret, and selected plane within the open collection. Edited documents SHALL be identified in every view. Opened files SHALL support filtering and keyboard navigation. Choosing a file or search result on a narrow screen SHALL reveal the document. Search and packing SHALL use current drafts. Failed local opens SHALL preserve the current collection. Explicit document navigation SHALL replace a stale source query with the current document hash. Acceptance Criteria: @@ -14,10 +14,11 @@ Acceptance Criteria: ### REQUIREMENT REQ-ThreeMDViewer-004 -The viewer page SHALL NOT offer a render-mode switch and SHALL NOT autoplay. Preview SHALL stay on one plane. Cubes SHALL draw complete, nearly cell-sized cubes with WebGL2, lit glyph-colored fill at 0.5 opacity and visible glyph-colored edges. The selected Z slice SHALL have gold edges at 0.8 opacity while retaining its glyph fill. The background SHALL be rgb(0.065, 0.085, 0.10). X SHALL be the column, Y the text row with row 0 toward the top, and Z the plane index. Orbit, zoom, and slice selection SHALL reuse the installed geometry. Each redraw SHALL use one instanced draw. Fit SHALL restore yaw 0.6, pitch 0.35, and zoom 1 without changing source or the selected slice. Camera buttons and the focused canvas SHALL support bounded zoom, and arrow keys SHALL orbit the focused canvas. Camera controls SHALL sit below the drawing without covering cubes. A document without a cube grid and an unavailable WebGL2 context SHALL offer Preview while preserving the source. The element bundle SHALL stay a text renderer. +The viewer page SHALL NOT offer a render-mode switch and SHALL NOT autoplay. Preview SHALL stay on one plane. Cubes SHALL draw complete, nearly cell-sized cubes with WebGL2, lit glyph-colored fill at 0.5 opacity and visible glyph-colored edges. The selected Z slice SHALL have gold edges at 0.8 opacity while retaining its glyph fill. The background SHALL be rgb(0.065, 0.085, 0.10). X SHALL be the column, Y the text row with row 0 toward the top, and Z the plane index. Orbit, zoom, and slice selection SHALL reuse the installed geometry. Each redraw SHALL use one instanced draw. Orbit SHALL rotate through full horizontal and vertical turns with a continuous camera basis at the poles. Pan mode, Shift-drag, and middle/right-drag SHALL move the view in screen space. Shift-arrow keys SHALL pan the focused canvas. Two-finger touch gestures SHALL pan and pinch to zoom. Wheel zoom SHALL respond proportionally to the gesture. Fit SHALL restore yaw 0.6, pitch 0.35, zoom 1, and zero pan without changing source or the selected slice. Camera buttons and the focused canvas SHALL support bounded zoom, and arrow keys SHALL orbit the focused canvas. Camera controls SHALL sit below the drawing without covering cubes. A document without a cube grid and an unavailable WebGL2 context SHALL offer Preview while preserving the source. The element bundle SHALL stay a text renderer. Acceptance Criteria: - The page has no render-mode menu and no page play control. A frame-axis document is not playing. -- A fenced grid draws on WebGL2, including a volume of about 1400 cubes. +- A fenced grid draws on WebGL2, including about 1400 cubes. A single cell has filled faces from every side. Selection changes edge color while the face interior keeps its glyph color. Camera, zoom, and selection redraw without geometry uploads. Click picking selects the nearest visible cube’s Z slice. +- X is the column, Y is the text row with row 0 toward the top, and Z is the plane index. Space, dot, and tab are empty. Keep the 64 by 64 per-plane and 4000-cell caps. - Evidence is VIEWER-6 and the cube tests in `uitests/viewer.spec.mjs`. diff --git a/.specsync/changes/put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/docs.md b/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/docs.md similarity index 69% rename from .specsync/changes/put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/docs.md rename to .specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/docs.md index 73beb913..2d43ee79 100644 --- a/.specsync/changes/put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/docs.md +++ b/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/docs.md @@ -6,12 +6,12 @@ artifact: docs # Docs - Human intent for the page is VIEWER-6 in `hi/tools.md`. It now says files stay on the left, Edit, Preview, and Cubes share one panel, and the page does not autoplay. -- The canonical contract is `specs/ThreeMDViewer/ThreeMDViewer.spec.md`, version 7, including REQ-ThreeMDViewer-003 and REQ-ThreeMDViewer-004. +- The canonical contract is `specs/ThreeMDViewer/ThreeMDViewer.spec.md`, version 10, including REQ-ThreeMDViewer-003 and REQ-ThreeMDViewer-004. - The page lead in `web/viewer.html` says Edit, the plane preview, and Cubes share the panel beside the files. - The public README, package versions, and release notes stay as they are. This change does not publish and does not move `v2.2.1`. -Sculpt parity and the caps are recorded in the canonical spec and VIEWER-6. Live comparison screenshots and verification results are in `docs/evidence/viewer-sculpt-parity/`. Definition approval remains open; no lifecycle approval, finalization, or archive was performed. +Sculpt parity and the caps are recorded in the canonical spec and VIEWER-6. Live comparison screenshots and verification results are in `docs/evidence/viewer-sculpt-parity/`. Those parity checks ran while the definition was unapproved; Leif subsequently approved final scope and verified closure on 2026-10-10. ## Continuing UI and UX pass -Synchronize VIEWER-6 and the canonical ThreeMDViewer contract and companions with the compact workspace, Document actions, camera controls, keyboard navigation, and empty/loading feedback. Record visual evidence under docs/evidence/viewer-ui/. Definition approval and permitted signed provenance remain separate gaps. +Synchronize VIEWER-6 and the canonical ThreeMDViewer contract and companions with the compact workspace, Document actions, camera controls, keyboard navigation, and empty/loading feedback. Record visual evidence under docs/evidence/viewer-ui/. Direct scope approval and verified closure are authorized on 2026-10-10. Permitted signed provenance remains unavailable. diff --git a/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/finalization.json b/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/finalization.json new file mode 100644 index 00000000..bac62c29 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/finalization.json @@ -0,0 +1,12 @@ +{ + "schema_version": 2, + "change_id": "put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below", + "implementation_commit": "47e18d32375406f98df343f4a580ea3e98f6d32d", + "implementation_tree": "39171f2e2bc521fae5c237ce54c6aad144404224", + "contract_digest": "3b63dbbb2bbe4105992cc11edf9c9e5af29cf072884081c8329b2389d8116e6d", + "workspace_digest": "94bd7478dfb8735a51286b1c04445028dc910df8754b57775bc06773797a4420", + "closing_digest": "c9fe3ea1761918c78195b8c9180169f787156e7d6b437505e9dd64d0152f4406", + "review_digest": "a626e9583b81095da2fd19af1229d93a01c698eeea3d684d6977f0a52aadca70", + "finalization_digest": "ee618ca48f72cd856bd14188ec0b7efd4dcd8588860e937f3bb399e30c2c1491", + "timestamp": 1791651086 +} diff --git a/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/lesson-bundle.md b/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/lesson-bundle.md new file mode 100644 index 00000000..b0a67500 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/lesson-bundle.md @@ -0,0 +1,98 @@ +# Lesson bundle — put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below + +Material for folding this change's lessons into the affected specs' `context.md`. +Synthesise from what actually happened below; do not restate the change description. + +## What this change was + +- **Title**: Put Edit and Preview in the same viewer panel and toggle them like GitHub. Files stay on the left. Edit shows first. Below 900px, Files and the document take turns, and the document panel still switches Edit and Preview. +- **Kind**: Feature +- **Specs**: ThreeMDViewer +- **Paths**: web/viewer.html, uitests/viewer.spec.mjs, hi/tools.md, specs/ThreeMDViewer +- **Acceptance**: Files stay beside one document panel on desktop; Edit, Preview, and Cubes switch with exactly one visible. Cubes opens first with the framed small sculpture. Below 900px Files and the document take turns. +- **Acceptance**: The page WebGL2 stage preserves Sculpt-style full outward-wound cubes, neighbor-face suppression, glyph fill and gold selected-slice edges, document axes, rendering caps, cached geometry, and one instanced draw. Camera and slice controls work with pointer and keyboard input. +- **Acceptance**: The compact workspace keeps document identity and edited state visible, groups exports under Document, shows insert tools in Edit, and offers Preview for nongrid documents or unavailable WebGL2. Camera controls remain below the drawing with usable phone framing. +- **Acceptance**: File and composition-entry switches preserve edits including invalid and empty drafts, caret, and selected plane. Linked entries share the corresponding file draft. File filtering and keyboard navigation retain focus; narrow-screen file and search opens reveal the document. +- **Acceptance**: Local and public GitHub open, search, sections, pack, and text/kind 2 export remain available. Search and packing use current drafts. Failed local opens preserve the collection. Explicit navigation clears stale source queries in favor of the current hash. Drafts last until refresh or opening another collection. +- **Acceptance**: The element and open-document bundles, Sculpt app, library APIs, format, package versions, fixtures, and trust policies remain unchanged. Complete verified SpecSync closure on the existing feature PR under Leif's 2026-10-10 approval; Leif retains merge authority. + +## Evidence + +- Verification commit: `47e18d32375406f98df343f4a580ea3e98f6d32d` +- Base commit: `e18f35e2c0c2c11c202342c5bf84b514ee12fe58` +- Verified by: `specsync check --spec ThreeMDViewer` + +## From the change's context.md + +# Context + +## What led here + +The hosted page shipped in PR 90 and the ThreeMDViewer spec shipped in PR 91. That page showed files, source, and the live view side by side. Leif asked for Edit and Preview to share one panel and toggle, like GitHub's Write and Preview. + +## What a later session needs + +- PR 92 merged; follow-up PR 93 uses branch `leif/viewer-draft-navigation` in `/Users/leif/Development/_CorvidLabs/3md-edit-preview`, based on `e18f35e`. Do not push to main. Do not merge. +- Files stay on the left. Edit, Preview, and Cubes share `.pane.stage`. Default is Cubes. Below 900px, `.fileswitch` swaps Files and the document. +- Choosing Preview calls `lab.render()` so the element measures the panel. The element still receives source while Edit is showing. +- Cubes is the first view of that panel, and the opening document is a small sculpture so the cubes are in the window. It reads the parsed planes and draws a fenced character grid as lit WebGL2 cubes. Orbit and zoom move the camera. The page does not offer a render-mode switch and does not autoplay. Preview stays on one plane. The element bundle is not a voxel engine and is not rebuilt. +- The element bundle is not rebuilt. Do not bump versions or move tag `v2.2.1`. +- Leif approved the final scope and verified lifecycle closure on 2026-10-10. Record this approval at the current time; earlier implementation was kept in draft. +- Do not finalize the kind 2, GDScript, storage-ceiling, or 2.1 docs-coverage changes. + +The cube parity follow-up uses the live Sculpt view as reference: 0.5 lit glyph fill, 0.4 glyph edges, 0.8 gold selected-slice edges, matching background and axes, full outward-wound cubes, neighbor-face suppression, and one instanced draw. Geometry is cached per document. Camera and selection changes use uniforms. The input caps stay 64 by 64 and 4000 cells. Sculpt app edits, painting, large worlds, and OBJ export stay out of scope. + +## Continuing UI and UX pass + +Leif requested continued UI and UX work on 2026-10-09. Preserve the cube-stage and publication limits. The draft lifecycle restriction was superseded by Leif's explicit 2026-10-10 approval of verified closure. The compact layout keeps the existing CorvidLabs tokens and typography; the stage is the focus. + +## Full camera movement request + +On 2026-10-10 Leif reported, "I can't rotate it fully 360 and easiy move it etc..." The same viewer fix now includes full horizontal and vertical orbit, stable orientation across the poles, visible Orbit/Pan tools, Shift/right/middle drag panning, Shift-arrow panning, two-finger pan and pinch zoom, and proportional wheel zoom. Fit resets camera position without changing the source or selected slice. Camera input keeps cached geometry and the single-draw renderer. These changes are pending implementation and verification; archiving remains pending. + +Current implementation and shared fixture receipts are in `docs/evidence/viewer-camera/`. Live pan and Fit preserved the native scene and slice. Default utility-camera framing preserves historical example images. Final full suites, Trust and lifecycle closure remain pending; the separate gizmo definition is not approved. + +## From the change's testing.md + +# Testing + +## Requirement evidence + +| ID | Canonical | Evidence | +| --- | --- | --- | +| REQ-ThreeMDViewer-003 | REQ-ThreeMDViewer-003 | VIEWER-6 in `hi/tools.md`. `web/viewer.html` switches Edit and Preview in one panel and calls `render` for Preview. `uitests/viewer.spec.mjs` covers the desktop switch and the narrow Files and document switch. | +| REQ-ThreeMDViewer-004 | REQ-ThreeMDViewer-004 | VIEWER-6 in `hi/tools.md`. `web/viewer.html` holds the element on `mode="single"`, removes the render-mode menu and the play control, and draws cubes with WebGL2. `uitests/viewer.spec.mjs` covers no autoplay and about 1400 cubes. | + +- `specsync check --spec ThreeMDViewer` +- `hi check` at the repository root +- Playwright `uitests/viewer.spec.mjs` passed 60 tests on Chromium and WebKit after the outline chip opens Preview first. The desktop and narrow layout tests passed again after the bar metadata hide. + +The Sculpt parity pass runs `./node_modules/.bin/playwright test viewer.spec.mjs` in `uitests` on Chromium and WebKit. Added GPU pixel evidence for a full single cell from six viewpoints and gold edges with unchanged glyph fill; nearest-Z picking; 1600 cells with zero camera/selection geometry uploads and one instanced draw per redraw. Live screenshots for Character orb and the starter geometry are in `docs/evidence/viewer-sculpt-parity/`. This is agent verification and was completed while definition approval remained open. + +Final parity browser verification: 70 passed on Chromium and WebKit. Strict ThreeMDViewer SpecSync check: 1 passed, zero warnings or failures. `hi check`: 85 criteria, no problems. Element bundle: current, 48840 bytes, no storage code. + +## Continuing UI and UX pass + +The Chromium/WebKit suite covers camera controls, phone layout and non-overlapping controls, Document disclosure dismissal, text and kind 2 download fidelity, editor focus after the save shortcut, prose Preview and sample loading, 30-slice keyboard navigation, GitHub rate-limit recovery, and WebGL2-unavailable guidance. Inspect dark/light desktop, Edit, and phone views and preserve screenshots under docs/evidence/viewer-ui/. + +## File navigation fix + +The Chromium and WebKit viewer suite covers exact draft restoration, invalid and empty edits, the caret and slice, composition-entry independence, linked entry/file sharing, original-text edited markers, current-text download, search and pack, file filtering and keyboard selection, mobile document reveal, failed-open preservation, and stale source-query removal on navigation. Screenshots from live desktop and phone inspection are in `docs/evidence/viewer-navigation/`. These are agent checks and do not themselves record human definition approval. + +## Closure verification + +The initial PR 93 hosted UI run had three Linux WebKit failures: a 179px canvas at 320 by 740, slice 0 restored instead of 1, and file keyboard focus leaving the expected button. All three reproduced in the matching Linux Playwright environment. Keep the assertions and verify the fixes in Linux and macOS. Leif's subsequent "I approve" authorizes recording the current definition and closing approval, without claiming backdated approval or independent review. + +Closure implementation checks: macOS viewer 98 passed; Linux hosted UI 190 passed and 8 existing skips; Bun helper suite 15 passed; strict SpecSync 4 specs passed with zero warnings and full configured coverage; Hi 85 criteria with no problems; pinned element bundle drift passed at 48840 bytes. Logs remain local under /private/tmp/3md-viewer-closure-*. The Trust and SpecSync closing gates are still pending. + +## Full camera movement request + +On 2026-10-10 Leif reported, "I can't rotate it fully 360 and easiy move it etc..." The same viewer fix now includes full horizontal and vertical orbit, stable orientation across the poles, visible Orbit/Pan tools, Shift/right/middle drag panning, Shift-arrow panning, two-finger pan and pinch zoom, and proportional wheel zoom. Fit resets camera position without changing the source or selected slice. Camera input keeps cached geometry and the single-draw renderer. These changes are pending implementation and verification; archiving remains pending. + +Current camera implementation: Mac Chromium/WebKit viewer 106 passed; Linux projection/phone selection 4 passed; native camera/input and unchanged math preview selection 23 passed in four suites. Root/native strict specs and Hi pass. Full current Linux/native runs and pinned Trust remain pending. See `docs/evidence/viewer-camera/README.md`. The separately requested axis gizmo remains an unapproved draft. + +Full native CI selection completed: 635 tests in 54 suites passed. Full Linux UI completed: 197 passed and one heavy-use WebKit test passed on retry, with eight existing skips; the heavy-use test passed alone on recheck. No new skips or relaxed assertions. Current camera implementation source matches commit c94e075164664cf724115f0a7e02cc53905a3114. Final pinned Trust, review and archive remain pending. + +## Where these lessons go + +- `specs/ThreeMDViewer/context.md` diff --git a/.specsync/changes/put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/plan.md b/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/plan.md similarity index 52% rename from .specsync/changes/put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/plan.md rename to .specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/plan.md index ab10bcda..560a697f 100644 --- a/.specsync/changes/put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/plan.md +++ b/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/plan.md @@ -7,7 +7,7 @@ artifact: plan ## WP1. Definition -- Keep this change in draft until Leif approves the definition. +- Record Leif's 2026-10-10 approval of the reconciled final definition, then verify and close this change on PR 93. - The semantic delta is `deltas/ThreeMDViewer.md`. - Hi for this behavior is VIEWER-6 in `hi/tools.md`. @@ -31,3 +31,15 @@ The cube parity follow-up uses the live Sculpt view as reference: 0.5 lit glyph ## Continuing UI and UX pass Compact the identity row and toolbar. Use a native Document disclosure for export and conversion tools, keep composition entry selection in the stage, and show insertion tools only in Edit. Place camera controls below the canvas and use the canvas dimensions for camera framing. Add keyboard camera, tab, and slice navigation, with one tab stop in each navigation group. Explain nongrid documents and unavailable GPU support with a Preview action. Add busy/recovery feedback around the existing GitHub loader. + +## File navigation fix + +Keep a page-owned draft for each opened file and composition entry, including invalid or empty edits. Share linked entry drafts with their corresponding source file. Refresh the line index from drafts when searching, use draft text when packing, and preserve selection and caret when returning. Validate a local open before replacing the collection. Show filenames and edited state across views, add a file filter with an explicit empty result, and reveal opened documents on narrow screens. Replace stale source queries on explicit navigation. + +## Hosted WebKit closure fixes + +Reproduce the three PR 93 UI failures with Linux Playwright 1.61.1. Preserve the selected slice through delayed source rendering and navigation, keep file-filter keyboard focus stable across native search events, and provide usable cube drawing space at a 320 by 740 viewport. Keep the existing assertions, then run the browser suites, strict contract checks, Hi, the pinned Trust lane, and provenance verification before closing the lifecycle. + +## Full camera movement request + +On 2026-10-10 Leif reported, "I can't rotate it fully 360 and easiy move it etc..." The same viewer fix now includes full horizontal and vertical orbit, stable orientation across the poles, visible Orbit/Pan tools, Shift/right/middle drag panning, Shift-arrow panning, two-finger pan and pinch zoom, and proportional wheel zoom. Fit resets camera position without changing the source or selected slice. Camera input keeps cached geometry and the single-draw renderer. These changes are pending implementation and verification; archiving remains pending. diff --git a/.specsync/changes/put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/requirements.md b/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/requirements.md similarity index 57% rename from .specsync/changes/put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/requirements.md rename to .specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/requirements.md index f5c685fb..675ab1e0 100644 --- a/.specsync/changes/put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/requirements.md +++ b/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/requirements.md @@ -5,8 +5,8 @@ artifact: requirements # Requirements -- **REQ-ThreeMDViewer-003** The viewer page SHALL show Edit, Preview, and Cubes in one panel. Exactly one of them SHALL be visible. Cubes SHALL be the default, and the opening document SHALL be a small sculpture whose cubes are inside the window. Files SHALL stay in the column beside that panel. Below 900px, Files and the document SHALL take turns, and the document panel SHALL still switch Edit, Preview, and Cubes. Choosing Preview SHALL render the live plane view. The workspace SHALL keep infrequent export and conversion actions in the Document disclosure, show insert tools only in Edit, and show the document title in every view. Tabs and the single-row plane outline SHALL provide one tab stop per group, with arrow, Home, and End navigation. -- **REQ-ThreeMDViewer-004** The viewer page SHALL NOT offer a render-mode switch and SHALL NOT autoplay. Preview SHALL stay on one plane. Cubes SHALL draw complete, nearly cell-sized cubes with WebGL2, lit glyph-colored fill at 0.5 opacity and visible glyph-colored edges. The selected Z slice SHALL have gold edges at 0.8 opacity while retaining its glyph fill. The background SHALL be rgb(0.065, 0.085, 0.10). X SHALL be the column, Y the text row with row 0 toward the top, and Z the plane index. Orbit, zoom, and slice selection SHALL reuse the installed geometry. Each redraw SHALL use one instanced draw. Fit SHALL restore yaw 0.6, pitch 0.35, and zoom 1 without changing source or the selected slice. Camera buttons and the focused canvas SHALL support bounded zoom, and arrow keys SHALL orbit the focused canvas. Camera controls SHALL sit below the drawing without covering cubes. A document without a cube grid and an unavailable WebGL2 context SHALL offer Preview while preserving the source. The element bundle SHALL stay a text renderer. +- **REQ-ThreeMDViewer-003** The viewer page SHALL show Edit, Preview, and Cubes in one panel. Exactly one of them SHALL be visible. Cubes SHALL be the default, and the opening document SHALL be a small sculpture whose cubes are inside the window. Files SHALL stay in the column beside that panel. Below 900px, Files and the document SHALL take turns, and the document panel SHALL still switch Edit, Preview, and Cubes. Choosing Preview SHALL render the live plane view. The workspace SHALL keep infrequent export and conversion actions in the Document disclosure, show insert tools only in Edit, and show the document title in every view. Tabs and the single-row plane outline SHALL provide one tab stop per group, with arrow, Home, and End navigation. File and composition-entry navigation SHALL preserve current edits, caret, and selected plane within the open collection. Edited documents SHALL be identified in every view. Opened files SHALL support filtering and keyboard navigation. Choosing a file or search result on a narrow screen SHALL reveal the document. Search and packing SHALL use current drafts. Failed local opens SHALL preserve the current collection. Explicit document navigation SHALL replace a stale source query with the current document hash. +- **REQ-ThreeMDViewer-004** The viewer page SHALL NOT offer a render-mode switch and SHALL NOT autoplay. Preview SHALL stay on one plane. Cubes SHALL draw complete, nearly cell-sized cubes with WebGL2, lit glyph-colored fill at 0.5 opacity and visible glyph-colored edges. The selected Z slice SHALL have gold edges at 0.8 opacity while retaining its glyph fill. The background SHALL be rgb(0.065, 0.085, 0.10). X SHALL be the column, Y the text row with row 0 toward the top, and Z the plane index. Orbit, zoom, and slice selection SHALL reuse the installed geometry. Each redraw SHALL use one instanced draw. Orbit SHALL rotate through full horizontal and vertical turns with a continuous camera basis at the poles. Pan mode, Shift-drag, and middle/right-drag SHALL move the view in screen space. Shift-arrow keys SHALL pan the focused canvas. Two-finger touch gestures SHALL pan and pinch to zoom. Wheel zoom SHALL respond proportionally to the gesture. Fit SHALL restore yaw 0.6, pitch 0.35, zoom 1, and zero pan without changing source or the selected slice. Camera buttons and the focused canvas SHALL support bounded zoom, and arrow keys SHALL orbit the focused canvas. Camera controls SHALL sit below the drawing without covering cubes. A document without a cube grid and an unavailable WebGL2 context SHALL offer Preview while preserving the source. The element bundle SHALL stay a text renderer. REQ-ThreeMDViewer-001 and REQ-ThreeMDViewer-002 stay. GitHub open, search, sections, pack, kind 2, hostname checks, and the text-only element stay. diff --git a/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/review-attempts.json b/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/review-attempts.json new file mode 100644 index 00000000..94da6d54 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/review-attempts.json @@ -0,0 +1,21 @@ +{ + "schema_version": 1, + "reviews": [ + { + "schema_version": 2, + "change_id": "put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below", + "reviewer": "agent:codex", + "provenance": { + "schema_version": 1, + "provider": "github_actions_check", + "required_check": "SpecSync scoped review" + }, + "verdict": "pass", + "implementation_commit": "47e18d32375406f98df343f4a580ea3e98f6d32d", + "contract_digest": "3b63dbbb2bbe4105992cc11edf9c9e5af29cf072884081c8329b2389d8116e6d", + "execution_digest": "ca236272754b3912cc5221e45a62020c70ffb0bb389840b6fb33d745834b8707", + "workspace_digest": "94bd7478dfb8735a51286b1c04445028dc910df8754b57775bc06773797a4420", + "timestamp": 1791651032 + } + ] +} diff --git a/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/review.json b/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/review.json new file mode 100644 index 00000000..905e5b09 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/review.json @@ -0,0 +1,16 @@ +{ + "schema_version": 2, + "change_id": "put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below", + "reviewer": "agent:codex", + "provenance": { + "schema_version": 1, + "provider": "github_actions_check", + "required_check": "SpecSync scoped review" + }, + "verdict": "pass", + "implementation_commit": "47e18d32375406f98df343f4a580ea3e98f6d32d", + "contract_digest": "3b63dbbb2bbe4105992cc11edf9c9e5af29cf072884081c8329b2389d8116e6d", + "execution_digest": "ca236272754b3912cc5221e45a62020c70ffb0bb389840b6fb33d745834b8707", + "workspace_digest": "94bd7478dfb8735a51286b1c04445028dc910df8754b57775bc06773797a4420", + "timestamp": 1791651032 +} diff --git a/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/state.json b/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/state.json new file mode 100644 index 00000000..5d56b197 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/state.json @@ -0,0 +1,47 @@ +{ + "schema_version": 1, + "workflow_version": 2, + "workflow_origin_version": 2, + "id": "put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below", + "slug": "put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below", + "title": "Put Edit and Preview in the same viewer panel and toggle them like GitHub. Files stay on the left. Edit shows first. Below 900px, Files and the document take turns, and the document panel still switches Edit and Preview.", + "description": "Put Edit and Preview in the same viewer panel and toggle them like GitHub. Files stay on the left. Edit shows first. Below 900px, Files and the document take turns, and the document panel still switches Edit and Preview.", + "kind": "feature", + "state": "archived", + "canonical_applied": true, + "base_commit": "e18f35e2c0c2c11c202342c5bf84b514ee12fe58", + "created_at": 1791595505, + "updated_at": 1791651150, + "affected_specs": [ + "ThreeMDViewer" + ], + "affected_paths": [ + "web/viewer.html", + "uitests/viewer.spec.mjs", + "hi/tools.md", + "specs/ThreeMDViewer" + ], + "no_spec_change": false, + "no_spec_change_rationale": null, + "acceptance_criteria": [ + "Files stay beside one document panel on desktop; Edit, Preview, and Cubes switch with exactly one visible. Cubes opens first with the framed small sculpture. Below 900px Files and the document take turns.", + "The page WebGL2 stage preserves Sculpt-style full outward-wound cubes, neighbor-face suppression, glyph fill and gold selected-slice edges, document axes, rendering caps, cached geometry, and one instanced draw. Camera and slice controls work with pointer and keyboard input.", + "The compact workspace keeps document identity and edited state visible, groups exports under Document, shows insert tools in Edit, and offers Preview for nongrid documents or unavailable WebGL2. Camera controls remain below the drawing with usable phone framing.", + "File and composition-entry switches preserve edits including invalid and empty drafts, caret, and selected plane. Linked entries share the corresponding file draft. File filtering and keyboard navigation retain focus; narrow-screen file and search opens reveal the document.", + "Local and public GitHub open, search, sections, pack, and text/kind 2 export remain available. Search and packing use current drafts. Failed local opens preserve the collection. Explicit navigation clears stale source queries in favor of the current hash. Drafts last until refresh or opening another collection.", + "The element and open-document bundles, Sculpt app, library APIs, format, package versions, fixtures, and trust policies remain unchanged. Complete verified SpecSync closure on the existing feature PR under Leif's 2026-10-10 approval; Leif retains merge authority." + ], + "selected_artifacts": [ + "context", + "requirements", + "plan", + "tasks", + "testing", + "docs" + ], + "dependencies": [], + "answers": { + "architecture_risk": "no", + "public_contract": "yes" + } +} diff --git a/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/tasks.md b/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/tasks.md new file mode 100644 index 00000000..c93ebed7 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/tasks.md @@ -0,0 +1,45 @@ +--- +change: put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below +artifact: tasks +--- + +# Tasks + +- [x] Put Edit and Preview in one panel in `web/viewer.html`, with Cubes first. +- [x] On a narrow window, switch Files and the document, and keep Edit and Preview inside the document. +- [x] Call `render` when Preview is shown. +- [x] Update VIEWER-6 and `specs/ThreeMDViewer/`. +- [x] Update the desktop and narrow Playwright tests. +- [x] Reconcile the final definition under Leif's direct 2026-10-10 approval; record that approval through SpecSync. + +- [x] Run Sculpt and compare the same sculpture in both live cube stages. +- [x] Match lit glyph fill and gold selected-slice edges, full faces, background, axes, and framing. +- [x] Keep camera, zoom, and selection on cached geometry with one instanced draw. + +## Continuing UI and UX pass + +- [x] Compact the workspace and group document actions. +- [x] Keep document titles visible and insert tools in Edit. +- [x] Add Fit, bounded zoom, keyboard orbiting, and scrolling slice navigation. +- [x] Explain nongrid/GPU-unavailable states and recover GitHub loading controls. +- [x] Verify the final browser suite and capture visual evidence. + +Pinned Trust runs after the feature head is committed and pushed; its result is recorded in the PR and local verification output. + +Leif approved the final scope and verified closure on 2026-10-10. This records direct human authorization, without claiming human diff review. + +- [x] Preserve file, linked-entry, invalid, and empty drafts with caret and selected plane across navigation. +- [x] Mark edits, filter files, navigate by keyboard, reveal phone documents, and avoid stale source queries. +- [x] Search and pack current drafts, and preserve the collection after a failed open. + +## Hosted WebKit closure fixes + +- [x] Correct delayed-render slice preservation, stable alphabetical file navigation, and small-phone drawing space. +- [x] Verify the implemented viewer behavior in macOS Chromium/WebKit, the full Linux hosted UI suite, strict specs, Hi, helper tests, and bundle drift. + +Targeted lifecycle verification, pinned Trust, provenance recording, acceptance, and archive remain pending. The verified implementation tasks above do not claim these later gates have completed. + +## Full camera movement + +- [x] Implement full orbit, screen-space panning, touch pan/pinch, proportional wheel zoom, and Fit recovery. +- [x] Verify camera input, pole stability, picking, unchanged source/slice, geometry reuse, and phone layout. diff --git a/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/testing.md b/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/testing.md new file mode 100644 index 00000000..aa1a9f4f --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/testing.md @@ -0,0 +1,43 @@ +--- +change: put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below +artifact: testing +--- + +# Testing + +## Requirement evidence + +| ID | Canonical | Evidence | +| --- | --- | --- | +| REQ-ThreeMDViewer-003 | REQ-ThreeMDViewer-003 | VIEWER-6 in `hi/tools.md`. `web/viewer.html` switches Edit and Preview in one panel and calls `render` for Preview. `uitests/viewer.spec.mjs` covers the desktop switch and the narrow Files and document switch. | +| REQ-ThreeMDViewer-004 | REQ-ThreeMDViewer-004 | VIEWER-6 in `hi/tools.md`. `web/viewer.html` holds the element on `mode="single"`, removes the render-mode menu and the play control, and draws cubes with WebGL2. `uitests/viewer.spec.mjs` covers no autoplay and about 1400 cubes. | + +- `specsync check --spec ThreeMDViewer` +- `hi check` at the repository root +- Playwright `uitests/viewer.spec.mjs` passed 60 tests on Chromium and WebKit after the outline chip opens Preview first. The desktop and narrow layout tests passed again after the bar metadata hide. + +The Sculpt parity pass runs `./node_modules/.bin/playwright test viewer.spec.mjs` in `uitests` on Chromium and WebKit. Added GPU pixel evidence for a full single cell from six viewpoints and gold edges with unchanged glyph fill; nearest-Z picking; 1600 cells with zero camera/selection geometry uploads and one instanced draw per redraw. Live screenshots for Character orb and the starter geometry are in `docs/evidence/viewer-sculpt-parity/`. This is agent verification and was completed while definition approval remained open. + +Final parity browser verification: 70 passed on Chromium and WebKit. Strict ThreeMDViewer SpecSync check: 1 passed, zero warnings or failures. `hi check`: 85 criteria, no problems. Element bundle: current, 48840 bytes, no storage code. + +## Continuing UI and UX pass + +The Chromium/WebKit suite covers camera controls, phone layout and non-overlapping controls, Document disclosure dismissal, text and kind 2 download fidelity, editor focus after the save shortcut, prose Preview and sample loading, 30-slice keyboard navigation, GitHub rate-limit recovery, and WebGL2-unavailable guidance. Inspect dark/light desktop, Edit, and phone views and preserve screenshots under docs/evidence/viewer-ui/. + +## File navigation fix + +The Chromium and WebKit viewer suite covers exact draft restoration, invalid and empty edits, the caret and slice, composition-entry independence, linked entry/file sharing, original-text edited markers, current-text download, search and pack, file filtering and keyboard selection, mobile document reveal, failed-open preservation, and stale source-query removal on navigation. Screenshots from live desktop and phone inspection are in `docs/evidence/viewer-navigation/`. These are agent checks and do not themselves record human definition approval. + +## Closure verification + +The initial PR 93 hosted UI run had three Linux WebKit failures: a 179px canvas at 320 by 740, slice 0 restored instead of 1, and file keyboard focus leaving the expected button. All three reproduced in the matching Linux Playwright environment. Keep the assertions and verify the fixes in Linux and macOS. Leif's subsequent "I approve" authorizes recording the current definition and closing approval, without claiming backdated approval or independent review. + +Closure implementation checks: macOS viewer 98 passed; Linux hosted UI 190 passed and 8 existing skips; Bun helper suite 15 passed; strict SpecSync 4 specs passed with zero warnings and full configured coverage; Hi 85 criteria with no problems; pinned element bundle drift passed at 48840 bytes. Logs remain local under /private/tmp/3md-viewer-closure-*. The Trust and SpecSync closing gates are still pending. + +## Full camera movement request + +On 2026-10-10 Leif reported, "I can't rotate it fully 360 and easiy move it etc..." The same viewer fix now includes full horizontal and vertical orbit, stable orientation across the poles, visible Orbit/Pan tools, Shift/right/middle drag panning, Shift-arrow panning, two-finger pan and pinch zoom, and proportional wheel zoom. Fit resets camera position without changing the source or selected slice. Camera input keeps cached geometry and the single-draw renderer. These changes are pending implementation and verification; archiving remains pending. + +Current camera implementation: Mac Chromium/WebKit viewer 106 passed; Linux projection/phone selection 4 passed; native camera/input and unchanged math preview selection 23 passed in four suites. Root/native strict specs and Hi pass. Full current Linux/native runs and pinned Trust remain pending. See `docs/evidence/viewer-camera/README.md`. The separately requested axis gizmo remains an unapproved draft. + +Full native CI selection completed: 635 tests in 54 suites passed. Full Linux UI completed: 197 passed and one heavy-use WebKit test passed on retry, with eight existing skips; the heavy-use test passed alone on recheck. No new skips or relaxed assertions. Current camera implementation source matches commit c94e075164664cf724115f0a7e02cc53905a3114. Final pinned Trust, review and archive remain pending. diff --git a/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/verification-attempts.json b/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/verification-attempts.json new file mode 100644 index 00000000..0398e708 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/verification-attempts.json @@ -0,0 +1,253 @@ +{ + "schema_version": 1, + "attempts": [ + { + "timestamp": 1791642684, + "commit": "58512a76333d3698e3ab7d140d7b378a1313ba2a", + "contract_digest": "3b63dbbb2bbe4105992cc11edf9c9e5af29cf072884081c8329b2389d8116e6d", + "execution_digest": "83b60b058c667a697e198215552d2b70040d8b858290098c25dbf50cf40f661b", + "workspace_digest": "ccf0dbace0554bce2254fe8eca0d40b709e80a9a6ecd0c862d8c9ade589df656", + "passed": true, + "commands": [ + { + "command": "specsync check --spec ThreeMDViewer", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [ + "REQ-ThreeMDViewer-003", + "REQ-ThreeMDViewer-004" + ] + }, + { + "timestamp": 1791642700, + "commit": "1b101504cbe0e707b7f76e55e1da075a756df084", + "contract_digest": "3b63dbbb2bbe4105992cc11edf9c9e5af29cf072884081c8329b2389d8116e6d", + "execution_digest": "83b60b058c667a697e198215552d2b70040d8b858290098c25dbf50cf40f661b", + "workspace_digest": "ccf0dbace0554bce2254fe8eca0d40b709e80a9a6ecd0c862d8c9ade589df656", + "passed": true, + "commands": [ + { + "command": "specsync check --spec ThreeMDViewer", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [ + "REQ-ThreeMDViewer-003", + "REQ-ThreeMDViewer-004" + ] + }, + { + "timestamp": 1791647718, + "commit": "106c0580607803adbad7da94556b6a7ec33f332f", + "contract_digest": "3b63dbbb2bbe4105992cc11edf9c9e5af29cf072884081c8329b2389d8116e6d", + "execution_digest": "ca236272754b3912cc5221e45a62020c70ffb0bb389840b6fb33d745834b8707", + "workspace_digest": "1fe89875c5f9e17b3f56b2e358519c256a4f2c83f55f5d95221dabd8b5a8ce0c", + "passed": true, + "commands": [ + { + "command": "specsync check --spec ThreeMDViewer", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [ + "REQ-ThreeMDViewer-003", + "REQ-ThreeMDViewer-004" + ] + }, + { + "timestamp": 1791647755, + "commit": "f5a72113e03b8bb2d7d34a1944875b039fd6a2f9", + "contract_digest": "3b63dbbb2bbe4105992cc11edf9c9e5af29cf072884081c8329b2389d8116e6d", + "execution_digest": "ca236272754b3912cc5221e45a62020c70ffb0bb389840b6fb33d745834b8707", + "workspace_digest": "1fe89875c5f9e17b3f56b2e358519c256a4f2c83f55f5d95221dabd8b5a8ce0c", + "passed": true, + "commands": [ + { + "command": "specsync check --spec ThreeMDViewer", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [ + "REQ-ThreeMDViewer-003", + "REQ-ThreeMDViewer-004" + ] + }, + { + "timestamp": 1791648117, + "commit": "fbfb7a5a97f155744383b3282ec00f363c4ee874", + "contract_digest": "3b63dbbb2bbe4105992cc11edf9c9e5af29cf072884081c8329b2389d8116e6d", + "execution_digest": "ca236272754b3912cc5221e45a62020c70ffb0bb389840b6fb33d745834b8707", + "workspace_digest": "1fe89875c5f9e17b3f56b2e358519c256a4f2c83f55f5d95221dabd8b5a8ce0c", + "passed": true, + "commands": [ + { + "command": "specsync check --spec ThreeMDViewer --strict", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [ + "REQ-ThreeMDViewer-003", + "REQ-ThreeMDViewer-004" + ] + }, + { + "timestamp": 1791650838, + "commit": "182dc07c321cd2c34aabfd2e5db6db7c461ad9c1", + "contract_digest": "3b63dbbb2bbe4105992cc11edf9c9e5af29cf072884081c8329b2389d8116e6d", + "execution_digest": "ca236272754b3912cc5221e45a62020c70ffb0bb389840b6fb33d745834b8707", + "workspace_digest": "94bd7478dfb8735a51286b1c04445028dc910df8754b57775bc06773797a4420", + "passed": true, + "commands": [ + { + "command": "specsync check --spec ThreeMDViewer", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [ + "REQ-ThreeMDViewer-003", + "REQ-ThreeMDViewer-004" + ] + }, + { + "timestamp": 1791650874, + "commit": "fd50f4c73e662da08853743519060f9045cbb0b0", + "contract_digest": "3b63dbbb2bbe4105992cc11edf9c9e5af29cf072884081c8329b2389d8116e6d", + "execution_digest": "ca236272754b3912cc5221e45a62020c70ffb0bb389840b6fb33d745834b8707", + "workspace_digest": "94bd7478dfb8735a51286b1c04445028dc910df8754b57775bc06773797a4420", + "passed": true, + "commands": [ + { + "command": "specsync check --spec ThreeMDViewer", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [ + "REQ-ThreeMDViewer-003", + "REQ-ThreeMDViewer-004" + ] + }, + { + "timestamp": 1791650874, + "commit": "47e18d32375406f98df343f4a580ea3e98f6d32d", + "contract_digest": "3b63dbbb2bbe4105992cc11edf9c9e5af29cf072884081c8329b2389d8116e6d", + "execution_digest": "ca236272754b3912cc5221e45a62020c70ffb0bb389840b6fb33d745834b8707", + "workspace_digest": "94bd7478dfb8735a51286b1c04445028dc910df8754b57775bc06773797a4420", + "acceptance_input_digest": "07e830005117d0349f94b4a1998d26f9c3fe91fc324f41a2f31c8d2555af7d83", + "acceptance_manifest": { + "schema_version": 1, + "entries": [ + { + "path": "hi/tools.md", + "kind": "file", + "mode": 33188, + "payload_digest": "a76304c2e07c30d6b289bd023e06e13d6ed830d56c173f0804d698a37d3848c6", + "entry_digest": "0708d4e1a5c692b379dbf8aeea378f07e8c05c29b09beb4cd103fabf10e3461d", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "specs/ThreeMDViewer", + "kind": "non_file", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "b53a01354acef7fb830687d9789c70f85c60f43e94da4a2dd0816c771a3bf773", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/ThreeMDViewer.spec.md", + "kind": "file", + "mode": 33188, + "payload_digest": "5179c246eb258124753ca8d43972397d7e4f4e127f328b08e850de0a384c85ae", + "entry_digest": "a37f342f975c33eb5ca5fbc7cdef521c1acbe4a5c2a1b5696148da3d4d92ecb4", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/context.md", + "kind": "file", + "mode": 33188, + "payload_digest": "a7ab898f969d9ff40b61db395ce087ae405c91ee030eac801841b61f5620b1a2", + "entry_digest": "ebb8aad85405c195091c5abe00fd981bc7b136341b46118384e1d34ea35a965f", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/requirements.md", + "kind": "file", + "mode": 33188, + "payload_digest": "85322d8b84eff25c4d066df2c18d0151f91840366b142063b01f394d52a418ee", + "entry_digest": "7a0a9b1a29b3873df944466ee2b1171c8130aac2caa2ce4727aff1d154b53f6a", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/tasks.md", + "kind": "file", + "mode": 33188, + "payload_digest": "6f50ec382d73d01804ec0a8b9712a3df6f4c3106d831e380151ddd08ca079dcb", + "entry_digest": "79d6c9552eb5eb74e8bea36ab47c5a85baceab186fa2543e267507b89e900848", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/testing.md", + "kind": "file", + "mode": 33188, + "payload_digest": "77e9e80d5ece361fbbeab6965779db0d043476558b73091ea06f4c5f01142f13", + "entry_digest": "fd7665984f3453381ff2b848e3507cdead5297842b8f6faffa9e67e1587ba6e8", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "uitests/viewer.spec.mjs", + "kind": "file", + "mode": 33188, + "payload_digest": "f8e7b1065581569ed471058c7e73bd31b66105306a0d67b903d300cd42caa4d3", + "entry_digest": "0d075959cdfcbc0940a8d5048812aeb330a61816a336b449e9c8ed77032df6ba", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "web/viewer.html", + "kind": "file", + "mode": 33188, + "payload_digest": "2e8fb29cf6e6996898d5ac39378d0bd42ff9bbaaf694c9dfbda876c6904b8a3c", + "entry_digest": "5355f2ce99c31879e758968500c49d8912e2f39a7eb9b985571fc5e260fe2641", + "owners": [ + "ThreeMDViewer" + ] + } + ] + }, + "passed": true, + "commands": [ + { + "command": "specsync check --spec ThreeMDViewer", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [ + "REQ-ThreeMDViewer-003", + "REQ-ThreeMDViewer-004" + ] + } + ] +} diff --git a/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/verification.json b/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/verification.json new file mode 100644 index 00000000..02755cf3 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/verification.json @@ -0,0 +1,115 @@ +{ + "timestamp": 1791650874, + "commit": "47e18d32375406f98df343f4a580ea3e98f6d32d", + "contract_digest": "3b63dbbb2bbe4105992cc11edf9c9e5af29cf072884081c8329b2389d8116e6d", + "execution_digest": "ca236272754b3912cc5221e45a62020c70ffb0bb389840b6fb33d745834b8707", + "workspace_digest": "94bd7478dfb8735a51286b1c04445028dc910df8754b57775bc06773797a4420", + "acceptance_input_digest": "07e830005117d0349f94b4a1998d26f9c3fe91fc324f41a2f31c8d2555af7d83", + "acceptance_manifest": { + "schema_version": 1, + "entries": [ + { + "path": "hi/tools.md", + "kind": "file", + "mode": 33188, + "payload_digest": "a76304c2e07c30d6b289bd023e06e13d6ed830d56c173f0804d698a37d3848c6", + "entry_digest": "0708d4e1a5c692b379dbf8aeea378f07e8c05c29b09beb4cd103fabf10e3461d", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "specs/ThreeMDViewer", + "kind": "non_file", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "b53a01354acef7fb830687d9789c70f85c60f43e94da4a2dd0816c771a3bf773", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/ThreeMDViewer.spec.md", + "kind": "file", + "mode": 33188, + "payload_digest": "5179c246eb258124753ca8d43972397d7e4f4e127f328b08e850de0a384c85ae", + "entry_digest": "a37f342f975c33eb5ca5fbc7cdef521c1acbe4a5c2a1b5696148da3d4d92ecb4", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/context.md", + "kind": "file", + "mode": 33188, + "payload_digest": "a7ab898f969d9ff40b61db395ce087ae405c91ee030eac801841b61f5620b1a2", + "entry_digest": "ebb8aad85405c195091c5abe00fd981bc7b136341b46118384e1d34ea35a965f", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/requirements.md", + "kind": "file", + "mode": 33188, + "payload_digest": "85322d8b84eff25c4d066df2c18d0151f91840366b142063b01f394d52a418ee", + "entry_digest": "7a0a9b1a29b3873df944466ee2b1171c8130aac2caa2ce4727aff1d154b53f6a", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/tasks.md", + "kind": "file", + "mode": 33188, + "payload_digest": "6f50ec382d73d01804ec0a8b9712a3df6f4c3106d831e380151ddd08ca079dcb", + "entry_digest": "79d6c9552eb5eb74e8bea36ab47c5a85baceab186fa2543e267507b89e900848", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/testing.md", + "kind": "file", + "mode": 33188, + "payload_digest": "77e9e80d5ece361fbbeab6965779db0d043476558b73091ea06f4c5f01142f13", + "entry_digest": "fd7665984f3453381ff2b848e3507cdead5297842b8f6faffa9e67e1587ba6e8", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "uitests/viewer.spec.mjs", + "kind": "file", + "mode": 33188, + "payload_digest": "f8e7b1065581569ed471058c7e73bd31b66105306a0d67b903d300cd42caa4d3", + "entry_digest": "0d075959cdfcbc0940a8d5048812aeb330a61816a336b449e9c8ed77032df6ba", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "web/viewer.html", + "kind": "file", + "mode": 33188, + "payload_digest": "2e8fb29cf6e6996898d5ac39378d0bd42ff9bbaaf694c9dfbda876c6904b8a3c", + "entry_digest": "5355f2ce99c31879e758968500c49d8912e2f39a7eb9b985571fc5e260fe2641", + "owners": [ + "ThreeMDViewer" + ] + } + ] + }, + "passed": true, + "commands": [ + { + "command": "specsync check --spec ThreeMDViewer", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [ + "REQ-ThreeMDViewer-003", + "REQ-ThreeMDViewer-004" + ] +} diff --git a/.specsync/archive/changes/2026-10-10-record-viewer-navigation-verification-evidence-for-the-approved-archive/accepted-state.json b/.specsync/archive/changes/2026-10-10-record-viewer-navigation-verification-evidence-for-the-approved-archive/accepted-state.json new file mode 100644 index 00000000..f37f77f8 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-record-viewer-navigation-verification-evidence-for-the-approved-archive/accepted-state.json @@ -0,0 +1,36 @@ +{ + "schema_version": 1, + "workflow_version": 2, + "workflow_origin_version": 2, + "id": "record-viewer-navigation-verification-evidence-for-the-approved-archive", + "slug": "record-viewer-navigation-verification-evidence-for-the-approved-archive", + "title": "Record viewer navigation verification evidence for the approved archive", + "description": "Record viewer navigation verification evidence for the approved archive", + "kind": "documentation", + "state": "accepted", + "canonical_applied": true, + "base_commit": "fefd8316adfff3af8bdb87d26b4a417650540b56", + "created_at": 1791643208, + "updated_at": 1791651315, + "affected_specs": [ + "ThreeMDViewer" + ], + "affected_paths": [ + "docs/evidence/viewer-navigation", + "docs/evidence/viewer-camera" + ], + "no_spec_change": true, + "no_spec_change_rationale": "Declare the existing PR 93 screenshots and verification README for complete delivery coverage; viewer behavior remains in the approved workspace change and no canonical contract change is required for evidence files.", + "acceptance_criteria": [ + "Record actual navigation and camera verification results and screenshots while preserving test and provenance limitations" + ], + "selected_artifacts": [ + "context", + "docs" + ], + "dependencies": [], + "answers": { + "architecture_risk": "no", + "public_contract": "no" + } +} diff --git a/.specsync/archive/changes/2026-10-10-record-viewer-navigation-verification-evidence-for-the-approved-archive/approvals.json b/.specsync/archive/changes/2026-10-10-record-viewer-navigation-verification-evidence-for-the-approved-archive/approvals.json new file mode 100644 index 00000000..e4cb1630 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-record-viewer-navigation-verification-evidence-for-the-approved-archive/approvals.json @@ -0,0 +1,45 @@ +{ + "approvals": [ + { + "gate": "definition", + "actor": "user:0xLeif", + "timestamp": 1791647235, + "digest": "7b6ea3e8aed7f48a86cf966b2975ca9ef04a2e023c3a5f51402f7e0e34dab65b", + "note": "Leif approved the viewer definition and verified closure and explicitly selected Approve camera parity and verified closure on 2026-10-10. This evidence-only record declares the navigation and camera receipts required by those approvals. It does not claim a new product-scope approval or user diff review.", + "approved_scope": { + "schema_version": 1, + "change_id": "record-viewer-navigation-verification-evidence-for-the-approved-archive", + "title": "Record viewer navigation verification evidence for the approved archive", + "description": "Record viewer navigation verification evidence for the approved archive", + "kind": "documentation", + "affected_specs": [ + "ThreeMDViewer" + ], + "affected_paths": [ + "docs/evidence/viewer-camera", + "docs/evidence/viewer-navigation" + ], + "no_spec_change": true, + "no_spec_change_rationale": "Declare the existing PR 93 screenshots and verification README for complete delivery coverage; viewer behavior remains in the approved workspace change and no canonical contract change is required for evidence files.", + "acceptance_criteria": [ + "Record actual navigation and camera verification results and screenshots while preserving test and provenance limitations" + ], + "dependencies": [], + "supersedes": [], + "answers": { + "architecture_risk": "no", + "public_contract": "no" + } + }, + "approved_delta_digests": {} + }, + { + "gate": "finalization", + "actor": "specsync:finalization", + "timestamp": 1791651315, + "digest": "995f61cb09f689a105231cb2c92aeb2ab963d65cd03404150333466b4423ddd5", + "note": "Same-PR finalization closing digest" + } + ], + "reopenings": [] +} diff --git a/.specsync/archive/changes/2026-10-10-record-viewer-navigation-verification-evidence-for-the-approved-archive/change.md b/.specsync/archive/changes/2026-10-10-record-viewer-navigation-verification-evidence-for-the-approved-archive/change.md new file mode 100644 index 00000000..58cc8561 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-record-viewer-navigation-verification-evidence-for-the-approved-archive/change.md @@ -0,0 +1,24 @@ +--- +id: record-viewer-navigation-verification-evidence-for-the-approved-archive +state: archived +type: documentation +base_commit: fefd8316adfff3af8bdb87d26b4a417650540b56 +--- + +# Record viewer navigation verification evidence for the approved archive + +## Intent + +Record viewer navigation verification evidence for the approved archive + +## Affected Canonical Specs + +- `ThreeMDViewer` + +## Acceptance Criteria + +- Record actual navigation and camera verification results and screenshots while preserving test and provenance limitations + +## No-spec Rationale + +Declare the existing PR 93 screenshots and verification README for complete delivery coverage; viewer behavior remains in the approved workspace change and no canonical contract change is required for evidence files. diff --git a/.specsync/archive/changes/2026-10-10-record-viewer-navigation-verification-evidence-for-the-approved-archive/context.md b/.specsync/archive/changes/2026-10-10-record-viewer-navigation-verification-evidence-for-the-approved-archive/context.md new file mode 100644 index 00000000..3dbd53ce --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-record-viewer-navigation-verification-evidence-for-the-approved-archive/context.md @@ -0,0 +1,8 @@ +--- +change: record-viewer-navigation-verification-evidence-for-the-approved-archive +artifact: context +--- + +# Context + +This record declares the already-authorized verification outputs for PR 93: navigation screenshots and the current camera parity fixture, screenshots and actual test receipts. Leif approved the viewer definition and verified closure, then explicitly selected camera parity and verified closure on 2026-10-10. These files provide evidence for the separately approved behavior rather than adding a new product contract. Current camera tests and screenshots are recorded in docs/evidence/viewer-camera/README.md. Historical navigation receipts remain in docs/evidence/viewer-navigation/README.md. Keep actual test, lifecycle and provenance limitations explicit. No independent human review or signature is claimed. diff --git a/.specsync/archive/changes/2026-10-10-record-viewer-navigation-verification-evidence-for-the-approved-archive/docs.md b/.specsync/archive/changes/2026-10-10-record-viewer-navigation-verification-evidence-for-the-approved-archive/docs.md new file mode 100644 index 00000000..f7ef7065 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-record-viewer-navigation-verification-evidence-for-the-approved-archive/docs.md @@ -0,0 +1,8 @@ +--- +change: record-viewer-navigation-verification-evidence-for-the-approved-archive +artifact: docs +--- + +# Evidence documentation + +The navigation and camera README files identify the tested behavior and limits. Camera parity uses one asymmetric scene and double-precision expected screen coordinates shared by browser and native tests. Current screenshots show Orbit, Pan, Fit and zoom and identify native inspection as an isolated agent preview. Test receipts distinguish current full suites, targeted reruns and pending gates. Future axis gizmo controls are a separate unapproved definition. Evidence never claims user diff review, independent review, successful archiving or signed provenance from scope approval alone. diff --git a/.specsync/archive/changes/2026-10-10-record-viewer-navigation-verification-evidence-for-the-approved-archive/finalization.json b/.specsync/archive/changes/2026-10-10-record-viewer-navigation-verification-evidence-for-the-approved-archive/finalization.json new file mode 100644 index 00000000..447ea14d --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-record-viewer-navigation-verification-evidence-for-the-approved-archive/finalization.json @@ -0,0 +1,12 @@ +{ + "schema_version": 2, + "change_id": "record-viewer-navigation-verification-evidence-for-the-approved-archive", + "implementation_commit": "083a3d5c277be0cd736217ee097d7869f8ce3d50", + "implementation_tree": "2452daa10256ab1502fac576f59069b0704345e5", + "contract_digest": "7b6ea3e8aed7f48a86cf966b2975ca9ef04a2e023c3a5f51402f7e0e34dab65b", + "workspace_digest": "9d1d4246e27778537055a9cf87c785b56a67ce526c69f177ce47eb615ae9f480", + "closing_digest": "995f61cb09f689a105231cb2c92aeb2ab963d65cd03404150333466b4423ddd5", + "review_digest": "6196820f83574825561f0d0f9bb9fbd3db4d36ef13c4f0eb8e0dddfc2fec9f2c", + "finalization_digest": "f3b3be9d49f8182ecc63285db082220844c5840c96514cdd5a8588aef6be3b58", + "timestamp": 1791651315 +} diff --git a/.specsync/archive/changes/2026-10-10-record-viewer-navigation-verification-evidence-for-the-approved-archive/lesson-bundle.md b/.specsync/archive/changes/2026-10-10-record-viewer-navigation-verification-evidence-for-the-approved-archive/lesson-bundle.md new file mode 100644 index 00000000..114a7a91 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-record-viewer-navigation-verification-evidence-for-the-approved-archive/lesson-bundle.md @@ -0,0 +1,28 @@ +# Lesson bundle — record-viewer-navigation-verification-evidence-for-the-approved-archive + +Material for folding this change's lessons into the affected specs' `context.md`. +Synthesise from what actually happened below; do not restate the change description. + +## What this change was + +- **Title**: Record viewer navigation verification evidence for the approved archive +- **Kind**: Documentation +- **Specs**: ThreeMDViewer +- **Paths**: docs/evidence/viewer-navigation, docs/evidence/viewer-camera +- **Acceptance**: Record actual navigation and camera verification results and screenshots while preserving test and provenance limitations + +## Evidence + +- Verification commit: `083a3d5c277be0cd736217ee097d7869f8ce3d50` +- Base commit: `fefd8316adfff3af8bdb87d26b4a417650540b56` +- Verified by: `specsync check --spec ThreeMDViewer` + +## From the change's context.md + +# Context + +This record declares the already-authorized verification outputs for PR 93: navigation screenshots and the current camera parity fixture, screenshots and actual test receipts. Leif approved the viewer definition and verified closure, then explicitly selected camera parity and verified closure on 2026-10-10. These files provide evidence for the separately approved behavior rather than adding a new product contract. Current camera tests and screenshots are recorded in docs/evidence/viewer-camera/README.md. Historical navigation receipts remain in docs/evidence/viewer-navigation/README.md. Keep actual test, lifecycle and provenance limitations explicit. No independent human review or signature is claimed. + +## Where these lessons go + +- `specs/ThreeMDViewer/context.md` diff --git a/.specsync/archive/changes/2026-10-10-record-viewer-navigation-verification-evidence-for-the-approved-archive/review-attempts.json b/.specsync/archive/changes/2026-10-10-record-viewer-navigation-verification-evidence-for-the-approved-archive/review-attempts.json new file mode 100644 index 00000000..4f2042de --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-record-viewer-navigation-verification-evidence-for-the-approved-archive/review-attempts.json @@ -0,0 +1,21 @@ +{ + "schema_version": 1, + "reviews": [ + { + "schema_version": 2, + "change_id": "record-viewer-navigation-verification-evidence-for-the-approved-archive", + "reviewer": "agent:codex", + "provenance": { + "schema_version": 1, + "provider": "github_actions_check", + "required_check": "SpecSync scoped review" + }, + "verdict": "pass", + "implementation_commit": "083a3d5c277be0cd736217ee097d7869f8ce3d50", + "contract_digest": "7b6ea3e8aed7f48a86cf966b2975ca9ef04a2e023c3a5f51402f7e0e34dab65b", + "execution_digest": "82d20742b15bee6a2b3aef0963278bb44b079661b72598eae0ced2bef0932944", + "workspace_digest": "9d1d4246e27778537055a9cf87c785b56a67ce526c69f177ce47eb615ae9f480", + "timestamp": 1791651286 + } + ] +} diff --git a/.specsync/archive/changes/2026-10-10-record-viewer-navigation-verification-evidence-for-the-approved-archive/review.json b/.specsync/archive/changes/2026-10-10-record-viewer-navigation-verification-evidence-for-the-approved-archive/review.json new file mode 100644 index 00000000..4e03c4cf --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-record-viewer-navigation-verification-evidence-for-the-approved-archive/review.json @@ -0,0 +1,16 @@ +{ + "schema_version": 2, + "change_id": "record-viewer-navigation-verification-evidence-for-the-approved-archive", + "reviewer": "agent:codex", + "provenance": { + "schema_version": 1, + "provider": "github_actions_check", + "required_check": "SpecSync scoped review" + }, + "verdict": "pass", + "implementation_commit": "083a3d5c277be0cd736217ee097d7869f8ce3d50", + "contract_digest": "7b6ea3e8aed7f48a86cf966b2975ca9ef04a2e023c3a5f51402f7e0e34dab65b", + "execution_digest": "82d20742b15bee6a2b3aef0963278bb44b079661b72598eae0ced2bef0932944", + "workspace_digest": "9d1d4246e27778537055a9cf87c785b56a67ce526c69f177ce47eb615ae9f480", + "timestamp": 1791651286 +} diff --git a/.specsync/archive/changes/2026-10-10-record-viewer-navigation-verification-evidence-for-the-approved-archive/state.json b/.specsync/archive/changes/2026-10-10-record-viewer-navigation-verification-evidence-for-the-approved-archive/state.json new file mode 100644 index 00000000..c964a28b --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-record-viewer-navigation-verification-evidence-for-the-approved-archive/state.json @@ -0,0 +1,36 @@ +{ + "schema_version": 1, + "workflow_version": 2, + "workflow_origin_version": 2, + "id": "record-viewer-navigation-verification-evidence-for-the-approved-archive", + "slug": "record-viewer-navigation-verification-evidence-for-the-approved-archive", + "title": "Record viewer navigation verification evidence for the approved archive", + "description": "Record viewer navigation verification evidence for the approved archive", + "kind": "documentation", + "state": "archived", + "canonical_applied": true, + "base_commit": "fefd8316adfff3af8bdb87d26b4a417650540b56", + "created_at": 1791643208, + "updated_at": 1791651372, + "affected_specs": [ + "ThreeMDViewer" + ], + "affected_paths": [ + "docs/evidence/viewer-navigation", + "docs/evidence/viewer-camera" + ], + "no_spec_change": true, + "no_spec_change_rationale": "Declare the existing PR 93 screenshots and verification README for complete delivery coverage; viewer behavior remains in the approved workspace change and no canonical contract change is required for evidence files.", + "acceptance_criteria": [ + "Record actual navigation and camera verification results and screenshots while preserving test and provenance limitations" + ], + "selected_artifacts": [ + "context", + "docs" + ], + "dependencies": [], + "answers": { + "architecture_risk": "no", + "public_contract": "no" + } +} diff --git a/.specsync/archive/changes/2026-10-10-record-viewer-navigation-verification-evidence-for-the-approved-archive/verification-attempts.json b/.specsync/archive/changes/2026-10-10-record-viewer-navigation-verification-evidence-for-the-approved-archive/verification-attempts.json new file mode 100644 index 00000000..72fe1bd3 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-record-viewer-navigation-verification-evidence-for-the-approved-archive/verification-attempts.json @@ -0,0 +1,277 @@ +{ + "schema_version": 1, + "attempts": [ + { + "timestamp": 1791647869, + "commit": "1e56f9bc3ea3d891143bab01778e28bec7852d29", + "contract_digest": "7b6ea3e8aed7f48a86cf966b2975ca9ef04a2e023c3a5f51402f7e0e34dab65b", + "execution_digest": "82d20742b15bee6a2b3aef0963278bb44b079661b72598eae0ced2bef0932944", + "workspace_digest": "1fe89875c5f9e17b3f56b2e358519c256a4f2c83f55f5d95221dabd8b5a8ce0c", + "passed": true, + "commands": [ + { + "command": "specsync check --spec ThreeMDViewer", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [] + }, + { + "timestamp": 1791647887, + "commit": "53a4c199d789267b3834140178430217cee602a8", + "contract_digest": "7b6ea3e8aed7f48a86cf966b2975ca9ef04a2e023c3a5f51402f7e0e34dab65b", + "execution_digest": "82d20742b15bee6a2b3aef0963278bb44b079661b72598eae0ced2bef0932944", + "workspace_digest": "1fe89875c5f9e17b3f56b2e358519c256a4f2c83f55f5d95221dabd8b5a8ce0c", + "passed": true, + "commands": [ + { + "command": "specsync check --spec ThreeMDViewer", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [] + }, + { + "timestamp": 1791648135, + "commit": "fbfb7a5a97f155744383b3282ec00f363c4ee874", + "contract_digest": "7b6ea3e8aed7f48a86cf966b2975ca9ef04a2e023c3a5f51402f7e0e34dab65b", + "execution_digest": "82d20742b15bee6a2b3aef0963278bb44b079661b72598eae0ced2bef0932944", + "workspace_digest": "1fe89875c5f9e17b3f56b2e358519c256a4f2c83f55f5d95221dabd8b5a8ce0c", + "passed": true, + "commands": [ + { + "command": "specsync check --spec ThreeMDViewer --strict", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [] + }, + { + "timestamp": 1791651244, + "commit": "c26fdfce25179ec22d69fe82a2fcea26ff8488c7", + "contract_digest": "7b6ea3e8aed7f48a86cf966b2975ca9ef04a2e023c3a5f51402f7e0e34dab65b", + "execution_digest": "82d20742b15bee6a2b3aef0963278bb44b079661b72598eae0ced2bef0932944", + "workspace_digest": "9d1d4246e27778537055a9cf87c785b56a67ce526c69f177ce47eb615ae9f480", + "passed": true, + "commands": [ + { + "command": "specsync check --spec ThreeMDViewer", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [] + }, + { + "timestamp": 1791651262, + "commit": "7161e4d83ee37916e19c88e082d4aef7d4571332", + "contract_digest": "7b6ea3e8aed7f48a86cf966b2975ca9ef04a2e023c3a5f51402f7e0e34dab65b", + "execution_digest": "82d20742b15bee6a2b3aef0963278bb44b079661b72598eae0ced2bef0932944", + "workspace_digest": "9d1d4246e27778537055a9cf87c785b56a67ce526c69f177ce47eb615ae9f480", + "passed": true, + "commands": [ + { + "command": "specsync check --spec ThreeMDViewer", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [] + }, + { + "timestamp": 1791651262, + "commit": "083a3d5c277be0cd736217ee097d7869f8ce3d50", + "contract_digest": "7b6ea3e8aed7f48a86cf966b2975ca9ef04a2e023c3a5f51402f7e0e34dab65b", + "execution_digest": "82d20742b15bee6a2b3aef0963278bb44b079661b72598eae0ced2bef0932944", + "workspace_digest": "9d1d4246e27778537055a9cf87c785b56a67ce526c69f177ce47eb615ae9f480", + "acceptance_input_digest": "07eb2a36893013f4c919ac965ca1f085b83eceadbea01d7e13e746e376f2fde4", + "acceptance_manifest": { + "schema_version": 1, + "entries": [ + { + "path": "docs/evidence/viewer-camera", + "kind": "non_file", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "0224f6df0a928630c9021722c48f51397f4befa92b9282fa946a3f238b7ee5ab", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-camera/README.md", + "kind": "file", + "mode": 33188, + "payload_digest": "53bbe5a8d8f4f2f17ebea677fca24661c1f43024bdd14b6bc02053c14a995258", + "entry_digest": "71cee6cd930a4a86f485c6dde97bf779494956a35795054d2a3d1108d904c52c", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-camera/camera-parity.3md", + "kind": "file", + "mode": 33188, + "payload_digest": "faa46b7ebb3f3c1c7a73413bfbbf3b08802e9a7d34503ef4d6ef14823160305c", + "entry_digest": "abe06f475c17303ca9cfaaf90da85464a10b1056e6a5bc9ef5c3d0c8897b5cef", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-camera/camera-parity.json", + "kind": "file", + "mode": 33188, + "payload_digest": "7aba56ae365864d46a79b0f9fe3fbfefff1bffc818ef12e1297291c00eef7969", + "entry_digest": "045ea0b36108124a822d94ea5a78574ab161f86c87f4a2a4244b6d8a77587ac2", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-camera/local-verification.json", + "kind": "file", + "mode": 33188, + "payload_digest": "1f65e49461641eadc2185139e5bb8e657ff144cd8ae8e5f64fda26a0332dc896", + "entry_digest": "562cb03a986d12c5035b27b6a3f7a804913ec9195d5294063260ac6116d36fdb", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-camera/sculpt-current.png", + "kind": "file", + "mode": 33188, + "payload_digest": "3b7d91b8f341b788076addbc48bcbc41136802648200ba64ae0f69df2a22f296", + "entry_digest": "01f02a65fd826a53e361216b12c8b2552b6db66fdd04acddf77044651af85849", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-camera/viewer-current.jpg", + "kind": "file", + "mode": 33188, + "payload_digest": "11fa94393462b83d7525c66387f28afdcb320ceaedd964204bd8b2ccdee65e3a", + "entry_digest": "8d44d08b523bf8f18a403ce2cc19ac339cc8dba82796719722ce5d068647eee5", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-navigation", + "kind": "non_file", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "4825c798737741569741a61f0e9e5354ccc4a2097b547f0551a4be8bb80b51cb", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-navigation/README.md", + "kind": "file", + "mode": 33188, + "payload_digest": "c7a8f3989ba219e1cdc3ffcb5a7b9742272e353b5dd19f29338e39f83d91af4d", + "entry_digest": "8bbf6aab36bbce8fc2641a632f77df43ad3a0a131b6d7c2aaa233506a57a1dac", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-navigation/desktop.jpg", + "kind": "file", + "mode": 33188, + "payload_digest": "ecfa9612c696c4bb815a8a34d0e0187be6d9e3df2040c05a28061946f51a48d5", + "entry_digest": "f375924f6c76ca8bd4e414cb0d8915d6b901d9f5770350a38921947f65a75075", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-navigation/phone-files.jpg", + "kind": "file", + "mode": 33188, + "payload_digest": "53802ebe42e86c58077dfee86489c648d9e93e22e5b3115e7a762a182ddead41", + "entry_digest": "2f14f232db596f47cb8836d83d0afaf82fe726b79fb725b498df4154331c6054", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-navigation/phone.jpg", + "kind": "file", + "mode": 33188, + "payload_digest": "66b256687d16e3c28992316287f07a6ab7d9c2b534dde5bed863abb72297e148", + "entry_digest": "2d859dd5e7a247e373c1591b028424eb87066e5b7feec5840729f8a4b0683c7a", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "specs/ThreeMDViewer/ThreeMDViewer.spec.md", + "kind": "file", + "mode": 33188, + "payload_digest": "5179c246eb258124753ca8d43972397d7e4f4e127f328b08e850de0a384c85ae", + "entry_digest": "a37f342f975c33eb5ca5fbc7cdef521c1acbe4a5c2a1b5696148da3d4d92ecb4", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/context.md", + "kind": "file", + "mode": 33188, + "payload_digest": "01c41362ddc8ac88b1c7baced558428b2083945ab29e4e8f1d428c32bbf186d5", + "entry_digest": "123abf2dcc8baffeaaa50e60f6b43fe681d912b8514616ba88019e8a3b4347e5", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/requirements.md", + "kind": "file", + "mode": 33188, + "payload_digest": "85322d8b84eff25c4d066df2c18d0151f91840366b142063b01f394d52a418ee", + "entry_digest": "7a0a9b1a29b3873df944466ee2b1171c8130aac2caa2ce4727aff1d154b53f6a", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/tasks.md", + "kind": "file", + "mode": 33188, + "payload_digest": "522a4319d65b92b58385ebd2324477b9cbfe4c7e32ca6dc4912ed57483cb1c85", + "entry_digest": "36a320b8026eb9a2936d247e843cfc857d5404feddc2c9e770096e9145264b0d", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/testing.md", + "kind": "file", + "mode": 33188, + "payload_digest": "77e9e80d5ece361fbbeab6965779db0d043476558b73091ea06f4c5f01142f13", + "entry_digest": "fd7665984f3453381ff2b848e3507cdead5297842b8f6faffa9e67e1587ba6e8", + "owners": [ + "ThreeMDViewer" + ] + } + ] + }, + "passed": true, + "commands": [ + { + "command": "specsync check --spec ThreeMDViewer", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [] + } + ] +} diff --git a/.specsync/archive/changes/2026-10-10-record-viewer-navigation-verification-evidence-for-the-approved-archive/verification.json b/.specsync/archive/changes/2026-10-10-record-viewer-navigation-verification-evidence-for-the-approved-archive/verification.json new file mode 100644 index 00000000..c8e94f01 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-record-viewer-navigation-verification-evidence-for-the-approved-archive/verification.json @@ -0,0 +1,192 @@ +{ + "timestamp": 1791651262, + "commit": "083a3d5c277be0cd736217ee097d7869f8ce3d50", + "contract_digest": "7b6ea3e8aed7f48a86cf966b2975ca9ef04a2e023c3a5f51402f7e0e34dab65b", + "execution_digest": "82d20742b15bee6a2b3aef0963278bb44b079661b72598eae0ced2bef0932944", + "workspace_digest": "9d1d4246e27778537055a9cf87c785b56a67ce526c69f177ce47eb615ae9f480", + "acceptance_input_digest": "07eb2a36893013f4c919ac965ca1f085b83eceadbea01d7e13e746e376f2fde4", + "acceptance_manifest": { + "schema_version": 1, + "entries": [ + { + "path": "docs/evidence/viewer-camera", + "kind": "non_file", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "0224f6df0a928630c9021722c48f51397f4befa92b9282fa946a3f238b7ee5ab", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-camera/README.md", + "kind": "file", + "mode": 33188, + "payload_digest": "53bbe5a8d8f4f2f17ebea677fca24661c1f43024bdd14b6bc02053c14a995258", + "entry_digest": "71cee6cd930a4a86f485c6dde97bf779494956a35795054d2a3d1108d904c52c", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-camera/camera-parity.3md", + "kind": "file", + "mode": 33188, + "payload_digest": "faa46b7ebb3f3c1c7a73413bfbbf3b08802e9a7d34503ef4d6ef14823160305c", + "entry_digest": "abe06f475c17303ca9cfaaf90da85464a10b1056e6a5bc9ef5c3d0c8897b5cef", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-camera/camera-parity.json", + "kind": "file", + "mode": 33188, + "payload_digest": "7aba56ae365864d46a79b0f9fe3fbfefff1bffc818ef12e1297291c00eef7969", + "entry_digest": "045ea0b36108124a822d94ea5a78574ab161f86c87f4a2a4244b6d8a77587ac2", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-camera/local-verification.json", + "kind": "file", + "mode": 33188, + "payload_digest": "1f65e49461641eadc2185139e5bb8e657ff144cd8ae8e5f64fda26a0332dc896", + "entry_digest": "562cb03a986d12c5035b27b6a3f7a804913ec9195d5294063260ac6116d36fdb", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-camera/sculpt-current.png", + "kind": "file", + "mode": 33188, + "payload_digest": "3b7d91b8f341b788076addbc48bcbc41136802648200ba64ae0f69df2a22f296", + "entry_digest": "01f02a65fd826a53e361216b12c8b2552b6db66fdd04acddf77044651af85849", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-camera/viewer-current.jpg", + "kind": "file", + "mode": 33188, + "payload_digest": "11fa94393462b83d7525c66387f28afdcb320ceaedd964204bd8b2ccdee65e3a", + "entry_digest": "8d44d08b523bf8f18a403ce2cc19ac339cc8dba82796719722ce5d068647eee5", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-navigation", + "kind": "non_file", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "4825c798737741569741a61f0e9e5354ccc4a2097b547f0551a4be8bb80b51cb", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-navigation/README.md", + "kind": "file", + "mode": 33188, + "payload_digest": "c7a8f3989ba219e1cdc3ffcb5a7b9742272e353b5dd19f29338e39f83d91af4d", + "entry_digest": "8bbf6aab36bbce8fc2641a632f77df43ad3a0a131b6d7c2aaa233506a57a1dac", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-navigation/desktop.jpg", + "kind": "file", + "mode": 33188, + "payload_digest": "ecfa9612c696c4bb815a8a34d0e0187be6d9e3df2040c05a28061946f51a48d5", + "entry_digest": "f375924f6c76ca8bd4e414cb0d8915d6b901d9f5770350a38921947f65a75075", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-navigation/phone-files.jpg", + "kind": "file", + "mode": 33188, + "payload_digest": "53802ebe42e86c58077dfee86489c648d9e93e22e5b3115e7a762a182ddead41", + "entry_digest": "2f14f232db596f47cb8836d83d0afaf82fe726b79fb725b498df4154331c6054", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-navigation/phone.jpg", + "kind": "file", + "mode": 33188, + "payload_digest": "66b256687d16e3c28992316287f07a6ab7d9c2b534dde5bed863abb72297e148", + "entry_digest": "2d859dd5e7a247e373c1591b028424eb87066e5b7feec5840729f8a4b0683c7a", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "specs/ThreeMDViewer/ThreeMDViewer.spec.md", + "kind": "file", + "mode": 33188, + "payload_digest": "5179c246eb258124753ca8d43972397d7e4f4e127f328b08e850de0a384c85ae", + "entry_digest": "a37f342f975c33eb5ca5fbc7cdef521c1acbe4a5c2a1b5696148da3d4d92ecb4", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/context.md", + "kind": "file", + "mode": 33188, + "payload_digest": "01c41362ddc8ac88b1c7baced558428b2083945ab29e4e8f1d428c32bbf186d5", + "entry_digest": "123abf2dcc8baffeaaa50e60f6b43fe681d912b8514616ba88019e8a3b4347e5", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/requirements.md", + "kind": "file", + "mode": 33188, + "payload_digest": "85322d8b84eff25c4d066df2c18d0151f91840366b142063b01f394d52a418ee", + "entry_digest": "7a0a9b1a29b3873df944466ee2b1171c8130aac2caa2ce4727aff1d154b53f6a", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/tasks.md", + "kind": "file", + "mode": 33188, + "payload_digest": "522a4319d65b92b58385ebd2324477b9cbfe4c7e32ca6dc4912ed57483cb1c85", + "entry_digest": "36a320b8026eb9a2936d247e843cfc857d5404feddc2c9e770096e9145264b0d", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/testing.md", + "kind": "file", + "mode": 33188, + "payload_digest": "77e9e80d5ece361fbbeab6965779db0d043476558b73091ea06f4c5f01142f13", + "entry_digest": "fd7665984f3453381ff2b848e3507cdead5297842b8f6faffa9e67e1587ba6e8", + "owners": [ + "ThreeMDViewer" + ] + } + ] + }, + "passed": true, + "commands": [ + { + "command": "specsync check --spec ThreeMDViewer", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [] +} diff --git a/.specsync/archive/changes/2026-10-10-repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera/accepted-state.json b/.specsync/archive/changes/2026-10-10-repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera/accepted-state.json new file mode 100644 index 00000000..82afd6c3 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera/accepted-state.json @@ -0,0 +1,39 @@ +{ + "schema_version": 1, + "workflow_version": 2, + "workflow_origin_version": 2, + "id": "repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera", + "slug": "repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera", + "title": "Repair blurry Cubes and Slice canvases after view and display-size changes while retaining the WebGL context and camera parity", + "description": "Repair blurry Cubes and Slice canvases after view and display-size changes while retaining the WebGL context and camera parity", + "kind": "bug_fix", + "state": "accepted", + "canonical_applied": true, + "base_commit": "dab4258541208f8bf6bb5a38f6200a5b348a858e", + "created_at": 1791656681, + "updated_at": 1791657999, + "affected_specs": [ + "ThreeMDViewer" + ], + "affected_paths": [ + "web/viewer.html", + "uitests/viewer.spec.mjs", + "specs/ThreeMDViewer", + "docs/evidence/viewer-resolution" + ], + "no_spec_change": false, + "no_spec_change_rationale": null, + "acceptance_criteria": [ + "The shared 3D canvas drawing buffer follows the displayed Cubes or Slice-reference size and device pixel ratio within the existing 2048-edge/2x limits; switching from a small reference or phone viewport to a large stage remains sharp; resizing retains the same WebGL context, geometry and camera/source/selection; Chromium, WebKit and the actual in-app browser verify transitions and picking." + ], + "selected_artifacts": [ + "context", + "testing", + "tasks" + ], + "dependencies": [], + "answers": { + "architecture_risk": "no", + "public_contract": "no" + } +} diff --git a/.specsync/archive/changes/2026-10-10-repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera/approvals.json b/.specsync/archive/changes/2026-10-10-repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera/approvals.json new file mode 100644 index 00000000..e6198206 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera/approvals.json @@ -0,0 +1,49 @@ +{ + "approvals": [ + { + "gate": "definition", + "actor": "agent:codex", + "timestamp": 1791656803, + "digest": "2434816b883b109a6be3b8d0f9f72837258bc21346df7a0d4357d9df27fe8dd0", + "note": "Codex records the narrow corrective scope under Leif’s standing direct authorization to keep improving browser/Sculpt parity and fix PR 93, prompted by the current blur report. This applies existing repair authority; it is not a claim of a new human definition review, Leif diff review, independent review or signature.", + "approved_scope": { + "schema_version": 1, + "change_id": "repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera", + "title": "Repair blurry Cubes and Slice canvases after view and display-size changes while retaining the WebGL context and camera parity", + "description": "Repair blurry Cubes and Slice canvases after view and display-size changes while retaining the WebGL context and camera parity", + "kind": "bug_fix", + "affected_specs": [ + "ThreeMDViewer" + ], + "affected_paths": [ + "docs/evidence/viewer-resolution", + "specs/ThreeMDViewer", + "uitests/viewer.spec.mjs", + "web/viewer.html" + ], + "no_spec_change": false, + "no_spec_change_rationale": null, + "acceptance_criteria": [ + "The shared 3D canvas drawing buffer follows the displayed Cubes or Slice-reference size and device pixel ratio within the existing 2048-edge/2x limits; switching from a small reference or phone viewport to a large stage remains sharp; resizing retains the same WebGL context, geometry and camera/source/selection; Chromium, WebKit and the actual in-app browser verify transitions and picking." + ], + "dependencies": [], + "supersedes": [], + "answers": { + "architecture_risk": "no", + "public_contract": "no" + } + }, + "approved_delta_digests": { + "ThreeMDViewer": "77b5cd3341a46906bd1c09ba7e2e6c3bff2aa8f9c8e30c453b632c680c52fed9" + } + }, + { + "gate": "finalization", + "actor": "specsync:finalization", + "timestamp": 1791657999, + "digest": "35f18f24b91066a63ba3add8c3a8035b64813c30cdce7b5322583a08ad75eb3a", + "note": "Same-PR finalization closing digest" + } + ], + "reopenings": [] +} diff --git a/.specsync/archive/changes/2026-10-10-repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera/change.md b/.specsync/archive/changes/2026-10-10-repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera/change.md new file mode 100644 index 00000000..b5838977 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera/change.md @@ -0,0 +1,24 @@ +--- +id: repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera +state: archived +type: bug_fix +base_commit: dab4258541208f8bf6bb5a38f6200a5b348a858e +--- + +# Repair blurry Cubes and Slice canvases after view and display-size changes while retaining the WebGL context and camera parity + +## Intent + +Repair blurry Cubes and Slice canvases after view and display-size changes while retaining the WebGL context and camera parity + +## Affected Canonical Specs + +- `ThreeMDViewer` + +## Acceptance Criteria + +- The shared 3D canvas drawing buffer follows the displayed Cubes or Slice-reference size and device pixel ratio within the existing 2048-edge/2x limits; switching from a small reference or phone viewport to a large stage remains sharp; resizing retains the same WebGL context, geometry and camera/source/selection; Chromium, WebKit and the actual in-app browser verify transitions and picking. + +## No-spec Rationale + +Not applicable diff --git a/.specsync/archive/changes/2026-10-10-repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera/context.md b/.specsync/archive/changes/2026-10-10-repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera/context.md new file mode 100644 index 00000000..616d215d --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera/context.md @@ -0,0 +1,10 @@ +--- +change: repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera +artifact: context +--- + +# Context + +Leif reported the existing browser preview was blurry after the approved Slice/camera work. Actual DOM and screenshot inspection found the shared 3D canvas bitmap at 368x322 while its Cubes display was 1099x911. The bitmap was frozen after initial context creation as a Safari workaround; a phone/reference-sized initialization was later stretched across a desktop stage. + +This repairs the existing approved viewer/Sculpt-quality behavior under Leif's standing request to continue improving the browser and fix the viewer PR. It adds no editing tool, storage behavior, renderer or camera convention. Preserve the single WebGL context, installed mesh, source, selection, pose, 2x density cap and 2048 pixel edge cap. Resize only the drawable when its required dimensions change; validate actual in-app WebKit behavior rather than assuming every resize loses its context. diff --git a/.specsync/archive/changes/2026-10-10-repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera/deltas/ThreeMDViewer.md b/.specsync/archive/changes/2026-10-10-repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera/deltas/ThreeMDViewer.md new file mode 100644 index 00000000..6cfca25e --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera/deltas/ThreeMDViewer.md @@ -0,0 +1,15 @@ +# ThreeMDViewer delta + +## MODIFIED + +### REQUIREMENT REQ-ThreeMDViewer-004 + +The viewer page SHALL NOT offer a render-mode switch and SHALL NOT autoplay. Preview SHALL stay on one plane. Cubes SHALL draw complete, nearly cell-sized cubes with WebGL2, lit glyph-colored fill at 0.5 opacity and visible glyph-colored edges. The selected Z slice SHALL have gold edges at 0.8 opacity while retaining its glyph fill. The background SHALL be rgb(0.065, 0.085, 0.10). X SHALL be the column, Y the text row with row 0 toward the top, and Z the plane index. Orbit, zoom, and slice selection SHALL reuse the installed geometry. Each redraw SHALL use one instanced draw. Orbit SHALL rotate through full horizontal and vertical turns with a continuous camera basis at the poles. Pan mode, Shift-drag, and middle/right-drag SHALL move the view in screen space. Shift-arrow keys SHALL pan the focused canvas. Two-finger touch gestures SHALL pan and pinch to zoom. Wheel zoom SHALL respond proportionally to the gesture. Fit SHALL restore yaw 0.6, pitch 0.35, zoom 1, and zero pan without changing source or the selected slice. Camera buttons and the focused canvas SHALL support bounded zoom, and arrow keys SHALL orbit the focused canvas. Camera controls SHALL sit below the drawing without covering cubes. A document without a cube grid and an unavailable WebGL2 context SHALL offer Preview while preserving the source. The element bundle SHALL stay a text renderer. + +Acceptance Criteria: + +- The page has no render-mode menu and no page play control. A frame-axis document is not playing. +- A fenced grid draws on WebGL2, including about 1400 cubes. A single cell has filled faces from every side. Selection changes edge color while the face interior keeps its glyph color. Camera, zoom, and selection redraw without geometry uploads. Click picking selects the nearest visible cube’s Z slice. +- X is the column, Y is the text row with row 0 toward the top, and Z is the plane index. Space, dot, and tab are empty. Keep the 64 by 64 per-plane and 4000-cell caps. +- Evidence is VIEWER-6 and the cube tests in `uitests/viewer.spec.mjs`. +- The same 3D context and geometry remain installed when moving between Cubes and the Slice reference or changing display size. The drawable follows the visible pane size and device pixel ratio, bounded to 2x and a proportional 2048-pixel edge cap; unchanged sizes avoid bitmap reallocations. Small-to-large, phone/desktop and Retina transitions remain sharp without changing source, camera, slice or nearest picking. diff --git a/.specsync/archive/changes/2026-10-10-repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera/finalization.json b/.specsync/archive/changes/2026-10-10-repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera/finalization.json new file mode 100644 index 00000000..b11b4dda --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera/finalization.json @@ -0,0 +1,12 @@ +{ + "schema_version": 2, + "change_id": "repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera", + "implementation_commit": "57a2db9ac4e98000a36aa9660df39e74aa21e17b", + "implementation_tree": "7f0597b4ae0f13eadb2f00388b1b6c7bb5216796", + "contract_digest": "2434816b883b109a6be3b8d0f9f72837258bc21346df7a0d4357d9df27fe8dd0", + "workspace_digest": "8d823c7fee2b7188d8da38049f5c4691eed8c49ad8f71a6b4210edcb9d2492b3", + "closing_digest": "35f18f24b91066a63ba3add8c3a8035b64813c30cdce7b5322583a08ad75eb3a", + "review_digest": "7ab87f1a1b99acbf5bff08b07a16dc0b0b0f78c182d1b962b8ad72b1e68549bd", + "finalization_digest": "7dce16ee853ce3924ccc051ca1fbc17002d8c7871abb4f89660bd65b83bd4ecf", + "timestamp": 1791657999 +} diff --git a/.specsync/archive/changes/2026-10-10-repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera/lesson-bundle.md b/.specsync/archive/changes/2026-10-10-repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera/lesson-bundle.md new file mode 100644 index 00000000..fac5dd1d --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera/lesson-bundle.md @@ -0,0 +1,52 @@ +# Lesson bundle — repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera + +Material for folding this change's lessons into the affected specs' `context.md`. +Synthesise from what actually happened below; do not restate the change description. + +## What this change was + +- **Title**: Repair blurry Cubes and Slice canvases after view and display-size changes while retaining the WebGL context and camera parity +- **Kind**: BugFix +- **Specs**: ThreeMDViewer +- **Paths**: web/viewer.html, uitests/viewer.spec.mjs, specs/ThreeMDViewer, docs/evidence/viewer-resolution +- **Acceptance**: The shared 3D canvas drawing buffer follows the displayed Cubes or Slice-reference size and device pixel ratio within the existing 2048-edge/2x limits; switching from a small reference or phone viewport to a large stage remains sharp; resizing retains the same WebGL context, geometry and camera/source/selection; Chromium, WebKit and the actual in-app browser verify transitions and picking. + +## Evidence + +- Verification commit: `57a2db9ac4e98000a36aa9660df39e74aa21e17b` +- Base commit: `dab4258541208f8bf6bb5a38f6200a5b348a858e` +- Verified by: `specsync check --spec ThreeMDViewer --strict` + +## From the change's context.md + +# Context + +Leif reported the existing browser preview was blurry after the approved Slice/camera work. Actual DOM and screenshot inspection found the shared 3D canvas bitmap at 368x322 while its Cubes display was 1099x911. The bitmap was frozen after initial context creation as a Safari workaround; a phone/reference-sized initialization was later stretched across a desktop stage. + +This repairs the existing approved viewer/Sculpt-quality behavior under Leif's standing request to continue improving the browser and fix the viewer PR. It adds no editing tool, storage behavior, renderer or camera convention. Preserve the single WebGL context, installed mesh, source, selection, pose, 2x density cap and 2048 pixel edge cap. Resize only the drawable when its required dimensions change; validate actual in-app WebKit behavior rather than assuming every resize loses its context. + +## From the change's testing.md + +# Testing + +At device pixel ratios 1 and 2, initialize a phone-sized Cubes stage, switch through Slice's small reference and expand/resize to desktop and larger-than-cap layouts. Check actual drawable width/height against proportional 2048-edge/2x bounds, the same context/program/mesh, zero context-loss events and zero subsequent geometry uploads. Preserve source, selected slice, camera pose and nearest picking. Run existing projection, pixel, Slice and navigation regressions on Chromium and WebKit and inspect the actual in-app WebKit output. Root strict specs and pinned Trust must pass; actual unsigned agent:codex provenance remains separate from a permitted signature or human diff review. + +## Requirement evidence + +| ID | Canonical | Evidence | +| --- | --- | --- | +| REQ-ThreeMDViewer-004 | REQ-ThreeMDViewer-004 | New actual drawable-density and context-retention regression, existing GPU pixel/projection/picking tests, in-app browser before/after measurements and screenshot. | + +## Current results + +The complete post-resize UI suite passed 230 tests. After final display-density listeners, the viewer suite passed 130 tests. The final media-query/window-resize density regressions passed 4 tests. All ran on Chromium and WebKit without skips or retries. Actual in-app bitmap/display measurements and screenshots, test logs and implementation digests are in `docs/evidence/viewer-resolution/`. Pinned Trust, actual provenance and finalization remain separately evidenced. + +## Repository verification and provenance + +Pinned Trust 1.2.2 with Fledge 1.7.2 passed on implementation commit `95c1213886b853a7b945fd833a5af02fa0f8128d`; Augur returned review at risk 36, with configured soft provenance degradation. The full configured verification lane passed. Strict root specs passed at 55/55 files and Hi passed 87 criteria. Source digests above bind the browser results to this implementation; later lifecycle/materialization records do not change the HTML or tests. + +Actual unsigned agent:codex attestation was recorded after the lane passed. The unchanged strict Attest policy rejects the unavailable permitted signature and reviewer allow-list, as shown in `attest-policy.json`. This is not a human review or signed provenance claim, and no policy was changed. Lifecycle closure is recorded separately in its supported receipt. + +## Where these lessons go + +- `specs/ThreeMDViewer/context.md` diff --git a/.specsync/archive/changes/2026-10-10-repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera/review-attempts.json b/.specsync/archive/changes/2026-10-10-repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera/review-attempts.json new file mode 100644 index 00000000..3b71f2a4 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera/review-attempts.json @@ -0,0 +1,21 @@ +{ + "schema_version": 1, + "reviews": [ + { + "schema_version": 2, + "change_id": "repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera", + "reviewer": "agent:codex", + "provenance": { + "schema_version": 1, + "provider": "github_actions_check", + "required_check": "SpecSync scoped review" + }, + "verdict": "pass", + "implementation_commit": "57a2db9ac4e98000a36aa9660df39e74aa21e17b", + "contract_digest": "2434816b883b109a6be3b8d0f9f72837258bc21346df7a0d4357d9df27fe8dd0", + "execution_digest": "a67030d2d4fae6350ec00846e2a062e089570c761064ec0b92e2f51bc1fb7ceb", + "workspace_digest": "8d823c7fee2b7188d8da38049f5c4691eed8c49ad8f71a6b4210edcb9d2492b3", + "timestamp": 1791657975 + } + ] +} diff --git a/.specsync/archive/changes/2026-10-10-repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera/review.json b/.specsync/archive/changes/2026-10-10-repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera/review.json new file mode 100644 index 00000000..86102b62 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera/review.json @@ -0,0 +1,16 @@ +{ + "schema_version": 2, + "change_id": "repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera", + "reviewer": "agent:codex", + "provenance": { + "schema_version": 1, + "provider": "github_actions_check", + "required_check": "SpecSync scoped review" + }, + "verdict": "pass", + "implementation_commit": "57a2db9ac4e98000a36aa9660df39e74aa21e17b", + "contract_digest": "2434816b883b109a6be3b8d0f9f72837258bc21346df7a0d4357d9df27fe8dd0", + "execution_digest": "a67030d2d4fae6350ec00846e2a062e089570c761064ec0b92e2f51bc1fb7ceb", + "workspace_digest": "8d823c7fee2b7188d8da38049f5c4691eed8c49ad8f71a6b4210edcb9d2492b3", + "timestamp": 1791657975 +} diff --git a/.specsync/archive/changes/2026-10-10-repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera/state.json b/.specsync/archive/changes/2026-10-10-repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera/state.json new file mode 100644 index 00000000..59e698ce --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera/state.json @@ -0,0 +1,39 @@ +{ + "schema_version": 1, + "workflow_version": 2, + "workflow_origin_version": 2, + "id": "repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera", + "slug": "repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera", + "title": "Repair blurry Cubes and Slice canvases after view and display-size changes while retaining the WebGL context and camera parity", + "description": "Repair blurry Cubes and Slice canvases after view and display-size changes while retaining the WebGL context and camera parity", + "kind": "bug_fix", + "state": "archived", + "canonical_applied": true, + "base_commit": "dab4258541208f8bf6bb5a38f6200a5b348a858e", + "created_at": 1791656681, + "updated_at": 1791658049, + "affected_specs": [ + "ThreeMDViewer" + ], + "affected_paths": [ + "web/viewer.html", + "uitests/viewer.spec.mjs", + "specs/ThreeMDViewer", + "docs/evidence/viewer-resolution" + ], + "no_spec_change": false, + "no_spec_change_rationale": null, + "acceptance_criteria": [ + "The shared 3D canvas drawing buffer follows the displayed Cubes or Slice-reference size and device pixel ratio within the existing 2048-edge/2x limits; switching from a small reference or phone viewport to a large stage remains sharp; resizing retains the same WebGL context, geometry and camera/source/selection; Chromium, WebKit and the actual in-app browser verify transitions and picking." + ], + "selected_artifacts": [ + "context", + "testing", + "tasks" + ], + "dependencies": [], + "answers": { + "architecture_risk": "no", + "public_contract": "no" + } +} diff --git a/.specsync/archive/changes/2026-10-10-repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera/tasks.md b/.specsync/archive/changes/2026-10-10-repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera/tasks.md new file mode 100644 index 00000000..9587a860 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera/tasks.md @@ -0,0 +1,13 @@ +--- +change: repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera +artifact: tasks +--- + +# Tasks + +- [x] Reproduce the reported blur and measure bitmap/display dimensions. +- [x] Define the bounded corrective repair under existing browser quality authority. +- [x] Make the shared 3D drawable follow visible pane and display density. +- [x] Verify Chromium/WebKit small-to-large, Slice/Cubes, desktop/phone and Retina transitions with one retained context and no geometry uploads. +- [x] Inspect sharp output in the actual in-app browser without losing Leif's edited draft. +- [x] Synchronize implementation notes, run strict specs and pinned Trust, and record actual provenance. diff --git a/.specsync/archive/changes/2026-10-10-repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera/testing.md b/.specsync/archive/changes/2026-10-10-repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera/testing.md new file mode 100644 index 00000000..2e239414 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera/testing.md @@ -0,0 +1,24 @@ +--- +change: repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera +artifact: testing +--- + +# Testing + +At device pixel ratios 1 and 2, initialize a phone-sized Cubes stage, switch through Slice's small reference and expand/resize to desktop and larger-than-cap layouts. Check actual drawable width/height against proportional 2048-edge/2x bounds, the same context/program/mesh, zero context-loss events and zero subsequent geometry uploads. Preserve source, selected slice, camera pose and nearest picking. Run existing projection, pixel, Slice and navigation regressions on Chromium and WebKit and inspect the actual in-app WebKit output. Root strict specs and pinned Trust must pass; actual unsigned agent:codex provenance remains separate from a permitted signature or human diff review. + +## Requirement evidence + +| ID | Canonical | Evidence | +| --- | --- | --- | +| REQ-ThreeMDViewer-004 | REQ-ThreeMDViewer-004 | New actual drawable-density and context-retention regression, existing GPU pixel/projection/picking tests, in-app browser before/after measurements and screenshot. | + +## Current results + +The complete post-resize UI suite passed 230 tests. After final display-density listeners, the viewer suite passed 130 tests. The final media-query/window-resize density regressions passed 4 tests. All ran on Chromium and WebKit without skips or retries. Actual in-app bitmap/display measurements and screenshots, test logs and implementation digests are in `docs/evidence/viewer-resolution/`. Pinned Trust, actual provenance and finalization remain separately evidenced. + +## Repository verification and provenance + +Pinned Trust 1.2.2 with Fledge 1.7.2 passed on implementation commit `95c1213886b853a7b945fd833a5af02fa0f8128d`; Augur returned review at risk 36, with configured soft provenance degradation. The full configured verification lane passed. Strict root specs passed at 55/55 files and Hi passed 87 criteria. Source digests above bind the browser results to this implementation; later lifecycle/materialization records do not change the HTML or tests. + +Actual unsigned agent:codex attestation was recorded after the lane passed. The unchanged strict Attest policy rejects the unavailable permitted signature and reviewer allow-list, as shown in `attest-policy.json`. This is not a human review or signed provenance claim, and no policy was changed. Lifecycle closure is recorded separately in its supported receipt. diff --git a/.specsync/archive/changes/2026-10-10-repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera/verification-attempts.json b/.specsync/archive/changes/2026-10-10-repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera/verification-attempts.json new file mode 100644 index 00000000..7424baa6 --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera/verification-attempts.json @@ -0,0 +1,255 @@ +{ + "schema_version": 1, + "attempts": [ + { + "timestamp": 1791657937, + "commit": "cc71e781a3226550611ea09d8637cbaf2e67a1c8", + "contract_digest": "2434816b883b109a6be3b8d0f9f72837258bc21346df7a0d4357d9df27fe8dd0", + "execution_digest": "a67030d2d4fae6350ec00846e2a062e089570c761064ec0b92e2f51bc1fb7ceb", + "workspace_digest": "8d823c7fee2b7188d8da38049f5c4691eed8c49ad8f71a6b4210edcb9d2492b3", + "passed": true, + "commands": [ + { + "command": "specsync check --spec ThreeMDViewer --strict", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [ + "REQ-ThreeMDViewer-004" + ] + }, + { + "timestamp": 1791657954, + "commit": "1269bffeb78bbca596decc28757938543df1a88f", + "contract_digest": "2434816b883b109a6be3b8d0f9f72837258bc21346df7a0d4357d9df27fe8dd0", + "execution_digest": "a67030d2d4fae6350ec00846e2a062e089570c761064ec0b92e2f51bc1fb7ceb", + "workspace_digest": "8d823c7fee2b7188d8da38049f5c4691eed8c49ad8f71a6b4210edcb9d2492b3", + "passed": true, + "commands": [ + { + "command": "specsync check --spec ThreeMDViewer --strict", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [ + "REQ-ThreeMDViewer-004" + ] + }, + { + "timestamp": 1791657954, + "commit": "57a2db9ac4e98000a36aa9660df39e74aa21e17b", + "contract_digest": "2434816b883b109a6be3b8d0f9f72837258bc21346df7a0d4357d9df27fe8dd0", + "execution_digest": "a67030d2d4fae6350ec00846e2a062e089570c761064ec0b92e2f51bc1fb7ceb", + "workspace_digest": "8d823c7fee2b7188d8da38049f5c4691eed8c49ad8f71a6b4210edcb9d2492b3", + "acceptance_input_digest": "474024b8d244e1b0e66609fa2555e10bb14829248a2539c9606188898d4020ea", + "acceptance_manifest": { + "schema_version": 1, + "entries": [ + { + "path": "docs/evidence/viewer-resolution", + "kind": "non_file", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "1181f446a18468191a072ade800c6ab693b2ed1dadc57d03da27b41b9fc3a3ff", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-resolution/README.md", + "kind": "file", + "mode": 33188, + "payload_digest": "7559047d56b41d7b92476e8880be512074186c309ded7d33de63bb8479220e1d", + "entry_digest": "df4cbb2e9c537933efbe70a8083143254b2df01cbb9c33eb3ce51b53282c4d51", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-resolution/attest-implementation.json", + "kind": "file", + "mode": 33188, + "payload_digest": "ebf8266fd7a37f7000ffb0ac1dda354903618d47f204d8c0d6e023b3f03945ea", + "entry_digest": "1345beebaa173db2e613589ce7040659a6b66a837c96dfa59562a4b29e2c53f4", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-resolution/attest-policy.json", + "kind": "file", + "mode": 33188, + "payload_digest": "75e89fd087362ae70a2e1edc8d998953de6655773018babea94783230a137bdf", + "entry_digest": "9e07cd2c092474a9ba50c4f93520a98993c819ecfc09c71fee13e7da5876741f", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-resolution/browser-after.png", + "kind": "file", + "mode": 33188, + "payload_digest": "32ab5ee993c52f5c17b5744bdd10326d47f132567d868042d63bdee4cfbfccf9", + "entry_digest": "0144a6e8335bb916f98f9f5d82e0cb5f1892f9daa70cf0ae9677c1787e051cd0", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-resolution/browser-before.png", + "kind": "file", + "mode": 33188, + "payload_digest": "b72015dc9ed9c634e022dda0f4c7021d56edd4af1e23f786180bf5df5c826eac", + "entry_digest": "586995ccca4e70d99751ad9ff94aeef7cd26b785c066ef25e0a47a2c132659ec", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-resolution/browser-full.log", + "kind": "file", + "mode": 33188, + "payload_digest": "d7a1034a41ea1aa87f04c8f0699af8aa692b6d33ffe7d7f990931797d5a28d51", + "entry_digest": "ea458237acf04e3fab7bf3b5b321b5a9a837bddb0ee080e3154dfb7ed23b7a9a", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-resolution/density-final.log", + "kind": "file", + "mode": 33188, + "payload_digest": "4ea0c6f45736a3d53a0678057abfb45a33c26afb515501e668fff7b2a7aaffa9", + "entry_digest": "d8cdc825d3cb0efd3d9baf285e5c59b5580a0f7ef75940f00e2d6cbe803aaf24", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-resolution/strict-implementation.json", + "kind": "file", + "mode": 33188, + "payload_digest": "e65b3be05140229cc195848694ecf5457afad42551f7d52769e00babee0b6f4f", + "entry_digest": "cdbe0c731a4a6ad2aef535556b8be975bf6059179a2ef3aca6e2f8516ad73784", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-resolution/trust-implementation.log", + "kind": "file", + "mode": 33188, + "payload_digest": "f6b524e5e16be131f202250e7ad006b61ffbce3c3bdf6ed0877aac0e80068227", + "entry_digest": "fa15062abb14bd0af5575017896f5f36cf81141dcbf55b918fc45f2d317b1117", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-resolution/viewer-final.log", + "kind": "file", + "mode": 33188, + "payload_digest": "9f08854409164c2d0046121631cb23ba537a0a1ff3b1f5504a402da9992d3f31", + "entry_digest": "45b6f6e6dfb9193e42dee450258ac77bb2f259a058453275c4617d75397d2bf5", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "specs/ThreeMDViewer", + "kind": "non_file", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "b53a01354acef7fb830687d9789c70f85c60f43e94da4a2dd0816c771a3bf773", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/ThreeMDViewer.spec.md", + "kind": "file", + "mode": 33188, + "payload_digest": "bac308a20661b3e1b61a6851c67de191c89d5a7246ba84dfcee459e1fb3f06da", + "entry_digest": "a60eb3fe5bb7d6dc19fc57f9787fe7757fc9e472697f56c68e6c9dc024e5a190", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/context.md", + "kind": "file", + "mode": 33188, + "payload_digest": "f09326e825a394cb101529b853966c6b5322a2fc3badf79fb1fd2f9d320ef047", + "entry_digest": "336da9d0cb28b6c6ddfc58263c1a3b07f2a4c39c63d37a989b40844d5d90c17d", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/requirements.md", + "kind": "file", + "mode": 33188, + "payload_digest": "3dac32212b6c3e224405474d1d7691a739cc502cce4b0bfd3159b5a44dbb46d0", + "entry_digest": "b58e0f42ebd2f6b8eaa9cdc1bd7970d34031262b334b43bf9de66a56dcedf382", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/tasks.md", + "kind": "file", + "mode": 33188, + "payload_digest": "1067ddf384b6f388c737b630526ea78a96b74af4a4592c3f9b53ec6ee4098eae", + "entry_digest": "59ae09c0a423c2b88af674e7bc7ed35b795891289ea775b3708575e05dc8225d", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/testing.md", + "kind": "file", + "mode": 33188, + "payload_digest": "6165442a33a7522678bc97daf88f790ac7dbe7235126760dc766909a5d7bb814", + "entry_digest": "04aa5d18efa83971c44d2f4412ff5a176ce1666ff86be9206c0262ed6d064c3d", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "uitests/viewer.spec.mjs", + "kind": "file", + "mode": 33188, + "payload_digest": "59894ffd439caff704f34d3fba39425e991f854fcfe83a73aca673b0883c1c97", + "entry_digest": "1af3072d0be2fb62f3b2f714b5cba967db575341c2b52d922246a262dc36302c", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "web/viewer.html", + "kind": "file", + "mode": 33188, + "payload_digest": "d5c226e7ccb6b46c7e462c6d72a89772138080dce9269f0813cd0979d10116b8", + "entry_digest": "99be08aa8855f3adc79655fc5802caee2260cc034f786496de965bf99a78cd3c", + "owners": [ + "ThreeMDViewer" + ] + } + ] + }, + "passed": true, + "commands": [ + { + "command": "specsync check --spec ThreeMDViewer --strict", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [ + "REQ-ThreeMDViewer-004" + ] + } + ] +} diff --git a/.specsync/archive/changes/2026-10-10-repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera/verification.json b/.specsync/archive/changes/2026-10-10-repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera/verification.json new file mode 100644 index 00000000..5fcc8f7f --- /dev/null +++ b/.specsync/archive/changes/2026-10-10-repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera/verification.json @@ -0,0 +1,214 @@ +{ + "timestamp": 1791657954, + "commit": "57a2db9ac4e98000a36aa9660df39e74aa21e17b", + "contract_digest": "2434816b883b109a6be3b8d0f9f72837258bc21346df7a0d4357d9df27fe8dd0", + "execution_digest": "a67030d2d4fae6350ec00846e2a062e089570c761064ec0b92e2f51bc1fb7ceb", + "workspace_digest": "8d823c7fee2b7188d8da38049f5c4691eed8c49ad8f71a6b4210edcb9d2492b3", + "acceptance_input_digest": "474024b8d244e1b0e66609fa2555e10bb14829248a2539c9606188898d4020ea", + "acceptance_manifest": { + "schema_version": 1, + "entries": [ + { + "path": "docs/evidence/viewer-resolution", + "kind": "non_file", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "1181f446a18468191a072ade800c6ab693b2ed1dadc57d03da27b41b9fc3a3ff", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-resolution/README.md", + "kind": "file", + "mode": 33188, + "payload_digest": "7559047d56b41d7b92476e8880be512074186c309ded7d33de63bb8479220e1d", + "entry_digest": "df4cbb2e9c537933efbe70a8083143254b2df01cbb9c33eb3ce51b53282c4d51", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-resolution/attest-implementation.json", + "kind": "file", + "mode": 33188, + "payload_digest": "ebf8266fd7a37f7000ffb0ac1dda354903618d47f204d8c0d6e023b3f03945ea", + "entry_digest": "1345beebaa173db2e613589ce7040659a6b66a837c96dfa59562a4b29e2c53f4", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-resolution/attest-policy.json", + "kind": "file", + "mode": 33188, + "payload_digest": "75e89fd087362ae70a2e1edc8d998953de6655773018babea94783230a137bdf", + "entry_digest": "9e07cd2c092474a9ba50c4f93520a98993c819ecfc09c71fee13e7da5876741f", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-resolution/browser-after.png", + "kind": "file", + "mode": 33188, + "payload_digest": "32ab5ee993c52f5c17b5744bdd10326d47f132567d868042d63bdee4cfbfccf9", + "entry_digest": "0144a6e8335bb916f98f9f5d82e0cb5f1892f9daa70cf0ae9677c1787e051cd0", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-resolution/browser-before.png", + "kind": "file", + "mode": 33188, + "payload_digest": "b72015dc9ed9c634e022dda0f4c7021d56edd4af1e23f786180bf5df5c826eac", + "entry_digest": "586995ccca4e70d99751ad9ff94aeef7cd26b785c066ef25e0a47a2c132659ec", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-resolution/browser-full.log", + "kind": "file", + "mode": 33188, + "payload_digest": "d7a1034a41ea1aa87f04c8f0699af8aa692b6d33ffe7d7f990931797d5a28d51", + "entry_digest": "ea458237acf04e3fab7bf3b5b321b5a9a837bddb0ee080e3154dfb7ed23b7a9a", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-resolution/density-final.log", + "kind": "file", + "mode": 33188, + "payload_digest": "4ea0c6f45736a3d53a0678057abfb45a33c26afb515501e668fff7b2a7aaffa9", + "entry_digest": "d8cdc825d3cb0efd3d9baf285e5c59b5580a0f7ef75940f00e2d6cbe803aaf24", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-resolution/strict-implementation.json", + "kind": "file", + "mode": 33188, + "payload_digest": "e65b3be05140229cc195848694ecf5457afad42551f7d52769e00babee0b6f4f", + "entry_digest": "cdbe0c731a4a6ad2aef535556b8be975bf6059179a2ef3aca6e2f8516ad73784", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-resolution/trust-implementation.log", + "kind": "file", + "mode": 33188, + "payload_digest": "f6b524e5e16be131f202250e7ad006b61ffbce3c3bdf6ed0877aac0e80068227", + "entry_digest": "fa15062abb14bd0af5575017896f5f36cf81141dcbf55b918fc45f2d317b1117", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "docs/evidence/viewer-resolution/viewer-final.log", + "kind": "file", + "mode": 33188, + "payload_digest": "9f08854409164c2d0046121631cb23ba537a0a1ff3b1f5504a402da9992d3f31", + "entry_digest": "45b6f6e6dfb9193e42dee450258ac77bb2f259a058453275c4617d75397d2bf5", + "owners": [ + "@exact:delivery" + ] + }, + { + "path": "specs/ThreeMDViewer", + "kind": "non_file", + "mode": 0, + "payload_digest": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "entry_digest": "b53a01354acef7fb830687d9789c70f85c60f43e94da4a2dd0816c771a3bf773", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/ThreeMDViewer.spec.md", + "kind": "file", + "mode": 33188, + "payload_digest": "bac308a20661b3e1b61a6851c67de191c89d5a7246ba84dfcee459e1fb3f06da", + "entry_digest": "a60eb3fe5bb7d6dc19fc57f9787fe7757fc9e472697f56c68e6c9dc024e5a190", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/context.md", + "kind": "file", + "mode": 33188, + "payload_digest": "f09326e825a394cb101529b853966c6b5322a2fc3badf79fb1fd2f9d320ef047", + "entry_digest": "336da9d0cb28b6c6ddfc58263c1a3b07f2a4c39c63d37a989b40844d5d90c17d", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/requirements.md", + "kind": "file", + "mode": 33188, + "payload_digest": "3dac32212b6c3e224405474d1d7691a739cc502cce4b0bfd3159b5a44dbb46d0", + "entry_digest": "b58e0f42ebd2f6b8eaa9cdc1bd7970d34031262b334b43bf9de66a56dcedf382", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/tasks.md", + "kind": "file", + "mode": 33188, + "payload_digest": "1067ddf384b6f388c737b630526ea78a96b74af4a4592c3f9b53ec6ee4098eae", + "entry_digest": "59ae09c0a423c2b88af674e7bc7ed35b795891289ea775b3708575e05dc8225d", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "specs/ThreeMDViewer/testing.md", + "kind": "file", + "mode": 33188, + "payload_digest": "6165442a33a7522678bc97daf88f790ac7dbe7235126760dc766909a5d7bb814", + "entry_digest": "04aa5d18efa83971c44d2f4412ff5a176ce1666ff86be9206c0262ed6d064c3d", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "uitests/viewer.spec.mjs", + "kind": "file", + "mode": 33188, + "payload_digest": "59894ffd439caff704f34d3fba39425e991f854fcfe83a73aca673b0883c1c97", + "entry_digest": "1af3072d0be2fb62f3b2f714b5cba967db575341c2b52d922246a262dc36302c", + "owners": [ + "ThreeMDViewer" + ] + }, + { + "path": "web/viewer.html", + "kind": "file", + "mode": 33188, + "payload_digest": "d5c226e7ccb6b46c7e462c6d72a89772138080dce9269f0813cd0979d10116b8", + "entry_digest": "99be08aa8855f3adc79655fc5802caee2260cc034f786496de965bf99a78cd3c", + "owners": [ + "ThreeMDViewer" + ] + } + ] + }, + "passed": true, + "commands": [ + { + "command": "specsync check --spec ThreeMDViewer --strict", + "success": true, + "exit_code": 0 + } + ], + "requirement_ids": [ + "REQ-ThreeMDViewer-004" + ] +} diff --git a/.specsync/changes/put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/approvals.json b/.specsync/changes/put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/approvals.json deleted file mode 100644 index 87b9bafb..00000000 --- a/.specsync/changes/put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/approvals.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "approvals": [], - "reopenings": [] -} diff --git a/.specsync/changes/put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/change.md b/.specsync/changes/put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/change.md deleted file mode 100644 index 919c8c96..00000000 --- a/.specsync/changes/put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/change.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -id: put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below -state: draft -type: feature -base_commit: e18f35e2c0c2c11c202342c5bf84b514ee12fe58 ---- - -# Share Edit, Preview, and Cubes in one viewer workspace - -## Intent - -Files stay on the left while Edit, Preview, and Cubes share the document panel. Cubes opens first with a small sculpture and matches Sculpt’s stage semantics. Leif’s continuation request asks for clearer controls and more room for the stage on desktop and phone screens. - -## Affected Canonical Specs - -- `ThreeMDViewer` - -## Acceptance Criteria - -- Keep the cube-stage geometry, colors, axes, rendering caps, and reuse contract. -- Keep document identity visible and group exports and conversions under Document; show insert tools in Edit. -- Add Fit and zoom controls below the canvas, keyboard orbiting, and a scrolling slice row with keyboard navigation. -- Offer Preview for documents without cubes and unavailable WebGL2. Show and recover GitHub loading controls. -- Preserve local and public GitHub open, every-line search, composition entries, sections, pack, and text/kind 2 download. The element stays a text renderer. - -## Authority and lifecycle - -Leif requested continued UI and UX implementation on 2026-10-09. This artifact remains an unapproved definition draft. Agent implementation and validation do not record Leif’s diff review or authorize a merge, tag, release, or deployment. - -## No-spec Rationale - -Not applicable diff --git a/.specsync/changes/put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/state.json b/.specsync/changes/put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/state.json deleted file mode 100644 index 1af87f78..00000000 --- a/.specsync/changes/put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/state.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "schema_version": 1, - "workflow_version": 2, - "workflow_origin_version": 2, - "id": "put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below", - "slug": "put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below", - "title": "Put Edit and Preview in the same viewer panel and toggle them like GitHub. Files stay on the left. Edit shows first. Below 900px, Files and the document take turns, and the document panel still switches Edit and Preview.", - "description": "Put Edit and Preview in the same viewer panel and toggle them like GitHub. Files stay on the left. Edit shows first. Below 900px, Files and the document take turns, and the document panel still switches Edit and Preview.", - "kind": "feature", - "state": "draft", - "base_commit": "e18f35e2c0c2c11c202342c5bf84b514ee12fe58", - "created_at": 1791595505, - "updated_at": 1791595557, - "affected_specs": [ - "ThreeMDViewer" - ], - "affected_paths": [ - "web/viewer.html", - "uitests/viewer.spec.mjs", - "hi/tools.md", - "specs/ThreeMDViewer" - ], - "no_spec_change": false, - "no_spec_change_rationale": null, - "acceptance_criteria": [ - "On a wide window, files stay on the left while Edit and Preview switch in one panel. Edit shows first and hides the preview. Preview shows the live plane view and hides the editor. Below 900px, Files and the document take turns, and the document still switches Edit and Preview. GitHub open, search, pack, and kind 2 stay. The element stays a text renderer." - ], - "selected_artifacts": [ - "context", - "requirements", - "plan", - "tasks", - "testing", - "docs" - ], - "dependencies": [], - "answers": { - "architecture_risk": "no", - "public_contract": "yes" - } -} diff --git a/.specsync/changes/put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/tasks.md b/.specsync/changes/put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/tasks.md deleted file mode 100644 index b03f8c46..00000000 --- a/.specsync/changes/put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/tasks.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -change: put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below -artifact: tasks ---- - -# Tasks - -- [x] Put Edit and Preview in one panel in `web/viewer.html`, with Cubes first. -- [x] On a narrow window, switch Files and the document, and keep Edit and Preview inside the document. -- [x] Call `render` when Preview is shown. -- [x] Update VIEWER-6 and `specs/ThreeMDViewer/`. -- [x] Update the desktop and narrow Playwright tests. -- [ ] Record definition approval from Leif. Do not self-approve. - -- [x] Run Sculpt and compare the same sculpture in both live cube stages. -- [x] Match lit glyph fill and gold selected-slice edges, full faces, background, axes, and framing. -- [x] Keep camera, zoom, and selection on cached geometry with one instanced draw. - -## Continuing UI and UX pass - -- [x] Compact the workspace and group document actions. -- [x] Keep document titles visible and insert tools in Edit. -- [x] Add Fit, bounded zoom, keyboard orbiting, and scrolling slice navigation. -- [x] Explain nongrid/GPU-unavailable states and recover GitHub loading controls. -- [x] Verify the final browser suite and capture visual evidence. - -Pinned Trust runs after the feature head is committed and pushed; its result is recorded in the PR and local verification output. - -Definition and human diff approval remain open. diff --git a/.specsync/changes/put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/testing.md b/.specsync/changes/put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/testing.md deleted file mode 100644 index 3d015c57..00000000 --- a/.specsync/changes/put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below/testing.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -change: put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below -artifact: testing ---- - -# Testing - -## Requirement evidence - -| ID | Canonical | Evidence | -| --- | --- | --- | -| REQ-ThreeMDViewer-003 | REQ-ThreeMDViewer-003 | VIEWER-6 in `hi/tools.md`. `web/viewer.html` switches Edit and Preview in one panel and calls `render` for Preview. `uitests/viewer.spec.mjs` covers the desktop switch and the narrow Files and document switch. | -| REQ-ThreeMDViewer-004 | REQ-ThreeMDViewer-004 | VIEWER-6 in `hi/tools.md`. `web/viewer.html` holds the element on `mode="single"`, removes the render-mode menu and the play control, and draws cubes with WebGL2. `uitests/viewer.spec.mjs` covers no autoplay and about 1400 cubes. | - -- `specsync check --spec ThreeMDViewer` -- `hi check` at the repository root -- Playwright `uitests/viewer.spec.mjs` passed 60 tests on Chromium and WebKit after the outline chip opens Preview first. The desktop and narrow layout tests passed again after the bar metadata hide. - -The Sculpt parity pass runs `./node_modules/.bin/playwright test viewer.spec.mjs` in `uitests` on Chromium and WebKit. Added GPU pixel evidence for a full single cell from six viewpoints and gold edges with unchanged glyph fill; nearest-Z picking; 1600 cells with zero camera/selection geometry uploads and one instanced draw per redraw. Live screenshots for Character orb and the starter geometry are in `docs/evidence/viewer-sculpt-parity/`. This is agent verification and leaves definition approval open. - -Final parity browser verification: 70 passed on Chromium and WebKit. Strict ThreeMDViewer SpecSync check: 1 passed, zero warnings or failures. `hi check`: 85 criteria, no problems. Element bundle: current, 48840 bytes, no storage code. - -## Continuing UI and UX pass - -The Chromium/WebKit suite covers camera controls, phone layout and non-overlapping controls, Document disclosure dismissal, text and kind 2 download fidelity, editor focus after the save shortcut, prose Preview and sample loading, 30-slice keyboard navigation, GitHub rate-limit recovery, and WebGL2-unavailable guidance. Inspect dark/light desktop, Edit, and phone views and preserve screenshots under docs/evidence/viewer-ui/. diff --git a/INTENT.md b/INTENT.md index 6381dce5..cc3b91c3 100644 --- a/INTENT.md +++ b/INTENT.md @@ -17,5 +17,5 @@ The title above is the product, not this worktree's directory name. - [reuse](hi/reuse.md): REUSE (11 criteria) - [storage](hi/storage.md): STORAGE (9 criteria) - [text](hi/text.md): TEXT (10 criteria) -- [tools](hi/tools.md): CLI, VIEWER, EDITOR (17 criteria) +- [tools](hi/tools.md): CLI, VIEWER, EDITOR (20 criteria) diff --git a/apps/sculpt/.specsync/hashes.json b/apps/sculpt/.specsync/hashes.json new file mode 100644 index 00000000..d6b927d1 --- /dev/null +++ b/apps/sculpt/.specsync/hashes.json @@ -0,0 +1,156 @@ +{ + "format_version": 1, + "hashes": { + "Sources/CLzfse/shim.h": "ca75399e58e707891638002011c7ffc4539211e815f61e82aa81e279222435d8", + "Sources/RookApp/Brand.swift": "5fec5c3cbae5181944483fe8e7876495e929b1ff02ffd4fc5601a370592dc6f9", + "Sources/RookApp/LayerGrid.swift": "8cc3be185e25120d5e5a04e5acfc86b2679f96a53b5e45d1a8cf563d64d39976", + "Sources/RookApp/MainView.swift": "a12282b2165abbbacf3f8e441891146c21556d402581456c2ed6c1acc506e01c", + "Sources/RookApp/RookApp.swift": "2561557e60ca5a77d60437223e7252eacee31fab4078c0bc0c30e6ac1b8ad88b", + "Sources/RookApp/SculptureCanvasKeyboard.swift": "9fa41ceaf7ade260a1844120dcbd10005d731e23f90142b3efb5731fb935d14c", + "Sources/RookApp/SculptureCanvasPointer.swift": "bf93c3e1c9817c553874ee2c396409e5dfb30d6f63a28f4db5d518590c223b9b", + "Sources/RookApp/SculptureCommandPalette.swift": "7487663179d120f1d1631ae20f3cc677da2c73031950fdb500a5aeac99257c65", + "Sources/RookApp/SculptureCommandSearchField.swift": "565009c4defd555b5d203648192d03f3b58cf4a62de8754439c9a874f67d1220", + "Sources/RookApp/SculptureCompositionEditor.swift": "386f45f28b1a2cf58265e0de2aa362b8401427d358084fdc110323a5345ac909", + "Sources/RookApp/SculptureDocumentCommands.swift": "a629929ed31bf1b1f93172d5340830eb2ca0c6045dbb69550a78b6d8b038f611", + "Sources/RookApp/SculptureEditor.swift": "ee02bf434002e3fc44fcf1f247ccf1dbe9ec22c366395150a5c8dce84a41e43b", + "Sources/RookApp/SculptureExamplesBrowser.swift": "b01273cded8b0010037dde8ba0c60df6c6ca9c1bff25ce5466b5955df0c02c9e", + "Sources/RookApp/SculptureExportStudio.swift": "7e0a542af8bbfcfb88e99a8312b07e82dea24d22a6932f1aa7c39e2ff85db1d1", + "Sources/RookApp/SculptureFile.swift": "b3e5549f9a94969ece6113afc7b26ba0ae1473a255e3164c04de038d011b4e3e", + "Sources/RookApp/SculptureGalleryBrowserModel.swift": "e172ab1dec9f458c2492a03f637c328a2f40ab55465f9603427948791fc64ae5", + "Sources/RookApp/SculptureGalleryOpening.swift": "aea929f3e076a2b91b5d688b2720468ff5da30f2a7d10d6fa14dd90381f051cf", + "Sources/RookApp/SculptureGalleryPreview.swift": "44bdc246a95938e208ce2ee907a610693d828c8127699313f62b9b2a34451c5b", + "Sources/RookApp/SculptureInsertionCommands.swift": "8e2ef936b3dcd298b6da7bc3876448efcc34be657c801c6adf8cb2ab6d638935", + "Sources/RookApp/SculptureInsertionFiles.swift": "8c9e588710c96f688ced965c9603510316796daf3b21961abeacca13efd69994", + "Sources/RookApp/SculptureLinkedSession.swift": "47f60b6f204906436d5a9e27631eec55dbc21fa3523fa270cd7df4ce388ed410", + "Sources/RookApp/SculptureLinkedViews.swift": "17507d0058555e23805740a5a14aadcd62b422c66c85db9a5818a5b91266b4d8", + "Sources/RookApp/SculpturePortableInterchange.swift": "136eb73bf6d848872a05998b533a2fe87b373be15673362745a10a552b3d1119", + "Sources/RookApp/SculptureProjectFolder.swift": "30cd9a767de4aa6dc42e1586d6e9e6df3e029accfeec18da6030778301a80a4d", + "Sources/RookApp/SculptureSaveJob.swift": "bc899f5561ce4b47151970f22115952b923cf4ccdedc2f354a78c98979101e28", + "Sources/RookApp/SculptureSharedModelEditor.swift": "bbbf28951ca2d033cd77f656ce86190c2c99767161f791668f00107bd8c2cdaa", + "Sources/RookApp/SculptureViewport.swift": "8d5ab6c914e03d60dadc58a3e8b6d4f595a261b1e032c46cc0cdbd0597757e45", + "Sources/RookApp/SculptureWorkspace.swift": "efcd1768402f9f09c852a5aff6797abb90f10c5a316e2248e222d6a629dbef7c", + "Sources/RookApp/SculptureWorldEditor.swift": "9746f952181a3c404dbcf377e179d1c2558006533712fe38ba56ccbaf5c14440", + "Sources/RookApp/SculptureWorldHandoff.swift": "f365d857ee10180ba2250025f7ede14a6ca4272f803e515b3bf514e262a03ee9", + "Sources/RookApp/SettingsView.swift": "05a08f44ebcc421a71c0e304022432514aca598ed6427c7f5e2b5073a1aa4a31", + "Sources/RookApp/SliceGridRendering.swift": "a357e465fdfea60688fb1092a20fe26b899b3cee1d08f4d1f90ba7635fd8a41e", + "Sources/RookCore/AppAppearance.swift": "8ffcf78080400a89c49d67520c4763ca3b38f419a206d5b973794104221a09c1", + "Sources/RookRendering/MetalSculptureView.swift": "69372bdc595a3d758c3a02660462f7c52ca1bc44a0ce4c0a940ef5b881b7293e", + "Sources/RookRendering/SculptureAnimationExporter.swift": "78dab790a8d4bd7e49a95bb63b5dd2f04b72968ade2ed89b0b57f26c9b2f29a4", + "Sources/RookRendering/SculptureLiveVoxelView.swift": "610272100afb40b290302e64c8cf72544b67f3c2cee3543b292f796531c9750e", + "Sources/RookRendering/SculptureLiveWorldView.swift": "61b75ba6d19de414c087681654bbed64077f5090d256f35a91e40f1123e60b5c", + "Sources/RookRendering/SculptureRasterizer.swift": "849e685001f4a144f637dc7a30be5c2a1c2bdff5c4cd039d285f34fca9d97848", + "Sources/RookRendering/SculptureRenderStyle.swift": "65525be59ccbe47f3d62ca557c2f7def035bdee1b88a64ed3c797d1cf76ab89b", + "Sources/RookRendering/SculptureVoxelGeometry.swift": "24c096ecd359193366e02097643561e28fb3ff422e1fafda1661dbf0f706eb86", + "Sources/RookRendering/SculptureVoxelMeshBuffers.swift": "9a4283a3dfdaf1651313419cad2520f989b5ba378c35e8b6c062d0b7706735e2", + "Sources/RookRendering/SculptureVoxelRasterizer.swift": "4f5f25e2e144400b414a37700a028bb145824a75cc69bc2dc6c0851c9abc4a39", + "Sources/RookRendering/SculptureVoxelSurface.swift": "677aa33e3a3858c80d154464a0a43278c1ae124a39a511b9d01fdd5b8c42085b", + "Sources/RookRendering/SculptureWorldCoarseMesh.swift": "7ae31d45410cf382f1d766178ae8dff4117f376598e8a1a33771aa094340e17d", + "Sources/RookRendering/SculptureWorldNavigation.swift": "094f8b15e01479d06e8009490075aeaf921b21cd97282769fbfba02a39d56a09", + "Sources/RookSculpture/Sculpture.swift": "65e462847a8c1cc0d0901e451994358f2f40ddb47f317d486199f1aa452293ae", + "Sources/RookSculpture/SculptureBinaryCodec.swift": "cbe131cbf13deff53b565ff3ac619dd1c970859cb8c93b12cb7fc4ad8f2f13a9", + "Sources/RookSculpture/SculptureBlockWorldExamples.swift": "9f3fedfb8614d898d9e03bf8cf0a40a0b49b9d7ae3aeeab9e9faacca70d05a01", + "Sources/RookSculpture/SculptureCodec.swift": "258e8da0944795023a11351e0696eb27850bc76b286462aa15ef4a6e08561929", + "Sources/RookSculpture/SculptureCommand.swift": "1bb2475246f54f95a686f0f9cba8829f9bbd7a108ac6c3760a4684dd2024a3b8", + "Sources/RookSculpture/SculptureComplexExamples.swift": "f91b134e34cae1c240622f93ec0c00588d846c578d961cd5d642fd1e3864ae96", + "Sources/RookSculpture/SculptureComposition.swift": "f645cf386d8521fc8768c71618ab334edd09fe6f1a2a3fae04ebd3f662dfe7bd", + "Sources/RookSculpture/SculptureCompositionCodec.swift": "462095b0b0ce1468cd2974be916cdcc2f27b13ca7564c22a5a67147b9cfa90c4", + "Sources/RookSculpture/SculptureCompositionExamples.swift": "dd9dadfcd8cd68c0bf195cb8362f13caebc653471e66bbeeeabad549c292f5c2", + "Sources/RookSculpture/SculptureExamples.swift": "2c679f4d6e1de79c870921f9211eec64ce98c823a318f2a890b6352737a72584", + "Sources/RookSculpture/SculptureGalleryCatalog.swift": "5b9158caf25d75087913f5164d89f1fe955be3193edbe526d69ef42c90a90b8f", + "Sources/RookSculpture/SculptureGenerationProbe.swift": "bff8e3b3e512c39c2820ef265a41b9925d797c003210256290204e28cb63a53b", + "Sources/RookSculpture/SculptureInsertionPlan.swift": "06a47b9286e07d0e8224ef242b04cb31de40f2ec2e84052ef602086b6dcc8bf9", + "Sources/RookSculpture/SculptureLinkedBundle.swift": "b8d4b31037ef1ff8b69c961542bc44c9e2a45d93a25fce1365a2e4a32c83b03a", + "Sources/RookSculpture/SculptureLinkedComposition.swift": "a6a4eb372ed3a4edc3e6d1d2327f97878727a5e66d7a3f2854cba020c4ea08fe", + "Sources/RookSculpture/SculptureLinkedError.swift": "a58116411775ada09cc2e833c7ae379766ef49d0545178ecad45bb27e1e0d01c", + "Sources/RookSculpture/SculptureLinkedResolver.swift": "da175e0312d0229c835c923764702a245fa868026d308b1d7039e442e0abc296", + "Sources/RookSculpture/SculptureMathExamples.swift": "337c00886c702b93b207ee8404ed283a03885c469ac02895a8c87f1b3e42ab54", + "Sources/RookSculpture/SculptureModelEditing.swift": "46f9142101e115290a12d9960fbb70f996a1133007927eb66eb2bb9022ecd3a8", + "Sources/RookSculpture/SculptureOBJExporter.swift": "3afea2ba9254dd9c0d26bc5fb02b7da476983b5d8740a48379c56b64355a3e6e", + "Sources/RookSculpture/SculptureProjection.swift": "d98745e56609642d7c65369aa67f251d82c3c6089199cd6a2bcc9b1fc928c8d4", + "Sources/RookSculpture/SculptureSHA256.swift": "11351975a70db957b19cadb56bb8cae125927a3cda6d5d0eed847b66d72d8425", + "Sources/RookSculpture/SculptureScene.swift": "625ead4b9e6b7bb3bbfceb81da895b047075d32cb25f6728809389c889bd044a", + "Sources/RookSculpture/SculptureSceneInsertion.swift": "c36b4ad82fe0c7fb5dde412eb74a36e38781f5d0747bf9272f8e936357e5d423", + "Sources/RookSculpture/SculptureSceneReader.swift": "4bb372428e5331e7eef1d679f5e26b0991f513939cf142ac53243ffa8830b463", + "Sources/RookSculpture/SculptureStorageFormat.swift": "c60aace57bafca01ef7ccab1fabff9f8ec2ed8b76fa06bf3a6bb73ce6dcaa159", + "Sources/RookSculpture/SculptureThreeMDCodec.swift": "f79ae566098d0c9728d9f528234e968875743455f0fd7c4b346548148d73b072", + "Sources/RookSculpture/SculptureThreeMDEditing.swift": "ca5cd02a5a31bf3797522b057da18305c2f7b0ff2397b17ba78607a9ecab994e", + "Sources/RookSculpture/SculptureVolumeStudyExamples.swift": "a5e13980fb2bcfcd4724844ec16c8f62d30c8aed1d0c8e3a0b232bb152d96ca3", + "Sources/RookSculpture/SculptureWorld.swift": "658718c3e0c5d4f40af92189c411627644ef5d5dfde7ee99f7913fef7659d7b0", + "Sources/RookSculpture/SculptureWorldCodec.swift": "99d7717ec47867e3ec938d845d4682b3581db4d35fdc987b0f151814f09a872a", + "Sources/RookSculpture/SculptureWorldExamples.swift": "ecff96ebed4c4f7d8ff37c98797581b8ad6fb1f82df49e6244ae197d773bd188", + "Sources/RookTool/SculptureCommandTool.swift": "04f24a0ee5bd7f9257deeb753e8f88a68c653943edfa15f77966ed41dc45355b", + "Sources/RookTool/SculptureExampleExport.swift": "662b27b2563cdd094418c0a81a84817de13ff84eed0f256caa8b42f43aeffb28", + "Sources/RookTool/SculptureInsertTool.swift": "781d0528e71e9d11d129185db4a85034fb9228e8e22f72963acb0515f86da228", + "Sources/RookTool/SculptureLinkedInput.swift": "b6f6267e9b0224f044f50b5167937b4145b56b92f076e38104222f484f4f0ba3", + "Sources/RookTool/SculptureMathExampleExport.swift": "052bc1bed6a6305bb8f5682d3d9f8ad35f446e62acee8228798f301162736883", + "Sources/RookTool/SculpturePortableTool.swift": "2470ccd968de1b7ae727caac2c3c852488cb4dfcc68a9b944cb3e7132677e44f", + "Sources/RookTool/SculptureReferenceModelTool.swift": "65e98ca193048c752ac16442f14c229b89c4e958baf52ca188276ca2141ee33a", + "Sources/RookTool/SculptureVolumeStudy.swift": "22c10385fef590081949ed596a6e382f0b33628368e44f00fb04f7a2c28c1e83", + "Sources/RookTool/SculptureVolumeStudyWorldExport.swift": "2b5802c358bb7e9b175bed195b8246620a8536b3b228911792f75103eafc8c90", + "Sources/RookTool/main.swift": "f2c9950f4abc272f3597d316bae51d6aa76df7ffe77c626a0c46950813d06c35", + "Sources/RookTooling/AppPackaging.swift": "87bdab8dec113a9ffe631f93ad026c51f6bc66b07053f7b0c1a22f39da41ed36", + "Sources/RookTooling/CommandRunner.swift": "c073401851a65739a0699364b73d7d3d523a1a646e6ccf6101ee3e1a1363cd7e", + "Sources/RookTooling/RookTooling.swift": "7e642db535057b7a6223b5df0557525ef7884a3da3a3748cc6c35c98564a0b4d", + "Sources/RookTooling/SourceBoundaries.swift": "43aa85abe772f6da4c8eee728e8270f69cf1576d2665133af7b66fae03f0cf6b", + "Sources/RookVerification/SwiftTestLog.swift": "665bbd1f611ec5c57aa81a551463b2d861cb260574c7cc3270631f6550585a73", + "Sources/RookVerification/SwiftTestRunner.swift": "ee863fa503e0c589d32e8fb3e94507eb0978e4c59cbd7e6e1458ed9a2d09e945", + "Sources/RookVerification/TestLogAssessment.swift": "67a38f94513a5be12a1432c1bae2e7d27e23686bafb37c19cecfcdbff927a4cc", + "specs/RookApp/RookApp.spec.md": "328f0e0ec49767f115960ba7a09b1395626ef6dd78cdb76f79ffc61d3b381859", + "specs/RookApp/requirements.md": "a998087ec9c46dec9d5e3f6e3f4c2680966f67d766be19fe3a7a1c9ae9fec9d3", + "specs/RookCore/RookCore.spec.md": "edd8f788a56817afc8eb2d477a0a75f3bc37135d205b1f6e9665d03ff0b74344", + "specs/RookCore/requirements.md": "80305947b009aeab89c4fae62bc8ef48cb0c6c95cfbd351cea9e2fc0f47a0b21", + "specs/RookDevelopment/RookDevelopment.spec.md": "b2c021c8fa8d74dc2197bd5ef8754e4f3eadb091c743831ad643b7867588c9d0", + "specs/RookDevelopment/requirements.md": "0efd07ebb2fa2d12769429f782dd1d2d70362adbeca2a82234251c6aa55abe90", + "specs/RookRendering/RookRendering.spec.md": "3eaeae84bde150f19ca189a04310b28dda74cfb90d55430c8835f07b1ee1008d", + "specs/RookRendering/requirements.md": "9360c435f8fb30b54a7fa3e411a6d8f5347e089ea9038a80734fc821b49dcdcf", + "specs/RookSculpture/RookSculpture.spec.md": "a89be62701494e3b6c7ffbde27888091fe3c0d7d81fb91813fe697686d0381ae", + "specs/RookSculpture/requirements.md": "fddb51105fb11306fc54c53f1c74771fde301812c8a3da5a253108ec89b5000d" + }, + "snapshots": { + "specs/RookApp/RookApp.spec.md": { + "snapshot_version": 1, + "spec_path": "specs/RookApp/RookApp.spec.md", + "errors": [], + "warnings": [], + "notices": [], + "input_digest": "5ac5341470754f4add3ef5867343c57ead06aa7731004f37c30176d21f3622ef", + "snapshot_digest": "740dde74d5d354b99cbd9da59d2c26c1f273af4138ea98af6b105a05a3101f19" + }, + "specs/RookCore/RookCore.spec.md": { + "snapshot_version": 1, + "spec_path": "specs/RookCore/RookCore.spec.md", + "errors": [], + "warnings": [], + "notices": [], + "input_digest": "73a423868c661e9b9223143830158f8d9b657410659390ae02b171ad183e02bf", + "snapshot_digest": "0eee6a05bb1277a330466e737c4d8c0da45ed033bc4e3bd9c28cb4f4e9ebe01e" + }, + "specs/RookDevelopment/RookDevelopment.spec.md": { + "snapshot_version": 1, + "spec_path": "specs/RookDevelopment/RookDevelopment.spec.md", + "errors": [], + "warnings": [], + "notices": [], + "input_digest": "fa14e05750d8a7baf7f92d1a71dbd0b9a9a7d542236051dbf18f86354f8126e9", + "snapshot_digest": "8e8fa0080ab4f8be16498988d7db8676b790975ab7438a6433cfb9d8777c13ac" + }, + "specs/RookRendering/RookRendering.spec.md": { + "snapshot_version": 1, + "spec_path": "specs/RookRendering/RookRendering.spec.md", + "errors": [], + "warnings": [], + "notices": [], + "input_digest": "9c4ea0850ca2faa6b8889e82967a30ba1be8560a96715f7b754a300d2b558d43", + "snapshot_digest": "aef9f7ef2cc1f5270b49ccaec630b578c3b70623b10de61638fef71f99462f06" + }, + "specs/RookSculpture/RookSculpture.spec.md": { + "snapshot_version": 1, + "spec_path": "specs/RookSculpture/RookSculpture.spec.md", + "errors": [], + "warnings": [], + "notices": [], + "input_digest": "f07345d2c229b7fd370b10dfe71380f84fd020e2fc5d783bd6f43b470643240d", + "snapshot_digest": "03567c819416801f9bf18d19006c4665c6baffccb4e79e01dd022973bbc06fca" + } + } +} \ No newline at end of file diff --git a/apps/sculpt/INTENT.md b/apps/sculpt/INTENT.md index 5cca4794..f544b324 100644 --- a/apps/sculpt/INTENT.md +++ b/apps/sculpt/INTENT.md @@ -20,7 +20,7 @@ WORLD-36 measures a literal physically initialized 1024-cubed one-byte developme - [composition](hi/composition.md): COMPOSITION (5 criteria) -- [cubes](hi/cubes.md): CUBES (4 criteria) +- [cubes](hi/cubes.md): CUBES (5 criteria) - [export](hi/export.md): EXPORT (8 criteria) - [gallery](hi/gallery.md): GALLERY (6 criteria) - [local](hi/local.md): LOCAL (2 criteria) diff --git a/apps/sculpt/Sources/RookApp/SculptureCanvasPointer.swift b/apps/sculpt/Sources/RookApp/SculptureCanvasPointer.swift index 3d620913..bbde1d69 100644 --- a/apps/sculpt/Sources/RookApp/SculptureCanvasPointer.swift +++ b/apps/sculpt/Sources/RookApp/SculptureCanvasPointer.swift @@ -5,22 +5,31 @@ internal enum SculpturePointerPhase: Equatable, Sendable { case down, drag, up } +internal enum SculptureCameraInput { + case pan(SculpturePointerPhase, CGPoint) + case panBy(CGSize) + case zoom(Double) +} + /// A transparent native event surface above the Metal view. Keyboard focus remains with the canvas controller. @MainActor internal struct SculptureCanvasPointer: NSViewRepresentable { let paint: Bool let event: @MainActor (SculpturePointerPhase, CGPoint) -> Void + var camera: @MainActor (SculptureCameraInput) -> Void = { _ in } func makeNSView(context: Context) -> SculptureCanvasPointerView { let view = SculptureCanvasPointerView(frame: .zero) view.paint = paint view.event = event + view.camera = camera return view } func updateNSView(_ view: SculptureCanvasPointerView, context: Context) { view.paint = paint view.event = event + view.camera = camera } } @@ -32,6 +41,8 @@ internal final class SculptureCanvasPointerView: NSView { } } var event: @MainActor (SculpturePointerPhase, CGPoint) -> Void = { _, _ in } + var camera: @MainActor (SculptureCameraInput) -> Void = { _ in } + private var panning = false override init(frame frameRect: NSRect) { super.init(frame: frameRect) @@ -57,8 +68,37 @@ internal final class SculptureCanvasPointerView: NSView { override func mouseDragged(with event: NSEvent) { dispatch(.drag, event) } override func mouseUp(with event: NSEvent) { dispatch(.up, event) } + override func rightMouseDown(with event: NSEvent) { dispatch(.down, event) } + override func rightMouseDragged(with event: NSEvent) { dispatch(.drag, event) } + override func rightMouseUp(with event: NSEvent) { dispatch(.up, event) } + override func otherMouseDown(with event: NSEvent) { dispatch(.down, event) } + override func otherMouseDragged(with event: NSEvent) { dispatch(.drag, event) } + override func otherMouseUp(with event: NSEvent) { dispatch(.up, event) } + + override func scrollWheel(with input: NSEvent) { + guard let window, input.windowNumber == window.windowNumber else { return } + let unit = input.hasPreciseScrollingDeltas ? 1.0 : 16.0 + if input.modifierFlags.contains(.shift) { + camera(.panBy(CGSize(width: input.scrollingDeltaX * unit, height: -input.scrollingDeltaY * unit))) + } else { + camera(.zoom(exp(max(-500, min(500, input.scrollingDeltaY * unit)) * 0.002))) + } + } + + override func magnify(with input: NSEvent) { + guard let window, input.windowNumber == window.windowNumber, input.magnification.isFinite else { return } + camera(.zoom(exp(max(-2, min(2, Double(input.magnification)))))) + } + private func dispatch(_ phase: SculpturePointerPhase, _ input: NSEvent) { guard let window, input.windowNumber == window.windowNumber else { return } - event(phase, convert(input.locationInWindow, from: nil)) + if phase == .down { + panning = + input.buttonNumber != 0 || input.type == .rightMouseDown || input.type == .otherMouseDown + || input.modifierFlags.contains(.shift) + } + let point = convert(input.locationInWindow, from: nil) + if panning { camera(.pan(phase, point)) } else { event(phase, point) } + if phase == .up { panning = false } } } diff --git a/apps/sculpt/Sources/RookApp/SculptureEditor.swift b/apps/sculpt/Sources/RookApp/SculptureEditor.swift index 0f20d9da..64818eb1 100644 --- a/apps/sculpt/Sources/RookApp/SculptureEditor.swift +++ b/apps/sculpt/Sources/RookApp/SculptureEditor.swift @@ -1205,6 +1205,9 @@ internal struct SculptureEditor: View { } private func fitCamera() { + workspace.camera.fitsVolume = true + workspace.camera.panX = 0 + workspace.camera.panY = 0 if workspace.renderStyle == .cubes { workspace.camera.zoom = 1; return } var camera = workspace.camera camera.zoom = 0.5 diff --git a/apps/sculpt/Sources/RookApp/SculptureViewport.swift b/apps/sculpt/Sources/RookApp/SculptureViewport.swift index c9b98ec6..87a6a955 100644 --- a/apps/sculpt/Sources/RookApp/SculptureViewport.swift +++ b/apps/sculpt/Sources/RookApp/SculptureViewport.swift @@ -86,6 +86,12 @@ internal struct SculptureViewport: View { @State private var orbitStart: SculptureCamera? @State private var pointerStart: CGPoint? @State private var showingCamera = false + @State private var panMode = false + @State private var rotationAxis: Int? + @State private var rotationStep = "15" + @State private var panStep = "0.25" + @State private var precisionMessage = "" + @State private var sphereStart: SculptureCamera? @State private var rendered: RenderedCanvas? @State private var strokeFrame: RenderedCanvas? @State private var strokeDocument: UUID? @@ -119,8 +125,18 @@ internal struct SculptureViewport: View { canvas(request: request, liveRequest: liveRequest, size: geometry.size) if showsControls { cameraBar.padding(16) } } + .overlay(alignment: .topTrailing) { + if showsControls { axisSphere.padding(12) } + } .background(Color(red: 0.065, green: 0.085, blue: 0.10)) .clipShape(RoundedRectangle(cornerRadius: 12)) + .onAppear { workspace.camera.fitsVolume = true } + .onChange(of: workspace.camera.fitsVolume) { _, fits in + if !fits { workspace.camera.fitsVolume = true } + } + .onChange(of: workspace.paintsIn3D) { _, paints in + if paints { panMode = false } + } .task(id: rasterRequest) { guard let request = rasterRequest else { return } let worker = Task.detached(priority: .userInitiated) { RenderedCanvas.render(request) } @@ -239,9 +255,44 @@ internal struct SculptureViewport: View { Text("Choose Paint and click the slice grid, or open an example.").font(.callout) }.foregroundStyle(.white.opacity(0.8)).padding(30) } - SculptureCanvasPointer(paint: isPainting) { phase, point in - handlePointer(phase, point: point, request: request, liveRequest: liveRequest, size: size) - } + SculptureCanvasPointer( + paint: isPainting, + event: { phase, point in + handlePointer(phase, point: point, request: request, liveRequest: liveRequest, size: size) + }, + camera: { input in + switch input { + case .pan(let phase, let point): + handlePointer( + phase, + point: point, + request: request, + liveRequest: liveRequest, + size: size, + pan: true + ) + case .panBy(let delta): + finishStroke() + workspace.camera.pan( + horizontal: delta.width, + vertical: delta.height, + extent: Double( + max(workspace.sculpture.width, workspace.sculpture.height, workspace.sculpture.depth) + ), + width: size.width, + height: size.height, + dimensions: SIMD3( + workspace.sculpture.width, + workspace.sculpture.height, + workspace.sculpture.depth + ) + ) + case .zoom(let factor): + finishStroke() + workspace.camera.magnify(factor) + } + } + ) } .accessibilityElement(children: .ignore) .accessibilityLabel("3D sculpture canvas") @@ -251,7 +302,7 @@ internal struct SculptureViewport: View { .accessibilityHint( isPainting ? "Draw adds a cube on a face or an empty slice cell. Erase removes the clicked cube. Each drag is one undo step." - : "Drag to orbit. Click a cell to select its slice. Amber marks the selected slice." + : "Drag to orbit freely. Choose Pan or Shift, middle or right drag to move. Scroll or pinch to zoom. Click a cube to select its slice." ) .accessibilityIdentifier("editor.canvas") } @@ -261,14 +312,17 @@ internal struct SculptureViewport: View { point: CGPoint, request: CanvasRenderRequest, liveRequest: LiveSceneRequest, - size: CGSize + size: CGSize, + pan: Bool = false ) { + let pans = pan || panMode + let paints = isPainting && !pans if phase == .down { focusCanvas() pointerStart = point orbitStart = workspace.camera } - if liveRequest.enabled, isPainting, phase != .up { + if liveRequest.enabled, paints, phase != .up { if liveStroke == nil { guard let liveScene, liveScene.request == liveRequest, liveController.installedSceneID == request.revision, @@ -294,7 +348,7 @@ internal struct SculptureViewport: View { } return } - if isPainting, phase != .up { + if paints, phase != .up { guard rendered?.cubes?.isOverBudget != true else { workspace.message = "Cube preview limit exceeded. Use Slice or ASCII to edit this volume." return @@ -317,14 +371,33 @@ internal struct SculptureViewport: View { } else { workspace.message = "Click a cube face or an empty cell in the selected slice grid." } - } else if !isPainting, let start = pointerStart { + } else if !paints, let start = pointerStart { let dx = point.x - start.x, dy = point.y - start.y if phase == .drag, let orbitStart, abs(dx) + abs(dy) >= 3 { - let yaw = orbitStart.yaw + dx * 0.008 - workspace.camera.yaw = atan2(sin(yaw), cos(yaw)) - workspace.camera.pitch = max(-1.4, min(1.4, orbitStart.pitch + dy * 0.008)) + var camera = orbitStart + if pans { + camera.pan( + horizontal: dx, + vertical: dy, + extent: Double( + max(workspace.sculpture.width, workspace.sculpture.height, workspace.sculpture.depth) + ), + width: size.width, + height: size.height, + dimensions: SIMD3( + workspace.sculpture.width, + workspace.sculpture.height, + workspace.sculpture.depth + ) + ) + } else if let rotationAxis { + camera.rotate(axis: rotationAxis, radians: (abs(dx) >= abs(dy) ? dx : -dy) * 0.008) + } else { + camera.orbit(horizontal: dx, vertical: dy) + } + workspace.camera = camera workspace.viewpoint = .perspective - } else if phase == .up, abs(dx) + abs(dy) < 3 { + } else if phase == .up, !pans, abs(dx) + abs(dy) < 3 { if liveRequest.enabled, liveScene?.request == liveRequest, liveController.installedSceneID == request.revision, liveController.currentCamera == request.camera, @@ -341,7 +414,9 @@ internal struct SculptureViewport: View { finishStroke() } } - private var isPainting: Bool { showsControls && workspace.renderStyle == .cubes && workspace.paintsIn3D } + private var isPainting: Bool { + showsControls && workspace.renderStyle == .cubes && workspace.paintsIn3D && !panMode + } private func finishStroke() { workspace.endStroke() @@ -373,6 +448,97 @@ internal struct SculptureViewport: View { } } + private func chooseAxis(_ axis: Int?) { + workspace.endStroke() + workspace.paintsIn3D = false + panMode = false + rotationAxis = axis + } + + private func nudgeRotation(_ sign: Double) { + guard let axis = rotationAxis, let step = Double(rotationStep), step.isFinite, step > 0 else { + precisionMessage = "Choose an axis and enter a finite, positive step." + return + } + precisionMessage = "" + workspace.camera.rotate(axis: axis, radians: sign * step.truncatingRemainder(dividingBy: 360) * .pi / 180) + workspace.viewpoint = .perspective + } + + private func nudgePan(_ x: Double, _ y: Double) { + guard let step = Double(panStep), step.isFinite, step > 0 else { + precisionMessage = "Enter a finite, positive pan step." + return + } + precisionMessage = "" + workspace.camera.panX -= x * step + workspace.camera.panY += y * step + workspace.camera = workspace.camera.normalized + } + + private func ringPoint(axis: Int, angle: Double) -> CGPoint { + let other = (0...2).filter { $0 != axis } + var point = SIMD3(repeating: 0) + point[other[0]] = cos(angle) + point[other[1]] = sin(angle) + point.y *= -1 + let basis = workspace.camera.basis + return CGPoint(x: 50 + 34 * (point * basis.right).sum(), y: 50 - 34 * (point * basis.up).sum()) + } + + private var axisSphere: some View { + VStack(spacing: 4) { + Canvas { context, _ in + let colors: [Color] = [.red, .green, .blue] + for axis in 0...2 { + var path = Path() + for index in 0...64 { + let point = ringPoint(axis: axis, angle: Double(index) * .pi / 32) + if index == 0 { path.move(to: point) } else { path.addLine(to: point) } + } + context.stroke( + path, + with: .color(colors[axis].opacity(rotationAxis == axis ? 1 : 0.65)), + lineWidth: rotationAxis == axis ? 4 : 2 + ) + } + } + .frame(width: 100, height: 100) + .accessibilityHidden(true) + .gesture( + DragGesture(minimumDistance: 0).onChanged { value in + if sphereStart == nil { + var nearest = (distance: Double.infinity, axis: 0) + for axis in 0...2 { + for index in 0...128 { + let point = ringPoint(axis: axis, angle: Double(index) * .pi / 64) + let distance = hypot(point.x - value.startLocation.x, point.y - value.startLocation.y) + if distance < nearest.distance { nearest = (distance, axis) } + } + } + chooseAxis(nearest.axis) + sphereStart = workspace.camera + } + guard var camera = sphereStart, let rotationAxis else { return } + let dx = value.translation.width, dy = value.translation.height + camera.rotate(axis: rotationAxis, radians: (abs(dx) >= abs(dy) ? dx : -dy) * 0.008) + workspace.camera = camera + workspace.viewpoint = .perspective + }.onEnded { _ in sphereStart = nil } + ) + HStack(spacing: 8) { + Button("Free") { chooseAxis(nil) }.accessibilityLabel("Free orbit") + ForEach(0...2, id: \.self) { axis in + Button(["X", "Y", "Z"][axis]) { chooseAxis(axis) } + .foregroundStyle(rotationAxis == axis ? Color.accentColor : Color.primary) + .accessibilityLabel("Rotate around " + ["X", "Y", "Z"][axis]) + .accessibilityValue(rotationAxis == axis ? "Selected" : "Unselected") + } + }.buttonStyle(.borderless).font(.caption) + } + .padding(8).background(.regularMaterial, in: RoundedRectangle(cornerRadius: 10)) + } + private var cameraBar: some View { HStack(spacing: 12) { Menu { @@ -390,7 +556,16 @@ internal struct SculptureViewport: View { ) } .accessibilityLabel("Camera view").accessibilityIdentifier("editor.camera.view") - Button("Fit", action: fit).accessibilityLabel("Fit sculpture in canvas").accessibilityIdentifier( + Button("Pan") { + panMode.toggle() + if panMode { workspace.paintsIn3D = false } + } + .foregroundStyle(panMode ? Color.accentColor : Color.primary) + .accessibilityValue(panMode ? "On" : "Off").accessibilityIdentifier("editor.camera.pan") + Button("Fit") { + workspace.setViewpoint(.perspective) + fit() + }.accessibilityLabel("Fit sculpture in canvas").accessibilityIdentifier( "editor.camera.fit" ) Divider().frame(height: 18) @@ -407,12 +582,29 @@ internal struct SculptureViewport: View { .popover(isPresented: $showingCamera) { VStack(alignment: .leading, spacing: 16) { Text("Camera").font(.headline) + HStack { + Text("Degrees") + TextField("Degrees", text: $rotationStep).frame(width: 70) + .accessibilityLabel("Rotation step in degrees") + Button("−") { nudgeRotation(-1) }.accessibilityLabel("Rotate negative step") + Button("+") { nudgeRotation(1) }.accessibilityLabel("Rotate positive step") + }.disabled(rotationAxis == nil) + HStack { + Text("Pan cells") + TextField("Pan cells", text: $panStep).frame(width: 70) + .accessibilityLabel("Pan step in cells") + Button("←") { nudgePan(-1, 0) }.accessibilityLabel("Pan left") + Button("↑") { nudgePan(0, -1) }.accessibilityLabel("Pan up") + Button("↓") { nudgePan(0, 1) }.accessibilityLabel("Pan down") + Button("→") { nudgePan(1, 0) }.accessibilityLabel("Pan right") + } + if !precisionMessage.isEmpty { Text(precisionMessage).font(.caption) } LabeledContent("Orbit") { Slider(value: $workspace.camera.yaw, in: (-Double.pi)...Double.pi) .accessibilityLabel("Camera orbit").accessibilityIdentifier("editor.camera.orbit") } LabeledContent("Tilt") { - Slider(value: $workspace.camera.pitch, in: -1.4...1.4) + Slider(value: $workspace.camera.pitch, in: (-Double.pi)...Double.pi) .accessibilityLabel("Camera tilt").accessibilityIdentifier("editor.camera.tilt") } if workspace.renderStyle == .cubes { diff --git a/apps/sculpt/Sources/RookRendering/SculptureLiveVoxelView.swift b/apps/sculpt/Sources/RookRendering/SculptureLiveVoxelView.swift index 5c8b94af..2fe011d6 100644 --- a/apps/sculpt/Sources/RookRendering/SculptureLiveVoxelView.swift +++ b/apps/sculpt/Sources/RookRendering/SculptureLiveVoxelView.swift @@ -354,19 +354,18 @@ internal struct LiveVoxelCamera { init(dimensions: SIMD3, camera: SculptureCamera, size: CGSize) { let extent = Double(max(dimensions.x, dimensions.y, dimensions.z)) let distance = extent * 3 - let yaw = camera.yaw.isFinite ? camera.yaw.truncatingRemainder(dividingBy: 2 * .pi) : 0 - let pitch = camera.pitch.isFinite ? max(-1.4, min(1.4, camera.pitch)) : 0 - let zoom = camera.zoom.isFinite ? max(0.5, min(2, camera.zoom)) : 1 + let camera = camera.normalized let width = max(1, Double(size.width)), height = max(1, Double(size.height)) - let scale = min(width, height) * 0.68 / extent * zoom - let cy = cos(yaw), sy = sin(yaw), cp = cos(pitch), sp = sin(pitch) - projectedGridSpacing = scale * min(sqrt(cy * cy + sy * sy * sp * sp), abs(cp)) + let scale = camera.projectionScale(dimensions: dimensions, width: width, height: height) + let basis = camera.basis + projectedGridSpacing = scale * min(hypot(basis.right.x, basis.up.x), hypot(basis.right.y, basis.up.y)) + let eye = basis.back * distance + basis.right * camera.panX + basis.up * camera.panY cameraToWorld = simd_float4x4( columns: ( - SIMD4(Float(cy), 0, Float(sy), 0), - SIMD4(Float(sy * sp), Float(cp), Float(-cy * sp), 0), - SIMD4(Float(-sy * cp), Float(sp), Float(cy * cp), 0), - SIMD4(Float(-sy * cp * distance), Float(sp * distance), Float(cy * cp * distance), 1) + SIMD4(Float(basis.right.x), Float(basis.right.y), Float(basis.right.z), 0), + SIMD4(Float(basis.up.x), Float(basis.up.y), Float(basis.up.z), 0), + SIMD4(Float(basis.back.x), Float(basis.back.y), Float(basis.back.z), 0), + SIMD4(Float(eye.x), Float(eye.y), Float(eye.z), 1) ) ) near = max(0.01, extent * 0.01) diff --git a/apps/sculpt/Sources/RookRendering/SculptureVoxelGeometry.swift b/apps/sculpt/Sources/RookRendering/SculptureVoxelGeometry.swift index fbaf841a..3b067245 100644 --- a/apps/sculpt/Sources/RookRendering/SculptureVoxelGeometry.swift +++ b/apps/sculpt/Sources/RookRendering/SculptureVoxelGeometry.swift @@ -267,11 +267,12 @@ private struct VoxelCamera { let width: Double let height: Double let scale: Double - let cy: Double - let sy: Double - let cp: Double - let sp: Double + let right: SIMD3 + let up: SIMD3 + let back: SIMD3 let distance: Double + let panX: Double + let panY: Double init(sculpture: Sculpture, camera: SculptureCamera, width: Int, height: Int) { self.init( @@ -291,11 +292,15 @@ private struct VoxelCamera { self.width = Double(width) self.height = Double(height) let extent = Double(max(volumeWidth, volumeHeight, volumeDepth)) - let yaw = camera.yaw.isFinite ? camera.yaw.truncatingRemainder(dividingBy: 2 * .pi) : 0 - let pitch = camera.pitch.isFinite ? max(-1.4, min(1.4, camera.pitch)) : 0 - let zoom = camera.zoom.isFinite ? max(0.5, min(2, camera.zoom)) : 1 - scale = Double(min(width, height)) * 0.68 / extent * zoom - cy = cos(yaw); sy = sin(yaw); cp = cos(pitch); sp = sin(pitch) + let camera = camera.normalized + let basis = camera.basis + panX = camera.panX; panY = camera.panY + scale = camera.projectionScale( + dimensions: SIMD3(volumeWidth, volumeHeight, volumeDepth), + width: Double(width), + height: Double(height) + ) + right = basis.right; up = basis.up; back = basis.back distance = extent * 3 } @@ -305,7 +310,9 @@ private struct VoxelCamera { let x = Double(cell.x) - centerX + nx * 0.5 let y = centerY - Double(cell.y) + ny * 0.5 let z = Double(cell.z) - centerZ + nz * 0.5 - return nx * (-sy * cp * distance - x) + ny * (sp * distance - y) + nz * (cy * cp * distance - z) > 0.000_001 + let eye = back * distance + right * panX + up * panY + let eyeX = eye.x, eyeY = eye.y, eyeZ = eye.z + return nx * (eyeX - x) + ny * (eyeY - y) + nz * (eyeZ - z) > 0.000_001 } func face(_ face: SculptureVoxelFace, cell: SculptureCell, glyph: UInt8, adjacent: SculptureCell?) @@ -394,14 +401,14 @@ private struct VoxelCamera { private func project(_ point: (Double, Double, Double)) -> SculptureVoxelVertex { let vx = point.0 - centerX, vy = centerY - point.1, vz = point.2 - centerZ - let rx = vx * cy + vz * sy - let rz = -vx * sy + vz * cy - let ry = vy * cp - rz * sp - let depth = vy * sp + rz * cp + let position = SIMD3(vx, vy, vz) + let rx = (position * right).sum() + let ry = (position * up).sum() + let depth = (position * back).sum() let perspective = 1 / (1 - depth / distance) return SculptureVoxelVertex( - x: width / 2 + rx * scale * perspective, - y: height / 2 - ry * scale * perspective, + x: width / 2 + (rx - panX) * scale * perspective, + y: height / 2 - (ry - panY) * scale * perspective, depth: depth ) } diff --git a/apps/sculpt/Sources/RookSculpture/SculptureProjection.swift b/apps/sculpt/Sources/RookSculpture/SculptureProjection.swift index 73ec5387..cd2f899d 100644 --- a/apps/sculpt/Sources/RookSculpture/SculptureProjection.swift +++ b/apps/sculpt/Sources/RookSculpture/SculptureProjection.swift @@ -4,11 +4,158 @@ public struct SculptureCamera: Equatable, Sendable { public var yaw: Double public var pitch: Double public var zoom: Double + public var panX: Double + public var panY: Double + public var fitsVolume: Bool + public var axisRotation: SIMD4 - public init(yaw: Double = -0.6, pitch: Double = 0.35, zoom: Double = 1) { + public init( + yaw: Double = -0.6, + pitch: Double = 0.35, + zoom: Double = 1, + panX: Double = 0, + panY: Double = 0, + fitsVolume: Bool = false, + axisRotation: SIMD4 = SIMD4(0, 0, 0, 1) + ) { self.yaw = yaw self.pitch = pitch self.zoom = zoom + self.panX = panX + self.panY = panY + self.fitsVolume = fitsVolume + self.axisRotation = axisRotation + } + + /// Session inputs are sanitized once for the scalar and live render paths. + public var normalized: Self { + Self( + yaw: yaw.isFinite ? yaw.truncatingRemainder(dividingBy: 2 * .pi) : 0, + pitch: pitch.isFinite ? pitch.truncatingRemainder(dividingBy: 2 * .pi) : 0, + zoom: zoom.isFinite ? max(0.5, min(2, zoom)) : 1, + panX: panX.isFinite ? max(-1_000_000, min(1_000_000, panX)) : 0, + panY: panY.isFinite ? max(-1_000_000, min(1_000_000, panY)) : 0, + fitsVolume: fitsVolume, + axisRotation: normalizedRotation + ) + } + + public var basis: (right: SIMD3, up: SIMD3, back: SIMD3) { + let camera = normalized + let cy = cos(camera.yaw), sy = sin(camera.yaw), cp = cos(camera.pitch), sp = sin(camera.pitch) + return ( + rotated(SIMD3(cy, 0, sy)), rotated(SIMD3(sy * sp, cp, -cy * sp)), + rotated(SIMD3(-sy * cp, sp, cy * cp)) + ) + } + + private var normalizedRotation: SIMD4 { + let largest = max(abs(axisRotation.x), abs(axisRotation.y), abs(axisRotation.z), abs(axisRotation.w)) + guard largest.isFinite, largest > 0, + axisRotation.x.isFinite, axisRotation.y.isFinite, axisRotation.z.isFinite, axisRotation.w.isFinite + else { return SIMD4(0, 0, 0, 1) } + let scaled = axisRotation / largest + return scaled / sqrt((scaled * scaled).sum()) + } + + private func rotated(_ point: SIMD3) -> SIMD3 { + let q = normalizedRotation + let vector = SIMD3(q.x, q.y, q.z) + let cross = + SIMD3( + vector.y * point.z - vector.z * point.y, + vector.z * point.x - vector.x * point.z, + vector.x * point.y - vector.y * point.x + ) * 2 + return point + q.w * cross + + SIMD3( + vector.y * cross.z - vector.z * cross.y, + vector.z * cross.x - vector.x * cross.z, + vector.x * cross.y - vector.y * cross.x + ) + } + + /// Positive rotation follows document X, row-down Y, and plane Z. Orientation remains session-only. + public mutating func rotate(axis: Int, radians: Double) { + guard (0...2).contains(axis), radians.isFinite else { return } + let angle = radians.truncatingRemainder(dividingBy: 2 * .pi) / 2 + var rotation = SIMD4(0, 0, 0, cos(angle)) + rotation[axis] = sin(angle) * (axis == 1 ? -1 : 1) + let q = normalizedRotation + let a = SIMD3(rotation.x, rotation.y, rotation.z), b = SIMD3(q.x, q.y, q.z) + let vector = + rotation.w * b + q.w * a + + SIMD3( + a.y * b.z - a.z * b.y, + a.z * b.x - a.x * b.z, + a.x * b.y - a.y * b.x + ) + axisRotation = SIMD4(vector.x, vector.y, vector.z, rotation.w * q.w - (a * b).sum()) + self = normalized + } + + /// Interactive sessions opt into complete-cube framing. Default cameras preserve existing exported previews. + public func projectionScale(dimensions: SIMD3, width: Double, height: Double) -> Double { + let camera = normalized + let extent = Double(max(1, dimensions.x, dimensions.y, dimensions.z)) + let distance = extent * 3 + let width = max(1, width), height = max(1, height) + let scale = min(width, height) * 0.68 / extent * camera.zoom + guard camera.fitsVolume else { return scale } + var tangent = height / (2 * scale * distance) + let basis = camera.basis + var fit = 0.0 + for x in [-Double(dimensions.x) / 2, Double(dimensions.x) / 2] { + for y in [-Double(dimensions.y) / 2, Double(dimensions.y) / 2] { + for z in [-Double(dimensions.z) / 2, Double(dimensions.z) / 2] { + let point = SIMD3(x, y, z) + let depth = distance - (point * basis.back).sum() + fit = max( + fit, + abs((point * basis.up).sum()) / depth, + abs((point * basis.right).sum()) / depth / (width / height) + ) + } + } + } + tangent = max(tangent, fit * 1.12 / camera.zoom) + return height / (2 * distance * tangent) + } + + public mutating func orbit(horizontal: Double, vertical: Double) { + guard horizontal.isFinite, vertical.isFinite else { return } + var camera = normalized + camera.yaw += horizontal * 0.008 + camera.pitch += vertical * 0.008 + self = camera.normalized + } + + public mutating func pan( + horizontal: Double, + vertical: Double, + extent: Double, + width: Double, + height: Double, + dimensions: SIMD3? = nil + ) { + guard horizontal.isFinite, vertical.isFinite, extent.isFinite, extent > 0, + width.isFinite, height.isFinite, width > 0, height > 0 + else { return } + var camera = normalized + let scale = + dimensions.map { camera.projectionScale(dimensions: $0, width: width, height: height) } + ?? min(width, height) * 0.68 / extent * camera.zoom + guard scale.isFinite, scale > 0 else { return } + camera.panX -= horizontal / scale + camera.panY += vertical / scale + self = camera.normalized + } + + public mutating func magnify(_ factor: Double) { + guard factor.isFinite, factor > 0 else { return } + var camera = normalized + camera.zoom = max(0.5, min(2, camera.zoom * factor)) + self = camera } } @@ -50,15 +197,14 @@ public enum SculptureProjection { guard !Task.isCancelled, sculpture.occupiedCount > 0 else { return SculptureFrame(columns: columns, rows: rows, pixels: pixels) } - let yaw = camera.yaw.isFinite ? camera.yaw.truncatingRemainder(dividingBy: 2 * .pi) : 0 - let pitch = camera.pitch.isFinite ? max(-1.4, min(1.4, camera.pitch)) : 0 - let zoom = camera.zoom.isFinite ? max(0.5, min(2, camera.zoom)) : 1 + let camera = camera.normalized + let basis = camera.basis let extent = Double(max(sculpture.width, sculpture.height, sculpture.depth)) - let scale = min(Double(columns) / 2, Double(rows)) * 0.68 / extent * zoom - let cy = cos(yaw) - let sy = sin(yaw) - let cp = cos(pitch) - let sp = sin(pitch) + let scale = camera.projectionScale( + dimensions: SIMD3(sculpture.width, sculpture.height, sculpture.depth), + width: Double(columns) / 2, + height: Double(rows) + ) let centerX = Double(sculpture.width - 1) / 2 let centerY = Double(sculpture.height - 1) / 2 let centerZ = Double(sculpture.depth - 1) / 2 @@ -76,13 +222,13 @@ public enum SculptureProjection { guard glyph != Sculpture.empty else { continue } let cell = SculptureCell(x: x, y: y, z: z) let vx = Double(x) - centerX - let rx = vx * cy + vz * sy - let rz = -vx * sy + vz * cy - let ry = vy * cp - rz * sp - let depth = vy * sp + rz * cp + let point = SIMD3(vx, vy, vz) + let rx = (point * basis.right).sum() + let ry = (point * basis.up).sum() + let depth = (point * basis.back).sum() let perspective = 1 / (1 - depth / (extent * 3)) - let column = Int((Double(columns) / 2 + rx * scale * 2 * perspective).rounded()) - let row = Int((Double(rows) / 2 - ry * scale * perspective).rounded()) + let column = Int((Double(columns) / 2 + (rx - camera.panX) * scale * 2 * perspective).rounded()) + let row = Int((Double(rows) / 2 - (ry - camera.panY) * scale * perspective).rounded()) guard (0..= depth { continue } diff --git a/apps/sculpt/Tests/RookAppTests/SculptureCanvasPointerTests.swift b/apps/sculpt/Tests/RookAppTests/SculptureCanvasPointerTests.swift index a9a49fba..4fcf75cb 100644 --- a/apps/sculpt/Tests/RookAppTests/SculptureCanvasPointerTests.swift +++ b/apps/sculpt/Tests/RookAppTests/SculptureCanvasPointerTests.swift @@ -82,6 +82,31 @@ struct SculptureCanvasPointerTests { #expect(window.firstResponder === keyboard) } + @MainActor + @Test func modifiedDragsPanWithoutDispatchingPaintOrSelectionEvents() throws { + _ = NSApplication.shared + let window = pointerWindow() + defer { window.close() } + let pointer = SculptureCanvasPointerView(frame: CGRect(x: 0, y: 0, width: 200, height: 100)) + try #require(window.contentView).addSubview(pointer) + var phases: [SculpturePointerPhase] = [] + var ordinaryEvents = 0 + pointer.event = { _, _ in ordinaryEvents += 1 } + pointer.camera = { input in + if case .pan(let phase, _) = input { phases.append(phase) } + } + pointer.mouseDown(with: try mouse(.leftMouseDown, at: .zero, in: window, modifiers: .shift)) + pointer.mouseDragged(with: try mouse(.leftMouseDragged, at: CGPoint(x: 10, y: 10), in: window)) + pointer.mouseUp(with: try mouse(.leftMouseUp, at: CGPoint(x: 20, y: 20), in: window)) + pointer.rightMouseDown(with: try mouse(.rightMouseDown, at: .zero, in: window)) + pointer.rightMouseDragged(with: try mouse(.rightMouseDragged, at: CGPoint(x: 10, y: 10), in: window)) + pointer.rightMouseUp(with: try mouse(.rightMouseUp, at: CGPoint(x: 20, y: 20), in: window)) + #expect(phases == [.down, .drag, .up, .down, .drag, .up]) + #expect(ordinaryEvents == 0) + pointer.mouseDown(with: try mouse(.leftMouseDown, at: .zero, in: window)) + #expect(ordinaryEvents == 1) + } + @MainActor private func pointerWindow() -> NSWindow { let window = NSWindow( @@ -96,12 +121,17 @@ struct SculptureCanvasPointerTests { } @MainActor - private func mouse(_ type: NSEvent.EventType, at point: CGPoint, in window: NSWindow) throws -> NSEvent { + private func mouse( + _ type: NSEvent.EventType, + at point: CGPoint, + in window: NSWindow, + modifiers: NSEvent.ModifierFlags = [] + ) throws -> NSEvent { try #require( NSEvent.mouseEvent( with: type, location: point, - modifierFlags: [], + modifierFlags: modifiers, timestamp: 1, windowNumber: window.windowNumber, context: nil, diff --git a/apps/sculpt/Tests/RookAppTests/SculptureWorkspaceTests.swift b/apps/sculpt/Tests/RookAppTests/SculptureWorkspaceTests.swift index 73286b90..ba6d2993 100644 --- a/apps/sculpt/Tests/RookAppTests/SculptureWorkspaceTests.swift +++ b/apps/sculpt/Tests/RookAppTests/SculptureWorkspaceTests.swift @@ -203,3 +203,52 @@ import Testing #expect(!workspace.canUndo) #expect(workspace.error != nil) } + +private struct SliceEditFixtures: Decodable { + let cases: [SliceEditCase] +} +private struct SliceEditCase: Decodable { + let name: String + let initial: [[String]] + let expected: [[String]] + let tool: String + let glyph: String + let size: Int + let z: Int + let path: [[Int]] +} + +@MainActor @Test func browserSliceFixturesMatchNativeWorkspaceToolsAndWholeStrokeHistory() throws { + var root = URL(fileURLWithPath: #filePath) + for _ in 0..<5 { root.deleteLastPathComponent() } + let fixtures = try JSONDecoder().decode( + SliceEditFixtures.self, + from: Data(contentsOf: root.appendingPathComponent("docs/evidence/viewer-slice/slice-parity.json")) + ) + for item in fixtures.cases { + let original = try Sculpture( + title: item.name, + width: item.initial[0][0].utf8.count, + height: item.initial[0].count, + layers: item.initial.map { Array($0.joined().utf8) } + ) + let workspace = SculptureWorkspace() + workspace.replace(with: original, opened: true) + workspace.tool = item.tool == "erase" ? .erase : item.tool == "fill" ? .fill : .draw + workspace.brush = item.glyph.utf8.first ?? 35 + workspace.brushSize = item.size + for (index, point) in item.path.enumerated() { + workspace.paint(SculptureCell(x: point[0], y: point[1], z: item.z), start: index == 0) + } + workspace.endStroke() + #expect(workspace.sculpture.layers == item.expected.map { Array($0.joined().utf8) }) + #expect(workspace.canUndo == (item.initial != item.expected)) + if workspace.canUndo { + workspace.undo() + #expect(workspace.sculpture == original) + #expect(!workspace.canUndo) + workspace.redo() + #expect(workspace.sculpture.layers == item.expected.map { Array($0.joined().utf8) }) + } + } +} diff --git a/apps/sculpt/Tests/RookRenderingTests/CameraParityTests.swift b/apps/sculpt/Tests/RookRenderingTests/CameraParityTests.swift new file mode 100644 index 00000000..77eed43b --- /dev/null +++ b/apps/sculpt/Tests/RookRenderingTests/CameraParityTests.swift @@ -0,0 +1,169 @@ +import Foundation +import RookSculpture +import Testing +import simd + +@testable import RookRendering + +@MainActor +struct CameraParityTests { + @Test func nativeCameraMatchesSharedBrowserProjectionCases() throws { + var root = URL(fileURLWithPath: #filePath) + for _ in 0..<5 { root.deleteLastPathComponent() } + let fixture = try JSONDecoder().decode( + CameraFixture.self, + from: Data(contentsOf: root.appendingPathComponent("docs/evidence/viewer-camera/camera-parity.json")) + ) + let dimensions = SIMD3(fixture.dimensions[0], fixture.dimensions[1], fixture.dimensions[2]) + let size = CGSize(width: fixture.viewport[0], height: fixture.viewport[1]) + for pose in fixture.cases { + var camera = SculptureCamera( + yaw: pose.yaw, + pitch: pose.pitch, + zoom: pose.zoom, + panX: pose.panX, + panY: pose.panY, + fitsVolume: true + ) + for step in pose.rotations ?? [] { camera.rotate(axis: Int(step[0]), radians: step[1] * .pi / 180) } + let layers = (0..( + Float(cell.x) - Float(dimensions.x - 1) / 2, + Float(dimensions.y - 1) / 2 - Float(cell.y), + Float(cell.z) - Float(dimensions.z - 1) / 2, + 1 + ) + let clip = transform.projection * simd_inverse(transform.cameraToWorld) * point + let x = (Double(clip.x / clip.w) + 1) * Double(fixture.viewport[0]) / 2 + let y = (1 - Double(clip.y / clip.w)) * Double(fixture.viewport[1]) / 2 + #expect(abs(x - pose.projected[index][0]) < 0.001) + #expect(abs(y - pose.projected[index][1]) < 0.001) + } + } + } + + @Test func axisRotationsRemainOrthonormalAndInvalidInputsDoNotMoveCamera() { + var camera = SculptureCamera() + let original = camera.basis + for axis in 0...2 { + for _ in 0..<24 { camera.rotate(axis: axis, radians: .pi / 12) } + } + for (actual, expected) in [ + (camera.basis.right, original.right), (camera.basis.up, original.up), (camera.basis.back, original.back), + ] { + #expect(((actual - expected) * (actual - expected)).sum() < 0.000_000_001) + } + for index in 0..<1000 { camera.rotate(axis: index % 3, radians: 0.013) } + let basis = camera.basis + #expect(abs((basis.right * basis.up).sum()) < 0.000_000_001) + #expect(abs((basis.back * basis.up).sum()) < 0.000_000_001) + #expect(abs((basis.right * basis.right).sum() - 1) < 0.000_000_001) + let before = camera + camera.rotate(axis: 3, radians: 1) + camera.rotate(axis: 0, radians: .nan) + #expect(camera == before) + #expect(SculptureCamera(axisRotation: SIMD4(.infinity, 0, 0, 0)).normalized.axisRotation == SIMD4(0, 0, 0, 1)) + } + + @Test func asciiPickingFollowsDocumentZRotation() throws { + var layers = Array(repeating: Array(repeating: Sculpture.empty, count: 63), count: 5) + layers[2][3 * 9 + 6] = 35 + let sculpture = try Sculpture(title: "ASCII axis", width: 9, height: 7, layers: layers) + let cell = SculptureCell(x: 6, y: 3, z: 2) + var camera = SculptureCamera(yaw: 0, pitch: 0) + camera.rotate(axis: 2, radians: .pi / 2) + let rotated = SculptureProjection.frame(sculpture, camera: camera, columns: 160, rows: 100) + #expect(rotated.cell(column: 80, row: 62) == cell) + camera.rotate(axis: 2, radians: -.pi / 2) + #expect( + SculptureProjection.frame(sculpture, camera: camera, columns: 160, rows: 100).cell(column: 104, row: 50) + == cell + ) + } + + @Test func interactiveFramingPreservesDefaultExportCameraScale() { + let dimensions = SIMD3(16, 16, 16) + let legacy = SculptureCamera() + let fitted = SculptureCamera(fitsVolume: true) + let scale = 576.0 * 0.68 / 16 + #expect(abs(legacy.projectionScale(dimensions: dimensions, width: 576, height: 648) - scale) < 0.000_001) + #expect(fitted.projectionScale(dimensions: dimensions, width: 576, height: 648) < scale) + #expect(fitted.normalized.fitsVolume) + } + + @Test func cameraInputsRemainFiniteAndPanHasTheNativeScreenScale() { + let invalid = SculptureCamera(yaw: .nan, pitch: .infinity, zoom: -.infinity, panX: .nan, panY: .infinity) + #expect(invalid.normalized == SculptureCamera(yaw: 0, pitch: 0)) + var camera = SculptureCamera(yaw: 0, pitch: 0) + camera.orbit(horizontal: 2 * .pi / 0.008, vertical: 2 * .pi / 0.008) + #expect(abs(camera.yaw) < 0.000_001 && abs(camera.pitch) < 0.000_001) + camera.pan(horizontal: 34, vertical: 68, extent: 9, width: 400, height: 320) + #expect(abs(camera.panX + 34 / (320 * 0.68 / 9)) < 0.000_001) + #expect(abs(camera.panY - 68 / (320 * 0.68 / 9)) < 0.000_001) + camera.magnify(100) + #expect(camera.zoom == 2) + camera.magnify(0.001) + #expect(camera.zoom == 0.5) + let previous = camera + camera.orbit(horizontal: .infinity, vertical: 0) + camera.pan(horizontal: 1, vertical: 1, extent: 9, width: 0, height: 320) + camera.magnify(.nan) + #expect(camera == previous) + } +} + +private struct CameraFixture: Decodable { + let dimensions: [Int] + let viewport: [Int] + let cells: [FixtureCell] + let cases: [FixturePose] +} + +private struct FixtureCell: Decodable { + let x: Int + let y: Int + let z: Int +} + +private struct FixturePose: Decodable { + let yaw: Double + let pitch: Double + let zoom: Double + let panX: Double + let panY: Double + let right: [Double] + let up: [Double] + let back: [Double] + let projected: [[Double]] + let rotations: [[Double]]? +} diff --git a/apps/sculpt/Tests/RookRenderingTests/SculptureLiveVoxelTests.swift b/apps/sculpt/Tests/RookRenderingTests/SculptureLiveVoxelTests.swift index c292dd8f..86f439f7 100644 --- a/apps/sculpt/Tests/RookRenderingTests/SculptureLiveVoxelTests.swift +++ b/apps/sculpt/Tests/RookRenderingTests/SculptureLiveVoxelTests.swift @@ -20,9 +20,17 @@ struct SculptureLiveVoxelTests { let view = controller.makeView() view.frame = CGRect(x: 0, y: 0, width: 400, height: 320) let id = UUID() + var rotated = SculptureCamera() + rotated.rotate(axis: 2, radians: .pi / 2) let poses = [ + rotated, SculptureCamera(yaw: 0, pitch: 0), SculptureCamera(yaw: -0.6, pitch: 0.7), SculptureCamera(yaw: 1.1, pitch: -0.4, zoom: 1.2), SculptureCamera(yaw: -.pi / 2, pitch: 0.2), + SculptureCamera(yaw: -0.6, pitch: .pi / 2), + SculptureCamera(yaw: -0.6, pitch: .pi / 2 + 0.2), + SculptureCamera(yaw: 1.1, pitch: -.pi / 2), + SculptureCamera(yaw: -0.6, pitch: .pi), + SculptureCamera(yaw: -0.6, pitch: 0.35, zoom: 1.2, panX: 1.25, panY: -0.6), ] for camera in poses { controller.configure( diff --git a/apps/sculpt/hi/cubes.md b/apps/sculpt/hi/cubes.md index 1dade856..4cc4441b 100644 --- a/apps/sculpt/hi/cubes.md +++ b/apps/sculpt/hi/cubes.md @@ -15,3 +15,5 @@ I want to sculpt translucent cubes as well as ASCII, paint on a visible face, an - **CUBES-22** I can add cubes on a visible face or an empty selected slice, erase cubes, and undo a painting stroke without accidentally orbiting the camera. - **CUBES-23** I can open and edit a sculpture up to 64 cells along each axis in the existing 3md schema, while oversized or malformed files are refused. - **CUBES-27** I can create, paint, save and reopen a 256 by 256 by 256 volume, reach every cell with zoom and scrolling, and receive a clear explanation if its surface detail exceeds a preview or mesh export limit. + +- **CUBES-28** I can choose X, Y or Z on a rotation sphere, drag around only that axis, enter an exact degree step, and pan by a number of cells. Free gives me ordinary orbit again. The same camera movement works in the browser, and it does not change my sculpture or undo history. diff --git a/apps/sculpt/hi/render.md b/apps/sculpt/hi/render.md index cb02df77..b3769a16 100644 --- a/apps/sculpt/hi/render.md +++ b/apps/sculpt/hi/render.md @@ -14,4 +14,4 @@ I want to orbit and zoom a large sculpture immediately, without waiting for the ## Criteria - **RENDER-25** Larger previews render away from the interface so I can keep using the editor, and an export that exceeds its mesh limit explains the limit without changing my sculpture. -- **RENDER-29** Live cube camera movement reuses the sculpture's prepared surfaces and updates the GPU camera without scanning the volume or rasterizing a bitmap on each event. Painting and selection still target the visible sculpture, and the packaged app uses an optimized build. +- **RENDER-29** Live cube camera movement reuses the sculpture's prepared surfaces and updates the GPU camera without scanning the volume or rasterizing a bitmap on each event. I can rotate through full turns, pan with a tool or modified drag, scroll or pinch to zoom, and Fit returns the sculpture to its starting view. Painting and selection still target the visible sculpture, camera controls match the web viewer, and the packaged app uses an optimized build. diff --git a/apps/sculpt/specs/RookApp/RookApp.spec.md b/apps/sculpt/specs/RookApp/RookApp.spec.md index 49a9f3c2..825fdee6 100644 --- a/apps/sculpt/specs/RookApp/RookApp.spec.md +++ b/apps/sculpt/specs/RookApp/RookApp.spec.md @@ -1,6 +1,6 @@ --- module: RookApp -version: 21 +version: 23 status: active files: - Sources/RookApp/SculpturePortableInterchange.swift @@ -111,6 +111,14 @@ The slice list creates rows lazily while preserving stable slice identifiers. It 15. Gallery construction runs outside the main actor so the first 256-volume scene construction does not block search controls. The command palette offers New 256-cubed volume through the same dirty-replacement path as the File menu. 16. Reopen uses the shared codec's private preparse limit of 100,000 physical lines as well as the 20 MiB bound. A tiny-line-heavy rejected file leaves the open sculpture unchanged and does not reach ThreeMD's per-line parsing allocations. +### REQ-RookApp-088 + +The volume canvas SHALL also show colored X/Y/Z sphere rings and accessible Free/X/Y/Z constraints. Selected-axis dragging and finite positive degree steps (default 15) SHALL rotate only that document axis. Finite positive pan steps (default 0.25 cells) SHALL move in screen space; invalid step input SHALL leave the pose unchanged. The volume canvas SHALL offer Pan in addition to Orbit. Shift-left, middle and right dragging SHALL pan without painting or selecting a slice, including when Paint is active. Scroll and trackpad magnification SHALL zoom proportionally within 0.5...2. The local pointer bridge SHALL retain the starting drag mode through mouse-up and preserve canvas keyboard focus. Fit SHALL restore the default orbit pose, zoom 1 and zero pan. Ordinary Paint and grouped stroke Undo SHALL remain available. + +Acceptance Criteria: + +- Native pointer regressions prove modified dragging emits only camera events and preserves ordinary mouse delivery. Native picking and painting continue to share the matched camera. Returning to Paint releases the Pan tool. + ## Behavioral Examples - Closing the main window and choosing Show Sculpt.3md orders that same window forward. @@ -137,6 +145,8 @@ COMPOSITION-39 makes insertion discoverable. While a composition or world sheet RookCore, RookSculpture, RookRendering, SwiftUI, AppKit, and UniformTypeIdentifiers. RookSculpture carries the immutable ThreeMD package dependency; the native portable adapter also imports its types directly. No bundled font or image. ## Change Log +- 2026-10-10: Full-turn volume camera, screen-space pan and matched browser/native projection. Verification and lifecycle closure are recorded separately. + - Version 12: explicit portable file actions and retained upstream shared-edit snapshots for EXPORT-35. Actual native observations and new test receipts are recorded separately. - Shared-model preparation: explicit Apply/Cancel sessions, library-aware graph history and dirty baselines for COMPOSITION-34. Current evidence is recorded separately; old lifecycle records remain historical. @@ -165,3 +175,7 @@ RookCore, RookSculpture, RookRendering, SwiftUI, AppKit, and UniformTypeIdentifi | 2026-10-06 | make-3md-file-and-folder-insertion-discoverable-and-reliable-for-people-and-explicit-file-agent-tools: Make 3md file and folder insertion discoverable and reliable for people and explicit-file agent tools | | 2026-10-07 | open-and-resolve-linked-3md-compositions-from-a-chosen-project-folder-and-import-self-contained-bundles: Open and resolve linked 3md compositions from a chosen project folder and import self-contained bundles | | 2026-10-07 | show-every-example-in-one-gallery-and-add-a-math-generated-size-ladder-from-16-to-10-240-cells: Show every example in one gallery and add a math-generated size ladder from 16 to 10,240 cells | + +## Document-axis camera controls + +The interactive camera composes a normalized session quaternion with its continuous yaw/pitch basis. Positive axis steps follow document X, row-down Y and plane Z. Shared matrix-reference fixtures cover X, Y and Z rotation, mixed sequences, negative and inverse steps and full turns. Scalar ASCII, CPU voxel projection and the native live camera consume this same basis. Camera changes reuse installed geometry and do not edit document cells or history. Legacy default export framing remains unchanged. diff --git a/apps/sculpt/specs/RookApp/requirements.md b/apps/sculpt/specs/RookApp/requirements.md index 67ab4b13..6a9afa62 100644 --- a/apps/sculpt/specs/RookApp/requirements.md +++ b/apps/sculpt/specs/RookApp/requirements.md @@ -164,3 +164,11 @@ Acceptance Criteria - In-process tests open a model, a composition and a world from the gallery, cancel a large entry while it loads, and confirm the current document and history are unchanged afterwards. - Listing the gallery generates no large entry. + +### REQ-RookApp-088 + +The volume canvas SHALL also show colored X/Y/Z sphere rings and accessible Free/X/Y/Z constraints. Selected-axis dragging and finite positive degree steps (default 15) SHALL rotate only that document axis. Finite positive pan steps (default 0.25 cells) SHALL move in screen space; invalid step input SHALL leave the pose unchanged. The volume canvas SHALL offer Pan in addition to Orbit. Shift-left, middle and right dragging SHALL pan without painting or selecting a slice, including when Paint is active. Scroll and trackpad magnification SHALL zoom proportionally within 0.5...2. The local pointer bridge SHALL retain the starting drag mode through mouse-up and preserve canvas keyboard focus. Fit SHALL restore the default orbit pose, zoom 1 and zero pan. Ordinary Paint and grouped stroke Undo SHALL remain available. + +Acceptance Criteria: + +- Native pointer regressions prove modified dragging emits only camera events and preserves ordinary mouse delivery. Native picking and painting continue to share the matched camera. Returning to Paint releases the Pan tool. diff --git a/apps/sculpt/specs/RookRendering/RookRendering.spec.md b/apps/sculpt/specs/RookRendering/RookRendering.spec.md index b4ec5cd8..fb48c0fb 100644 --- a/apps/sculpt/specs/RookRendering/RookRendering.spec.md +++ b/apps/sculpt/specs/RookRendering/RookRendering.spec.md @@ -1,6 +1,6 @@ --- module: RookRendering -version: 7 +version: 9 status: active files: - Sources/RookRendering/SculptureWorldNavigation.swift @@ -207,6 +207,14 @@ The world controller's publicly readable, privately set properties are `installe 22. World scene identity changes install one GPU geometry set per prepared model definition. Repeated instances share that set. Focus and radius changes rebuild only bounded placement nodes and proxy/detail choices. Camera-only updates retain model buffers and instance nodes and update native transform/projection only; they do not resolve models, extract surfaces, scan placements, or run the CPU rasterizer. Native resize updates the projection. Session focus, distances, and camera are not document metadata. 23. Native world mouse dragging beyond the click threshold changes yaw/pitch; scroll changes bounded zoom. A click selects the nearest detailed surface or proxy bounds through upper-left-origin native view-local picking, returning its stored instance ID. This view owns no placement edit, undo transaction, filesystem access, process, or network capability. World rendering has no selected-slice ghost mesh. The caller owns world edits and supplies a changed identity and prepared scene for those edits. +### REQ-RookRendering-008 + +Scalar ASCII, CPU voxel and live GPU volume cameras SHALL consume the same normalized three-axis basis, including Z rotation, with matching projection and picking and no geometry reinstall. Native scalar, prepared and live volume projection SHALL use the same full-turn camera basis, screen-space pan target and finite inputs. Panning SHALL translate both the eye and target in the camera right/up plane. Camera-facing surface selection and nearest-quad picking SHALL account for the translated eye. Camera updates SHALL reuse the installed document buffers. Rendering, ghost and export budgets SHALL remain unchanged. + +Acceptance Criteria: + +- The shared camera fixture compares native basis and projected points with browser values. Native scalar/live picks agree through the poles, upside down and after pan; the mesh installation count remains one. + ## Behavioral Examples - A frame raster is wider than an empty frame's uniform charcoal only where glyphs were projected. @@ -243,6 +251,8 @@ RookSculpture, AppKit, Observation, SceneKit, simd, Core Text, Core Graphics, Im ## Change Log +- 2026-10-10: Full-turn volume camera, screen-space pan and matched browser/native projection. Verification and lifecycle closure are recorded separately. + - Version 6: worker-prepared native mesh/ghost bytes, cached model reuse across world placement edits, subpixel grid edge detail, direct-neighbor exterior extraction and a prepared-scene cube projection reused by animation jobs for WORLD-33. Existing scalar fallback and capacity limits remain. New release measurements and verification are recorded separately under `docs/evidence/blockhaven/`; no lifecycle approval or finalization is claimed. - Version 1: raster and Metal-backed view from the sources on `leif/ascii-sculpture`. Export names are bare. No review or finalization is claimed. @@ -253,3 +263,7 @@ RookSculpture, AppKit, Observation, SceneKit, simd, Core Text, Core Graphics, Im - Correction, same version: adapt live empty-slice edge visibility below 2.5 projected AppKit points, retaining faint fill picking and unchanged mesh buffers. The dense-grid snapshot/target regression, full lane and actual native orbit, zoom, selection and face/ghost-stroke Undo checks passed; retained evidence is in that same directory. - Version 5: a Sendable prepared sparse-world scene and observable native SceneKit Metal controller retain shared model buffers across focus and camera changes. Exact integer rebasing precedes distance culling and GPU conversion; nearby placements use bounded full detail, farther or over-budget placements use selectable bounds. Unique prepared definitions are limited to 1_000_000 exterior faces; at most 512 active placements and 500_000 full/proxy faces are rendered. Controlled tests are authored with execution and new visual evidence pending in the root lane. Earlier bounded-document camera evidence is unchanged; no lifecycle approval, review, or finalization is claimed. | 2026-10-05 | add-free-exploration-of-sparse-worlds-with-wasd-movement-drag-to-look-vertical-travel-and-a-clear-overview: Add free exploration of sparse worlds with WASD movement, drag to look, vertical travel and a clear overview | + +## Document-axis camera controls + +The interactive camera composes a normalized session quaternion with its continuous yaw/pitch basis. Positive axis steps follow document X, row-down Y and plane Z. Shared matrix-reference fixtures cover X, Y and Z rotation, mixed sequences, negative and inverse steps and full turns. Scalar ASCII, CPU voxel projection and the native live camera consume this same basis. Camera changes reuse installed geometry and do not edit document cells or history. Legacy default export framing remains unchanged. diff --git a/apps/sculpt/specs/RookRendering/requirements.md b/apps/sculpt/specs/RookRendering/requirements.md index 9703071f..974a0001 100644 --- a/apps/sculpt/specs/RookRendering/requirements.md +++ b/apps/sculpt/specs/RookRendering/requirements.md @@ -94,3 +94,11 @@ Acceptance Criteria - Coarse geometry remains bounded, camera-independent and recognizable for nonempty models. - Directions, normalization, Int64 edges and input cancellation have semantic and native tests. - Native and visual evidence is distinct from FPS claims. + +### REQ-RookRendering-008 + +Scalar ASCII, CPU voxel and live GPU volume cameras SHALL consume the same normalized three-axis basis, including Z rotation, with matching projection and picking and no geometry reinstall. Native scalar, prepared and live volume projection SHALL use the same full-turn camera basis, screen-space pan target and finite inputs. Panning SHALL translate both the eye and target in the camera right/up plane. Camera-facing surface selection and nearest-quad picking SHALL account for the translated eye. Camera updates SHALL reuse the installed document buffers. Rendering, ghost and export budgets SHALL remain unchanged. + +Acceptance Criteria: + +- The shared camera fixture compares native basis and projected points with browser values. Native scalar/live picks agree through the poles, upside down and after pan; the mesh installation count remains one. diff --git a/apps/sculpt/specs/RookSculpture/RookSculpture.spec.md b/apps/sculpt/specs/RookSculpture/RookSculpture.spec.md index de82963f..3bf48477 100644 --- a/apps/sculpt/specs/RookSculpture/RookSculpture.spec.md +++ b/apps/sculpt/specs/RookSculpture/RookSculpture.spec.md @@ -1,6 +1,6 @@ --- module: RookSculpture -version: 22 +version: 24 status: active files: - Sources/RookSculpture/SculptureVolumeStudyExamples.swift @@ -226,8 +226,19 @@ Names below are the public declarations in the source files. This table does not | `format` | format(of:) chooses compact only when the complete eight-byte compact magic matches; otherwise the readable codec performs validation. | | `SculptureCamera` | Session pose. | | `yaw` | Horizontal orbit, in radians. | -| `pitch` | Vertical tilt, in radians. | -| `zoom` | Frame scale. | +| `pitch` | Full-turn vertical orbit, in radians. | +| `zoom` | Frame scale, normalized to 0.5...2. | +| `panX` | Session target offset along camera right, in cells; defaults to zero. | +| `panY` | Session target offset along camera up, in cells; defaults to zero. | +| `basis` | Continuous camera right, up and back vectors from normalized full-turn inputs. | +| `projectionScale` | Native 0.68 viewport scale for supplied dimensions and viewport; `fitsVolume` opts into the same complete-cube fit margin as the browser. | +| `fitsVolume` | Session framing flag. Interactive Sculpt cameras opt into the same complete-cube margin as the browser; default utility cameras keep the established 0.68 scale for deterministic example previews. The flag follows the session into CPU/ASCII/GPU rendering and exports and is never stored in a sculpture. | +| `normalized` | A sanitized camera value with periodic angles, bounded zoom and finite bounded pan. | +| `axisRotation` | Session-only normalized `(x, y, z, w)` quaternion composed before the yaw/pitch basis; invalid or zero quaternions become identity. | +| `rotate` | `rotate(axis:radians:)` rotates the camera basis about document X, row-down Y or plane Z. Finite steps compose and normalize; invalid axes and angles leave it unchanged. | +| `orbit` | `orbit(horizontal:vertical:)` applies 0.008 radians per local point without a vertical stop. Invalid inputs leave the camera unchanged. | +| `pan` | `pan(horizontal:vertical:extent:width:height:)` applies screen-space movement using the inverse native projection scale. Invalid inputs leave the camera unchanged. | +| `magnify` | `magnify(_:)` applies a finite positive zoom factor and clamps to 0.5...2. | | `ProjectedGlyph` | One projected cell. | | `brightness` | Projected glyph brightness. | | `SculptureFrame` | PNG-independent view. | @@ -406,7 +417,7 @@ For EXPORT-35, explicit portable scene encoding and decoding SHALL use ThreeMD2 5. The document is 3md. `encode` sets the document version to `1.0`, axis `space`, the sculpture title, and metadata keys `scene-schema`, `width`, and `height` only. `scene-schema` is `ascii-sculpture-1`. Width and height are decimal strings. There is no preamble. Plane `z` values are `0.. component › all deck cards share one width (focused matches the cards behind it) (148ms) + ✓ 1 [chromium] › component.spec.mjs:35:3 › component › upgrades, renders planes, no console errors (149ms) +[WebServer] ::1 - - [10/Oct/2026 12:30:46] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:46] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:46] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:46] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:46] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:46] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:46] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:46] "GET /sample.3md HTTP/1.1" 200 - + ✓ 3 [chromium] › component.spec.mjs:69:3 › component › wide ASCII-art content is not clipped (card widens to fit rigid blocks) (96ms) +[WebServer] ::1 - - [10/Oct/2026 12:30:46] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:46] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:46] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:46] "GET /sample.3md HTTP/1.1" 200 - + ✓ 4 [chromium] › component.spec.mjs:84:3 › component › focused plane is frontmost across the scrubber (691ms) +[WebServer] ::1 - - [10/Oct/2026 12:30:46] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:46] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:46] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:46] "GET /sample.3md HTTP/1.1" 200 - + ✓ 6 [chromium] › component.spec.mjs:109:3 › component › no horizontal overflow from 320px to 1440px (178ms) +[WebServer] ::1 - - [10/Oct/2026 12:30:47] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:47] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:47] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:47] "GET /sample.3md HTTP/1.1" 200 - + ✓ 7 [chromium] › component.spec.mjs:123:3 › component › playback advances and pauses (animations) (2.4s) +[WebServer] ::1 - - [10/Oct/2026 12:30:49] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:49] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:49] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:49] "GET /sample.3md HTTP/1.1" 200 - + ✓ 8 [chromium] › component.spec.mjs:139:3 › component › frame animations render as a flipbook (one frame, no deck) and autoplay (100ms) +[WebServer] ::1 - - [10/Oct/2026 12:30:49] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:49] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:49] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:49] "GET /sample.3md HTTP/1.1" 200 - + ✓ 9 [chromium] › component.spec.mjs:160:3 › component › does not auto-convert characters; an optional legend maps them (94ms) +[WebServer] ::1 - - [10/Oct/2026 12:30:49] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:49] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:49] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:49] "GET /sample.3md HTTP/1.1" 200 - + ✓ 10 [chromium] › component.spec.mjs:184:3 › component › camera: WASD/wheel/orbit move the scene; retired modes alias (91ms) +[WebServer] ::1 - - [10/Oct/2026 12:30:49] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:49] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:49] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:49] "GET /sample.3md HTTP/1.1" 200 - + ✓ 11 [chromium] › component.spec.mjs:210:3 › component › map mode lays planes out by x/y (90ms) +[WebServer] ::1 - - [10/Oct/2026 12:30:49] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:49] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:49] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:49] "GET /sample.3md HTTP/1.1" 200 - + ✓ 12 [chromium] › component.spec.mjs:223:3 › component › renders Markdown tables (not raw pipes) (89ms) +[WebServer] ::1 - - [10/Oct/2026 12:30:49] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:49] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:49] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:49] "GET /sample.3md HTTP/1.1" 200 - + ✓ 13 [chromium] › component.spec.mjs:239:3 › component › layers shows aligned overlays at once, with toggle chips (87ms) +[WebServer] ::1 - - [10/Oct/2026 12:30:50] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:50] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:50] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:50] "GET /sample.3md HTTP/1.1" 200 - + ✓ 14 [chromium] › component.spec.mjs:261:3 › component › blend mode renders content as 3D voxels (86ms) +[WebServer] ::1 - - [10/Oct/2026 12:30:50] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:50] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:50] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:50] "GET /sample.3md HTTP/1.1" 200 - + ✓ 15 [chromium] › component.spec.mjs:281:3 › component › single-card mode shows only the focused plane (225ms) +[WebServer] ::1 - - [10/Oct/2026 12:30:50] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:50] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:50] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:50] "GET /sample.3md HTTP/1.1" 200 - + ✓ 16 [chromium] › component.spec.mjs:303:3 › component › single-card mode scrolls a long plane (reader) (93ms) +[WebServer] ::1 - - [10/Oct/2026 12:30:50] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:50] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:50] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:50] "GET /sample.3md HTTP/1.1" 200 - + ✓ 17 [chromium] › component.spec.mjs:326:3 › component › reflects the resolved mode as data-mode (for fullscreen styling) (90ms) +[WebServer] ::1 - - [10/Oct/2026 12:30:50] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:50] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:50] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:50] "GET /sample.3md HTTP/1.1" 200 - + ✓ 18 [chromium] › component.spec.mjs:343:3 › component › space and PageDown advance like a slideshow (not in reader) (96ms) +[WebServer] ::1 - - [10/Oct/2026 12:30:50] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:50] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:50] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:50] "GET /sample.3md HTTP/1.1" 200 - + ✓ 19 [chromium] › component.spec.mjs:366:3 › component › cross-plane links [[z=N|text]] are clickable and navigate (87ms) +[WebServer] ::1 - - [10/Oct/2026 12:30:50] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:50] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:50] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:50] "GET /sample.3md HTTP/1.1" 200 - + ✓ 20 [chromium] › component.spec.mjs:383:3 › component › a tap (pointer, no drag) on a cross-plane link navigates (88ms) +[WebServer] ::1 - - [10/Oct/2026 12:30:50] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:50] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:50] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:50] "GET /sample.3md HTTP/1.1" 200 - + ✓ 21 [chromium] › component.spec.mjs:402:3 › component › flipbook frames are a fixed size (no resize between frames) (95ms) +[WebServer] ::1 - - [10/Oct/2026 12:30:50] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:50] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:50] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:50] "GET /sample.3md HTTP/1.1" 200 - + ✓ 22 [chromium] › component.spec.mjs:420:3 › component › loop toggle controls whether playback wraps (99ms) +[WebServer] ::1 - - [10/Oct/2026 12:30:51] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:51] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:51] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:51] "GET /sample.3md HTTP/1.1" 200 - + ✓ 23 [chromium] › component.spec.mjs:438:3 › component › emits planechange when stepping (85ms) +[WebServer] ::1 - - [10/Oct/2026 12:30:51] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:51] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:51] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:51] "GET /sample.3md HTTP/1.1" 200 - + ✓ 24 [chromium] › component.spec.mjs:450:3 › component › legend values cannot inject HTML (XSS sink is escaped) (281ms) +[WebServer] ::1 - - [10/Oct/2026 12:30:51] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:51] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:51] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:51] "GET /sample.3md HTTP/1.1" 200 - + ✓ 25 [chromium] › component.spec.mjs:485:3 › component › cross-plane links work for decimal z (not just integers) (87ms) +[WebServer] ::1 - - [10/Oct/2026 12:30:51] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:51] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:51] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:51] "GET /sample.3md HTTP/1.1" 200 - + ✓ 26 [chromium] › component.spec.mjs:503:3 › component › switching into blend after load builds voxels (no empty stage) (268ms) +[WebServer] ::1 - - [10/Oct/2026 12:30:51] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:51] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:51] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:51] "GET /sample.3md HTTP/1.1" 200 - + ✓ 27 [chromium] › component.spec.mjs:518:3 › component › blend voxels are the legend-mapped character glyphs, and billboard faces the camera (85ms) +[WebServer] ::1 - - [10/Oct/2026 12:30:51] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:51] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:51] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:51] "GET /sample.3md HTTP/1.1" 200 - + ✓ 28 [chromium] › component.spec.mjs:537:3 › component › without a legend, blend voxels show the raw characters (87ms) +[WebServer] ::1 - - [10/Oct/2026 12:30:51] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:51] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:51] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:51] "GET /sample.3md HTTP/1.1" 200 - + ✓ 29 [chromium] › component.spec.mjs:549:3 › component › blend is gated to COMPACT art: a sprawling grid is not voxelizable (falls back to deck) (85ms) +[WebServer] ::1 - - [10/Oct/2026 12:30:52] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:52] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:52] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:52] "GET /sample.3md HTTP/1.1" 200 - + ✓ 30 [chromium] › component.spec.mjs:571:3 › component › map and layers keep every tile inside the stage on all edges (many tiles) (93ms) +[WebServer] ::1 - - [10/Oct/2026 12:30:52] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:52] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:52] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:52] "GET /sample.3md HTTP/1.1" 200 - + ✓ 31 [chromium] › component.spec.mjs:598:3 › component › map orbit is clamped so an extreme pose never spills a tile off the stage (87ms) +[WebServer] ::1 - - [10/Oct/2026 12:30:52] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:52] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:52] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:52] "GET /sample.3md HTTP/1.1" 200 - + ✓ 32 [chromium] › component.spec.mjs:623:3 › component › map snaps coordinates to a non-overlapping grid (same x = column, same y = row) (84ms) + ✓ 5 [chromium] › component.spec.mjs:94:3 › component › works with requestAnimationFrame paused (Low Power Mode) (6.1s) +[WebServer] ::1 - - [10/Oct/2026 12:30:52] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:52] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:52] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:52] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:52] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:52] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:52] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:52] "GET /sample.3md HTTP/1.1" 200 - + ✓ 33 [chromium] › component.spec.mjs:652:3 › component › map: no-coordinate planes lay out in a clean non-overlapping grid (98ms) + ✓ 34 [chromium] › component.spec.mjs:672:3 › component › map: the focused card pops to a larger readable size than the board tiles (92ms) +[WebServer] ::1 - - [10/Oct/2026 12:30:52] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:52] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:52] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:52] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:52] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:52] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:52] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:52] "GET /sample.3md HTTP/1.1" 200 - + ✓ 35 [chromium] › component.spec.mjs:689:3 › component › map opens on a full-board overview (nothing forced open) until a tile is opened (95ms) + ✓ 36 [chromium] › component.spec.mjs:711:3 › component › map: partially-positioned planes (only x or only y) do not pile up (92ms) +[WebServer] ::1 - - [10/Oct/2026 12:30:52] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:52] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:52] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:52] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:52] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:52] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:52] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:52] "GET /sample.3md HTTP/1.1" 200 - + ✓ 37 [chromium] › component.spec.mjs:728:3 › component › map: unpositioned planes do not collapse onto explicit (0,0) (102ms) +[WebServer] ::1 - - [10/Oct/2026 12:30:52] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:52] "GET /index.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:52] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:52] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:52] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:53] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 39 [chromium] › lab.spec.mjs:59:3 › lab demo (index.html, backed by ) › renders via the component with no console errors (768ms) +[WebServer] ::1 - - [10/Oct/2026 12:30:53] "GET /index.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:53] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:53] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:53] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:53] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 38 [chromium] › examples-coverage.spec.mjs:8:1 › the component renders every gallery example cleanly (1.9s) +[WebServer] ::1 - - [10/Oct/2026 12:30:54] "GET /index.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:54] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:54] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:54] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:54] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 40 [chromium] › lab.spec.mjs:69:3 › lab demo (index.html, backed by ) › focused plane is frontmost across the scrubber (1.3s) +[WebServer] ::1 - - [10/Oct/2026 12:30:54] "GET /index.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:54] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:54] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:54] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:55] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 42 [chromium] › lab.spec.mjs:92:3 › lab demo (index.html, backed by ) › no horizontal overflow from 320px to 1440px (783ms) +[WebServer] ::1 - - [10/Oct/2026 12:30:55] "GET /index.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:55] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:55] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:55] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:55] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 43 [chromium] › lab.spec.mjs:102:3 › lab demo (index.html, backed by ) › stepping the component highlights the synced source (927ms) +[WebServer] ::1 - - [10/Oct/2026 12:30:56] "GET /index.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:56] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:56] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:56] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:56] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 41 [chromium] › lab.spec.mjs:75:3 › lab demo (index.html, backed by ) › every axis tab loads, scrubs cleanly, and syncs the source panel (5.1s) +[WebServer] ::1 - - [10/Oct/2026 12:30:59] "GET /index.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:59] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:59] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:59] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:30:59] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 44 [chromium] › robustness.spec.mjs:37:3 › robustness (no degradation under heavy use) › no rAF-loop accumulation after switching tabs many times (3.8s) +[WebServer] ::1 - - [10/Oct/2026 12:31:00] "GET /index.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:00] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:00] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:00] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:00] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 46 [chromium] › robustness.spec.mjs:95:3 › robustness (no degradation under heavy use) › rapid play/pause and scrub leave no timers or errors (2.2s) +[WebServer] ::1 - - [10/Oct/2026 12:31:02] "GET /index.html?theme=dark HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:02] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:02] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:02] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:02] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 45 [chromium] › robustness.spec.mjs:65:3 › robustness (no degradation under heavy use) › DOM does not grow and the renderer stays correct after heavy use (3.4s) +[WebServer] ::1 - - [10/Oct/2026 12:31:02] "GET /index.html?theme=dark HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:02] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:02] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:02] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:03] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 47 [chromium] › snapshots.spec.mjs:37:3 › stage snapshot: stack (1.0s) +[WebServer] ::1 - - [10/Oct/2026 12:31:03] "GET /index.html?theme=dark HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:03] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:03] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:03] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:03] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 48 [chromium] › snapshots.spec.mjs:37:3 › stage snapshot: layers (1.1s) +[WebServer] ::1 - - [10/Oct/2026 12:31:04] "GET /index.html?theme=dark HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:04] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:04] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:04] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:04] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 49 [chromium] › snapshots.spec.mjs:37:3 › stage snapshot: scene (1.1s) +[WebServer] ::1 - - [10/Oct/2026 12:31:04] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:04] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:04] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:04] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:04] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:04] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:04] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:04] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:04] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 50 [chromium] › snapshots.spec.mjs:37:3 › stage snapshot: present (1.1s) +[WebServer] ::1 - - [10/Oct/2026 12:31:05] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:05] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:05] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:05] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:05] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 51 [chromium] › viewer.spec.mjs:34:3 › viewer & editor (viewer.html) › opening the page shows lit cubes in the window (637ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:05] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:05] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:05] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:05] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:05] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:05] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:05] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:05] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:05] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:05] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:05] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:05] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:05] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 52 [chromium] › viewer.spec.mjs:78:3 › viewer & editor (viewer.html) › one cell has filled faces from every side, with gold edges and glyph fill (804ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:05] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:05] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:05] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:05] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:05] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 53 [chromium] › viewer.spec.mjs:152:3 › viewer & editor (viewer.html) › clicking a visible cube picks its Z slice and blank stage does not (743ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:06] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:06] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:06] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:06] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:06] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:06] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:06] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:06] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:06] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:06] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:06] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:06] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:06] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 54 [chromium] › viewer.spec.mjs:165:3 › viewer & editor (viewer.html) › renders the starter document with no console errors (618ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:06] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:06] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:06] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:06] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:06] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:06] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:06] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:06] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:06] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 55 [chromium] › viewer.spec.mjs:176:3 › viewer & editor (viewer.html) › editing the source re-renders live (1.0s) +[WebServer] ::1 - - [10/Oct/2026 12:31:07] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:07] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:07] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:07] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:07] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:07] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:07] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:07] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:07] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 56 [chromium] › viewer.spec.mjs:190:3 › viewer & editor (viewer.html) › invalid 3md shows an error without crashing (1.1s) +[WebServer] ::1 - - [10/Oct/2026 12:31:07] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:07] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:07] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:07] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:07] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:07] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:07] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:07] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:07] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 57 [chromium] › viewer.spec.mjs:204:3 › viewer & editor (viewer.html) › loading an example populates the editor and viewer (1.3s) + ✓ 58 [chromium] › viewer.spec.mjs:218:3 › viewer & editor (viewer.html) › editor highlights syntax and numbers every line (703ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:08] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:08] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:08] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:08] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:08] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:08] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:08] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:08] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:08] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:08] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:08] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:08] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:08] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:08] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:08] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:08] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:08] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:08] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 59 [chromium] › viewer.spec.mjs:246:3 › viewer & editor (viewer.html) › Tab indents and Enter continues a list (699ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:09] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:09] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:09] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:09] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:09] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:09] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:09] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:09] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:09] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 60 [chromium] › viewer.spec.mjs:262:3 › viewer & editor (viewer.html) › clicking a plane outline chip focuses that plane (982ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:09] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:09] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:09] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:09] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:09] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:09] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:09] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:09] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:09] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 61 [chromium] › viewer.spec.mjs:273:3 › viewer & editor (viewer.html) › the highlight backdrop scrolls with the textarea (tall document) (750ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:09] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:09] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:09] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:09] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:09] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:10] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:10] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:10] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:10] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 62 [chromium] › viewer.spec.mjs:290:3 › viewer & editor (viewer.html) › smart-key edits are undoable and never corrupt the buffer (792ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:10] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:10] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:10] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:10] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:10] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:10] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:10] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:10] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:10] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 63 [chromium] › viewer.spec.mjs:311:3 › viewer & editor (viewer.html) › validity state is machine-readable via data attributes (967ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:10] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:10] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:10] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:10] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:10] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:10] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:10] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:10] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:10] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 64 [chromium] › viewer.spec.mjs:337:3 › viewer & editor (viewer.html) › Tab does not trap keyboard focus (Esc then Tab leaves the editor) (866ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:11] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:11] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:11] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:11] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:11] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:11] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:11] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:11] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:11] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 65 [chromium] › viewer.spec.mjs:351:3 › viewer & editor (viewer.html) › agent API validates and reports structured state (670ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:11] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:11] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:11] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:11] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:11] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 66 [chromium] › viewer.spec.mjs:364:3 › viewer & editor (viewer.html) › validate(src) is side-effect-free and reports the error code (648ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:11] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:11] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:11] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:11] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:11] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:11] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:11] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:11] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:11] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:11] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:11] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:11] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:11] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 67 [chromium] › viewer.spec.mjs:380:3 › viewer & editor (viewer.html) › repository search opens the 24-generation Conway document (1.1s) +[WebServer] ::1 - - [10/Oct/2026 12:31:12] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:12] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:12] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:12] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:12] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 68 [chromium] › viewer.spec.mjs:395:3 › viewer & editor (viewer.html) › kind 2 canopy opens as text in the element (1.1s) +[WebServer] ::1 - - [10/Oct/2026 12:31:12] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:12] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:12] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:12] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:12] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:12] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:12] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:12] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:12] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:13] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:13] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:13] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:13] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 69 [chromium] › viewer.spec.mjs:412:3 › viewer & editor (viewer.html) › linked village search resolves the folder (1.2s) +[WebServer] ::1 - - [10/Oct/2026 12:31:13] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:13] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:13] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:13] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:13] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:14] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:14] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:14] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:14] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 70 [chromium] › viewer.spec.mjs:426:3 › viewer & editor (viewer.html) › a composition profile shows the root and can switch entries (1.5s) +[WebServer] ::1 - - [10/Oct/2026 12:31:14] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:14] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:14] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:14] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:14] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:14] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:14] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:14] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:14] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 72 [chromium] › viewer.spec.mjs:458:3 › viewer & editor (viewer.html) › desktop layout keeps files beside a panel that switches Edit and Preview (913ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:15] "GET /viewer.html HTTP/1.1" 200 - + ✓ 71 [chromium] › viewer.spec.mjs:441:3 › viewer & editor (viewer.html) › markdown headings become planes and a plane search opens one (1.4s) +[WebServer] ::1 - - [10/Oct/2026 12:31:15] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:15] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:15] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:15] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:15] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:15] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:15] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:15] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:15] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:15] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:15] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:15] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:15] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:15] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:15] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:15] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:15] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 74 [chromium] › viewer.spec.mjs:546:3 › viewer & editor (viewer.html) › orbiting about 1400 gpu cubes stays interactive (787ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:16] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:16] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:16] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:16] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:16] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:16] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:16] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:16] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:16] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 73 [chromium] › viewer.spec.mjs:514:3 › viewer & editor (viewer.html) › cubes tab draws a fenced grid as translucent cubes (1.3s) +[WebServer] ::1 - - [10/Oct/2026 12:31:16] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:16] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:16] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:16] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:16] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:16] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:16] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:16] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:16] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 76 [chromium] › viewer.spec.mjs:627:3 › viewer & editor (viewer.html) › an empty document reads as a neutral prompt, not a red error (995ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:17] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:17] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:17] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:17] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:17] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 75 [chromium] › viewer.spec.mjs:591:3 › viewer & editor (viewer.html) › narrow layout switches Files and the document, and Edit and Preview still switch (1.5s) +[WebServer] ::1 - - [10/Oct/2026 12:31:17] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:17] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:17] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:17] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:17] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:17] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:17] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:17] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:17] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:17] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:17] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:17] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:17] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 77 [chromium] › viewer.spec.mjs:645:3 › viewer & editor (viewer.html) › axis lint warns on a TYPO but not on a valid free-string semantic axis (740ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:18] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:18] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:18] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:18] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:18] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 78 [chromium] › viewer.spec.mjs:671:3 › viewer & editor (viewer.html) › the page has no render-mode switch and does not autoplay (744ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:18] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:18] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:18] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:18] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:18] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:18] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:18] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:18] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:18] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:18] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:18] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:18] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:18] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 79 [chromium] › viewer.spec.mjs:692:3 › viewer & editor (viewer.html) › the agent schema lists error codes and the axis-to-mode map (634ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:18] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:18] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:18] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:18] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:18] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:19] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:19] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:19] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:19] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 80 [chromium] › viewer.spec.mjs:702:3 › viewer & editor (viewer.html) › dangling cross-plane links are flagged as a non-fatal warning (1.0s) +[WebServer] ::1 - - [10/Oct/2026 12:31:19] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:19] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:19] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:19] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:19] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:19] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:19] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:19] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:19] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 81 [chromium] › viewer.spec.mjs:713:3 › viewer & editor (viewer.html) › a corrupt share hash signals a decode error (not a silent starter) (915ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:19] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:19] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:19] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:19] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:19] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 82 [chromium] › viewer.spec.mjs:722:3 › viewer & editor (viewer.html) › the embedded agent schema marks axis optional, only 3md required (713ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:20] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:20] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:20] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:20] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:20] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:20] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:20] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:20] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:20] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:20] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:20] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:20] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:20] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 83 [chromium] › viewer.spec.mjs:729:3 › viewer & editor (viewer.html) › invalid doc clears stale plane/axis data on the badge (979ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:20] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:20] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:20] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:20] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:20] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 84 [chromium] › viewer.spec.mjs:742:3 › viewer & editor (viewer.html) › an invalid document flags the offending line and the badge (1.0s) +[WebServer] ::1 - - [10/Oct/2026 12:31:21] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:21] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:21] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:21] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:21] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:21] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:21] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:21] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:21] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:21] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:21] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:21] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:21] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 85 [chromium] › viewer.spec.mjs:755:3 › viewer & editor (viewer.html) › a shared hash link restores the document (681ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:21] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:21] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:21] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:21] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:21] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:21] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:21] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:21] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:21] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 86 [chromium] › viewer.spec.mjs:766:3 › viewer & editor (viewer.html) › camera buttons and keyboard orbit, zoom, and fit without changing the document (1.0s) +[WebServer] ::1 - - [10/Oct/2026 12:31:22] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:22] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:22] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:22] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:22] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 87 [chromium] › viewer.spec.mjs:795:3 › viewer & editor (viewer.html) › full camera turns cross both poles continuously and retain geometry (774ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:22] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:22] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:22] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:22] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:22] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:22] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:22] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:22] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:22] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:22] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:22] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:22] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:22] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 88 [chromium] › viewer.spec.mjs:843:3 › viewer & editor (viewer.html) › pan tools and modified dragging move only the camera and Fit recenters (835ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:22] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:22] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:22] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:22] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:22] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 89 [chromium] › viewer.spec.mjs:874:3 › viewer & editor (viewer.html) › two fingers pan and pinch and a cancelled gesture cannot select a slice (798ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:23] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:23] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:23] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:23] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:23] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:23] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:23] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:23] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:23] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:23] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:23] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:23] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:23] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 91 [chromium] › viewer.spec.mjs:965:3 › viewer & editor (viewer.html) › phone layout leaves room for cubes and keeps controls outside the drawing (828ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:23] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:23] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:23] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:23] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:23] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:24] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:24] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:24] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:24] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 92 [chromium] › viewer.spec.mjs:987:3 › viewer & editor (viewer.html) › Document disclosure dismisses with Escape and both downloads preserve the document (942ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:24] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:24] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:24] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:24] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:24] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:25] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:25] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:25] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:25] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 93 [chromium] › viewer.spec.mjs:1024:3 › viewer & editor (viewer.html) › a prose document offers Preview without replacing its source (872ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:25] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:25] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:25] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:25] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:25] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:25] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:25] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:25] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:25] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 94 [chromium] › viewer.spec.mjs:1042:3 › viewer & editor (viewer.html) › slice navigation keeps the selected plane in a single scrolling row (737ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:26] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:26] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:26] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:26] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:26] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 90 [chromium] › viewer.spec.mjs:897:3 › viewer & editor (viewer.html) › browser camera projects and picks the shared native parity fixture (3.6s) +[WebServer] ::1 - - [10/Oct/2026 12:31:26] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:26] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:26] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:26] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:26] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:26] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:26] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:26] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:26] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:26] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:26] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:26] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:26] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 96 [chromium] › viewer.spec.mjs:1084:3 › viewer & editor (viewer.html) › GPU unavailability explains how to keep reading in Preview (717ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:27] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:27] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:27] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:27] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:27] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 95 [chromium] › viewer.spec.mjs:1064:3 › viewer & editor (viewer.html) › a GitHub load shows busy state and recovers after a rate limit (858ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:27] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:27] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:27] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:27] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:27] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:27] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:27] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:27] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:27] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:27] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:27] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:27] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:27] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 98 [chromium] › viewer.spec.mjs:1143:3 › viewer & editor (viewer.html) › composition entry switches preserve each draft without copying it into another entry (813ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:28] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:28] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:28] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:28] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:28] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 97 [chromium] › viewer.spec.mjs:1100:3 › viewer & editor (viewer.html) › file switches preserve edited, invalid, and empty drafts with caret and slice (1.2s) +[WebServer] ::1 - - [10/Oct/2026 12:31:28] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:28] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:28] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:28] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:28] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:28] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:28] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:28] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:28] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:28] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:28] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:28] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:28] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 99 [chromium] › viewer.spec.mjs:1170:3 › viewer & editor (viewer.html) › linked entries and file navigation share the same draft (854ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:29] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:29] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:29] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:29] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:29] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:29] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:29] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:29] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:29] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 100 [chromium] › viewer.spec.mjs:1195:3 › viewer & editor (viewer.html) › search and packing use drafts rather than original file text (1.0s) +[WebServer] ::1 - - [10/Oct/2026 12:31:29] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:29] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:29] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:29] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:29] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:29] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:29] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:29] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:29] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 101 [chromium] › viewer.spec.mjs:1212:3 › viewer & editor (viewer.html) › file filtering, keyboard selection, and phone opens reveal the document (912ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:29] "GET /viewer.html?src=original-document.3md&theme=dark HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:29] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:29] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:29] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:29] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:30] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:30] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:30] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:30] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 102 [chromium] › viewer.spec.mjs:1240:3 › viewer & editor (viewer.html) › a failed local open preserves the collection and current draft (1.2s) +[WebServer] ::1 - - [10/Oct/2026 12:31:30] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:30] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:30] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:30] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:30] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:30] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:30] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:30] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:30] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:30] "GET /viewer.html?theme=dark HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:30] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:30] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:30] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:30] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:31] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:31] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:31] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:31] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:31] "GET /viewer.html?theme=dark HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:31] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:31] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:31] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:31] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:31] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:31] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:31] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:31] "GET /gallery-data.json HTTP/1.1" 200 - + ✓ 103 [chromium] › viewer.spec.mjs:1259:3 › viewer & editor (viewer.html) › explicit document navigation removes stale source queries and reloads the chosen source (1.6s) +[WebServer] ::1 - - [10/Oct/2026 12:31:31] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:31] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:31] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:31] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:31] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:31] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:31] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:31] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:31] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 105 [chromium] › viewer.spec.mjs:1316:3 › Sculpt Slice parity › grid edits preserve CRLF, labels, prose and downloads exactly (1.2s) +[WebServer] ::1 - - [10/Oct/2026 12:31:32] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:32] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:32] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:32] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:32] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:32] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:32] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:32] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:32] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 106 [chromium] › viewer.spec.mjs:1328:3 › Sculpt Slice parity › keyboard cells, grid zoom, previous overlay and shared WebGL reference (903ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:33] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:33] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:33] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:33] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:33] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 104 [chromium] › viewer.spec.mjs:1298:3 › Sculpt Slice parity › shared native strokes, clipped brushes, four-neighbor fill and no-op undo (3.1s) +[WebServer] ::1 - - [10/Oct/2026 12:31:33] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:33] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:33] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:33] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:33] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:33] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:33] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:33] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:33] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:34] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:34] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:34] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:34] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 107 [chromium] › viewer.spec.mjs:1341:3 › Sculpt Slice parity › source typing and Slice share undo and retain it across file navigation (963ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:34] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:34] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:34] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:34] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:34] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:34] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:34] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:34] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:34] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 108 [chromium] › viewer.spec.mjs:1353:3 › Sculpt Slice parity › unsupported grids stay readable and budget rejection restores the full stroke (1.8s) + ✓ 109 [chromium] › viewer.spec.mjs:1361:3 › Sculpt Slice parity › phone Slice tools and axis controls stay usable without horizontal page overflow (995ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:35] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:35] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:35] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:35] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:35] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:35] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:35] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:35] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:35] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:35] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:35] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:35] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:35] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:35] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:35] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:35] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:35] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:35] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 110 [chromium] › viewer.spec.mjs:1370:3 › Sculpt Slice parity › 2D editing works with an unavailable WebGL reference (737ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:36] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:36] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:36] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:36] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:36] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 111 [chromium] › viewer.spec.mjs:1375:3 › Sculpt Slice parity › axis inverse, finite inputs, pan steps and Fit leave source and geometry intact (872ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:36] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:36] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:36] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:36] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:36] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:36] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:36] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:36] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:36] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:36] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:36] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:36] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:36] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 113 [chromium] › viewer.spec.mjs:1411:1 › Slice navigation finishes a touch stroke and ignores its late pointer movement (851ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:37] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:37] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:37] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:37] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:37] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:37] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:37] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:37] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:37] "GET /gallery-data.json HTTP/1.1" 200 - + ✓ 114 [chromium] › viewer.spec.mjs:1427:3 › shared cube drawable stays sharp through view/viewport changes at 1x density (2.4s) +[WebServer] ::1 - - [10/Oct/2026 12:31:39] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:39] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:39] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:39] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:39] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:40] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:40] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:40] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:40] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 115 [chromium] › viewer.spec.mjs:1427:3 › shared cube drawable stays sharp through view/viewport changes at 2x density (2.7s) + ✓ 112 [chromium] › viewer.spec.mjs:1389:1 › Slice history drops only old snapshots at the per-draft and collection budgets (6.3s) +(node:76965) Warning: The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set. +(Use `node --trace-warnings ...` to show where the warning was created) +(node:76967) Warning: The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set. +(Use `node --trace-warnings ...` to show where the warning was created) +[WebServer] ::1 - - [10/Oct/2026 12:31:43] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:43] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:43] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:43] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:43] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:43] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:43] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:43] "GET /sample.3md HTTP/1.1" 200 - + ✓ 117 [webkit] › component.spec.mjs:53:3 › component › all deck cards share one width (focused matches the cards behind it) (791ms) + ✓ 116 [webkit] › component.spec.mjs:35:3 › component › upgrades, renders planes, no console errors (811ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:44] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:44] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:44] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:44] "GET /sample.3md HTTP/1.1" 200 - + ✓ 119 [webkit] › component.spec.mjs:84:3 › component › focused plane is frontmost across the scrubber (820ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:44] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:44] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:44] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:44] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:47] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:47] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:47] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:47] "GET /sample.3md HTTP/1.1" 200 - + ✓ 118 [webkit] › component.spec.mjs:69:3 › component › wide ASCII-art content is not clipped (card widens to fit rigid blocks) (3.6s) +[WebServer] ::1 - - [10/Oct/2026 12:31:51] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:51] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:51] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - + ✓ 120 [webkit] › component.spec.mjs:94:3 › component › works with requestAnimationFrame paused (Low Power Mode) (6.3s) +[WebServer] ::1 - - [10/Oct/2026 12:31:51] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:51] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:51] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:51] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:51] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:51] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:51] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:51] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:51] "GET /sample.3md HTTP/1.1" 200 - + ✓ 121 [webkit] › component.spec.mjs:109:3 › component › no horizontal overflow from 320px to 1440px (3.7s) +[WebServer] ::1 - - [10/Oct/2026 12:31:51] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:51] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:51] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:51] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:51] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:51] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:51] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:51] "GET /sample.3md HTTP/1.1" 200 - + ✓ 123 [webkit] › component.spec.mjs:139:3 › component › frame animations render as a flipbook (one frame, no deck) and autoplay (277ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:51] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:51] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:51] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:51] "GET /sample.3md HTTP/1.1" 200 - + ✓ 124 [webkit] › component.spec.mjs:160:3 › component › does not auto-convert characters; an optional legend maps them (271ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:51] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:51] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:51] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:51] "GET /sample.3md HTTP/1.1" 200 - + ✓ 125 [webkit] › component.spec.mjs:184:3 › component › camera: WASD/wheel/orbit move the scene; retired modes alias (277ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:52] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:52] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:52] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:52] "GET /sample.3md HTTP/1.1" 200 - + ✓ 126 [webkit] › component.spec.mjs:210:3 › component › map mode lays planes out by x/y (278ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:52] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:52] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:52] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:52] "GET /sample.3md HTTP/1.1" 200 - + ✓ 127 [webkit] › component.spec.mjs:223:3 › component › renders Markdown tables (not raw pipes) (269ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:52] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:52] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:52] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:52] "GET /sample.3md HTTP/1.1" 200 - + ✓ 128 [webkit] › component.spec.mjs:239:3 › component › layers shows aligned overlays at once, with toggle chips (266ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:53] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:53] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:53] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:53] "GET /sample.3md HTTP/1.1" 200 - + ✓ 129 [webkit] › component.spec.mjs:261:3 › component › blend mode renders content as 3D voxels (273ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:53] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:53] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:53] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:53] "GET /sample.3md HTTP/1.1" 200 - + ✓ 130 [webkit] › component.spec.mjs:281:3 › component › single-card mode shows only the focused plane (385ms) + ✓ 122 [webkit] › component.spec.mjs:123:3 › component › playback advances and pauses (animations) (2.6s) +[WebServer] ::1 - - [10/Oct/2026 12:31:53] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:53] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:53] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:53] "GET /sample.3md HTTP/1.1" 200 - + ✓ 131 [webkit] › component.spec.mjs:303:3 › component › single-card mode scrolls a long plane (reader) (279ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:53] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:53] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:53] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:53] "GET /sample.3md HTTP/1.1" 200 - + ✓ 132 [webkit] › component.spec.mjs:326:3 › component › reflects the resolved mode as data-mode (for fullscreen styling) (272ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:54] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:54] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:54] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:54] "GET /sample.3md HTTP/1.1" 200 - + ✓ 133 [webkit] › component.spec.mjs:343:3 › component › space and PageDown advance like a slideshow (not in reader) (266ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:54] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:54] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:54] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:54] "GET /sample.3md HTTP/1.1" 200 - + ✓ 134 [webkit] › component.spec.mjs:366:3 › component › cross-plane links [[z=N|text]] are clickable and navigate (273ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:54] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:54] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:54] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:54] "GET /sample.3md HTTP/1.1" 200 - + ✓ 136 [webkit] › component.spec.mjs:402:3 › component › flipbook frames are a fixed size (no resize between frames) (271ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:54] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:54] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:54] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:54] "GET /sample.3md HTTP/1.1" 200 - + ✓ 137 [webkit] › component.spec.mjs:420:3 › component › loop toggle controls whether playback wraps (282ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:54] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:54] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:54] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:54] "GET /sample.3md HTTP/1.1" 200 - + ✓ 138 [webkit] › component.spec.mjs:438:3 › component › emits planechange when stepping (259ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:55] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:55] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:55] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:55] "GET /sample.3md HTTP/1.1" 200 - + ✓ 139 [webkit] › component.spec.mjs:450:3 › component › legend values cannot inject HTML (XSS sink is escaped) (445ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:55] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:55] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:55] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:55] "GET /sample.3md HTTP/1.1" 200 - + ✓ 140 [webkit] › component.spec.mjs:485:3 › component › cross-plane links work for decimal z (not just integers) (268ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:55] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:55] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:55] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:55] "GET /sample.3md HTTP/1.1" 200 - + ✓ 141 [webkit] › component.spec.mjs:503:3 › component › switching into blend after load builds voxels (no empty stage) (448ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:56] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:56] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:56] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:56] "GET /sample.3md HTTP/1.1" 200 - + ✓ 142 [webkit] › component.spec.mjs:518:3 › component › blend voxels are the legend-mapped character glyphs, and billboard faces the camera (374ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:56] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:56] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:56] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:56] "GET /sample.3md HTTP/1.1" 200 - + ✓ 143 [webkit] › component.spec.mjs:537:3 › component › without a legend, blend voxels show the raw characters (263ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:57] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:57] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:57] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:57] "GET /sample.3md HTTP/1.1" 200 - + ✓ 144 [webkit] › component.spec.mjs:549:3 › component › blend is gated to COMPACT art: a sprawling grid is not voxelizable (falls back to deck) (267ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:57] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:57] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:57] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:57] "GET /sample.3md HTTP/1.1" 200 - + ✓ 145 [webkit] › component.spec.mjs:571:3 › component › map and layers keep every tile inside the stage on all edges (many tiles) (296ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:57] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:57] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:57] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:57] "GET /sample.3md HTTP/1.1" 200 - + ✓ 135 [webkit] › component.spec.mjs:383:3 › component › a tap (pointer, no drag) on a cross-plane link navigates (3.5s) +[WebServer] ::1 - - [10/Oct/2026 12:31:57] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:57] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:57] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:57] "GET /sample.3md HTTP/1.1" 200 - + ✓ 146 [webkit] › component.spec.mjs:598:3 › component › map orbit is clamped so an extreme pose never spills a tile off the stage (283ms) +[WebServer] ::1 - - [10/Oct/2026 12:31:57] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:57] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:57] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:31:57] "GET /sample.3md HTTP/1.1" 200 - + ✓ 148 [webkit] › component.spec.mjs:652:3 › component › map: no-coordinate planes lay out in a clean non-overlapping grid (267ms) +[WebServer] ::1 - - [10/Oct/2026 12:32:01] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:01] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:01] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:01] "GET /sample.3md HTTP/1.1" 200 - + ✓ 147 [webkit] › component.spec.mjs:623:3 › component › map snaps coordinates to a non-overlapping grid (same x = column, same y = row) (3.6s) +[WebServer] ::1 - - [10/Oct/2026 12:32:01] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:01] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:01] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:01] "GET /sample.3md HTTP/1.1" 200 - + ✓ 149 [webkit] › component.spec.mjs:672:3 › component › map: the focused card pops to a larger readable size than the board tiles (3.5s) +[WebServer] ::1 - - [10/Oct/2026 12:32:04] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:04] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:04] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:04] "GET /sample.3md HTTP/1.1" 200 - + ✓ 150 [webkit] › component.spec.mjs:689:3 › component › map opens on a full-board overview (nothing forced open) until a tile is opened (3.6s) +[WebServer] ::1 - - [10/Oct/2026 12:32:05] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:05] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:05] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:05] "GET /sample.3md HTTP/1.1" 200 - + ✓ 151 [webkit] › component.spec.mjs:711:3 › component › map: partially-positioned planes (only x or only y) do not pile up (3.5s) +[WebServer] ::1 - - [10/Oct/2026 12:32:08] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:08] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:08] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:08] "GET /sample.3md HTTP/1.1" 200 - + ✓ 152 [webkit] › component.spec.mjs:728:3 › component › map: unpositioned planes do not collapse onto explicit (0,0) (3.6s) +[WebServer] ::1 - - [10/Oct/2026 12:32:08] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:08] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:08] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:08] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:08] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 153 [webkit] › examples-coverage.spec.mjs:8:1 › the component renders every gallery example cleanly (6.5s) +[WebServer] ::1 - - [10/Oct/2026 12:32:11] "GET /index.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:11] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:11] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:11] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:11] "GET /index.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:11] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:11] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:11] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:12] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:12] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 154 [webkit] › lab.spec.mjs:59:3 › lab demo (index.html, backed by ) › renders via the component with no console errors (3.9s) +[WebServer] ::1 - - [10/Oct/2026 12:32:12] "GET /index.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:12] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:12] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:12] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:12] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 155 [webkit] › lab.spec.mjs:69:3 › lab demo (index.html, backed by ) › focused plane is frontmost across the scrubber (1.2s) +[WebServer] ::1 - - [10/Oct/2026 12:32:13] "GET /index.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:13] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:13] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:13] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:13] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:13] "GET /index.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:13] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:13] "GET /index.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:13] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:13] "GET /index.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:13] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:13] "GET /index.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:13] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 157 [webkit] › lab.spec.mjs:92:3 › lab demo (index.html, backed by ) › no horizontal overflow from 320px to 1440px (864ms) +[WebServer] ::1 - - [10/Oct/2026 12:32:13] "GET /index.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:13] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:13] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:13] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:14] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 158 [webkit] › lab.spec.mjs:102:3 › lab demo (index.html, backed by ) › stepping the component highlights the synced source (984ms) +[WebServer] ::1 - - [10/Oct/2026 12:32:14] "GET /index.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:14] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:14] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:14] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:15] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 156 [webkit] › lab.spec.mjs:75:3 › lab demo (index.html, backed by ) › every axis tab loads, scrubs cleanly, and syncs the source panel (4.7s) +[WebServer] ::1 - - [10/Oct/2026 12:32:17] "GET /index.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:17] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:17] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:17] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:17] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 159 [webkit] › robustness.spec.mjs:37:3 › robustness (no degradation under heavy use) › no rAF-loop accumulation after switching tabs many times (4.3s) +[WebServer] ::1 - - [10/Oct/2026 12:32:19] "GET /index.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:19] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:19] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:19] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:19] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 160 [webkit] › robustness.spec.mjs:65:3 › robustness (no degradation under heavy use) › DOM does not grow and the renderer stays correct after heavy use (3.9s) + ✓ 161 [webkit] › robustness.spec.mjs:95:3 › robustness (no degradation under heavy use) › rapid play/pause and scrub leave no timers or errors (2.2s) +[WebServer] ::1 - - [10/Oct/2026 12:32:21] "GET /index.html?theme=dark HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:21] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:21] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:21] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:21] "GET /index.html?theme=dark HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:21] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:21] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:21] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:21] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:21] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 162 [webkit] › snapshots.spec.mjs:37:3 › stage snapshot: stack (1.1s) + ✓ 163 [webkit] › snapshots.spec.mjs:37:3 › stage snapshot: layers (1.1s) +[WebServer] ::1 - - [10/Oct/2026 12:32:22] "GET /index.html?theme=dark HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:22] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:22] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:22] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:22] "GET /index.html?theme=dark HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:22] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:22] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:22] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:22] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:22] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 164 [webkit] › snapshots.spec.mjs:37:3 › stage snapshot: scene (1.0s) + ✓ 165 [webkit] › snapshots.spec.mjs:37:3 › stage snapshot: present (1.0s) +[WebServer] ::1 - - [10/Oct/2026 12:32:23] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:23] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:23] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:23] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:23] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:23] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:23] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:23] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:23] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:23] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:23] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:23] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:23] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:23] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:23] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:23] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:23] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:23] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 166 [webkit] › viewer.spec.mjs:34:3 › viewer & editor (viewer.html) › opening the page shows lit cubes in the window (588ms) +[WebServer] ::1 - - [10/Oct/2026 12:32:23] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:23] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:23] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:23] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:23] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:23] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:23] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:23] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:23] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 167 [webkit] › viewer.spec.mjs:78:3 › viewer & editor (viewer.html) › one cell has filled faces from every side, with gold edges and glyph fill (806ms) + ✓ 168 [webkit] › viewer.spec.mjs:152:3 › viewer & editor (viewer.html) › clicking a visible cube picks its Z slice and blank stage does not (646ms) +[WebServer] ::1 - - [10/Oct/2026 12:32:24] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:24] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:24] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:24] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:24] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:24] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:24] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:24] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:24] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:24] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:24] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:24] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:24] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:24] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:24] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:24] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:24] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:24] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 169 [webkit] › viewer.spec.mjs:165:3 › viewer & editor (viewer.html) › renders the starter document with no console errors (583ms) +[WebServer] ::1 - - [10/Oct/2026 12:32:24] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:24] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:24] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:24] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:24] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:24] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:24] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:24] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:24] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 170 [webkit] › viewer.spec.mjs:176:3 › viewer & editor (viewer.html) › editing the source re-renders live (981ms) +[WebServer] ::1 - - [10/Oct/2026 12:32:25] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:25] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:25] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:25] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:25] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:25] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:25] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:25] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:25] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 171 [webkit] › viewer.spec.mjs:190:3 › viewer & editor (viewer.html) › invalid 3md shows an error without crashing (1.0s) +[WebServer] ::1 - - [10/Oct/2026 12:32:25] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:25] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:25] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:25] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:25] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:26] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:26] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:26] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:26] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 172 [webkit] › viewer.spec.mjs:204:3 › viewer & editor (viewer.html) › loading an example populates the editor and viewer (1.1s) + ✓ 173 [webkit] › viewer.spec.mjs:218:3 › viewer & editor (viewer.html) › editor highlights syntax and numbers every line (703ms) +[WebServer] ::1 - - [10/Oct/2026 12:32:26] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:26] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:26] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:26] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:26] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:26] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:26] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:26] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:26] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:26] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:26] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:26] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:26] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:26] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:26] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:26] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:26] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:26] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 174 [webkit] › viewer.spec.mjs:246:3 › viewer & editor (viewer.html) › Tab indents and Enter continues a list (671ms) +[WebServer] ::1 - - [10/Oct/2026 12:32:27] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:27] "GET /assets/tokens.css HTTP/1.1" 200 - + ✓ 175 [webkit] › viewer.spec.mjs:262:3 › viewer & editor (viewer.html) › clicking a plane outline chip focuses that plane (866ms) +[WebServer] ::1 - - [10/Oct/2026 12:32:27] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:27] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:27] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:27] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:27] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:27] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:27] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:27] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:27] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:27] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:27] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:27] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:27] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:27] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:27] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:27] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 176 [webkit] › viewer.spec.mjs:273:3 › viewer & editor (viewer.html) › the highlight backdrop scrolls with the textarea (tall document) (670ms) +[WebServer] ::1 - - [10/Oct/2026 12:32:28] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:28] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:28] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:28] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:28] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:28] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:28] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:28] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:28] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 177 [webkit] › viewer.spec.mjs:290:3 › viewer & editor (viewer.html) › smart-key edits are undoable and never corrupt the buffer (845ms) +[WebServer] ::1 - - [10/Oct/2026 12:32:28] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:28] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:28] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:28] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:28] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:28] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:28] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:28] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:28] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 178 [webkit] › viewer.spec.mjs:311:3 › viewer & editor (viewer.html) › validity state is machine-readable via data attributes (898ms) + ✓ 179 [webkit] › viewer.spec.mjs:337:3 › viewer & editor (viewer.html) › Tab does not trap keyboard focus (Esc then Tab leaves the editor) (644ms) +[WebServer] ::1 - - [10/Oct/2026 12:32:28] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:28] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:28] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:28] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:28] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:28] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:28] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:28] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:28] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:29] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:29] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:29] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:29] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:29] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:29] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:29] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:29] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:29] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 180 [webkit] › viewer.spec.mjs:351:3 › viewer & editor (viewer.html) › agent API validates and reports structured state (612ms) + ✓ 181 [webkit] › viewer.spec.mjs:364:3 › viewer & editor (viewer.html) › validate(src) is side-effect-free and reports the error code (626ms) +[WebServer] ::1 - - [10/Oct/2026 12:32:29] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:29] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:29] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:29] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:29] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:29] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:29] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:29] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:29] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:29] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:29] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:29] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:29] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:29] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:29] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:29] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:29] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:29] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 182 [webkit] › viewer.spec.mjs:380:3 › viewer & editor (viewer.html) › repository search opens the 24-generation Conway document (1.0s) +[WebServer] ::1 - - [10/Oct/2026 12:32:30] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:30] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:30] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:30] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:30] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 183 [webkit] › viewer.spec.mjs:395:3 › viewer & editor (viewer.html) › kind 2 canopy opens as text in the element (1.1s) +[WebServer] ::1 - - [10/Oct/2026 12:32:30] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:30] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:30] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:30] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:30] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:30] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:30] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:30] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:30] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:30] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:30] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:30] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:30] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 184 [webkit] › viewer.spec.mjs:412:3 › viewer & editor (viewer.html) › linked village search resolves the folder (1.0s) +[WebServer] ::1 - - [10/Oct/2026 12:32:31] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:31] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:31] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:31] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:31] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:31] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:31] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:31] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:31] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 185 [webkit] › viewer.spec.mjs:426:3 › viewer & editor (viewer.html) › a composition profile shows the root and can switch entries (1.3s) +[WebServer] ::1 - - [10/Oct/2026 12:32:32] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:32] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:32] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:32] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:32] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:32] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:32] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:32] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:32] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 186 [webkit] › viewer.spec.mjs:441:3 › viewer & editor (viewer.html) › markdown headings become planes and a plane search opens one (1.4s) + ✓ 187 [webkit] › viewer.spec.mjs:458:3 › viewer & editor (viewer.html) › desktop layout keeps files beside a panel that switches Edit and Preview (1.0s) +[WebServer] ::1 - - [10/Oct/2026 12:32:33] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:33] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:33] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:33] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:33] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:33] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:33] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:33] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:33] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:33] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:33] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:33] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:33] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:33] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:33] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:33] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:33] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:33] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 189 [webkit] › viewer.spec.mjs:546:3 › viewer & editor (viewer.html) › orbiting about 1400 gpu cubes stays interactive (625ms) +[WebServer] ::1 - - [10/Oct/2026 12:32:33] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:33] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:33] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:33] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:33] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:33] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:33] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:33] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:33] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 188 [webkit] › viewer.spec.mjs:514:3 › viewer & editor (viewer.html) › cubes tab draws a fenced grid as translucent cubes (1.2s) +[WebServer] ::1 - - [10/Oct/2026 12:32:34] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:34] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:34] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:34] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:34] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:34] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:34] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:34] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:34] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 190 [webkit] › viewer.spec.mjs:591:3 › viewer & editor (viewer.html) › narrow layout switches Files and the document, and Edit and Preview still switch (863ms) +[WebServer] ::1 - - [10/Oct/2026 12:32:34] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:34] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:34] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:34] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:34] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:34] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:34] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:34] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:34] "GET /gallery-data.json HTTP/1.1" 200 - + ✓ 191 [webkit] › viewer.spec.mjs:627:3 › viewer & editor (viewer.html) › an empty document reads as a neutral prompt, not a red error (844ms) + ✓ 192 [webkit] › viewer.spec.mjs:645:3 › viewer & editor (viewer.html) › axis lint warns on a TYPO but not on a valid free-string semantic axis (495ms) +[WebServer] ::1 - - [10/Oct/2026 12:32:35] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:35] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:35] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:35] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:35] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:35] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:35] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:35] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:35] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:35] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:35] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:35] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:35] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:35] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:35] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:35] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:35] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:35] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 193 [webkit] › viewer.spec.mjs:671:3 › viewer & editor (viewer.html) › the page has no render-mode switch and does not autoplay (489ms) + ✓ 194 [webkit] › viewer.spec.mjs:692:3 › viewer & editor (viewer.html) › the agent schema lists error codes and the axis-to-mode map (468ms) +[WebServer] ::1 - - [10/Oct/2026 12:32:35] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:35] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:35] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:35] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:35] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:35] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:35] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:35] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:35] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:35] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:35] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:35] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:35] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:35] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:35] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:35] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:35] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:35] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 196 [webkit] › viewer.spec.mjs:713:3 › viewer & editor (viewer.html) › a corrupt share hash signals a decode error (not a silent starter) (816ms) + ✓ 195 [webkit] › viewer.spec.mjs:702:3 › viewer & editor (viewer.html) › dangling cross-plane links are flagged as a non-fatal warning (901ms) +[WebServer] ::1 - - [10/Oct/2026 12:32:36] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:36] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:36] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:36] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:36] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:36] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:36] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:36] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:36] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:36] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:36] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:36] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:36] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:36] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:36] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:36] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:36] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:36] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 197 [webkit] › viewer.spec.mjs:722:3 › viewer & editor (viewer.html) › the embedded agent schema marks axis optional, only 3md required (466ms) +[WebServer] ::1 - - [10/Oct/2026 12:32:36] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:36] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:36] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:36] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:36] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:36] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:36] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:36] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:36] "GET /gallery-data.json HTTP/1.1" 200 - + ✓ 198 [webkit] › viewer.spec.mjs:729:3 › viewer & editor (viewer.html) › invalid doc clears stale plane/axis data on the badge (1.1s) +[WebServer] ::1 - - [10/Oct/2026 12:32:37] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:37] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:37] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:37] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:37] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:37] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:37] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:37] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:37] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 199 [webkit] › viewer.spec.mjs:742:3 › viewer & editor (viewer.html) › an invalid document flags the offending line and the badge (997ms) + ✓ 200 [webkit] › viewer.spec.mjs:755:3 › viewer & editor (viewer.html) › a shared hash link restores the document (520ms) +[WebServer] ::1 - - [10/Oct/2026 12:32:37] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:37] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:37] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:37] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:37] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:37] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:37] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:37] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:37] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:38] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:38] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:38] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:38] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:38] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:38] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:38] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:38] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:38] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 201 [webkit] › viewer.spec.mjs:766:3 › viewer & editor (viewer.html) › camera buttons and keyboard orbit, zoom, and fit without changing the document (674ms) +[WebServer] ::1 - - [10/Oct/2026 12:32:38] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:38] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:38] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:38] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:38] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 202 [webkit] › viewer.spec.mjs:795:3 › viewer & editor (viewer.html) › full camera turns cross both poles continuously and retain geometry (718ms) +[WebServer] ::1 - - [10/Oct/2026 12:32:38] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:38] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:38] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:38] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:38] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:38] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:38] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:38] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:38] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:38] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:38] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:38] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:38] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 203 [webkit] › viewer.spec.mjs:843:3 › viewer & editor (viewer.html) › pan tools and modified dragging move only the camera and Fit recenters (774ms) + ✓ 204 [webkit] › viewer.spec.mjs:874:3 › viewer & editor (viewer.html) › two fingers pan and pinch and a cancelled gesture cannot select a slice (585ms) +[WebServer] ::1 - - [10/Oct/2026 12:32:39] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:39] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:39] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:39] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:39] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:39] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:39] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:39] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:39] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:39] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:39] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:39] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:39] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:39] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:39] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:39] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:39] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:39] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 206 [webkit] › viewer.spec.mjs:965:3 › viewer & editor (viewer.html) › phone layout leaves room for cubes and keeps controls outside the drawing (628ms) +[WebServer] ::1 - - [10/Oct/2026 12:32:40] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:40] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:40] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:40] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:40] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:40] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:40] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:40] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:40] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 207 [webkit] › viewer.spec.mjs:987:3 › viewer & editor (viewer.html) › Document disclosure dismisses with Escape and both downloads preserve the document (839ms) +[WebServer] ::1 - - [10/Oct/2026 12:32:40] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:40] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:40] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:40] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:40] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:40] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:40] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:40] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:40] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 208 [webkit] › viewer.spec.mjs:1024:3 › viewer & editor (viewer.html) › a prose document offers Preview without replacing its source (664ms) +[WebServer] ::1 - - [10/Oct/2026 12:32:41] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:41] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:41] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:41] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:41] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:41] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:41] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:41] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:41] "GET /gallery-data.json HTTP/1.1" 200 - + ✓ 209 [webkit] › viewer.spec.mjs:1042:3 › viewer & editor (viewer.html) › slice navigation keeps the selected plane in a single scrolling row (652ms) +[WebServer] ::1 - - [10/Oct/2026 12:32:42] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:42] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:42] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:42] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:42] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:42] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:42] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:42] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:42] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 210 [webkit] › viewer.spec.mjs:1064:3 › viewer & editor (viewer.html) › a GitHub load shows busy state and recovers after a rate limit (788ms) + ✓ 205 [webkit] › viewer.spec.mjs:897:3 › viewer & editor (viewer.html) › browser camera projects and picks the shared native parity fixture (3.9s) +[WebServer] ::1 - - [10/Oct/2026 12:32:42] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:43] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:43] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:43] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:43] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:43] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:43] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:43] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:43] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:43] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:43] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:43] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:43] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:43] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:43] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:43] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:43] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:43] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 211 [webkit] › viewer.spec.mjs:1084:3 › viewer & editor (viewer.html) › GPU unavailability explains how to keep reading in Preview (590ms) +[WebServer] ::1 - - [10/Oct/2026 12:32:43] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:43] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:43] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:43] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:43] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:43] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:43] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:43] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:43] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 213 [webkit] › viewer.spec.mjs:1143:3 › viewer & editor (viewer.html) › composition entry switches preserve each draft without copying it into another entry (748ms) + ✓ 212 [webkit] › viewer.spec.mjs:1100:3 › viewer & editor (viewer.html) › file switches preserve edited, invalid, and empty drafts with caret and slice (1.1s) +[WebServer] ::1 - - [10/Oct/2026 12:32:44] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:44] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:44] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:44] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:44] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:44] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:44] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:44] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:44] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:44] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:44] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:44] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:44] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:44] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:44] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:44] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:44] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:44] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 214 [webkit] › viewer.spec.mjs:1170:3 › viewer & editor (viewer.html) › linked entries and file navigation share the same draft (823ms) + ✓ 215 [webkit] › viewer.spec.mjs:1195:3 › viewer & editor (viewer.html) › search and packing use drafts rather than original file text (821ms) +[WebServer] ::1 - - [10/Oct/2026 12:32:45] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:45] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:45] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:45] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:45] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:45] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:45] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:45] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:45] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:45] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:45] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:45] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:45] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:45] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:45] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:45] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:45] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:45] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 216 [webkit] › viewer.spec.mjs:1212:3 › viewer & editor (viewer.html) › file filtering, keyboard selection, and phone opens reveal the document (775ms) +[WebServer] ::1 - - [10/Oct/2026 12:32:45] "GET /viewer.html?src=original-document.3md&theme=dark HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:45] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:45] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:45] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:45] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:45] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:45] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:45] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:45] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 217 [webkit] › viewer.spec.mjs:1240:3 › viewer & editor (viewer.html) › a failed local open preserves the collection and current draft (1.1s) +[WebServer] ::1 - - [10/Oct/2026 12:32:46] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:46] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:46] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:46] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:46] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:46] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:46] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:46] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:46] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:46] "GET /viewer.html?theme=dark HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:46] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:46] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:46] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:46] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:46] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:46] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:46] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:46] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:46] "GET /viewer.html?theme=dark HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:46] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:46] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:46] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:46] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:46] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:46] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:46] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:46] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:46] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:46] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:46] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:46] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:46] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 218 [webkit] › viewer.spec.mjs:1259:3 › viewer & editor (viewer.html) › explicit document navigation removes stale source queries and reloads the chosen source (1.1s) +[WebServer] ::1 - - [10/Oct/2026 12:32:46] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:47] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:47] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:47] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:47] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:47] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:47] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:47] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:47] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:47] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:47] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:47] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:47] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:47] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:47] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:47] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:47] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:47] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:47] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:47] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:47] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:47] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:47] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:47] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 220 [webkit] › viewer.spec.mjs:1316:3 › Sculpt Slice parity › grid edits preserve CRLF, labels, prose and downloads exactly (770ms) +[WebServer] ::1 - - [10/Oct/2026 12:32:47] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:47] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:47] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:47] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:47] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:47] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:47] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:47] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:47] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:47] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:47] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:47] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:47] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:47] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:47] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:47] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:47] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:47] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:47] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:48] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:48] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:48] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:48] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:48] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 219 [webkit] › viewer.spec.mjs:1298:3 › Sculpt Slice parity › shared native strokes, clipped brushes, four-neighbor fill and no-op undo (2.2s) + ✓ 221 [webkit] › viewer.spec.mjs:1328:3 › Sculpt Slice parity › keyboard cells, grid zoom, previous overlay and shared WebGL reference (758ms) +[WebServer] ::1 - - [10/Oct/2026 12:32:48] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:48] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:48] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:48] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:48] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:48] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:48] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:48] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:48] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:48] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:48] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:48] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:48] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:48] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:48] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:48] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:48] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:48] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 222 [webkit] › viewer.spec.mjs:1341:3 › Sculpt Slice parity › source typing and Slice share undo and retain it across file navigation (837ms) + ✓ 223 [webkit] › viewer.spec.mjs:1353:3 › Sculpt Slice parity › unsupported grids stay readable and budget rejection restores the full stroke (778ms) +[WebServer] ::1 - - [10/Oct/2026 12:32:49] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:49] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:49] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:49] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:49] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:49] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:49] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:49] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:49] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:49] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:49] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:49] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:49] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:49] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:49] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:49] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:49] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:49] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 225 [webkit] › viewer.spec.mjs:1370:3 › Sculpt Slice parity › 2D editing works with an unavailable WebGL reference (671ms) + ✓ 224 [webkit] › viewer.spec.mjs:1361:3 › Sculpt Slice parity › phone Slice tools and axis controls stay usable without horizontal page overflow (970ms) +[WebServer] ::1 - - [10/Oct/2026 12:32:50] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:50] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:50] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:50] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:50] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:50] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:50] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:50] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:50] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:50] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:50] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:50] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:50] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:50] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:50] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:50] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:50] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:50] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 226 [webkit] › viewer.spec.mjs:1375:3 › Sculpt Slice parity › axis inverse, finite inputs, pan steps and Fit leave source and geometry intact (912ms) +[WebServer] ::1 - - [10/Oct/2026 12:32:50] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:50] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:50] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:50] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:50] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:50] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:50] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:50] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:50] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 228 [webkit] › viewer.spec.mjs:1411:1 › Slice navigation finishes a touch stroke and ignores its late pointer movement (816ms) +[WebServer] ::1 - - [10/Oct/2026 12:32:51] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:51] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:51] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:51] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:51] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:51] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:51] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:51] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:51] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 229 [webkit] › viewer.spec.mjs:1427:3 › shared cube drawable stays sharp through view/viewport changes at 1x density (1.9s) +[WebServer] ::1 - - [10/Oct/2026 12:32:53] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:53] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:53] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:53] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:53] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:53] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:53] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:53] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:32:53] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 230 [webkit] › viewer.spec.mjs:1427:3 › shared cube drawable stays sharp through view/viewport changes at 2x density (1.8s) + ✓ 227 [webkit] › viewer.spec.mjs:1389:1 › Slice history drops only old snapshots at the per-draft and collection budgets (6.5s) + + 230 passed (2.2m) diff --git a/docs/evidence/viewer-resolution/density-final.log b/docs/evidence/viewer-resolution/density-final.log new file mode 100644 index 00000000..f8b324a7 --- /dev/null +++ b/docs/evidence/viewer-resolution/density-final.log @@ -0,0 +1,53 @@ + +Running 4 tests using 2 workers + +(node:78296) Warning: The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set. +(Use `node --trace-warnings ...` to show where the warning was created) +(node:78295) Warning: The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set. +(Use `node --trace-warnings ...` to show where the warning was created) +[WebServer] ::1 - - [10/Oct/2026 12:37:32] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:37:32] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:37:32] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:37:32] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:37:32] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:37:32] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:37:32] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:37:32] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:37:32] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:37:32] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:37:32] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:37:32] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:37:32] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:37:32] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:37:32] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:37:32] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:37:32] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:37:32] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 1 [chromium] › viewer.spec.mjs:1427:3 › shared cube drawable stays sharp through view/viewport changes at 1x density (2.6s) + ✓ 2 [chromium] › viewer.spec.mjs:1427:3 › shared cube drawable stays sharp through view/viewport changes at 2x density (2.7s) +(node:78314) Warning: The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set. +(Use `node --trace-warnings ...` to show where the warning was created) +(node:78315) Warning: The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set. +(Use `node --trace-warnings ...` to show where the warning was created) +[WebServer] ::1 - - [10/Oct/2026 12:37:35] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:37:35] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:37:35] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:37:35] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:37:35] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:37:35] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:37:35] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:37:35] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:37:35] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:37:35] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:37:35] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:37:35] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:37:35] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:37:35] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:37:35] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:37:35] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:37:35] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:37:35] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 4 [webkit] › viewer.spec.mjs:1427:3 › shared cube drawable stays sharp through view/viewport changes at 2x density (2.0s) + ✓ 3 [webkit] › viewer.spec.mjs:1427:3 › shared cube drawable stays sharp through view/viewport changes at 1x density (2.3s) + + 4 passed (6.3s) diff --git a/docs/evidence/viewer-resolution/strict-implementation.json b/docs/evidence/viewer-resolution/strict-implementation.json new file mode 100644 index 00000000..17523388 --- /dev/null +++ b/docs/evidence/viewer-resolution/strict-implementation.json @@ -0,0 +1,11 @@ +{ + "errors": [], + "manifest_notices": [], + "notices": [], + "passed": true, + "skipped_links": [], + "specs_checked": 4, + "stale": [], + "suppressed_warnings": [], + "warnings": [] +} diff --git a/docs/evidence/viewer-resolution/trust-implementation.log b/docs/evidence/viewer-resolution/trust-implementation.log new file mode 100644 index 00000000..08a1cb47 --- /dev/null +++ b/docs/evidence/viewer-resolution/trust-implementation.log @@ -0,0 +1,1489 @@ +▶️ Lane: verify — Three language suites, nine-pair public-package interchange, generated bundle drift and editor grammar. Trust runs SpecSync after this lane. + ▶️ Running task: lint + ✔ Step 1 done (597ms) + ▶️ Running task: build +Building for debugging... +[0/5] Write swift-version--58304C5D6DBC2206.txt +Build complete! (0.13s) + ✔ Step 2 done (641ms) + ▶️ Running task: test +[0/1] Planning build +Building for debugging... +[0/6] Write swift-version--58304C5D6DBC2206.txt +Build complete! (0.20s) +Test Suite 'All tests' started at 2026-10-10 12:40:49.862. +Test Suite '3mdPackageTests.xctest' started at 2026-10-10 12:40:49.863. +Test Suite 'CompositionEditingTests' started at 2026-10-10 12:40:49.863. +Test Case '-[ThreeMDTests.CompositionEditingTests testCancelledGraphTransactionPropagatesCancellation]' started. +Test Case '-[ThreeMDTests.CompositionEditingTests testCancelledGraphTransactionPropagatesCancellation]' passed (0.005 seconds). +Test Case '-[ThreeMDTests.CompositionEditingTests testEntryReplacementKeepsIDAndCanEditSharedDefinitionWithoutFlattening]' started. +Test Case '-[ThreeMDTests.CompositionEditingTests testEntryReplacementKeepsIDAndCanEditSharedDefinitionWithoutFlattening]' passed (0.004 seconds). +Test Case '-[ThreeMDTests.CompositionEditingTests testFinalGraphValidationAllowsForwardReferenceInsertionAndRootReplacement]' started. +Test Case '-[ThreeMDTests.CompositionEditingTests testFinalGraphValidationAllowsForwardReferenceInsertionAndRootReplacement]' passed (0.003 seconds). +Test Case '-[ThreeMDTests.CompositionEditingTests testGraphRevisionIncludesReferenceOrderAttributesAndRootAndSurvivesReopen]' started. +Test Case '-[ThreeMDTests.CompositionEditingTests testGraphRevisionIncludesReferenceOrderAttributesAndRootAndSurvivesReopen]' passed (0.008 seconds). +Test Case '-[ThreeMDTests.CompositionEditingTests testGraphSnapshotsAndPatchesAreCodableAndDecodedGraphsStillValidate]' started. +Test Case '-[ThreeMDTests.CompositionEditingTests testGraphSnapshotsAndPatchesAreCodableAndDecodedGraphsStillValidate]' passed (0.004 seconds). +Test Case '-[ThreeMDTests.CompositionEditingTests testGraphTransactionBoundsOperationsPayloadAndDefinitions]' started. +Test Case '-[ThreeMDTests.CompositionEditingTests testGraphTransactionBoundsOperationsPayloadAndDefinitions]' passed (0.002 seconds). +Test Case '-[ThreeMDTests.CompositionEditingTests testMissingTargetAndCycleFailuresHaveGraphPathsWithoutPartialPublication]' started. +Test Case '-[ThreeMDTests.CompositionEditingTests testMissingTargetAndCycleFailuresHaveGraphPathsWithoutPartialPublication]' passed (0.003 seconds). +Test Case '-[ThreeMDTests.CompositionEditingTests testReferenceIdentityCannotChangeOrBeDuplicatedWithinOwner]' started. +Test Case '-[ThreeMDTests.CompositionEditingTests testReferenceIdentityCannotChangeOrBeDuplicatedWithinOwner]' passed (0.004 seconds). +Test Case '-[ThreeMDTests.CompositionEditingTests testReferenceRetargetMoveAndRemoveKeepInstanceIdentityAndOpaqueAttributes]' started. +Test Case '-[ThreeMDTests.CompositionEditingTests testReferenceRetargetMoveAndRemoveKeepInstanceIdentityAndOpaqueAttributes]' passed (0.002 seconds). +Test Case '-[ThreeMDTests.CompositionEditingTests testRemovingAndRewritingReferencesValidatesOnlyCompleteFinalGraph]' started. +Test Case '-[ThreeMDTests.CompositionEditingTests testRemovingAndRewritingReferencesValidatesOnlyCompleteFinalGraph]' passed (0.002 seconds). +Test Suite 'CompositionEditingTests' passed at 2026-10-10 12:40:49.899. + Executed 10 tests, with 0 failures (0 unexpected) in 0.035 (0.037) seconds +Test Suite 'ConformanceTests' started at 2026-10-10 12:40:49.899. +Test Case '-[ThreeMDTests.ConformanceTests testConformanceVectors]' started. +Test Case '-[ThreeMDTests.ConformanceTests testConformanceVectors]' passed (0.010 seconds). +Test Suite 'ConformanceTests' passed at 2026-10-10 12:40:49.909. + Executed 1 test, with 0 failures (0 unexpected) in 0.010 (0.010) seconds +Test Suite 'CrossPlaneLinkHTMLTests' started at 2026-10-10 12:40:49.909. +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testAnchorHrefMatchesSectionId]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testAnchorHrefMatchesSectionId]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testCrossPlaneAnchorDecimalTarget]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testCrossPlaneAnchorDecimalTarget]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testCrossPlaneAnchorDefaultTextIsEscaped]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testCrossPlaneAnchorDefaultTextIsEscaped]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testCrossPlaneAnchorEmptyText]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testCrossPlaneAnchorEmptyText]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testCrossPlaneAnchorNegativeTarget]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testCrossPlaneAnchorNegativeTarget]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testCrossPlaneAnchorNoText]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testCrossPlaneAnchorNoText]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testCrossPlaneAnchorScientificNotation]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testCrossPlaneAnchorScientificNotation]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testCrossPlaneAnchorTextIsEscaped]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testCrossPlaneAnchorTextIsEscaped]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testCrossPlaneAnchorWithText]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testCrossPlaneAnchorWithText]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testHexTargetNotRenderedAsAnchor]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testHexTargetNotRenderedAsAnchor]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testInfTargetNotRenderedAsAnchor]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testInfTargetNotRenderedAsAnchor]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testInvalidTargetNotRenderedAsAnchor]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testInvalidTargetNotRenderedAsAnchor]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testPublicAnchorHelpersMatchRendererIds]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testPublicAnchorHelpersMatchRendererIds]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testSectionHasIdAttribute]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testSectionHasIdAttribute]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testSectionIdForDecimalZ]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testSectionIdForDecimalZ]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testSectionIdForNegativeZ]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testSectionIdForNegativeZ]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testSectionIdPrecedesDataZ]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testSectionIdPrecedesDataZ]' passed (0.000 seconds). +Test Suite 'CrossPlaneLinkHTMLTests' passed at 2026-10-10 12:40:49.913. + Executed 17 tests, with 0 failures (0 unexpected) in 0.003 (0.004) seconds +Test Suite 'CrossPlaneLinkTests' started at 2026-10-10 12:40:49.913. +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testBasicLinkNoText]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testBasicLinkNoText]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testDanglingLinksFiltersOnlyMissingTargets]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testDanglingLinksFiltersOnlyMissingTargets]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testDanglingLinkTargetExistsFalse]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testDanglingLinkTargetExistsFalse]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testDecimalTarget]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testDecimalTarget]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testDocumentWithNoLinksReturnsEmpty]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testDocumentWithNoLinksReturnsEmpty]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testHexTargetIgnored]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testHexTargetIgnored]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testLinkGraphCollapsesRepeatedEdgesInEncounterOrder]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testLinkGraphCollapsesRepeatedEdgesInEncounterOrder]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testLinkGraphKeepsDanglingEdgeStatus]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testLinkGraphKeepsDanglingEdgeStatus]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testLinksAcrossMultiplePlanesInSourceOrder]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testLinksAcrossMultiplePlanesInSourceOrder]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testLinkWithEmptyText]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testLinkWithEmptyText]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testLinkWithText]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testLinkWithText]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testMultipleLinksLeftToRight]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testMultipleLinksLeftToRight]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testNanTargetIgnored]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testNanTargetIgnored]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testNegativeDecimalTarget]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testNegativeDecimalTarget]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testNonDecimalTargetIgnored]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testNonDecimalTargetIgnored]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testOrdinaryMarkdownLinkNotExtracted]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testOrdinaryMarkdownLinkNotExtracted]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testScientificNotationTarget]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testScientificNotationTarget]' passed (0.000 seconds). +Test Suite 'CrossPlaneLinkTests' passed at 2026-10-10 12:40:49.918. + Executed 17 tests, with 0 failures (0 unexpected) in 0.004 (0.005) seconds +Test Suite 'DocumentCompositionCodecTests' started at 2026-10-10 12:40:49.918. +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testCanonicalProfileStoresSharedDefinitionOnceAndIsOrderIndependent]' started. +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testCanonicalProfileStoresSharedDefinitionOnceAndIsOrderIndependent]' passed (0.004 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testCheckedInGrovePreservesItsSingleCanopyDefinitionAndBindingAcrossFormats]' started. +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testCheckedInGrovePreservesItsSingleCanopyDefinitionAndBindingAcrossFormats]' passed (0.011 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testJSONAllocationPreflightRejectsExcessiveArraysNestingAndTrailingBytes]' started. +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testJSONAllocationPreflightRejectsExcessiveArraysNestingAndTrailingBytes]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testProfileAndDefinitionBytePoliciesBoundBothReaderAndWriter]' started. +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testProfileAndDefinitionBytePoliciesBoundBothReaderAndWriter]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testProfileUsesGenericPortableBinaryEnvelopeWithoutAnotherFormat]' started. +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testProfileUsesGenericPortableBinaryEnvelopeWithoutAnotherFormat]' passed (0.003 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testReaderRejectsDuplicateDefinitionIDsAndUnusedMissingReferences]' started. +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testReaderRejectsDuplicateDefinitionIDsAndUnusedMissingReferences]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testReaderRejectsDuplicateJSONKeysIncludingEscapedSpelling]' started. +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testReaderRejectsDuplicateJSONKeysIncludingEscapedSpelling]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testReaderRejectsInvalidUnusedDefinitionsAndDoesNotLoadSourcePaths]' started. +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testReaderRejectsInvalidUnusedDefinitionsAndDoesNotLoadSourcePaths]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testReaderRejectsUnknownManifestEntryAndReferenceKeys]' started. +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testReaderRejectsUnknownManifestEntryAndReferenceKeys]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testReaderRequiresExactEnvelopeAndVersionedManifest]' started. +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testReaderRequiresExactEnvelopeAndVersionedManifest]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testReferenceAttributesPreserveControlsQuotesAndUnicodeWithoutBreakingFences]' started. +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testReferenceAttributesPreserveControlsQuotesAndUnicodeWithoutBreakingFences]' passed (0.002 seconds). +Test Suite 'DocumentCompositionCodecTests' passed at 2026-10-10 12:40:49.945. + Executed 11 tests, with 0 failures (0 unexpected) in 0.026 (0.027) seconds +Test Suite 'DocumentCompositionTests' started at 2026-10-10 12:40:49.945. +Test Case '-[ThreeMDTests.DocumentCompositionTests testCanceledConstructionAndStorageStayDistinctFromValidationErrors]' started. +Test Case '-[ThreeMDTests.DocumentCompositionTests testCanceledConstructionAndStorageStayDistinctFromValidationErrors]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionTests testCyclesAreRejectedInRootAndUnusedNodes]' started. +Test Case '-[ThreeMDTests.DocumentCompositionTests testCyclesAreRejectedInRootAndUnusedNodes]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionTests testDefinitionDepthAndReferenceBudgetsHaveExactBoundarySemantics]' started. +Test Case '-[ThreeMDTests.DocumentCompositionTests testDefinitionDepthAndReferenceBudgetsHaveExactBoundarySemantics]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionTests testDefinitionDocumentPolicyIsIndependentOfCompositionPolicy]' started. +Test Case '-[ThreeMDTests.DocumentCompositionTests testDefinitionDocumentPolicyIsIndependentOfCompositionPolicy]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionTests testEveryDefinitionIsValidatedEvenWhenUnused]' started. +Test Case '-[ThreeMDTests.DocumentCompositionTests testEveryDefinitionIsValidatedEvenWhenUnused]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionTests testIDsAreCaseSensitiveAndNeverFileOrNetworkLocations]' started. +Test Case '-[ThreeMDTests.DocumentCompositionTests testIDsAreCaseSensitiveAndNeverFileOrNetworkLocations]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionTests testMissingRootMissingTargetAndDuplicateDefinitionsAreRejected]' started. +Test Case '-[ThreeMDTests.DocumentCompositionTests testMissingRootMissingTargetAndDuplicateDefinitionsAreRejected]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionTests testOccurrenceBudgetCountsSharedReferencesWithoutMaterializingThem]' started. +Test Case '-[ThreeMDTests.DocumentCompositionTests testOccurrenceBudgetCountsSharedReferencesWithoutMaterializingThem]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionTests testReferenceAttributesAreOpaqueUnicodeDataWithCountAndByteLimits]' started. +Test Case '-[ThreeMDTests.DocumentCompositionTests testReferenceAttributesAreOpaqueUnicodeDataWithCountAndByteLimits]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionTests testResourceLimitsCannotBeRaisedBeyondAbsoluteBounds]' started. +Test Case '-[ThreeMDTests.DocumentCompositionTests testResourceLimitsCannotBeRaisedBeyondAbsoluteBounds]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionTests testSharedNestedDefinitionsPreserveAxesMetadataAndReferenceOrder]' started. +Test Case '-[ThreeMDTests.DocumentCompositionTests testSharedNestedDefinitionsPreserveAxesMetadataAndReferenceOrder]' passed (0.003 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionTests testUniqueSourceByteBudgetCountsEachDefinitionOnce]' started. +Test Case '-[ThreeMDTests.DocumentCompositionTests testUniqueSourceByteBudgetCountsEachDefinitionOnce]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionTests testUnusedDepthAndOccurrenceBudgetsAreAlsoEnforced]' started. +Test Case '-[ThreeMDTests.DocumentCompositionTests testUnusedDepthAndOccurrenceBudgetsAreAlsoEnforced]' passed (0.000 seconds). +Test Suite 'DocumentCompositionTests' passed at 2026-10-10 12:40:49.955. + Executed 13 tests, with 0 failures (0 unexpected) in 0.010 (0.010) seconds +Test Suite 'DocumentDiagnosticTests' started at 2026-10-10 12:40:49.955. +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testCancellationIsNeverConvertedIntoAValidationDiagnostic]' started. +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testCancellationIsNeverConvertedIntoAValidationDiagnostic]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testCancelledCompositionDiagnosticsDoNotBeginPreflightOrGraphValidation]' started. +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testCancelledCompositionDiagnosticsDoNotBeginPreflightOrGraphValidation]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testCompositionDiagnosticBudgetRejectsBeforeExpensiveGraphSourceValidation]' started. +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testCompositionDiagnosticBudgetRejectsBeforeExpensiveGraphSourceValidation]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testCompositionDiagnosticPreflightStillEnforcesCheapCountPolicies]' started. +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testCompositionDiagnosticPreflightStillEnforcesCheapCountPolicies]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testCompositionDiagnosticsScopeRepeatedInstanceIDsByOwner]' started. +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testCompositionDiagnosticsScopeRepeatedInstanceIDsByOwner]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testDiagnosticCeilingSignalsUninspectedRemainder]' started. +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testDiagnosticCeilingSignalsUninspectedRemainder]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testDiagnosticInputAndValueByteWorkAreBounded]' started. +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testDiagnosticInputAndValueByteWorkAreBounded]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testHostileLinkPrefixesDoNotTriggerLegacyRegexDuringDiagnostics]' started. +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testHostileLinkPrefixesDoNotTriggerLegacyRegexDuringDiagnostics]' passed (0.017 seconds). +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testSharedDecimalScannerRejectsLongMalformedLinkNumberAndPreservesGrammar]' started. +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testSharedDecimalScannerRejectsLongMalformedLinkNumberAndPreservesGrammar]' passed (0.004 seconds). +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testSourceParseDiagnosticsPreserveRealLineEvidence]' started. +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testSourceParseDiagnosticsPreserveRealLineEvidence]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testValueDiagnosticsHavePlanePathsAndNoInventedLines]' started. +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testValueDiagnosticsHavePlanePathsAndNoInventedLines]' passed (0.001 seconds). +Test Suite 'DocumentDiagnosticTests' passed at 2026-10-10 12:40:49.980. + Executed 11 tests, with 0 failures (0 unexpected) in 0.024 (0.025) seconds +Test Suite 'DocumentEditingTests' started at 2026-10-10 12:40:49.980. +Test Case '-[ThreeMDTests.DocumentEditingTests testAtomicCoordinateSwapRetainsIDsSourceOrderMetadataAndLegacyLinks]' started. +Test Case '-[ThreeMDTests.DocumentEditingTests testAtomicCoordinateSwapRetainsIDsSourceOrderMetadataAndLegacyLinks]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentEditingTests testCancelledTransactionPropagatesCancellation]' started. +Test Case '-[ThreeMDTests.DocumentEditingTests testCancelledTransactionPropagatesCancellation]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentEditingTests testCanonicalReopenHasSameRevisionAndCodableValuesRoundTrip]' started. +Test Case '-[ThreeMDTests.DocumentEditingTests testCanonicalReopenHasSameRevisionAndCodableValuesRoundTrip]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentEditingTests testFailureAfterValidFirstOperationPublishesNothing]' started. +Test Case '-[ThreeMDTests.DocumentEditingTests testFailureAfterValidFirstOperationPublishesNothing]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentEditingTests testFinalCoordinateConflictReturnsPrecisePathAndNoMutation]' started. +Test Case '-[ThreeMDTests.DocumentEditingTests testFinalCoordinateConflictReturnsPrecisePathAndNoMutation]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentEditingTests testInsertMoveRemoveAndHeaderTransactionPreservesUnrelatedPlanes]' started. +Test Case '-[ThreeMDTests.DocumentEditingTests testInsertMoveRemoveAndHeaderTransactionPreservesUnrelatedPlanes]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentEditingTests testInvalidFinalDirectValuesCannotEscapeStorageValidation]' started. +Test Case '-[ThreeMDTests.DocumentEditingTests testInvalidFinalDirectValuesCannotEscapeStorageValidation]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentEditingTests testInvalidInsertMoveAndDuplicateIdentityAreDiagnosed]' started. +Test Case '-[ThreeMDTests.DocumentEditingTests testInvalidInsertMoveAndDuplicateIdentityAreDiagnosed]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentEditingTests testNoIdentityLegacyDocumentRequiresExplicitAdoptionForTargetedEdits]' started. +Test Case '-[ThreeMDTests.DocumentEditingTests testNoIdentityLegacyDocumentRequiresExplicitAdoptionForTargetedEdits]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentEditingTests testOperationOperandAndExpectedRevisionBudgetsAreEnforced]' started. +Test Case '-[ThreeMDTests.DocumentEditingTests testOperationOperandAndExpectedRevisionBudgetsAreEnforced]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentEditingTests testReplacementCannotSilentlyChangeOrDropIdentity]' started. +Test Case '-[ThreeMDTests.DocumentEditingTests testReplacementCannotSilentlyChangeOrDropIdentity]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentEditingTests testSnapshotDecoderRejectsForgedRevision]' started. +Test Case '-[ThreeMDTests.DocumentEditingTests testSnapshotDecoderRejectsForgedRevision]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentEditingTests testStaleExactRevisionRejectsChangedContentAndUnicodeEquivalentBytes]' started. +Test Case '-[ThreeMDTests.DocumentEditingTests testStaleExactRevisionRejectsChangedContentAndUnicodeEquivalentBytes]' passed (0.000 seconds). +Test Suite 'DocumentEditingTests' passed at 2026-10-10 12:40:49.988. + Executed 13 tests, with 0 failures (0 unexpected) in 0.007 (0.008) seconds +Test Suite 'DocumentFileCompositionTests' started at 2026-10-10 12:40:49.988. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testAttributeBoundCountsNormalizedDirectoryPrefixBytes]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testAttributeBoundCountsNormalizedDirectoryPrefixBytes]' passed (0.003 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testBundledTextAndBinaryReopenWithoutSupplyingAnySourceFiles]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testBundledTextAndBinaryReopenWithoutSupplyingAnySourceFiles]' passed (0.005 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testCachedSubtreeIsChargedAtItsDeeperOccurrenceAgainstTheDiscoveryCeiling]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testCachedSubtreeIsChargedAtItsDeeperOccurrenceAgainstTheDiscoveryCeiling]' passed (0.250 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testCancellationDuringARunningFanOutResolutionPublishesNoResult]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testCancellationDuringARunningFanOutResolutionPublishesNoResult]' passed (1.161 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testCancellationStaysDistinctAndNeverReturnsPartialComposition]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testCancellationStaysDistinctAndNeverReturnsPartialComposition]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testCancelledPathResolutionPrecedesOversizedInput]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testCancelledPathResolutionPrecedesOversizedInput]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testChildStorageFailuresKeepOriginalErrorType]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testChildStorageFailuresKeepOriginalErrorType]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testDisconnectedEmbeddedLedgerUsesActualEntryDepthAndRepeatedCachedFiles]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testDisconnectedEmbeddedLedgerUsesActualEntryDepthAndRepeatedCachedFiles]' passed (0.003 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testDiscoveryMissingFilePrecedesUnvalidatedFinalGraphDepth]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testDiscoveryMissingFilePrecedesUnvalidatedFinalGraphDepth]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testDuplicateBasenamesAndUnicodeScalarOrderingRemainDistinct]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testDuplicateBasenamesAndUnicodeScalarOrderingRemainDistinct]' passed (0.003 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testDuplicateNormalizedAndCanonicallyEquivalentSourcesFailBeforeDecode]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testDuplicateNormalizedAndCanonicallyEquivalentSourcesFailBeforeDecode]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testExistingBundleRetainsUnusedEntriesOpaqueAttributesAndIdentitiesAndScansEveryLedger]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testExistingBundleRetainsUnusedEntriesOpaqueAttributesAndIdentitiesAndScansEveryLedger]' passed (0.009 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testExistingEdgesPrecedeLedgerEdgesAndEmbeddedLedgersResolveFromTheirBundleFolder]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testExistingEdgesPrecedeLedgerEdgesAndEmbeddedLedgersResolveFromTheirBundleFolder]' passed (0.004 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testFileCyclesIncludeUnusedEmbeddedEntryLedgers]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testFileCyclesIncludeUnusedEmbeddedEntryLedgers]' passed (0.002 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testFixedFileDiscoverySafetyCeilingRemainsBoundedForDisconnectedEntries]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testFixedFileDiscoverySafetyCeilingRemainsBoundedForDisconnectedEntries]' passed (0.208 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testLedgerEscapesDecodeBeforePathGrammar]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testLedgerEscapesDecodeBeforePathGrammar]' passed (0.003 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testLedgerRejectsDuplicateEscapedKeysAndMalformedValuesAndGlyphs]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testLedgerRejectsDuplicateEscapedKeysAndMalformedValuesAndGlyphs]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testLongDirectoryOwnersResolveRepeatedSourcesOnceAndRefuseOverBoundTargetsAtTheFirstEdge]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testLongDirectoryOwnersResolveRepeatedSourcesOnceAndRefuseOverBoundTargetsAtTheFirstEdge]' passed (1.608 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testLongOwnerPathWithManyReferencesResolvesEveryReferenceInItsDirectory]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testLongOwnerPathWithManyReferencesResolvesEveryReferenceInItsDirectory]' passed (0.107 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testLoweredDefinitionDepthReferenceTraversalAndAttributePoliciesApplyToCompleteGraph]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testLoweredDefinitionDepthReferenceTraversalAndAttributePoliciesApplyToCompleteGraph]' passed (0.004 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testLoweredPolicyChargesOriginalPathBytesBeforePathGrammarAndEncodedBytesBeforeDecoding]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testLoweredPolicyChargesOriginalPathBytesBeforePathGrammarAndEncodedBytesBeforeDecoding]' passed (0.002 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testMissingRootAndLinkedChildReportNormalizedMissingPaths]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testMissingRootAndLinkedChildReportNormalizedMissingPaths]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testNestedParentPathsAndRefreshedChildrenRetainDeterministicIDs]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testNestedParentPathsAndRefreshedChildrenRetainDeterministicIDs]' passed (0.003 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testNestedProfileUsesProfileRecordPolicyWhileOrdinaryAndChildDocumentsKeepTheirOwnPolicy]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testNestedProfileUsesProfileRecordPolicyWhileOrdinaryAndChildDocumentsKeepTheirOwnPolicy]' passed (0.006 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testOnlyReachableSourcesDecode]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testOnlyReachableSourcesDecode]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testOuterRecognitionDoesNotUseCallerPlaneLimitBeforeByteAndLinePolicies]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testOuterRecognitionDoesNotUseCallerPlaneLimitBeforeByteAndLinePolicies]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testOverBoundLedgerEdgeIsRefusedWhileResolvingBeforeLaterRefusals]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testOverBoundLedgerEdgeIsRefusedWhileResolvingBeforeLaterRefusals]' passed (0.002 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testOwnerDirectoryResolutionKeepsParentDotAndGrammarSemantics]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testOwnerDirectoryResolutionKeepsParentDotAndGrammarSemantics]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testPathsNormalizeNFCAndParentsWithoutPercentDecoding]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testPathsNormalizeNFCAndParentsWithoutPercentDecoding]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testReachableEncodedByteAndSuppliedCountAndAggregatePathLimitsFailBeforeIndexingOrPublishing]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testReachableEncodedByteAndSuppliedCountAndAggregatePathLimitsFailBeforeIndexingOrPublishing]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testRefusalsFollowEntryIDThenGlyphDiscoveryOrder]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testRefusalsFollowEntryIDThenGlyphDiscoveryOrder]' passed (0.005 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testRepeatedCachedFilesAreStillCheckedAgainstFinalCompleteEntryDepth]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testRepeatedCachedFilesAreStillCheckedAgainstFinalCompleteEntryDepth]' passed (0.003 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testResolverOutputRebundlesWithOpaqueGlyphAndSourceFileAttributes]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testResolverOutputRebundlesWithOpaqueGlyphAndSourceFileAttributes]' passed (0.004 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testRootAndUnreachableSuppliedPathsUseTheLedgerPathGrammar]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testRootAndUnreachableSuppliedPathsUseTheLedgerPathGrammar]' passed (0.003 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testSelfAndAliasCyclesCompareNormalizedPaths]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testSelfAndAliasCyclesCompareNormalizedPaths]' passed (0.002 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testSimpleRepeatedFilesProduceOneDefinitionAndPreserveOrdinaryDocumentFields]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testSimpleRepeatedFilesProduceOneDefinitionAndPreserveOrdinaryDocumentFields]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testSourceFileAttributeBoundCountsNormalizedUTF8Bytes]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testSourceFileAttributeBoundCountsNormalizedUTF8Bytes]' passed (0.146 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testStandalonePathsAndLedgersPastTheOldRecordSizeAreSaved]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testStandalonePathsAndLedgersPastTheOldRecordSizeAreSaved]' passed (0.975 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testTextAndUncompressedBinaryChildrenBundleIdenticallyWithoutExtensionRestrictions]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testTextAndUncompressedBinaryChildrenBundleIdenticallyWithoutExtensionRestrictions]' passed (0.004 seconds). +Test Suite 'DocumentFileCompositionTests' passed at 2026-10-10 12:40:54.526. + Executed 39 tests, with 0 failures (0 unexpected) in 4.535 (4.538) seconds +Test Suite 'DocumentIdentityTests' started at 2026-10-10 12:40:54.526. +Test Case '-[ThreeMDTests.DocumentIdentityTests testAdoptionPreservesNamespaceMetadataAndDeterministicallySkipsExistingIDs]' started. +Test Case '-[ThreeMDTests.DocumentIdentityTests testAdoptionPreservesNamespaceMetadataAndDeterministicallySkipsExistingIDs]' passed (0.002 seconds). +Test Case '-[ThreeMDTests.DocumentIdentityTests testCancelledIdentityAdoptionReturnsCancellation]' started. +Test Case '-[ThreeMDTests.DocumentIdentityTests testCancelledIdentityAdoptionReturnsCancellation]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentIdentityTests testDuplicateReferenceIdentityFailsWithinOwnerOnly]' started. +Test Case '-[ThreeMDTests.DocumentIdentityTests testDuplicateReferenceIdentityFailsWithinOwnerOnly]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentIdentityTests testDuplicatesAreRejectedRatherThanSilentlyRegenerated]' started. +Test Case '-[ThreeMDTests.DocumentIdentityTests testDuplicatesAreRejectedRatherThanSilentlyRegenerated]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentIdentityTests testExplicitIdentitiesRoundTripThroughTextAndBothBinaryBackends]' started. +Test Case '-[ThreeMDTests.DocumentIdentityTests testExplicitIdentitiesRoundTripThroughTextAndBothBinaryBackends]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentIdentityTests testIdentityAdoptionRespectsDocumentAndReferenceAttributeBudgets]' started. +Test Case '-[ThreeMDTests.DocumentIdentityTests testIdentityAdoptionRespectsDocumentAndReferenceAttributeBudgets]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentIdentityTests testRepeatedTargetsGainIndependentOwnerScopedReferenceIDs]' started. +Test Case '-[ThreeMDTests.DocumentIdentityTests testRepeatedTargetsGainIndependentOwnerScopedReferenceIDs]' passed (0.003 seconds). +Test Case '-[ThreeMDTests.DocumentIdentityTests testUnsafeAndEmptyExistingIDsAreRejectedWithExactPaths]' started. +Test Case '-[ThreeMDTests.DocumentIdentityTests testUnsafeAndEmptyExistingIDsAreRejectedWithExactPaths]' passed (0.001 seconds). +Test Suite 'DocumentIdentityTests' passed at 2026-10-10 12:40:54.534. + Executed 8 tests, with 0 failures (0 unexpected) in 0.008 (0.008) seconds +Test Suite 'DocumentStorageBoundsTests' started at 2026-10-10 12:40:54.534. +Test Case '-[ThreeMDTests.DocumentStorageBoundsTests testADocumentPastTheOldCeilingRoundTrips]' started. +Test Case '-[ThreeMDTests.DocumentStorageBoundsTests testADocumentPastTheOldCeilingRoundTrips]' passed (19.038 seconds). +Test Case '-[ThreeMDTests.DocumentStorageBoundsTests testCanceledTasksCannotReturnPartiallyEncodedOrDecodedDocuments]' started. +Test Case '-[ThreeMDTests.DocumentStorageBoundsTests testCanceledTasksCannotReturnPartiallyEncodedOrDecodedDocuments]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentStorageBoundsTests testCombinedScalarAndDirectiveBytesCannotBypassTheOutputBound]' started. +Test Case '-[ThreeMDTests.DocumentStorageBoundsTests testCombinedScalarAndDirectiveBytesCannotBypassTheOutputBound]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentStorageBoundsTests testLimitsArePositiveAndHaveNoAbsoluteCeiling]' started. +Test Case '-[ThreeMDTests.DocumentStorageBoundsTests testLimitsArePositiveAndHaveNoAbsoluteCeiling]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentStorageBoundsTests testPhysicalLinesAreBoundedBeforeParsingEvenForBlankInputs]' started. +Test Case '-[ThreeMDTests.DocumentStorageBoundsTests testPhysicalLinesAreBoundedBeforeParsingEvenForBlankInputs]' passed (0.009 seconds). +Test Case '-[ThreeMDTests.DocumentStorageBoundsTests testPlanePreflightIgnoresDirectivesInsideBothKindsOfFences]' started. +Test Case '-[ThreeMDTests.DocumentStorageBoundsTests testPlanePreflightIgnoresDirectivesInsideBothKindsOfFences]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentStorageBoundsTests testRecordBoundIncludesWholePlaneBodiesAndEscapedScalarLines]' started. +Test Case '-[ThreeMDTests.DocumentStorageBoundsTests testRecordBoundIncludesWholePlaneBodiesAndEscapedScalarLines]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentStorageBoundsTests testTextAndPortableBinaryAcceptExactByteBounds]' started. +Test Case '-[ThreeMDTests.DocumentStorageBoundsTests testTextAndPortableBinaryAcceptExactByteBounds]' passed (0.001 seconds). +Test Suite 'DocumentStorageBoundsTests' passed at 2026-10-10 12:41:13.584. + Executed 8 tests, with 0 failures (0 unexpected) in 19.050 (19.050) seconds +Test Suite 'DocumentStorageCompressionTests' started at 2026-10-10 12:41:13.584. +Test Case '-[ThreeMDTests.DocumentStorageCompressionTests testAppleLZFSECompressionIsDeterministicAndRoundTripsGeneralText]' started. +Test Case '-[ThreeMDTests.DocumentStorageCompressionTests testAppleLZFSECompressionIsDeterministicAndRoundTripsGeneralText]' passed (0.144 seconds). +Test Case '-[ThreeMDTests.DocumentStorageCompressionTests testCanceledCompressionAndDecompressionRemainCancellationErrors]' started. +Test Case '-[ThreeMDTests.DocumentStorageCompressionTests testCanceledCompressionAndDecompressionRemainCancellationErrors]' passed (0.002 seconds). +Test Case '-[ThreeMDTests.DocumentStorageCompressionTests testDeclaredOutputSizeCannotTruncateOrGrowDecompression]' started. +Test Case '-[ThreeMDTests.DocumentStorageCompressionTests testDeclaredOutputSizeCannotTruncateOrGrowDecompression]' passed (0.030 seconds). +Test Case '-[ThreeMDTests.DocumentStorageCompressionTests testEveryTruncationAndMalformedCompressionPayloadFailsWithoutPartialResults]' started. +Test Case '-[ThreeMDTests.DocumentStorageCompressionTests testEveryTruncationAndMalformedCompressionPayloadFailsWithoutPartialResults]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentStorageCompressionTests testLargeFirstStreamDrainsMultipleChunksBeforeFinalMarkerAndRejectsConcatenation]' started. +Test Case '-[ThreeMDTests.DocumentStorageCompressionTests testLargeFirstStreamDrainsMultipleChunksBeforeFinalMarkerAndRejectsConcatenation]' passed (0.005 seconds). +Test Case '-[ThreeMDTests.DocumentStorageCompressionTests testLZFSERejectsTrailingAndConcatenatedStreamsWithValidChecksums]' started. +Test Case '-[ThreeMDTests.DocumentStorageCompressionTests testLZFSERejectsTrailingAndConcatenatedStreamsWithValidChecksums]' passed (0.000 seconds). +Test Suite 'DocumentStorageCompressionTests' passed at 2026-10-10 12:41:13.768. + Executed 6 tests, with 0 failures (0 unexpected) in 0.183 (0.184) seconds +Test Suite 'DocumentStorageDecimalTests' started at 2026-10-10 12:41:13.768. +Test Case '-[ThreeMDTests.DocumentStorageDecimalTests testCancellationDuringAnInvalidParseRemainsCancellationError]' started. +Test Case '-[ThreeMDTests.DocumentStorageDecimalTests testCancellationDuringAnInvalidParseRemainsCancellationError]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentStorageDecimalTests testLongMalformedDecimalRejectsReadableAndChecksummedBinaryWithoutBacktracking]' started. +Test Case '-[ThreeMDTests.DocumentStorageDecimalTests testLongMalformedDecimalRejectsReadableAndChecksummedBinaryWithoutBacktracking]' passed (0.002 seconds). +Test Suite 'DocumentStorageDecimalTests' passed at 2026-10-10 12:41:13.772. + Executed 2 tests, with 0 failures (0 unexpected) in 0.004 (0.004) seconds +Test Suite 'DocumentStorageStructuredTests' started at 2026-10-10 12:41:13.772. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testAmplifiedQuotedKeysAreRejectedByPhaseLBeforeAnyPhaseQParse]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testAmplifiedQuotedKeysAreRejectedByPhaseLBeforeAnyPhaseQParse]' passed (0.395 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testCanceledTasksReturnNoStructuredDocumentOrBytes]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testCanceledTasksReturnNoStructuredDocumentOrBytes]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testCancellationIsCheckedAtEveryStructuredCheckpoint]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testCancellationIsCheckedAtEveryStructuredCheckpoint]' passed (0.955 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testCanonicallyEquivalentKeysInOnePayloadMapAreInvalidDocuments]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testCanonicallyEquivalentKeysInOnePayloadMapAreInvalidDocuments]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testChecksumSlicingMatchesTheBytewiseDefinitionAtEveryAlignment]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testChecksumSlicingMatchesTheBytewiseDefinitionAtEveryAlignment]' passed (1.673 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testChunkedUTF8ValidationAgreesWithWholeValidationAcrossChunkBoundaries]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testChunkedUTF8ValidationAgreesWithWholeValidationAcrossChunkBoundaries]' passed (0.465 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testConcurrentTasksEncodeAndDecodeIndependently]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testConcurrentTasksEncodeAndDecodeIndependently]' passed (0.018 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testContainerInfoReportsRawHeaderFieldsWithoutValidation]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testContainerInfoReportsRawHeaderFieldsWithoutValidation]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testCountFramingDividesAndPrecedesThePlaneLimitAtTheLargestCounts]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testCountFramingDividesAndPrecedesThePlaneLimitAtTheLargestCounts]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testDecodeAcceptsDataSlicesWithANonzeroStartIndex]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testDecodeAcceptsDataSlicesWithANonzeroStartIndex]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testDecodedLengthBoundPrecedesTheChecksumAndDecompression]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testDecodedLengthBoundPrecedesTheChecksumAndDecompression]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testDecodingPeakMemoryGrowthStaysUnderThreeTimesTheInput]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testDecodingPeakMemoryGrowthStaysUnderThreeTimesTheInput]' passed (29.619 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testEightyEmptyPlanesDecodeUnderAnEncodedLimitTheirTextWouldExceed]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testEightyEmptyPlanesDecodeUnderAnEncodedLimitTheirTextWouldExceed]' passed (0.003 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testEveryGoldenIsByteIdenticalAndDecodesToTheBoundedTextDecode]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testEveryGoldenIsByteIdenticalAndDecodesToTheBoundedTextDecode]' passed (0.067 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testEveryVectorReportsItsCodeUnderItsLimits]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testEveryVectorReportsItsCodeUnderItsLimits]' passed (0.019 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testFrozenWhitespaceSetHoldsExactlyNineteenScalars]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testFrozenWhitespaceSetHoldsExactlyNineteenScalars]' passed (0.267 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testKeysAreOrderedByUTF8BytesWhichIsCodePointOrder]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testKeysAreOrderedByUTF8BytesWhichIsCodePointOrder]' passed (0.007 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testLongAttributeKeysAreComparedWithTheirLowercaseAcrossChunkEdges]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testLongAttributeKeysAreComparedWithTheirLowercaseAcrossChunkEdges]' passed (0.233 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testLZFSEStructuredPayloadsRoundTripAndKeepTheDecodedBound]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testLZFSEStructuredPayloadsRoundTripAndKeepTheDecodedBound]' passed (0.005 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testLZFSEStructuredStreamsMustEndOnceAndMatchTheDeclaredLength]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testLZFSEStructuredStreamsMustEndOnceAndMatchTheDeclaredLength]' passed (0.003 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testMetricsMatchTheTextWriterAtEveryExampleLimitEdge]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testMetricsMatchTheTextWriterAtEveryExampleLimitEdge]' passed (1.244 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testMetricsMatchTheTextWriterAtTheLimitEdgesOfGeneratedDocuments]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testMetricsMatchTheTextWriterAtTheLimitEdgesOfGeneratedDocuments]' passed (9.797 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testMutatedFilesGiveOneTypedOutcomeAndAcceptedOnesAreCanonical]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testMutatedFilesGiveOneTypedOutcomeAndAcceptedOnesAreCanonical]' passed (3.205 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testNumberFormsFollowTheCanonicalTableAndDecodeBitExactly]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testNumberFormsFollowTheCanonicalTableAndDecodeBitExactly]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testNumericPowersSpellAsTheSharedCanonicalNumbersAndRoundTripBitExactly]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testNumericPowersSpellAsTheSharedCanonicalNumbersAndRoundTripBitExactly]' passed (0.174 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testRandomBitPatternsTakeTheirCanonicalFormAndRoundTripBitExactly]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testRandomBitPatternsTakeTheirCanonicalFormAndRoundTripBitExactly]' passed (2.260 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testSegmentRulesAgreeWithTheTextParserOnRandomBodies]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testSegmentRulesAgreeWithTheTextParserOnRandomBodies]' passed (7.509 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testSegmentRulesMatchTheTextRoundTripOnHandCases]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testSegmentRulesMatchTheTextRoundTripOnHandCases]' passed (0.007 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testShortStringsChargeTheCancellationBudgetInEveryPass]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testShortStringsChargeTheCancellationBudgetInEveryPass]' passed (1.775 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testSizeGateHoldsForEveryExampleAndTheCorpus]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testSizeGateHoldsForEveryExampleAndTheCorpus]' passed (0.622 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testTextContainerWriterKeepsTheTwoZeroBytesAndHeaderChecks]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testTextContainerWriterKeepsTheTwoZeroBytesAndHeaderChecks]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testUnicodeSkewVectorsFollowTheRuntimeUnicodeData]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testUnicodeSkewVectorsFollowTheRuntimeUnicodeData]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testUTF8ValidityIsRepairedDecodingThatEqualsTheInputBytes]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testUTF8ValidityIsRepairedDecodingThatEqualsTheInputBytes]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testVarEncodesMinimallyAndDecodesEveryBoundary]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testVarEncodesMinimallyAndDecodesEveryBoundary]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testWorkedExamplesHoldTheBytesAndChecksumsOfTheSpecification]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testWorkedExamplesHoldTheBytesAndChecksumsOfTheSpecification]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testWriterAcceptanceEqualsValidationAndDecodeEqualsTheTextDecode]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testWriterAcceptanceEqualsValidationAndDecodeEqualsTheTextDecode]' passed (3.227 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testWriterCapsTheUncompressedContainerAtTheEncodedLimit]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testWriterCapsTheUncompressedContainerAtTheEncodedLimit]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testWriterOutputDecodesUnderTheSameLimitsToTheNormalizedDocument]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testWriterOutputDecodesUnderTheSameLimitsToTheNormalizedDocument]' passed (0.406 seconds). +Test Suite 'DocumentStorageStructuredTests' passed at 2026-10-10 12:42:17.736. + Executed 38 tests, with 0 failures (0 unexpected) in 63.960 (63.964) seconds +Test Suite 'DocumentStorageTests' started at 2026-10-10 12:42:17.736. +Test Case '-[ThreeMDTests.DocumentStorageTests testAllHeaderFieldsAndCorruptionAreChecked]' started. +Test Case '-[ThreeMDTests.DocumentStorageTests testAllHeaderFieldsAndCorruptionAreChecked]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentStorageTests testBinaryDecodeHandlesDataSlices]' started. +Test Case '-[ThreeMDTests.DocumentStorageTests testBinaryDecodeHandlesDataSlices]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentStorageTests testCheckedInCompressedCanopyRoundTripsToItsReadableDocument]' started. +Test Case '-[ThreeMDTests.DocumentStorageTests testCheckedInCompressedCanopyRoundTripsToItsReadableDocument]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentStorageTests testCheckedInExtensionManifestDescribesTheActualSixArtifacts]' started. +Test Case '-[ThreeMDTests.DocumentStorageTests testCheckedInExtensionManifestDescribesTheActualSixArtifacts]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentStorageTests testCheckedInPortableCanopyRoundTripsToItsReadableDocument]' started. +Test Case '-[ThreeMDTests.DocumentStorageTests testCheckedInPortableCanopyRoundTripsToItsReadableDocument]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentStorageTests testContainerPayloadMustBeValidUTF8AndThreeMDText]' started. +Test Case '-[ThreeMDTests.DocumentStorageTests testContainerPayloadMustBeValidUTF8AndThreeMDText]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentStorageTests testDirectDocumentValidationRejectsLossyOrAmbiguousSerialization]' started. +Test Case '-[ThreeMDTests.DocumentStorageTests testDirectDocumentValidationRejectsLossyOrAmbiguousSerialization]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentStorageTests testGeneralDocumentsPreserveUnicodeCustomAxesAndFractionalPositions]' started. +Test Case '-[ThreeMDTests.DocumentStorageTests testGeneralDocumentsPreserveUnicodeCustomAxesAndFractionalPositions]' passed (0.002 seconds). +Test Case '-[ThreeMDTests.DocumentStorageTests testPortableContainerFixedVector]' started. +Test Case '-[ThreeMDTests.DocumentStorageTests testPortableContainerFixedVector]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentStorageTests testStorageRetainsTextGrammarAndLegacySerializerPreservesLiteralQuotes]' started. +Test Case '-[ThreeMDTests.DocumentStorageTests testStorageRetainsTextGrammarAndLegacySerializerPreservesLiteralQuotes]' passed (0.000 seconds). +Test Suite 'DocumentStorageTests' passed at 2026-10-10 12:42:17.745. + Executed 10 tests, with 0 failures (0 unexpected) in 0.008 (0.009) seconds +Test Suite 'ExtensionConformanceTests' started at 2026-10-10 12:42:17.745. +Test Case '-[ThreeMDTests.ExtensionConformanceTests testCanonicalNumericBitPatternsMatchSharedSwiftFormattingVectors]' started. +Test Case '-[ThreeMDTests.ExtensionConformanceTests testCanonicalNumericBitPatternsMatchSharedSwiftFormattingVectors]' passed (0.005 seconds). +Test Case '-[ThreeMDTests.ExtensionConformanceTests testDocumentEnvelopeAndProfileGoldensMatchExactCanonicalBytes]' started. +Test Case '-[ThreeMDTests.ExtensionConformanceTests testDocumentEnvelopeAndProfileGoldensMatchExactCanonicalBytes]' passed (0.011 seconds). +Test Case '-[ThreeMDTests.ExtensionConformanceTests testSharedBinaryChecksumGoldensRejectCorruption]' started. +Test Case '-[ThreeMDTests.ExtensionConformanceTests testSharedBinaryChecksumGoldensRejectCorruption]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ExtensionConformanceTests testSharedCompositionTransactionsKeepUnchangedDefinitionsAndRepeatedInstances]' started. +Test Case '-[ThreeMDTests.ExtensionConformanceTests testSharedCompositionTransactionsKeepUnchangedDefinitionsAndRepeatedInstances]' passed (0.010 seconds). +Test Case '-[ThreeMDTests.ExtensionConformanceTests testSharedDocumentTransactionsValidateFinalValuesAtomically]' started. +Test Case '-[ThreeMDTests.ExtensionConformanceTests testSharedDocumentTransactionsValidateFinalValuesAtomically]' passed (0.004 seconds). +Test Case '-[ThreeMDTests.ExtensionConformanceTests testSharedFailedTransactionsHaveStableCodesPathsAndNoPartialPublication]' started. +Test Case '-[ThreeMDTests.ExtensionConformanceTests testSharedFailedTransactionsHaveStableCodesPathsAndNoPartialPublication]' passed (0.008 seconds). +Test Case '-[ThreeMDTests.ExtensionConformanceTests testSharedIdentityAdoptionPreservesOpaqueFieldsAndOwnerScopes]' started. +Test Case '-[ThreeMDTests.ExtensionConformanceTests testSharedIdentityAdoptionPreservesOpaqueFieldsAndOwnerScopes]' passed (0.004 seconds). +Test Case '-[ThreeMDTests.ExtensionConformanceTests testStrictCompositionJSONRejectsCanonicallyEquivalentDuplicateKeys]' started. +Test Case '-[ThreeMDTests.ExtensionConformanceTests testStrictCompositionJSONRejectsCanonicallyEquivalentDuplicateKeys]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.ExtensionConformanceTests testUnicodeKeyOrderingGoldensPreserveOriginalSpellingAndExactBytes]' started. +Test Case '-[ThreeMDTests.ExtensionConformanceTests testUnicodeKeyOrderingGoldensPreserveOriginalSpellingAndExactBytes]' passed (0.002 seconds). +Test Case '-[ThreeMDTests.ExtensionConformanceTests testUnicodeSourceKeyCollisionsKeepFirstSpellingAndLastValue]' started. +Test Case '-[ThreeMDTests.ExtensionConformanceTests testUnicodeSourceKeyCollisionsKeepFirstSpellingAndLastValue]' passed (0.001 seconds). +Test Suite 'ExtensionConformanceTests' passed at 2026-10-10 12:42:17.792. + Executed 10 tests, with 0 failures (0 unexpected) in 0.046 (0.047) seconds +Test Suite 'HTMLRendererTests' started at 2026-10-10 12:42:17.792. +Test Case '-[ThreeMDTests.HTMLRendererTests testAmpersandEscaped]' started. +Test Case '-[ThreeMDTests.HTMLRendererTests testAmpersandEscaped]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.HTMLRendererTests testAxisEmittedInMeta]' started. +Test Case '-[ThreeMDTests.HTMLRendererTests testAxisEmittedInMeta]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.HTMLRendererTests testBodyRenderedAsMarkdown]' started. +Test Case '-[ThreeMDTests.HTMLRendererTests testBodyRenderedAsMarkdown]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.HTMLRendererTests testDecimalZInDataAttribute]' started. +Test Case '-[ThreeMDTests.HTMLRendererTests testDecimalZInDataAttribute]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.HTMLRendererTests testDoubleQuoteEscaped]' started. +Test Case '-[ThreeMDTests.HTMLRendererTests testDoubleQuoteEscaped]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.HTMLRendererTests testLabelRenderedAsHeading]' started. +Test Case '-[ThreeMDTests.HTMLRendererTests testLabelRenderedAsHeading]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.HTMLRendererTests testLabelSpecialCharsEscaped]' started. +Test Case '-[ThreeMDTests.HTMLRendererTests testLabelSpecialCharsEscaped]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.HTMLRendererTests testLessThanEscaped]' started. +Test Case '-[ThreeMDTests.HTMLRendererTests testLessThanEscaped]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.HTMLRendererTests testMissingTitleFallsBackToDefault]' started. +Test Case '-[ThreeMDTests.HTMLRendererTests testMissingTitleFallsBackToDefault]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.HTMLRendererTests testOutputContainsHeadAndBody]' started. +Test Case '-[ThreeMDTests.HTMLRendererTests testOutputContainsHeadAndBody]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.HTMLRendererTests testOutputIsStandaloneHTML]' started. +Test Case '-[ThreeMDTests.HTMLRendererTests testOutputIsStandaloneHTML]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.HTMLRendererTests testPlaneCountMatchesSections]' started. +Test Case '-[ThreeMDTests.HTMLRendererTests testPlaneCountMatchesSections]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.HTMLRendererTests testPreambleRenderedInSection]' started. +Test Case '-[ThreeMDTests.HTMLRendererTests testPreambleRenderedInSection]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.HTMLRendererTests testSectionCarriesAriaLabel]' started. +Test Case '-[ThreeMDTests.HTMLRendererTests testSectionCarriesAriaLabel]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.HTMLRendererTests testSectionCarriesDataZ]' started. +Test Case '-[ThreeMDTests.HTMLRendererTests testSectionCarriesDataZ]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.HTMLRendererTests testSingleQuoteEscaped]' started. +Test Case '-[ThreeMDTests.HTMLRendererTests testSingleQuoteEscaped]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.HTMLRendererTests testTitleEmittedInH1]' started. +Test Case '-[ThreeMDTests.HTMLRendererTests testTitleEmittedInH1]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.HTMLRendererTests testTitleEmittedInTitleElement]' started. +Test Case '-[ThreeMDTests.HTMLRendererTests testTitleEmittedInTitleElement]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.HTMLRendererTests testTitleSpecialCharsEscaped]' started. +Test Case '-[ThreeMDTests.HTMLRendererTests testTitleSpecialCharsEscaped]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.HTMLRendererTests testVersionEmittedInMeta]' started. +Test Case '-[ThreeMDTests.HTMLRendererTests testVersionEmittedInMeta]' passed (0.000 seconds). +Test Suite 'HTMLRendererTests' passed at 2026-10-10 12:42:17.797. + Executed 20 tests, with 0 failures (0 unexpected) in 0.004 (0.005) seconds +Test Suite 'InterchangeConformanceTests' started at 2026-10-10 12:42:17.797. +Test Case '-[ThreeMDTests.InterchangeConformanceTests testAdoptionAndDeterministicDocumentEditsHaveExactRevisionAndRejectReuse]' started. +Test Case '-[ThreeMDTests.InterchangeConformanceTests testAdoptionAndDeterministicDocumentEditsHaveExactRevisionAndRejectReuse]' passed (0.040 seconds). +Test Case '-[ThreeMDTests.InterchangeConformanceTests testASCIIFencePrefixesWithCombiningMarksKeepInnerDirectivesAsBody]' started. +Test Case '-[ThreeMDTests.InterchangeConformanceTests testASCIIFencePrefixesWithCombiningMarksKeepInnerDirectivesAsBody]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.InterchangeConformanceTests testCatalogIncludesEveryDeclaredExtensionSourceAndBinaryGolden]' started. +Test Case '-[ThreeMDTests.InterchangeConformanceTests testCatalogIncludesEveryDeclaredExtensionSourceAndBinaryGolden]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.InterchangeConformanceTests testCatalogRequiresEveryLegacySourceAndHasUniqueCompleteCases]' started. +Test Case '-[ThreeMDTests.InterchangeConformanceTests testCatalogRequiresEveryLegacySourceAndHasUniqueCompleteCases]' passed (0.039 seconds). +Test Case '-[ThreeMDTests.InterchangeConformanceTests testCombiningMarkEscapesChargeExactCanonicalUTF8OutputBytes]' started. +Test Case '-[ThreeMDTests.InterchangeConformanceTests testCombiningMarkEscapesChargeExactCanonicalUTF8OutputBytes]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.InterchangeConformanceTests testEveryInvalidCatalogSourceReportsItsRequiredTypedError]' started. +Test Case '-[ThreeMDTests.InterchangeConformanceTests testEveryInvalidCatalogSourceReportsItsRequiredTypedError]' passed (0.006 seconds). +Test Case '-[ThreeMDTests.InterchangeConformanceTests testEveryValidCatalogSourceAndLegacyOutputPreserveExactCanonicalBytes]' started. +Test Case '-[ThreeMDTests.InterchangeConformanceTests testEveryValidCatalogSourceAndLegacyOutputPreserveExactCanonicalBytes]' passed (0.052 seconds). +Test Case '-[ThreeMDTests.InterchangeConformanceTests testLegacySerializerPreservesRepresentableScalarQuotesAndFoundationEdgeWhitespace]' started. +Test Case '-[ThreeMDTests.InterchangeConformanceTests testLegacySerializerPreservesRepresentableScalarQuotesAndFoundationEdgeWhitespace]' passed (0.003 seconds). +Test Case '-[ThreeMDTests.InterchangeConformanceTests testScalarFieldSeparatorsAndSpaceTokensMatchBoundedPreflight]' started. +Test Case '-[ThreeMDTests.InterchangeConformanceTests testScalarFieldSeparatorsAndSpaceTokensMatchBoundedPreflight]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.InterchangeConformanceTests testScalarQuoteAndEscapeDelimitersPreserveAdjacentCombiningMarks]' started. +Test Case '-[ThreeMDTests.InterchangeConformanceTests testScalarQuoteAndEscapeDelimitersPreserveAdjacentCombiningMarks]' passed (0.002 seconds). +Test Case '-[ThreeMDTests.InterchangeConformanceTests testSharedDAGAndUnusedDefinitionsSurviveAdoptionAndRootReplacement]' started. +Test Case '-[ThreeMDTests.InterchangeConformanceTests testSharedDAGAndUnusedDefinitionsSurviveAdoptionAndRootReplacement]' passed (0.005 seconds). +Test Case '-[ThreeMDTests.InterchangeConformanceTests testStorageRejectsReservedASCIIDelimitersInsideCombiningGraphemes]' started. +Test Case '-[ThreeMDTests.InterchangeConformanceTests testStorageRejectsReservedASCIIDelimitersInsideCombiningGraphemes]' passed (0.000 seconds). +Test Suite 'InterchangeConformanceTests' passed at 2026-10-10 12:42:17.946. + Executed 12 tests, with 0 failures (0 unexpected) in 0.149 (0.149) seconds +Test Suite 'MarkdownRendererTests' started at 2026-10-10 12:42:17.946. +Test Case '-[ThreeMDTests.MarkdownRendererTests testAmpersandInParagraphIsEscaped]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testAmpersandInParagraphIsEscaped]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testBlankLineSeparatesParagraphs]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testBlankLineSeparatesParagraphs]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testBlockquote]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testBlockquote]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testBoldDoubleAsterisk]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testBoldDoubleAsterisk]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testBoldDoubleUnderscore]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testBoldDoubleUnderscore]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testBoldMidSentence]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testBoldMidSentence]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testCheckedTaskItemLowercase]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testCheckedTaskItemLowercase]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testCheckedTaskItemUppercase]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testCheckedTaskItemUppercase]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testDoubleQuoteInParagraphIsEscaped]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testDoubleQuoteInParagraphIsEscaped]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testFencedCodeBlock]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testFencedCodeBlock]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testFencedCodeBlockEscapesHTML]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testFencedCodeBlockEscapesHTML]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testFencedCodeBlockPreservesMarkdownLookingContent]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testFencedCodeBlockPreservesMarkdownLookingContent]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testFencedCodeBlockWithLanguage]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testFencedCodeBlockWithLanguage]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testH1]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testH1]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testH2]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testH2]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testH3]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testH3]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testH4]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testH4]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testH5]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testH5]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testH6]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testH6]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testHeadingFollowedByParagraph]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testHeadingFollowedByParagraph]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testHeadingRequiresSpaceAfterHash]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testHeadingRequiresSpaceAfterHash]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testInlineCode]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testInlineCode]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testInlineCodeDoesNotRenderMarkdown]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testInlineCodeDoesNotRenderMarkdown]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testInlineCodeEscapesHTML]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testInlineCodeEscapesHTML]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testItalicAsterisk]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testItalicAsterisk]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testItalicUnderscore]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testItalicUnderscore]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testLessThanInParagraphIsEscaped]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testLessThanInParagraphIsEscaped]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testLink]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testLink]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testLinkHrefIsEscaped]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testLinkHrefIsEscaped]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testLinkTextIsEscaped]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testLinkTextIsEscaped]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testMultiLineBlockquote]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testMultiLineBlockquote]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testMultiLineParagraphJoinsWithSpace]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testMultiLineParagraphJoinsWithSpace]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testOrderedList]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testOrderedList]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testParagraphWithBoldAndLink]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testParagraphWithBoldAndLink]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testSingleLineParagraph]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testSingleLineParagraph]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testSingleQuoteInParagraphIsEscaped]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testSingleQuoteInParagraphIsEscaped]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testUncheckedTaskItem]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testUncheckedTaskItem]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testUnorderedListAsterisk]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testUnorderedListAsterisk]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testUnorderedListDash]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testUnorderedListDash]' passed (0.000 seconds). +Test Suite 'MarkdownRendererTests' passed at 2026-10-10 12:42:17.953. + Executed 39 tests, with 0 failures (0 unexpected) in 0.005 (0.007) seconds +Test Suite 'ParseErrorMetadataTests' started at 2026-10-10 12:42:17.953. +Test Case '-[ThreeMDTests.ParseErrorMetadataTests testDuplicatePlaneMetadata]' started. +Test Case '-[ThreeMDTests.ParseErrorMetadataTests testDuplicatePlaneMetadata]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParseErrorMetadataTests testInvalidDirectiveMetadata]' started. +Test Case '-[ThreeMDTests.ParseErrorMetadataTests testInvalidDirectiveMetadata]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParseErrorMetadataTests testMissingVersionCode]' started. +Test Case '-[ThreeMDTests.ParseErrorMetadataTests testMissingVersionCode]' passed (0.000 seconds). +Test Suite 'ParseErrorMetadataTests' passed at 2026-10-10 12:42:17.954. + Executed 3 tests, with 0 failures (0 unexpected) in 0.000 (0.000) seconds +Test Suite 'ParserNumericTests' started at 2026-10-10 12:42:17.954. +Test Case '-[ThreeMDTests.ParserNumericTests testFiniteDecimalGrammarIsPreservedForEveryCoordinate]' started. +Test Case '-[ThreeMDTests.ParserNumericTests testFiniteDecimalGrammarIsPreservedForEveryCoordinate]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.ParserNumericTests testMalformedAndNonfiniteNumbersAreRejectedForEveryCoordinate]' started. +Test Case '-[ThreeMDTests.ParserNumericTests testMalformedAndNonfiniteNumbersAreRejectedForEveryCoordinate]' passed (0.001 seconds). +Test Suite 'ParserNumericTests' passed at 2026-10-10 12:42:17.956. + Executed 2 tests, with 0 failures (0 unexpected) in 0.002 (0.002) seconds +Test Suite 'ParserTests' started at 2026-10-10 12:42:17.956. +Test Case '-[ThreeMDTests.ParserTests testAxisDefaultsToLayer]' started. +Test Case '-[ThreeMDTests.ParserTests testAxisDefaultsToLayer]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testAxisRawValueNormalized]' started. +Test Case '-[ThreeMDTests.ParserTests testAxisRawValueNormalized]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testDecimalZValue]' started. +Test Case '-[ThreeMDTests.ParserTests testDecimalZValue]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testDuplicatePositionThrows]' started. +Test Case '-[ThreeMDTests.ParserTests testDuplicatePositionThrows]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testEmptyDocumentProducesNoPlanes]' started. +Test Case '-[ThreeMDTests.ParserTests testEmptyDocumentProducesNoPlanes]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testFrontmatterIgnoresCommentLines]' started. +Test Case '-[ThreeMDTests.ParserTests testFrontmatterIgnoresCommentLines]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testFrontmatterStripsQuotedValues]' started. +Test Case '-[ThreeMDTests.ParserTests testFrontmatterStripsQuotedValues]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testInvalidDirectiveTokenThrows]' started. +Test Case '-[ThreeMDTests.ParserTests testInvalidDirectiveTokenThrows]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testKnownAxesMatchSpec]' started. +Test Case '-[ThreeMDTests.ParserTests testKnownAxesMatchSpec]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testLeadingBlankLinesBeforeFrontmatter]' started. +Test Case '-[ThreeMDTests.ParserTests testLeadingBlankLinesBeforeFrontmatter]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testMissingFrontmatterThrows]' started. +Test Case '-[ThreeMDTests.ParserTests testMissingFrontmatterThrows]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testMissingPlanePositionThrows]' started. +Test Case '-[ThreeMDTests.ParserTests testMissingPlanePositionThrows]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testMissingVersionThrows]' started. +Test Case '-[ThreeMDTests.ParserTests testMissingVersionThrows]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testNegativeZValue]' started. +Test Case '-[ThreeMDTests.ParserTests testNegativeZValue]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testNonNumericPositionThrows]' started. +Test Case '-[ThreeMDTests.ParserTests testNonNumericPositionThrows]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testNonNumericXThrows]' started. +Test Case '-[ThreeMDTests.ParserTests testNonNumericXThrows]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testNonNumericYThrows]' started. +Test Case '-[ThreeMDTests.ParserTests testNonNumericYThrows]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testParseErrorDescriptions]' started. +Test Case '-[ThreeMDTests.ParserTests testParseErrorDescriptions]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testParsesFrontmatter]' started. +Test Case '-[ThreeMDTests.ParserTests testParsesFrontmatter]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testParsesMultiplePlanes]' started. +Test Case '-[ThreeMDTests.ParserTests testParsesMultiplePlanes]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testParsesPlaneCoordinatesAndAttributes]' started. +Test Case '-[ThreeMDTests.ParserTests testParsesPlaneCoordinatesAndAttributes]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testPlainMarkdownBecomesSinglePlane]' started. +Test Case '-[ThreeMDTests.ParserTests testPlainMarkdownBecomesSinglePlane]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testPlaneAtZReturnsNilForMissingPosition]' started. +Test Case '-[ThreeMDTests.ParserTests testPlaneAtZReturnsNilForMissingPosition]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testPlaneBodyTrimsLeadingAndTrailingBlanks]' started. +Test Case '-[ThreeMDTests.ParserTests testPlaneBodyTrimsLeadingAndTrailingBlanks]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testPlanesByZAreSorted]' started. +Test Case '-[ThreeMDTests.ParserTests testPlanesByZAreSorted]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testPreambleBeforeFirstPlane]' started. +Test Case '-[ThreeMDTests.ParserTests testPreambleBeforeFirstPlane]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testReservedAttributeKeysNotInExtras]' started. +Test Case '-[ThreeMDTests.ParserTests testReservedAttributeKeysNotInExtras]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testRoundTripThroughSerializer]' started. +Test Case '-[ThreeMDTests.ParserTests testRoundTripThroughSerializer]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testRoundTripWithMetadataAndAttributes]' started. +Test Case '-[ThreeMDTests.ParserTests testRoundTripWithMetadataAndAttributes]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testRoundTripWithPreamble]' started. +Test Case '-[ThreeMDTests.ParserTests testRoundTripWithPreamble]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testUnclosedFrontmatterThrows]' started. +Test Case '-[ThreeMDTests.ParserTests testUnclosedFrontmatterThrows]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testWindowsLineEndingsNormalized]' started. +Test Case '-[ThreeMDTests.ParserTests testWindowsLineEndingsNormalized]' passed (0.000 seconds). +Test Suite 'ParserTests' passed at 2026-10-10 12:42:17.963. + Executed 32 tests, with 0 failures (0 unexpected) in 0.005 (0.007) seconds +Test Suite '3mdPackageTests.xctest' passed at 2026-10-10 12:42:17.963. + Executed 322 tests, with 0 failures (0 unexpected) in 88.077 (88.100) seconds +Test Suite 'All tests' passed at 2026-10-10 12:42:17.963. + Executed 322 tests, with 0 failures (0 unexpected) in 88.077 (88.101) seconds +◇ Test run started. +↳ Testing Library Version: 1902 +↳ Target Platform: arm64e-apple-macos14.0 +✔ Test run with 0 tests in 0 suites passed after 0.001 seconds. + ✔ Step 3 done (1m 28.937s) + ▶️ Running task: js +bun install v1.4.0 (34cbb9a40) + +Checked 5 installs across 6 packages (no changes) [24.00ms] +$ tsc --noEmit +$ bun build ./src/index.ts --outdir ./dist --target node --format esm && tsc -p tsconfig.build.json +Bundled 9 modules in 15ms + + index.js 146.91 KB (entry point) + +bun test v1.4.0 (34cbb9a40) + +test/interchange.test.ts: +(pass) lossless cross-language interchange > raw parsing and bounded decoding use the literal Foundation whitespace set [19.19ms] +(pass) lossless cross-language interchange > Unicode whitespace fences do not invent directives during bounded preflight [1.87ms] +(pass) lossless cross-language interchange > UTF-8 decoding leaves BOM removal to the parser exactly once [0.20ms] +(pass) lossless cross-language interchange > source dictionary collisions retain first spelling and the last assignment in source order [7.42ms] +(pass) lossless cross-language interchange > legacy serialization preserves literal apostrophes, edge whitespace, quotes and backslashes [1.26ms] +(pass) lossless cross-language interchange > legacy number formatting and Unicode scalar key order agree with canonical wire writers [0.85ms] +(pass) lossless cross-language interchange > links preserve long finite targets, long labels and multiline labels [0.33ms] +(pass) lossless cross-language interchange > linear link scanning preserves reference regex matching for malformed nested candidates [1.71ms] + +test/structured.test.ts: +(pass) structured goldens (test-plan section 1) > the manifest lists 49 interchange anchors, 2 examples and 3 worked examples [0.07ms] +(pass) structured goldens (test-plan section 1) > axis-48: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [3.71ms] +(pass) structured goldens (test-plan section 1) > axis-49: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.60ms] +(pass) structured goldens (test-plan section 1) > axis-50: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.34ms] +(pass) structured goldens (test-plan section 1) > axis-51: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.36ms] +(pass) structured goldens (test-plan section 1) > axis-52: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.35ms] +(pass) structured goldens (test-plan section 1) > axis-53: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.30ms] +(pass) structured goldens (test-plan section 1) > axis-54: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.28ms] +(pass) structured goldens (test-plan section 1) > axis-55: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.61ms] +(pass) structured goldens (test-plan section 1) > axis-56: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.42ms] +(pass) structured goldens (test-plan section 1) > axis-57: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.26ms] +(pass) structured goldens (test-plan section 1) > combining-mark-delimiters: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [1.54ms] +(pass) structured goldens (test-plan section 1) > combining-mark-fences: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.47ms] +(pass) structured goldens (test-plan section 1) > combining-mark-scalars: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [1.57ms] +(pass) structured goldens (test-plan section 1) > composition-empty-root: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [4.25ms] +(pass) structured goldens (test-plan section 1) > composition-shared-dag-unused: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [7.62ms] +(pass) structured goldens (test-plan section 1) > empty-document: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.28ms] +(pass) structured goldens (test-plan section 1) > empty-planes: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [1.12ms] +(pass) structured goldens (test-plan section 1) > extension-composition-instances: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [4.98ms] +(pass) structured goldens (test-plan section 1) > extension-document-unicode: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.86ms] +(pass) structured goldens (test-plan section 1) > extension-unicode-key-order: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [1.11ms] +(pass) structured goldens (test-plan section 1) > extension-unicode-source-collision: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.42ms] +(pass) structured goldens (test-plan section 1) > fences-and-directives: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.39ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-attribute-numeric-stays-string: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.17ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-axis-default: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.17ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-axis-lowercased: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.12ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-bom: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.14ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-code-block-directive-safe: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.14ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-coordinates-attributes: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.25ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-crlf: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.16ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-decimal-negative-z: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.16ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-empty-body: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.09ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-empty-plane-body: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.12ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-escaped-quote-label: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.14ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-frontmatter-comments: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.20ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-indented-directive-is-body: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.16ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-leading-blank-lines: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.18ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-metadata-key-case-preserved: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.15ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-multi-plane: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.33ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-plane-prefix-not-directive: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.14ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-preamble-with-planes: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.24ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-repeated-directive-key-last-wins: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.16ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-single-plane-shorthand: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.14ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-version-1-0: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.12ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-z-scientific-notation: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.18ms] +(pass) structured goldens (test-plan section 1) > mixed-coordinates: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.27ms] +(pass) structured goldens (test-plan section 1) > nfc-source-keys: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.24ms] +(pass) structured goldens (test-plan section 1) > scalar-quoting: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.42ms] +(pass) structured goldens (test-plan section 1) > unicode-exact-values: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.47ms] +(pass) structured goldens (test-plan section 1) > whitespace-crlf-bom: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.15ms] +(pass) structured goldens (test-plan section 1) > canopy: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.39ms] +(pass) structured goldens (test-plan section 1) > shared-grove: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [3.16ms] +(pass) structured goldens (test-plan section 1) > worked-document: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.27ms] +(pass) structured goldens (test-plan section 1) > worked-numbers: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.17ms] +(pass) structured goldens (test-plan section 1) > worked-keys: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.22ms] +(pass) structured goldens (test-plan section 1) > the worked document has the metrics of SPEC.md 11.3.17 and the annotated bytes [1.04ms] +(pass) structured vectors (test-plan section 2) > the manifest holds 156 vectors: 30 with limits, 25 ok, 131 typed errors [0.13ms] +(pass) structured vectors (test-plan section 2) > container-truncated-header (D4) gives invalidContainer [0.17ms] +(pass) structured vectors (test-plan section 2) > container-version-2 (D5) gives unsupportedVersion [0.04ms] +(pass) structured vectors (test-plan section 2) > container-kind-0 (D6) gives unsupportedPayloadKind [0.03ms] +(pass) structured vectors (test-plan section 2) > container-kind-3 (D6) gives unsupportedPayloadKind [0.03ms] +(pass) structured vectors (test-plan section 2) > container-kind-4 (D6) gives unsupportedPayloadKind [0.07ms] +(pass) structured vectors (test-plan section 2) > container-kind-255 (D6) gives unsupportedPayloadKind [0.04ms] +(pass) structured vectors (test-plan section 2) > container-kind-3-bad-crc (D6) gives unsupportedPayloadKind [0.03ms] +(pass) structured vectors (test-plan section 2) > container-compression-2 (D7) gives unsupportedCompression [0.03ms] +(pass) structured vectors (test-plan section 2) > container-flags (D8) gives unsupportedFlags [0.02ms] +(pass) structured vectors (test-plan section 2) > container-reserved (D9) gives nonzeroReserved [0.02ms] +(pass) structured vectors (test-plan section 2) > container-decoded-over-emax (D10) gives oversizedOutput [0.04ms] +(pass) structured vectors (test-plan section 2) > container-decoded-over-2dmax-bad-crc (D10) gives oversizedOutput [0.03ms] +(pass) structured vectors (test-plan section 2) > container-encoded-zero (D11) gives lengthMismatch [0.02ms] +(pass) structured vectors (test-plan section 2) > container-decoded-zero (D11) gives lengthMismatch [0.02ms] +(pass) structured vectors (test-plan section 2) > container-encoded-mismatch (D11) gives lengthMismatch [0.03ms] +(pass) structured vectors (test-plan section 2) > container-uncompressed-lengths-differ (D11) gives lengthMismatch [0.03ms] +(pass) structured vectors (test-plan section 2) > container-trailing-byte (D11) gives lengthMismatch [0.03ms] +(pass) structured vectors (test-plan section 2) > container-crc-field (D12) gives checksumMismatch [0.02ms] +(pass) structured vectors (test-plan section 2) > container-crc-payload (D12) gives checksumMismatch [0.03ms] +(pass) structured vectors (test-plan section 2) > container-lzfse-portable (D13) gives compressionUnavailable [0.20ms] +(pass) structured vectors (test-plan section 2) > var-non-minimal (V3) gives invalidContainer [0.07ms] +(pass) structured vectors (test-plan section 2) > var-non-minimal-zero (V3) gives invalidContainer [0.03ms] +(pass) structured vectors (test-plan section 2) > var-five-bytes (Str1) gives lengthMismatch [0.03ms] +(pass) structured vectors (test-plan section 2) > var-four-continuation-truncated (V1) gives lengthMismatch [0.03ms] +(pass) structured vectors (test-plan section 2) > var-truncated (V1) gives lengthMismatch [0.03ms] +(pass) structured vectors (test-plan section 2) > var-max-length (Str1) gives lengthMismatch [0.04ms] +(pass) structured vectors (test-plan section 2) > count-metadata (C) gives lengthMismatch [0.04ms] +(pass) structured vectors (test-plan section 2) > count-planes (C) gives lengthMismatch [0.04ms] +(pass) structured vectors (test-plan section 2) > count-attributes (C) gives lengthMismatch [0.07ms] +(pass) structured vectors (test-plan section 2) > count-planes-edge-ok (C) gives ok [0.07ms] +(pass) structured vectors (test-plan section 2) > count-planes-over-pmax-and-remaining (C) gives lengthMismatch [0.03ms] +(pass) structured vectors (test-plan section 2) > str-remaining-plus-one (Str1) gives lengthMismatch [0.03ms] +(pass) structured vectors (test-plan section 2) > str-remaining-before-limit (Str1) gives lengthMismatch [0.09ms] +(pass) structured vectors (test-plan section 2) > str-two-byte-var-exact-ok (Str1) gives ok [0.08ms] +(pass) structured vectors (test-plan section 2) > str-two-byte-var-plus-one (Str1) gives lengthMismatch [0.05ms] +(pass) structured vectors (test-plan section 2) > str-over-record (Str2) gives oversizedRecord [0.04ms] +(pass) structured vectors (test-plan section 2) > str-preamble-over-r-minus-1 (S7) gives oversizedRecord [0.03ms] +(pass) structured vectors (test-plan section 2) > utf8-scalar-overlong (Str3) gives invalidUTF8 [0.26ms] +(pass) structured vectors (test-plan section 2) > utf8-scalar-surrogate (Str3) gives invalidUTF8 [0.03ms] +(pass) structured vectors (test-plan section 2) > utf8-scalar-above-max (Str3) gives invalidUTF8 [0.03ms] +(pass) structured vectors (test-plan section 2) > utf8-scalar-truncated (Str3) gives invalidUTF8 [0.03ms] +(pass) structured vectors (test-plan section 2) > utf8-scalar-lone-continuation (Str3) gives invalidUTF8 [0.03ms] +(pass) structured vectors (test-plan section 2) > utf8-scalar-ff (Str3) gives invalidUTF8 [0.03ms] +(pass) structured vectors (test-plan section 2) > utf8-body-split (Str3) gives invalidUTF8 [0.03ms] +(pass) structured vectors (test-plan section 2) > utf8-before-line-break (Str3) gives invalidUTF8 [0.03ms] +(pass) structured vectors (test-plan section 2) > scalar-lf (Str4) gives invalidDocument [0.07ms] +(pass) structured vectors (test-plan section 2) > scalar-cr (Str4) gives invalidDocument [0.03ms] +(pass) structured vectors (test-plan section 2) > flags-document-bit2 (S1) gives invalidContainer [0.03ms] +(pass) structured vectors (test-plan section 2) > flags-document-bit7 (S1) gives invalidContainer [0.03ms] +(pass) structured vectors (test-plan section 2) > flags-plane-bit7 (P1) gives invalidContainer [0.02ms] +(pass) structured vectors (test-plan section 2) > flags-plane-z-form-0 (P1) gives invalidContainer [0.02ms] +(pass) structured vectors (test-plan section 2) > number-f32-integer (N) gives invalidContainer [0.03ms] +(pass) structured vectors (test-plan section 2) > number-f32-negative-zero (N) gives invalidContainer [0.03ms] +(pass) structured vectors (test-plan section 2) > number-f32-nan (N) gives invalidDocument [0.03ms] +(pass) structured vectors (test-plan section 2) > number-f32-infinity (N) gives invalidDocument [0.02ms] +(pass) structured vectors (test-plan section 2) > number-f32-truncated (N) gives lengthMismatch [0.02ms] +(pass) structured vectors (test-plan section 2) > number-f64-truncated (N) gives lengthMismatch [0.02ms] +(pass) structured vectors (test-plan section 2) > number-f64-integer (N) gives invalidContainer [0.06ms] +(pass) structured vectors (test-plan section 2) > number-f64-binary32 (N) gives invalidContainer [0.05ms] +(pass) structured vectors (test-plan section 2) > number-f64-negative-zero (N) gives invalidContainer [0.04ms] +(pass) structured vectors (test-plan section 2) > number-f64-nan (N) gives invalidDocument [0.03ms] +(pass) structured vectors (test-plan section 2) > number-f64-negative-infinity (N) gives invalidDocument [0.03ms] +(pass) structured vectors (test-plan section 2) > number-f64-int-boundary (N) gives invalidContainer [0.03ms] +(pass) structured vectors (test-plan section 2) > number-f32-two-pow-27-ok (N) gives ok [0.07ms] +(pass) structured vectors (test-plan section 2) > number-f64-two-pow-53-plus-2-ok (N) gives ok [0.05ms] +(pass) structured vectors (test-plan section 2) > number-f32-for-f64-value (N) gives ok [0.04ms] +(pass) structured vectors (test-plan section 2) > order-metadata-decreasing (S6) gives invalidContainer [0.03ms] +(pass) structured vectors (test-plan section 2) > order-metadata-identical (S6) gives invalidContainer [0.03ms] +(pass) structured vectors (test-plan section 2) > order-nfc-instead-of-bytes (S6) gives invalidContainer [0.03ms] +(pass) structured vectors (test-plan section 2) > order-utf16-instead-of-bytes (S6) gives invalidContainer [0.05ms] +(pass) structured vectors (test-plan section 2) > order-equivalent-keys (S6b) gives invalidDocument [0.10ms] +(pass) structured vectors (test-plan section 2) > order-equivalent-kelvin (S6b) gives invalidDocument [0.05ms] +(pass) structured vectors (test-plan section 2) > order-attributes-decreasing (P7) gives invalidContainer [0.04ms] +(pass) structured vectors (test-plan section 2) > order-attributes-equivalent (P7a) gives invalidDocument [0.04ms] +(pass) structured vectors (test-plan section 2) > order-keys-ok (S6) gives ok [0.17ms] +(pass) structured vectors (test-plan section 2) > field-empty-version (S2) gives invalidDocument [0.09ms] +(pass) structured vectors (test-plan section 2) > axis-uppercase (R2) gives invalidDocument [0.03ms] +(pass) structured vectors (test-plan section 2) > axis-leading-space (R2) gives invalidDocument [0.03ms] +(pass) structured vectors (test-plan section 2) > axis-trailing-tab (R2) gives invalidDocument [0.04ms] +(pass) structured vectors (test-plan section 2) > axis-trailing-nbsp (R2) gives invalidDocument [0.03ms] +(pass) structured vectors (test-plan section 2) > axis-non-ascii-uppercase (R2) gives invalidDocument [0.03ms] +(pass) structured vectors (test-plan section 2) > axis-unicode-ok (R2) gives ok [0.04ms] +(pass) structured vectors (test-plan section 2) > metadata-key-colon (R3) gives invalidDocument [0.02ms] +(pass) structured vectors (test-plan section 2) > metadata-key-hash (R3) gives invalidDocument [0.03ms] +(pass) structured vectors (test-plan section 2) > metadata-key-leading-space (R3) gives invalidDocument [0.03ms] +(pass) structured vectors (test-plan section 2) > metadata-key-trailing-ideographic-space (R3) gives invalidDocument [0.03ms] +(pass) structured vectors (test-plan section 2) > metadata-key-axis (R3) gives invalidDocument [0.03ms] +(pass) structured vectors (test-plan section 2) > metadata-key-title (R3) gives invalidDocument [0.04ms] +(pass) structured vectors (test-plan section 2) > metadata-key-version (R3) gives invalidDocument [0.03ms] +(pass) structured vectors (test-plan section 2) > metadata-key-empty-ok (R3) gives ok [0.04ms] +(pass) structured vectors (test-plan section 2) > attribute-key-empty (R9) gives invalidDocument [0.03ms] +(pass) structured vectors (test-plan section 2) > attribute-key-uppercase (R9) gives invalidDocument [0.03ms] +(pass) structured vectors (test-plan section 2) > attribute-key-label (R9) gives invalidDocument [0.04ms] +(pass) structured vectors (test-plan section 2) > attribute-key-z (R9) gives invalidDocument [0.02ms] +(pass) structured vectors (test-plan section 2) > attribute-key-equals (R9) gives invalidDocument [0.02ms] +(pass) structured vectors (test-plan section 2) > attribute-key-space (R9) gives invalidDocument [0.02ms] +(pass) structured vectors (test-plan section 2) > attribute-key-tab (R9) gives invalidDocument [0.02ms] +(pass) structured vectors (test-plan section 2) > attribute-key-leading-nbsp (R9) gives invalidDocument [0.03ms] +(pass) structured vectors (test-plan section 2) > attribute-key-sigma (R9) gives invalidDocument [0.03ms] +(pass) structured vectors (test-plan section 2) > duplicate-z (L0) gives invalidDocument [0.03ms] +(pass) structured vectors (test-plan section 2) > preamble-without-planes (S8) gives invalidDocument [0.04ms] +(pass) structured vectors (test-plan section 2) > too-many-planes (S8) gives tooManyPlanes [0.03ms] +(pass) structured vectors (test-plan section 2) > segment-empty-preamble (G1) gives invalidDocument [0.02ms] +(pass) structured vectors (test-plan section 2) > segment-trailing-cr (G2) gives invalidDocument [0.03ms] +(pass) structured vectors (test-plan section 2) > segment-inner-cr-ok (G2) gives ok [0.06ms] +(pass) structured vectors (test-plan section 2) > segment-crlf (G3) gives invalidDocument [0.03ms] +(pass) structured vectors (test-plan section 2) > segment-leading-blank (G4) gives invalidDocument [0.03ms] +(pass) structured vectors (test-plan section 2) > segment-trailing-blank (G4) gives invalidDocument [0.02ms] +(pass) structured vectors (test-plan section 2) > segment-leading-nbsp-line (G4) gives invalidDocument [0.02ms] +(pass) structured vectors (test-plan section 2) > segment-trailing-ideographic-line (G4) gives invalidDocument [0.05ms] +(pass) structured vectors (test-plan section 2) > segment-plane-line (G5) gives invalidDocument [0.03ms] +(pass) structured vectors (test-plan section 2) > segment-plane-directive (G5) gives invalidDocument [0.04ms] +(pass) structured vectors (test-plan section 2) > segment-plane-tab (G5) gives invalidDocument [0.02ms] +(pass) structured vectors (test-plan section 2) > segment-indented-plane-ok (G5) gives ok [0.04ms] +(pass) structured vectors (test-plan section 2) > segment-planet-ok (G5) gives ok [0.05ms] +(pass) structured vectors (test-plan section 2) > segment-fence-backtick-tilde-ok (G5) gives ok [0.04ms] +(pass) structured vectors (test-plan section 2) > segment-fence-tilde-closed (G5) gives invalidDocument [0.22ms] +(pass) structured vectors (test-plan section 2) > segment-fence-nbsp-indented-ok (G5) gives ok [0.16ms] +(pass) structured vectors (test-plan section 2) > segment-fence-open-not-final (G6) gives invalidDocument [0.05ms] +(pass) structured vectors (test-plan section 2) > segment-fence-open-final-ok (G6) gives ok [0.09ms] +(pass) structured vectors (test-plan section 2) > segment-fence-open-preamble (G6) gives invalidDocument [0.04ms] +(pass) structured vectors (test-plan section 2) > segment-bom-nul-ok (Str3) gives ok [0.06ms] +(pass) structured vectors (test-plan section 2) > phase-q-apostrophe (Q) gives invalidDocument [0.16ms] +(pass) structured vectors (test-plan section 2) > phase-q-double-quote (Q) gives invalidDocument [0.06ms] +(pass) structured vectors (test-plan section 2) > phase-q-paired-ok (Q) gives ok [0.10ms] +(pass) structured vectors (test-plan section 2) > phase-q-spaced-pair-ok (Q) gives ok [0.24ms] +(pass) structured vectors (test-plan section 2) > phase-q-quoted-space-ok (Q) gives ok [0.22ms] +(pass) structured vectors (test-plan section 2) > phase-q-swallow-next (Q) gives invalidDocument [0.11ms] +(pass) structured vectors (test-plan section 2) > phase-q-inject-z (Q) gives invalidDocument [0.06ms] +(pass) structured vectors (test-plan section 2) > phase-q-inject-label (Q) gives invalidDocument [0.09ms] +(pass) structured vectors (test-plan section 2) > phase-q-uppercase-quoted (Q) gives invalidDocument [0.05ms] +(pass) structured vectors (test-plan section 2) > limit-record-below-3 (L1) gives oversizedRecord [0.04ms] +(pass) structured vectors (test-plan section 2) > limit-frontmatter-line (L2) gives oversizedRecord [0.03ms] +(pass) structured vectors (test-plan section 2) > limit-directive-line (L3) gives oversizedRecord [0.03ms] +(pass) structured vectors (test-plan section 2) > limit-text-length (L4) gives oversizedOutput [0.03ms] +(pass) structured vectors (test-plan section 2) > limit-lines (L5) gives tooManyLines [0.04ms] +(pass) structured vectors (test-plan section 2) > precedence-l0-over-l3 (L0) gives invalidDocument [0.03ms] +(pass) structured vectors (test-plan section 2) > precedence-l3-over-l4 (L3) gives oversizedRecord [0.03ms] +(pass) structured vectors (test-plan section 2) > precedence-l4-over-l5 (L4) gives oversizedOutput [0.03ms] +(pass) structured vectors (test-plan section 2) > precedence-s-order (S9) gives invalidDocument [0.04ms] +(pass) structured vectors (test-plan section 2) > precedence-utf8-before-limits (S4) gives invalidUTF8 [0.03ms] +(pass) structured vectors (test-plan section 2) > end-trailing-byte (S10) gives lengthMismatch [0.03ms] +(pass) structured vectors (test-plan section 2) > bound-2dmax-exact (L4) gives oversizedOutput [0.03ms] +(pass) structured vectors (test-plan section 2) > eighty-planes-emax-1000 (L4) gives ok [0.19ms] +(pass) structured vectors (test-plan section 2) > edges-maximumDecodedBytes-at (L4) gives ok [0.13ms] +(pass) structured vectors (test-plan section 2) > edges-maximumDecodedBytes-below (L4) gives oversizedOutput [0.03ms] +(pass) structured vectors (test-plan section 2) > edges-maximumLines-at (L5) gives ok [0.06ms] +(pass) structured vectors (test-plan section 2) > edges-maximumLines-below (L5) gives tooManyLines [0.03ms] +(pass) structured vectors (test-plan section 2) > edges-maximumPlanes-at (S8) gives ok [0.07ms] +(pass) structured vectors (test-plan section 2) > edges-maximumPlanes-below (S8) gives tooManyPlanes [0.03ms] +(pass) structured vectors (test-plan section 2) > edges-maximumRecordBytes-at (L3) gives ok [0.08ms] +(pass) structured vectors (test-plan section 2) > edges-maximumRecordBytes-below (L3) gives oversizedRecord [0.03ms] +(pass) structured vectors (test-plan section 2) > edges-maximumEncodedBytes-at (D2) gives ok [0.07ms] +(pass) structured vectors (test-plan section 2) > edges-maximumEncodedBytes-below (D2) gives oversizedInput [0.03ms] +(pass) structured vectors (test-plan section 2) > preamble-record-31 (Str2) gives ok [0.05ms] +(pass) structured vectors (test-plan section 2) > preamble-record-30 (Str2) gives oversizedRecord [0.02ms] +(pass) structured unit checklist (test-plan section 3) > Var encodes and decodes minimally at every byte-count boundary [17.20ms] +(pass) structured unit checklist (test-plan section 3) > Var rejections V1 to V3 [0.34ms] +(pass) structured unit checklist (test-plan section 3) > number forms follow SPEC.md 11.3.3 and every encoding decodes bit for bit [0.33ms] +(pass) structured unit checklist (test-plan section 3) > CRC check value, slicing against a bytewise reference, and container checksums [77.47ms] +(pass) structured unit checklist (test-plan section 3) > chunked UTF-8 validation agrees with whole-string validation at every chunk boundary [11.30ms] +(pass) structured unit checklist (test-plan section 3) > segment rules G1 to G6 on hand cases [0.43ms] +(pass) structured unit checklist (test-plan section 3) > segment scanner agrees with the 2.0 parser round trip on 100,000 random bodies [1376.81ms] +(pass) structured unit checklist (test-plan section 3) > canonical text metrics equal the 2.0 writer on every Example and 100,000 generated documents [8832.17ms] +(pass) structured unit checklist (test-plan section 3) > byte-order keys: code point order equals UTF-8 byte order, never UTF-16 order [80.31ms] +(pass) structured unit checklist (test-plan section 3) > key equivalence matches normalize("NFC") on decode [0.60ms] +(pass) structured unit checklist (test-plan section 3) > numeric-powers.json: 4,318 canonical spellings [12.72ms] +(pass) structured unit checklist (test-plan section 3) > containerInfo reports raw header fields without validating them [0.71ms] +(pass) structured unit checklist (test-plan section 3) > encodeTextContainer keeps the 2.0 binary writer's bytes and error order [11.32ms] +(pass) structured unit checklist (test-plan section 3) > writer edges: W1b, the exact Emax cap, compression after the self-check [0.65ms] +(pass) structured unit checklist (test-plan section 3) > TypeScript writer: lone surrogates, equivalent-key merge, dropped values and __proto__ [0.80ms] +(pass) structured unit checklist (test-plan section 3) > the portable utf8Length path, where String.prototype.isWellFormed is missing, writes the same bytes [5.25ms] +(pass) structured unit checklist (test-plan section 3) > decoded values have the 2.0 bounded decoder's shape [0.20ms] +(pass) structured unit checklist (test-plan section 3) > Unicode skew vectors outside Unicode 13.0 (recorded for the runtime's Unicode data) [1.74ms] +(pass) structured unit checklist (test-plan section 3) > size gate G6 (perf-gate section 4) holds for the Examples and the committed large-input sizes [82.82ms] +(pass) structured unit checklist (test-plan section 3) > the package index exports exactly the two new storage names [0.50ms] +(pass) TypeScript chunked decoding never carries bytes into the next string > Bun: a truncated last chunk and the following string both report invalidUTF8 [26.71ms] +(pass) TypeScript chunked decoding never carries bytes into the next string > Node: the same two-call sequences on the current sources [121.35ms] +(pass) differential properties at CI volume (test-plan section 4) > P1, P2 and P3 over 10,410 mutants of every anchor and the kind-2 Examples (seed 0x51a7) [2212.40ms] +(pass) differential properties at CI volume (test-plan section 4) > P5: encode(D, L) succeeds exactly when decode(encode(D, L), L) does, and returns the normalized D [97.00ms] +(pass) differential properties at CI volume (test-plan section 4) > P6: binary acceptance equals validate under standard and lowered limits, and decode equals the text decode [743.09ms] +(pass) cancellation, resource bounds and buffer ownership (test-plan section 5) > before entry: a pre-aborted signal fails every storage entry point with its reason [0.19ms] +(pass) cancellation, resource bounds and buffer ownership (test-plan section 5) > every decode and encode check point aborts with the reason and leaves no partial result [30.90ms] +(pass) cancellation, resource bounds and buffer ownership (test-plan section 5) > mid-CRC on a 64 MiB input [301.12ms] +(pass) cancellation, resource bounds and buffer ownership (test-plan section 5) > inside a 1 MiB scalar scan and between the UTF-8 chunks of an 8 MiB body [181.96ms] +(pass) cancellation, resource bounds and buffer ownership (test-plan section 5) > before plane k of 65,536 and in Phase L [809.00ms] +(pass) cancellation, resource bounds and buffer ownership (test-plan section 5) > before and after a Phase Q parse [0.59ms] +(pass) cancellation, resource bounds and buffer ownership (test-plan section 5) > mid-emission and mid-self-check on encode [1.05ms] +(pass) cancellation, resource bounds and buffer ownership (test-plan section 5) > the result walk checks by bytes inside one plane of 700,000 attributes (standard limits) [1260.83ms] +(pass) cancellation, resource bounds and buffer ownership (test-plan section 5) > the equivalence checks of long decomposed keys check by bytes, metadata and attributes (standard limits) [562.59ms] +(pass) cancellation, resource bounds and buffer ownership (test-plan section 5) > the writer checks by work inside large maps: merge tests, sorts, the plan and the emission [1659.27ms] +Bun memory growth / input: body a: 2.58, body é: 2.55, body €: 2.26, body 😀: 2.53, planes: 2.14, attributes: 1.23 +(pass) cancellation, resource bounds and buffer ownership (test-plan section 5) > memory on Bun: resident growth under 4 times the input for the 64 MiB worst cases and an 8 MiB body [2283.74ms] +Node memory growth / input: body a: 2.11, body é: 2.10, body €: 1.75, body 😀: 2.12, planes: 2.86, attributes: 1.04 +(pass) cancellation, resource bounds and buffer ownership (test-plan section 5) > memory on Node: the same cases on the current sources [2157.61ms] +(pass) cancellation, resource bounds and buffer ownership (test-plan section 5) > amplification: 65,536 quoted-key planes over R are rejected before any Phase Q parse, in under a second [259.52ms] +(pass) cancellation, resource bounds and buffer ownership (test-plan section 5) > Phase S allocates nothing per key: 2,000,000 minimal attributes stay far below 4 times the input [795.86ms] +(pass) cancellation, resource bounds and buffer ownership (test-plan section 5) > buffer ownership: overwriting or slicing the caller's buffer never changes a decoded value [2.23ms] +(pass) cancellation, resource bounds and buffer ownership (test-plan section 5) > a kind-2 file whose uncompressed container exceeds Emax or 2 Dmax stops at D10 before the CRC [0.20ms] + +test/composition.test.ts: +(pass) bounded self-contained composition > safe ID grammar, duplicates, absent roots and unreachable missing targets fail [1.95ms] +(pass) bounded self-contained composition > cycles, unused cycles, cached depth and repeated-traversal occurrence limits fail [1.00ms] +(pass) bounded self-contained composition > counts, unique source bytes and per-reference UTF-8 attributes are bounded [0.34ms] +(pass) bounded self-contained composition > constructors enforce absolute integer limits and legitimate zero reference limits [0.07ms] +(pass) bounded self-contained composition > public graph codecs validate plain-object composition policies before reading or writing [0.16ms] +(pass) bounded self-contained composition > strict envelopes, schemas, unknown fields and JSON types are rejected [0.87ms] +(pass) bounded self-contained composition > duplicate escaped keys, nested records, numeric fields and trailing JSON fail before object decoding [0.58ms] +(pass) bounded self-contained composition > embedded paths and malformed unused sources stay local parse errors [0.30ms] +(pass) bounded self-contained composition > profile and escaped JSON bounds count the complete envelope [0.40ms] +(pass) bounded self-contained composition > opaque attributes preserve controls, Unicode and prototype-looking keys [0.40ms] +(pass) bounded self-contained composition > pre-aborted graph construction and codecs propagate cancellation [0.12ms] +(pass) bounded self-contained composition > new reference writers sort Unicode scalar keys and strict JSON rejects equivalent duplicate keys [1.43ms] + +test/conformance.test.ts: +(pass) conformance vectors > at least one valid and one invalid vector exist [0.26ms] +(pass) conformance vectors > invalid-duplicate-plane.json: two planes sharing the same z value are rejected [0.14ms] +(pass) conformance vectors > invalid-duplicate-z-decimal-forms.json: z=0 and z=0.0 are the same position [0.03ms] +(pass) conformance vectors > invalid-frontmatter-no-colon.json: frontmatter line without a colon separator is rejected [0.03ms] +(pass) conformance vectors > invalid-frontmatter-unclosed.json: frontmatter block that is never closed is rejected [0.02ms] +(pass) conformance vectors > invalid-missing-frontmatter.json: document without a frontmatter fence is rejected +(pass) conformance vectors > invalid-missing-plane-position.json: a plane directive with no z attribute is rejected [0.02ms] +(pass) conformance vectors > invalid-missing-version.json: frontmatter without the 3md version key is rejected +(pass) conformance vectors > invalid-plane-token-no-equals.json: a plane attribute token with no equals sign is rejected (Swift throws; it is not skipped) [0.04ms] +(pass) conformance vectors > invalid-plane-x-not-number.json: a plane directive whose x is not a number is rejected [0.03ms] +(pass) conformance vectors > invalid-plane-z-not-number.json: a plane directive whose z is not a number is rejected [0.02ms] +(pass) conformance vectors > invalid-unterminated-quote.json: an unterminated quote in a directive is rejected [0.01ms] +(pass) conformance vectors > invalid-z-hex.json: hex z is rejected so Swift and TS agree +(pass) conformance vectors > invalid-z-infinity.json: z=inf is rejected (non-finite) +(pass) conformance vectors > invalid-z-nan.json: z=nan is rejected (non-finite, also closes the NaN dedup bypass) +(pass) conformance vectors > invalid-z-thousands-separator.json: thousands separators are rejected +(pass) conformance vectors > links-basic.json: a [[z=N]] reference resolves to the source z, target z, and existence [0.11ms] +(pass) conformance vectors > links-dangling.json: a reference to a missing plane is reported with targetExists false [0.01ms] +(pass) conformance vectors > links-decimal-target.json: a decimal target z is matched against a decimal plane z [0.01ms] +(pass) conformance vectors > links-invalid-ignored.json: non-finite targets and ordinary Markdown links are not cross-plane links +(pass) conformance vectors > links-multiple.json: multiple links in one body are returned left to right [0.01ms] +(pass) conformance vectors > links-with-text.json: a [[z=N|text]] reference captures the link text [0.01ms] +(pass) conformance vectors > valid-attribute-numeric-stays-string.json: non z/x/y attributes stay strings, not coerced [0.04ms] +(pass) conformance vectors > valid-axis-default.json: axis defaults to layer when omitted +(pass) conformance vectors > valid-axis-lowercased.json: axis value is trimmed and lowercased +(pass) conformance vectors > valid-bom.json: a leading UTF-8 BOM is stripped before parsing +(pass) conformance vectors > valid-code-block-directive-safe.json: a @plane line inside a fenced code block stays body text +(pass) conformance vectors > valid-coordinates-attributes.json: coordinates, label, and extra attributes are captured [0.02ms] +(pass) conformance vectors > valid-crlf.json: CRLF line endings are normalized to LF [0.01ms] +(pass) conformance vectors > valid-decimal-negative-z.json: z accepts negative and decimal values and keeps source order +(pass) conformance vectors > valid-empty-body.json: frontmatter only with no body yields no planes +(pass) conformance vectors > valid-empty-plane-body.json: a plane directive with no following content has an empty body +(pass) conformance vectors > valid-escaped-quote-label.json: escaped quotes inside a quoted label round-trip +(pass) conformance vectors > valid-frontmatter-comments.json: frontmatter skips comment and blank lines and strips quotes +(pass) conformance vectors > valid-indented-directive-is-body.json: an indented @plane is body, not a directive +(pass) conformance vectors > valid-leading-blank-lines.json: leading blank lines before the frontmatter fence are allowed +(pass) conformance vectors > valid-metadata-key-case-preserved.json: non-reserved frontmatter keys keep their case [0.01ms] +(pass) conformance vectors > valid-multi-plane.json: valid multi-plane document with title, metadata, and preamble [0.02ms] +(pass) conformance vectors > valid-plane-prefix-not-directive.json: @planex is not a directive; the doc is single-plane shorthand +(pass) conformance vectors > valid-preamble-with-planes.json: preamble is preserved when planes follow and quoted attribute keeps spaces [0.09ms] +(pass) conformance vectors > valid-repeated-directive-key-last-wins.json: a repeated directive key takes the last value [0.02ms] +(pass) conformance vectors > valid-single-plane-shorthand.json: single-plane shorthand wraps body at z=0 when no directives +(pass) conformance vectors > valid-version-1-0.json: the 1.0 format marker parses, with version reported as 1.0 +(pass) conformance vectors > valid-z-scientific-notation.json: scientific notation in z parses as a decimal [0.02ms] +(pass) round trip: parse -> serialize -> parse > valid-attribute-numeric-stays-string.json: non z/x/y attributes stay strings, not coerced [0.11ms] +(pass) round trip: parse -> serialize -> parse > valid-axis-default.json: axis defaults to layer when omitted [0.02ms] +(pass) round trip: parse -> serialize -> parse > valid-axis-lowercased.json: axis value is trimmed and lowercased [0.02ms] +(pass) round trip: parse -> serialize -> parse > valid-bom.json: a leading UTF-8 BOM is stripped before parsing [0.01ms] +(pass) round trip: parse -> serialize -> parse > valid-code-block-directive-safe.json: a @plane line inside a fenced code block stays body text [0.02ms] +(pass) round trip: parse -> serialize -> parse > valid-coordinates-attributes.json: coordinates, label, and extra attributes are captured [0.05ms] +(pass) round trip: parse -> serialize -> parse > valid-crlf.json: CRLF line endings are normalized to LF [0.02ms] +(pass) round trip: parse -> serialize -> parse > valid-decimal-negative-z.json: z accepts negative and decimal values and keeps source order [0.02ms] +(pass) round trip: parse -> serialize -> parse > valid-empty-body.json: frontmatter only with no body yields no planes [0.01ms] +(pass) round trip: parse -> serialize -> parse > valid-empty-plane-body.json: a plane directive with no following content has an empty body [0.01ms] +(pass) round trip: parse -> serialize -> parse > valid-escaped-quote-label.json: escaped quotes inside a quoted label round-trip [0.01ms] +(pass) round trip: parse -> serialize -> parse > valid-frontmatter-comments.json: frontmatter skips comment and blank lines and strips quotes [0.03ms] +(pass) round trip: parse -> serialize -> parse > valid-indented-directive-is-body.json: an indented @plane is body, not a directive [0.01ms] +(pass) round trip: parse -> serialize -> parse > valid-leading-blank-lines.json: leading blank lines before the frontmatter fence are allowed [0.01ms] +(pass) round trip: parse -> serialize -> parse > valid-metadata-key-case-preserved.json: non-reserved frontmatter keys keep their case [0.01ms] +(pass) round trip: parse -> serialize -> parse > valid-multi-plane.json: valid multi-plane document with title, metadata, and preamble [0.04ms] +(pass) round trip: parse -> serialize -> parse > valid-plane-prefix-not-directive.json: @planex is not a directive; the doc is single-plane shorthand +(pass) round trip: parse -> serialize -> parse > valid-preamble-with-planes.json: preamble is preserved when planes follow and quoted attribute keeps spaces [0.03ms] +(pass) round trip: parse -> serialize -> parse > valid-repeated-directive-key-last-wins.json: a repeated directive key takes the last value [0.01ms] +(pass) round trip: parse -> serialize -> parse > valid-single-plane-shorthand.json: single-plane shorthand wraps body at z=0 when no directives [0.01ms] +(pass) round trip: parse -> serialize -> parse > valid-version-1-0.json: the 1.0 format marker parses, with version reported as 1.0 [0.02ms] +(pass) round trip: parse -> serialize -> parse > valid-z-scientific-notation.json: scientific notation in z parses as a decimal [0.02ms] + +test/editing.test.ts: +(pass) portable atomic editing and diagnostics > adoption skips existing IDs, preserves id metadata and rejects unsafe or duplicated identities [0.80ms] +(pass) portable atomic editing and diagnostics > snapshots deep-copy and freeze values; reconstruction rejects a forged revision [0.77ms] +(pass) portable atomic editing and diagnostics > insert, move, remove and header replacements are one pure transaction [0.49ms] +(pass) portable atomic editing and diagnostics > later invalid operation rolls back; replacement identities, indices and missing targets are precise [0.51ms] +(pass) portable atomic editing and diagnostics > exact revisions reject NFC-equivalent bytes and expected-content budgets [0.32ms] +(pass) portable atomic editing and diagnostics > structurally typed snapshot revisions cannot replace the exact-content comparison [0.60ms] +(pass) portable atomic editing and diagnostics > operation, payload and final invalid-document policies return no partial result [0.34ms] +(pass) portable atomic editing and diagnostics > two NaN coordinate replacements reach invalid-document validation without a false duplicate [0.12ms] +(pass) portable atomic editing and diagnostics > graph patches allow forward definitions and final root swaps without flattening [1.61ms] +(pass) portable atomic editing and diagnostics > graph final failures identify the missing target or root and enforce scoped IDs [1.95ms] +(pass) portable atomic editing and diagnostics > source diagnostics carry only actual parser lines; value paths and truncation stay precise [0.55ms] +(pass) portable atomic editing and diagnostics > diagnostic payload preflight precedes expensive graph validation and retains owner paths [2.31ms] +(pass) portable atomic editing and diagnostics > all identity, transaction and diagnostic entry points honor pre-aborted signals [0.39ms] +(pass) portable atomic editing and diagnostics > public editor and diagnostic boundaries reject forged plain-object policies [0.30ms] + +test/storage.test.ts: +(pass) bounded portable storage > fixed envelope vectors match Swift and sliced data retains its byte offset [0.20ms] +(pass) bounded portable storage > existing Swift canopy and grove envelopes remain readable and byte-identical [2.05ms] +(pass) bounded portable storage > LZFSE is explicitly unavailable while unknown compression remains a different error [0.20ms] +(pass) bounded portable storage > header fields, checksums, trailing bytes and unsafe 64-bit lengths are checked [0.27ms] +(pass) bounded portable storage > the same header, checksum and payload checks hold for payload kind 2 [0.17ms] +(pass) bounded portable storage > resource constructors reject noninteger and nonpositive limits and accept any safe size [0.08ms] +(pass) bounded portable storage > a document past the old 64 MiB ceiling round-trips as text and as kind 2 [1563.62ms] +(pass) bounded portable storage > public storage boundaries validate structurally typed plain-object policies [0.25ms] +(pass) bounded portable storage > exact byte boundaries succeed; physical lines, planes and entire records are bounded [0.41ms] +(pass) bounded portable storage > preflight respects code fences and preserves the existing parser/serializer behavior [0.12ms] +(pass) bounded portable storage > direct lossy values and malformed decimals fail without changing legacy text APIs [2.76ms] +(pass) bounded portable storage > hostile interior and trailing ASCII whitespace remains exact through text and portable storage [23.68ms] +(pass) bounded portable storage > pre-aborted operations propagate the abort reason [0.22ms] +(pass) bounded portable storage > new canonical maps use Swift Unicode key equality, scalar order and original spelling [0.68ms] + +test/interchange-adapter.test.ts: +(pass) development files adapter limits > limit literals are judged by their correctly rounded IEEE double, like Swift and Rust [94.47ms] + +test/extensions.test.ts: +(pass) Swift portable extension conformance > all IEEE754 number vectors match Swift canonical formatting [0.94ms] +(pass) Swift portable extension conformance > Swift scientific notation starts strictly above the exact 2^53 boundary [0.03ms] +(pass) Swift portable extension conformance > canonical Unicode document text, envelope and revision are byte-identical to Swift [0.79ms] +(pass) Swift portable extension conformance > canonical composition preserves shared definitions, instance IDs and exact profile bytes [1.98ms] +(pass) Swift portable extension conformance > additive Swift Unicode key ordering and source-collision goldens match the portable codecs [1.51ms] +(pass) Swift portable extension conformance > identity adoption follows the Swift fixture and preserves ordinary id metadata [0.89ms] +(pass) Swift portable extension conformance > document transaction: atomic-coordinate-swap [0.49ms] +(pass) Swift portable extension conformance > document transaction: source-order-change [0.31ms] +(pass) Swift portable extension conformance > composition transaction: retarget-and-reorder-owner-instance [1.37ms] +(pass) Swift portable extension conformance > composition transaction: remove-one-repeated-target-instance [1.16ms] +(pass) Swift portable extension conformance > atomic failure: stale-document-revision [0.32ms] +(pass) Swift portable extension conformance > atomic failure: final-coordinate-conflict [0.14ms] +(pass) Swift portable extension conformance > atomic failure: changed-plane-identity [0.12ms] +(pass) Swift portable extension conformance > atomic failure: stale-composition-revision [0.05ms] +(pass) Swift portable extension conformance > atomic failure: final-reference-cycle [0.46ms] +(pass) Swift portable extension conformance > atomic failure: wrong-owner-reference-target [0.34ms] + +test/file-composition.test.ts: +(pass) explicit supplied-file composition > simple and repeated glyph links deduplicate files and refresh changed child bytes [1.47ms] +(pass) explicit supplied-file composition > nested parent paths and duplicate basenames resolve relative to each containing file [1.06ms] +(pass) explicit supplied-file composition > payload kind 1 children and bundles (the 2.0 binary bytes) still resolve [1.26ms] +(pass) explicit supplied-file composition > binary nested bundles retain unused entries, stable identities and opaque edges before new ledger edges [1.65ms] +(pass) explicit supplied-file composition > nested profile records use the outer composition policy while embedded ordinary records retain child bounds [1499.82ms] +(pass) explicit supplied-file composition > paths use NFC and Unicode scalar ordering rather than UTF16 or locale sorting [1.17ms] +(pass) explicit supplied-file composition > path grammar rejects escape, absolute paths, empty segments, controls and normalized aliases [0.58ms] +(pass) explicit supplied-file composition > strict ledger scanner rejects duplicate escaped keys, malformed JSON and invalid glyphs before values [0.43ms] +(pass) explicit supplied-file composition > missing files and malformed reachable storage retain distinct errors, unreachable storage is ignored [0.35ms] +(pass) explicit supplied-file composition > file cycles also fail when unused bundle entries form a cycle across files [0.88ms] +(pass) explicit supplied-file composition > supplied counts, original path bytes and reachable bytes use input limits before decoding [105.72ms] +(pass) explicit supplied-file composition > outer recognition applies child byte and line policies before its lowered plane ceiling [1.01ms] +(pass) explicit supplied-file composition > disconnected embedded ledgers use final entry depth rather than incoming file depth [0.93ms] +(pass) explicit supplied-file composition > repeated cached dependencies validate final depth after complete discovery [0.79ms] +(pass) explicit supplied-file composition > independent fixed64 discovery safety bounds disconnected file chains [35.29ms] +(pass) explicit supplied-file composition > lowered policies enforce final graph depth, imported entries, edges, conceptual traversal and final profile size [0.96ms] +(pass) explicit supplied-file composition > pre-aborted and cooperatively aborted operations propagate the caller's cancellation reason [0.16ms] +(pass) linked composition parity hardening > static resolve, ledger and resolvePath do not depend on their class binding [0.26ms] +(pass) linked composition parity hardening > owner directories keep parent, dot and grammar semantics [0.11ms] +(pass) linked composition parity hardening > a long owner path with many references resolves every reference in its directory [7.58ms] +(pass) linked composition parity hardening > refusals follow entry ID, then glyph, discovery order [1.03ms] +(pass) linked composition parity hardening > root and unreachable supplied paths use the ledger path grammar [0.73ms] +(pass) linked composition parity hardening > ledger escapes decode before path grammar [0.74ms] +(pass) linked composition parity hardening > self and alias cycles compare normalized paths [0.35ms] +(pass) linked composition parity hardening > a cached subtree is charged at its deeper occurrence against the discovery ceiling [41.05ms] +(pass) linked composition parity hardening > existing edges precede ledger edges; embedded ledgers resolve from their bundle folder; output rebundles [1.96ms] +(pass) linked composition parity hardening > the source-file attribute bound counts normalized UTF-8 bytes [10.47ms] +(pass) linked composition parity hardening > lowered policies charge original path bytes before path grammar; invalid limits are refused first [0.19ms] +(pass) linked composition parity hardening > an abort inside the ledger scanner propagates the caller's reason [1.91ms] +(pass) linked composition parity hardening > an abort inside the scalar path sort propagates the caller's reason [1.69ms] +(pass) early source-file attribute bound and long-directory owners > an over-bound ledger edge is refused while resolving, before later refusals [0.39ms] +(pass) early source-file attribute bound and long-directory owners > the attribute bound counts normalized directory prefix bytes [0.45ms] +(pass) early source-file attribute bound and long-directory owners > long-directory owners resolve repeated sources once and refuse over-bound targets at the first edge [189.50ms] + +test/links.test.ts: +(pass) links() > basic reference resolves source, target, and existence [0.85ms] +(pass) links() > captures optional link text [0.04ms] +(pass) links() > present-but-empty link text is the empty string [0.02ms] +(pass) links() > multiple links in one body are returned left to right [0.02ms] +(pass) links() > links across planes follow source order [0.02ms] +(pass) links() > dangling reference reports targetExists false [0.02ms] +(pass) links() > decimal target matches a decimal plane z [0.02ms] +(pass) links() > non-finite and non-link sequences are ignored [0.01ms] +(pass) links() > signed and exponent targets parse as finite decimals [0.02ms] +(pass) links() > a document with no links returns an empty array [0.01ms] +(pass) links() > danglingLinks filters only missing targets [0.05ms] +(pass) links() > linkGraph collapses repeated source-target pairs [0.10ms] +(pass) links() > linkGraph keeps dangling edge status [0.03ms] + + 431 pass + 0 fail + 764396 expect() calls +Ran 431 tests across 10 files. [27.81s] + ✔ Step 4 done (29.778s) + ▶️ Running task: rust + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.16s + Finished `test` profile [unoptimized + debuginfo] target(s) in 0.08s + Running unittests src/lib.rs (target/debug/deps/threemd-3e8d3a72ef8b0b84) + +running 18 tests +test checksum::tests::check_value_matches_the_specification ... ok +test structured::tests::number_forms_follow_the_table_and_decode_bit_exactly ... ok +test structured::tests::var_round_trips_at_every_size_boundary_and_rejects_v1_to_v3 ... ok +test structured::tests::equivalence_is_rejected_only_for_canonically_equal_distinct_keys ... ok +test structured::tests::line_feed_bits_mark_exactly_the_line_feeds ... ok +test structured::tests::checked_chars_stop_at_a_failed_check_and_keep_the_error ... ok +test structured::tests::long_key_hashes_and_nfc_forms_check_cancellation_on_their_input ... ok +test structured::tests::every_cancellation_check_cancels_decode_and_encode_without_a_result ... ok +test structured::tests::phase_s_checks_cancellation_within_long_keys_and_axes ... ok +test checksum::tests::slicing_matches_the_bytewise_reference_at_every_alignment ... ok +test structured::tests::cancellation_reaches_long_scans_and_every_plane ... ok +test structured::tests::lowercase_test_agrees_with_to_lowercase ... ok +test structured::tests::w2_checks_cancellation_between_short_keys_and_within_long_keys ... ok +test structured::tests::phase_q_normalizes_each_key_once_in_the_2_0_writer_order ... ok +test structured::tests::equivalence_matches_brute_force_and_compares_forms_only_when_hashes_meet ... ok +test structured::tests::cancellation_reaches_the_crc_of_a_64_mib_input ... ok +test structured::tests::phase_q_runs_only_after_phase_l_bounds_every_directive ... ok +test structured::tests::long_key_nfc_test_agrees_with_is_nfc_and_checks_every_chunk ... ok + +test result: ok. 18 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 4.50s + + Running tests/conformance.rs (target/debug/deps/conformance-283cd1b2cb105be9) + +running 1 test +test conformance_vectors_pass ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s + + Running tests/editing.rs (target/debug/deps/editing-997e6fa6b85c2c5a) + +running 9 tests +test direct_btree_maps_reject_ambiguous_canonically_equivalent_keys ... ok +test operation_payload_and_final_document_policies_are_enforced ... ok +test adopted_entries_report_the_specific_graph_error_that_adoption_wraps ... ok +test all_document_operations_preserve_source_order_and_header_fields ... ok +test identity_adoption_is_explicit_and_scoped ... ok +test document_operation_failures_are_structured_and_do_not_mutate_input ... ok +test graph_revision_roundtrip_diagnostics_and_cancellation ... ok +test all_composition_operations_validate_the_final_graph_atomically ... ok +test graph_failures_validate_counts_identity_and_reference_existence ... ok + +test result: ok. 9 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.01s + + Running tests/extensions.rs (target/debug/deps/extensions-4eb0504670bb68cf) + +running 15 tests +test binary_header_fields_and_corruption_are_rejected ... ok +test bounded_diagnostics_preserve_real_parser_lines_and_legacy_ids ... ok +test canonical_decimal_ties_use_nearest_even_shortest_spelling ... ok +test exact_utf8_revision_reopen_and_forged_snapshot_validation ... ok +test storage_resource_policies_and_faithful_value_validation ... ok +test graph_validates_unused_entries_cycles_and_resource_limits ... ok +test swift_unicode_key_order_and_source_collision_semantics_match ... ok +test original_extension_artifacts_and_lzfse_unavailability ... ok +test composition_json_is_strict_and_rejects_decoded_duplicate_keys ... ok +test cancellation_propagates_without_publishing_values ... ok +test swift_numeric_vectors_match_exact_storage_spelling ... ok +test swift_document_and_composition_goldens_are_byte_identical ... ok +test swift_adoption_transactions_and_failures_match_semantics ... ok +test every_signed_power_of_two_and_ten_matches_the_shared_canonical_spelling ... ok +test a_document_past_the_old_ceiling_round_trips ... ok + +test result: ok. 15 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 9.19s + + Running tests/file_composition.rs (target/debug/deps/file_composition-82fdc3545091eafc) + +running 30 tests +test owner_directory_resolution_keeps_parent_dot_and_grammar_semantics ... ok +test outer_recognition_preserves_child_byte_and_line_policy_precedence_over_planes ... ok +test ledger_is_strict_json_with_ascii_glyph_validation_before_duplicate_checks ... ok +test attribute_bound_counts_normalized_directory_prefix_bytes ... ok +test outer_profile_records_are_independent_of_child_record_policy ... ok +test over_bound_ledger_edge_is_refused_while_resolving_before_later_refusals ... ok +test existing_edges_precede_ledger_edges_and_embedded_ledgers_resolve_from_their_bundle_folder ... ok +test lowered_policy_charges_original_path_bytes_before_grammar_and_rejects_invalid_limits_first ... ok +test nested_relative_paths_keep_duplicate_basenames_and_use_scalar_order ... ok +test disconnected_embedded_ledgers_use_actual_entry_depth_and_repeated_cached_files ... ok +test final_depth_checks_include_cached_dependencies_and_cancelled_operations_are_atomic ... ok +test missing_files_and_file_cycles_include_ledgers_in_unused_bundle_entries ... ok +test supplied_and_resolved_policies_are_checked_before_returning_a_bundle ... ok +test self_and_alias_cycles_compare_normalized_paths ... ok +test repeated_links_are_deterministic_and_preserve_the_ordinary_document ... ok +test ledger_escapes_decode_before_path_grammar ... ok +test unreachable_content_is_ignored_but_every_supplied_path_is_validated ... ok +test refusals_follow_entry_id_then_glyph_discovery_order ... ok +test root_and_unreachable_supplied_paths_use_the_ledger_path_grammar ... ok +test resolver_output_rebundles_with_opaque_glyph_and_source_file_attributes ... ok +test repeated_cached_files_validate_final_depth_and_missing_discovery_precedence ... ok +test binary_children_and_nested_bundles_preserve_unused_entries_and_reference_ids ... ok +test source_file_attribute_bound_counts_normalized_utf8_bytes ... ok +test discovery_ceiling_is_the_standard_maximum_depth ... ok +test fixed_file_discovery_ceiling_bounds_disconnected_chains ... ok +test cached_subtree_is_charged_at_its_deeper_occurrence_against_the_discovery_ceiling ... ok +test long_owner_path_with_many_references_resolves_every_reference_in_its_directory ... ok +test long_directory_owners_resolve_repeated_sources_once_and_refuse_over_bound_targets_early ... ok +test project_paths_have_explicit_rules_and_bounded_standalone_work ... ok +test cancellation_from_another_thread_during_resolution_returns_no_result ... ok + +test result: ok. 30 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 1.65s + + Running tests/interchange.rs (target/debug/deps/interchange-1ce7f8e1fb0daa3c) + +running 5 tests +test bounded_parse_keeps_limits_and_explicit_cancellation ... ok +test source_unicode_aliases_keep_first_spelling_and_last_value_in_both_parsers ... ok +test legacy_serializer_preserves_quoted_apostrophes_and_boundary_whitespace ... ok +test raw_and_bounded_parsers_share_foundation_horizontal_whitespace ... ok +test large_unique_plane_sets_and_numeric_duplicate_equality_are_preserved ... ok + +test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.45s + + Running tests/structured.rs (target/debug/deps/structured-e12e8226d3e976db) + +running 24 tests +test p1_to_p4_every_mutant_reports_the_shared_outcome ... ignored, 102,600 decodes; run with --release -- --ignored +test container_info_reports_raw_fields_without_validation ... ok +test unicode_skew_vectors_follow_this_toolchains_data ... ok +test payload_kind_dispatch_and_the_decoded_length_bound ... ok +test a_truncated_tail_never_carries_into_the_next_string_or_call ... ok +test worked_examples_have_the_specified_bytes ... ok +test writer_cap_negative_zero_and_compression_follow_w1_to_w6 ... ok +test compositions_accept_kind_1_and_2_envelopes_and_refuse_kind_3 ... ok +test text_container_writer_keeps_the_2_0_bytes_and_error_order ... ok +test every_vector_reports_its_code_under_its_limits ... ok +test new_types_are_send_and_sync_and_codecs_run_from_32_threads ... ok +test var_prefixes_at_size_boundaries_round_trip_through_bodies ... ok +test every_golden_is_reproduced_byte_for_byte_and_decodes_to_the_text_decode ... ok +test number_forms_round_trip_bit_exactly_and_spell_canonically ... ok +test g6_kind_2_sizes_match_sizes_json ... ok +test keys_are_written_in_byte_order_and_equivalent_spellings_are_rejected ... ok +test chunked_utf8_validation_agrees_with_whole_string_validation ... ok +test cancellation_returns_no_value_and_leaves_inputs_reusable ... ok +test p5_p6_writer_acceptance_equals_validate_under_standard_limits ... ok +test p5_p6_writer_acceptance_equals_validate_under_lowered_limits ... ok +test metrics_equal_the_canonical_text_on_every_example ... ok +test p1_to_p4_mutants_report_the_shared_outcomes ... ok +test segment_rules_agree_with_the_text_round_trip_on_random_bodies ... ok +test metrics_equal_the_canonical_text_on_generated_documents ... ok + +test result: ok. 23 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 6.74s + + Running tests/structured_memory.rs (target/debug/deps/structured_memory-4f6ad24055334ee6) + +running 1 test +test kind_2_decoding_stays_under_four_times_the_input ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 9.36s + + Running unittests examples/interchange.rs (target/debug/examples/interchange-3e1831aec2fdc659) + +running 9 tests +test tests::hex_is_exact_and_rejects_uppercase_or_odd_input ... ok +test tests::document_adapter_edits_and_rejects_stale_patch_for_both_file_formats ... ok +test tests::malformed_protocol_keys_numbers_and_depth_precede_source_count ... ok +test tests::supplied_file_adapter_rejects_malformed_protocol_and_maps_core_errors ... ok +test tests::supplied_file_adapter_emits_reopenable_composition_outputs ... ok +test tests::composition_adapter_preserves_references_and_binary_parity ... ok +test tests::file_limits_are_strict_shapes_with_library_validated_values ... ok +test tests::supplied_file_count_precedes_source_shape_validation_but_not_top_level_validation ... ok +test tests::oversized_requests_are_consumed_and_responses_are_atomic ... ok + +test result: ok. 9 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.10s + + Finished `test` profile [unoptimized + debuginfo] target(s) in 0.02s + Doc-tests threemd + +running 4 tests +test src/storage.rs - storage::DocumentContainerInfo (line 216) ... ok +test src/lib.rs - axis (line 67) ... ok +test src/lib.rs - ParseError::code (line 178) ... ok +test src/lib.rs - (line 12) ... ok + +test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 1.47s + + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.02s + ✔ Step 5 done (34.550s) + ▶️ Running task: interchange +[0/1] Planning build +Building for debugging... +[0/3] Write swift-version--58304C5D6DBC2206.txt +Build of product 'threemd-interchange' complete! (0.24s) +{"cases":569,"compression":"none; optional Apple LZFSE excluded","imports":17991,"pairCounts":{"Rust -> Rust":1999,"Rust -> Swift":1999,"Rust -> TypeScript-Node":1999,"Swift -> Rust":1999,"Swift -> Swift":1999,"Swift -> TypeScript-Node":1999,"TypeScript-Node -> Rust":1999,"TypeScript-Node -> Swift":1999,"TypeScript-Node -> TypeScript-Node":1999},"passed":true,"producerConsumerPairs":9,"schema":"3md-interchange-receipt-1"} +Interchange evidence: /var/folders/5k/616qy7sj28l0d53k4c6w_4x00000gn/T/3md-interchange-1821610F-1D1B-407E-9F78-29D88EC6380A + ✔ Step 6 done (50.574s) + ▶️ Running task: element-bundle +Bundled 10 modules in 8ms + + three-md.js 48.84 KB (entry point) + +element bundle is current (48840 bytes, no storage code) + ✔ Step 7 done (46ms) + ▶️ Running task: editor +bun install v1.4.0 (34cbb9a40) + +Checked 183 installs across 192 packages (no changes) [47.00ms] +$ vscode-tmgrammar-test -g syntaxes/3md.tmLanguage.json -g syntaxes/3md-links.injection.json -g tests/grammars/markdown.tmLanguage.json "tests/*.3md" +grammar not found for "source.yaml" +grammar not found for "text.html.derivative" +grammar not found for "source.css" +grammar not found for "text.html.basic" +grammar not found for "source.ini" +grammar not found for "source.java" +grammar not found for "source.lua" +grammar not found for "source.makefile" +grammar not found for "source.perl" +grammar not found for "source.r" +grammar not found for "source.ruby" +grammar not found for "source.php" +grammar not found for "source.sql" +grammar not found for "source.asp.vb.net" +grammar not found for "text.xml" +grammar not found for "text.xml.xsl" +grammar not found for "source.batchfile" +grammar not found for "source.clojure" +grammar not found for "source.coffee" +grammar not found for "source.c" +grammar not found for "source.cpp" +grammar not found for "source.diff" +grammar not found for "source.dockerfile" +grammar not found for "text.git-commit" +grammar not found for "text.git-rebase" +grammar not found for "source.go" +grammar not found for "source.groovy" +grammar not found for "text.pug" +grammar not found for "source.ignore" +grammar not found for "source.js" +grammar not found for "source.js.regexp" +grammar not found for "source.json" +grammar not found for "source.json.comments" +grammar not found for "source.json.lines" +grammar not found for "source.css.less" +grammar not found for "source.objc" +grammar not found for "source.swift" +grammar not found for "source.css.scss" +grammar not found for "source.perl.6" +grammar not found for "source.powershell" +grammar not found for "source.python" +grammar not found for "source.julia" +grammar not found for "source.regexp.python" +grammar not found for "source.rust" +grammar not found for "source.scala" +grammar not found for "source.shell" +grammar not found for "source.ts" +grammar not found for "source.tsx" +grammar not found for "source.cs" +grammar not found for "source.fsharp" +grammar not found for "source.dart" +grammar not found for "text.html.handlebars" +grammar not found for "text.log" +grammar not found for "source.erlang" +grammar not found for "source.elixir" +grammar not found for "text.tex.latex" +grammar not found for "text.bibtex" +grammar not found for "source.twig" +grammar not found for "source.yang" +grammar not found for "source.abap" +grammar not found for "source.rst" +✓ tests/cross-plane-link.3md run successfuly. +✓ tests/frontmatter.3md run successfuly. +✓ tests/markdown-body.3md run successfuly. +✓ tests/plane-directive.3md run successfuly. + ✔ Step 8 done (539ms) +✅ Lane verify completed (8 steps in 3m 25.668s) +⊘ Skipped 4 unchanged spec(s) (use --force/--no-cache to re-validate all) + ℹ Cache: /Users/leif/Development/_CorvidLabs/3md-edit-preview/.specsync/hashes.json + +All specs unchanged — nothing to validate. +File coverage: 55/55 (100%) +LOC coverage: 21185/21185 (100%) +augur: config: loaded ./.augur.toml +augur gate · review (risk 36) +trust range: origin/leif/viewer-draft-navigation..HEAD +== lifecycle == +== contract == +== risk == +== provenance == +provenance degraded: policy is not satisfied +== atlas: off (Atlas publication was not enabled during adoption) == +trust gate passed (progressive provenance) diff --git a/docs/evidence/viewer-resolution/viewer-final.log b/docs/evidence/viewer-resolution/viewer-final.log new file mode 100644 index 00000000..9598ef45 --- /dev/null +++ b/docs/evidence/viewer-resolution/viewer-final.log @@ -0,0 +1,1385 @@ + +Running 130 tests using 2 workers + +(node:77726) Warning: The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set. +(Use `node --trace-warnings ...` to show where the warning was created) +(node:77727) Warning: The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set. +(Use `node --trace-warnings ...` to show where the warning was created) +[WebServer] ::1 - - [10/Oct/2026 12:35:08] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:08] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:08] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:08] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:08] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:08] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:08] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:08] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:08] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:08] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:08] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:08] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:08] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:08] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:08] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:08] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:08] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:08] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 2 [chromium] › viewer.spec.mjs:34:3 › viewer & editor (viewer.html) › opening the page shows lit cubes in the window (1.2s) +[WebServer] ::1 - - [10/Oct/2026 12:35:09] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:09] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:09] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:09] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:09] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 1 [chromium] › viewer.spec.mjs:78:3 › viewer & editor (viewer.html) › one cell has filled faces from every side, with gold edges and glyph fill (1.3s) +[WebServer] ::1 - - [10/Oct/2026 12:35:09] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:09] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:09] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:09] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:09] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:09] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:09] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:09] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:09] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:09] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:09] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:09] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:09] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 3 [chromium] › viewer.spec.mjs:152:3 › viewer & editor (viewer.html) › clicking a visible cube picks its Z slice and blank stage does not (773ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:09] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:09] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:09] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:09] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:09] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 4 [chromium] › viewer.spec.mjs:165:3 › viewer & editor (viewer.html) › renders the starter document with no console errors (726ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:09] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:09] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:09] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:09] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:09] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:10] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:10] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:10] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:10] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:10] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:10] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:10] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:10] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 5 [chromium] › viewer.spec.mjs:176:3 › viewer & editor (viewer.html) › editing the source re-renders live (1.1s) +[WebServer] ::1 - - [10/Oct/2026 12:35:10] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:10] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:10] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:10] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:10] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 6 [chromium] › viewer.spec.mjs:190:3 › viewer & editor (viewer.html) › invalid 3md shows an error without crashing (1.1s) +[WebServer] ::1 - - [10/Oct/2026 12:35:11] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:11] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:11] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:11] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:11] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:11] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:11] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:11] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:11] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:11] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:11] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:11] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:11] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 8 [chromium] › viewer.spec.mjs:218:3 › viewer & editor (viewer.html) › editor highlights syntax and numbers every line (731ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:11] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:11] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:11] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:11] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:11] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:12] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:12] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:12] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:12] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 7 [chromium] › viewer.spec.mjs:204:3 › viewer & editor (viewer.html) › loading an example populates the editor and viewer (1.2s) +[WebServer] ::1 - - [10/Oct/2026 12:35:12] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:12] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:12] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:12] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:12] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:12] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:12] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:12] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:12] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 9 [chromium] › viewer.spec.mjs:246:3 › viewer & editor (viewer.html) › Tab indents and Enter continues a list (737ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:12] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:12] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:12] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:12] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:12] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:12] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:12] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:12] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:12] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 10 [chromium] › viewer.spec.mjs:262:3 › viewer & editor (viewer.html) › clicking a plane outline chip focuses that plane (927ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:13] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:13] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:13] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:13] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:13] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 11 [chromium] › viewer.spec.mjs:273:3 › viewer & editor (viewer.html) › the highlight backdrop scrolls with the textarea (tall document) (752ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:13] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:13] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:13] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:13] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:13] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:13] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:13] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:13] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:13] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:13] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:13] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:13] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:13] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 12 [chromium] › viewer.spec.mjs:290:3 › viewer & editor (viewer.html) › smart-key edits are undoable and never corrupt the buffer (909ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:13] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:13] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:13] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:13] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:13] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:14] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:14] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:14] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:14] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 13 [chromium] › viewer.spec.mjs:311:3 › viewer & editor (viewer.html) › validity state is machine-readable via data attributes (1.0s) +[WebServer] ::1 - - [10/Oct/2026 12:35:14] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:14] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:14] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:14] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:14] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:14] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:14] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:14] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:14] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 14 [chromium] › viewer.spec.mjs:337:3 › viewer & editor (viewer.html) › Tab does not trap keyboard focus (Esc then Tab leaves the editor) (799ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:14] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:14] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:14] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:14] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:14] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 15 [chromium] › viewer.spec.mjs:351:3 › viewer & editor (viewer.html) › agent API validates and reports structured state (678ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:15] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:15] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:15] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:15] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:15] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:15] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:15] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:15] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:15] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:15] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:15] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:15] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:15] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 16 [chromium] › viewer.spec.mjs:364:3 › viewer & editor (viewer.html) › validate(src) is side-effect-free and reports the error code (708ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:15] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:15] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:15] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:15] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:15] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:15] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:15] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:15] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:15] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 17 [chromium] › viewer.spec.mjs:380:3 › viewer & editor (viewer.html) › repository search opens the 24-generation Conway document (1.2s) +[WebServer] ::1 - - [10/Oct/2026 12:35:16] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:16] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:16] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:16] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:16] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:16] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:16] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:16] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:16] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 18 [chromium] › viewer.spec.mjs:395:3 › viewer & editor (viewer.html) › kind 2 canopy opens as text in the element (1.1s) +[WebServer] ::1 - - [10/Oct/2026 12:35:16] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:16] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:16] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:16] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:16] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:16] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:16] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:16] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:16] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 19 [chromium] › viewer.spec.mjs:412:3 › viewer & editor (viewer.html) › linked village search resolves the folder (1.1s) +[WebServer] ::1 - - [10/Oct/2026 12:35:17] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:17] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:17] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:17] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:17] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:17] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:17] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:17] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:17] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 20 [chromium] › viewer.spec.mjs:426:3 › viewer & editor (viewer.html) › a composition profile shows the root and can switch entries (1.5s) +[WebServer] ::1 - - [10/Oct/2026 12:35:18] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:18] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:18] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:18] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:18] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:18] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:18] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:18] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:18] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 21 [chromium] › viewer.spec.mjs:441:3 › viewer & editor (viewer.html) › markdown headings become planes and a plane search opens one (1.4s) +[WebServer] ::1 - - [10/Oct/2026 12:35:18] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:18] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:18] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:18] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:18] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:18] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:18] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:18] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:18] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 22 [chromium] › viewer.spec.mjs:458:3 › viewer & editor (viewer.html) › desktop layout keeps files beside a panel that switches Edit and Preview (932ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:19] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:19] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:19] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:19] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:19] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:19] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:19] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:19] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:19] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 24 [chromium] › viewer.spec.mjs:546:3 › viewer & editor (viewer.html) › orbiting about 1400 gpu cubes stays interactive (821ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:19] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:19] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:19] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:19] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:19] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:20] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:20] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:20] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:20] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 23 [chromium] › viewer.spec.mjs:514:3 › viewer & editor (viewer.html) › cubes tab draws a fenced grid as translucent cubes (1.3s) +[WebServer] ::1 - - [10/Oct/2026 12:35:20] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:20] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:20] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:20] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:20] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:20] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:20] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:20] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:20] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 25 [chromium] › viewer.spec.mjs:591:3 › viewer & editor (viewer.html) › narrow layout switches Files and the document, and Edit and Preview still switch (1.1s) +[WebServer] ::1 - - [10/Oct/2026 12:35:20] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:20] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:20] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:20] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:20] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 26 [chromium] › viewer.spec.mjs:627:3 › viewer & editor (viewer.html) › an empty document reads as a neutral prompt, not a red error (960ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:21] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:21] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:21] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:21] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:21] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:21] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:21] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:21] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:21] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:21] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:21] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:21] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:21] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 27 [chromium] › viewer.spec.mjs:645:3 › viewer & editor (viewer.html) › axis lint warns on a TYPO but not on a valid free-string semantic axis (650ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:21] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:21] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:21] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:21] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:21] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 28 [chromium] › viewer.spec.mjs:671:3 › viewer & editor (viewer.html) › the page has no render-mode switch and does not autoplay (722ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:21] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:21] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:21] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:21] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:21] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:21] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:21] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:21] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:21] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:22] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:22] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:22] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:22] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 29 [chromium] › viewer.spec.mjs:692:3 › viewer & editor (viewer.html) › the agent schema lists error codes and the axis-to-mode map (759ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:22] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:22] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:22] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:22] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:22] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:22] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:22] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:22] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:22] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 30 [chromium] › viewer.spec.mjs:702:3 › viewer & editor (viewer.html) › dangling cross-plane links are flagged as a non-fatal warning (1.0s) +[WebServer] ::1 - - [10/Oct/2026 12:35:22] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:22] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:22] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:22] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:22] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:23] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:23] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:23] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:23] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 31 [chromium] › viewer.spec.mjs:713:3 › viewer & editor (viewer.html) › a corrupt share hash signals a decode error (not a silent starter) (938ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:23] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:23] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:23] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:23] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:23] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 32 [chromium] › viewer.spec.mjs:722:3 › viewer & editor (viewer.html) › the embedded agent schema marks axis optional, only 3md required (720ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:23] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:23] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:23] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:23] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:23] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:23] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:23] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:23] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:23] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:23] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:23] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:23] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:23] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 33 [chromium] › viewer.spec.mjs:729:3 › viewer & editor (viewer.html) › invalid doc clears stale plane/axis data on the badge (1.0s) +[WebServer] ::1 - - [10/Oct/2026 12:35:24] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:24] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:24] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:24] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:24] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 34 [chromium] › viewer.spec.mjs:742:3 › viewer & editor (viewer.html) › an invalid document flags the offending line and the badge (998ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:24] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:24] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:24] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:24] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:24] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:24] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:24] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:24] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:24] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:24] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:24] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:24] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:24] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 35 [chromium] › viewer.spec.mjs:755:3 › viewer & editor (viewer.html) › a shared hash link restores the document (687ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:24] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:24] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:24] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:24] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:24] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:25] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:25] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:25] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:25] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 36 [chromium] › viewer.spec.mjs:766:3 › viewer & editor (viewer.html) › camera buttons and keyboard orbit, zoom, and fit without changing the document (937ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:25] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:25] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:25] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:25] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:25] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 37 [chromium] › viewer.spec.mjs:795:3 › viewer & editor (viewer.html) › full camera turns cross both poles continuously and retain geometry (755ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:25] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:25] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:25] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:25] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:25] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:25] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:25] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:25] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:25] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:25] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:25] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:25] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:25] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 38 [chromium] › viewer.spec.mjs:843:3 › viewer & editor (viewer.html) › pan tools and modified dragging move only the camera and Fit recenters (830ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:26] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:26] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:26] "GET /assets/tokens.css HTTP/1.1" 200 - + ✓ 39 [chromium] › viewer.spec.mjs:874:3 › viewer & editor (viewer.html) › two fingers pan and pinch and a cancelled gesture cannot select a slice (668ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:26] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:26] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:26] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:26] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:26] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:26] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:26] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:26] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:26] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:26] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:26] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:26] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:26] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:26] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:26] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 41 [chromium] › viewer.spec.mjs:965:3 › viewer & editor (viewer.html) › phone layout leaves room for cubes and keeps controls outside the drawing (700ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:27] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:27] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:27] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:27] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:27] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:27] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:27] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:27] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:27] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 42 [chromium] › viewer.spec.mjs:987:3 › viewer & editor (viewer.html) › Document disclosure dismisses with Escape and both downloads preserve the document (879ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:27] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:27] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:27] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:27] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:27] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:28] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:28] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:28] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:28] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 43 [chromium] › viewer.spec.mjs:1024:3 › viewer & editor (viewer.html) › a prose document offers Preview without replacing its source (815ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:28] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:28] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:28] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:28] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:28] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:29] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:29] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:29] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:29] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 44 [chromium] › viewer.spec.mjs:1042:3 › viewer & editor (viewer.html) › slice navigation keeps the selected plane in a single scrolling row (660ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:29] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:29] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:29] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:29] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:29] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 40 [chromium] › viewer.spec.mjs:897:3 › viewer & editor (viewer.html) › browser camera projects and picks the shared native parity fixture (3.5s) +[WebServer] ::1 - - [10/Oct/2026 12:35:29] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:29] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:29] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:29] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:29] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:29] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:29] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:29] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:29] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:30] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:30] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:30] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:30] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 45 [chromium] › viewer.spec.mjs:1064:3 › viewer & editor (viewer.html) › a GitHub load shows busy state and recovers after a rate limit (793ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:30] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:30] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:30] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:30] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:30] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:30] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:30] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:30] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:30] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 46 [chromium] › viewer.spec.mjs:1084:3 › viewer & editor (viewer.html) › GPU unavailability explains how to keep reading in Preview (682ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:30] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:30] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:30] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:30] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:30] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:30] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:30] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:30] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:30] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 48 [chromium] › viewer.spec.mjs:1143:3 › viewer & editor (viewer.html) › composition entry switches preserve each draft without copying it into another entry (842ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:31] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:31] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:31] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:31] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:31] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 47 [chromium] › viewer.spec.mjs:1100:3 › viewer & editor (viewer.html) › file switches preserve edited, invalid, and empty drafts with caret and slice (1.2s) +[WebServer] ::1 - - [10/Oct/2026 12:35:31] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:31] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:31] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:31] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:31] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:31] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:31] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:31] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:31] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:31] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:31] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:31] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:31] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 49 [chromium] › viewer.spec.mjs:1170:3 › viewer & editor (viewer.html) › linked entries and file navigation share the same draft (817ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:32] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:32] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:32] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:32] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:32] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 50 [chromium] › viewer.spec.mjs:1195:3 › viewer & editor (viewer.html) › search and packing use drafts rather than original file text (834ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:32] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:32] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:32] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:32] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:32] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:32] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:32] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:32] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:32] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:32] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:32] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:32] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:32] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 51 [chromium] › viewer.spec.mjs:1212:3 › viewer & editor (viewer.html) › file filtering, keyboard selection, and phone opens reveal the document (797ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:33] "GET /viewer.html?src=original-document.3md&theme=dark HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:33] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:33] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:33] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:33] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:33] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:33] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:33] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:33] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 52 [chromium] › viewer.spec.mjs:1240:3 › viewer & editor (viewer.html) › a failed local open preserves the collection and current draft (1.2s) +[WebServer] ::1 - - [10/Oct/2026 12:35:33] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:33] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:33] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:33] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:33] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:33] "GET /viewer.html?theme=dark HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:33] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:33] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:33] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:33] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:33] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:33] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:33] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:33] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:34] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:34] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:34] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:34] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:34] "GET /viewer.html?theme=dark HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:34] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:34] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:34] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:34] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:34] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:34] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:34] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:34] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 53 [chromium] › viewer.spec.mjs:1259:3 › viewer & editor (viewer.html) › explicit document navigation removes stale source queries and reloads the chosen source (1.5s) +[WebServer] ::1 - - [10/Oct/2026 12:35:34] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:34] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:34] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:34] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:34] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:34] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:34] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:34] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:34] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 55 [chromium] › viewer.spec.mjs:1316:3 › Sculpt Slice parity › grid edits preserve CRLF, labels, prose and downloads exactly (780ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:35] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:35] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:35] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:35] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:35] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:35] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:35] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:35] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:35] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:35] "GET /viewer.html HTTP/1.1" 304 - + ✓ 56 [chromium] › viewer.spec.mjs:1328:3 › Sculpt Slice parity › keyboard cells, grid zoom, previous overlay and shared WebGL reference (885ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:36] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:36] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:36] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:36] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:36] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 54 [chromium] › viewer.spec.mjs:1298:3 › Sculpt Slice parity › shared native strokes, clipped brushes, four-neighbor fill and no-op undo (2.9s) +[WebServer] ::1 - - [10/Oct/2026 12:35:36] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:36] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:36] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:36] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:36] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:37] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:37] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:37] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:37] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:37] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:37] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:37] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:37] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 57 [chromium] › viewer.spec.mjs:1341:3 › Sculpt Slice parity › source typing and Slice share undo and retain it across file navigation (1.4s) +[WebServer] ::1 - - [10/Oct/2026 12:35:37] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:37] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:37] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:37] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:37] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:37] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:37] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:37] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:37] "GET /gallery-data.json HTTP/1.1" 200 - + ✓ 59 [chromium] › viewer.spec.mjs:1361:3 › Sculpt Slice parity › phone Slice tools and axis controls stay usable without horizontal page overflow (1.0s) +[WebServer] ::1 - - [10/Oct/2026 12:35:38] "GET /viewer.html HTTP/1.1" 200 - + ✓ 58 [chromium] › viewer.spec.mjs:1353:3 › Sculpt Slice parity › unsupported grids stay readable and budget rejection restores the full stroke (2.2s) +[WebServer] ::1 - - [10/Oct/2026 12:35:38] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:38] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:38] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:38] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:38] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:38] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:38] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:38] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:38] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:38] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:38] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:38] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:38] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:38] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:38] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:38] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:38] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 60 [chromium] › viewer.spec.mjs:1370:3 › Sculpt Slice parity › 2D editing works with an unavailable WebGL reference (716ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:39] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:39] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:39] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:39] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:39] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 61 [chromium] › viewer.spec.mjs:1375:3 › Sculpt Slice parity › axis inverse, finite inputs, pan steps and Fit leave source and geometry intact (881ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:39] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:39] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:39] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:39] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:39] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:39] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:39] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:39] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:39] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:39] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:39] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:39] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:39] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 63 [chromium] › viewer.spec.mjs:1411:1 › Slice navigation finishes a touch stroke and ignores its late pointer movement (963ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:40] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:40] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:40] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:40] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:40] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:40] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:40] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:40] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:40] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 64 [chromium] › viewer.spec.mjs:1427:3 › shared cube drawable stays sharp through view/viewport changes at 1x density (2.4s) +[WebServer] ::1 - - [10/Oct/2026 12:35:42] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:42] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:42] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:42] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:42] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:43] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:43] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:43] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:43] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 65 [chromium] › viewer.spec.mjs:1427:3 › shared cube drawable stays sharp through view/viewport changes at 2x density (2.6s) +(node:77903) Warning: The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set. +(Use `node --trace-warnings ...` to show where the warning was created) + ✓ 62 [chromium] › viewer.spec.mjs:1389:1 › Slice history drops only old snapshots at the per-draft and collection budgets (6.7s) +(node:77913) Warning: The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set. +(Use `node --trace-warnings ...` to show where the warning was created) +[WebServer] ::1 - - [10/Oct/2026 12:35:46] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:46] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:46] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:46] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:46] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:46] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:46] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:46] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:46] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 66 [webkit] › viewer.spec.mjs:34:3 › viewer & editor (viewer.html) › opening the page shows lit cubes in the window (694ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:47] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:47] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:47] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:47] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:47] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:47] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:47] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:47] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:47] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:47] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:47] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:47] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:47] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:47] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:47] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:47] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:47] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:47] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 68 [webkit] › viewer.spec.mjs:152:3 › viewer & editor (viewer.html) › clicking a visible cube picks its Z slice and blank stage does not (593ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:47] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:47] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:47] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:47] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:47] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:47] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:47] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:47] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:47] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 67 [webkit] › viewer.spec.mjs:78:3 › viewer & editor (viewer.html) › one cell has filled faces from every side, with gold edges and glyph fill (1.1s) + ✓ 69 [webkit] › viewer.spec.mjs:165:3 › viewer & editor (viewer.html) › renders the starter document with no console errors (457ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:47] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:47] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:47] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:47] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:47] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:47] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:47] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:47] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:47] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:48] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:48] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:48] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:48] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:48] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:48] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:48] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:48] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:48] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 71 [webkit] › viewer.spec.mjs:190:3 › viewer & editor (viewer.html) › invalid 3md shows an error without crashing (938ms) + ✓ 70 [webkit] › viewer.spec.mjs:176:3 › viewer & editor (viewer.html) › editing the source re-renders live (1.0s) +[WebServer] ::1 - - [10/Oct/2026 12:35:49] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:49] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:49] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:49] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:49] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:49] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:49] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:49] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:49] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:49] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:49] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:49] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:49] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:49] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:49] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:49] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:49] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:49] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 73 [webkit] › viewer.spec.mjs:218:3 › viewer & editor (viewer.html) › editor highlights syntax and numbers every line (718ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:49] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:49] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:49] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:49] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:49] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:49] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:49] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:49] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:49] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 72 [webkit] › viewer.spec.mjs:204:3 › viewer & editor (viewer.html) › loading an example populates the editor and viewer (1.1s) + ✓ 74 [webkit] › viewer.spec.mjs:246:3 › viewer & editor (viewer.html) › Tab indents and Enter continues a list (592ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:50] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:50] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:50] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:50] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:50] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:50] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:50] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:50] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:50] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:50] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:50] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:50] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:50] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:50] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:50] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:50] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:50] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:50] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 75 [webkit] › viewer.spec.mjs:262:3 › viewer & editor (viewer.html) › clicking a plane outline chip focuses that plane (848ms) + ✓ 76 [webkit] › viewer.spec.mjs:273:3 › viewer & editor (viewer.html) › the highlight backdrop scrolls with the textarea (tall document) (746ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:50] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:50] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:50] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:50] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:50] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:51] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:51] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:51] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:51] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:51] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:51] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:51] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:51] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:51] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:51] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:51] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:51] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:51] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 77 [webkit] › viewer.spec.mjs:290:3 › viewer & editor (viewer.html) › smart-key edits are undoable and never corrupt the buffer (832ms) + ✓ 78 [webkit] › viewer.spec.mjs:311:3 › viewer & editor (viewer.html) › validity state is machine-readable via data attributes (921ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:51] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:51] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:51] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:51] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:51] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:51] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:51] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:51] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:51] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:52] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:52] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:52] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:52] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:52] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:52] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:52] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:52] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:52] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 80 [webkit] › viewer.spec.mjs:351:3 › viewer & editor (viewer.html) › agent API validates and reports structured state (559ms) + ✓ 79 [webkit] › viewer.spec.mjs:337:3 › viewer & editor (viewer.html) › Tab does not trap keyboard focus (Esc then Tab leaves the editor) (765ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:52] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:52] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:52] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:52] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:52] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:52] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:52] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:52] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:52] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:52] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:52] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:52] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:52] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:52] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:52] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:52] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:52] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:52] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 81 [webkit] › viewer.spec.mjs:364:3 › viewer & editor (viewer.html) › validate(src) is side-effect-free and reports the error code (574ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:53] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:53] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:53] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:53] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:53] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:53] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:53] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:53] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:53] "GET /gallery-data.json HTTP/1.1" 200 - + ✓ 82 [webkit] › viewer.spec.mjs:380:3 › viewer & editor (viewer.html) › repository search opens the 24-generation Conway document (1.0s) +[WebServer] ::1 - - [10/Oct/2026 12:35:53] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:53] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:53] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:53] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:53] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:53] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:53] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:53] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:53] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 83 [webkit] › viewer.spec.mjs:395:3 › viewer & editor (viewer.html) › kind 2 canopy opens as text in the element (1.1s) +[WebServer] ::1 - - [10/Oct/2026 12:35:54] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:54] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:54] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:54] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:54] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:54] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:54] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:54] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:54] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 84 [webkit] › viewer.spec.mjs:412:3 › viewer & editor (viewer.html) › linked village search resolves the folder (1.0s) +[WebServer] ::1 - - [10/Oct/2026 12:35:54] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:54] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:54] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:54] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:54] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:54] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:54] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:54] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:54] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 85 [webkit] › viewer.spec.mjs:426:3 › viewer & editor (viewer.html) › a composition profile shows the root and can switch entries (1.3s) +[WebServer] ::1 - - [10/Oct/2026 12:35:55] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:55] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:55] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:55] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:55] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:55] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:55] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:55] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:55] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 86 [webkit] › viewer.spec.mjs:441:3 › viewer & editor (viewer.html) › markdown headings become planes and a plane search opens one (1.4s) +[WebServer] ::1 - - [10/Oct/2026 12:35:56] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:56] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:56] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:56] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:56] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:56] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:56] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:56] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:56] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 87 [webkit] › viewer.spec.mjs:458:3 › viewer & editor (viewer.html) › desktop layout keeps files beside a panel that switches Edit and Preview (847ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:56] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:56] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:56] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:56] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:56] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:56] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:56] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:56] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:56] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 89 [webkit] › viewer.spec.mjs:546:3 › viewer & editor (viewer.html) › orbiting about 1400 gpu cubes stays interactive (644ms) + ✓ 88 [webkit] › viewer.spec.mjs:514:3 › viewer & editor (viewer.html) › cubes tab draws a fenced grid as translucent cubes (1.2s) +[WebServer] ::1 - - [10/Oct/2026 12:35:57] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:57] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:57] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:57] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:57] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:57] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:57] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:57] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:57] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:57] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:57] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:57] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:57] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:57] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:57] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:57] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:57] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:57] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 90 [webkit] › viewer.spec.mjs:591:3 › viewer & editor (viewer.html) › narrow layout switches Files and the document, and Edit and Preview still switch (809ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:57] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:57] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:57] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:57] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:57] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:57] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:57] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:57] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:57] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 91 [webkit] › viewer.spec.mjs:627:3 › viewer & editor (viewer.html) › an empty document reads as a neutral prompt, not a red error (947ms) + ✓ 92 [webkit] › viewer.spec.mjs:645:3 › viewer & editor (viewer.html) › axis lint warns on a TYPO but not on a valid free-string semantic axis (493ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:58] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:58] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:58] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:58] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:58] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:58] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:58] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:58] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:58] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:58] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:58] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:58] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:58] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:58] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:58] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:58] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:58] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:58] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 93 [webkit] › viewer.spec.mjs:671:3 › viewer & editor (viewer.html) › the page has no render-mode switch and does not autoplay (522ms) + ✓ 94 [webkit] › viewer.spec.mjs:692:3 › viewer & editor (viewer.html) › the agent schema lists error codes and the axis-to-mode map (536ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:58] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:58] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:58] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:58] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:58] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:58] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:58] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:58] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:58] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:58] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:58] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:58] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:58] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:58] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:58] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:58] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:58] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:58] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 95 [webkit] › viewer.spec.mjs:702:3 › viewer & editor (viewer.html) › dangling cross-plane links are flagged as a non-fatal warning (941ms) + ✓ 96 [webkit] › viewer.spec.mjs:713:3 › viewer & editor (viewer.html) › a corrupt share hash signals a decode error (not a silent starter) (795ms) +[WebServer] ::1 - - [10/Oct/2026 12:35:59] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:59] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:59] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:59] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:59] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:59] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:59] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:59] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:59] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:59] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:59] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:59] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:59] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:59] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:59] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:59] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:59] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:35:59] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 97 [webkit] › viewer.spec.mjs:722:3 › viewer & editor (viewer.html) › the embedded agent schema marks axis optional, only 3md required (418ms) +[WebServer] ::1 - - [10/Oct/2026 12:36:00] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:00] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:00] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:00] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:00] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:00] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:00] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:00] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:00] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 98 [webkit] › viewer.spec.mjs:729:3 › viewer & editor (viewer.html) › invalid doc clears stale plane/axis data on the badge (837ms) +[WebServer] ::1 - - [10/Oct/2026 12:36:00] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:00] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:00] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:00] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:00] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:00] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:00] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:00] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:00] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 99 [webkit] › viewer.spec.mjs:742:3 › viewer & editor (viewer.html) › an invalid document flags the offending line and the badge (954ms) + ✓ 100 [webkit] › viewer.spec.mjs:755:3 › viewer & editor (viewer.html) › a shared hash link restores the document (517ms) +[WebServer] ::1 - - [10/Oct/2026 12:36:01] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:01] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:01] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:01] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:01] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:01] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:01] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:01] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:01] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:01] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:01] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:01] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:01] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:01] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:01] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:01] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:01] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:01] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 102 [webkit] › viewer.spec.mjs:795:3 › viewer & editor (viewer.html) › full camera turns cross both poles continuously and retain geometry (660ms) + ✓ 101 [webkit] › viewer.spec.mjs:766:3 › viewer & editor (viewer.html) › camera buttons and keyboard orbit, zoom, and fit without changing the document (793ms) +[WebServer] ::1 - - [10/Oct/2026 12:36:01] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:01] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:01] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:01] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:01] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:01] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:01] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:01] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:01] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:01] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:01] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:01] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:01] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:01] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:01] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:01] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:01] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:01] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 103 [webkit] › viewer.spec.mjs:843:3 › viewer & editor (viewer.html) › pan tools and modified dragging move only the camera and Fit recenters (684ms) + ✓ 104 [webkit] › viewer.spec.mjs:874:3 › viewer & editor (viewer.html) › two fingers pan and pinch and a cancelled gesture cannot select a slice (642ms) +[WebServer] ::1 - - [10/Oct/2026 12:36:02] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:02] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:02] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:02] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:02] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:02] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:02] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:02] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:02] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:02] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:02] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:02] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:02] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:02] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:02] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:02] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:02] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:02] "GET /gallery-data.json HTTP/1.1" 200 - + ✓ 106 [webkit] › viewer.spec.mjs:965:3 › viewer & editor (viewer.html) › phone layout leaves room for cubes and keeps controls outside the drawing (699ms) +[WebServer] ::1 - - [10/Oct/2026 12:36:03] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:03] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:03] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:03] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:03] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:03] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:03] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:03] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:03] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 107 [webkit] › viewer.spec.mjs:987:3 › viewer & editor (viewer.html) › Document disclosure dismisses with Escape and both downloads preserve the document (807ms) +[WebServer] ::1 - - [10/Oct/2026 12:36:04] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:04] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:04] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:04] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:04] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:04] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:04] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:04] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:04] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 108 [webkit] › viewer.spec.mjs:1024:3 › viewer & editor (viewer.html) › a prose document offers Preview without replacing its source (669ms) +[WebServer] ::1 - - [10/Oct/2026 12:36:04] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:04] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:04] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:04] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:04] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:04] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:04] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:04] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:04] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 109 [webkit] › viewer.spec.mjs:1042:3 › viewer & editor (viewer.html) › slice navigation keeps the selected plane in a single scrolling row (607ms) +[WebServer] ::1 - - [10/Oct/2026 12:36:05] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:05] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:05] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:05] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:05] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:05] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:05] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:05] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:05] "GET /gallery-data.json HTTP/1.1" 200 - + ✓ 110 [webkit] › viewer.spec.mjs:1064:3 › viewer & editor (viewer.html) › a GitHub load shows busy state and recovers after a rate limit (655ms) +[WebServer] ::1 - - [10/Oct/2026 12:36:05] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:06] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:06] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:06] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:06] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:06] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:06] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:06] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:06] "GET /gallery-data.json HTTP/1.1" 200 - + ✓ 105 [webkit] › viewer.spec.mjs:897:3 › viewer & editor (viewer.html) › browser camera projects and picks the shared native parity fixture (4.1s) + ✓ 111 [webkit] › viewer.spec.mjs:1084:3 › viewer & editor (viewer.html) › GPU unavailability explains how to keep reading in Preview (585ms) +[WebServer] ::1 - - [10/Oct/2026 12:36:06] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:06] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:06] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:06] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:06] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:06] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:06] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:06] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:06] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:06] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:06] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:06] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:06] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:06] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:06] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:06] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:06] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:06] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 113 [webkit] › viewer.spec.mjs:1143:3 › viewer & editor (viewer.html) › composition entry switches preserve each draft without copying it into another entry (773ms) +[WebServer] ::1 - - [10/Oct/2026 12:36:07] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:07] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:07] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:07] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:07] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 112 [webkit] › viewer.spec.mjs:1100:3 › viewer & editor (viewer.html) › file switches preserve edited, invalid, and empty drafts with caret and slice (1.1s) +[WebServer] ::1 - - [10/Oct/2026 12:36:07] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:07] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:07] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:07] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:07] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:07] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:07] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:07] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:07] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:07] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:07] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:07] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:07] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 114 [webkit] › viewer.spec.mjs:1170:3 › viewer & editor (viewer.html) › linked entries and file navigation share the same draft (756ms) +[WebServer] ::1 - - [10/Oct/2026 12:36:08] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:08] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:08] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:08] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:08] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:08] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:08] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:08] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:08] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 115 [webkit] › viewer.spec.mjs:1195:3 › viewer & editor (viewer.html) › search and packing use drafts rather than original file text (828ms) +[WebServer] ::1 - - [10/Oct/2026 12:36:08] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:08] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:08] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:08] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:08] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:08] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:08] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:08] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:08] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 116 [webkit] › viewer.spec.mjs:1212:3 › viewer & editor (viewer.html) › file filtering, keyboard selection, and phone opens reveal the document (901ms) +[WebServer] ::1 - - [10/Oct/2026 12:36:09] "GET /viewer.html?src=original-document.3md&theme=dark HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:09] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:09] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:09] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:09] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:09] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:09] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:09] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:09] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 117 [webkit] › viewer.spec.mjs:1240:3 › viewer & editor (viewer.html) › a failed local open preserves the collection and current draft (1.2s) +[WebServer] ::1 - - [10/Oct/2026 12:36:09] "GET /viewer.html?theme=dark HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:09] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:09] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:09] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:09] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:09] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:09] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:09] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:09] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:09] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:09] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:09] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:09] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:09] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:09] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:09] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:09] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:09] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:09] "GET /viewer.html?theme=dark HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:09] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:09] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:09] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:09] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:09] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:09] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:09] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:09] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 118 [webkit] › viewer.spec.mjs:1259:3 › viewer & editor (viewer.html) › explicit document navigation removes stale source queries and reloads the chosen source (1.3s) +[WebServer] ::1 - - [10/Oct/2026 12:36:10] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:10] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:10] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:10] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:10] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:10] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:10] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:10] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:10] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:10] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:10] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:10] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:10] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:10] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:10] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:10] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:10] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:10] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:10] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:10] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:10] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:10] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:10] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:10] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 120 [webkit] › viewer.spec.mjs:1316:3 › Sculpt Slice parity › grid edits preserve CRLF, labels, prose and downloads exactly (761ms) +[WebServer] ::1 - - [10/Oct/2026 12:36:10] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:10] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:10] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:10] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:10] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:11] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:11] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:11] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:11] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:11] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:11] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:11] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:11] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:11] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:11] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:11] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:11] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:11] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:11] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:11] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:11] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:11] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:11] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:11] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:11] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:11] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:11] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:11] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:11] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 121 [webkit] › viewer.spec.mjs:1328:3 › Sculpt Slice parity › keyboard cells, grid zoom, previous overlay and shared WebGL reference (815ms) + ✓ 119 [webkit] › viewer.spec.mjs:1298:3 › Sculpt Slice parity › shared native strokes, clipped brushes, four-neighbor fill and no-op undo (2.3s) +[WebServer] ::1 - - [10/Oct/2026 12:36:11] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:11] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:11] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:11] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:11] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:11] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:11] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:11] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:11] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:11] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:11] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:11] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:11] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:11] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:11] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:11] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:11] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:11] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 122 [webkit] › viewer.spec.mjs:1341:3 › Sculpt Slice parity › source typing and Slice share undo and retain it across file navigation (833ms) + ✓ 123 [webkit] › viewer.spec.mjs:1353:3 › Sculpt Slice parity › unsupported grids stay readable and budget rejection restores the full stroke (848ms) +[WebServer] ::1 - - [10/Oct/2026 12:36:12] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:12] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:12] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:12] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:12] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:12] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:12] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:12] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:12] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:12] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:12] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:12] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:12] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:12] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:12] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:12] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:12] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:12] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 125 [webkit] › viewer.spec.mjs:1370:3 › Sculpt Slice parity › 2D editing works with an unavailable WebGL reference (696ms) + ✓ 124 [webkit] › viewer.spec.mjs:1361:3 › Sculpt Slice parity › phone Slice tools and axis controls stay usable without horizontal page overflow (830ms) +[WebServer] ::1 - - [10/Oct/2026 12:36:13] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:13] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:13] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:13] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:13] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:13] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:13] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:13] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:13] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:13] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:13] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:13] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:13] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:13] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:13] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:13] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:13] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:13] "GET /gallery-data.json HTTP/1.1" 200 - + ✓ 126 [webkit] › viewer.spec.mjs:1375:3 › Sculpt Slice parity › axis inverse, finite inputs, pan steps and Fit leave source and geometry intact (896ms) +[WebServer] ::1 - - [10/Oct/2026 12:36:14] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:14] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:14] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:14] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:14] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:14] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:14] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:14] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:14] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 128 [webkit] › viewer.spec.mjs:1411:1 › Slice navigation finishes a touch stroke and ignores its late pointer movement (725ms) +[WebServer] ::1 - - [10/Oct/2026 12:36:15] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:15] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:15] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:15] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:15] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:15] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:15] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:15] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:15] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 129 [webkit] › viewer.spec.mjs:1427:3 › shared cube drawable stays sharp through view/viewport changes at 1x density (1.8s) +[WebServer] ::1 - - [10/Oct/2026 12:36:16] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:16] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:16] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:16] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:16] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:16] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:16] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:16] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 12:36:16] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 130 [webkit] › viewer.spec.mjs:1427:3 › shared cube drawable stays sharp through view/viewport changes at 2x density (1.9s) + ✓ 127 [webkit] › viewer.spec.mjs:1389:1 › Slice history drops only old snapshots at the per-draft and collection budgets (6.8s) + + 130 passed (1.2m) diff --git a/docs/evidence/viewer-slice/README.md b/docs/evidence/viewer-slice/README.md new file mode 100644 index 00000000..317a2bf0 --- /dev/null +++ b/docs/evidence/viewer-slice/README.md @@ -0,0 +1,23 @@ +# Slice and camera parity evidence + +The browser Slice workspace follows Sculpt’s Draw/Erase/Fill, palette and square brush behavior. Shared `slice-parity.json` cases use independently stated expected rows and run through real native workspaces and browser pointer gestures. The cases cover sparse diagonal and horizontal strokes, unchanged starts, repeated points, asymmetric 9×7×5 slices, size-3/5 edge clipping, erase, four-neighbor boundaries, untouched planes and no-op history. Camera cases in `../viewer-camera/camera-parity.json` use an independent rotation-matrix reference, including X/Y/Z, negative steps, mixed sequences, inverse steps and full turns. Actual GPU projection and nearest picking are compared with those values; native scalar/live picking and ASCII Z picking are also checked. + +Verified locally on 2026-10-10: + +- Full macOS Chromium/WebKit UI suite: 226 passed, no skips or retries (`mac-browser.log`). +- Linux CI Chromium/WebKit suite: 218 passed, 8 existing platform-snapshot skips, no retries, in 3.4 minutes (`linux-ci.log`). The first run omitted CI=1 and passed all 218 functional tests but failed eight macOS-only visual snapshot comparisons; the complete rerun used the repository’s unchanged CI policy. All eight snapshots passed in the full macOS run. +- Final expanded shared browser fixtures: 4 passed (`browser-fixtures.log`). +- Final phone regressions at 390×844 and 320×740: 4 passed (`phone.log`). +- Configured native regression selection: 637 tests in 54 suites passed (`native-full.log`), using the existing `--skip deterministicPortableInterchangeFixtures` selection. The previously established release-fixture/version mismatch remains outside this UI change; no new skip was introduced. +- Final native camera, live picking/mesh reuse and expanded Slice fixture selection: 11 passed (`native-parity.log`). This includes the independent ASCII Z-picking test added after the broad suite; implementation did not change afterwards. +- Strict root and nested app specs passed with complete configured coverage. Hi criteria are unique and generated intent indexes are current. + +Visual evidence uses the actual browser and an isolated source-built Sculpt preview: `browser-desktop.png`, `browser-phone.png`, and `sculpt-axis.png`. This is agent visual verification, not Leif’s implementation diff review or an independent human approval. + +Slice preserves raw non-target text, including CRLF, fractional plane positions, labels and prose; exported text and kind 2 use the current draft. History is bounded to 100 snapshots per draft and 8 MiB across the current collection. Over-budget transactions roll back completely, and late pointer events cannot edit a newly activated file. One WebGL canvas is shared with the live reference. Source editing and 2D Slice remain available without WebGL. + +The browser’s supported edit profile is complete common rectangular grids up to 64×64, 256 planes, 4000 occupied cells and 1.5 MiB source, with the native palette and dot/space empties. Structural slice actions, volume resizing and browser 3D painting remain subsequent work. Native storage, formats, library APIs, examples, generated browser bundles and releases are unchanged. + +Linux CI verification is complete. Both approved changes passed current verification and supported scoped review/finalization, and are archived under `.specsync/archive/changes/2026-10-10-*`. Closure receipts are `slice-closure.json` and `axis-closure.json`; exact final archive-head Trust and remote CI status are reported in PR #93. Actual reviewer identity is agent:codex. Scope and conditional verified closure were directly authorized by Leif; that does not supply a permitted signature or a human diff review. Existing soft unsigned provenance policy remains intact. + +Implementation commit: `8e9a0c4`. Pinned Trust 1.2.2 / Fledge 1.7.2 passed (`trust-implementation.log`). Actual unsigned agent:codex record and unchanged policy result are in `attestation-implementation.json` and `provenance-implementation.json`; the strict provenance policy fails for the unsigned/unpermitted reviewer, while Trust’s configured soft mode passes with progressive provenance. No policy was changed. diff --git a/docs/evidence/viewer-slice/attestation-implementation.json b/docs/evidence/viewer-slice/attestation-implementation.json new file mode 100644 index 00000000..542cae94 --- /dev/null +++ b/docs/evidence/viewer-slice/attestation-implementation.json @@ -0,0 +1 @@ +{"commit":"8e9a0c4eecfa50b8918b864b3569c1dec5fde559","confidence":0.86,"humanApproved":false,"note":"Actual Codex implementation and review claim: Slice and three-axis camera parity passed macOS browser, native broad and final focused checks; pinned Trust passed. Leif authorized scope and conditional closure, not a diff review. No permitted signature or independent human approval is claimed.","reviewer":"agent:codex","testsPassed":true,"timestamp":1791655286,"verdict":"review"} diff --git a/docs/evidence/viewer-slice/axis-closure.json b/docs/evidence/viewer-slice/axis-closure.json new file mode 100644 index 00000000..3d3c08bb --- /dev/null +++ b/docs/evidence/viewer-slice/axis-closure.json @@ -0,0 +1,13 @@ +{ + "archived": "/Users/leif/Development/_CorvidLabs/3md-edit-preview/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer", + "contract_digest": "4b6d4eb372c26f296d08a35c4242b772ba7f537d690b3ac81723034860824618", + "finalization_digest": "1225a89a0f4a47068497828dd6ef78edf4902c37edde6c9670427d91af38c098", + "id": "add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer", + "implementation_commit": "60055f7806a4d46964b766672784be45713e3c3a", + "implementation_tree": "9970ef31ab167b4c3429cc3aa17af3651c830918", + "lesson_bundle": "/Users/leif/Development/_CorvidLabs/3md-edit-preview/.specsync/archive/changes/2026-10-10-add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer/lesson-bundle.md", + "next_action": "merge the PR on GitHub", + "ready_for_github_merge": true, + "review_digest": "cf186ff11b71dbf0169c2d3aeaa61edefc6e214954bf82620c6ad53d5759d410", + "workspace_digest": "fde013fc78a6110e0c0b88de16f5f6e7522e6561a06c0a5c5fd273d884ed5278" +} diff --git a/docs/evidence/viewer-slice/browser-desktop.png b/docs/evidence/viewer-slice/browser-desktop.png new file mode 100644 index 00000000..7e3f3f44 Binary files /dev/null and b/docs/evidence/viewer-slice/browser-desktop.png differ diff --git a/docs/evidence/viewer-slice/browser-fixtures.log b/docs/evidence/viewer-slice/browser-fixtures.log new file mode 100644 index 00000000..750b4f81 --- /dev/null +++ b/docs/evidence/viewer-slice/browser-fixtures.log @@ -0,0 +1,88 @@ + +Running 4 tests using 2 workers + +(node:48212) Warning: The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set. +(Use `node --trace-warnings ...` to show where the warning was created) +(node:48211) Warning: The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set. +(Use `node --trace-warnings ...` to show where the warning was created) +[WebServer] ::1 - - [10/Oct/2026 11:56:30] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:30] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:30] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:30] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:30] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:30] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:30] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:30] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:30] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:30] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:30] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:30] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:30] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:30] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:30] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:30] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:30] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:30] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 2 [chromium] › viewer.spec.mjs:1316:3 › Sculpt Slice parity › grid edits preserve CRLF, labels, prose and downloads exactly (1.4s) +(node:48225) Warning: The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set. +(Use `node --trace-warnings ...` to show where the warning was created) +[WebServer] ::1 - - [10/Oct/2026 11:56:32] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:33] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:33] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:33] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:33] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:33] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:33] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:33] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:33] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 1 [chromium] › viewer.spec.mjs:1298:3 › Sculpt Slice parity › shared native strokes, clipped brushes, four-neighbor fill and no-op undo (3.5s) +[WebServer] ::1 - - [10/Oct/2026 11:56:33] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:33] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:33] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:33] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:33] "GET /nested-examples.json HTTP/1.1" 200 - +(node:48260) Warning: The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set. +(Use `node --trace-warnings ...` to show where the warning was created) +[WebServer] ::1 - - [10/Oct/2026 11:56:33] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:33] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:33] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:33] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:33] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:34] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:34] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:34] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:34] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:34] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:34] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:34] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:34] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:34] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:34] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:34] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:34] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:34] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:34] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:34] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:34] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:34] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:34] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:34] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:34] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:34] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:34] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:34] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:34] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:34] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:34] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:34] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:34] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:34] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:35] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:35] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:35] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:35] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:56:35] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 3 [webkit] › viewer.spec.mjs:1298:3 › Sculpt Slice parity › shared native strokes, clipped brushes, four-neighbor fill and no-op undo (3.3s) + ✓ 4 [webkit] › viewer.spec.mjs:1316:3 › Sculpt Slice parity › grid edits preserve CRLF, labels, prose and downloads exactly (1.3s) + + 4 passed (6.6s) diff --git a/docs/evidence/viewer-slice/browser-phone.png b/docs/evidence/viewer-slice/browser-phone.png new file mode 100644 index 00000000..2177259a Binary files /dev/null and b/docs/evidence/viewer-slice/browser-phone.png differ diff --git a/docs/evidence/viewer-slice/linux-ci.log b/docs/evidence/viewer-slice/linux-ci.log new file mode 100644 index 00000000..171b1538 --- /dev/null +++ b/docs/evidence/viewer-slice/linux-ci.log @@ -0,0 +1,1615 @@ + +Running 226 tests using 2 workers +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:02:58] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:02:58] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:02:58] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:02:58] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:02:58] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:02:58] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:02:58] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:02:58] "GET /sample.3md HTTP/1.1" 200 - +··[WebServer] 127.0.0.1 - - [10/Oct/2026 18:02:58] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:02:58] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:02:58] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:02:58] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:02:58] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:02:58] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:02:58] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:02:58] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:02:58] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:02:58] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:02:58] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:02:58] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:00] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:00] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:00] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:00] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:00] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:00] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:00] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:00] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:02] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:03] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:03] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:03] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:03] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:03] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:03] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:03] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:03] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:03] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:03] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:03] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:03] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:03] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:03] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:03] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:03] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:03] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:03] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:03] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:03] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:03] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:03] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:03] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:03] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:03] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:03] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:03] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:03] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:03] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:03] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:03] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:03] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:03] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:03] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:04] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:04] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:04] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:04] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:04] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:04] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:04] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:04] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:04] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:04] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:04] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:04] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:04] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:04] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:04] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:04] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:04] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:04] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:04] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:04] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:04] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:04] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:04] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:04] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:04] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:04] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:04] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:04] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:04] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:04] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:04] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:04] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:04] "GET /sample.3md HTTP/1.1" 200 - +··[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /sample.3md HTTP/1.1" 200 - +··[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /sample.3md HTTP/1.1" 200 - +··[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /embed-example.html HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /embed-example.html HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /assets/tokens.css HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /assets/tokens.css HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /index.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:05] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:06] "GET /all-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:06] "GET /index.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:06] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:06] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:06] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:06] "GET /all-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:08] "GET /index.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:08] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:08] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:08] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:08] "GET /all-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:08] "GET /index.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:08] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:08] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:08] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:08] "GET /all-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:09] "GET /index.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:09] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:09] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:09] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:09] "GET /all-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:10] "GET /index.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:10] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:10] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:10] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:10] "GET /all-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:15] "GET /index.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:15] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:15] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:15] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:15] "GET /all-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:19] "GET /index.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:19] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:19] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:19] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:19] "GET /all-examples.json HTTP/1.1" 200 - +·°°°°[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:20] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:20] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:20] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:20] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:20] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:20] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:20] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:20] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:20] "GET /all-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:20] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:20] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:20] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:20] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:20] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:21] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:21] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:21] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:21] "GET /all-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:21] "GET /viewer.html HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:21] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:21] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:21] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:21] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:21] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:21] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:21] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:21] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:21] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:21] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:21] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:21] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:21] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:21] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:21] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:21] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:21] "GET /gallery-data.json HTTP/1.1" 200 - +··[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:22] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:22] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:22] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:22] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:22] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:22] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:22] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:22] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:22] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:22] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:22] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:22] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:22] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:22] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:22] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:22] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:22] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:22] "GET /binary-samples.json HTTP/1.1" 200 - +··[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:23] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:23] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:23] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:23] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:23] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:23] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:23] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:23] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:23] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:23] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:23] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:23] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:23] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:23] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:23] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:23] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:23] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:23] "GET /all-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:24] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:24] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:24] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:24] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:24] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:24] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:24] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:24] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:24] "GET /nested-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:24] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:24] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:24] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:24] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:24] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:24] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:24] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:24] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:24] "GET /gallery-data.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:24] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:24] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:24] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:24] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:24] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:25] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:25] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:25] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:25] "GET /gallery-data.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:25] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:25] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:25] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:25] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:25] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:25] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:25] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:25] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:25] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:25] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:26] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:26] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:26] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:26] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:26] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:26] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:26] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:26] "GET /all-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:26] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:26] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:26] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:26] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:26] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:26] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:26] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:26] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:26] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:26] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:26] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:26] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:26] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:26] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:27] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:27] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:27] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:27] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:27] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:27] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:27] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:27] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:27] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:27] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:27] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:27] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:27] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:27] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:27] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:27] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:27] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:27] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:27] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:27] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:27] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:27] "GET /nested-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:28] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:28] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:28] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:28] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:28] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:28] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:28] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:28] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:28] "GET /gallery-data.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:28] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:28] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:28] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:28] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:28] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:29] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:29] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:29] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:29] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:29] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:29] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:29] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:29] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:29] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:29] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:29] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:29] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:29] "GET /all-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:29] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:29] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:29] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:29] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:29] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:30] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:30] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:30] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:30] "GET /gallery-data.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:30] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:30] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:30] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:30] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:30] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:30] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:30] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:30] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:30] "GET /nested-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:31] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:31] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:31] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:31] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:31] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:31] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:31] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:31] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:31] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:31] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:31] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:31] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:31] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:31] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:31] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:31] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:31] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:31] "GET /nested-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:32] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:32] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:32] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:32] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:32] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:32] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:32] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:32] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:32] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:32] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:32] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:32] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:32] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:32] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:32] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:32] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:32] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:32] "GET /gallery-data.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:33] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:33] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:33] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:33] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:33] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:33] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:33] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:33] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:33] "GET /gallery-data.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:34] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:34] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:34] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:34] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:34] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:34] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:34] "GET /nested-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:34] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:34] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:34] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:34] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:34] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:34] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:34] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:34] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:34] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:34] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:34] "GET /nested-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:35] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:35] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:35] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:35] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:35] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:35] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:35] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:35] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:35] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:35] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:35] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:35] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:35] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:35] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:35] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:35] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:35] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:35] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:35] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:35] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:35] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:35] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:35] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:36] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:36] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:36] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:36] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:36] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:36] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:36] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:36] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:36] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:36] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:36] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:36] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:36] "GET /all-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:36] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:36] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:36] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:36] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:36] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:36] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:36] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:36] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:36] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:37] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:37] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:37] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:37] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:37] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:37] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:37] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:37] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:37] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:37] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:37] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:37] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:37] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:37] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:37] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:37] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:37] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:37] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:37] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:37] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:37] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:37] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:37] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:37] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:37] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:37] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:37] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:38] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:38] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:38] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:38] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:38] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:38] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:38] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:38] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:38] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:38] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:38] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:38] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:38] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:38] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:38] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:38] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:38] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:38] "GET /all-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:39] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:39] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:39] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:39] "GET /assets/theme.js HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:39] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:39] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:39] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:39] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:39] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:39] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:39] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:39] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:39] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:39] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:39] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:39] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:39] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:39] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:40] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:40] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:40] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:40] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:40] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:40] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:40] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:40] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:40] "GET /nested-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:41] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:41] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:41] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:41] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:41] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:41] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:41] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:41] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:41] "GET /all-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:42] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:42] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:42] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:42] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:42] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:42] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:42] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:42] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:42] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:42] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:42] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:42] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:42] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:42] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:42] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:42] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:42] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:42] "GET /nested-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:43] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:43] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:43] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:43] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:43] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:43] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:43] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:43] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:43] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:44] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:44] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:44] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:44] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:44] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:44] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:44] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:44] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:44] "GET /binary-samples.json HTTP/1.1" 200 - +··[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:45] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:45] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:45] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:45] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:45] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:45] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:45] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:45] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:45] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:45] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:45] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:45] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:45] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:45] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:45] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:45] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:45] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:45] "GET /binary-samples.json HTTP/1.1" 200 - +··[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:46] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:46] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:46] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:46] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:46] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:46] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:46] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:46] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:46] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:46] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:46] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:46] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:46] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:46] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:46] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:46] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:46] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:46] "GET /nested-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:47] "GET /viewer.html HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:47] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:47] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:47] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:47] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:47] "GET /viewer.html?src=original-document.3md&theme=dark HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:47] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:47] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:47] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:47] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:47] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:47] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:47] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:47] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:47] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:47] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:47] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:47] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:48] "GET /viewer.html?theme=dark HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:48] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:48] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:48] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:48] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:48] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:48] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:48] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:48] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:48] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:48] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:48] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:48] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:48] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:48] "GET /viewer.html?theme=dark HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:48] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:48] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:48] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:48] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:48] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:48] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:48] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:48] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:48] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:48] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:48] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:49] "GET /nested-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:49] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:49] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:49] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:49] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:49] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:49] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:49] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:49] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:49] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:50] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:50] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:50] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:50] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:50] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:50] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:50] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:50] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:50] "GET /all-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:51] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:51] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:51] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:51] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:51] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:51] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:51] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:51] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:51] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:52] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:52] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:52] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:52] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:52] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:52] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:52] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:52] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:52] "GET /gallery-data.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:53] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:53] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:53] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:53] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:53] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:53] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:53] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:53] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:53] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:54] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:54] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:54] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:54] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:54] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:54] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:54] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:54] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:54] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:54] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:54] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:54] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:54] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:54] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:55] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:55] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:55] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:55] "GET /all-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:55] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:55] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:55] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:55] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:55] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:55] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:55] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:55] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:55] "GET /gallery-data.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:56] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:56] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:56] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:56] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:56] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:56] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:56] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:56] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:56] "GET /all-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:58] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:58] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:58] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:58] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:58] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:58] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:58] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:58] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:58] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:58] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:58] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:58] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:58] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:58] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:58] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:03:59] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:03] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:03] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:03] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:03] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:09] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:09] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:09] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:09] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:09] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:09] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:09] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:09] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:09] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:09] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:09] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:09] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:09] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:09] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:09] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:10] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:11] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:11] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:11] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:11] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:11] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:11] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:11] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:11] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:12] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:12] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:12] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:12] "GET /sample.3md HTTP/1.1" 200 - +··[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:12] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:12] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:12] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:12] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:12] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:12] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:12] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:12] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:12] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:12] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:12] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:13] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:13] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:13] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:13] "GET /assets/tokens.css HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:13] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:13] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:13] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:13] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:13] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:13] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:13] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:13] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:13] "GET /sample.3md HTTP/1.1" 200 - +··[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:14] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:14] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:14] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:14] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:14] "GET /embed-example.html HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:14] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:14] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:14] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:14] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:14] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:14] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:14] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:14] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:14] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:14] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:15] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:15] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:15] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:15] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:15] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:15] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:15] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:15] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:15] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:15] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:15] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:15] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:16] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:16] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:16] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:16] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:16] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:16] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:16] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:16] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:16] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:16] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:16] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:16] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:16] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:16] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:16] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:16] "GET /assets/tokens.css HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:17] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:17] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:17] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:17] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:17] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:17] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:17] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:17] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:17] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:18] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:18] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:18] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:18] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:18] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:18] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:18] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:18] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:18] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:18] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:18] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:18] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:18] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:18] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:18] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:19] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:19] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:19] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:19] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:19] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:19] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:19] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:19] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:19] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:19] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:19] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:19] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:19] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:20] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:20] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:20] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:20] "GET /sample.3md HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:20] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:20] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:20] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:20] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:20] "GET /index.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:20] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:20] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:20] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:20] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:20] "GET /all-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:21] "GET /index.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:21] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:21] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:21] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:21] "GET /all-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:25] "GET /index.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:25] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:25] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:25] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:25] "GET /all-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:27] "GET /index.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:27] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:27] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:27] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:27] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:27] "GET /index.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:27] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:27] "GET /index.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:27] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:27] "GET /index.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:27] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:27] "GET /index.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:27] "GET /all-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:27] "GET /index.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:27] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:27] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:27] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:28] "GET /all-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:28] "GET /index.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:28] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:28] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:28] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:29] "GET /all-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:41] "GET /index.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:41] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:41] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:41] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:42] "GET /all-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:42] "GET /index.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:43] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:43] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:43] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:43] "GET /all-examples.json HTTP/1.1" 200 - +·°° +°°[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:45] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:45] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:45] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:45] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:45] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:45] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:45] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:45] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:45] "GET /gallery-data.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:46] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:46] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:46] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:46] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:46] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:46] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:46] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:46] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:46] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:47] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:47] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:47] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:47] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:47] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:47] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:47] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:47] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:47] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:48] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:48] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:48] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:48] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:48] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:48] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:48] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:48] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:48] "GET /nested-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:49] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:49] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:49] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:49] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:49] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:49] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:49] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:49] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:49] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:50] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:50] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:50] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:50] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:50] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:50] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:50] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:50] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:50] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:52] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:52] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:52] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:52] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:52] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:52] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:52] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:52] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:52] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:53] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:53] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:53] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:53] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:53] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:53] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:53] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:53] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:53] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:54] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:54] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:54] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:54] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:54] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:54] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:54] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:54] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:54] "GET /nested-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:55] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:55] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:55] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:55] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:55] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:55] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:55] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:55] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:55] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:57] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:57] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:57] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:57] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:57] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:57] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:57] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:57] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:57] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:58] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:58] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:58] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:58] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:58] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:58] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:58] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:58] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:58] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:59] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:59] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:59] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:59] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:59] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:59] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:59] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:59] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:04:59] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:01] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:01] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:01] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:01] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:01] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:01] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:01] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:01] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:01] "GET /gallery-data.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:01] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:01] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:01] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:01] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:01] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:01] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:01] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:01] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:01] "GET /all-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:02] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:02] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:02] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:02] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:02] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:02] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:02] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:02] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:02] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:02] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:02] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:02] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:02] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:02] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:02] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:02] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:02] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:02] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:02] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:02] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:02] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:02] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:02] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:02] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:02] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:02] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:02] "GET /binary-samples.json HTTP/1.1" 200 - +··[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:04] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:04] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:04] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:04] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:04] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:04] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:04] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:04] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:04] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:04] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:04] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:04] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:04] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:04] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:04] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:04] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:04] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:04] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:05] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:05] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:05] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:05] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:05] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:05] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:05] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:05] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:05] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:05] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:05] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:05] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:05] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:05] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:05] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:05] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:05] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:05] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:07] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:07] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:07] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:07] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:07] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:07] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:07] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:07] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:07] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:08] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:08] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:08] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:08] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:08] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:08] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:08] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:08] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:08] "GET /binary-samples.json HTTP/1.1" 200 - +··[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:10] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:10] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:10] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:10] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:10] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:10] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:10] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:10] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:10] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:10] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:10] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:10] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:10] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:10] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:10] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:10] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:10] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:10] "GET /gallery-data.json HTTP/1.1" 200 - +··[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:11] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:11] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:11] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:11] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:11] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:11] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:11] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:11] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:11] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:11] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:11] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:11] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:11] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:11] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:11] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:11] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:11] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:11] "GET /binary-samples.json HTTP/1.1" 200 - +··[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:12] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:12] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:12] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:12] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:12] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:12] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:12] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:12] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:12] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:12] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:12] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:12] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:12] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:12] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:12] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:12] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:12] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:12] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:13] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:13] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:13] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:13] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:13] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:13] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:13] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:13] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:13] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:13] "GET /viewer.html HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:13] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:13] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:13] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:13] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:13] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:13] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:13] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:13] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:13] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:13] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:13] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:13] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:13] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:13] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:13] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:13] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:13] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:14] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:14] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:14] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:14] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:14] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:14] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:14] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:14] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:14] "GET /binary-samples.json HTTP/1.1" 200 - +··[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:16] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:16] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:16] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:16] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:16] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:16] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:16] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:16] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:16] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:16] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:16] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:16] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:16] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:16] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:16] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:16] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:16] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:16] "GET /all-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:16] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:16] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:16] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:16] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:16] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:17] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:17] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:17] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:17] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:18] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:18] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:18] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:18] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:18] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:18] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:18] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:18] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:18] "GET /nested-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:18] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:18] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:18] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:18] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:18] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:18] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:18] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:18] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:18] "GET /nested-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:19] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:19] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:19] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:19] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:19] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:19] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:19] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:19] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:19] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:19] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:19] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:19] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:19] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:19] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:19] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:19] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:19] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:19] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:21] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:21] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:21] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:21] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:21] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:21] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:21] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:21] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:21] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:23] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:23] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:23] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:23] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:23] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:23] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:23] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:23] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:23] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:24] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:24] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:24] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:24] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:24] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:24] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:24] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:24] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:24] "GET /nested-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:25] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:25] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:25] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:25] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:25] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:25] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:25] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:25] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:25] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:26] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:26] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:26] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:26] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:26] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:26] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:26] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:26] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:26] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:27] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:27] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:27] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:27] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:27] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:27] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:27] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:27] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:27] "GET /all-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:30] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:30] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:30] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:30] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:30] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:30] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:30] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:30] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:30] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:32] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:32] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:32] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:32] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:32] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:32] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:32] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:32] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:32] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:34] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:34] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:34] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:34] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:34] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:34] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:34] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:34] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:34] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:36] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:36] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:36] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:36] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:36] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:36] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:36] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:36] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:36] "GET /binary-samples.json HTTP/1.1" 200 - +··[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:38] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:38] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:38] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:38] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:38] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:38] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:38] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:38] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:38] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:38] "GET /viewer.html?src=original-document.3md&theme=dark HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:38] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:38] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:38] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:38] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:38] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:38] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:38] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:38] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:39] "GET /viewer.html?theme=dark HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:39] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:39] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:39] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:39] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:39] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:39] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:39] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:39] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:40] "GET /viewer.html?theme=dark HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:40] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:40] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:40] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:40] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:40] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:40] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:40] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:40] "GET /binary-samples.json HTTP/1.1" 200 - +··[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:40] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:40] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:40] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:40] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:40] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:40] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:40] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:40] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:40] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:40] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:40] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:40] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:40] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:40] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:40] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:40] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:40] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:40] "GET /all-examples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:43] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:43] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:43] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:43] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:43] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:43] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:43] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:43] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:43] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:43] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:43] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:43] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:43] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:43] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:44] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:44] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:44] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:44] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:44] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:45] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:45] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:45] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:45] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:45] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:45] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:45] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:45] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:45] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:45] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:45] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:45] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:45] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:45] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:47] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:47] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:47] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:47] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:47] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:47] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:47] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:47] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:47] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:47] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:47] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:47] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:47] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:47] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:48] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:48] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:48] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:48] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:48] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:48] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:48] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:48] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:48] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:48] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:49] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:49] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:49] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:49] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:49] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:49] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:49] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:49] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:49] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:51] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:51] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:51] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:51] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:51] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:52] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:52] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:52] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:52] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:52] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:52] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:52] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:52] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:52] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:52] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:52] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:52] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:52] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:52] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:52] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:52] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:52] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:52] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:53] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:53] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:53] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:53] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:53] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:53] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:53] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:53] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:53] "GET /binary-samples.json HTTP/1.1" 200 - +·[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:54] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:54] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:54] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:54] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:54] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:54] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:54] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:54] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] 127.0.0.1 - - [10/Oct/2026 18:05:54] "GET /all-examples.json HTTP/1.1" 200 - +·· +::notice title=🎭 Playwright Run Summary:: 8 skipped%0A 218 passed (3.4m) + 8 skipped + 218 passed (3.4m) diff --git a/docs/evidence/viewer-slice/mac-browser.log b/docs/evidence/viewer-slice/mac-browser.log new file mode 100644 index 00000000..b6d1c0c2 --- /dev/null +++ b/docs/evidence/viewer-slice/mac-browser.log @@ -0,0 +1,1876 @@ + +Running 226 tests using 2 workers + +(node:46477) Warning: The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set. +(Use `node --trace-warnings ...` to show where the warning was created) +(node:46478) Warning: The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set. +(Use `node --trace-warnings ...` to show where the warning was created) +[WebServer] ::1 - - [10/Oct/2026 11:50:25] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:25] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:25] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:25] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:25] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:25] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:25] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:25] "GET /sample.3md HTTP/1.1" 200 - + ✓ 1 [chromium] › component.spec.mjs:35:3 › component › upgrades, renders planes, no console errors (112ms) + ✓ 2 [chromium] › component.spec.mjs:53:3 › component › all deck cards share one width (focused matches the cards behind it) (111ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:25] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:25] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:25] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:25] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:25] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:25] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:25] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:25] "GET /sample.3md HTTP/1.1" 200 - + ✓ 3 [chromium] › component.spec.mjs:69:3 › component › wide ASCII-art content is not clipped (card widens to fit rigid blocks) (91ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:25] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:25] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:25] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:25] "GET /sample.3md HTTP/1.1" 200 - + ✓ 4 [chromium] › component.spec.mjs:84:3 › component › focused plane is frontmost across the scrubber (696ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:26] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:26] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:26] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:26] "GET /sample.3md HTTP/1.1" 200 - + ✓ 6 [chromium] › component.spec.mjs:109:3 › component › no horizontal overflow from 320px to 1440px (174ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:26] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:26] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:26] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:26] "GET /sample.3md HTTP/1.1" 200 - + ✓ 7 [chromium] › component.spec.mjs:123:3 › component › playback advances and pauses (animations) (2.4s) +[WebServer] ::1 - - [10/Oct/2026 11:50:28] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:28] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:28] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:28] "GET /sample.3md HTTP/1.1" 200 - + ✓ 8 [chromium] › component.spec.mjs:139:3 › component › frame animations render as a flipbook (one frame, no deck) and autoplay (93ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:28] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:28] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:28] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:28] "GET /sample.3md HTTP/1.1" 200 - + ✓ 9 [chromium] › component.spec.mjs:160:3 › component › does not auto-convert characters; an optional legend maps them (94ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:29] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:29] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:29] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:29] "GET /sample.3md HTTP/1.1" 200 - + ✓ 10 [chromium] › component.spec.mjs:184:3 › component › camera: WASD/wheel/orbit move the scene; retired modes alias (98ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:29] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:29] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:29] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:29] "GET /sample.3md HTTP/1.1" 200 - + ✓ 11 [chromium] › component.spec.mjs:210:3 › component › map mode lays planes out by x/y (94ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:29] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:29] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:29] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:29] "GET /sample.3md HTTP/1.1" 200 - + ✓ 12 [chromium] › component.spec.mjs:223:3 › component › renders Markdown tables (not raw pipes) (95ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:29] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:29] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:29] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:29] "GET /sample.3md HTTP/1.1" 200 - + ✓ 13 [chromium] › component.spec.mjs:239:3 › component › layers shows aligned overlays at once, with toggle chips (92ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:29] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:29] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:29] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:29] "GET /sample.3md HTTP/1.1" 200 - + ✓ 14 [chromium] › component.spec.mjs:261:3 › component › blend mode renders content as 3D voxels (95ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:29] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:29] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:29] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:29] "GET /sample.3md HTTP/1.1" 200 - + ✓ 15 [chromium] › component.spec.mjs:281:3 › component › single-card mode shows only the focused plane (233ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:29] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:29] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:29] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:29] "GET /sample.3md HTTP/1.1" 200 - + ✓ 16 [chromium] › component.spec.mjs:303:3 › component › single-card mode scrolls a long plane (reader) (97ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:29] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:29] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:29] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:29] "GET /sample.3md HTTP/1.1" 200 - + ✓ 17 [chromium] › component.spec.mjs:326:3 › component › reflects the resolved mode as data-mode (for fullscreen styling) (94ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:29] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:29] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:29] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:29] "GET /sample.3md HTTP/1.1" 200 - + ✓ 18 [chromium] › component.spec.mjs:343:3 › component › space and PageDown advance like a slideshow (not in reader) (99ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:30] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:30] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:30] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:30] "GET /sample.3md HTTP/1.1" 200 - + ✓ 19 [chromium] › component.spec.mjs:366:3 › component › cross-plane links [[z=N|text]] are clickable and navigate (88ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:30] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:30] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:30] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:30] "GET /sample.3md HTTP/1.1" 200 - + ✓ 20 [chromium] › component.spec.mjs:383:3 › component › a tap (pointer, no drag) on a cross-plane link navigates (89ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:30] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:30] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:30] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:30] "GET /sample.3md HTTP/1.1" 200 - + ✓ 21 [chromium] › component.spec.mjs:402:3 › component › flipbook frames are a fixed size (no resize between frames) (87ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:30] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:30] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:30] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:30] "GET /sample.3md HTTP/1.1" 200 - + ✓ 22 [chromium] › component.spec.mjs:420:3 › component › loop toggle controls whether playback wraps (91ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:30] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:30] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:30] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:30] "GET /sample.3md HTTP/1.1" 200 - + ✓ 23 [chromium] › component.spec.mjs:438:3 › component › emits planechange when stepping (91ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:30] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:30] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:30] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:30] "GET /sample.3md HTTP/1.1" 200 - + ✓ 24 [chromium] › component.spec.mjs:450:3 › component › legend values cannot inject HTML (XSS sink is escaped) (275ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:30] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:30] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:30] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:30] "GET /sample.3md HTTP/1.1" 200 - + ✓ 25 [chromium] › component.spec.mjs:485:3 › component › cross-plane links work for decimal z (not just integers) (84ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:30] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:30] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:30] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:30] "GET /sample.3md HTTP/1.1" 200 - + ✓ 26 [chromium] › component.spec.mjs:503:3 › component › switching into blend after load builds voxels (no empty stage) (272ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /sample.3md HTTP/1.1" 200 - + ✓ 27 [chromium] › component.spec.mjs:518:3 › component › blend voxels are the legend-mapped character glyphs, and billboard faces the camera (91ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /sample.3md HTTP/1.1" 200 - + ✓ 28 [chromium] › component.spec.mjs:537:3 › component › without a legend, blend voxels show the raw characters (83ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /sample.3md HTTP/1.1" 200 - + ✓ 29 [chromium] › component.spec.mjs:549:3 › component › blend is gated to COMPACT art: a sprawling grid is not voxelizable (falls back to deck) (93ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /sample.3md HTTP/1.1" 200 - + ✓ 30 [chromium] › component.spec.mjs:571:3 › component › map and layers keep every tile inside the stage on all edges (many tiles) (95ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /sample.3md HTTP/1.1" 200 - + ✓ 31 [chromium] › component.spec.mjs:598:3 › component › map orbit is clamped so an extreme pose never spills a tile off the stage (90ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - + ✓ 5 [chromium] › component.spec.mjs:94:3 › component › works with requestAnimationFrame paused (Low Power Mode) (6.1s) +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /sample.3md HTTP/1.1" 200 - + ✓ 32 [chromium] › component.spec.mjs:623:3 › component › map snaps coordinates to a non-overlapping grid (same x = column, same y = row) (90ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /sample.3md HTTP/1.1" 200 - + ✓ 33 [chromium] › component.spec.mjs:652:3 › component › map: no-coordinate planes lay out in a clean non-overlapping grid (112ms) + ✓ 34 [chromium] › component.spec.mjs:672:3 › component › map: the focused card pops to a larger readable size than the board tiles (92ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /sample.3md HTTP/1.1" 200 - + ✓ 35 [chromium] › component.spec.mjs:689:3 › component › map opens on a full-board overview (nothing forced open) until a tile is opened (92ms) + ✓ 36 [chromium] › component.spec.mjs:711:3 › component › map: partially-positioned planes (only x or only y) do not pile up (88ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:31] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 37 [chromium] › component.spec.mjs:728:3 › component › map: unpositioned planes do not collapse onto explicit (0,0) (98ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:32] "GET /index.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:32] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:32] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:32] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:32] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 39 [chromium] › lab.spec.mjs:59:3 › lab demo (index.html, backed by ) › renders via the component with no console errors (599ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:32] "GET /index.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:32] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:32] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:32] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:32] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 38 [chromium] › examples-coverage.spec.mjs:8:1 › the component renders every gallery example cleanly (1.8s) +[WebServer] ::1 - - [10/Oct/2026 11:50:33] "GET /index.html HTTP/1.1" 200 - + ✓ 40 [chromium] › lab.spec.mjs:69:3 › lab demo (index.html, backed by ) › focused plane is frontmost across the scrubber (1.2s) +[WebServer] ::1 - - [10/Oct/2026 11:50:33] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:33] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:33] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:33] "GET /index.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:33] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:33] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:33] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:34] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:34] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 42 [chromium] › lab.spec.mjs:92:3 › lab demo (index.html, backed by ) › no horizontal overflow from 320px to 1440px (843ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:34] "GET /index.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:34] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:34] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:34] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:35] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 43 [chromium] › lab.spec.mjs:102:3 › lab demo (index.html, backed by ) › stepping the component highlights the synced source (1.0s) +[WebServer] ::1 - - [10/Oct/2026 11:50:35] "GET /index.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:35] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:35] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:35] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:35] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 41 [chromium] › lab.spec.mjs:75:3 › lab demo (index.html, backed by ) › every axis tab loads, scrubs cleanly, and syncs the source panel (5.1s) +[WebServer] ::1 - - [10/Oct/2026 11:50:38] "GET /index.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:38] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:38] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:38] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:39] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 44 [chromium] › robustness.spec.mjs:37:3 › robustness (no degradation under heavy use) › no rAF-loop accumulation after switching tabs many times (3.8s) +[WebServer] ::1 - - [10/Oct/2026 11:50:39] "GET /index.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:39] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:39] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:39] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:39] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 46 [chromium] › robustness.spec.mjs:95:3 › robustness (no degradation under heavy use) › rapid play/pause and scrub leave no timers or errors (2.2s) +[WebServer] ::1 - - [10/Oct/2026 11:50:41] "GET /index.html?theme=dark HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:41] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:41] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:41] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:41] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 45 [chromium] › robustness.spec.mjs:65:3 › robustness (no degradation under heavy use) › DOM does not grow and the renderer stays correct after heavy use (3.4s) +[WebServer] ::1 - - [10/Oct/2026 11:50:42] "GET /index.html?theme=dark HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:42] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:42] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:42] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:42] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 47 [chromium] › snapshots.spec.mjs:37:3 › stage snapshot: stack (1.1s) +[WebServer] ::1 - - [10/Oct/2026 11:50:42] "GET /index.html?theme=dark HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:42] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:42] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:42] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:43] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 48 [chromium] › snapshots.spec.mjs:37:3 › stage snapshot: layers (1.1s) +[WebServer] ::1 - - [10/Oct/2026 11:50:43] "GET /index.html?theme=dark HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:43] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:43] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:43] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:43] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 49 [chromium] › snapshots.spec.mjs:37:3 › stage snapshot: scene (1.0s) +[WebServer] ::1 - - [10/Oct/2026 11:50:43] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:43] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:43] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:43] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:43] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:44] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:44] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:44] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:44] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 50 [chromium] › snapshots.spec.mjs:37:3 › stage snapshot: present (1.1s) + ✓ 51 [chromium] › viewer.spec.mjs:34:3 › viewer & editor (viewer.html) › opening the page shows lit cubes in the window (666ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:44] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:44] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:44] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:44] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:44] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:44] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:44] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:44] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:44] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:44] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:44] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:44] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:44] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:44] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:44] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:44] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:44] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:44] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 53 [chromium] › viewer.spec.mjs:152:3 › viewer & editor (viewer.html) › clicking a visible cube picks its Z slice and blank stage does not (762ms) + ✓ 52 [chromium] › viewer.spec.mjs:78:3 › viewer & editor (viewer.html) › one cell has filled faces from every side, with gold edges and glyph fill (807ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:45] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:45] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:45] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:45] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:45] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:45] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:45] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:45] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:45] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:45] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:45] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:45] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:45] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:45] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:45] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:45] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:45] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:45] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 54 [chromium] › viewer.spec.mjs:165:3 › viewer & editor (viewer.html) › renders the starter document with no console errors (781ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:46] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:46] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:46] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:46] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:46] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:46] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:46] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:46] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:46] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 55 [chromium] › viewer.spec.mjs:176:3 › viewer & editor (viewer.html) › editing the source re-renders live (1.1s) +[WebServer] ::1 - - [10/Oct/2026 11:50:46] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:46] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:46] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:46] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:46] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:46] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:46] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:46] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:46] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 56 [chromium] › viewer.spec.mjs:190:3 › viewer & editor (viewer.html) › invalid 3md shows an error without crashing (1.0s) +[WebServer] ::1 - - [10/Oct/2026 11:50:47] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:47] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:47] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:47] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:47] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:47] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:47] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:47] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:47] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 57 [chromium] › viewer.spec.mjs:204:3 › viewer & editor (viewer.html) › loading an example populates the editor and viewer (1.1s) +[WebServer] ::1 - - [10/Oct/2026 11:50:47] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:47] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:47] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:47] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:47] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:47] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:47] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:47] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:47] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 58 [chromium] › viewer.spec.mjs:218:3 › viewer & editor (viewer.html) › editor highlights syntax and numbers every line (739ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:47] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:47] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:47] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:47] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:47] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:48] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:48] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:48] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:48] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 59 [chromium] › viewer.spec.mjs:246:3 › viewer & editor (viewer.html) › Tab indents and Enter continues a list (838ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:48] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:48] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:48] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:48] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:48] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:48] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:48] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:48] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:48] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 60 [chromium] › viewer.spec.mjs:262:3 › viewer & editor (viewer.html) › clicking a plane outline chip focuses that plane (943ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:48] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:48] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:48] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:48] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:48] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:49] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:49] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:49] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:49] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 61 [chromium] › viewer.spec.mjs:273:3 › viewer & editor (viewer.html) › the highlight backdrop scrolls with the textarea (tall document) (737ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:49] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:49] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:49] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:49] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:49] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:49] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:49] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:49] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:49] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 62 [chromium] › viewer.spec.mjs:290:3 › viewer & editor (viewer.html) › smart-key edits are undoable and never corrupt the buffer (884ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:49] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:49] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:49] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:49] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:49] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:49] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:49] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:49] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:49] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 63 [chromium] › viewer.spec.mjs:311:3 › viewer & editor (viewer.html) › validity state is machine-readable via data attributes (1.1s) +[WebServer] ::1 - - [10/Oct/2026 11:50:50] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:50] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:50] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:50] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:50] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:50] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:50] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:50] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:50] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 64 [chromium] › viewer.spec.mjs:337:3 › viewer & editor (viewer.html) › Tab does not trap keyboard focus (Esc then Tab leaves the editor) (745ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:50] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:50] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:50] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:50] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:50] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:50] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:50] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:50] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:50] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 65 [chromium] › viewer.spec.mjs:351:3 › viewer & editor (viewer.html) › agent API validates and reports structured state (745ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:50] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:50] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:50] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:50] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:50] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 66 [chromium] › viewer.spec.mjs:364:3 › viewer & editor (viewer.html) › validate(src) is side-effect-free and reports the error code (668ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:51] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:51] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:51] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:51] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:51] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:51] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:51] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:51] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:51] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:51] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:51] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:51] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:51] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 67 [chromium] › viewer.spec.mjs:380:3 › viewer & editor (viewer.html) › repository search opens the 24-generation Conway document (1.2s) +[WebServer] ::1 - - [10/Oct/2026 11:50:52] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:52] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:52] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:52] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:52] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 68 [chromium] › viewer.spec.mjs:395:3 › viewer & editor (viewer.html) › kind 2 canopy opens as text in the element (1.2s) +[WebServer] ::1 - - [10/Oct/2026 11:50:52] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:52] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:52] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:52] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:52] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:52] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:52] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:52] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:52] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:52] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:52] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:52] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:52] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 69 [chromium] › viewer.spec.mjs:412:3 › viewer & editor (viewer.html) › linked village search resolves the folder (1.3s) +[WebServer] ::1 - - [10/Oct/2026 11:50:53] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:53] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:53] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:53] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:53] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 70 [chromium] › viewer.spec.mjs:426:3 › viewer & editor (viewer.html) › a composition profile shows the root and can switch entries (1.4s) +[WebServer] ::1 - - [10/Oct/2026 11:50:53] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:53] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:53] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:53] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:53] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:53] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:53] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:53] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:53] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:54] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:54] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:54] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:54] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 72 [chromium] › viewer.spec.mjs:458:3 › viewer & editor (viewer.html) › desktop layout keeps files beside a panel that switches Edit and Preview (1.0s) +[WebServer] ::1 - - [10/Oct/2026 11:50:54] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:54] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:54] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:54] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:54] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 71 [chromium] › viewer.spec.mjs:441:3 › viewer & editor (viewer.html) › markdown headings become planes and a plane search opens one (1.4s) +[WebServer] ::1 - - [10/Oct/2026 11:50:54] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:54] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:54] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:54] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:54] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:55] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:55] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:55] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:55] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:55] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:55] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:55] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:55] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 74 [chromium] › viewer.spec.mjs:546:3 › viewer & editor (viewer.html) › orbiting about 1400 gpu cubes stays interactive (960ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:55] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:55] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:55] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:55] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:55] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:56] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:56] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:56] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:56] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 73 [chromium] › viewer.spec.mjs:514:3 › viewer & editor (viewer.html) › cubes tab draws a fenced grid as translucent cubes (1.3s) +[WebServer] ::1 - - [10/Oct/2026 11:50:56] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:56] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:56] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:56] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:56] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:56] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:56] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:56] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:56] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 75 [chromium] › viewer.spec.mjs:591:3 › viewer & editor (viewer.html) › narrow layout switches Files and the document, and Edit and Preview still switch (1.2s) +[WebServer] ::1 - - [10/Oct/2026 11:50:57] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:57] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:57] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:57] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:57] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 76 [chromium] › viewer.spec.mjs:627:3 › viewer & editor (viewer.html) › an empty document reads as a neutral prompt, not a red error (1.0s) +[WebServer] ::1 - - [10/Oct/2026 11:50:57] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:57] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:57] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:57] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:57] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:57] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:57] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:57] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:57] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:57] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:57] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:57] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:57] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 77 [chromium] › viewer.spec.mjs:645:3 › viewer & editor (viewer.html) › axis lint warns on a TYPO but not on a valid free-string semantic axis (763ms) + ✓ 78 [chromium] › viewer.spec.mjs:671:3 › viewer & editor (viewer.html) › the page has no render-mode switch and does not autoplay (647ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:57] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:57] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:57] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:57] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:57] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:57] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:57] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:57] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:57] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:57] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:58] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:58] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:58] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:58] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:58] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:58] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:58] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:58] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 79 [chromium] › viewer.spec.mjs:692:3 › viewer & editor (viewer.html) › the agent schema lists error codes and the axis-to-mode map (778ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:58] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:58] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:58] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:58] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:58] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 80 [chromium] › viewer.spec.mjs:702:3 › viewer & editor (viewer.html) › dangling cross-plane links are flagged as a non-fatal warning (1.0s) +[WebServer] ::1 - - [10/Oct/2026 11:50:58] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:58] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:58] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:58] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:58] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:58] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:58] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:58] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:58] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:59] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:59] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:59] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:59] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 82 [chromium] › viewer.spec.mjs:722:3 › viewer & editor (viewer.html) › the embedded agent schema marks axis optional, only 3md required (673ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:59] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:59] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:59] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:59] "GET /assets/theme.js HTTP/1.1" 200 - + ✓ 81 [chromium] › viewer.spec.mjs:713:3 › viewer & editor (viewer.html) › a corrupt share hash signals a decode error (not a silent starter) (991ms) +[WebServer] ::1 - - [10/Oct/2026 11:50:59] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:59] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:59] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:59] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:59] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:59] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:59] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:59] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:59] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:59] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:59] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:59] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:59] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:50:59] "GET /gallery-data.json HTTP/1.1" 200 - + ✓ 83 [chromium] › viewer.spec.mjs:729:3 › viewer & editor (viewer.html) › invalid doc clears stale plane/axis data on the badge (1.0s) +[WebServer] ::1 - - [10/Oct/2026 11:51:00] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:00] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:00] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:00] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:00] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 84 [chromium] › viewer.spec.mjs:742:3 › viewer & editor (viewer.html) › an invalid document flags the offending line and the badge (1.2s) +[WebServer] ::1 - - [10/Oct/2026 11:51:00] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:00] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:00] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:00] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:00] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:00] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:00] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:00] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:00] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:00] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:00] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:00] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:00] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 85 [chromium] › viewer.spec.mjs:755:3 › viewer & editor (viewer.html) › a shared hash link restores the document (706ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:01] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:01] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:01] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:01] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:01] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:01] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:01] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:01] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:01] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 86 [chromium] › viewer.spec.mjs:766:3 › viewer & editor (viewer.html) › camera buttons and keyboard orbit, zoom, and fit without changing the document (921ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:01] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:01] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:01] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:01] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:01] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:01] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:01] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:01] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:01] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 87 [chromium] › viewer.spec.mjs:795:3 › viewer & editor (viewer.html) › full camera turns cross both poles continuously and retain geometry (709ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:01] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:02] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:02] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:02] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:02] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:02] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:02] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:02] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:02] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 88 [chromium] › viewer.spec.mjs:843:3 › viewer & editor (viewer.html) › pan tools and modified dragging move only the camera and Fit recenters (1.0s) +[WebServer] ::1 - - [10/Oct/2026 11:51:02] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:02] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:02] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:02] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:02] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 89 [chromium] › viewer.spec.mjs:874:3 › viewer & editor (viewer.html) › two fingers pan and pinch and a cancelled gesture cannot select a slice (759ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:02] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:02] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:02] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:02] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:02] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:02] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:02] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:02] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:02] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:02] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:02] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:02] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:02] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 91 [chromium] › viewer.spec.mjs:965:3 › viewer & editor (viewer.html) › phone layout leaves room for cubes and keeps controls outside the drawing (756ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:03] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:03] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:03] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:03] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:03] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:03] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:03] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:03] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:03] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 92 [chromium] › viewer.spec.mjs:987:3 › viewer & editor (viewer.html) › Document disclosure dismisses with Escape and both downloads preserve the document (922ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:04] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:04] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:04] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:04] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:04] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:04] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:04] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:04] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:04] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 93 [chromium] › viewer.spec.mjs:1024:3 › viewer & editor (viewer.html) › a prose document offers Preview without replacing its source (802ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:05] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:05] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:05] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:05] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:05] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:05] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:05] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:05] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:05] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 94 [chromium] › viewer.spec.mjs:1042:3 › viewer & editor (viewer.html) › slice navigation keeps the selected plane in a single scrolling row (675ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:05] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:05] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:05] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:05] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:05] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 90 [chromium] › viewer.spec.mjs:897:3 › viewer & editor (viewer.html) › browser camera projects and picks the shared native parity fixture (3.5s) +[WebServer] ::1 - - [10/Oct/2026 11:51:06] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:06] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:06] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:06] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:06] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:06] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:06] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:06] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:06] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:06] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:06] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:06] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:06] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 95 [chromium] › viewer.spec.mjs:1064:3 › viewer & editor (viewer.html) › a GitHub load shows busy state and recovers after a rate limit (719ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:06] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:06] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:06] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:06] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:06] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 96 [chromium] › viewer.spec.mjs:1084:3 › viewer & editor (viewer.html) › GPU unavailability explains how to keep reading in Preview (744ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:06] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:06] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:06] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:06] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:06] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:06] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:06] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:06] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:06] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:07] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:07] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:07] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:07] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 98 [chromium] › viewer.spec.mjs:1143:3 › viewer & editor (viewer.html) › composition entry switches preserve each draft without copying it into another entry (877ms) + ✓ 97 [chromium] › viewer.spec.mjs:1100:3 › viewer & editor (viewer.html) › file switches preserve edited, invalid, and empty drafts with caret and slice (1.1s) +[WebServer] ::1 - - [10/Oct/2026 11:51:07] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:07] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:07] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:07] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:07] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:07] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:07] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:07] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:07] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:07] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:08] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:08] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:08] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:08] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:08] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:08] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:08] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:08] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 99 [chromium] › viewer.spec.mjs:1170:3 › viewer & editor (viewer.html) › linked entries and file navigation share the same draft (836ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:08] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:08] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:08] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:08] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:08] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 100 [chromium] › viewer.spec.mjs:1195:3 › viewer & editor (viewer.html) › search and packing use drafts rather than original file text (937ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:08] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:08] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:08] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:08] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:08] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:08] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:08] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:08] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:08] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:08] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:08] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:08] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:08] "GET /gallery-data.json HTTP/1.1" 200 - + ✓ 101 [chromium] › viewer.spec.mjs:1212:3 › viewer & editor (viewer.html) › file filtering, keyboard selection, and phone opens reveal the document (778ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:09] "GET /viewer.html?src=original-document.3md&theme=dark HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:09] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:09] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:09] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:09] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:09] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:09] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:09] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:09] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 102 [chromium] › viewer.spec.mjs:1240:3 › viewer & editor (viewer.html) › a failed local open preserves the collection and current draft (1.1s) +[WebServer] ::1 - - [10/Oct/2026 11:51:09] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:09] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:09] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:09] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:09] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:10] "GET /viewer.html?theme=dark HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:10] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:10] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:10] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:10] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:10] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:10] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:10] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:10] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:10] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:10] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:10] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:10] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:10] "GET /viewer.html?theme=dark HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:10] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:10] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:10] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:10] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:10] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:10] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:10] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:10] "GET /gallery-data.json HTTP/1.1" 200 - + ✓ 103 [chromium] › viewer.spec.mjs:1259:3 › viewer & editor (viewer.html) › explicit document navigation removes stale source queries and reloads the chosen source (1.3s) +[WebServer] ::1 - - [10/Oct/2026 11:51:10] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:10] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:10] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:10] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:10] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:10] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:10] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:10] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:10] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 105 [chromium] › viewer.spec.mjs:1315:3 › Sculpt Slice parity › grid edits preserve CRLF, labels, prose and downloads exactly (790ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:11] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:11] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:11] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:11] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:11] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:11] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:11] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:11] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:11] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 104 [chromium] › viewer.spec.mjs:1298:3 › Sculpt Slice parity › shared native strokes, clipped brushes, four-neighbor fill and no-op undo (2.3s) +[WebServer] ::1 - - [10/Oct/2026 11:51:12] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:12] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:12] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:12] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:12] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 106 [chromium] › viewer.spec.mjs:1327:3 › Sculpt Slice parity › keyboard cells, grid zoom, previous overlay and shared WebGL reference (859ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:12] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:12] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:12] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:12] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:12] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:12] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:12] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:12] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:12] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:12] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:12] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:12] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:12] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 107 [chromium] › viewer.spec.mjs:1340:3 › Sculpt Slice parity › source typing and Slice share undo and retain it across file navigation (900ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:13] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:13] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:13] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:13] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:13] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:13] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:13] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:13] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:13] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 109 [chromium] › viewer.spec.mjs:1360:3 › Sculpt Slice parity › phone Slice tools and axis controls stay usable without horizontal page overflow (1.0s) + ✓ 108 [chromium] › viewer.spec.mjs:1352:3 › Sculpt Slice parity › unsupported grids stay readable and budget rejection restores the full stroke (1.7s) +[WebServer] ::1 - - [10/Oct/2026 11:51:14] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:14] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:14] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:14] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:14] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:14] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:14] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:14] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:14] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:14] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:14] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:14] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:14] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:14] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:14] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:14] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:14] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:14] "GET /gallery-data.json HTTP/1.1" 200 - + ✓ 110 [chromium] › viewer.spec.mjs:1369:3 › Sculpt Slice parity › 2D editing works with an unavailable WebGL reference (798ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:14] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:14] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:14] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:14] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:14] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - + ✓ 111 [chromium] › viewer.spec.mjs:1374:3 › Sculpt Slice parity › axis inverse, finite inputs, pan steps and Fit leave source and geometry intact (910ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:15] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:15] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:15] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:15] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:15] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:15] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:15] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:15] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:15] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:15] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:15] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:15] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:15] "GET /gallery-data.json HTTP/1.1" 200 - + ✓ 113 [chromium] › viewer.spec.mjs:1410:1 › Slice navigation finishes a touch stroke and ignores its late pointer movement (885ms) +(node:46807) Warning: The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set. +(Use `node --trace-warnings ...` to show where the warning was created) +[WebServer] ::1 - - [10/Oct/2026 11:51:17] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:17] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:17] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:17] "GET /sample.3md HTTP/1.1" 200 - + ✓ 114 [webkit] › component.spec.mjs:35:3 › component › upgrades, renders planes, no console errors (578ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:20] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:20] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:20] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:20] "GET /sample.3md HTTP/1.1" 200 - + ✓ 115 [webkit] › component.spec.mjs:53:3 › component › all deck cards share one width (focused matches the cards behind it) (3.6s) + ✓ 112 [chromium] › viewer.spec.mjs:1388:1 › Slice history drops only old snapshots at the per-draft and collection budgets (6.5s) +(node:46839) Warning: The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set. +(Use `node --trace-warnings ...` to show where the warning was created) +[WebServer] ::1 - - [10/Oct/2026 11:51:22] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:22] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:22] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:22] "GET /sample.3md HTTP/1.1" 200 - + ✓ 117 [webkit] › component.spec.mjs:84:3 › component › focused plane is frontmost across the scrubber (1.1s) +[WebServer] ::1 - - [10/Oct/2026 11:51:23] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:23] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:23] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:23] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:24] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:24] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:24] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:24] "GET /sample.3md HTTP/1.1" 200 - + ✓ 116 [webkit] › component.spec.mjs:69:3 › component › wide ASCII-art content is not clipped (card widens to fit rigid blocks) (3.6s) +[WebServer] ::1 - - [10/Oct/2026 11:51:27] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:27] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:27] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:27] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:27] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:27] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:27] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:27] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:27] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:27] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:27] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:27] "GET /sample.3md HTTP/1.1" 200 - + ✓ 119 [webkit] › component.spec.mjs:109:3 › component › no horizontal overflow from 320px to 1440px (3.7s) +[WebServer] ::1 - - [10/Oct/2026 11:51:28] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:28] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:28] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:28] "GET /sample.3md HTTP/1.1" 200 - + ✓ 118 [webkit] › component.spec.mjs:94:3 › component › works with requestAnimationFrame paused (Low Power Mode) (6.3s) +[WebServer] ::1 - - [10/Oct/2026 11:51:29] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:29] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:29] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:29] "GET /sample.3md HTTP/1.1" 200 - + ✓ 121 [webkit] › component.spec.mjs:139:3 › component › frame animations render as a flipbook (one frame, no deck) and autoplay (277ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:29] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:29] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:29] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:29] "GET /sample.3md HTTP/1.1" 200 - + ✓ 122 [webkit] › component.spec.mjs:160:3 › component › does not auto-convert characters; an optional legend maps them (279ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:30] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:30] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:30] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:30] "GET /sample.3md HTTP/1.1" 200 - + ✓ 123 [webkit] › component.spec.mjs:184:3 › component › camera: WASD/wheel/orbit move the scene; retired modes alias (271ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:30] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:30] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:30] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:30] "GET /sample.3md HTTP/1.1" 200 - + ✓ 124 [webkit] › component.spec.mjs:210:3 › component › map mode lays planes out by x/y (258ms) + ✓ 120 [webkit] › component.spec.mjs:123:3 › component › playback advances and pauses (animations) (2.6s) +[WebServer] ::1 - - [10/Oct/2026 11:51:30] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:30] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:30] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:30] "GET /sample.3md HTTP/1.1" 200 - + ✓ 125 [webkit] › component.spec.mjs:223:3 › component › renders Markdown tables (not raw pipes) (269ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:30] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:30] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:30] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:30] "GET /sample.3md HTTP/1.1" 200 - + ✓ 126 [webkit] › component.spec.mjs:239:3 › component › layers shows aligned overlays at once, with toggle chips (268ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:30] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:30] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:30] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:30] "GET /sample.3md HTTP/1.1" 200 - + ✓ 127 [webkit] › component.spec.mjs:261:3 › component › blend mode renders content as 3D voxels (265ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:30] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:30] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:30] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:30] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:31] "GET /embed-example.html HTTP/1.1" 200 - + ✓ 128 [webkit] › component.spec.mjs:281:3 › component › single-card mode shows only the focused plane (376ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:31] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:31] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:31] "GET /sample.3md HTTP/1.1" 200 - + ✓ 129 [webkit] › component.spec.mjs:303:3 › component › single-card mode scrolls a long plane (reader) (274ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:31] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:31] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:31] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:31] "GET /sample.3md HTTP/1.1" 200 - + ✓ 130 [webkit] › component.spec.mjs:326:3 › component › reflects the resolved mode as data-mode (for fullscreen styling) (262ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:31] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:31] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:31] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:31] "GET /sample.3md HTTP/1.1" 200 - + ✓ 131 [webkit] › component.spec.mjs:343:3 › component › space and PageDown advance like a slideshow (not in reader) (265ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:31] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:31] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:31] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:31] "GET /sample.3md HTTP/1.1" 200 - + ✓ 132 [webkit] › component.spec.mjs:366:3 › component › cross-plane links [[z=N|text]] are clickable and navigate (261ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:31] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:31] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:31] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:31] "GET /sample.3md HTTP/1.1" 200 - + ✓ 133 [webkit] › component.spec.mjs:383:3 › component › a tap (pointer, no drag) on a cross-plane link navigates (266ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:31] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:31] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:31] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:31] "GET /sample.3md HTTP/1.1" 200 - + ✓ 134 [webkit] › component.spec.mjs:402:3 › component › flipbook frames are a fixed size (no resize between frames) (266ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:31] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:31] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:31] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:31] "GET /sample.3md HTTP/1.1" 200 - + ✓ 135 [webkit] › component.spec.mjs:420:3 › component › loop toggle controls whether playback wraps (270ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:32] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:32] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:32] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:32] "GET /sample.3md HTTP/1.1" 200 - + ✓ 136 [webkit] › component.spec.mjs:438:3 › component › emits planechange when stepping (271ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:32] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:32] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:32] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:32] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:32] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:32] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:32] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:32] "GET /sample.3md HTTP/1.1" 200 - + ✓ 137 [webkit] › component.spec.mjs:450:3 › component › legend values cannot inject HTML (XSS sink is escaped) (465ms) + ✓ 138 [webkit] › component.spec.mjs:485:3 › component › cross-plane links work for decimal z (not just integers) (273ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:32] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:32] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:32] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:32] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:32] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:32] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:32] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:32] "GET /sample.3md HTTP/1.1" 200 - + ✓ 140 [webkit] › component.spec.mjs:518:3 › component › blend voxels are the legend-mapped character glyphs, and billboard faces the camera (297ms) + ✓ 139 [webkit] › component.spec.mjs:503:3 › component › switching into blend after load builds voxels (no empty stage) (466ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:33] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:33] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:33] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:33] "GET /sample.3md HTTP/1.1" 200 - + ✓ 141 [webkit] › component.spec.mjs:537:3 › component › without a legend, blend voxels show the raw characters (266ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:33] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:33] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:33] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:33] "GET /sample.3md HTTP/1.1" 200 - + ✓ 142 [webkit] › component.spec.mjs:549:3 › component › blend is gated to COMPACT art: a sprawling grid is not voxelizable (falls back to deck) (267ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:33] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:33] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:33] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:33] "GET /sample.3md HTTP/1.1" 200 - + ✓ 143 [webkit] › component.spec.mjs:571:3 › component › map and layers keep every tile inside the stage on all edges (many tiles) (278ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:33] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:33] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:33] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:33] "GET /sample.3md HTTP/1.1" 200 - + ✓ 144 [webkit] › component.spec.mjs:598:3 › component › map orbit is clamped so an extreme pose never spills a tile off the stage (255ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:33] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:33] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:33] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:33] "GET /sample.3md HTTP/1.1" 200 - + ✓ 146 [webkit] › component.spec.mjs:652:3 › component › map: no-coordinate planes lay out in a clean non-overlapping grid (277ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:34] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:34] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:34] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:34] "GET /sample.3md HTTP/1.1" 200 - + ✓ 147 [webkit] › component.spec.mjs:672:3 › component › map: the focused card pops to a larger readable size than the board tiles (256ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:34] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:34] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:34] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:34] "GET /sample.3md HTTP/1.1" 200 - + ✓ 148 [webkit] › component.spec.mjs:689:3 › component › map opens on a full-board overview (nothing forced open) until a tile is opened (263ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:34] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:34] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:34] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:34] "GET /sample.3md HTTP/1.1" 200 - + ✓ 149 [webkit] › component.spec.mjs:711:3 › component › map: partially-positioned planes (only x or only y) do not pile up (247ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:34] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:34] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:34] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:34] "GET /sample.3md HTTP/1.1" 200 - + ✓ 150 [webkit] › component.spec.mjs:728:3 › component › map: unpositioned planes do not collapse onto explicit (0,0) (278ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:35] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:35] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:35] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:35] "GET /sample.3md HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:35] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:36] "GET /embed-example.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:36] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:36] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:36] "GET /sample.3md HTTP/1.1" 200 - + ✓ 145 [webkit] › component.spec.mjs:623:3 › component › map snaps coordinates to a non-overlapping grid (same x = column, same y = row) (3.5s) + ✓ 151 [webkit] › examples-coverage.spec.mjs:8:1 › the component renders every gallery example cleanly (3.2s) +[WebServer] ::1 - - [10/Oct/2026 11:51:38] "GET /index.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:38] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:38] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:38] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:38] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 153 [webkit] › lab.spec.mjs:69:3 › lab demo (index.html, backed by ) › focused plane is frontmost across the scrubber (1.1s) +[WebServer] ::1 - - [10/Oct/2026 11:51:39] "GET /index.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:39] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:39] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:39] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:39] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:40] "GET /index.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:40] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:40] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:40] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:40] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 152 [webkit] › lab.spec.mjs:59:3 › lab demo (index.html, backed by ) › renders via the component with no console errors (4.0s) +[WebServer] ::1 - - [10/Oct/2026 11:51:41] "GET /index.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:41] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:41] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:41] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:41] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:41] "GET /index.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:41] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:41] "GET /index.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:41] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:41] "GET /index.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:41] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:41] "GET /index.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:41] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 155 [webkit] › lab.spec.mjs:92:3 › lab demo (index.html, backed by ) › no horizontal overflow from 320px to 1440px (864ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:42] "GET /index.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:42] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:42] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:42] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:42] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 156 [webkit] › lab.spec.mjs:102:3 › lab demo (index.html, backed by ) › stepping the component highlights the synced source (977ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:42] "GET /index.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:43] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:43] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:43] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:43] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 154 [webkit] › lab.spec.mjs:75:3 › lab demo (index.html, backed by ) › every axis tab loads, scrubs cleanly, and syncs the source panel (4.8s) +[WebServer] ::1 - - [10/Oct/2026 11:51:44] "GET /index.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:44] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:44] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:44] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:44] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 157 [webkit] › robustness.spec.mjs:37:3 › robustness (no degradation under heavy use) › no rAF-loop accumulation after switching tabs many times (4.3s) +[WebServer] ::1 - - [10/Oct/2026 11:51:47] "GET /index.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:47] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:47] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:47] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:47] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 158 [webkit] › robustness.spec.mjs:65:3 › robustness (no degradation under heavy use) › DOM does not grow and the renderer stays correct after heavy use (4.0s) +[WebServer] ::1 - - [10/Oct/2026 11:51:48] "GET /index.html?theme=dark HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:48] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:48] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:48] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:48] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 160 [webkit] › snapshots.spec.mjs:37:3 › stage snapshot: stack (999ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:49] "GET /index.html?theme=dark HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:49] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:49] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:49] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - + ✓ 159 [webkit] › robustness.spec.mjs:95:3 › robustness (no degradation under heavy use) › rapid play/pause and scrub leave no timers or errors (2.2s) +[WebServer] ::1 - - [10/Oct/2026 11:51:49] "GET /index.html?theme=dark HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:49] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:49] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:49] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:49] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:49] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 161 [webkit] › snapshots.spec.mjs:37:3 › stage snapshot: layers (1.0s) + ✓ 162 [webkit] › snapshots.spec.mjs:37:3 › stage snapshot: scene (976ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:50] "GET /index.html?theme=dark HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:50] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:50] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:50] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:50] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:50] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:50] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:50] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:50] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:50] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:50] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:50] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:50] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:50] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 164 [webkit] › viewer.spec.mjs:34:3 › viewer & editor (viewer.html) › opening the page shows lit cubes in the window (423ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:50] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:50] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:50] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:50] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:50] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:50] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:50] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:50] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:50] "GET /gallery-data.json HTTP/1.1" 200 - + ✓ 163 [webkit] › snapshots.spec.mjs:37:3 › stage snapshot: present (1.0s) +[WebServer] ::1 - - [10/Oct/2026 11:51:51] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:51] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:51] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:51] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:51] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:51] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:51] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:51] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:51] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 165 [webkit] › viewer.spec.mjs:78:3 › viewer & editor (viewer.html) › one cell has filled faces from every side, with gold edges and glyph fill (789ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:51] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:51] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:51] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:51] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:51] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:51] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:51] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:51] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:51] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 166 [webkit] › viewer.spec.mjs:152:3 › viewer & editor (viewer.html) › clicking a visible cube picks its Z slice and blank stage does not (692ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:52] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:52] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:52] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:52] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:52] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:52] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:52] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:52] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:52] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 167 [webkit] › viewer.spec.mjs:165:3 › viewer & editor (viewer.html) › renders the starter document with no console errors (611ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:52] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:52] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:52] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:52] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:52] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:52] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:52] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:52] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:52] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 168 [webkit] › viewer.spec.mjs:176:3 › viewer & editor (viewer.html) › editing the source re-renders live (986ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:53] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:53] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:53] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:53] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:53] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:53] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:53] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:53] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:53] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 169 [webkit] › viewer.spec.mjs:190:3 › viewer & editor (viewer.html) › invalid 3md shows an error without crashing (1.0s) +[WebServer] ::1 - - [10/Oct/2026 11:51:53] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:53] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:53] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:53] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:53] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:53] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:53] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:53] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:53] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 170 [webkit] › viewer.spec.mjs:204:3 › viewer & editor (viewer.html) › loading an example populates the editor and viewer (1.1s) +[WebServer] ::1 - - [10/Oct/2026 11:51:54] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:54] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:54] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:54] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:54] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:54] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:54] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:54] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:54] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 171 [webkit] › viewer.spec.mjs:218:3 › viewer & editor (viewer.html) › editor highlights syntax and numbers every line (1.1s) +[WebServer] ::1 - - [10/Oct/2026 11:51:54] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:54] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:54] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:54] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:54] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:54] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:54] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:54] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:54] "GET /gallery-data.json HTTP/1.1" 200 - + ✓ 172 [webkit] › viewer.spec.mjs:246:3 › viewer & editor (viewer.html) › Tab indents and Enter continues a list (733ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:54] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:54] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:54] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:54] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:54] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:54] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:54] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:54] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:54] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 173 [webkit] › viewer.spec.mjs:262:3 › viewer & editor (viewer.html) › clicking a plane outline chip focuses that plane (948ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:55] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:55] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:55] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:55] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:55] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:55] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:55] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:55] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:55] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 174 [webkit] › viewer.spec.mjs:273:3 › viewer & editor (viewer.html) › the highlight backdrop scrolls with the textarea (tall document) (840ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:55] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:55] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:55] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:55] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:55] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:55] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:55] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:55] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:55] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 175 [webkit] › viewer.spec.mjs:290:3 › viewer & editor (viewer.html) › smart-key edits are undoable and never corrupt the buffer (831ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:56] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:56] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:56] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:56] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:56] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:56] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:56] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:56] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:56] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 176 [webkit] › viewer.spec.mjs:311:3 › viewer & editor (viewer.html) › validity state is machine-readable via data attributes (902ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:56] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:56] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:56] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:56] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:56] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:56] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:56] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:56] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:56] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 177 [webkit] › viewer.spec.mjs:337:3 › viewer & editor (viewer.html) › Tab does not trap keyboard focus (Esc then Tab leaves the editor) (716ms) + ✓ 178 [webkit] › viewer.spec.mjs:351:3 › viewer & editor (viewer.html) › agent API validates and reports structured state (548ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:57] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:57] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:57] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:57] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:57] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:57] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:57] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:57] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:57] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:57] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:57] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:57] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:57] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:57] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:57] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:57] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:57] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:57] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 179 [webkit] › viewer.spec.mjs:364:3 › viewer & editor (viewer.html) › validate(src) is side-effect-free and reports the error code (637ms) +[WebServer] ::1 - - [10/Oct/2026 11:51:57] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:57] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:57] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:57] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:57] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:57] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:57] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:57] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:57] "GET /gallery-data.json HTTP/1.1" 200 - + ✓ 180 [webkit] › viewer.spec.mjs:380:3 › viewer & editor (viewer.html) › repository search opens the 24-generation Conway document (1.1s) +[WebServer] ::1 - - [10/Oct/2026 11:51:58] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:58] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:58] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:58] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:58] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:58] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:58] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:58] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:58] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 181 [webkit] › viewer.spec.mjs:395:3 › viewer & editor (viewer.html) › kind 2 canopy opens as text in the element (1.1s) +[WebServer] ::1 - - [10/Oct/2026 11:51:58] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:58] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:58] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:58] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:58] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:58] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:58] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:58] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:58] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 182 [webkit] › viewer.spec.mjs:412:3 › viewer & editor (viewer.html) › linked village search resolves the folder (1.0s) +[WebServer] ::1 - - [10/Oct/2026 11:51:59] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:59] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:59] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:59] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:59] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:59] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:59] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:59] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:51:59] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 183 [webkit] › viewer.spec.mjs:426:3 › viewer & editor (viewer.html) › a composition profile shows the root and can switch entries (1.3s) +[WebServer] ::1 - - [10/Oct/2026 11:52:00] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:00] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:00] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:00] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:00] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:00] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:00] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:00] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:00] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 184 [webkit] › viewer.spec.mjs:441:3 › viewer & editor (viewer.html) › markdown headings become planes and a plane search opens one (1.3s) + ✓ 185 [webkit] › viewer.spec.mjs:458:3 › viewer & editor (viewer.html) › desktop layout keeps files beside a panel that switches Edit and Preview (779ms) +[WebServer] ::1 - - [10/Oct/2026 11:52:00] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:00] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:00] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:00] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:00] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:00] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:00] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:00] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:00] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:00] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:00] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:00] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:00] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:00] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:00] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:00] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:00] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:00] "GET /gallery-data.json HTTP/1.1" 200 - + ✓ 187 [webkit] › viewer.spec.mjs:546:3 › viewer & editor (viewer.html) › orbiting about 1400 gpu cubes stays interactive (781ms) +[WebServer] ::1 - - [10/Oct/2026 11:52:01] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:01] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:01] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:01] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:01] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:01] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:01] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:01] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:01] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 186 [webkit] › viewer.spec.mjs:514:3 › viewer & editor (viewer.html) › cubes tab draws a fenced grid as translucent cubes (1.3s) +[WebServer] ::1 - - [10/Oct/2026 11:52:01] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:01] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:01] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:01] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:01] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:01] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:01] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:01] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:01] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 188 [webkit] › viewer.spec.mjs:591:3 › viewer & editor (viewer.html) › narrow layout switches Files and the document, and Edit and Preview still switch (832ms) +[WebServer] ::1 - - [10/Oct/2026 11:52:02] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:02] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:02] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:02] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:02] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:02] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:02] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:02] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:02] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 189 [webkit] › viewer.spec.mjs:627:3 › viewer & editor (viewer.html) › an empty document reads as a neutral prompt, not a red error (992ms) + ✓ 190 [webkit] › viewer.spec.mjs:645:3 › viewer & editor (viewer.html) › axis lint warns on a TYPO but not on a valid free-string semantic axis (501ms) +[WebServer] ::1 - - [10/Oct/2026 11:52:02] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:02] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:02] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:02] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:02] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:02] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:02] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:02] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:02] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:02] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:02] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:02] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:02] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:02] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:02] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:02] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:02] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:02] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 191 [webkit] › viewer.spec.mjs:671:3 › viewer & editor (viewer.html) › the page has no render-mode switch and does not autoplay (476ms) + ✓ 192 [webkit] › viewer.spec.mjs:692:3 › viewer & editor (viewer.html) › the agent schema lists error codes and the axis-to-mode map (493ms) +[WebServer] ::1 - - [10/Oct/2026 11:52:03] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:03] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:03] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:03] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:03] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:03] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:03] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:03] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:03] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:03] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:03] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:03] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:03] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:03] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:03] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:03] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:03] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:03] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 194 [webkit] › viewer.spec.mjs:713:3 › viewer & editor (viewer.html) › a corrupt share hash signals a decode error (not a silent starter) (730ms) + ✓ 193 [webkit] › viewer.spec.mjs:702:3 › viewer & editor (viewer.html) › dangling cross-plane links are flagged as a non-fatal warning (923ms) +[WebServer] ::1 - - [10/Oct/2026 11:52:04] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:04] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:04] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:04] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:04] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:04] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:04] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:04] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:04] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:04] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:04] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:04] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:04] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:04] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:04] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:04] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:04] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:04] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 195 [webkit] › viewer.spec.mjs:722:3 › viewer & editor (viewer.html) › the embedded agent schema marks axis optional, only 3md required (404ms) +[WebServer] ::1 - - [10/Oct/2026 11:52:04] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:04] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:04] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:04] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:04] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:04] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:04] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:04] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:04] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 196 [webkit] › viewer.spec.mjs:729:3 › viewer & editor (viewer.html) › invalid doc clears stale plane/axis data on the badge (989ms) + ✓ 197 [webkit] › viewer.spec.mjs:742:3 › viewer & editor (viewer.html) › an invalid document flags the offending line and the badge (927ms) +[WebServer] ::1 - - [10/Oct/2026 11:52:05] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:05] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:05] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:05] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:05] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:05] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:05] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:05] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:05] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:05] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:05] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:05] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:05] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:05] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:05] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:05] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:05] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:05] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 198 [webkit] › viewer.spec.mjs:755:3 › viewer & editor (viewer.html) › a shared hash link restores the document (493ms) +[WebServer] ::1 - - [10/Oct/2026 11:52:05] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:05] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:05] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:05] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:05] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:05] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:05] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:05] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:05] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 199 [webkit] › viewer.spec.mjs:766:3 › viewer & editor (viewer.html) › camera buttons and keyboard orbit, zoom, and fit without changing the document (761ms) + ✓ 200 [webkit] › viewer.spec.mjs:795:3 › viewer & editor (viewer.html) › full camera turns cross both poles continuously and retain geometry (557ms) +[WebServer] ::1 - - [10/Oct/2026 11:52:06] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:06] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:06] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:06] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:06] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:06] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:06] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:06] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:06] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:06] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:06] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:06] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:06] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:06] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:06] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:06] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:06] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:06] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 201 [webkit] › viewer.spec.mjs:843:3 › viewer & editor (viewer.html) › pan tools and modified dragging move only the camera and Fit recenters (671ms) + ✓ 202 [webkit] › viewer.spec.mjs:874:3 › viewer & editor (viewer.html) › two fingers pan and pinch and a cancelled gesture cannot select a slice (608ms) +[WebServer] ::1 - - [10/Oct/2026 11:52:06] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:06] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:06] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:06] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:06] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:06] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:06] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:06] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:06] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:06] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:06] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:06] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:06] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:06] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:06] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:06] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:06] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:06] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 204 [webkit] › viewer.spec.mjs:965:3 › viewer & editor (viewer.html) › phone layout leaves room for cubes and keeps controls outside the drawing (763ms) +[WebServer] ::1 - - [10/Oct/2026 11:52:07] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:07] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:07] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:07] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:07] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:07] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:07] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:07] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:07] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 205 [webkit] › viewer.spec.mjs:987:3 › viewer & editor (viewer.html) › Document disclosure dismisses with Escape and both downloads preserve the document (805ms) +[WebServer] ::1 - - [10/Oct/2026 11:52:08] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:08] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:08] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:08] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:08] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:08] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:08] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:08] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:08] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 206 [webkit] › viewer.spec.mjs:1024:3 › viewer & editor (viewer.html) › a prose document offers Preview without replacing its source (767ms) +[WebServer] ::1 - - [10/Oct/2026 11:52:09] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:09] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:09] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:09] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:09] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:09] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:09] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:09] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:09] "GET /gallery-data.json HTTP/1.1" 200 - + ✓ 207 [webkit] › viewer.spec.mjs:1042:3 › viewer & editor (viewer.html) › slice navigation keeps the selected plane in a single scrolling row (598ms) +[WebServer] ::1 - - [10/Oct/2026 11:52:09] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:09] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:09] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:09] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:09] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:09] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:09] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:09] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:09] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 208 [webkit] › viewer.spec.mjs:1064:3 › viewer & editor (viewer.html) › a GitHub load shows busy state and recovers after a rate limit (581ms) +[WebServer] ::1 - - [10/Oct/2026 11:52:10] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:10] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:10] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:10] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:10] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:10] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:10] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:10] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:10] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 203 [webkit] › viewer.spec.mjs:897:3 › viewer & editor (viewer.html) › browser camera projects and picks the shared native parity fixture (4.1s) + ✓ 209 [webkit] › viewer.spec.mjs:1084:3 › viewer & editor (viewer.html) › GPU unavailability explains how to keep reading in Preview (641ms) +[WebServer] ::1 - - [10/Oct/2026 11:52:11] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:11] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:11] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:11] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:11] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:11] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:11] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:11] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:11] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:11] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:11] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:11] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:11] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:11] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:11] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:11] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:11] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:11] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 211 [webkit] › viewer.spec.mjs:1143:3 › viewer & editor (viewer.html) › composition entry switches preserve each draft without copying it into another entry (864ms) + ✓ 210 [webkit] › viewer.spec.mjs:1100:3 › viewer & editor (viewer.html) › file switches preserve edited, invalid, and empty drafts with caret and slice (1.1s) +[WebServer] ::1 - - [10/Oct/2026 11:52:12] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:12] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:12] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:12] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:12] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:12] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:12] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:12] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:12] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:12] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:12] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:12] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:12] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:12] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:12] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:12] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:12] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:12] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 212 [webkit] › viewer.spec.mjs:1170:3 › viewer & editor (viewer.html) › linked entries and file navigation share the same draft (721ms) +[WebServer] ::1 - - [10/Oct/2026 11:52:12] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:12] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:12] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:12] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:12] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:12] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:12] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:12] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:12] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 213 [webkit] › viewer.spec.mjs:1195:3 › viewer & editor (viewer.html) › search and packing use drafts rather than original file text (888ms) +[WebServer] ::1 - - [10/Oct/2026 11:52:13] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:13] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:13] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:13] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:13] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:13] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:13] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:13] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:13] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 214 [webkit] › viewer.spec.mjs:1212:3 › viewer & editor (viewer.html) › file filtering, keyboard selection, and phone opens reveal the document (982ms) +[WebServer] ::1 - - [10/Oct/2026 11:52:13] "GET /viewer.html?src=original-document.3md&theme=dark HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:13] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:13] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:13] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:13] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:13] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:13] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:13] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:13] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 215 [webkit] › viewer.spec.mjs:1240:3 › viewer & editor (viewer.html) › a failed local open preserves the collection and current draft (1.0s) +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /viewer.html?theme=dark HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /viewer.html?theme=dark HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /gallery-data.json HTTP/1.1" 200 - + ✓ 216 [webkit] › viewer.spec.mjs:1259:3 › viewer & editor (viewer.html) › explicit document navigation removes stale source queries and reloads the chosen source (1.0s) +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:14] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:15] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:15] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:15] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:15] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:15] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:15] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:15] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:15] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:15] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:15] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 218 [webkit] › viewer.spec.mjs:1315:3 › Sculpt Slice parity › grid edits preserve CRLF, labels, prose and downloads exactly (856ms) +[WebServer] ::1 - - [10/Oct/2026 11:52:15] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:15] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:15] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:15] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:15] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:15] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:15] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:15] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:15] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:15] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:15] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:15] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:15] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:15] "GET /nested-examples.json HTTP/1.1" 200 - + ✓ 217 [webkit] › viewer.spec.mjs:1298:3 › Sculpt Slice parity › shared native strokes, clipped brushes, four-neighbor fill and no-op undo (1.8s) +[WebServer] ::1 - - [10/Oct/2026 11:52:15] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:15] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:15] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:15] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:15] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:15] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:15] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:15] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:15] "GET /gallery-data.json HTTP/1.1" 200 - + ✓ 219 [webkit] › viewer.spec.mjs:1327:3 › Sculpt Slice parity › keyboard cells, grid zoom, previous overlay and shared WebGL reference (813ms) +[WebServer] ::1 - - [10/Oct/2026 11:52:16] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:16] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:16] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:16] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:16] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:16] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:16] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:16] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:16] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 220 [webkit] › viewer.spec.mjs:1340:3 › Sculpt Slice parity › source typing and Slice share undo and retain it across file navigation (894ms) +[WebServer] ::1 - - [10/Oct/2026 11:52:16] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:16] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:16] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:16] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:16] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:16] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:16] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:16] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:16] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 221 [webkit] › viewer.spec.mjs:1352:3 › Sculpt Slice parity › unsupported grids stay readable and budget rejection restores the full stroke (857ms) +[WebServer] ::1 - - [10/Oct/2026 11:52:17] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:17] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:17] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:17] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:17] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:17] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:17] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:17] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:17] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 222 [webkit] › viewer.spec.mjs:1360:3 › Sculpt Slice parity › phone Slice tools and axis controls stay usable without horizontal page overflow (1.0s) + ✓ 223 [webkit] › viewer.spec.mjs:1369:3 › Sculpt Slice parity › 2D editing works with an unavailable WebGL reference (665ms) +[WebServer] ::1 - - [10/Oct/2026 11:52:17] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:17] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:17] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:17] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:17] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:17] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:17] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:17] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:17] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:17] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:17] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:17] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:17] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:17] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:17] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:17] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:17] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:17] "GET /all-examples.json HTTP/1.1" 200 - + ✓ 224 [webkit] › viewer.spec.mjs:1374:3 › Sculpt Slice parity › axis inverse, finite inputs, pan steps and Fit leave source and geometry intact (802ms) +[WebServer] ::1 - - [10/Oct/2026 11:52:18] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:18] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:18] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:18] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:18] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:18] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:18] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:18] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:52:18] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 226 [webkit] › viewer.spec.mjs:1410:1 › Slice navigation finishes a touch stroke and ignores its late pointer movement (799ms) + ✓ 225 [webkit] › viewer.spec.mjs:1388:1 › Slice history drops only old snapshots at the per-draft and collection budgets (7.2s) + + 226 passed (2.0m) diff --git a/docs/evidence/viewer-slice/native-full.log b/docs/evidence/viewer-slice/native-full.log new file mode 100644 index 00000000..f0cbb0f4 --- /dev/null +++ b/docs/evidence/viewer-slice/native-full.log @@ -0,0 +1,1584 @@ +Building for debugging... +[0/8] Write sources +[2/8] Write swift-version--58304C5D6DBC2206.txt +[4/10] Compiling RookRenderingTests SculptureLiveVoxelTests.swift +[5/10] Emitting module RookRenderingTests +[6/10] Compiling RookApp SculptureViewport.swift +[7/10] Emitting module RookApp +[7/12] Write Objects.LinkFileList +[8/12] Linking Rook +[9/12] Applying Rook +[11/13] Emitting module RookAppTests +[11/13] Write Objects.LinkFileList +[12/13] Linking RookPackageTests +Build complete! (6.08s) +Test Suite 'Selected tests' started at 2026-10-10 11:45:50.126. +Test Suite 'RookPackageTests.xctest' started at 2026-10-10 11:45:50.127. +Test Suite 'RookPackageTests.xctest' passed at 2026-10-10 11:45:50.127. + Executed 0 tests, with 0 failures (0 unexpected) in 0.000 (0.000) seconds +Test Suite 'Selected tests' passed at 2026-10-10 11:45:50.127. + Executed 0 tests, with 0 failures (0 unexpected) in 0.000 (0.002) seconds +◇ Test run started. +↳ Testing Library Version: 1902 +↳ Target Platform: arm64e-apple-macos14.0 +◇ Test systemPreferenceDefersToMacAppearance() started. +✔ Test systemPreferenceDefersToMacAppearance() passed after 0.001 seconds. +◇ Test largeSliceGridFitAndZoomKeepSquareCellsWithinTheirCanvas() started. +✔ Test largeSliceGridFitAndZoomKeepSquareCellsWithinTheirCanvas() passed after 0.001 seconds. +◇ Test rectangularSliceGridUsesItsActualAspectRatioAtEveryZoom() started. +✔ Test rectangularSliceGridUsesItsActualAspectRatioAtEveryZoom() passed after 0.001 seconds. +◇ Test maximumVolumeGridZoomCanReachTheLastCellPrecisely() started. +✔ Test maximumVolumeGridZoomCanReachTheLastCellPrecisely() passed after 0.001 seconds. +◇ Test scrollingChangesViewportPositionWithoutChangingLocalCellCoordinates() started. +✔ Test scrollingChangesViewportPositionWithoutChangingLocalCellCoordinates() passed after 0.001 seconds. +◇ Test gridHitTestingRejectsOutsideNonFiniteAndUnavailableGeometry() started. +✔ Test gridHitTestingRejectsOutsideNonFiniteAndUnavailableGeometry() passed after 0.001 seconds. +◇ Suite LayerGridScrollPresentationTests started. +◇ Test nativeClipMeasurementIsWindowScopedAndDisconnectsWhenDismantled() started. +✔ Test nativeClipMeasurementIsWindowScopedAndDisconnectsWhenDismantled() passed after 0.506 seconds. +◇ Test nativeZoomedSliceKeepsDrawingAfterItsOriginScrollsOutOfView() started. +✔ Test nativeZoomedSliceKeepsDrawingAfterItsOriginScrollsOutOfView() passed after 0.941 seconds. +✔ Suite LayerGridScrollPresentationTests passed after 1.448 seconds. +◇ Suite SculptureCanvasPointerTests started. +◇ Test nativePointerDispatchesTopLeftCoordinatesAndAllMousePhases() started. +✔ Test nativePointerDispatchesTopLeftCoordinatesAndAllMousePhases() passed after 0.026 seconds. +◇ Test pointerEventsStayWithinTheirOwnWindow() started. +✔ Test pointerEventsStayWithinTheirOwnWindow() passed after 0.023 seconds. +◇ Test mouseInputDoesNotStealTheExistingKeyboardResponder() started. +✔ Test mouseInputDoesNotStealTheExistingKeyboardResponder() passed after 0.010 seconds. +◇ Test modifiedDragsPanWithoutDispatchingPaintOrSelectionEvents() started. +✔ Test modifiedDragsPanWithoutDispatchingPaintOrSelectionEvents() passed after 0.019 seconds. +✔ Suite SculptureCanvasPointerTests passed after 0.080 seconds. +◇ Suite SculptureCommandFocusTests started. +◇ Test nativeSearchTakesPriorTitleResponderAndReturnRunsFilteredAction() started. +✔ Test nativeSearchTakesPriorTitleResponderAndReturnRunsFilteredAction() passed after 0.498 seconds. +◇ Test nativeSearchReturnHandsMountedCanvasRealArrowAndSpaceEvents() started. +✔ Test nativeSearchReturnHandsMountedCanvasRealArrowAndSpaceEvents() passed after 0.298 seconds. +◇ Test nativeSearchEscapeUnmountsAndDoesNotRetakeRestoredTitleResponder() started. +✔ Test nativeSearchEscapeUnmountsAndDoesNotRetakeRestoredTitleResponder() passed after 0.281 seconds. +✔ Suite SculptureCommandFocusTests passed after 1.078 seconds. +◇ Test compositionDraftStartsWithSmallReferencedModelsAndDistinctMapCharacters() started. +✔ Test compositionDraftStartsWithSmallReferencedModelsAndDistinctMapCharacters() passed after 0.042 seconds. +◇ Test compositionTilePlacementAndErasingDoNotAlterReferencedModels() started. +✔ Test compositionTilePlacementAndErasingDoNotAlterReferencedModels() passed after 0.001 seconds. +◇ Test compositionShrinkRefusesOccupiedClippingAndKeepsSurvivingRowsAligned() started. +✔ Test compositionShrinkRefusesOccupiedClippingAndKeepsSurvivingRowsAligned() passed after 0.001 seconds. +◇ Test compositionReopeningRetainsNestedGraphAndRotationChangesOnlyItsBinding() started. +✔ Test compositionReopeningRetainsNestedGraphAndRotationChangesOnlyItsBinding() passed after 0.001 seconds. +◇ Test compositionInsertionRemapsEntireGraphAndKeepsRepeatedReferencesSelfContained() started. +✔ Test compositionInsertionRemapsEntireGraphAndKeepsRepeatedReferencesSelfContained() passed after 0.445 seconds. +◇ Test compositionTitleDraftAndBoundsErrorsDoNotDiscardMapOrLibrary() started. +✔ Test compositionTitleDraftAndBoundsErrorsDoNotDiscardMapOrLibrary() passed after 0.001 seconds. +◇ Test cancelingCompositionPreparationNeverOpensTheCanceledSnapshot() started. +✔ Test cancelingCompositionPreparationNeverOpensTheCanceledSnapshot() passed after 0.001 seconds. +◇ Suite SculptureEditorPresentationTests started. +◇ Test actualEditorViewsRenderAtMinimumAndDefaultSizes() started. +Retained editor presentation captures: /Users/leif/Development/_CorvidLabs/3md-edit-preview/apps/sculpt/.build/verification/editor-presentation-89EEEAED-B01F-42CB-AB5C-51F09B194E67 +✔ Test actualEditorViewsRenderAtMinimumAndDefaultSizes() passed after 9.787 seconds. +✔ Suite SculptureEditorPresentationTests passed after 9.787 seconds. +◇ Test "Export names cannot introduce paths or hidden files" started. +✔ Test "Export names cannot introduce paths or hidden files" passed after 0.018 seconds. +◇ Test "Preparing a mesh export keeps the source and cleans up its private staging folder" started. +✔ Test "Preparing a mesh export keeps the source and cleans up its private staging folder" passed after 0.016 seconds. +◇ Suite SculptureGalleryBrowserTests started. +◇ Test listingGroupsEveryEntryWithItsSizeAndGeneratesNothingUntilAsked() started. +✔ Test listingGroupsEveryEntryWithItsSizeAndGeneratesNothingUntilAsked() passed after 0.024 seconds. +◇ Test filtersNarrowByKindCategoryAndSearch() started. +✔ Test filtersNarrowByKindCategoryAndSearch() passed after 0.001 seconds. +◇ Test openingAModelHandsItsPreparedGeometryToTheMainDocument() started. +✔ Test openingAModelHandsItsPreparedGeometryToTheMainDocument() passed after 0.304 seconds. +◇ Test openingACompositionStartsAnUnmodifiedDraftWithItsAssembledPreview() started. +✔ Test openingACompositionStartsAnUnmodifiedDraftWithItsAssembledPreview() passed after 0.107 seconds. +◇ Test openingAWorldStartsAnUnmodifiedDraftWithItsPreparedScene() started. +✔ Test openingAWorldStartsAnUnmodifiedDraftWithItsPreparedScene() passed after 0.819 seconds. +◇ Test cancellingALargeEntryWhileGeneratingLeavesTheDocumentSelectionAndHistory() started. +✔ Test cancellingALargeEntryWhileGeneratingLeavesTheDocumentSelectionAndHistory() passed after 0.077 seconds. +◇ Test cancellingWhilePreparingGeometryPublishesNothing() started. +✔ Test cancellingWhilePreparingGeometryPublishesNothing() passed after 0.058 seconds. +◇ Test doneStopsAnOpeningAndItsThumbnailsBeforeTheGalleryClosesSoALateResultIsNeverPublished() started. +✔ Test doneStopsAnOpeningAndItsThumbnailsBeforeTheGalleryClosesSoALateResultIsNeverPublished() passed after 0.055 seconds. +◇ Test loadPreviewAgainAfterCancelPublishesTheNewThumbnailWhileTheFirstWorkerStillRuns() started. +✔ Test loadPreviewAgainAfterCancelPublishesTheNewThumbnailWhileTheFirstWorkerStillRuns() passed after 0.003 seconds. +◇ Test aFailedOpeningReportsItAndKeepsTheGalleryUsable() started. +✔ Test aFailedOpeningReportsItAndKeepsTheGalleryUsable() passed after 0.001 seconds. +◇ Test placementCountsMatchEveryGeneratedWorld() started. +✔ Test placementCountsMatchEveryGeneratedWorld() passed after 1.466 seconds. +◇ Test previewsReduceLargeVolumesAndDrawWorldsAsBoundedPlans() started. +✔ Test previewsReduceLargeVolumesAndDrawWorldsAsBoundedPlans() passed after 0.070 seconds. +✔ Suite SculptureGalleryBrowserTests passed after 2.991 seconds. +◇ Suite "Reference save snapshots" started. +◇ Test compositionPreparationRetainsReferencesAndLeavesVoxelBaselineAlone() started. +✔ Test compositionPreparationRetainsReferencesAndLeavesVoxelBaselineAlone() passed after 0.036 seconds. +◇ Test cancellationAndReplacementCannotPublishAnOldGraph() started. +✔ Test cancellationAndReplacementCannotPublishAnOldGraph() passed after 0.018 seconds. +◇ Test worldPreparationPreservesExactSparseCoordinates() started. +✔ Test worldPreparationPreservesExactSparseCoordinates() passed after 0.034 seconds. +✔ Suite "Reference save snapshots" passed after 0.089 seconds. +◇ Suite "Insertion discoverability" started. +◇ Test fileMenuActionsPresentTheSheetsImporterAndAreUnavailableWhileBusy() started. +✔ Test fileMenuActionsPresentTheSheetsImporterAndAreUnavailableWhileBusy() passed after 0.031 seconds. +◇ Test worldMenuActionsFollowTheSameRulesAndNeverChangeTheWorld() started. +✔ Test worldMenuActionsFollowTheSameRulesAndNeverChangeTheWorld() passed after 0.032 seconds. +◇ Test commandPaletteOffersInsertionWithSearchableKeywordsAndOpensTheMatchingSheet() started. +✔ Test commandPaletteOffersInsertionWithSearchableKeywordsAndOpensTheMatchingSheet() passed after 0.001 seconds. +◇ Test insertionCanvasesStartEmptyAndAcceptTheFirstFileWithoutReplacingAnything() started. +✔ Test insertionCanvasesStartEmptyAndAcceptTheFirstFileWithoutReplacingAnything() passed after 0.024 seconds. +◇ Test menuUndoActsOnTheOpenSheetAndNeverChangesTheHiddenSculpture() started. +✔ Test menuUndoActsOnTheOpenSheetAndNeverChangesTheHiddenSculpture() passed after 0.010 seconds. +◇ Test menuUndoFallsBackToTheMainSculptureOnlyWhenNoSheetCoversIt() started. +✔ Test menuUndoFallsBackToTheMainSculptureOnlyWhenNoSheetCoversIt() passed after 0.001 seconds. +◇ Test sheetHistoryIsUnavailableWhileBusyAndFollowsAnOpenSharedEdit() started. +✔ Test sheetHistoryIsUnavailableWhileBusyAndFollowsAnOpenSharedEdit() passed after 0.030 seconds. +◇ Test worldSheetHistoryRoutesAndStaysUnavailableWhileItsPreparationRuns() started. +✔ Test worldSheetHistoryRoutesAndStaysUnavailableWhileItsPreparationRuns() passed after 0.049 seconds. +◇ Test replacingTheDraftWithAnExampleClearsStalePortableDataAndUndoRestoresIt() started. +✔ Test replacingTheDraftWithAnExampleClearsStalePortableDataAndUndoRestoresIt() passed after 0.011 seconds. +◇ Test useInAWorldCarriesTheCompositionsPortableMetadataAndNestedTitles() started. +✔ Test useInAWorldCarriesTheCompositionsPortableMetadataAndNestedTitles() passed after 0.051 seconds. +◇ Test useInAWorldWithoutPortableDataOrBeyondPortableCapacityFallsBackWithAPlainNotice() started. +✔ Test useInAWorldWithoutPortableDataOrBeyondPortableCapacityFallsBackWithAPlainNotice() passed after 2.322 seconds. +◇ Test cancelingAWorldHandoffNeverDeliversIt() started. +✔ Test cancelingAWorldHandoffNeverDeliversIt() passed after 0.005 seconds. +◇ Test insertingAtAnUnchangedFocusKeepsTheExploreEyeWherever() started. +✔ Test insertingAtAnUnchangedFocusKeepsTheExploreEyeWherever() passed after 0.015 seconds. +◇ Test openingEditableVoxelsEndsTheNavigationPauseAndCatchesTheFocusUpWithTheExploreAnchor() started. +✔ Test openingEditableVoxelsEndsTheNavigationPauseAndCatchesTheFocusUpWithTheExploreAnchor() passed after 0.014 seconds. +◇ Test walkingWhileAnInsertionPreparesDoesNotRefuseItAndFocusCatchesUpAfterwards() started. +✔ Test walkingWhileAnInsertionPreparesDoesNotRefuseItAndFocusCatchesUpAfterwards() passed after 0.032 seconds. +◇ Test batchesNameTheirFirstAndLastTilesAndSayWhenTheyContinueOntoAnotherRowOrLayer() started. +✔ Test batchesNameTheirFirstAndLastTilesAndSayWhenTheyContinueOntoAnotherRowOrLayer() passed after 0.040 seconds. +◇ Test replacementQuestionAndSummaryUseCorrectPlurals() started. +✔ Test replacementQuestionAndSummaryUseCorrectPlurals() passed after 0.030 seconds. +◇ Test labelsShowModelTitlesAndDimensionsNeverGeneratedIDs() started. +✔ Test labelsShowModelTitlesAndDimensionsNeverGeneratedIDs() passed after 0.024 seconds. +◇ Test nativeSaveAndInsertionRefuseGraphsThatWouldNotReopen() started. +✔ Test nativeSaveAndInsertionRefuseGraphsThatWouldNotReopen() passed after 4.795 seconds. +◇ Test largeNativeParentsInsertWithNativeValuesAndExplainTheFallback() started. +✔ Test largeNativeParentsInsertWithNativeValuesAndExplainTheFallback() passed after 12.003 seconds. +✔ Suite "Insertion discoverability" passed after 19.529 seconds. +◇ Suite "Native model insertion" started. +◇ Test compositionBatchPlacesNestedModelsAndRestoresTheCompleteSnapshotWithOneUndo() started. +✔ Test compositionBatchPlacesNestedModelsAndRestoresTheCompleteSnapshotWithOneUndo() passed after 0.043 seconds. +◇ Test worldBatchPlacesAtExactFocusAndKeepsLibraryAndSnapshotInOneHistoryEntry() started. +✔ Test worldBatchPlacesAtExactFocusAndKeepsLibraryAndSnapshotInOneHistoryEntry() passed after 0.041 seconds. +◇ Test compositionRefusalsNeverPublishAPartialBatchOrCreateHistory() started. +✔ Test compositionRefusalsNeverPublishAPartialBatchOrCreateHistory() passed after 0.004 seconds. +◇ Test failedInsertionRetainsAnExistingRedoAndSavedBaseline() started. +✔ Test failedInsertionRetainsAnExistingRedoAndSavedBaseline() passed after 0.008 seconds. +◇ Test exhaustedGlyphLedgerRefusesInsertionWithoutChangingTheMapOrHistory() started. +✔ Test exhaustedGlyphLedgerRefusesInsertionWithoutChangingTheMapOrHistory() passed after 0.001 seconds. +◇ Test worldRefusalsKeepExactDocumentHistoryAndPortableSnapshot() started. +✔ Test worldRefusalsKeepExactDocumentHistoryAndPortableSnapshot() passed after 0.003 seconds. +◇ Test multiselectUsesNaturalFilenameOrderNotSelectionOrderAndRetainsPortableInputs() started. +✔ Test multiselectUsesNaturalFilenameOrderNotSelectionOrderAndRetainsPortableInputs() passed after 0.026 seconds. +◇ Test equalFilenamesInDifferentFoldersKeepAStablePathOrder() started. +✔ Test equalFilenamesInDifferentFoldersKeepAStablePathOrder() passed after 0.003 seconds. +◇ Test recursiveFolderSelectionSkipsHiddenUnsupportedAndSymbolicEntries() started. +✔ Test recursiveFolderSelectionSkipsHiddenUnsupportedAndSymbolicEntries() passed after 0.005 seconds. +◇ Test fileSelectionRefusesEmptyUnsupportedSymlinkAndOversizedInputsNamingTheFileAndLimit() started. +✔ Test fileSelectionRefusesEmptyUnsupportedSymlinkAndOversizedInputsNamingTheFileAndLimit() passed after 0.013 seconds. +◇ Test earlyChecksRefuseAnOversizedBatchBeforeDecodingEveryFile() started. +✔ Test earlyChecksRefuseAnOversizedBatchBeforeDecodingEveryFile() passed after 0.003 seconds. +◇ Test cancelledFileReadsAndDraftInsertionNeverPublishOrCreateHistory() started. +✔ Test cancelledFileReadsAndDraftInsertionNeverPublishOrCreateHistory() passed after 0.009 seconds. +◇ Test nativeFolderInsertionAutomaticallyPlacesTheBatchAndUnsupportedSelectionIsAtomic() started. +✔ Test nativeFolderInsertionAutomaticallyPlacesTheBatchAndUnsupportedSelectionIsAtomic() passed after 0.045 seconds. +◇ Test worldInsertionRejectsAParentChangedDuringFilePreparation() started. +✔ Test worldInsertionRejectsAParentChangedDuringFilePreparation() passed after 0.029 seconds. +◇ Test selectToolChoosesTheInsertionStartWithoutPaintingOrChangingHistory() started. +✔ Test selectToolChoosesTheInsertionStartWithoutPaintingOrChangingHistory() passed after 0.009 seconds. +◇ Test occupiedTargetsRequireConfirmationAndCancelPreservesTheCompleteParent() started. +✔ Test occupiedTargetsRequireConfirmationAndCancelPreservesTheCompleteParent() passed after 0.053 seconds. +◇ Test editedParentInvalidatesReplacementConfirmationWithoutPublishingTheCandidate() started. +✔ Test editedParentInvalidatesReplacementConfirmationWithoutPublishingTheCandidate() passed after 0.019 seconds. +◇ Test changedStartAndSavedSnapshotInvalidateReplacementConfirmationWithoutHistory() started. +✔ Test changedStartAndSavedSnapshotInvalidateReplacementConfirmationWithoutHistory() passed after 0.039 seconds. +◇ Test filePreparationStagesOccupiedTargetsBeforeAnyMutation() started. +✔ Test filePreparationStagesOccupiedTargetsBeforeAnyMutation() passed after 0.035 seconds. +◇ Test compositionEditsDuringPreparationCancelTheCandidateAndRetainOnlyTheEditHistory() started. +✔ Test compositionEditsDuringPreparationCancelTheCandidateAndRetainOnlyTheEditHistory() passed after 0.015 seconds. +◇ Test saveFinishingDuringCompositionPreparationRetainsItsSnapshotWithoutInsertion() started. +✔ Test saveFinishingDuringCompositionPreparationRetainsItsSnapshotWithoutInsertion() passed after 0.014 seconds. +◇ Test worldInsertionRejectsASnapshotChangedByACompletedSaveDuringPreparation() started. +✔ Test worldInsertionRejectsASnapshotChangedByACompletedSaveDuringPreparation() passed after 0.043 seconds. +◇ Test worldInsertionRejectsFocusChangesDuringPreparationWithoutLosingTheNewFocus() started. +✔ Test worldInsertionRejectsFocusChangesDuringPreparationWithoutLosingTheNewFocus() passed after 0.052 seconds. +◇ Test fileRefusalsIdentifyTheFilenameWithoutExposingItsPrivateDirectory() started. +✔ Test fileRefusalsIdentifyTheFilenameWithoutExposingItsPrivateDirectory() passed after 0.002 seconds. +◇ Test tileFitRefusalNamesTheModelAndRequiredAndCurrentDimensions() started. +✔ Test tileFitRefusalNamesTheModelAndRequiredAndCurrentDimensions() passed after 0.001 seconds. +◇ Test portableActionsResumeOnlyAfterPreparationAndReplacementDecisionFinish() started. +✔ Test portableActionsResumeOnlyAfterPreparationAndReplacementDecisionFinish() passed after 0.045 seconds. +◇ Test selectedWorldChildrenNameTheirSourceAndRefuseTheWholeNativeBatch() started. +✔ Test selectedWorldChildrenNameTheirSourceAndRefuseTheWholeNativeBatch() passed after 0.096 seconds. +✔ Suite "Native model insertion" passed after 0.670 seconds. +◇ Suite "Insertion repairs" started. +◇ Test aNativeWorldFallsBackNativelyWhetherFilesArriveOneAtATimeOrTogether() started. +✔ Test aNativeWorldFallsBackNativelyWhetherFilesArriveOneAtATimeOrTogether() passed after 22.346 seconds. +◇ Test aSnapshotMintedByASharedEditDoesNotForceLaterInsertionsDownThePortablePath() started. +✔ Test aSnapshotMintedByASharedEditDoesNotForceLaterInsertionsDownThePortablePath() passed after 13.207 seconds. +◇ Test portableDataTheDraftTrulyHoldsStillRefusesAnOversizedInsertionByName() started. +✔ Test portableDataTheDraftTrulyHoldsStillRefusesAnOversizedInsertionByName() passed after 13.165 seconds. +◇ Test theDraftsPortableFlagFollowsCarriedDataExportsAndReplacementAndUndoRestoresIt() started. +✔ Test theDraftsPortableFlagFollowsCarriedDataExportsAndReplacementAndUndoRestoresIt() passed after 0.021 seconds. +◇ Test theWorldDraftsPortableFlagFollowsCarriedDataAndUndoRestoresIt() started. +✔ Test theWorldDraftsPortableFlagFollowsCarriedDataAndUndoRestoresIt() passed after 0.036 seconds. +◇ Test largeNativeFilesInsertNativelyAndTheSameFilesWithPortableDataAreRefusedByName() started. +✔ Test largeNativeFilesInsertNativelyAndTheSameFilesWithPortableDataAreRefusedByName() passed after 45.325 seconds. +◇ Test historyIsUnavailableWhileApplyValidatesAndAStaleApplyKeepsTheSessionOpen() started. +✔ Test historyIsUnavailableWhileApplyValidatesAndAStaleApplyKeepsTheSessionOpen() passed after 0.008 seconds. +◇ Test aWorldApplyAlsoRejectsContentThatChangedWhileItWasValidated() started. +✔ Test aWorldApplyAlsoRejectsContentThatChangedWhileItWasValidated() passed after 0.021 seconds. +◇ Test sharedModelMenusTellSameTitleAndSizeModelsApartOnlyWhenTheyCollide() started. +✔ Test sharedModelMenusTellSameTitleAndSizeModelsApartOnlyWhenTheyCollide() passed after 0.001 seconds. +◇ Test theAppReaderRefusesByNameWhenTheResolvedVolumeBudgetIsFullBeforeDecodingAnyFile() started. +✔ Test theAppReaderRefusesByNameWhenTheResolvedVolumeBudgetIsFullBeforeDecodingAnyFile() passed after 0.003 seconds. +◇ Test theByteBudgetIsAdmittedForEveryFileBeforeAnyEarlierFileIsDecoded() started. +✔ Test theByteBudgetIsAdmittedForEveryFileBeforeAnyEarlierFileIsDecoded() passed after 0.001 seconds. +◇ Test theCompositionCanvasHoldsAWholeFolderAndNamesTheLayerItSpillsInto() started. +✔ Test theCompositionCanvasHoldsAWholeFolderAndNamesTheLayerItSpillsInto() passed after 0.068 seconds. +◇ Test commandAvailabilityIsOneDecisionForTheFileMenuEditMenuAndPalette() started. +✔ Test commandAvailabilityIsOneDecisionForTheFileMenuEditMenuAndPalette() passed after 0.001 seconds. +◇ Test aDelayedImporterRequestIsPresentedDroppedOrLeftAloneByTheLiveState() started. +✔ Test aDelayedImporterRequestIsPresentedDroppedOrLeftAloneByTheLiveState() passed after 0.001 seconds. +◇ Test historyAvailabilityIsObservedSoMenusRefreshWhenADraftEdits() started. +✔ Test historyAvailabilityIsObservedSoMenusRefreshWhenADraftEdits() passed after 0.001 seconds. +✔ Suite "Insertion repairs" passed after 94.210 seconds. +◇ Suite "Linked file confinement" started. +◇ Test aSymbolicLinkFolderComponentIsRefusedNamingTheFile() started. +✔ Test aSymbolicLinkFolderComponentIsRefusedNamingTheFile() passed after 0.006 seconds. +◇ Test aSymbolicLinkFileIsRefusedEvenWhenItPointsInsideOrOutsideTheFolder() started. +✔ Test aSymbolicLinkFileIsRefusedEvenWhenItPointsInsideOrOutsideTheFolder() passed after 0.005 seconds. +◇ Test aScalarThatJoinsASeparatorToItsNameCannotCarryOneOpenThroughASymbolicLink() started. +✔ Test aScalarThatJoinsASeparatorToItsNameCannotCarryOneOpenThroughASymbolicLink() passed after 0.005 seconds. +◇ Test aRootReachedThroughASymbolicLinkFolderIsReadFromItsRealLocationOnly() started. +✔ Test aRootReachedThroughASymbolicLinkFolderIsReadFromItsRealLocationOnly() passed after 0.009 seconds. +◇ Test hiddenFoldersAndFilesAreRefusedNamingTheFile() started. +✔ Test hiddenFoldersAndFilesAreRefusedNamingTheFile() passed after 0.006 seconds. +◇ Test aLeadingPeriodWithACombiningMarkIsStillHidden() started. +✔ Test aLeadingPeriodWithACombiningMarkIsStillHidden() passed after 0.004 seconds. +◇ Test aHardLinkedFileIsRefusedNamingTheFile() started. +✔ Test aHardLinkedFileIsRefusedNamingTheFile() passed after 0.003 seconds. +◇ Test aSecondSpellingOfAFileAlreadyReadIsRefusedWhereTheVolumeAllowsIt() started. +✔ Test aSecondSpellingOfAFileAlreadyReadIsRefusedWhereTheVolumeAllowsIt() passed after 0.006 seconds. +◇ Test readsAreBoundedRegularAndReportMissingFilesSoTheLinkingFileIsNamed() started. +✔ Test readsAreBoundedRegularAndReportMissingFilesSoTheLinkingFileIsNamed() passed after 0.005 seconds. +◇ Test theFolderScopeIsHeldOnlyForTheAttemptAndCancellationPublishesNothing() started. +✔ Test theFolderScopeIsHeldOnlyForTheAttemptAndCancellationPublishesNothing() passed after 0.008 seconds. +✔ Suite "Linked file confinement" passed after 0.063 seconds. +◇ Suite "Linked roots in insertion and bundles" started. +◇ Test insertingALinkedRootIsRefusedNamingTheFileAndChangesNothing() started. +✔ Test insertingALinkedRootIsRefusedNamingTheFileAndChangesNothing() passed after 0.562 seconds. +◇ Test aModelFolderThatHoldsALinkedRootIsRefusedNamingThatFile() started. +✔ Test aModelFolderThatHoldsALinkedRootIsRefusedNamingThatFile() passed after 0.003 seconds. +◇ Test readableAndBinaryBundlesOpenThroughPlainOpenWithoutAFolder() started. +✔ Test readableAndBinaryBundlesOpenThroughPlainOpenWithoutAFolder() passed after 0.026 seconds. +✔ Suite "Linked roots in insertion and bundles" passed after 0.592 seconds. +◇ Suite "Linked session presentation" started. +◇ Test theViewOnlyCompositionShowsReloadAndTheExplanationWithEditingControlsUnavailable() started. +Linked presentation: this offscreen host exposes no accessibility tree, so control identifiers and enabled states were not checked here. SculptureLinkedSessionTests checks the values the controls read. +✔ Test theViewOnlyCompositionShowsReloadAndTheExplanationWithEditingControlsUnavailable() passed after 0.432 seconds. +◇ Test theRepairViewListsFailuresWithReloadAndChooseFolder() started. +Linked presentation: this offscreen host exposes no accessibility tree, so control identifiers and enabled states were not checked here. SculptureLinkedSessionTests checks the values the controls read. +✔ Test theRepairViewListsFailuresWithReloadAndChooseFolder() passed after 0.179 seconds. +✔ Suite "Linked session presentation" passed after 0.611 seconds. +◇ Suite "Linked sessions" started. +◇ Test plainOpenOfALinkedRootAsksForItsProjectFolder() started. +✔ Test plainOpenOfALinkedRootAsksForItsProjectFolder() passed after 0.012 seconds. +◇ Test aBinaryLinkedRootIsRefusedByNameWithoutAskingForAFolder() started. +✔ Test aBinaryLinkedRootIsRefusedByNameWithoutAskingForAFolder() passed after 0.002 seconds. +◇ Test openingWithItsFolderResolvesNestedChildrenIntoAViewOnlyComposition() started. +✔ Test openingWithItsFolderResolvesNestedChildrenIntoAViewOnlyComposition() passed after 0.013 seconds. +◇ Test cancellingTheFolderRequestOrTheResolutionOpensNothing() started. +✔ Test cancellingTheFolderRequestOrTheResolutionOpensNothing() passed after 0.004 seconds. +◇ Test aRootOutsideTheChosenFolderIsRefusedByNameAndOpensNothing() started. +✔ Test aRootOutsideTheChosenFolderIsRefusedByNameAndOpensNothing() passed after 0.005 seconds. +◇ Test reloadPicksUpChangedFilesWithoutMarkingTheSessionChanged() started. +✔ Test reloadPicksUpChangedFilesWithoutMarkingTheSessionChanged() passed after 0.014 seconds. +◇ Test aFailedReloadKeepsThePreviousSceneNamesTheFileAndNeverMarksTheSessionChanged() started. +✔ Test aFailedReloadKeepsThePreviousSceneNamesTheFileAndNeverMarksTheSessionChanged() passed after 0.015 seconds. +◇ Test theRepairViewListsEachFailingLinkWithItsFileAndReasonAndWritesNothing() started. +✔ Test theRepairViewListsEachFailingLinkWithItsFileAndReasonAndWritesNothing() passed after 0.016 seconds. +◇ Test theRepairViewOffersChooseFolderAndReloadWheneverNoResolutionRuns() started. +✔ Test theRepairViewOffersChooseFolderAndReloadWheneverNoResolutionRuns() passed after 0.004 seconds. +◇ Test aCycleIsListedAsAChainOfProjectPathsForTheLinkThatLeadsToIt() started. +✔ Test aCycleIsListedAsAChainOfProjectPathsForTheLinkThatLeadsToIt() passed after 0.004 seconds. +◇ Test aGlobalFailureIsListedEvenWhenEveryLinkResolvesOnItsOwn() started. +✔ Test aGlobalFailureIsListedEvenWhenEveryLinkResolvesOnItsOwn() passed after 0.181 seconds. +◇ Test anUnreadableRootOpensTheRepairViewNamingTheRoot() started. +✔ Test anUnreadableRootOpensTheRepairViewNamingTheRoot() passed after 0.010 seconds. +◇ Test chooseFolderRegrantsOnlyAFolderThatContainsTheRoot() started. +✔ Test chooseFolderRegrantsOnlyAFolderThatContainsTheRoot() passed after 0.289 seconds. +◇ Test aLinkedSessionIsViewOnlyAndEveryEditingActionIsUnavailable() started. +✔ Test aLinkedSessionIsViewOnlyAndEveryEditingActionIsUnavailable() passed after 0.576 seconds. +◇ Test aRepairSessionOffersReloadButNoEditingCommands() started. +✔ Test aRepairSessionOffersReloadButNoEditingCommands() passed after 0.003 seconds. +✔ Suite "Linked sessions" passed after 1.155 seconds. +◇ Test cameraMotionDoesNotInvalidateVoxelMesh() started. +✔ Test cameraMotionDoesNotInvalidateVoxelMesh() passed after 0.001 seconds. +◇ Test editsUndoRedoAndReplacementInvalidateVoxelMesh() started. +✔ Test editsUndoRedoAndReplacementInvalidateVoxelMesh() passed after 0.001 seconds. +◇ Test titleEditsAndTheirUndoKeepGeometryButRemainDirty() started. +✔ Test titleEditsAndTheirUndoKeepGeometryButRemainDirty() passed after 0.001 seconds. +◇ Suite "Portable native scene interchange" started. +◇ Test copyPreparationKeepsTheNativeWorkspaceAndReferenceBaseline() started. +✔ Test copyPreparationKeepsTheNativeWorkspaceAndReferenceBaseline() passed after 0.022 seconds. +◇ Test voxelCopyLeavesTheSavedBaselineUndoAndNativeSaveMessageAlone() started. +✔ Test voxelCopyLeavesTheSavedBaselineUndoAndNativeSaveMessageAlone() passed after 0.016 seconds. +◇ Test regularFileOpenReopensAnAdoptedGenericBinaryAsReadablePortableText() started. +✔ Test regularFileOpenReopensAnAdoptedGenericBinaryAsReadablePortableText() passed after 0.003 seconds. +◇ Test cancellationAndSupersessionDoNotPublishStaleCopies() started. +✔ Test cancellationAndSupersessionDoNotPublishStaleCopies() passed after 0.023 seconds. +◇ Test contentOpenRoutesAllPortableScenesAndKeepsLegacyDecoding() started. +✔ Test contentOpenRoutesAllPortableScenesAndKeepsLegacyDecoding() passed after 0.032 seconds. +◇ Test sharedApplyAndUndoRetainOriginalIdentitiesAndExactRevisions() started. +✔ Test sharedApplyAndUndoRetainOriginalIdentitiesAndExactRevisions() passed after 0.015 seconds. +◇ Test worldApplyRetainsExactAnchorsAndSnapshotUndo() started. +✔ Test worldApplyRetainsExactAnchorsAndSnapshotUndo() passed after 0.021 seconds. +◇ Test staleNativeParentDoesNotPublishAnyPortableSnapshot() started. +✔ Test staleNativeParentDoesNotPublishAnyPortableSnapshot() passed after 0.016 seconds. +◇ Test onlyCapacityFailuresUseTheLegacyNativeEditingFallback() started. +✔ Test onlyCapacityFailuresUseTheLegacyNativeEditingFallback() passed after 4.347 seconds. +◇ Test diagnosticPresentationKeepsCodesPathsAndRealSourceLines() started. +✔ Test diagnosticPresentationKeepsCodesPathsAndRealSourceLines() passed after 0.001 seconds. +✔ Suite "Portable native scene interchange" passed after 4.500 seconds. +◇ Suite "Reference editor presentation" started. +◇ Test nativeReferenceControlsFitBothSizesAndThemes() started. +Retained reference editor presentation: /Users/leif/Development/_CorvidLabs/3md-edit-preview/apps/sculpt/.build/verification/reference-presentation-B133BB30-2D58-4CDD-9DC1-94E5AB4BB79B +✔ Test nativeReferenceControlsFitBothSizesAndThemes() passed after 3.142 seconds. +✔ Suite "Reference editor presentation" passed after 3.142 seconds. +◇ Suite "Reference save session lifecycle" started. +◇ Test compositionSuccessfulSaveRetainsExactDraftSelectionAndGraphHistory() started. +✔ Test compositionSuccessfulSaveRetainsExactDraftSelectionAndGraphHistory() passed after 0.030 seconds. +◇ Test worldSuccessfulSaveRetainsLibraryHistoryFocusCameraAndSelectedInstance() started. +✔ Test worldSuccessfulSaveRetainsLibraryHistoryFocusCameraAndSelectedInstance() passed after 0.027 seconds. +◇ Test panelCancellationAndWriteFailureKeepSameDraftBaselineAndHistory() started. +✔ Test panelCancellationAndWriteFailureKeepSameDraftBaselineAndHistory() passed after 0.013 seconds. +◇ Test saveOnlyMarksCapturedSnapshotAndLeavesLaterEditsDirty() started. +✔ Test saveOnlyMarksCapturedSnapshotAndLeavesLaterEditsDirty() passed after 0.013 seconds. +◇ Test preparationFailureRetainsDraftAndCaptureFailureDoesNotDismissIt() started. +✔ Test preparationFailureRetainsDraftAndCaptureFailureDoesNotDismissIt() passed after 0.369 seconds. +✔ Suite "Reference save session lifecycle" passed after 0.454 seconds. +◇ Test asyncSavePreservesSnapshotAndLaterEditsStayDirty(format:) started. +◇ Test case passing 1 argument format → .readable to asyncSavePreservesSnapshotAndLaterEditsStayDirty(format:) started. +◇ Test case passing 1 argument format → .compact to asyncSavePreservesSnapshotAndLaterEditsStayDirty(format:) started. +✔ Test asyncSavePreservesSnapshotAndLaterEditsStayDirty(format:) with 2 test cases passed after 0.023 seconds. +◇ Test replacedDocumentCannotBeMarkedSavedByAnEarlierSave() started. +✔ Test replacedDocumentCannotBeMarkedSavedByAnEarlierSave() passed after 0.007 seconds. +◇ Test cancelledSaveDoesNotPublishAndCanBeRetried() started. +✔ Test cancelledSaveDoesNotPublishAndCanBeRetried() passed after 0.008 seconds. +◇ Suite "Shared model draft editing" started. +◇ Test compositionApplyUpdatesNestedReferencesAsOneParentUndoAndRedo() started. +✔ Test compositionApplyUpdatesNestedReferencesAsOneParentUndoAndRedo() passed after 0.009 seconds. +◇ Test compositionCancelAndNoOpKeepReferenceWorkspaceAndHistoryExact() started. +✔ Test compositionCancelAndNoOpKeepReferenceWorkspaceAndHistoryExact() passed after 0.009 seconds. +◇ Test compositionSessionRejectsChangedParentAndInvalidLeafWithoutOverwritingNewerState() started. +✔ Test compositionSessionRejectsChangedParentAndInvalidLeafWithoutOverwritingNewerState() passed after 0.010 seconds. +◇ Test compositionHistoryIncludesRootMapAndLibraryTogether() started. +✔ Test compositionHistoryIncludesRootMapAndLibraryTogether() passed after 0.001 seconds. +◇ Test savedRootEditsRemainCleanAfterSharedApplyUndoAndRetainNewerDirtyEdits() started. +✔ Test savedRootEditsRemainCleanAfterSharedApplyUndoAndRetainNewerDirtyEdits() passed after 0.008 seconds. +◇ Test worldSharedApplyAndUniqueBothIncludeLibraryInDirtyAndUndoHistory() started. +✔ Test worldSharedApplyAndUniqueBothIncludeLibraryInDirtyAndUndoHistory() passed after 0.014 seconds. +◇ Test worldCancelNoOpAndStaleSessionRetainExactDocumentAndScene() started. +✔ Test worldCancelNoOpAndStaleSessionRetainExactDocumentAndScene() passed after 0.024 seconds. +◇ Test cancellationNeverPublishesChildAndNestedMapIsNotMadeUnique() started. +✔ Test cancellationNeverPublishesChildAndNestedMapIsNotMadeUnique() passed after 0.001 seconds. +✔ Suite "Shared model draft editing" passed after 0.079 seconds. +◇ Suite "Shared model native presentation" started. +◇ Test nativeSessionRendersBothSizesAndThemesWithAccessibilityEvidenceWhenAvailable() started. +Retained native shared-model presentation: /Users/leif/Development/_CorvidLabs/3md-edit-preview/apps/sculpt/.build/verification/shared-model-presentation-ADC395FA-5B42-4ECA-978A-46850C293E42 +✔ Test nativeSessionRendersBothSizesAndThemesWithAccessibilityEvidenceWhenAvailable() passed after 1.137 seconds. +◇ Test paletteAcceptsEveryOfferedGlyphAndNativeCancelKeepsParentWhenAccessibilityAvailable() started. +✔ Test paletteAcceptsEveryOfferedGlyphAndNativeCancelKeepsParentWhenAccessibilityAvailable() passed after 0.347 seconds. +✔ Suite "Shared model native presentation" passed after 1.484 seconds. +◇ Test cubeSurfacePaintingAddsTheNeighborAndUndoRestoresTheOriginal() started. +✔ Test cubeSurfacePaintingAddsTheNeighborAndUndoRestoresTheOriginal() passed after 0.012 seconds. +◇ Test cubeEraseTargetsTheClickedCubeAndFullBoundaryDoesNotCreateHistory() started. +✔ Test cubeEraseTargetsTheClickedCubeAndFullBoundaryDoesNotCreateHistory() passed after 0.001 seconds. +◇ Test emptySliceCanStartACubeAndPresentationDoesNotDirtyTheDocument() started. +✔ Test emptySliceCanStartACubeAndPresentationDoesNotDirtyTheDocument() passed after 0.001 seconds. +◇ Test paintStrokeUndoRestoresWholeStrokeAndRedoReappliesIt() started. +✔ Test paintStrokeUndoRestoresWholeStrokeAndRedoReappliesIt() passed after 0.001 seconds. +◇ Test strokeBeginningOnUnchangedCellStillHasOneUndoStep() started. +✔ Test strokeBeginningOnUnchangedCellStillHasOneUndoStep() passed after 0.001 seconds. +◇ Test savedSnapshotDoesNotMarkLaterEditsSavedAndFailedOpenDoesNotReplaceState() started. +✔ Test savedSnapshotDoesNotMarkLaterEditsSavedAndFailedOpenDoesNotReplaceState() passed after 0.001 seconds. +◇ Test layerUndoAndRedoKeepSelectionInBounds() started. +✔ Test layerUndoAndRedoKeepSelectionInBounds() passed after 0.001 seconds. +◇ Test fastDiagonalStrokeHasNoGapsAndOneUndoStep() started. +✔ Test fastDiagonalStrokeHasNoGapsAndOneUndoStep() passed after 0.001 seconds. +◇ Test largeBrushClipsToVolumeAndUndoRestoresAllChangedCells() started. +✔ Test largeBrushClipsToVolumeAndUndoRestoresAllChangedCells() passed after 0.001 seconds. +◇ Test fillStopsAtGlyphBoundaryAndRemainsOneUndoableChange() started. +✔ Test fillStopsAtGlyphBoundaryAndRemainsOneUndoableChange() passed after 0.001 seconds. +◇ Test invalidTitleDraftIsPreservedWithoutModalErrorAndProtectsUnsavedWork() started. +✔ Test invalidTitleDraftIsPreservedWithoutModalErrorAndProtectsUnsavedWork() passed after 0.001 seconds. +◇ Test clearingSliceKeepsOtherSlicesAndCanBeUndone() started. +✔ Test clearingSliceKeepsOtherSlicesAndCanBeUndone() passed after 0.002 seconds. +◇ Test changingCameraAndSelectionDoesNotDirtySavedDocument() started. +✔ Test changingCameraAndSelectionDoesNotDirtySavedDocument() passed after 0.002 seconds. +◇ Test structuredEditsShareHumanFillSemanticsAndBatchHasOneUndo() started. +✔ Test structuredEditsShareHumanFillSemanticsAndBatchHasOneUndo() passed after 0.001 seconds. +◇ Test invalidCommandBatchKeepsDocumentHistoryAndDraft() started. +✔ Test invalidCommandBatchKeepsDocumentHistoryAndDraft() passed after 0.001 seconds. +◇ Test browserSliceFixturesMatchNativeWorkspaceToolsAndWholeStrokeHistory() started. +✔ Test browserSliceFixturesMatchNativeWorkspaceToolsAndWholeStrokeHistory() passed after 0.007 seconds. +◇ Test worldExplorationAndOverviewPreserveSavedContentAndUndoAtExactDistantCoordinates() started. +✔ Test worldExplorationAndOverviewPreserveSavedContentAndUndoAtExactDistantCoordinates() passed after 0.011 seconds. +◇ Test worldOverviewRefusesUnframeableExtentWithoutOverflowOrChangingDocument() started. +✔ Test worldOverviewRefusesUnframeableExtentWithoutOverflowOrChangingDocument() passed after 0.001 seconds. +◇ Test worldDraftStartsSparseAndKeepsDistantAnchorsWithoutExpandingSpace() started. +✔ Test worldDraftStartsSparseAndKeepsDistantAnchorsWithoutExpandingSpace() passed after 0.001 seconds. +◇ Test worldFocusDistancesAndCameraAreSessionStateAndReuseTheSceneRevision() started. +✔ Test worldFocusDistancesAndCameraAreSessionStateAndReuseTheSceneRevision() passed after 0.001 seconds. +◇ Test worldPlacementUndoAndRedoPreserveExactInt64OriginsAndSharedLibrary() started. +✔ Test worldPlacementUndoAndRedoPreserveExactInt64OriginsAndSharedLibrary() passed after 0.001 seconds. +◇ Test worldFocusOverflowAndUnsafePlacementLeaveInstancesUnchanged() started. +✔ Test worldFocusOverflowAndUnsafePlacementLeaveInstancesUnchanged() passed after 0.001 seconds. +◇ Test worldSelectedRotationDeletionAndUndoNeverChangeModelDefinitions() started. +✔ Test worldSelectedRotationDeletionAndUndoNeverChangeModelDefinitions() passed after 0.001 seconds. +◇ Test worldPaginationBoundsRowsAndSelectionCanRevealADistantInstance() started. +✔ Test worldPaginationBoundsRowsAndSelectionCanRevealADistantInstance() passed after 0.001 seconds. +◇ Test unsavedWorldRestorationAndTitleDraftProtectPublicationWithoutLosingPlacements() started. +✔ Test unsavedWorldRestorationAndTitleDraftProtectPublicationWithoutLosingPlacements() passed after 0.001 seconds. +◇ Test cancelingWorldModelPreparationDoesNotOpenAnAbandonedCopy() started. +✔ Test cancelingWorldModelPreparationDoesNotOpenAnAbandonedCopy() passed after 0.001 seconds. +◇ Test fittedLargeSliceKeepsEveryCellAndRectangularPaddingDoesNotClipRows() started. +✔ Test fittedLargeSliceKeepsEveryCellAndRectangularPaddingDoesNotClipRows() passed after 0.001 seconds. +◇ Test zoomedSliceDrawsTheVisibleNeighborhoodAndKeepsTheLastCellReachable() started. +✔ Test zoomedSliceDrawsTheVisibleNeighborhoodAndKeepsTheLastCellReachable() passed after 0.001 seconds. +◇ Test fractionalScrollEdgesHaveAnAntialiasingFringeAndInvalidRegionsStayEmpty() started. +✔ Test fractionalScrollEdgesHaveAnAntialiasingFringeAndInvalidRegionsStayEmpty() passed after 0.001 seconds. +◇ Test thumbnailCacheKeyIgnoresOtherSliceEditsAndInvalidatesForItsOwnPixelsAndAppearance() started. +✔ Test thumbnailCacheKeyIgnoresOtherSliceEditsAndInvalidatesForItsOwnPixelsAndAppearance() passed after 0.001 seconds. +◇ Test thumbnailPixelsPreserveRectangularEmptyPaddingAndMaterialTint() started. +✔ Test thumbnailPixelsPreserveRectangularEmptyPaddingAndMaterialTint() passed after 0.001 seconds. +◇ Test canceledThumbnailPreparationDoesNotPublishPixels() started. +✔ Test canceledThumbnailPreparationDoesNotPublishPixels() passed after 0.001 seconds. +◇ Test thumbnailRowsMatchTheTopLeftOriginOfTheEditableSlice() started. +✔ Test thumbnailRowsMatchTheTopLeftOriginOfTheEditableSlice() passed after 0.001 seconds. +◇ Test perSliceOccupancyRemainsCorrectAcrossPaletteEditsRotationDuplicationAndStorage() started. +✔ Test perSliceOccupancyRemainsCorrectAcrossPaletteEditsRotationDuplicationAndStorage() passed after 0.001 seconds. +◇ Test scrolledLastCellStrokeStillHasOneExactUndoAndPreviousSliceBytesStayUnchanged() started. +✔ Test scrolledLastCellStrokeStillHasOneExactUndoAndPreviousSliceBytesStayUnchanged() passed after 0.022 seconds. +◇ Test unknownOrMissingStoredAppearanceUsesSystem() started. +✔ Test unknownOrMissingStoredAppearanceUsesSystem() passed after 0.001 seconds. +◇ Test knownAppearanceValuesSurviveStorageRoundTrip() started. +✔ Test knownAppearanceValuesSurviveStorageRoundTrip() passed after 0.001 seconds. +◇ Suite AnimationExportTests started. +◇ Test configurationRejectsUnboundedWorkAndOddMovieDimensions() started. +✔ Test configurationRejectsUnboundedWorkAndOddMovieDimensions() passed after 0.001 seconds. +◇ Test gifLoopsWithCorrectFrameTimingAndChangingDecodedImages() started. +✔ Test gifLoopsWithCorrectFrameTimingAndChangingDecodedImages() passed after 0.011 seconds. +◇ Test mp4DecodesEveryFrameWithCorrectDurationDimensionsAndVisibleGlyphs(_:) started. +◇ Test case passing 1 argument framesPerSecond → 10 to mp4DecodesEveryFrameWithCorrectDurationDimensionsAndVisibleGlyphs(_:) started. +◇ Test case passing 1 argument framesPerSecond → 30 to mp4DecodesEveryFrameWithCorrectDurationDimensionsAndVisibleGlyphs(_:) started. +✔ Test mp4DecodesEveryFrameWithCorrectDurationDimensionsAndVisibleGlyphs(_:) with 2 test cases passed after 0.699 seconds. +◇ Test cancellationRemovesPartialAnimationAndOwnedStagingFile(_:) started. +◇ Test case passing 1 argument format → .gif to cancellationRemovesPartialAnimationAndOwnedStagingFile(_:) started. +◇ Test case passing 1 argument format → .mp4 to cancellationRemovesPartialAnimationAndOwnedStagingFile(_:) started. +✔ Test cancellationRemovesPartialAnimationAndOwnedStagingFile(_:) with 2 test cases passed after 0.093 seconds. +◇ Test existingDestinationIsPreservedAndUnsupportedGIFRateCreatesNothing() started. +✔ Test existingDestinationIsPreservedAndUnsupportedGIFRateCreatesNothing() passed after 0.004 seconds. +✔ Suite AnimationExportTests passed after 0.809 seconds. +◇ Suite CameraParityTests started. +◇ Test nativeCameraMatchesSharedBrowserProjectionCases() started. +✔ Test nativeCameraMatchesSharedBrowserProjectionCases() passed after 0.006 seconds. +◇ Test axisRotationsRemainOrthonormalAndInvalidInputsDoNotMoveCamera() started. +✔ Test axisRotationsRemainOrthonormalAndInvalidInputsDoNotMoveCamera() passed after 0.001 seconds. +◇ Test interactiveFramingPreservesDefaultExportCameraScale() started. +✔ Test interactiveFramingPreservesDefaultExportCameraScale() passed after 0.001 seconds. +◇ Test cameraInputsRemainFiniteAndPanHasTheNativeScreenScale() started. +✔ Test cameraInputsRemainFiniteAndPanHasTheNativeScreenScale() passed after 0.001 seconds. +✔ Suite CameraParityTests passed after 0.008 seconds. +◇ Suite CubeExportTests started. +◇ Test cubePNGAndASCIIRepresentTheSameDocumentWithDifferentImages() started. +✔ Test cubePNGAndASCIIRepresentTheSameDocumentWithDifferentImages() passed after 0.045 seconds. +◇ Test cubeTurntableEncodesActualGeometryFrames(_:) started. +◇ Test case passing 1 argument format → .gif to cubeTurntableEncodesActualGeometryFrames(_:) started. +◇ Test case passing 1 argument format → .mp4 to cubeTurntableEncodesActualGeometryFrames(_:) started. +✔ Test cubeTurntableEncodesActualGeometryFrames(_:) with 2 test cases passed after 0.181 seconds. +✔ Suite CubeExportTests passed after 0.227 seconds. +◇ Suite ExampleArtifactTests started. +◇ Test galleryManifestMatchesAllPublishedFilesAndDownloadLinks() started. +✔ Test galleryManifestMatchesAllPublishedFilesAndDownloadLinks() passed after 0.016 seconds. +◇ Test everyExampleHasFiveCompleteArtifacts(_:) started. +◇ Test case passing 1 argument id → "character-orb" to everyExampleHasFiveCompleteArtifacts(_:) started. +◇ Test case passing 1 argument id → "woven-torus" to everyExampleHasFiveCompleteArtifacts(_:) started. +◇ Test case passing 1 argument id → "moon-gate" to everyExampleHasFiveCompleteArtifacts(_:) started. +◇ Test case passing 1 argument id → "spiral-tower" to everyExampleHasFiveCompleteArtifacts(_:) started. +◇ Test case passing 1 argument id → "crystal-garden" to everyExampleHasFiveCompleteArtifacts(_:) started. +◇ Test case passing 1 argument id → "little-rocket" to everyExampleHasFiveCompleteArtifacts(_:) started. +◇ Test case passing 1 argument id → "pixel-bonsai" to everyExampleHasFiveCompleteArtifacts(_:) started. +◇ Test case passing 1 argument id → "orbital-rings" to everyExampleHasFiveCompleteArtifacts(_:) started. +◇ Test case passing 1 argument id → "hill-observatory" to everyExampleHasFiveCompleteArtifacts(_:) started. +◇ Test case passing 1 argument id → "terraced-island" to everyExampleHasFiveCompleteArtifacts(_:) started. +◇ Test case passing 1 argument id → "canal-city" to everyExampleHasFiveCompleteArtifacts(_:) started. +◇ Test case passing 1 argument id → "alpine-valley" to everyExampleHasFiveCompleteArtifacts(_:) started. +◇ Test case passing 1 argument id → "wandering-cartographer" to everyExampleHasFiveCompleteArtifacts(_:) started. +◇ Test case passing 1 argument id → "clockwork-dragon" to everyExampleHasFiveCompleteArtifacts(_:) started. +◇ Test case passing 1 argument id → "woodland-fox" to everyExampleHasFiveCompleteArtifacts(_:) started. +◇ Test case passing 1 argument id → "deep-sea-whale" to everyExampleHasFiveCompleteArtifacts(_:) started. +◇ Test case passing 1 argument id → "citadel-of-arches" to everyExampleHasFiveCompleteArtifacts(_:) started. +◇ Test case passing 1 argument id → "sky-island-village" to everyExampleHasFiveCompleteArtifacts(_:) started. +◇ Test case passing 1 argument id → "canyon-waterfall" to everyExampleHasFiveCompleteArtifacts(_:) started. +◇ Test case passing 1 argument id → "moonlit-harbor" to everyExampleHasFiveCompleteArtifacts(_:) started. +◇ Test case passing 1 argument id → "grand-solar-system" to everyExampleHasFiveCompleteArtifacts(_:) started. +✔ Test everyExampleHasFiveCompleteArtifacts(_:) with 21 test cases passed after 3.377 seconds. +◇ Test everyPNGDecodesAtThePublishedSizeWithVisibleGeometry(_:) started. +◇ Test case passing 1 argument id → "character-orb" to everyPNGDecodesAtThePublishedSizeWithVisibleGeometry(_:) started. +◇ Test case passing 1 argument id → "woven-torus" to everyPNGDecodesAtThePublishedSizeWithVisibleGeometry(_:) started. +◇ Test case passing 1 argument id → "moon-gate" to everyPNGDecodesAtThePublishedSizeWithVisibleGeometry(_:) started. +◇ Test case passing 1 argument id → "spiral-tower" to everyPNGDecodesAtThePublishedSizeWithVisibleGeometry(_:) started. +◇ Test case passing 1 argument id → "crystal-garden" to everyPNGDecodesAtThePublishedSizeWithVisibleGeometry(_:) started. +◇ Test case passing 1 argument id → "little-rocket" to everyPNGDecodesAtThePublishedSizeWithVisibleGeometry(_:) started. +◇ Test case passing 1 argument id → "pixel-bonsai" to everyPNGDecodesAtThePublishedSizeWithVisibleGeometry(_:) started. +◇ Test case passing 1 argument id → "orbital-rings" to everyPNGDecodesAtThePublishedSizeWithVisibleGeometry(_:) started. +◇ Test case passing 1 argument id → "hill-observatory" to everyPNGDecodesAtThePublishedSizeWithVisibleGeometry(_:) started. +◇ Test case passing 1 argument id → "terraced-island" to everyPNGDecodesAtThePublishedSizeWithVisibleGeometry(_:) started. +◇ Test case passing 1 argument id → "canal-city" to everyPNGDecodesAtThePublishedSizeWithVisibleGeometry(_:) started. +◇ Test case passing 1 argument id → "alpine-valley" to everyPNGDecodesAtThePublishedSizeWithVisibleGeometry(_:) started. +◇ Test case passing 1 argument id → "wandering-cartographer" to everyPNGDecodesAtThePublishedSizeWithVisibleGeometry(_:) started. +◇ Test case passing 1 argument id → "clockwork-dragon" to everyPNGDecodesAtThePublishedSizeWithVisibleGeometry(_:) started. +◇ Test case passing 1 argument id → "woodland-fox" to everyPNGDecodesAtThePublishedSizeWithVisibleGeometry(_:) started. +◇ Test case passing 1 argument id → "deep-sea-whale" to everyPNGDecodesAtThePublishedSizeWithVisibleGeometry(_:) started. +◇ Test case passing 1 argument id → "citadel-of-arches" to everyPNGDecodesAtThePublishedSizeWithVisibleGeometry(_:) started. +◇ Test case passing 1 argument id → "sky-island-village" to everyPNGDecodesAtThePublishedSizeWithVisibleGeometry(_:) started. +◇ Test case passing 1 argument id → "canyon-waterfall" to everyPNGDecodesAtThePublishedSizeWithVisibleGeometry(_:) started. +◇ Test case passing 1 argument id → "moonlit-harbor" to everyPNGDecodesAtThePublishedSizeWithVisibleGeometry(_:) started. +◇ Test case passing 1 argument id → "grand-solar-system" to everyPNGDecodesAtThePublishedSizeWithVisibleGeometry(_:) started. +✔ Test everyPNGDecodesAtThePublishedSizeWithVisibleGeometry(_:) with 21 test cases passed after 1.558 seconds. +◇ Test everyGIFLoopsForFourSecondsWithFortyTimedFrames(_:) started. +◇ Test case passing 1 argument id → "character-orb" to everyGIFLoopsForFourSecondsWithFortyTimedFrames(_:) started. +◇ Test case passing 1 argument id → "woven-torus" to everyGIFLoopsForFourSecondsWithFortyTimedFrames(_:) started. +◇ Test case passing 1 argument id → "moon-gate" to everyGIFLoopsForFourSecondsWithFortyTimedFrames(_:) started. +◇ Test case passing 1 argument id → "spiral-tower" to everyGIFLoopsForFourSecondsWithFortyTimedFrames(_:) started. +◇ Test case passing 1 argument id → "crystal-garden" to everyGIFLoopsForFourSecondsWithFortyTimedFrames(_:) started. +◇ Test case passing 1 argument id → "little-rocket" to everyGIFLoopsForFourSecondsWithFortyTimedFrames(_:) started. +◇ Test case passing 1 argument id → "pixel-bonsai" to everyGIFLoopsForFourSecondsWithFortyTimedFrames(_:) started. +◇ Test case passing 1 argument id → "orbital-rings" to everyGIFLoopsForFourSecondsWithFortyTimedFrames(_:) started. +◇ Test case passing 1 argument id → "hill-observatory" to everyGIFLoopsForFourSecondsWithFortyTimedFrames(_:) started. +◇ Test case passing 1 argument id → "terraced-island" to everyGIFLoopsForFourSecondsWithFortyTimedFrames(_:) started. +◇ Test case passing 1 argument id → "canal-city" to everyGIFLoopsForFourSecondsWithFortyTimedFrames(_:) started. +◇ Test case passing 1 argument id → "alpine-valley" to everyGIFLoopsForFourSecondsWithFortyTimedFrames(_:) started. +◇ Test case passing 1 argument id → "wandering-cartographer" to everyGIFLoopsForFourSecondsWithFortyTimedFrames(_:) started. +◇ Test case passing 1 argument id → "clockwork-dragon" to everyGIFLoopsForFourSecondsWithFortyTimedFrames(_:) started. +◇ Test case passing 1 argument id → "woodland-fox" to everyGIFLoopsForFourSecondsWithFortyTimedFrames(_:) started. +◇ Test case passing 1 argument id → "deep-sea-whale" to everyGIFLoopsForFourSecondsWithFortyTimedFrames(_:) started. +◇ Test case passing 1 argument id → "citadel-of-arches" to everyGIFLoopsForFourSecondsWithFortyTimedFrames(_:) started. +◇ Test case passing 1 argument id → "sky-island-village" to everyGIFLoopsForFourSecondsWithFortyTimedFrames(_:) started. +◇ Test case passing 1 argument id → "canyon-waterfall" to everyGIFLoopsForFourSecondsWithFortyTimedFrames(_:) started. +◇ Test case passing 1 argument id → "moonlit-harbor" to everyGIFLoopsForFourSecondsWithFortyTimedFrames(_:) started. +◇ Test case passing 1 argument id → "grand-solar-system" to everyGIFLoopsForFourSecondsWithFortyTimedFrames(_:) started. +✔ Test everyGIFLoopsForFourSecondsWithFortyTimedFrames(_:) with 21 test cases passed after 5.474 seconds. +◇ Test everyMP4HasOneSilentFourSecondVideoTrackAndDecodableFrames(_:) started. +◇ Test case passing 1 argument id → "character-orb" to everyMP4HasOneSilentFourSecondVideoTrackAndDecodableFrames(_:) started. +◇ Test case passing 1 argument id → "woven-torus" to everyMP4HasOneSilentFourSecondVideoTrackAndDecodableFrames(_:) started. +◇ Test case passing 1 argument id → "moon-gate" to everyMP4HasOneSilentFourSecondVideoTrackAndDecodableFrames(_:) started. +◇ Test case passing 1 argument id → "spiral-tower" to everyMP4HasOneSilentFourSecondVideoTrackAndDecodableFrames(_:) started. +◇ Test case passing 1 argument id → "crystal-garden" to everyMP4HasOneSilentFourSecondVideoTrackAndDecodableFrames(_:) started. +◇ Test case passing 1 argument id → "little-rocket" to everyMP4HasOneSilentFourSecondVideoTrackAndDecodableFrames(_:) started. +◇ Test case passing 1 argument id → "pixel-bonsai" to everyMP4HasOneSilentFourSecondVideoTrackAndDecodableFrames(_:) started. +◇ Test case passing 1 argument id → "orbital-rings" to everyMP4HasOneSilentFourSecondVideoTrackAndDecodableFrames(_:) started. +◇ Test case passing 1 argument id → "hill-observatory" to everyMP4HasOneSilentFourSecondVideoTrackAndDecodableFrames(_:) started. +◇ Test case passing 1 argument id → "terraced-island" to everyMP4HasOneSilentFourSecondVideoTrackAndDecodableFrames(_:) started. +◇ Test case passing 1 argument id → "canal-city" to everyMP4HasOneSilentFourSecondVideoTrackAndDecodableFrames(_:) started. +◇ Test case passing 1 argument id → "alpine-valley" to everyMP4HasOneSilentFourSecondVideoTrackAndDecodableFrames(_:) started. +◇ Test case passing 1 argument id → "wandering-cartographer" to everyMP4HasOneSilentFourSecondVideoTrackAndDecodableFrames(_:) started. +◇ Test case passing 1 argument id → "clockwork-dragon" to everyMP4HasOneSilentFourSecondVideoTrackAndDecodableFrames(_:) started. +◇ Test case passing 1 argument id → "woodland-fox" to everyMP4HasOneSilentFourSecondVideoTrackAndDecodableFrames(_:) started. +◇ Test case passing 1 argument id → "deep-sea-whale" to everyMP4HasOneSilentFourSecondVideoTrackAndDecodableFrames(_:) started. +◇ Test case passing 1 argument id → "citadel-of-arches" to everyMP4HasOneSilentFourSecondVideoTrackAndDecodableFrames(_:) started. +◇ Test case passing 1 argument id → "sky-island-village" to everyMP4HasOneSilentFourSecondVideoTrackAndDecodableFrames(_:) started. +◇ Test case passing 1 argument id → "canyon-waterfall" to everyMP4HasOneSilentFourSecondVideoTrackAndDecodableFrames(_:) started. +◇ Test case passing 1 argument id → "moonlit-harbor" to everyMP4HasOneSilentFourSecondVideoTrackAndDecodableFrames(_:) started. +◇ Test case passing 1 argument id → "grand-solar-system" to everyMP4HasOneSilentFourSecondVideoTrackAndDecodableFrames(_:) started. +✔ Test everyMP4HasOneSilentFourSecondVideoTrackAndDecodableFrames(_:) with 21 test cases passed after 5.339 seconds. +◇ Test everyOBJContainsBoundedOutwardFacingVoxelGeometry(_:) started. +◇ Test case passing 1 argument id → "character-orb" to everyOBJContainsBoundedOutwardFacingVoxelGeometry(_:) started. +◇ Test case passing 1 argument id → "woven-torus" to everyOBJContainsBoundedOutwardFacingVoxelGeometry(_:) started. +◇ Test case passing 1 argument id → "moon-gate" to everyOBJContainsBoundedOutwardFacingVoxelGeometry(_:) started. +◇ Test case passing 1 argument id → "spiral-tower" to everyOBJContainsBoundedOutwardFacingVoxelGeometry(_:) started. +◇ Test case passing 1 argument id → "crystal-garden" to everyOBJContainsBoundedOutwardFacingVoxelGeometry(_:) started. +◇ Test case passing 1 argument id → "little-rocket" to everyOBJContainsBoundedOutwardFacingVoxelGeometry(_:) started. +◇ Test case passing 1 argument id → "pixel-bonsai" to everyOBJContainsBoundedOutwardFacingVoxelGeometry(_:) started. +◇ Test case passing 1 argument id → "orbital-rings" to everyOBJContainsBoundedOutwardFacingVoxelGeometry(_:) started. +◇ Test case passing 1 argument id → "hill-observatory" to everyOBJContainsBoundedOutwardFacingVoxelGeometry(_:) started. +◇ Test case passing 1 argument id → "terraced-island" to everyOBJContainsBoundedOutwardFacingVoxelGeometry(_:) started. +◇ Test case passing 1 argument id → "canal-city" to everyOBJContainsBoundedOutwardFacingVoxelGeometry(_:) started. +◇ Test case passing 1 argument id → "alpine-valley" to everyOBJContainsBoundedOutwardFacingVoxelGeometry(_:) started. +◇ Test case passing 1 argument id → "wandering-cartographer" to everyOBJContainsBoundedOutwardFacingVoxelGeometry(_:) started. +◇ Test case passing 1 argument id → "clockwork-dragon" to everyOBJContainsBoundedOutwardFacingVoxelGeometry(_:) started. +◇ Test case passing 1 argument id → "woodland-fox" to everyOBJContainsBoundedOutwardFacingVoxelGeometry(_:) started. +◇ Test case passing 1 argument id → "deep-sea-whale" to everyOBJContainsBoundedOutwardFacingVoxelGeometry(_:) started. +◇ Test case passing 1 argument id → "citadel-of-arches" to everyOBJContainsBoundedOutwardFacingVoxelGeometry(_:) started. +◇ Test case passing 1 argument id → "sky-island-village" to everyOBJContainsBoundedOutwardFacingVoxelGeometry(_:) started. +◇ Test case passing 1 argument id → "canyon-waterfall" to everyOBJContainsBoundedOutwardFacingVoxelGeometry(_:) started. +◇ Test case passing 1 argument id → "moonlit-harbor" to everyOBJContainsBoundedOutwardFacingVoxelGeometry(_:) started. +◇ Test case passing 1 argument id → "grand-solar-system" to everyOBJContainsBoundedOutwardFacingVoxelGeometry(_:) started. +✔ Test everyOBJContainsBoundedOutwardFacingVoxelGeometry(_:) with 21 test cases passed after 15.440 seconds. +◇ Test blockhavenManifestMatchesSelfContainedSourcesCompactVolumeAndAllDownloadLinks() started. +✔ Test blockhavenManifestMatchesSelfContainedSourcesCompactVolumeAndAllDownloadLinks() passed after 6.642 seconds. +◇ Test blockhavenPNGAndLoopingGIFDecodeWithVisibleChangingLandscapeAndPublishedTiming() started. +✔ Test blockhavenPNGAndLoopingGIFDecodeWithVisibleChangingLandscapeAndPublishedTiming() passed after 0.560 seconds. +◇ Test blockhavenVideoHasThePublishedSilentTimingAndDecodableLandscape() started. +✔ Test blockhavenVideoHasThePublishedSilentTimingAndDecodableLandscape() passed after 0.250 seconds. +◇ Test blockhavenOBJHasEveryExteriorFaceWithCorrectBoundsMaterialsAndOutwardWinding() started. +✔ Test blockhavenOBJHasEveryExteriorFaceWithCorrectBoundsMaterialsAndOutwardWinding() passed after 5.943 seconds. +✔ Suite ExampleArtifactTests passed after 44.605 seconds. +◇ Suite PreparedVoxelProjectionTests started. +◇ Test directExtractionPreservesAllNeighborsMaterialsBoundariesAndStableOrder() started. +✔ Test directExtractionPreservesAllNeighborsMaterialsBoundariesAndStableOrder() passed after 0.001 seconds. +◇ Test preparedFramesHaveExactDocumentProjectionAndPixelParityAcrossCameraPoses() started. +✔ Test preparedFramesHaveExactDocumentProjectionAndPixelParityAcrossCameraPoses() passed after 0.138 seconds. +◇ Test preparedEmptyAndCancelledFramesNeverPublishGhostsOrPartialPicking() started. +✔ Test preparedEmptyAndCancelledFramesNeverPublishGhostsOrPartialPicking() passed after 0.001 seconds. +◇ Test cubeAnimationRetainsPerFrameFallbackWhenCompleteSceneExceedsExtractionBudget() started. +✔ Test cubeAnimationRetainsPerFrameFallbackWhenCompleteSceneExceedsExtractionBudget() passed after 15.235 seconds. +◇ Test cubeAnimationFallbackStillRefusesAnOverBudgetFrameAndCleansItsStaging() started. +✔ Test cubeAnimationFallbackStillRefusesAnOverBudgetFrameAndCleansItsStaging() passed after 1.544 seconds. +✔ Suite PreparedVoxelProjectionTests passed after 16.919 seconds. +◇ Test imageExportHasExpectedDimensionsAndDecodesAsPNG() started. +✔ Test imageExportHasExpectedDimensionsAndDecodesAsPNG() passed after 0.009 seconds. +◇ Test glyphRasterDiffersFromEmptyVolume() started. +✔ Test glyphRasterDiffersFromEmptyVolume() passed after 0.012 seconds. +◇ Test metalBackendCompletesAndWritesVisibleGlyphs() started. +✔ Test metalBackendCompletesAndWritesVisibleGlyphs() passed after 0.048 seconds. +◇ Suite SculptureBlockPerformanceTests started. +◇ Test measureLargeLandscapePreparationAndCameraWork() started. +✔ Test measureLargeLandscapePreparationAndCameraWork() passed after 0.001 seconds. +✔ Suite SculptureBlockPerformanceTests passed after 0.001 seconds. +◇ Suite SculptureLiveVoxelTests started. +◇ Test gpuPickingMatchesTheExistingProjectionAtOffCenterPointsAndSeveralPoses() started. +✔ Test gpuPickingMatchesTheExistingProjectionAtOffCenterPointsAndSeveralPoses() passed after 0.004 seconds. +◇ Test gpuPickingChoosesTheNearestCubeOrGhostAndPreservesTheVolumeBoundary() started. +✔ Test gpuPickingChoosesTheNearestCubeOrGhostAndPreservesTheVolumeBoundary() passed after 0.001 seconds. +◇ Test metalSnapshotRendersRealColoredGeometryAndRetainsNativeEvidence() started. +✔ Test metalSnapshotRendersRealColoredGeometryAndRetainsNativeEvidence() passed after 0.079 seconds. +◇ Test cameraResizeUsesTheSameMeshAndMatchesTheReferencePickingScale() started. +✔ Test cameraResizeUsesTheSameMeshAndMatchesTheReferencePickingScale() passed after 0.002 seconds. +◇ Test denseGhostGridKeepsEveryPickTargetAndVisibleCubesWhenGridEdgesAreHidden() started. +✔ Test denseGhostGridKeepsEveryPickTargetAndVisibleCubesWhenGridEdgesAreHidden() passed after 0.152 seconds. +✔ Suite SculptureLiveVoxelTests passed after 0.241 seconds. +◇ Suite SculptureLiveWorldTests started. +◇ Test largeIntegerAnchorsPreserveAdjacentPositionsPickingAndSharedGeometryAcrossCameraUpdates() started. +✔ Test largeIntegerAnchorsPreserveAdjacentPositionsPickingAndSharedGeometryAcrossCameraUpdates() passed after 0.002 seconds. +◇ Test boundingIntersectionRotationAndDetailDistanceControlDetailedAndColoredCoarseNodes() started. +✔ Test boundingIntersectionRotationAndDetailDistanceControlDetailedAndColoredCoarseNodes() passed after 0.003 seconds. +◇ Test visibleCapacityAndFullFaceBudgetDegradeToBoundedSharedProxiesDeterministically() started. +✔ Test visibleCapacityAndFullFaceBudgetDegradeToBoundedSharedProxiesDeterministically() passed after 0.059 seconds. +◇ Test preparationSkipsUnusedDefinitionsAndRejectsAnOversizedAggregateCache() started. +✔ Test preparationSkipsUnusedDefinitionsAndRejectsAnOversizedAggregateCache() passed after 1.610 seconds. +◇ Test actualMetalWorldSnapshotsContainColoredDetailsSelectableCoarseModelsAndRetainedEvidence() started. +✔ Test actualMetalWorldSnapshotsContainColoredDetailsSelectableCoarseModelsAndRetainedEvidence() passed after 0.321 seconds. +◇ Test nestedGardenAndCourtyardKeepGlyphColorsAcrossDenseNativeEdges() started. +✔ Test nestedGardenAndCourtyardKeepGlyphColorsAcrossDenseNativeEdges() passed after 1.405 seconds. +✔ Suite SculptureLiveWorldTests passed after 3.402 seconds. +◇ Suite SculptureSolarPerformanceTests started. +◇ Test actualSolarSystemFitsTheReusableExteriorMeshBudget() started. +✔ Test actualSolarSystemFitsTheReusableExteriorMeshBudget() passed after 0.442 seconds. +◇ Test solarCameraAndLayerChangesRetainActualNativeGeometryBuffers() started. +✔ Test solarCameraAndLayerChangesRetainActualNativeGeometryBuffers() passed after 0.570 seconds. +✔ Suite SculptureSolarPerformanceTests passed after 1.013 seconds. +◇ Suite SculptureVolumeStudyRenderingTests started. +◇ Test smallWorldCountsAndCameraUpdatesRetainSharedMeshes() started. +✔ Test smallWorldCountsAndCameraUpdatesRetainSharedMeshes() passed after 0.002 seconds. +◇ Test measure1024WorldMetalRendering() started. +✔ Test measure1024WorldMetalRendering() passed after 0.001 seconds. +✔ Suite SculptureVolumeStudyRenderingTests passed after 0.002 seconds. +◇ Suite SculptureVoxelMeshBuffersTests started. +◇ Test packedBytesPreserveEveryMaterialFaceWindingAndStablePickingIndex() started. +✔ Test packedBytesPreserveEveryMaterialFaceWindingAndStablePickingIndex() passed after 0.001 seconds. +◇ Test ghostBuffersPreserveFilteringOrderDepthCoordinatesAndExactTargetCapacity() started. +✔ Test ghostBuffersPreserveFilteringOrderDepthCoordinatesAndExactTargetCapacity() passed after 0.135 seconds. +◇ Test placementChangesReuseImmutablePreparedModelsButDefinitionChangesInvalidateThem() started. +✔ Test placementChangesReuseImmutablePreparedModelsButDefinitionChangesInvalidateThem() passed after 0.001 seconds. +◇ Test canceledWorkersNeverPublishPartialMeshGhostsOrReusedWorldScenes() started. +✔ Test canceledWorkersNeverPublishPartialMeshGhostsOrReusedWorldScenes() passed after 0.001 seconds. +✔ Suite SculptureVoxelMeshBuffersTests passed after 0.137 seconds. +◇ Suite SculpturePreparedNativeMeshTests started. +◇ Test selectedSliceOutlineMovesToTheChosenDepthInTheActualMetalImage() started. +✔ Test selectedSliceOutlineMovesToTheChosenDepthInTheActualMetalImage() passed after 3.017 seconds. +◇ Test preparedCanvasRetainsPickingAndSelectedOutlineWhenDenseGridLODChanges() started. +✔ Test preparedCanvasRetainsPickingAndSelectedOutlineWhenDenseGridLODChanges() passed after 0.296 seconds. +◇ Test movedAndRotatedWorldInstancesKeepActualModelGeometryAndNearestPicks() started. +✔ Test movedAndRotatedWorldInstancesKeepActualModelGeometryAndNearestPicks() passed after 0.001 seconds. +✔ Suite SculpturePreparedNativeMeshTests passed after 3.315 seconds. +◇ Test singleVoxelSurfaceIncludesEveryFaceAndItsEmptyNeighborInStableOrder() started. +✔ Test singleVoxelSurfaceIncludesEveryFaceAndItsEmptyNeighborInStableOrder() passed after 0.001 seconds. +◇ Test neighboringMaterialsOmitSharedInteriorFaces() started. +✔ Test neighboringMaterialsOmitSharedInteriorFaces() passed after 0.001 seconds. +◇ Test hollowVolumeRetainsCavityFacesWithoutExposingJoinedFaces() started. +✔ Test hollowVolumeRetainsCavityFacesWithoutExposingJoinedFaces() passed after 0.001 seconds. +◇ Test sparseFinalCellOfMaximumVolumeHasSixCorrectlyBoundedFaces() started. +✔ Test sparseFinalCellOfMaximumVolumeHasSixCorrectlyBoundedFaces() passed after 2.099 seconds. +◇ Test cachedOccupancySupportsBoundsAndIndependentSurfaceSnapshotsAfterEditing() started. +✔ Test cachedOccupancySupportsBoundsAndIndependentSurfaceSnapshotsAfterEditing() passed after 0.001 seconds. +◇ Test disconnectedSurfaceBudgetThrowsInsteadOfReturningPartialGeometry() started. +✔ Test disconnectedSurfaceBudgetThrowsInsteadOfReturningPartialGeometry() passed after 0.214 seconds. +◇ Test cancelledSurfaceExtractionReturnsNoPartialScene() started. +✔ Test cancelledSurfaceExtractionReturnsNoPartialScene() passed after 0.002 seconds. +◇ Suite "Bounded colored world silhouettes" started. +◇ Test emptyVolumeHasNoGeometryAndSmallModelsMatchFullDetail() started. +✔ Test emptyVolumeHasNoGeometryAndSmallModelsMatchFullDetail() passed after 0.001 seconds. +◇ Test dominantNonemptyMaterialAndPaletteOrderTiesAreDeterministic() started. +✔ Test dominantNonemptyMaterialAndPaletteOrderTiesAreDeterministic() passed after 0.001 seconds. +◇ Test thinRoofTrunkAndGroundKeepARecognizableSilhouetteInsteadOfAFullBox() started. +✔ Test thinRoofTrunkAndGroundKeepARecognizableSilhouetteInsteadOfAFullBox() passed after 0.040 seconds. +◇ Test oddDimensionsAndPartialBinsPreserveRealExtentsAndCenter() started. +✔ Test oddDimensionsAndPartialBinsPreserveRealExtentsAndCenter() passed after 0.003 seconds. +◇ Test maximumStrideCountsDenseBinsWithoutOverflowOrOversizedGrid() started. +✔ Test maximumStrideCountsDenseBinsWithoutOverflowOrOversizedGrid() passed after 0.045 seconds. +◇ Test disconnectedCoarseGridStaysBelowTheExplicitFaceAndByteBudgets() started. +✔ Test disconnectedCoarseGridStaysBelowTheExplicitFaceAndByteBudgets() passed after 0.027 seconds. +◇ Test cancellationReturnsNoPartialCoarseResult() started. +✔ Test cancellationReturnsNoPartialCoarseResult() passed after 0.008 seconds. +✔ Suite "Bounded colored world silhouettes" passed after 0.127 seconds. +◇ Suite SculptureWorldExplorationRenderingTests started. +◇ Test optionalActualMetalOverviewAndLandmarkExplorationEvidence() started. +✔ Test optionalActualMetalOverviewAndLandmarkExplorationEvidence() passed after 0.001 seconds. +◇ Test perspectiveAndOrbitSwitchesRestoreCameraWithoutChangingWorldOrMeshes() started. +✔ Test perspectiveAndOrbitSwitchesRestoreCameraWithoutChangingWorldOrMeshes() passed after 0.012 seconds. +◇ Test localTravelLookAndExactIntegerRebaseRetainDetailedAndCoarseBuffers() started. +✔ Test localTravelLookAndExactIntegerRebaseRetainDetailedAndCoarseBuffers() passed after 0.002 seconds. +◇ Test nativePerspectiveAndOrbitPickBothColoredCoarseAndDetailedInstances() started. +✔ Test nativePerspectiveAndOrbitPickBothColoredCoarseAndDetailedInstances() passed after 0.003 seconds. +◇ Test realNativeKeyEventsMapHorizontalAndVerticalMovementAndReleaseWithoutClockRaces() started. +✔ Test realNativeKeyEventsMapHorizontalAndVerticalMovementAndReleaseWithoutClockRaces() passed after 0.016 seconds. +◇ Test nativeHeldKeysStopOnResponderLossWindowKeyLossCloseModeChangeAndDismantling() started. +✔ Test nativeHeldKeysStopOnResponderLossWindowKeyLossCloseModeChangeAndDismantling() passed after 0.016 seconds. +◇ Test nativeExploreDragChangesLookAndClickStillSelectsWithoutMutatingSource() started. +✔ Test nativeExploreDragChangesLookAndClickStillSelectsWithoutMutatingSource() passed after 0.020 seconds. +✔ Suite SculptureWorldExplorationRenderingTests passed after 0.071 seconds. +◇ Suite SculptureWorldNavigationTests started. +◇ Test smallMovesRetainExactAnchorsBeyondDoubleIntegerPrecision() started. +✔ Test smallMovesRetainExactAnchorsBeyondDoubleIntegerPrecision() passed after 0.001 seconds. +◇ Test positiveAndNegativeRebasesPreserveFractionalEyeOffsetsExactly() started. +✔ Test positiveAndNegativeRebasesPreserveFractionalEyeOffsetsExactly() passed after 0.001 seconds. +◇ Test diagonalsAndVerticalTravelUseTheSameCellsPerSecondSpeed() started. +✔ Test diagonalsAndVerticalTravelUseTheSameCellsPerSecondSpeed() passed after 0.001 seconds. +◇ Test yawRotatesFlatMovementWhilePitchOnlyChangesLook() started. +✔ Test yawRotatesFlatMovementWhilePitchOnlyChangesLook() passed after 0.001 seconds. +◇ Test elapsedTimeAndFastSpeedAreIndependentOfEventRepeatFrequency() started. +✔ Test elapsedTimeAndFastSpeedAreIndependentOfEventRepeatFrequency() passed after 0.001 seconds. +◇ Test checkedBoundariesRejectOverflowBeforeRebaseAndLeaveMovementAtomic() started. +✔ Test checkedBoundariesRejectOverflowBeforeRebaseAndLeaveMovementAtomic() passed after 0.001 seconds. +◇ Test invalidMovementFailsWithoutMutatingAndLookNeverInverts() started. +✔ Test invalidMovementFailsWithoutMutatingAndLookNeverInverts() passed after 0.001 seconds. +✔ Suite SculptureWorldNavigationTests passed after 0.001 seconds. +◇ Suite VoxelRenderingTests started. +◇ Test excessiveDisconnectedSurfaceReturnsAnExplicitBudgetFailureWithoutPartialPicking() started. +✔ Test excessiveDisconnectedSurfaceReturnsAnExplicitBudgetFailureWithoutPartialPicking() passed after 1.514 seconds. +◇ Test frontFacePickingAddsOnlyToAnEmptyInBoundsNeighbor() started. +✔ Test frontFacePickingAddsOnlyToAnEmptyInBoundsNeighbor() passed after 0.001 seconds. +◇ Test joinedCubesCullSharedFacesAndPickTheNearestVisibleCube() started. +✔ Test joinedCubesCullSharedFacesAndPickTheNearestVisibleCube() passed after 0.001 seconds. +◇ Test cameraRotationChangesThePaintableFaceAndNeighbor() started. +✔ Test cameraRotationChangesThePaintableFaceAndNeighbor() passed after 0.001 seconds. +◇ Test selectedEmptySliceProvidesRealPickableCellsWithoutInventingCubes() started. +✔ Test selectedEmptySliceProvidesRealPickableCellsWithoutInventingCubes() passed after 0.001 seconds. +◇ Test ghostGridCannotStealAnOccludedCubeHit() started. +✔ Test ghostGridCannotStealAnOccludedCubeHit() passed after 0.001 seconds. +◇ Test fullSizeSolidVolumeExposesOnlyItsOuterSurface() started. +✔ Test fullSizeSolidVolumeExposesOnlyItsOuterSurface() passed after 0.512 seconds. +◇ Test rasterOutputHasGenuineTranslucentFacesAndOptionalClearBackground() started. +✔ Test rasterOutputHasGenuineTranslucentFacesAndOptionalClearBackground() passed after 0.001 seconds. +◇ Test projectionRejectsInvalidHitCoordinatesAndNormalizesNonfiniteCamera() started. +✔ Test projectionRejectsInvalidHitCoordinatesAndNormalizesNonfiniteCamera() passed after 0.001 seconds. +◇ Test cancelledRenderDoesNotPublishPartialGeometryOrImage() started. +✔ Test cancelledRenderDoesNotPublishPartialGeometryOrImage() passed after 0.001 seconds. +✔ Suite VoxelRenderingTests passed after 2.030 seconds. +◇ Test singleVoxelOBJHasClosedOutwardSurfaceAndCenteredBounds() started. +✔ Test singleVoxelOBJHasClosedOutwardSurfaceAndCenteredBounds() passed after 0.001 seconds. +◇ Test neighboringGlyphsShareVerticesAndOmitTheirInternalFaces() started. +✔ Test neighboringGlyphsShareVerticesAndOmitTheirInternalFaces() passed after 0.001 seconds. +◇ Test hollowVoxelMeshPreservesTheInteriorSurface() started. +✔ Test hollowVoxelMeshPreservesTheInteriorSurface() passed after 0.002 seconds. +◇ Test emptyOBJContainsNoInventedGeometry() started. +✔ Test emptyOBJContainsNoInventedGeometry() passed after 0.001 seconds. +◇ Test orbOBJIsClosedAndCanBeRetainedAsExportEvidence() started. +✔ Test orbOBJIsClosedAndCanBeRetainedAsExportEvidence() passed after 0.070 seconds. +◇ Test sixtyFourSolidVolumeExportsItsSurfaceRatherThanEveryCube() started. +✔ Test sixtyFourSolidVolumeExportsItsSurfaceRatherThanEveryCube() passed after 1.950 seconds. +◇ Test highCoordinatesExportAClosedSurfaceWithCorrectCenteredBounds() started. +✔ Test highCoordinatesExportAClosedSurfaceWithCorrectCenteredBounds() passed after 0.034 seconds. +◇ Test isolatedCubeVolumeFailsBeforeAllocatingAnUnboundedMesh() started. +✔ Test isolatedCubeVolumeFailsBeforeAllocatingAnUnboundedMesh() passed after 0.171 seconds. +◇ Test cancelledOBJExportDoesNotReturnAPartialMesh() started. +✔ Test cancelledOBJExportDoesNotReturnAPartialMesh() passed after 0.001 seconds. +◇ Test sha256MatchesThePublishedEmptyAndABCVectors() started. +✔ Test sha256MatchesThePublishedEmptyAndABCVectors() passed after 0.001 seconds. +◇ Test sha256MatchesCryptoKit() started. +✔ Test sha256MatchesCryptoKit() passed after 0.054 seconds. +◇ Test compactRoundTripPreservesEveryGlyphRectangularDimensionsAndTitle() started. +✔ Test compactRoundTripPreservesEveryGlyphRectangularDimensionsAndTitle() passed after 0.001 seconds. +◇ Test documentCodecAutodetectsFormatsAndLeavesReadableEncodingUnchanged() started. +✔ Test documentCodecAutodetectsFormatsAndLeavesReadableEncodingUnchanged() passed after 0.011 seconds. +◇ Test compactMaximumFilledVolumeRoundTripsWithExactDimensionsAndOccupancy() started. +✔ Test compactMaximumFilledVolumeRoundTripsWithExactDimensionsAndOccupancy() passed after 28.290 seconds. +◇ Test sparseCompactStorageIsSubstantiallySmallerThanRawVoxels() started. +✔ Test sparseCompactStorageIsSubstantiallySmallerThanRawVoxels() passed after 0.362 seconds. +◇ Test compactRejectsEmptyIncompleteAndCorruptedHeaders() started. +✔ Test compactRejectsEmptyIncompleteAndCorruptedHeaders() passed after 0.005 seconds. +◇ Test compactBoundsDimensionsTitleAndDeclaredCountsBeforeDecompression() started. +✔ Test compactBoundsDimensionsTitleAndDeclaredCountsBeforeDecompression() passed after 0.009 seconds. +◇ Test compactChecksumProtectsBothMetadataAndVoxelContent() started. +✔ Test compactChecksumProtectsBothMetadataAndVoxelContent() passed after 0.001 seconds. +◇ Test compactRejectsTruncationTrailingBytesAndConcatenatedStreamsEvenWithCorrectChecksums() started. +✔ Test compactRejectsTruncationTrailingBytesAndConcatenatedStreamsEvenWithCorrectChecksums() passed after 0.001 seconds. +◇ Test compactRejectsConcatenationAfterDrainingFourBufferedOutputChunks() started. +✔ Test compactRejectsConcatenationAfterDrainingFourBufferedOutputChunks() passed after 0.329 seconds. +◇ Test compactDecompressionRejectsExpansionBeyondTheDeclaredVolumeAndShortOutput() started. +✔ Test compactDecompressionRejectsExpansionBeyondTheDeclaredVolumeAndShortOutput() passed after 0.001 seconds. +◇ Test malformedCompressedStreamsFailWithoutUnboundedOutputOrNoProgressLoops() started. +✔ Test malformedCompressedStreamsFailWithoutUnboundedOutputOrNoProgressLoops() passed after 0.006 seconds. +◇ Test compactCodecCancellationDoesNotReturnPartialData(operation:) started. +◇ Test case passing 1 argument operation → "encode" to compactCodecCancellationDoesNotReturnPartialData(operation:) started. +◇ Test case passing 1 argument operation → "decode" to compactCodecCancellationDoesNotReturnPartialData(operation:) started. +✔ Test compactCodecCancellationDoesNotReturnPartialData(operation:) with 2 test cases passed after 0.007 seconds. +◇ Suite SculptureBlockWorldExamplesTests started. +◇ Test chunkLibraryIsDeterministicAndExpandsToTheCompleteLandscape() started. +✔ Test chunkLibraryIsDeterministicAndExpandsToTheCompleteLandscape() passed after 3.569 seconds. +◇ Test adjacentChunksHaveContinuousGroundAndAConnectedRiverAcrossEveryDepthSeam() started. +✔ Test adjacentChunksHaveContinuousGroundAndAConnectedRiverAcrossEveryDepthSeam() passed after 0.002 seconds. +◇ Test landscapeHasDeepHillsWaterBanksCavesAndThreeDistinctTreeSilhouettes() started. +✔ Test landscapeHasDeepHillsWaterBanksCavesAndThreeDistinctTreeSilhouettes() passed after 0.282 seconds. +◇ Test villageAndLandmarksHaveUsableInteriorsDoorsWindowsCropsAndRoofs() started. +✔ Test villageAndLandmarksHaveUsableInteriorsDoorsWindowsCropsAndRoofs() passed after 0.001 seconds. +◇ Test sparsePlacementsUseExactlyAlignedChunkModelsAndStayWithinGeometryBudgets() started. +✔ Test sparsePlacementsUseExactlyAlignedChunkModelsAndStayWithinGeometryBudgets() passed after 2.788 seconds. +◇ Test canceledGenerationThrowsInsteadOfReturningAPartialLibraryOrWorld() started. +✔ Test canceledGenerationThrowsInsteadOfReturningAPartialLibraryOrWorld() passed after 0.001 seconds. +✔ Suite SculptureBlockWorldExamplesTests passed after 6.642 seconds. +◇ Test commandsEncodeAsFlatTaggedObjectsAndRoundTrip() started. +✔ Test commandsEncodeAsFlatTaggedObjectsAndRoundTrip() passed after 0.001 seconds. +◇ Test strictCommandDecodingRejectsUnknownIrrelevantMissingAndWrongFields() started. +✔ Test strictCommandDecodingRejectsUnknownIrrelevantMissingAndWrongFields() passed after 0.003 seconds. +◇ Test batchVersionAndCommandCountAreRequiredAndBounded() started. +✔ Test batchVersionAndCommandCountAreRequiredAndBounded() passed after 0.001 seconds. +◇ Test paintEraseAndEmptyGlyphUseExactValidatedCoordinates() started. +✔ Test paintEraseAndEmptyGlyphUseExactValidatedCoordinates() passed after 0.001 seconds. +◇ Test invalidCellsAndGlyphsThrowRatherThanSilentlyIgnoreOrFallback() started. +✔ Test invalidCellsAndGlyphsThrowRatherThanSilentlyIgnoreOrFallback() passed after 0.001 seconds. +◇ Test fillVisitsOnlyFourConnectedMatchingCellsOnItsOwnSlice() started. +✔ Test fillVisitsOnlyFourConnectedMatchingCellsOnItsOwnSlice() passed after 0.001 seconds. +◇ Test fillCanPaintOrEraseEmptyRegionsWithoutCrossingABarrier() started. +✔ Test fillCanPaintOrEraseEmptyRegionsWithoutCrossingABarrier() passed after 0.001 seconds. +◇ Test clearingOneSliceLeavesOtherLayersAndTitleIntact() started. +✔ Test clearingOneSliceLeavesOtherLayersAndTitleIntact() passed after 0.001 seconds. +◇ Test rotationIsClockwiseBoundedAndRejectsRectangularSlices() started. +✔ Test rotationIsClockwiseBoundedAndRejectsRectangularSlices() passed after 0.001 seconds. +◇ Test renamePreservesGeometryAndRejectsInvalidTitles() started. +✔ Test renamePreservesGeometryAndRejectsInvalidTitles() passed after 0.001 seconds. +◇ Test batchesApplyInOrderAndFailAtomicallyWithoutChangingTheirSource() started. +✔ Test batchesApplyInOrderAndFailAtomicallyWithoutChangingTheirSource() passed after 0.001 seconds. +◇ Test inspectionIsCodableAndDescribesTheDocumentCoordinateSystem() started. +✔ Test inspectionIsCodableAndDescribesTheDocumentCoordinateSystem() passed after 0.002 seconds. +◇ Test complexCatalogAddsCharactersCreaturesArchitectureAndWorlds() started. +✔ Test complexCatalogAddsCharactersCreaturesArchitectureAndWorlds() passed after 0.001 seconds. +◇ Test largeExamplesStayEditableAndBoundedForMeshAndMediaExport(id:) started. +◇ Test case passing 1 argument id → "wandering-cartographer" to largeExamplesStayEditableAndBoundedForMeshAndMediaExport(id:) started. +◇ Test case passing 1 argument id → "clockwork-dragon" to largeExamplesStayEditableAndBoundedForMeshAndMediaExport(id:) started. +◇ Test case passing 1 argument id → "woodland-fox" to largeExamplesStayEditableAndBoundedForMeshAndMediaExport(id:) started. +◇ Test case passing 1 argument id → "deep-sea-whale" to largeExamplesStayEditableAndBoundedForMeshAndMediaExport(id:) started. +◇ Test case passing 1 argument id → "citadel-of-arches" to largeExamplesStayEditableAndBoundedForMeshAndMediaExport(id:) started. +◇ Test case passing 1 argument id → "sky-island-village" to largeExamplesStayEditableAndBoundedForMeshAndMediaExport(id:) started. +◇ Test case passing 1 argument id → "canyon-waterfall" to largeExamplesStayEditableAndBoundedForMeshAndMediaExport(id:) started. +◇ Test case passing 1 argument id → "moonlit-harbor" to largeExamplesStayEditableAndBoundedForMeshAndMediaExport(id:) started. +✔ Test largeExamplesStayEditableAndBoundedForMeshAndMediaExport(id:) with 8 test cases passed after 1.086 seconds. +◇ Test cartographerHasFaceMapStaffAndSeparatedLegs() started. +✔ Test cartographerHasFaceMapStaffAndSeparatedLegs() passed after 0.001 seconds. +◇ Test dragonHasMirroredRaisedWingsHornsAndAnOpenJaw() started. +✔ Test dragonHasMirroredRaisedWingsHornsAndAnOpenJaw() passed after 0.001 seconds. +◇ Test foxHasTwoEarTipsLongMuzzleAndSeparatedFrontPaws() started. +✔ Test foxHasTwoEarTipsLongMuzzleAndSeparatedFrontPaws() passed after 0.001 seconds. +◇ Test whaleHasWideNotchedFlukeFlippersAndBranchingSpout() started. +✔ Test whaleHasWideNotchedFlukeFlippersAndBranchingSpout() passed after 0.001 seconds. +◇ Test citadelHasTraversableGateCourtyardAndHollowTowerRooms() started. +✔ Test citadelHasTraversableGateCourtyardAndHollowTowerRooms() passed after 0.001 seconds. +◇ Test skyVillageHasSuspendedTerrainBridgesAndWindmillAboveHomes() started. +✔ Test skyVillageHasSuspendedTerrainBridgesAndWindmillAboveHomes() passed after 0.001 seconds. +◇ Test canyonHasFlowingWaterOpenArchAndCarvedCave() started. +✔ Test canyonHasFlowingWaterOpenArchAndCarvedCave() passed after 0.001 seconds. +◇ Test harborHasSailsLightedLanternOpenHomesAndCrescentMoon() started. +✔ Test harborHasSailsLightedLanternOpenHomesAndCrescentMoon() passed after 0.001 seconds. +◇ Suite "Composition example" started. +◇ Test startersAreBoundedAndIndependent() started. +✔ Test startersAreBoundedAndIndependent() passed after 0.001 seconds. +◇ Test repeatedNestedReferencesRoundTripAndExpandExactly() started. +✔ Test repeatedNestedReferencesRoundTripAndExpandExactly() passed after 0.770 seconds. +◇ Test sparseWorldExamplePreservesTrillionCellDistancesWithoutDenseAllocation() started. +✔ Test sparseWorldExamplePreservesTrillionCellDistancesWithoutDenseAllocation() passed after 0.020 seconds. +✔ Suite "Composition example" passed after 0.791 seconds. +◇ Suite SculptureCompositionTests started. +◇ Test tileBlocksPreserveDepthPaddingAndAllFourRectangularRotations() started. +✔ Test tileBlocksPreserveDepthPaddingAndAllFourRectangularRotations() passed after 0.001 seconds. +◇ Test nestedModelsResolveByGlobalIDAndPeriodsReserveEmptyBlocks() started. +✔ Test nestedModelsResolveByGlobalIDAndPeriodsReserveEmptyBlocks() passed after 0.001 seconds. +◇ Test validationRejectsUnusedMissingReferencesAndCycles() started. +✔ Test validationRejectsUnusedMissingReferencesAndCycles() passed after 0.001 seconds. +◇ Test invalidBindingsGridsIDsAndRootAreExplicitFailures() started. +✔ Test invalidBindingsGridsIDsAndRootAreExplicitFailures() passed after 0.001 seconds. +◇ Test dimensionsAndRotatedChildFitNeverCropOrOverflow() started. +✔ Test dimensionsAndRotatedChildFitNeverCropOrOverflow() passed after 0.001 seconds. +◇ Test modelAndDependencyDepthLimitsHaveAcceptedBoundaryCases() started. +✔ Test modelAndDependencyDepthLimitsHaveAcceptedBoundaryCases() passed after 0.001 seconds. +◇ Test recursivePlacementLimitIncludesRepeatedNestedOccurrences() started. +✔ Test recursivePlacementLimitIncludesRepeatedNestedOccurrences() passed after 0.105 seconds. +◇ Test resolvedVolumeBudgetCountsDistinctUnusedModelsBeforeExpansion() started. +✔ Test resolvedVolumeBudgetCountsDistinctUnusedModelsBeforeExpansion() passed after 2.090 seconds. +◇ Test canonicalCodecPreservesTheGraphAndExpandedResult() started. +✔ Test canonicalCodecPreservesTheGraphAndExpandedResult() passed after 0.001 seconds. +◇ Test fenceLookingRowsAndDirectiveLookingCharactersRoundTripExactly() started. +✔ Test fenceLookingRowsAndDirectiveLookingCharactersRoundTripExactly() passed after 0.001 seconds. +◇ Test unknownAndOverwrittenMetadataPlaneAttributesAndBindingAliasesFail() started. +✔ Test unknownAndOverwrittenMetadataPlaneAttributesAndBindingAliasesFail() passed after 0.001 seconds. +◇ Test libraryRejectsUnknownKeysDuplicateKeysDuplicateIDsAndNestedLibraries() started. +✔ Test libraryRejectsUnknownKeysDuplicateKeysDuplicateIDsAndNestedLibraries() passed after 0.001 seconds. +◇ Test decoderBoundsPhysicalLinesBytesJSONDepthAndDirectiveAllocations() started. +✔ Test decoderBoundsPhysicalLinesBytesJSONDepthAndDirectiveAllocations() passed after 0.073 seconds. +◇ Test nativeEncodingSharesTheDecodeLineBudgetSoEveryAcceptedSaveReopens() started. +✔ Test nativeEncodingSharesTheDecodeLineBudgetSoEveryAcceptedSaveReopens() passed after 1.030 seconds. +◇ Test cancellationRejectsEncodingDecodingAndExpansionWithoutPartialOutput() started. +✔ Test cancellationRejectsEncodingDecodingAndExpansionWithoutPartialOutput() passed after 0.001 seconds. +✔ Suite SculptureCompositionTests passed after 3.308 seconds. +◇ Test exampleCatalogOffersDistinctSculpturesAndSpatialMaps() started. +✔ Test exampleCatalogOffersDistinctSculpturesAndSpatialMaps() passed after 0.039 seconds. +◇ Test eachExampleBuiltAloneEqualsTheCatalogElementAndBuildsNothingElse() started. +✔ Test eachExampleBuiltAloneEqualsTheCatalogElementAndBuildsNothingElse() passed after 3.325 seconds. +◇ Test everyExampleOpensThroughTheRealThreeMDCodec(id:) started. +◇ Test case passing 1 argument id → "character-orb" to everyExampleOpensThroughTheRealThreeMDCodec(id:) started. +◇ Test case passing 1 argument id → "woven-torus" to everyExampleOpensThroughTheRealThreeMDCodec(id:) started. +◇ Test case passing 1 argument id → "moon-gate" to everyExampleOpensThroughTheRealThreeMDCodec(id:) started. +◇ Test case passing 1 argument id → "spiral-tower" to everyExampleOpensThroughTheRealThreeMDCodec(id:) started. +◇ Test case passing 1 argument id → "crystal-garden" to everyExampleOpensThroughTheRealThreeMDCodec(id:) started. +◇ Test case passing 1 argument id → "little-rocket" to everyExampleOpensThroughTheRealThreeMDCodec(id:) started. +◇ Test case passing 1 argument id → "pixel-bonsai" to everyExampleOpensThroughTheRealThreeMDCodec(id:) started. +◇ Test case passing 1 argument id → "orbital-rings" to everyExampleOpensThroughTheRealThreeMDCodec(id:) started. +◇ Test case passing 1 argument id → "hill-observatory" to everyExampleOpensThroughTheRealThreeMDCodec(id:) started. +◇ Test case passing 1 argument id → "terraced-island" to everyExampleOpensThroughTheRealThreeMDCodec(id:) started. +◇ Test case passing 1 argument id → "canal-city" to everyExampleOpensThroughTheRealThreeMDCodec(id:) started. +◇ Test case passing 1 argument id → "alpine-valley" to everyExampleOpensThroughTheRealThreeMDCodec(id:) started. +◇ Test case passing 1 argument id → "wandering-cartographer" to everyExampleOpensThroughTheRealThreeMDCodec(id:) started. +◇ Test case passing 1 argument id → "clockwork-dragon" to everyExampleOpensThroughTheRealThreeMDCodec(id:) started. +◇ Test case passing 1 argument id → "woodland-fox" to everyExampleOpensThroughTheRealThreeMDCodec(id:) started. +◇ Test case passing 1 argument id → "deep-sea-whale" to everyExampleOpensThroughTheRealThreeMDCodec(id:) started. +◇ Test case passing 1 argument id → "citadel-of-arches" to everyExampleOpensThroughTheRealThreeMDCodec(id:) started. +◇ Test case passing 1 argument id → "sky-island-village" to everyExampleOpensThroughTheRealThreeMDCodec(id:) started. +◇ Test case passing 1 argument id → "canyon-waterfall" to everyExampleOpensThroughTheRealThreeMDCodec(id:) started. +◇ Test case passing 1 argument id → "moonlit-harbor" to everyExampleOpensThroughTheRealThreeMDCodec(id:) started. +◇ Test case passing 1 argument id → "grand-solar-system" to everyExampleOpensThroughTheRealThreeMDCodec(id:) started. +✔ Test everyExampleOpensThroughTheRealThreeMDCodec(id:) with 21 test cases passed after 3.964 seconds. +◇ Test shippedThreeMDExamplesMatchTheEditableCatalog(id:) started. +◇ Test case passing 1 argument id → "character-orb" to shippedThreeMDExamplesMatchTheEditableCatalog(id:) started. +◇ Test case passing 1 argument id → "woven-torus" to shippedThreeMDExamplesMatchTheEditableCatalog(id:) started. +◇ Test case passing 1 argument id → "moon-gate" to shippedThreeMDExamplesMatchTheEditableCatalog(id:) started. +◇ Test case passing 1 argument id → "spiral-tower" to shippedThreeMDExamplesMatchTheEditableCatalog(id:) started. +◇ Test case passing 1 argument id → "crystal-garden" to shippedThreeMDExamplesMatchTheEditableCatalog(id:) started. +◇ Test case passing 1 argument id → "little-rocket" to shippedThreeMDExamplesMatchTheEditableCatalog(id:) started. +◇ Test case passing 1 argument id → "pixel-bonsai" to shippedThreeMDExamplesMatchTheEditableCatalog(id:) started. +◇ Test case passing 1 argument id → "orbital-rings" to shippedThreeMDExamplesMatchTheEditableCatalog(id:) started. +◇ Test case passing 1 argument id → "hill-observatory" to shippedThreeMDExamplesMatchTheEditableCatalog(id:) started. +◇ Test case passing 1 argument id → "terraced-island" to shippedThreeMDExamplesMatchTheEditableCatalog(id:) started. +◇ Test case passing 1 argument id → "canal-city" to shippedThreeMDExamplesMatchTheEditableCatalog(id:) started. +◇ Test case passing 1 argument id → "alpine-valley" to shippedThreeMDExamplesMatchTheEditableCatalog(id:) started. +◇ Test case passing 1 argument id → "wandering-cartographer" to shippedThreeMDExamplesMatchTheEditableCatalog(id:) started. +◇ Test case passing 1 argument id → "clockwork-dragon" to shippedThreeMDExamplesMatchTheEditableCatalog(id:) started. +◇ Test case passing 1 argument id → "woodland-fox" to shippedThreeMDExamplesMatchTheEditableCatalog(id:) started. +◇ Test case passing 1 argument id → "deep-sea-whale" to shippedThreeMDExamplesMatchTheEditableCatalog(id:) started. +◇ Test case passing 1 argument id → "citadel-of-arches" to shippedThreeMDExamplesMatchTheEditableCatalog(id:) started. +◇ Test case passing 1 argument id → "sky-island-village" to shippedThreeMDExamplesMatchTheEditableCatalog(id:) started. +◇ Test case passing 1 argument id → "canyon-waterfall" to shippedThreeMDExamplesMatchTheEditableCatalog(id:) started. +◇ Test case passing 1 argument id → "moonlit-harbor" to shippedThreeMDExamplesMatchTheEditableCatalog(id:) started. +◇ Test case passing 1 argument id → "grand-solar-system" to shippedThreeMDExamplesMatchTheEditableCatalog(id:) started. +✔ Test shippedThreeMDExamplesMatchTheEditableCatalog(id:) with 21 test cases passed after 3.363 seconds. +◇ Test exampleShapesKeepTheirCharacteristicOpenSpaces() started. +✔ Test exampleShapesKeepTheirCharacteristicOpenSpaces() passed after 0.001 seconds. +◇ Test mapExamplesHaveElevationAndUseCharacterMaterials() started. +✔ Test mapExamplesHaveElevationAndUseCharacterMaterials() passed after 0.010 seconds. +◇ Suite SculptureGalleryCatalogTests started. +◇ Test listingIsPlainMetadataThatGeneratesNothing() started. +✔ Test listingIsPlainMetadataThatGeneratesNothing() passed after 0.001 seconds. +◇ Test listingRunsNoBuilderOrGenerator() started. +✔ Test listingRunsNoBuilderOrGenerator() passed after 0.001 seconds. +◇ Test openingTheSmallestAuthoredModelBuildsOnlyThatModel() started. +✔ Test openingTheSmallestAuthoredModelBuildsOnlyThatModel() passed after 0.002 seconds. +◇ Test cancellingAtTheStartReachesNoOtherEntrysBuilder() started. +✔ Test cancellingAtTheStartReachesNoOtherEntrysBuilder() passed after 0.001 seconds. +◇ Test voxelMetadataMatchesTheGeneratedCatalogExactly() started. +✔ Test voxelMetadataMatchesTheGeneratedCatalogExactly() passed after 0.001 seconds. +◇ Test mathLadderRunsFromSixteenCellsToTwoHundredFiftySix() started. +✔ Test mathLadderRunsFromSixteenCellsToTwoHundredFiftySix() passed after 0.001 seconds. +◇ Test everyFactoryCreatesItsDeclaredKindExtentAndTitle() started. +✔ Test everyFactoryCreatesItsDeclaredKindExtentAndTitle() passed after 13.474 seconds. +◇ Test factoriesReportProgressFromZeroToOne() started. +✔ Test factoriesReportProgressFromZeroToOne() passed after 0.004 seconds. +◇ Test unlistedOrAlteredEntriesAreRefused() started. +✔ Test unlistedOrAlteredEntriesAreRefused() passed after 0.001 seconds. +◇ Test cancellingAnOpeningEntryPublishesNothing() started. +✔ Test cancellingAnOpeningEntryPublishesNothing() passed after 0.001 seconds. +◇ Test extentsMeasureRotatedPlacementsAndSaturateAtIntMaximum() started. +✔ Test extentsMeasureRotatedPlacementsAndSaturateAtIntMaximum() passed after 0.001 seconds. +✔ Suite SculptureGalleryCatalogTests passed after 13.483 seconds. +◇ Suite SculptureInsertionPlanTests started. +◇ Test naturalFilenameOrderIsDeterministicForAnySelectionOrder() started. +✔ Test naturalFilenameOrderIsDeterministicForAnySelectionOrder() passed after 0.001 seconds. +◇ Test onlyReadableAndCompactFilesAreInsertableInAnyLetterCase() started. +✔ Test onlyReadableAndCompactFilesAreInsertableInAnyLetterCase() passed after 0.001 seconds. +◇ Test countsCellsGlyphsAndModelsAreRefusedBeforeAnyFileIsRead() started. +✔ Test countsCellsGlyphsAndModelsAreRefusedBeforeAnyFileIsRead() passed after 0.001 seconds. +◇ Test worldPlansBoundPlacementsAndHaveNoTileFit() started. +✔ Test worldPlansBoundPlacementsAndHaveNoTileFit() passed after 0.168 seconds. +◇ Test aggregateBytesAreBudgetedAcrossFilesAndRefuseByName() started. +✔ Test aggregateBytesAreBudgetedAcrossFilesAndRefuseByName() passed after 0.001 seconds. +◇ Test decodeNamesTheSourceForWorldsGenericMarkdownAndMalformedInput() started. +✔ Test decodeNamesTheSourceForWorldsGenericMarkdownAndMalformedInput() passed after 0.001 seconds. +◇ Test admittedFilesAreCheckedForFitAndCumulativeModelCountRightAfterTheirOwnDecode() started. +✔ Test admittedFilesAreCheckedForFitAndCumulativeModelCountRightAfterTheirOwnDecode() passed after 0.015 seconds. +◇ Test compactHeaderFitIsRefusedBeforeDecompressionAndOnlyForSupportedHeaders() started. +✔ Test compactHeaderFitIsRefusedBeforeDecompressionAndOnlyForSupportedHeaders() passed after 0.002 seconds. +◇ Test resolvedVolumeIsBudgetedFromTheParentLibraryAndRefusedByNameBeforeDecoding() started. +✔ Test resolvedVolumeIsBudgetedFromTheParentLibraryAndRefusedByNameBeforeDecoding() passed after 0.001 seconds. +◇ Test resolvedVolumeAccumulatesAcrossAdmittedInputsWithoutAnyParent() started. +✔ Test resolvedVolumeAccumulatesAcrossAdmittedInputsWithoutAnyParent() passed after 0.001 seconds. +✔ Suite SculptureInsertionPlanTests passed after 0.192 seconds. +◇ Suite SculptureLinkedBundleTests started. +◇ Test readableAndBinaryBundlesRoundTripWithoutTheProjectFolder() started. +✔ Test readableAndBinaryBundlesRoundTripWithoutTheProjectFolder() passed after 0.064 seconds. +◇ Test aBundleProducedDirectlyByThreeMDResolutionOpensAsAComposition() started. +✔ Test aBundleProducedDirectlyByThreeMDResolutionOpensAsAComposition() passed after 0.026 seconds. +◇ Test sourceFileIsNeverFollowedAndOtherReferenceAttributesAreIgnored() started. +✔ Test sourceFileIsNeverFollowedAndOtherReferenceAttributesAreIgnored() passed after 0.034 seconds. +◇ Test aBundledLinkedEntryMustBeAVersionOneSpaceDocument() started. +✔ Test aBundledLinkedEntryMustBeAVersionOneSpaceDocument() passed after 0.029 seconds. +◇ Test editedBundleScenesSaveAsCompositionsWithoutLinkedMetadata() started. +✔ Test editedBundleScenesSaveAsCompositionsWithoutLinkedMetadata() passed after 0.037 seconds. +✔ Suite SculptureLinkedBundleTests passed after 0.191 seconds. +◇ Suite SculptureLinkedCodecTests started. +◇ Test ledgerIsSingleLineSortedJSONThatRoundTripsQuotesBackslashesAndNFCPaths() started. +✔ Test ledgerIsSingleLineSortedJSONThatRoundTripsQuotesBackslashesAndNFCPaths() passed after 0.001 seconds. +◇ Test ledgerRefusesSpacesPeriodsMultiCharacterKeysAndEmptyPaths() started. +✔ Test ledgerRefusesSpacesPeriodsMultiCharacterKeysAndEmptyPaths() passed after 0.001 seconds. +◇ Test linkedRootRoundTripsExactlyWithTurnsAndFenceLikeRows() started. +✔ Test linkedRootRoundTripsExactlyWithTurnsAndFenceLikeRows() passed after 0.001 seconds. +◇ Test everyPlacedByteMustBeLinkedAndLinkCharactersExcludeSpacesAndPeriods() started. +✔ Test everyPlacedByteMustBeLinkedAndLinkCharactersExcludeSpacesAndPeriods() passed after 0.001 seconds. +◇ Test decodingRequiresExactMetadataATitleAndNoPreamble() started. +✔ Test decodingRequiresExactMetadataATitleAndNoPreamble() passed after 0.104 seconds. +◇ Test sceneReaderAsksForAProjectFolderAfterExistingKindsAndRefusesBinaryRootsByName() started. +✔ Test sceneReaderAsksForAProjectFolderAfterExistingKindsAndRefusesBinaryRootsByName() passed after 0.001 seconds. +◇ Test detectionScansTheWholeFrontmatterBeyondTheExistingPrefixWindow() started. +✔ Test detectionScansTheWholeFrontmatterBeyondTheExistingPrefixWindow() passed after 0.054 seconds. +◇ Test linkedErrorMessagesNameProjectPathsAndLimits() started. +✔ Test linkedErrorMessagesNameProjectPathsAndLimits() passed after 0.001 seconds. +◇ Test existingKindsKeepTheirDetectionAndMessages() started. +✔ Test existingKindsKeepTheirDetectionAndMessages() passed after 0.009 seconds. +✔ Suite SculptureLinkedCodecTests passed after 0.173 seconds. +◇ Suite SculptureLinkedResolverTests started. +◇ Test resolvesOnlyReachableFilesIntoACompositionWithPathsAndDigests() started. +✔ Test resolvesOnlyReachableFilesIntoACompositionWithPathsAndDigests() passed after 0.007 seconds. +◇ Test theRootCanBeReadThroughTheSameReader() started. +✔ Test theRootCanBeReadThroughTheSameReader() passed after 0.004 seconds. +◇ Test aSharedChildIsReadOnceAcrossGlyphsAndNestedLinkedRoots() started. +✔ Test aSharedChildIsReadOnceAcrossGlyphsAndNestedLinkedRoots() passed after 0.003 seconds. +◇ Test missingFilesAndReaderFailuresNameTheProjectPath() started. +✔ Test missingFilesAndReaderFailuresNameTheProjectPath() passed after 0.001 seconds. +◇ Test cyclesAreReportedAsChainsOfProjectPaths() started. +✔ Test cyclesAreReportedAsChainsOfProjectPaths() passed after 0.001 seconds. +◇ Test invalidAndEscapingPathsAreRefusedNamingTheLinkingFile() started. +✔ Test invalidAndEscapingPathsAreRefusedNamingTheLinkingFile() passed after 0.003 seconds. +◇ Test aRootInsideTheProjectWhosePathCannotBeRepresentedIsNamedNotCalledOutside() started. +✔ Test aRootInsideTheProjectWhosePathCannotBeRepresentedIsNamedNotCalledOutside() passed after 0.001 seconds. +◇ Test nestedLinkOccurrencesBeyondThreeMDsLimitNameTheRootWithoutPortableSaveAdvice() started. +✔ Test nestedLinkOccurrencesBeyondThreeMDsLimitNameTheRootWithoutPortableSaveAdvice() passed after 0.009 seconds. +◇ Test eachUnsupportedChildKindIsRefusedByNameAndContent() started. +✔ Test eachUnsupportedChildKindIsRefusedByNameAndContent() passed after 0.014 seconds. +◇ Test rootsThatAreNotReadableLinkedCompositionsAreRefusedByName() started. +✔ Test rootsThatAreNotReadableLinkedCompositionsAreRefusedByName() passed after 0.001 seconds. +◇ Test malformedChildrenAndOversizedModelsNameTheirFilesWithoutBundleIDs() started. +✔ Test malformedChildrenAndOversizedModelsNameTheirFilesWithoutBundleIDs() passed after 0.003 seconds. +◇ Test fileCountCapHoldsAtSixtyFourAndRefusesTheNextFile() started. +✔ Test fileCountCapHoldsAtSixtyFourAndRefusesTheNextFile() passed after 0.064 seconds. +◇ Test linkCapHoldsAtFiveHundredTwelveLedgerEntries() started. +✔ Test linkCapHoldsAtFiveHundredTwelveLedgerEntries() passed after 0.083 seconds. +◇ Test depthCapHoldsAtSixteenFilesOnOnePath() started. +✔ Test depthCapHoldsAtSixteenFilesOnOnePath() passed after 0.024 seconds. +◇ Test depthCapCountsAnAlreadyResolvedSubtreeReachedLater() started. +✔ Test depthCapCountsAnAlreadyResolvedSubtreeReachedLater() passed after 0.006 seconds. +◇ Test pathAndComponentCapsHoldAtTheirLimits() started. +✔ Test pathAndComponentCapsHoldAtTheirLimits() passed after 0.013 seconds. +◇ Test definitionByteBudgetHoldsAtItsLimitAndBoundsEachRead() started. +✔ Test definitionByteBudgetHoldsAtItsLimitAndBoundsEachRead() passed after 0.002 seconds. +◇ Test rawLedgerCapHoldsAtOneHundredTwentyEightKiB() started. +✔ Test rawLedgerCapHoldsAtOneHundredTwentyEightKiB() passed after 0.882 seconds. +◇ Test cancellationIsHonoredBetweenFiles() started. +✔ Test cancellationIsHonoredBetweenFiles() passed after 0.001 seconds. +◇ Test linksAreNormalizedToNFCBeforeReading() started. +✔ Test linksAreNormalizedToNFCBeforeReading() passed after 0.002 seconds. +✔ Suite SculptureLinkedResolverTests passed after 1.131 seconds. +◇ Suite SculptureMathExamplesTests started. +◇ Test smallRungsHaveExactSizesAndRepeatTheSameBytes() started. +✔ Test smallRungsHaveExactSizesAndRepeatTheSameBytes() passed after 1.834 seconds. +◇ Test everyRungHasSensibleOccupancyAndSeveralColors() started. +✔ Test everyRungHasSensibleOccupancyAndSeveralColors() passed after 2.498 seconds. +◇ Test formulasProduceTheirRecognizableShapes() started. +✔ Test formulasProduceTheirRecognizableShapes() passed after 1.113 seconds. +◇ Test terrainSpotChecksMatchItsPublishedHeightfield() started. +✔ Test terrainSpotChecksMatchItsPublishedHeightfield() passed after 1.397 seconds. +◇ Test terrainRepeatsTheSameCellsAndItsPublishedOccupancy() started. +✔ Test terrainRepeatsTheSameCellsAndItsPublishedOccupancy() passed after 7.793 seconds. +◇ Test publishedFormulasStateTheirCentersAndReproduceTheOccupiedCells() started. +✔ Test publishedFormulasStateTheirCentersAndReproduceTheOccupiedCells() passed after 1.324 seconds. +◇ Test generationReportsIncreasingProgressEndingAtOne() started. +✔ Test generationReportsIncreasingProgressEndingAtOne() passed after 0.010 seconds. +◇ Test cancelledTasksThrowBeforeGenerating() started. +✔ Test cancelledTasksThrowBeforeGenerating() passed after 0.001 seconds. +◇ Test cancellingDuringGenerationStopsAtTheNextLayer() started. +✔ Test cancellingDuringGenerationStopsAtTheNextLayer() passed after 0.010 seconds. +✔ Suite SculptureMathExamplesTests passed after 15.984 seconds. +◇ Suite "Shared model value editing" started. +◇ Test replacementPropagatesThroughRepeatedNestedRotatedReferences() started. +✔ Test replacementPropagatesThroughRepeatedNestedRotatedReferences() passed after 0.001 seconds. +◇ Test staleLeafAndOversizedReplacementAreRejectedWithoutChangingSource() started. +✔ Test staleLeafAndOversizedReplacementAreRejectedWithoutChangingSource() passed after 0.001 seconds. +◇ Test uniquePlacementClonesOneLeafAndPreservesOthersAndTransforms() started. +✔ Test uniquePlacementClonesOneLeafAndPreservesOthersAndTransforms() passed after 0.002 seconds. +◇ Test uniqueRejectsNestedMapsDuplicateInvalidIDsAndLibraryCapacity() started. +✔ Test uniqueRejectsNestedMapsDuplicateInvalidIDsAndLibraryCapacity() passed after 0.001 seconds. +◇ Test cancelledReplacementDoesNotPublish() started. +✔ Test cancelledReplacementDoesNotPublish() passed after 0.001 seconds. +◇ Test uniqueCloneRejectsReadableFileOverflowBeforePublishingLibrary() started. +✔ Test uniqueCloneRejectsReadableFileOverflowBeforePublishingLibrary() passed after 2.385 seconds. +✔ Suite "Shared model value editing" passed after 2.390 seconds. +◇ Suite SculptureSceneInsertionTests started. +◇ Test selectedVoxelGetsABindingAndImmediatePlacementWithoutChangingTheParent() started. +✔ Test selectedVoxelGetsABindingAndImmediatePlacementWithoutChangingTheParent() passed after 0.008 seconds. +◇ Test batchPlacementCrossesRowsAndLayersInSelectionOrder() started. +✔ Test batchPlacementCrossesRowsAndLayersInSelectionOrder() passed after 0.015 seconds. +◇ Test placingOverAnOccupiedCellRetainsItsExistingReusableModelAndBinding() started. +✔ Test placingOverAnOccupiedCellRetainsItsExistingReusableModelAndBinding() passed after 0.014 seconds. +◇ Test nestedGraphsNamespaceCollisionsAndRetainSharedChildrenRotationsAndUnusedModels() started. +✔ Test nestedGraphsNamespaceCollisionsAndRetainSharedChildrenRotationsAndUnusedModels() passed after 0.018 seconds. +◇ Test repeatedInputKeepsEachImportIndependentButItsInternalSharingIntact() started. +✔ Test repeatedInputKeepsEachImportIndependentButItsInternalSharingIntact() passed after 0.026 seconds. +◇ Test worldBatchUsesExactFocusAndRootWidthsWithoutFlattening() started. +✔ Test worldBatchUsesExactFocusAndRootWidthsWithoutFlattening() passed after 0.036 seconds. +◇ Test worldBatchRefusesCheckedOverflowAndUnsafeOriginsAtomically() started. +✔ Test worldBatchRefusesCheckedOverflowAndUnsafeOriginsAtomically() passed after 0.001 seconds. +◇ Test unsupportedChildrenEmptyBatchesAndMismatchedSnapshotsRefuse() started. +✔ Test unsupportedChildrenEmptyBatchesAndMismatchedSnapshotsRefuse() passed after 0.001 seconds. +◇ Test invalidSelectionInsufficientSpaceAndChildFitCannotPartiallyEdit() started. +✔ Test invalidSelectionInsufficientSpaceAndChildFitCannotPartiallyEdit() passed after 0.001 seconds. +◇ Test completeUnusedModelCountsRemainBoundedBeforeAnyInsertion() started. +✔ Test completeUnusedModelCountsRemainBoundedBeforeAnyInsertion() passed after 0.001 seconds. +◇ Test portableRefusalInsertsNativeValuesWhenNeitherParentNorInputsCarryPortableData() started. +✔ Test portableRefusalInsertsNativeValuesWhenNeitherParentNorInputsCarryPortableData() passed after 14.301 seconds. +◇ Test portableDataOnTheParentOrAnInputRefusesNamingThePortableLimitAndSources() started. +✔ Test portableDataOnTheParentOrAnInputRefusesNamingThePortableLimitAndSources() passed after 12.211 seconds. +◇ Test portableDataOnlyOnAnInputStillYieldsASnapshotAndNoneYieldsNone() started. +✔ Test portableDataOnlyOnAnInputStillYieldsASnapshotAndNoneYieldsNone() passed after 0.042 seconds. +◇ Test nativeCapacityIsCheckedBeforeBlamingThePortableLimit() started. +✔ Test nativeCapacityIsCheckedBeforeBlamingThePortableLimit() passed after 13.182 seconds. +◇ Test nativeVariantsMatchThePortablePlacementWithoutAnySnapshot() started. +✔ Test nativeVariantsMatchThePortablePlacementWithoutAnySnapshot() passed after 0.086 seconds. +◇ Test insertionTargetsDescribeRowMajorTilesAndTheModelsTheyReplace() started. +✔ Test insertionTargetsDescribeRowMajorTilesAndTheModelsTheyReplace() passed after 0.001 seconds. +◇ Test insertionRefusesNativeGraphsThatWouldNotReopenAndLeavesTheParentIntact() started. +✔ Test insertionRefusesNativeGraphsThatWouldNotReopenAndLeavesTheParentIntact() passed after 9.308 seconds. +◇ Test exhaustedBindingCharactersRefuseWithoutRemovingExistingBindings() started. +✔ Test exhaustedBindingCharactersRefuseWithoutRemovingExistingBindings() passed after 0.001 seconds. +◇ Test parentAndImportedOpaqueDocumentsAndScopedIdentitiesSurviveNamespaceInsertion() started. +✔ Test parentAndImportedOpaqueDocumentsAndScopedIdentitiesSurviveNamespaceInsertion() passed after 0.048 seconds. +◇ Test authoredLeafAndTilePlaneOrderSurvivesInsertionAndPortableReopen() started. +✔ Test authoredLeafAndTilePlaneOrderSurvivesInsertionAndPortableReopen() passed after 0.075 seconds. +◇ Test recaptureKeepsSurvivingAuthoredOrderAndAppendsNewSlicesByZ() started. +✔ Test recaptureKeepsSurvivingAuthoredOrderAndAppendsNewSlicesByZ() passed after 0.011 seconds. +◇ Test standaloneVoxelMetadataIsCarriedIntoItsImportedDefinition() started. +✔ Test standaloneVoxelMetadataIsCarriedIntoItsImportedDefinition() passed after 0.013 seconds. +◇ Test worldRootAndNestedDocumentMetadataSurvivePlacementChangesAndSharedEditing() started. +✔ Test worldRootAndNestedDocumentMetadataSurvivePlacementChangesAndSharedEditing() passed after 0.052 seconds. +◇ Test recapturePreservesOpaqueMetadataWhileRecognizedGeometryStillChanges() started. +✔ Test recapturePreservesOpaqueMetadataWhileRecognizedGeometryStillChanges() passed after 0.003 seconds. +◇ Test metadataPreservationDoesNotPermitArbitraryMarkdownOrMalformedGeometry() started. +✔ Test metadataPreservationDoesNotPermitArbitraryMarkdownOrMalformedGeometry() passed after 0.001 seconds. +◇ Test portableOpaqueAttributesDoNotHideInvalidIdentitiesOrBindingEdges() started. +✔ Test portableOpaqueAttributesDoNotHideInvalidIdentitiesOrBindingEdges() passed after 0.010 seconds. +◇ Test cancellationReturnsNoPartialInsertionForEitherParentKind() started. +✔ Test cancellationReturnsNoPartialInsertionForEitherParentKind() passed after 0.001 seconds. +✔ Suite SculptureSceneInsertionTests passed after 49.474 seconds. +◇ Test solarSystemExtendsTheGalleryWithoutReplacingExistingExamples() started. +✔ Test solarSystemExtendsTheGalleryWithoutReplacingExistingExamples() passed after 0.001 seconds. +◇ Test solarSystemUsesTheFullEditableVolumeAndRoundTripsThroughThreeMD() started. +✔ Test solarSystemUsesTheFullEditableVolumeAndRoundTripsThroughThreeMD() passed after 5.505 seconds. +◇ Test solarSystemHasEightSolidSeparatedPlanetsWithDistinctSurfaceFeatures() started. +✔ Test solarSystemHasEightSolidSeparatedPlanetsWithDistinctSurfaceFeatures() passed after 0.001 seconds. +◇ Test solarSystemRingsMoonsAndOrbitGuidesRetainRealAirGaps() started. +✔ Test solarSystemRingsMoonsAndOrbitGuidesRetainRealAirGaps() passed after 0.001 seconds. +◇ Test solarSystemHasAsteroidBeltCometAndElevatedStars() started. +✔ Test solarSystemHasAsteroidBeltCometAndElevatedStars() passed after 0.001 seconds. +◇ Test sculptureRoundTripsThroughRealThreeMDParser() started. +✔ Test sculptureRoundTripsThroughRealThreeMDParser() passed after 0.002 seconds. +◇ Test rejectsOversizedAndUnrelatedDocuments() started. +✔ Test rejectsOversizedAndUnrelatedDocuments() passed after 0.001 seconds. +◇ Test fileSizeGuardAcceptsItsExactBoundaryBeforeValidatingUTF8() started. +✔ Test fileSizeGuardAcceptsItsExactBoundaryBeforeValidatingUTF8() passed after 0.001 seconds. +◇ Test refusesMalformedDimensionsRowsGlyphsAndDepth() started. +✔ Test refusesMalformedDimensionsRowsGlyphsAndDepth() passed after 0.001 seconds. +◇ Test protectsGridBoundsAndRejectsInvalidGlyphs() started. +✔ Test protectsGridBoundsAndRejectsInvalidGlyphs() passed after 0.001 seconds. +◇ Test duplicatedLayerIsIndependentAndLastLayerIsProtected() started. +✔ Test duplicatedLayerIsIndependentAndLastLayerIsProtected() passed after 0.001 seconds. +◇ Test quarterTurnMovesCellAndFourTurnsRestoreLayer() started. +✔ Test quarterTurnMovesCellAndFourTurnsRestoreLayer() passed after 0.001 seconds. +◇ Test nearestCellWinsOcclusionAndCanBePicked() started. +✔ Test nearestCellWinsOcclusionAndCanBePicked() passed after 0.001 seconds. +◇ Test cameraOrbitChangesProjectionAndNonFiniteValuesRemainSafe() started. +✔ Test cameraOrbitChangesProjectionAndNonFiniteValuesRemainSafe() passed after 0.001 seconds. +◇ Test emptyProjectionExportsSpacesWithoutInventingCharacters() started. +✔ Test emptyProjectionExportsSpacesWithoutInventingCharacters() passed after 0.001 seconds. +◇ Test titleCannotInjectFrontmatterAndLayerLimitIsEnforced() started. +✔ Test titleCannotInjectFrontmatterAndLayerLimitIsEnforced() passed after 0.001 seconds. +◇ Test maximumTwoHundredFiftySixCubeRoundTripsWithinTwentyMiB() started. +✔ Test maximumTwoHundredFiftySixCubeRoundTripsWithinTwentyMiB() passed after 8.926 seconds. +◇ Test dimensionsAboveTwoHundredFiftySixAreRejectedOnEveryAxis() started. +✔ Test dimensionsAboveTwoHundredFiftySixAreRejectedOnEveryAxis() passed after 0.001 seconds. +◇ Test formerCubeDocumentsRemainCompatible(dimension:) started. +◇ Test case passing 1 argument dimension → 32 to formerCubeDocumentsRemainCompatible(dimension:) started. +◇ Test case passing 1 argument dimension → 64 to formerCubeDocumentsRemainCompatible(dimension:) started. +✔ Test formerCubeDocumentsRemainCompatible(dimension:) with 2 test cases passed after 0.098 seconds. +◇ Test codecRejectsExcessiveDirectivesBeforeAllocatingThreeMDPlanes() started. +✔ Test codecRejectsExcessiveDirectivesBeforeAllocatingThreeMDPlanes() passed after 0.001 seconds. +◇ Test codecRejectsExcessiveBlankLinesBeforeThreeMDAllocatesTheirArray() started. +✔ Test codecRejectsExcessiveBlankLinesBeforeThreeMDAllocatesTheirArray() passed after 0.034 seconds. +◇ Test occupiedCountRemainsAccurateAcrossEveryMutationAndValueCopy() started. +✔ Test occupiedCountRemainsAccurateAcrossEveryMutationAndValueCopy() passed after 0.001 seconds. +◇ Test projectionCanPickTheNearestCellBeyondTheOldDepthLimit() started. +✔ Test projectionCanPickTheNearestCellBeyondTheOldDepthLimit() passed after 0.001 seconds. +◇ Test denseSixtyFourVolumeProjectionStaysBoundedAndPicksActualSourceCells() started. +✔ Test denseSixtyFourVolumeProjectionStaysBoundedAndPicksActualSourceCells() passed after 0.312 seconds. +◇ Test maximumCoordinatesStayEditableAndProjectionCachesFollowLayerChanges() started. +✔ Test maximumCoordinatesStayEditableAndProjectionCachesFollowLayerChanges() passed after 2.102 seconds. +◇ Test cancelledSculptureDecodeDoesNotReturnAPartialVolume() started. +✔ Test cancelledSculptureDecodeDoesNotReturnAPartialVolume() passed after 0.001 seconds. +◇ Test cancelledASCIIProjectionReturnsABoundedEmptyFrameWithoutPartialPicking() started. +✔ Test cancelledASCIIProjectionReturnsABoundedEmptyFrameWithoutPartialPicking() passed after 0.002 seconds. +◇ Suite SculptureThreeMDTests started. +◇ Test unmarkedGeneralBinaryAdoptsPortableMarkerWithoutLosingImportedIDs() started. +✔ Test unmarkedGeneralBinaryAdoptsPortableMarkerWithoutLosingImportedIDs() passed after 0.003 seconds. +◇ Test portableWorldRootNeverOverwritesAUserModelAndRetainsUnusedBindings() started. +✔ Test portableWorldRootNeverOverwritesAUserModelAndRetainsUnusedBindings() passed after 0.015 seconds. +◇ Test maximumWorldPlacementsKeepUniqueGraphReferencesAndExactIDs() started. +✔ Test maximumWorldPlacementsKeepUniqueGraphReferencesAndExactIDs() passed after 26.937 seconds. +◇ Test portableSceneRoundTripsInTextAndUncompressedBinary() started. +✔ Test portableSceneRoundTripsInTextAndUncompressedBinary() passed after 0.052 seconds. +◇ Test legacyFilesAndSaveDefaultsRemainDistinct() started. +✔ Test legacyFilesAndSaveDefaultsRemainDistinct() passed after 0.002 seconds. +◇ Test customPlaneAndReferenceIDsSurviveRecaptureAndSharedEditing() started. +✔ Test customPlaneAndReferenceIDsSurviveRecaptureAndSharedEditing() passed after 0.029 seconds. +◇ Test untitledNestedDefinitionsStayUntitledWhileNewOnesAreTitledByTheirID() started. +✔ Test untitledNestedDefinitionsStayUntitledWhileNewOnesAreTitledByTheirID() passed after 0.023 seconds. +◇ Test preservedReferenceAttributesFollowTheGlyphAndItsTargetNotTheGlyphAlone() started. +✔ Test preservedReferenceAttributesFollowTheGlyphAndItsTargetNotTheGlyphAlone() passed after 0.020 seconds. +◇ Test wholeSceneRevisionRejectsStaleModelEditWithoutPublishingChanges() started. +✔ Test wholeSceneRevisionRejectsStaleModelEditWithoutPublishingChanges() passed after 0.011 seconds. +◇ Test invalidSharedReplacementIsAtomicAndWorldAnchorsStayExact() started. +✔ Test invalidSharedReplacementIsAtomicAndWorldAnchorsStayExact() passed after 0.014 seconds. +◇ Test malformedIdentitiesAndDisagreeingReferencesNeverUseLegacyFallback() started. +✔ Test malformedIdentitiesAndDisagreeingReferencesNeverUseLegacyFallback() passed after 0.009 seconds. +◇ Test largeLegacyLibraryRetainsItsOwnCapacityAndPortableFailureIsExplicit() started. +✔ Test largeLegacyLibraryRetainsItsOwnCapacityAndPortableFailureIsExplicit() passed after 30.431 seconds. +◇ Test cancellationPropagatesThroughAllPublicPortableOperations() started. +✔ Test cancellationPropagatesThroughAllPublicPortableOperations() passed after 0.005 seconds. +✔ Suite SculptureThreeMDTests passed after 57.557 seconds. +◇ Suite SculptureVolumeStudyExamplesTests started. +◇ Test denseEquivalentUsesOneSharedSolidModelToFillExactly1024Cubed() started. +✔ Test denseEquivalentUsesOneSharedSolidModelToFillExactly1024Cubed() passed after 0.110 seconds. +◇ Test landscapeSeparatesItsSparseOccupancyFromItsAddressDomain() started. +✔ Test landscapeSeparatesItsSparseOccupancyFromItsAddressDomain() passed after 0.567 seconds. +◇ Test landscapeContainsNavigableCastlesWaterTerracesAndForestAirGaps() started. +✔ Test landscapeContainsNavigableCastlesWaterTerracesAndForestAirGaps() passed after 0.001 seconds. +◇ Test studyFactoriesAreDeterministicAndPreserveFiniteProductionLimits() started. +✔ Test studyFactoriesAreDeterministicAndPreserveFiniteProductionLimits() passed after 2.064 seconds. +◇ Test studyFactoriesRespectCancelledTasksBeforeConstructingTheirLibraries() started. +✔ Test studyFactoriesRespectCancelledTasksBeforeConstructingTheirLibraries() passed after 0.001 seconds. +✔ Suite SculptureVolumeStudyExamplesTests passed after 2.742 seconds. +◇ Suite SculptureWorldTests started. +◇ Test distantInstancesRemainSparseAndShareOneLibraryModel() started. +✔ Test distantInstancesRemainSparseAndShareOneLibraryModel() passed after 0.001 seconds. +◇ Test exactInt64ExtremesAndAdjacentAnchorsSurviveJSONRoundTrip() started. +✔ Test exactInt64ExtremesAndAdjacentAnchorsSurviveJSONRoundTrip() passed after 0.001 seconds. +◇ Test originHeadroomIDsAndRotationsAreValidatedBeforeWorldConstruction() started. +✔ Test originHeadroomIDsAndRotationsAreValidatedBeforeWorldConstruction() passed after 0.001 seconds. +◇ Test worldsRejectMissingModelsDuplicateInstancesAndInvalidTitles() started. +✔ Test worldsRejectMissingModelsDuplicateInstancesAndInvalidTitles() passed after 0.001 seconds. +◇ Test finitePlacementCapacityDoesNotImposeASpatialExtent() started. +✔ Test finitePlacementCapacityDoesNotImposeASpatialExtent() passed after 3.987 seconds. +◇ Test codecRejectsUnknownDuplicateMetadataAndUnsupportedPlaneOrFences() started. +✔ Test codecRejectsUnknownDuplicateMetadataAndUnsupportedPlaneOrFences() passed after 0.001 seconds. +◇ Test codecRejectsUnknownDuplicateJSONKeysAndInexactCoordinateTypes() started. +✔ Test codecRejectsUnknownDuplicateJSONKeysAndInexactCoordinateTypes() passed after 0.001 seconds. +◇ Test decoderBoundsBytesPhysicalLinesAndJSONNestingBeforeAllocatingModels() started. +✔ Test decoderBoundsBytesPhysicalLinesAndJSONNestingBeforeAllocatingModels() passed after 0.070 seconds. +◇ Test cancellationReturnsNoWorldOrSerializedOutput() started. +✔ Test cancellationReturnsNoWorldOrSerializedOutput() passed after 0.001 seconds. +✔ Suite SculptureWorldTests passed after 4.066 seconds. +◇ Test commandCLIInspectsAndPublishesCanonicalEditsWithMachineReadableResult() started. +✔ Test commandCLIInspectsAndPublishesCanonicalEditsWithMachineReadableResult() passed after 0.005 seconds. +◇ Test failedCLIBatchCreatesNoOutputAndKeepsInputAndCommandBytes() started. +✔ Test failedCLIBatchCreatesNoOutputAndKeepsInputAndCommandBytes() passed after 0.002 seconds. +◇ Test cliRefusesExistingFilesDirectoriesAndDanglingOutputSymlinks() started. +✔ Test cliRefusesExistingFilesDirectoriesAndDanglingOutputSymlinks() passed after 0.008 seconds. +◇ Test cliRefusesNonRegularOversizedAndMalformedInputsBeforePublishing() started. +✔ Test cliRefusesNonRegularOversizedAndMalformedInputsBeforePublishing() passed after 0.012 seconds. +◇ Test commandCLIInspectsAndEditsSliceTwoHundredFiftyFiveBeyondTheOldFileBudget() started. +✔ Test commandCLIInspectsAndEditsSliceTwoHundredFiftyFiveBeyondTheOldFileBudget() passed after 1.456 seconds. +◇ Test commandJSONKeepsItsIndependentTwoHundredFiftySixKiBBoundary() started. +✔ Test commandJSONKeepsItsIndependentTwoHundredFiftySixKiBBoundary() passed after 0.005 seconds. +◇ Test cliWritesChosenTemporaryDirectoryAndDirectoryAliasWithoutReplacingEntries() started. +✔ Test cliWritesChosenTemporaryDirectoryAndDirectoryAliasWithoutReplacingEntries() passed after 0.006 seconds. +◇ Test commandCLIInspectsCompactDocumentsAndAutodetectsBytesWithoutExtensionHints() started. +✔ Test commandCLIInspectsCompactDocumentsAndAutodetectsBytesWithoutExtensionHints() passed after 0.002 seconds. +◇ Test commandCLIStoresCompactEditsFromExplicitOutputExtensionAndPreservesInput() started. +✔ Test commandCLIStoresCompactEditsFromExplicitOutputExtensionAndPreservesInput() passed after 0.004 seconds. +◇ Test commandCLIConvertsBothStorageFormatsWhileApplyingTheSameCommands() started. +✔ Test commandCLIConvertsBothStorageFormatsWhileApplyingTheSameCommands() passed after 0.005 seconds. +◇ Test commandCLIRejectsUnsupportedOutputExtensionsWithoutWritingOrChangingInputs() started. +✔ Test commandCLIRejectsUnsupportedOutputExtensionsWithoutWritingOrChangingInputs() passed after 0.002 seconds. +◇ Test commandCLIReportsTruncatedCompactInputWithoutPublishingEdits() started. +✔ Test commandCLIReportsTruncatedCompactInputWithoutPublishingEdits() passed after 0.001 seconds. +◇ Test compositionCLIEmbedsOneSharedModelAndPlacesRotatedSingleCharacterTilesInThreeAxes() started. +✔ Test compositionCLIEmbedsOneSharedModelAndPlacesRotatedSingleCharacterTilesInThreeAxes() passed after 0.005 seconds. +◇ Test compositionCLIExpandsToBothVoxelFormatsAndRefusesImplicitFlattening() started. +✔ Test compositionCLIExpandsToBothVoxelFormatsAndRefusesImplicitFlattening() passed after 0.010 seconds. +◇ Test compositionCLIImportsNestedGraphsWithoutPrivateIDCollisionsOrExternalDependencies() started. +✔ Test compositionCLIImportsNestedGraphsWithoutPrivateIDCollisionsOrExternalDependencies() passed after 0.008 seconds. +◇ Test compositionCLIRejectsUnknownFieldsInvalidReferencesAndUnusableFilesWithoutPublishing() started. +✔ Test compositionCLIRejectsUnknownFieldsInvalidReferencesAndUnusableFilesWithoutPublishing() passed after 0.015 seconds. +◇ Test compositionCLIRequiresExplicitFormatsAndAtomicallyRefusesExistingEntries() started. +✔ Test compositionCLIRequiresExplicitFormatsAndAtomicallyRefusesExistingEntries() passed after 0.007 seconds. +◇ Suite "Explicit-file insertion commands" started. +◇ Test portableInsertPlacesFilesInRequestOrderAndWritesAReopenableDeterministicOutput() started. +✔ Test portableInsertPlacesFilesInRequestOrderAndWritesAReopenableDeterministicOutput() passed after 0.064 seconds. +◇ Test portableInsertPlacesWorldModelsAtExactInt64FocusStrings() started. +✔ Test portableInsertPlacesWorldModelsAtExactInt64FocusStrings() passed after 0.034 seconds. +◇ Test occupiedTargetsNeedExplicitPermissionAndReportWhatTheyReplace() started. +✔ Test occupiedTargetsNeedExplicitPermissionAndReportWhatTheyReplace() passed after 0.048 seconds. +◇ Test worldAndGenericMarkdownChildrenAreRefusedByNameWithoutWritingAnything() started. +✔ Test worldAndGenericMarkdownChildrenAreRefusedByNameWithoutWritingAnything() passed after 0.018 seconds. +◇ Test staleRevisionsExistingOutputsAndBadExtensionsRefuseWithoutWriting() started. +✔ Test staleRevisionsExistingOutputsAndBadExtensionsRefuseWithoutWriting() passed after 0.020 seconds. +◇ Test requestsAreStrictBoundedAndNameTheirMistakes() started. +✔ Test requestsAreStrictBoundedAndNameTheirMistakes() passed after 0.081 seconds. +◇ Test earlyChecksRefuseByCountCellAndSizeBeforeReadingFiles() started. +✔ Test earlyChecksRefuseByCountCellAndSizeBeforeReadingFiles() passed after 0.030 seconds. +◇ Test symbolicLinkChildrenAreRefusedByName() started. +✔ Test symbolicLinkChildrenAreRefusedByName() passed after 0.011 seconds. +◇ Test referenceInsertWritesANativeReadableCompositionAndWorldAndRefusesStaleStyleFields() started. +✔ Test referenceInsertWritesANativeReadableCompositionAndWorldAndRefusesStaleStyleFields() passed after 0.017 seconds. +◇ Test nativeBudgetRefusesAnInsertionThatWouldNotReopen() started. +✔ Test nativeBudgetRefusesAnInsertionThatWouldNotReopen() passed after 0.659 seconds. +◇ Test portableInsertIntoANativeInputKeepsChildMetadataAndNeverBlamesAnOpenSceneThatHasNone() started. +✔ Test portableInsertIntoANativeInputKeepsChildMetadataAndNeverBlamesAnOpenSceneThatHasNone() passed after 0.046 seconds. +◇ Test aNativeInputTooLargeForAPortableCopyIsRefusedNamingItAndPointingToReferenceInsert() started. +✔ Test aNativeInputTooLargeForAPortableCopyIsRefusedNamingItAndPointingToReferenceInsert() passed after 10.750 seconds. +◇ Test inputAndExpectedSceneFailuresNameTheirFile() started. +✔ Test inputAndExpectedSceneFailuresNameTheirFile() passed after 0.008 seconds. +◇ Test graphLimitsHitAfterReadingNameEveryListedFile() started. +✔ Test graphLimitsHitAfterReadingNameEveryListedFile() passed after 0.008 seconds. +◇ Test theResolvedVolumeBudgetRefusesByNameBeforeAnyHugeFileIsDecoded() started. +✔ Test theResolvedVolumeBudgetRefusesByNameBeforeAnyHugeFileIsDecoded() passed after 0.005 seconds. +◇ Test referenceReceiptNamesChildrenWhosePortableDataWasNotCarried() started. +✔ Test referenceReceiptNamesChildrenWhosePortableDataWasNotCarried() passed after 0.006 seconds. +◇ Test cancellationBeforePublicationLeavesNoFile() started. +✔ Test cancellationBeforePublicationLeavesNoFile() passed after 0.004 seconds. +✔ Suite "Explicit-file insertion commands" passed after 11.819 seconds. +◇ Suite "Linked composition inputs to explicit-file commands" started. +◇ Test everyCommandThatReadsAScenePathRefusesALinkedRootNamingItAndItsProjectFolder() started. +✔ Test everyCommandThatReadsAScenePathRefusesALinkedRootNamingItAndItsProjectFolder() passed after 0.021 seconds. +◇ Test aBinaryLinkedRootIsRefusedByNameWithTheSharedExplanation() started. +✔ Test aBinaryLinkedRootIsRefusedByNameWithTheSharedExplanation() passed after 0.005 seconds. +◇ Test otherInputsKeepTheirExistingRefusals() started. +✔ Test otherInputsKeepTheirExistingRefusals() passed after 0.007 seconds. +◇ Test portableInspectionReadsSelfContainedBundlesAsCompositionsWithoutTheProjectFolder() started. +✔ Test portableInspectionReadsSelfContainedBundlesAsCompositionsWithoutTheProjectFolder() passed after 0.055 seconds. +✔ Suite "Linked composition inputs to explicit-file commands" passed after 0.090 seconds. +◇ Suite "Math ladder artifacts" started. +◇ Test manifestListsTheLadderInOrderWithCatalogFacts() started. +✔ Test manifestListsTheLadderInOrderWithCatalogFacts() passed after 0.001 seconds. +◇ Test committedFilesMatchTheManifestAndOmitTheLargestEntries() started. +✔ Test committedFilesMatchTheManifestAndOmitTheLargestEntries() passed after 0.004 seconds. +◇ Test regeneratedModelArtifactsMatchTheCommittedFiles(_:) started. +◇ Test case passing 1 argument model → .ripple to regeneratedModelArtifactsMatchTheCommittedFiles(_:) started. +◇ Test case passing 1 argument model → .torus to regeneratedModelArtifactsMatchTheCommittedFiles(_:) started. +◇ Test case passing 1 argument model → .gyroid to regeneratedModelArtifactsMatchTheCommittedFiles(_:) started. +◇ Test case passing 1 argument model → .harmonicSphere to regeneratedModelArtifactsMatchTheCommittedFiles(_:) started. +✔ Test regeneratedModelArtifactsMatchTheCommittedFiles(_:) with 4 test cases passed after 5.024 seconds. +◇ Test regeneratedTerrainMatchesItsCommittedRecordAndPreview() started. +✔ Test regeneratedTerrainMatchesItsCommittedRecordAndPreview() passed after 22.193 seconds. +◇ Test previewComparisonToleratesAntialiasingButNotChangedContent() started. +✔ Test previewComparisonToleratesAntialiasingButNotChangedContent() passed after 2.439 seconds. +◇ Test directoryListingIgnoresOnlyHiddenEntries() started. +✔ Test directoryListingIgnoresOnlyHiddenEntries() passed after 0.002 seconds. +◇ Test readmeWritesEachUncommittedEntryOutsideTheRepository() started. +✔ Test readmeWritesEachUncommittedEntryOutsideTheRepository() passed after 0.001 seconds. +◇ Test writesModelEntriesAsReadableOrCompactByExtension() started. +✔ Test writesModelEntriesAsReadableOrCompactByExtension() passed after 0.027 seconds. +◇ Test refusesExistingOutputsAndInvalidRequestsWithoutWriting() started. +✔ Test refusesExistingOutputsAndInvalidRequestsWithoutWriting() passed after 0.001 seconds. +◇ Test anOutputCreatedDuringGenerationIsPreserved() started. +✔ Test anOutputCreatedDuringGenerationIsPreserved() passed after 0.026 seconds. +◇ Test cancellationDuringGenerationWritesNothing() started. +✔ Test cancellationDuringGenerationWritesNothing() passed after 0.001 seconds. +✔ Suite "Math ladder artifacts" passed after 29.723 seconds. +◇ Suite "Portable scene development commands" started. +◇ Test exportAcceptsEveryLegacySceneAndPublishesBothPortableFormatsWithoutChangingInput() started. +✔ Test exportAcceptsEveryLegacySceneAndPublishesBothPortableFormatsWithoutChangingInput() passed after 0.054 seconds. +◇ Test inspectReportsStructuredDiagnosticsAndPortableSceneFacts() started. +✔ Test inspectReportsStructuredDiagnosticsAndPortableSceneFacts() passed after 0.012 seconds. +◇ Test applyUsesExactExpectedRevisionPreservesReferencesAndIsDeterministic() started. +✔ Test applyUsesExactExpectedRevisionPreservesReferencesAndIsDeterministic() passed after 0.061 seconds. +◇ Test staleSceneAndFailedCommandBatchNeverCreateOutput() started. +✔ Test staleSceneAndFailedCommandBatchNeverCreateOutput() passed after 0.019 seconds. +◇ Test requestsRejectUnknownDuplicateEquivalentAndOversizedFields() started. +✔ Test requestsRejectUnknownDuplicateEquivalentAndOversizedFields() passed after 0.024 seconds. +◇ Test exportsNeverOverwriteExistingFilesOrSymbolicLinksAndRejectUnknownExtensions() started. +✔ Test exportsNeverOverwriteExistingFilesOrSymbolicLinksAndRejectUnknownExtensions() passed after 0.018 seconds. +◇ Test cancellationBeforePublicationLeavesNoFile() started. +✔ Test cancellationBeforePublicationLeavesNoFile() passed after 0.001 seconds. +✔ Suite "Portable scene development commands" passed after 0.193 seconds. +◇ Test referenceCLIInspectsSharedIDsAndProvidesACompleteExpectedModelSnapshot() started. +✔ Test referenceCLIInspectsSharedIDsAndProvidesACompleteExpectedModelSnapshot() passed after 0.019 seconds. +◇ Test referenceCLIInspectsWorldTransformsWithoutLosingLargeIntegerPrecision() started. +✔ Test referenceCLIInspectsWorldTransformsWithoutLosingLargeIntegerPrecision() passed after 0.009 seconds. +◇ Test referenceCLIUpdatesSharedCompositionLeafAndKeepsNestedBindings() started. +✔ Test referenceCLIUpdatesSharedCompositionLeafAndKeepsNestedBindings() passed after 0.005 seconds. +◇ Test referenceCLIUpdatesWorldLeafWithoutChangingInstancesOrFlatteningTheLibrary() started. +✔ Test referenceCLIUpdatesWorldLeafWithoutChangingInstancesOrFlatteningTheLibrary() passed after 0.005 seconds. +◇ Test referenceCLIMakesOneWorldLeafUniqueThenEditsOnlyItsCopy() started. +✔ Test referenceCLIMakesOneWorldLeafUniqueThenEditsOnlyItsCopy() passed after 0.011 seconds. +◇ Test referenceCLIRejectsStaleModelsEvenWhenDimensionsAndOccupiedCountsMatch() started. +✔ Test referenceCLIRejectsStaleModelsEvenWhenDimensionsAndOccupiedCountsMatch() passed after 0.003 seconds. +◇ Test referenceCLIRequiresCompleteMatchingSourceBytesForUniqueWorldInstances() started. +✔ Test referenceCLIRequiresCompleteMatchingSourceBytesForUniqueWorldInstances() passed after 0.004 seconds. +◇ Test referenceCLIRejectsUnknownInstancesExistingModelIDsAndNestedUniqueness() started. +✔ Test referenceCLIRejectsUnknownInstancesExistingModelIDsAndNestedUniqueness() passed after 0.008 seconds. +◇ Test referenceCLIFailedCommandsLeaveTheSourceAndOutputUntouched() started. +✔ Test referenceCLIFailedCommandsLeaveTheSourceAndOutputUntouched() passed after 0.003 seconds. +◇ Test referenceCLIRefusesTileEditingFlatteningAndAmbiguousRequestFields() started. +✔ Test referenceCLIRefusesTileEditingFlatteningAndAmbiguousRequestFields() passed after 0.006 seconds. +◇ Test referenceCLIRefusesExistingOutputsIncludingSourceDirectoriesAndDanglingLinks() started. +✔ Test referenceCLIRefusesExistingOutputsIncludingSourceDirectoriesAndDanglingLinks() passed after 0.009 seconds. +◇ Test referenceCLIBoundsRequestFilesAndRefusesNonRegularInputs() started. +✔ Test referenceCLIBoundsRequestFilesAndRefusesNonRegularInputs() passed after 0.020 seconds. +◇ Test referenceCLICancellationDoesNotPublishAFile() started. +✔ Test referenceCLICancellationDoesNotPublishAFile() passed after 0.002 seconds. +◇ Suite "Dense volume study reduced fixtures" started. +◇ Test strictCLIRequiresAbsoluteNewOutputAndExplicitDenseOptIn() started. +✔ Test strictCLIRequiresAbsoluteNewOutputAndExplicitDenseOptIn() passed after 0.001 seconds. +◇ Test reducedDenseStudyTouchesHashesStreamsAndComparesEveryByte() started. +✔ Test reducedDenseStudyTouchesHashesStreamsAndComparesEveryByte() passed after 0.002 seconds. +◇ Test resourceGuardRefusesBeforeCreatingOutputAndHonorsKernelProcessLimit() started. +✔ Test resourceGuardRefusesBeforeCreatingOutputAndHonorsKernelProcessLimit() passed after 0.001 seconds. +◇ Test reduced64CubePatternCrossesEachBlockAxisAndHasAnIndependentDigest() started. +✔ Test reduced64CubePatternCrossesEachBlockAxisAndHasAnIndependentDigest() passed after 0.057 seconds. +◇ Test stagingReplacementBeforeEncodingOrPublicationPreservesForeignContent() started. +✔ Test stagingReplacementBeforeEncodingOrPublicationPreservesForeignContent() passed after 0.004 seconds. +◇ Test newOutputGuardPreservesExistingDirectoriesAndSymbolicLinks() started. +✔ Test newOutputGuardPreservesExistingDirectoriesAndSymbolicLinks() passed after 0.001 seconds. +◇ Test streamingVerificationRejectsCorruptionTruncationConcatenationAndLengthMismatch() started. +✔ Test streamingVerificationRejectsCorruptionTruncationConcatenationAndLengthMismatch() passed after 0.305 seconds. +◇ Test cancellationAfterAllocationCleansStagingAndPublishesNothing() started. +✔ Test cancellationAfterAllocationCleansStagingAndPublishesNothing() passed after 0.015 seconds. +✔ Suite "Dense volume study reduced fixtures" passed after 0.388 seconds. +◇ Suite "Volume world study publication" started. +◇ Test rejectsInvalidAndExistingDestinationsWithoutChangingThem() started. +✔ Test rejectsInvalidAndExistingDestinationsWithoutChangingThem() passed after 0.002 seconds. +◇ Test publishesSupportedWorldCopiesWithExactFacts() started. +✔ Test publishesSupportedWorldCopiesWithExactFacts() passed after 33.385 seconds. +◇ Test replacementDirectoryIsNeitherPublishedNorRecursivelyRemoved() started. +✔ Test replacementDirectoryIsNeitherPublishedNorRecursivelyRemoved() passed after 0.002 seconds. +◇ Test exclusiveDirectoryPublicationPreservesARacingExistingTarget() started. +✔ Test exclusiveDirectoryPublicationPreservesARacingExistingTarget() passed after 0.001 seconds. +◇ Test cleanupPreservesAReplacementFileInsideThePinnedStagingDirectory() started. +✔ Test cleanupPreservesAReplacementFileInsideThePinnedStagingDirectory() passed after 0.001 seconds. +◇ Test cancellationAfterCreatingStagingLeavesNoOutputOrTemporaryDirectory() started. +✔ Test cancellationAfterCreatingStagingLeavesNoOutputOrTemporaryDirectory() passed after 0.001 seconds. +✔ Suite "Volume world study publication" passed after 33.394 seconds. +◇ Test sparseWorldCLIInspectKeepsExactCoordinatesAndExtractsOnlyAnExplicitModel() started. +✔ Test sparseWorldCLIInspectKeepsExactCoordinatesAndExtractsOnlyAnExplicitModel() passed after 0.255 seconds. +◇ Test directProcessExecutionDoesNotInterpretArgumentText() started. +✔ Test directProcessExecutionDoesNotInterpretArgumentText() passed after 0.005 seconds. +◇ Test incorrectPinnedVersionStopsBeforeRunningTheTool() started. +✔ Test incorrectPinnedVersionStopsBeforeRunningTheTool() passed after 0.001 seconds. +◇ Test specArgumentsRemainLiteralArgumentsAndFailuresPropagate() started. +failed +✔ Test specArgumentsRemainLiteralArgumentsAndFailuresPropagate() passed after 0.001 seconds. +◇ Test failedReleaseBuildDoesNotScanAnOldExecutable() started. +build failed✔ Test failedReleaseBuildDoesNotScanAnOldExecutable() passed after 0.001 seconds. +◇ Test failedPackagingReleaseBuildDoesNotCopyAnOldExecutableOrReplaceTheBundle() started. +release build failed✔ Test failedPackagingReleaseBuildDoesNotCopyAnOldExecutableOrReplaceTheBundle() passed after 0.004 seconds. +◇ Test sourceScanRejectsNetworkProcessAndCoreBridges() started. +✔ Test sourceScanRejectsNetworkProcessAndCoreBridges() passed after 0.014 seconds. +◇ Test entitlementCheckRequiresExactlyTheSandboxAndUserSelectedKeys() started. +✔ Test entitlementCheckRequiresExactlyTheSandboxAndUserSelectedKeys() passed after 0.006 seconds. +◇ Test boundaryStepRefusesAnAddedEntitlementBeforeRunningAnyTool() started. +✔ Test boundaryStepRefusesAnAddedEntitlementBeforeRunningAnyTool() passed after 0.003 seconds. +◇ Test productSourcesRefuseStoredDefaultsKeysOtherThanAppearance() started. +✔ Test productSourcesRefuseStoredDefaultsKeysOtherThanAppearance() passed after 0.036 seconds. +◇ Test productSourcesRefuseFileWatchersAndSecurityScopedBookmarks() started. +✔ Test productSourcesRefuseFileWatchersAndSecurityScopedBookmarks() passed after 0.019 seconds. +◇ Test currentRepositorySourcesAndEntitlementsPassTheBoundaryScan() started. +✔ Test currentRepositorySourcesAndEntitlementsPassTheBoundaryScan() passed after 0.922 seconds. +◇ Test productDependencyGraphRejectsTransitiveToolingAndUnknownEdges() started. +✔ Test productDependencyGraphRejectsTransitiveToolingAndUnknownEdges() passed after 0.001 seconds. +◇ Test releaseMarkerScanIncludesEmbeddedUnprintableBytes() started. +✔ Test releaseMarkerScanIncludesEmbeddedUnprintableBytes() passed after 0.001 seconds. +◇ Test repositoryInventoryRejectsPythonAndShellProgramsOutsideDependencies() started. +✔ Test repositoryInventoryRejectsPythonAndShellProgramsOutsideDependencies() passed after 0.001 seconds. +◇ Test failedRepositoryInventoryCannotPassSourceBoundaries() started. +git failed✔ Test failedRepositoryInventoryCannotPassSourceBoundaries() passed after 0.003 seconds. +◇ Test signingFailurePreservesTheExistingBundleAndRemovesStaging() started. +signing failed✔ Test signingFailurePreservesTheExistingBundleAndRemovesStaging() passed after 0.007 seconds. +◇ Test successfulPackagingBuildsAndCopiesReleaseBeforeReplacingTheOwnedBundle() started. +release builtsignedverifiedentitlementspackaged /var/folders/5k/616qy7sj28l0d53k4c6w_4x00000gn/T/rook-tooling-test-D34F7460-4CAF-4316-AB6A-49FFAA99664C/dist/Rook.app; local ad-hoc signature, not notarized +✔ Test successfulPackagingBuildsAndCopiesReleaseBeforeReplacingTheOwnedBundle() passed after 0.031 seconds. +◇ Test packagingDoesNotFallBackToDebugWhenReleaseIsMissing() started. +✔ Test packagingDoesNotFallBackToDebugWhenReleaseIsMissing() passed after 0.004 seconds. +◇ Test packagingRefusesUnrelatedBundlesAndSymbolicLinkDestinations() started. +✔ Test packagingRefusesUnrelatedBundlesAndSymbolicLinkDestinations() passed after 0.005 seconds. +◇ Test runnerAcceptsCompleteSwiftChild() started. +✔ Test runnerAcceptsCompleteSwiftChild() passed after 0.451 seconds. +◇ Test runnerRejectsPrematureSwiftChildExitZero() started. +✔ Test runnerRejectsPrematureSwiftChildExitZero() passed after 0.216 seconds. +◇ Test runnerRejectsSwiftChildRecordedIssueAtExitZero() started. +✔ Test runnerRejectsSwiftChildRecordedIssueAtExitZero() passed after 0.226 seconds. +◇ Test runnerPreservesActualSwiftChildExitSeven() started. +✔ Test runnerPreservesActualSwiftChildExitSeven() passed after 0.213 seconds. +◇ Test runnerDoesNotOverwriteRetainedEvidence() started. +✔ Test runnerDoesNotOverwriteRetainedEvidence() passed after 0.001 seconds. +◇ Test completeSwiftTestingRunIsAcceptedWithTypedSummary() started. +✔ Test completeSwiftTestingRunIsAcceptedWithTypedSummary() passed after 0.009 seconds. +◇ Test recordedIssuesAndMissingSummaryAreBothRejected() started. +✔ Test recordedIssuesAndMissingSummaryAreBothRejected() passed after 0.007 seconds. +◇ Test incompleteRunWithoutFailureCannotPass() started. +✔ Test incompleteRunWithoutFailureCannotPass() passed after 0.008 seconds. +◇ Test xctestZeroAloneCannotPass() started. +✔ Test xctestZeroAloneCannotPass() passed after 0.005 seconds. +◇ Test ansiUnicodeAndCIFormattingAreAccepted() started. +✔ Test ansiUnicodeAndCIFormattingAreAccepted() passed after 0.004 seconds. +◇ Test failureWordsInsidePassingTestNamesAreNotIssues() started. +✔ Test failureWordsInsidePassingTestNamesAreNotIssues() passed after 0.008 seconds. +◇ Test upstreamFailureCannotBeHiddenBySuccessfulSummary() started. +✔ Test upstreamFailureCannotBeHiddenBySuccessfulSummary() passed after 0.007 seconds. +◇ Test earlierIssueCannotBeHiddenBySuccessfulSummary() started. +✔ Test earlierIssueCannotBeHiddenBySuccessfulSummary() passed after 0.007 seconds. +◇ Test earlierSummaryCannotHideALaterUnfinishedRun() started. +✔ Test earlierSummaryCannotHideALaterUnfinishedRun() passed after 0.012 seconds. +◇ Test zeroSwiftTestingCountIsRejected() started. +✔ Test zeroSwiftTestingCountIsRejected() passed after 0.003 seconds. +◇ Test explicitExpectedCountIsEnforcedWithoutAProductCountPin() started. +✔ Test explicitExpectedCountIsEnforcedWithoutAProductCountPin() passed after 0.011 seconds. +◇ Test xctestFailureIsRejectedEvenWithSwiftTestingSuccess() started. +✔ Test xctestFailureIsRejectedEvenWithSwiftTestingSuccess() passed after 0.005 seconds. +✔ Test run with 637 tests in 54 suites passed after 515.994 seconds. diff --git a/docs/evidence/viewer-slice/native-parity.log b/docs/evidence/viewer-slice/native-parity.log new file mode 100644 index 00000000..84dfd283 --- /dev/null +++ b/docs/evidence/viewer-slice/native-parity.log @@ -0,0 +1,39 @@ +Building for debugging... +[0/6] Write swift-version--58304C5D6DBC2206.txt +Build complete! (0.16s) +Test Suite 'Selected tests' started at 2026-10-10 11:56:33.902. +Test Suite 'RookPackageTests.xctest' started at 2026-10-10 11:56:33.904. +Test Suite 'RookPackageTests.xctest' passed at 2026-10-10 11:56:33.904. + Executed 0 tests, with 0 failures (0 unexpected) in 0.000 (0.000) seconds +Test Suite 'Selected tests' passed at 2026-10-10 11:56:33.904. + Executed 0 tests, with 0 failures (0 unexpected) in 0.000 (0.002) seconds +◇ Test run started. +↳ Testing Library Version: 1902 +↳ Target Platform: arm64e-apple-macos14.0 +◇ Test browserSliceFixturesMatchNativeWorkspaceToolsAndWholeStrokeHistory() started. +✔ Test browserSliceFixturesMatchNativeWorkspaceToolsAndWholeStrokeHistory() passed after 0.016 seconds. +◇ Suite CameraParityTests started. +◇ Test nativeCameraMatchesSharedBrowserProjectionCases() started. +✔ Test nativeCameraMatchesSharedBrowserProjectionCases() passed after 0.008 seconds. +◇ Test axisRotationsRemainOrthonormalAndInvalidInputsDoNotMoveCamera() started. +✔ Test axisRotationsRemainOrthonormalAndInvalidInputsDoNotMoveCamera() passed after 0.002 seconds. +◇ Test asciiPickingFollowsDocumentZRotation() started. +✔ Test asciiPickingFollowsDocumentZRotation() passed after 0.001 seconds. +◇ Test interactiveFramingPreservesDefaultExportCameraScale() started. +✔ Test interactiveFramingPreservesDefaultExportCameraScale() passed after 0.001 seconds. +◇ Test cameraInputsRemainFiniteAndPanHasTheNativeScreenScale() started. +✔ Test cameraInputsRemainFiniteAndPanHasTheNativeScreenScale() passed after 0.001 seconds. +✔ Suite CameraParityTests passed after 0.012 seconds. +◇ Suite SculptureLiveVoxelTests started. +◇ Test gpuPickingMatchesTheExistingProjectionAtOffCenterPointsAndSeveralPoses() started. +✔ Test gpuPickingMatchesTheExistingProjectionAtOffCenterPointsAndSeveralPoses() passed after 0.064 seconds. +◇ Test gpuPickingChoosesTheNearestCubeOrGhostAndPreservesTheVolumeBoundary() started. +✔ Test gpuPickingChoosesTheNearestCubeOrGhostAndPreservesTheVolumeBoundary() passed after 0.006 seconds. +◇ Test metalSnapshotRendersRealColoredGeometryAndRetainsNativeEvidence() started. +✔ Test metalSnapshotRendersRealColoredGeometryAndRetainsNativeEvidence() passed after 0.198 seconds. +◇ Test cameraResizeUsesTheSameMeshAndMatchesTheReferencePickingScale() started. +✔ Test cameraResizeUsesTheSameMeshAndMatchesTheReferencePickingScale() passed after 0.005 seconds. +◇ Test denseGhostGridKeepsEveryPickTargetAndVisibleCubesWhenGridEdgesAreHidden() started. +✔ Test denseGhostGridKeepsEveryPickTargetAndVisibleCubesWhenGridEdgesAreHidden() passed after 0.166 seconds. +✔ Suite SculptureLiveVoxelTests passed after 0.441 seconds. +✔ Test run with 11 tests in 2 suites passed after 0.470 seconds. diff --git a/docs/evidence/viewer-slice/phone.log b/docs/evidence/viewer-slice/phone.log new file mode 100644 index 00000000..956a7a07 --- /dev/null +++ b/docs/evidence/viewer-slice/phone.log @@ -0,0 +1,53 @@ + +Running 4 tests using 2 workers + +(node:47769) Warning: The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set. +(Use `node --trace-warnings ...` to show where the warning was created) +(node:47770) Warning: The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set. +(Use `node --trace-warnings ...` to show where the warning was created) +[WebServer] ::1 - - [10/Oct/2026 11:55:09] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:55:09] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:55:09] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:55:09] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:55:09] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:55:09] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:55:09] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:55:09] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:55:09] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:55:09] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:55:10] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:55:10] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:55:10] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:55:10] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:55:10] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:55:10] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:55:10] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:55:10] "GET /binary-samples.json HTTP/1.1" 200 - + ✓ 1 [chromium] › viewer.spec.mjs:965:3 › viewer & editor (viewer.html) › phone layout leaves room for cubes and keeps controls outside the drawing (1.2s) + ✓ 2 [chromium] › viewer.spec.mjs:1360:3 › Sculpt Slice parity › phone Slice tools and axis controls stay usable without horizontal page overflow (1.3s) +(node:47783) Warning: The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set. +(Use `node --trace-warnings ...` to show where the warning was created) +(node:47784) Warning: The 'NO_COLOR' env is ignored due to the 'FORCE_COLOR' env being set. +(Use `node --trace-warnings ...` to show where the warning was created) +[WebServer] ::1 - - [10/Oct/2026 11:55:12] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:55:12] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:55:12] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:55:12] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:55:12] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:55:12] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:55:12] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:55:12] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:55:12] "GET /gallery-data.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:55:12] "GET /viewer.html HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:55:12] "GET /assets/tokens.css HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:55:12] "GET /assets/theme.js HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:55:12] "GET /assets/three-md.js?v=1.7.17 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:55:12] "GET /assets/open-document.js?v=3 HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:55:12] "GET /nested-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:55:12] "GET /binary-samples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:55:12] "GET /all-examples.json HTTP/1.1" 200 - +[WebServer] ::1 - - [10/Oct/2026 11:55:12] "GET /gallery-data.json HTTP/1.1" 200 - + ✓ 3 [webkit] › viewer.spec.mjs:965:3 › viewer & editor (viewer.html) › phone layout leaves room for cubes and keeps controls outside the drawing (1.0s) + ✓ 4 [webkit] › viewer.spec.mjs:1360:3 › Sculpt Slice parity › phone Slice tools and axis controls stay usable without horizontal page overflow (1.3s) + + 4 passed (4.0s) diff --git a/docs/evidence/viewer-slice/provenance-implementation.json b/docs/evidence/viewer-slice/provenance-implementation.json new file mode 100644 index 00000000..6990f11f --- /dev/null +++ b/docs/evidence/viewer-slice/provenance-implementation.json @@ -0,0 +1 @@ +{"checkedCommits":1,"passed":false,"violations":[{"commit":"8e9a0c4eecfa50b8918b864b3569c1dec5fde559","detail":"no valid signed attestation","rule":"requireSignature"},{"commit":"8e9a0c4eecfa50b8918b864b3569c1dec5fde559","detail":"reviewer agent:codex is not in the allow-list [\"agent:claude\", \"human:\"]","rule":"allowedReviewers"}]} diff --git a/docs/evidence/viewer-slice/sculpt-axis.png b/docs/evidence/viewer-slice/sculpt-axis.png new file mode 100644 index 00000000..ef4031a2 Binary files /dev/null and b/docs/evidence/viewer-slice/sculpt-axis.png differ diff --git a/docs/evidence/viewer-slice/slice-closure.json b/docs/evidence/viewer-slice/slice-closure.json new file mode 100644 index 00000000..2f0818d6 --- /dev/null +++ b/docs/evidence/viewer-slice/slice-closure.json @@ -0,0 +1,13 @@ +{ + "archived": "/Users/leif/Development/_CorvidLabs/3md-edit-preview/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference", + "contract_digest": "c0b8195b500e020a9703bb7edd72d722e7f379c81edd26658c5b1473356c2d6f", + "finalization_digest": "0caf17781aef4d755beecc9b6930d254942651a5365545cae8df19c5ed4bee94", + "id": "bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference", + "implementation_commit": "6e8d0bb72dec11684d501cf5cbdc25b2f276b853", + "implementation_tree": "87451f2cfbbdf4b72ad4e767612aa45e91478c81", + "lesson_bundle": "/Users/leif/Development/_CorvidLabs/3md-edit-preview/.specsync/archive/changes/2026-10-10-bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference/lesson-bundle.md", + "next_action": "merge the PR on GitHub", + "ready_for_github_merge": true, + "review_digest": "855b061f32615f8397bb99951a89b1b7d0a691fc1508e574abe41b268a242ca6", + "workspace_digest": "fde013fc78a6110e0c0b88de16f5f6e7522e6561a06c0a5c5fd273d884ed5278" +} diff --git a/docs/evidence/viewer-slice/slice-parity.json b/docs/evidence/viewer-slice/slice-parity.json new file mode 100644 index 00000000..0b1aab9d --- /dev/null +++ b/docs/evidence/viewer-slice/slice-parity.json @@ -0,0 +1,330 @@ +{ + "cases": [ + { + "name": "sparse diagonal", + "initial": [ + [ + ".....", + ".....", + ".....", + ".....", + "....." + ] + ], + "tool": "draw", + "glyph": "#", + "size": 1, + "path": [ + [ + 0, + 0 + ], + [ + 4, + 4 + ] + ], + "z": 0, + "expected": [ + [ + "#....", + ".#...", + "..#..", + "...#.", + "....#" + ] + ] + }, + { + "name": "edge clipped brush", + "initial": [ + [ + ".....", + ".....", + "....." + ] + ], + "tool": "draw", + "glyph": "@", + "size": 3, + "path": [ + [ + 0, + 0 + ] + ], + "z": 0, + "expected": [ + [ + "@@...", + "@@...", + "....." + ] + ] + }, + { + "name": "five wide erase", + "initial": [ + [ + "#####", + "#####", + "#####" + ] + ], + "tool": "erase", + "glyph": "#", + "size": 5, + "path": [ + [ + 0, + 0 + ] + ], + "z": 0, + "expected": [ + [ + "...##", + "...##", + "...##" + ] + ] + }, + { + "name": "four neighbor slice fill", + "initial": [ + [ + "..@..", + "..@..", + "..@.." + ], + [ + ".....", + ".....", + "....." + ] + ], + "tool": "fill", + "glyph": "o", + "size": 5, + "path": [ + [ + 0, + 1 + ], + [ + 4, + 1 + ] + ], + "z": 0, + "expected": [ + [ + "oo@..", + "oo@..", + "oo@.." + ], + [ + ".....", + ".....", + "....." + ] + ] + }, + { + "name": "diagonal fill remains disconnected", + "initial": [ + [ + ".#.", + "#.#", + ".#." + ] + ], + "tool": "fill", + "glyph": "*", + "size": 1, + "path": [ + [ + 1, + 1 + ] + ], + "z": 0, + "expected": [ + [ + ".#.", + "#*#", + ".#." + ] + ] + }, + { + "name": "no-op erase", + "initial": [ + [ + "...", + "..." + ] + ], + "tool": "erase", + "glyph": "#", + "size": 3, + "path": [ + [ + 0, + 0 + ], + [ + 2, + 1 + ] + ], + "z": 0, + "expected": [ + [ + "...", + "..." + ] + ] + }, + { + "name": "asymmetric five slice horizontal repeated stroke", + "initial": [ + [ + ".........", + ".........", + ".........", + ".........", + "......@..", + ".........", + "........." + ], + [ + ".........", + ".........", + ".........", + ".........", + ".........", + ".........", + "........." + ], + [ + ".........", + "....#....", + ".........", + ".........", + ".........", + ".........", + "........." + ], + [ + ".........", + ".........", + ".........", + ".........", + ".........", + ".........", + "........." + ], + [ + ".........", + ".........", + ".........", + ".........", + ".........", + "..o......", + "........." + ] + ], + "expected": [ + [ + ".........", + ".........", + ".........", + ".........", + "......@..", + ".........", + "........." + ], + [ + ".........", + ".........", + ".........", + ".........", + ".........", + ".........", + "........." + ], + [ + ".........", + "....#####", + ".........", + ".........", + ".........", + ".........", + "........." + ], + [ + ".........", + ".........", + ".........", + ".........", + ".........", + ".........", + "........." + ], + [ + ".........", + ".........", + ".........", + ".........", + ".........", + "..o......", + "........." + ] + ], + "tool": "draw", + "glyph": "#", + "size": 1, + "path": [ + [ + 4, + 1 + ], + [ + 8, + 1 + ], + [ + 8, + 1 + ] + ], + "z": 2 + }, + { + "name": "no-op fill", + "initial": [ + [ + "###", + "###" + ] + ], + "expected": [ + [ + "###", + "###" + ] + ], + "tool": "fill", + "glyph": "#", + "size": 1, + "path": [ + [ + 1, + 1 + ] + ], + "z": 0 + } + ] +} diff --git a/docs/evidence/viewer-slice/trust-implementation.log b/docs/evidence/viewer-slice/trust-implementation.log new file mode 100644 index 00000000..b2ed0e0c --- /dev/null +++ b/docs/evidence/viewer-slice/trust-implementation.log @@ -0,0 +1,1497 @@ +▶️ Lane: verify — Three language suites, nine-pair public-package interchange, generated bundle drift and editor grammar. Trust runs SpecSync after this lane. + ▶️ Running task: lint + ✔ Step 1 done (576ms) + ▶️ Running task: build +Building for debugging... +[0/5] Write swift-version--58304C5D6DBC2206.txt +Build complete! (0.13s) + ✔ Step 2 done (617ms) + ▶️ Running task: test +[0/1] Planning build +Building for debugging... +[0/6] Write swift-version--58304C5D6DBC2206.txt +Build complete! (0.21s) +Test Suite 'All tests' started at 2026-10-10 11:55:29.448. +Test Suite '3mdPackageTests.xctest' started at 2026-10-10 11:55:29.450. +Test Suite 'CompositionEditingTests' started at 2026-10-10 11:55:29.450. +Test Case '-[ThreeMDTests.CompositionEditingTests testCancelledGraphTransactionPropagatesCancellation]' started. +Test Case '-[ThreeMDTests.CompositionEditingTests testCancelledGraphTransactionPropagatesCancellation]' passed (0.005 seconds). +Test Case '-[ThreeMDTests.CompositionEditingTests testEntryReplacementKeepsIDAndCanEditSharedDefinitionWithoutFlattening]' started. +Test Case '-[ThreeMDTests.CompositionEditingTests testEntryReplacementKeepsIDAndCanEditSharedDefinitionWithoutFlattening]' passed (0.004 seconds). +Test Case '-[ThreeMDTests.CompositionEditingTests testFinalGraphValidationAllowsForwardReferenceInsertionAndRootReplacement]' started. +Test Case '-[ThreeMDTests.CompositionEditingTests testFinalGraphValidationAllowsForwardReferenceInsertionAndRootReplacement]' passed (0.003 seconds). +Test Case '-[ThreeMDTests.CompositionEditingTests testGraphRevisionIncludesReferenceOrderAttributesAndRootAndSurvivesReopen]' started. +Test Case '-[ThreeMDTests.CompositionEditingTests testGraphRevisionIncludesReferenceOrderAttributesAndRootAndSurvivesReopen]' passed (0.008 seconds). +Test Case '-[ThreeMDTests.CompositionEditingTests testGraphSnapshotsAndPatchesAreCodableAndDecodedGraphsStillValidate]' started. +Test Case '-[ThreeMDTests.CompositionEditingTests testGraphSnapshotsAndPatchesAreCodableAndDecodedGraphsStillValidate]' passed (0.003 seconds). +Test Case '-[ThreeMDTests.CompositionEditingTests testGraphTransactionBoundsOperationsPayloadAndDefinitions]' started. +Test Case '-[ThreeMDTests.CompositionEditingTests testGraphTransactionBoundsOperationsPayloadAndDefinitions]' passed (0.002 seconds). +Test Case '-[ThreeMDTests.CompositionEditingTests testMissingTargetAndCycleFailuresHaveGraphPathsWithoutPartialPublication]' started. +Test Case '-[ThreeMDTests.CompositionEditingTests testMissingTargetAndCycleFailuresHaveGraphPathsWithoutPartialPublication]' passed (0.002 seconds). +Test Case '-[ThreeMDTests.CompositionEditingTests testReferenceIdentityCannotChangeOrBeDuplicatedWithinOwner]' started. +Test Case '-[ThreeMDTests.CompositionEditingTests testReferenceIdentityCannotChangeOrBeDuplicatedWithinOwner]' passed (0.003 seconds). +Test Case '-[ThreeMDTests.CompositionEditingTests testReferenceRetargetMoveAndRemoveKeepInstanceIdentityAndOpaqueAttributes]' started. +Test Case '-[ThreeMDTests.CompositionEditingTests testReferenceRetargetMoveAndRemoveKeepInstanceIdentityAndOpaqueAttributes]' passed (0.002 seconds). +Test Case '-[ThreeMDTests.CompositionEditingTests testRemovingAndRewritingReferencesValidatesOnlyCompleteFinalGraph]' started. +Test Case '-[ThreeMDTests.CompositionEditingTests testRemovingAndRewritingReferencesValidatesOnlyCompleteFinalGraph]' passed (0.002 seconds). +Test Suite 'CompositionEditingTests' passed at 2026-10-10 11:55:29.486. + Executed 10 tests, with 0 failures (0 unexpected) in 0.035 (0.036) seconds +Test Suite 'ConformanceTests' started at 2026-10-10 11:55:29.486. +Test Case '-[ThreeMDTests.ConformanceTests testConformanceVectors]' started. +Test Case '-[ThreeMDTests.ConformanceTests testConformanceVectors]' passed (0.010 seconds). +Test Suite 'ConformanceTests' passed at 2026-10-10 11:55:29.496. + Executed 1 test, with 0 failures (0 unexpected) in 0.010 (0.010) seconds +Test Suite 'CrossPlaneLinkHTMLTests' started at 2026-10-10 11:55:29.496. +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testAnchorHrefMatchesSectionId]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testAnchorHrefMatchesSectionId]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testCrossPlaneAnchorDecimalTarget]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testCrossPlaneAnchorDecimalTarget]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testCrossPlaneAnchorDefaultTextIsEscaped]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testCrossPlaneAnchorDefaultTextIsEscaped]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testCrossPlaneAnchorEmptyText]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testCrossPlaneAnchorEmptyText]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testCrossPlaneAnchorNegativeTarget]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testCrossPlaneAnchorNegativeTarget]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testCrossPlaneAnchorNoText]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testCrossPlaneAnchorNoText]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testCrossPlaneAnchorScientificNotation]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testCrossPlaneAnchorScientificNotation]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testCrossPlaneAnchorTextIsEscaped]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testCrossPlaneAnchorTextIsEscaped]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testCrossPlaneAnchorWithText]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testCrossPlaneAnchorWithText]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testHexTargetNotRenderedAsAnchor]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testHexTargetNotRenderedAsAnchor]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testInfTargetNotRenderedAsAnchor]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testInfTargetNotRenderedAsAnchor]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testInvalidTargetNotRenderedAsAnchor]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testInvalidTargetNotRenderedAsAnchor]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testPublicAnchorHelpersMatchRendererIds]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testPublicAnchorHelpersMatchRendererIds]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testSectionHasIdAttribute]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testSectionHasIdAttribute]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testSectionIdForDecimalZ]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testSectionIdForDecimalZ]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testSectionIdForNegativeZ]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testSectionIdForNegativeZ]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testSectionIdPrecedesDataZ]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkHTMLTests testSectionIdPrecedesDataZ]' passed (0.000 seconds). +Test Suite 'CrossPlaneLinkHTMLTests' passed at 2026-10-10 11:55:29.500. + Executed 17 tests, with 0 failures (0 unexpected) in 0.003 (0.004) seconds +Test Suite 'CrossPlaneLinkTests' started at 2026-10-10 11:55:29.500. +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testBasicLinkNoText]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testBasicLinkNoText]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testDanglingLinksFiltersOnlyMissingTargets]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testDanglingLinksFiltersOnlyMissingTargets]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testDanglingLinkTargetExistsFalse]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testDanglingLinkTargetExistsFalse]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testDecimalTarget]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testDecimalTarget]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testDocumentWithNoLinksReturnsEmpty]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testDocumentWithNoLinksReturnsEmpty]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testHexTargetIgnored]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testHexTargetIgnored]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testLinkGraphCollapsesRepeatedEdgesInEncounterOrder]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testLinkGraphCollapsesRepeatedEdgesInEncounterOrder]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testLinkGraphKeepsDanglingEdgeStatus]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testLinkGraphKeepsDanglingEdgeStatus]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testLinksAcrossMultiplePlanesInSourceOrder]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testLinksAcrossMultiplePlanesInSourceOrder]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testLinkWithEmptyText]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testLinkWithEmptyText]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testLinkWithText]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testLinkWithText]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testMultipleLinksLeftToRight]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testMultipleLinksLeftToRight]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testNanTargetIgnored]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testNanTargetIgnored]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testNegativeDecimalTarget]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testNegativeDecimalTarget]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testNonDecimalTargetIgnored]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testNonDecimalTargetIgnored]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testOrdinaryMarkdownLinkNotExtracted]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testOrdinaryMarkdownLinkNotExtracted]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testScientificNotationTarget]' started. +Test Case '-[ThreeMDTests.CrossPlaneLinkTests testScientificNotationTarget]' passed (0.000 seconds). +Test Suite 'CrossPlaneLinkTests' passed at 2026-10-10 11:55:29.504. + Executed 17 tests, with 0 failures (0 unexpected) in 0.003 (0.004) seconds +Test Suite 'DocumentCompositionCodecTests' started at 2026-10-10 11:55:29.504. +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testCanonicalProfileStoresSharedDefinitionOnceAndIsOrderIndependent]' started. +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testCanonicalProfileStoresSharedDefinitionOnceAndIsOrderIndependent]' passed (0.004 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testCheckedInGrovePreservesItsSingleCanopyDefinitionAndBindingAcrossFormats]' started. +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testCheckedInGrovePreservesItsSingleCanopyDefinitionAndBindingAcrossFormats]' passed (0.011 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testJSONAllocationPreflightRejectsExcessiveArraysNestingAndTrailingBytes]' started. +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testJSONAllocationPreflightRejectsExcessiveArraysNestingAndTrailingBytes]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testProfileAndDefinitionBytePoliciesBoundBothReaderAndWriter]' started. +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testProfileAndDefinitionBytePoliciesBoundBothReaderAndWriter]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testProfileUsesGenericPortableBinaryEnvelopeWithoutAnotherFormat]' started. +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testProfileUsesGenericPortableBinaryEnvelopeWithoutAnotherFormat]' passed (0.003 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testReaderRejectsDuplicateDefinitionIDsAndUnusedMissingReferences]' started. +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testReaderRejectsDuplicateDefinitionIDsAndUnusedMissingReferences]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testReaderRejectsDuplicateJSONKeysIncludingEscapedSpelling]' started. +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testReaderRejectsDuplicateJSONKeysIncludingEscapedSpelling]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testReaderRejectsInvalidUnusedDefinitionsAndDoesNotLoadSourcePaths]' started. +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testReaderRejectsInvalidUnusedDefinitionsAndDoesNotLoadSourcePaths]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testReaderRejectsUnknownManifestEntryAndReferenceKeys]' started. +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testReaderRejectsUnknownManifestEntryAndReferenceKeys]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testReaderRequiresExactEnvelopeAndVersionedManifest]' started. +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testReaderRequiresExactEnvelopeAndVersionedManifest]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testReferenceAttributesPreserveControlsQuotesAndUnicodeWithoutBreakingFences]' started. +Test Case '-[ThreeMDTests.DocumentCompositionCodecTests testReferenceAttributesPreserveControlsQuotesAndUnicodeWithoutBreakingFences]' passed (0.001 seconds). +Test Suite 'DocumentCompositionCodecTests' passed at 2026-10-10 11:55:29.530. + Executed 11 tests, with 0 failures (0 unexpected) in 0.025 (0.026) seconds +Test Suite 'DocumentCompositionTests' started at 2026-10-10 11:55:29.530. +Test Case '-[ThreeMDTests.DocumentCompositionTests testCanceledConstructionAndStorageStayDistinctFromValidationErrors]' started. +Test Case '-[ThreeMDTests.DocumentCompositionTests testCanceledConstructionAndStorageStayDistinctFromValidationErrors]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionTests testCyclesAreRejectedInRootAndUnusedNodes]' started. +Test Case '-[ThreeMDTests.DocumentCompositionTests testCyclesAreRejectedInRootAndUnusedNodes]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionTests testDefinitionDepthAndReferenceBudgetsHaveExactBoundarySemantics]' started. +Test Case '-[ThreeMDTests.DocumentCompositionTests testDefinitionDepthAndReferenceBudgetsHaveExactBoundarySemantics]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionTests testDefinitionDocumentPolicyIsIndependentOfCompositionPolicy]' started. +Test Case '-[ThreeMDTests.DocumentCompositionTests testDefinitionDocumentPolicyIsIndependentOfCompositionPolicy]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionTests testEveryDefinitionIsValidatedEvenWhenUnused]' started. +Test Case '-[ThreeMDTests.DocumentCompositionTests testEveryDefinitionIsValidatedEvenWhenUnused]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionTests testIDsAreCaseSensitiveAndNeverFileOrNetworkLocations]' started. +Test Case '-[ThreeMDTests.DocumentCompositionTests testIDsAreCaseSensitiveAndNeverFileOrNetworkLocations]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionTests testMissingRootMissingTargetAndDuplicateDefinitionsAreRejected]' started. +Test Case '-[ThreeMDTests.DocumentCompositionTests testMissingRootMissingTargetAndDuplicateDefinitionsAreRejected]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionTests testOccurrenceBudgetCountsSharedReferencesWithoutMaterializingThem]' started. +Test Case '-[ThreeMDTests.DocumentCompositionTests testOccurrenceBudgetCountsSharedReferencesWithoutMaterializingThem]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionTests testReferenceAttributesAreOpaqueUnicodeDataWithCountAndByteLimits]' started. +Test Case '-[ThreeMDTests.DocumentCompositionTests testReferenceAttributesAreOpaqueUnicodeDataWithCountAndByteLimits]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionTests testResourceLimitsCannotBeRaisedBeyondAbsoluteBounds]' started. +Test Case '-[ThreeMDTests.DocumentCompositionTests testResourceLimitsCannotBeRaisedBeyondAbsoluteBounds]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionTests testSharedNestedDefinitionsPreserveAxesMetadataAndReferenceOrder]' started. +Test Case '-[ThreeMDTests.DocumentCompositionTests testSharedNestedDefinitionsPreserveAxesMetadataAndReferenceOrder]' passed (0.003 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionTests testUniqueSourceByteBudgetCountsEachDefinitionOnce]' started. +Test Case '-[ThreeMDTests.DocumentCompositionTests testUniqueSourceByteBudgetCountsEachDefinitionOnce]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentCompositionTests testUnusedDepthAndOccurrenceBudgetsAreAlsoEnforced]' started. +Test Case '-[ThreeMDTests.DocumentCompositionTests testUnusedDepthAndOccurrenceBudgetsAreAlsoEnforced]' passed (0.000 seconds). +Test Suite 'DocumentCompositionTests' passed at 2026-10-10 11:55:29.542. + Executed 13 tests, with 0 failures (0 unexpected) in 0.010 (0.011) seconds +Test Suite 'DocumentDiagnosticTests' started at 2026-10-10 11:55:29.542. +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testCancellationIsNeverConvertedIntoAValidationDiagnostic]' started. +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testCancellationIsNeverConvertedIntoAValidationDiagnostic]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testCancelledCompositionDiagnosticsDoNotBeginPreflightOrGraphValidation]' started. +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testCancelledCompositionDiagnosticsDoNotBeginPreflightOrGraphValidation]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testCompositionDiagnosticBudgetRejectsBeforeExpensiveGraphSourceValidation]' started. +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testCompositionDiagnosticBudgetRejectsBeforeExpensiveGraphSourceValidation]' passed (0.002 seconds). +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testCompositionDiagnosticPreflightStillEnforcesCheapCountPolicies]' started. +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testCompositionDiagnosticPreflightStillEnforcesCheapCountPolicies]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testCompositionDiagnosticsScopeRepeatedInstanceIDsByOwner]' started. +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testCompositionDiagnosticsScopeRepeatedInstanceIDsByOwner]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testDiagnosticCeilingSignalsUninspectedRemainder]' started. +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testDiagnosticCeilingSignalsUninspectedRemainder]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testDiagnosticInputAndValueByteWorkAreBounded]' started. +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testDiagnosticInputAndValueByteWorkAreBounded]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testHostileLinkPrefixesDoNotTriggerLegacyRegexDuringDiagnostics]' started. +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testHostileLinkPrefixesDoNotTriggerLegacyRegexDuringDiagnostics]' passed (0.016 seconds). +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testSharedDecimalScannerRejectsLongMalformedLinkNumberAndPreservesGrammar]' started. +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testSharedDecimalScannerRejectsLongMalformedLinkNumberAndPreservesGrammar]' passed (0.004 seconds). +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testSourceParseDiagnosticsPreserveRealLineEvidence]' started. +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testSourceParseDiagnosticsPreserveRealLineEvidence]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testValueDiagnosticsHavePlanePathsAndNoInventedLines]' started. +Test Case '-[ThreeMDTests.DocumentDiagnosticTests testValueDiagnosticsHavePlanePathsAndNoInventedLines]' passed (0.000 seconds). +Test Suite 'DocumentDiagnosticTests' passed at 2026-10-10 11:55:29.566. + Executed 11 tests, with 0 failures (0 unexpected) in 0.024 (0.025) seconds +Test Suite 'DocumentEditingTests' started at 2026-10-10 11:55:29.566. +Test Case '-[ThreeMDTests.DocumentEditingTests testAtomicCoordinateSwapRetainsIDsSourceOrderMetadataAndLegacyLinks]' started. +Test Case '-[ThreeMDTests.DocumentEditingTests testAtomicCoordinateSwapRetainsIDsSourceOrderMetadataAndLegacyLinks]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentEditingTests testCancelledTransactionPropagatesCancellation]' started. +Test Case '-[ThreeMDTests.DocumentEditingTests testCancelledTransactionPropagatesCancellation]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentEditingTests testCanonicalReopenHasSameRevisionAndCodableValuesRoundTrip]' started. +Test Case '-[ThreeMDTests.DocumentEditingTests testCanonicalReopenHasSameRevisionAndCodableValuesRoundTrip]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentEditingTests testFailureAfterValidFirstOperationPublishesNothing]' started. +Test Case '-[ThreeMDTests.DocumentEditingTests testFailureAfterValidFirstOperationPublishesNothing]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentEditingTests testFinalCoordinateConflictReturnsPrecisePathAndNoMutation]' started. +Test Case '-[ThreeMDTests.DocumentEditingTests testFinalCoordinateConflictReturnsPrecisePathAndNoMutation]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentEditingTests testInsertMoveRemoveAndHeaderTransactionPreservesUnrelatedPlanes]' started. +Test Case '-[ThreeMDTests.DocumentEditingTests testInsertMoveRemoveAndHeaderTransactionPreservesUnrelatedPlanes]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentEditingTests testInvalidFinalDirectValuesCannotEscapeStorageValidation]' started. +Test Case '-[ThreeMDTests.DocumentEditingTests testInvalidFinalDirectValuesCannotEscapeStorageValidation]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentEditingTests testInvalidInsertMoveAndDuplicateIdentityAreDiagnosed]' started. +Test Case '-[ThreeMDTests.DocumentEditingTests testInvalidInsertMoveAndDuplicateIdentityAreDiagnosed]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentEditingTests testNoIdentityLegacyDocumentRequiresExplicitAdoptionForTargetedEdits]' started. +Test Case '-[ThreeMDTests.DocumentEditingTests testNoIdentityLegacyDocumentRequiresExplicitAdoptionForTargetedEdits]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentEditingTests testOperationOperandAndExpectedRevisionBudgetsAreEnforced]' started. +Test Case '-[ThreeMDTests.DocumentEditingTests testOperationOperandAndExpectedRevisionBudgetsAreEnforced]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentEditingTests testReplacementCannotSilentlyChangeOrDropIdentity]' started. +Test Case '-[ThreeMDTests.DocumentEditingTests testReplacementCannotSilentlyChangeOrDropIdentity]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentEditingTests testSnapshotDecoderRejectsForgedRevision]' started. +Test Case '-[ThreeMDTests.DocumentEditingTests testSnapshotDecoderRejectsForgedRevision]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentEditingTests testStaleExactRevisionRejectsChangedContentAndUnicodeEquivalentBytes]' started. +Test Case '-[ThreeMDTests.DocumentEditingTests testStaleExactRevisionRejectsChangedContentAndUnicodeEquivalentBytes]' passed (0.001 seconds). +Test Suite 'DocumentEditingTests' passed at 2026-10-10 11:55:29.576. + Executed 13 tests, with 0 failures (0 unexpected) in 0.008 (0.009) seconds +Test Suite 'DocumentFileCompositionTests' started at 2026-10-10 11:55:29.576. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testAttributeBoundCountsNormalizedDirectoryPrefixBytes]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testAttributeBoundCountsNormalizedDirectoryPrefixBytes]' passed (0.003 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testBundledTextAndBinaryReopenWithoutSupplyingAnySourceFiles]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testBundledTextAndBinaryReopenWithoutSupplyingAnySourceFiles]' passed (0.005 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testCachedSubtreeIsChargedAtItsDeeperOccurrenceAgainstTheDiscoveryCeiling]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testCachedSubtreeIsChargedAtItsDeeperOccurrenceAgainstTheDiscoveryCeiling]' passed (0.259 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testCancellationDuringARunningFanOutResolutionPublishesNoResult]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testCancellationDuringARunningFanOutResolutionPublishesNoResult]' passed (1.146 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testCancellationStaysDistinctAndNeverReturnsPartialComposition]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testCancellationStaysDistinctAndNeverReturnsPartialComposition]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testCancelledPathResolutionPrecedesOversizedInput]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testCancelledPathResolutionPrecedesOversizedInput]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testChildStorageFailuresKeepOriginalErrorType]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testChildStorageFailuresKeepOriginalErrorType]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testDisconnectedEmbeddedLedgerUsesActualEntryDepthAndRepeatedCachedFiles]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testDisconnectedEmbeddedLedgerUsesActualEntryDepthAndRepeatedCachedFiles]' passed (0.003 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testDiscoveryMissingFilePrecedesUnvalidatedFinalGraphDepth]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testDiscoveryMissingFilePrecedesUnvalidatedFinalGraphDepth]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testDuplicateBasenamesAndUnicodeScalarOrderingRemainDistinct]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testDuplicateBasenamesAndUnicodeScalarOrderingRemainDistinct]' passed (0.003 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testDuplicateNormalizedAndCanonicallyEquivalentSourcesFailBeforeDecode]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testDuplicateNormalizedAndCanonicallyEquivalentSourcesFailBeforeDecode]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testExistingBundleRetainsUnusedEntriesOpaqueAttributesAndIdentitiesAndScansEveryLedger]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testExistingBundleRetainsUnusedEntriesOpaqueAttributesAndIdentitiesAndScansEveryLedger]' passed (0.009 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testExistingEdgesPrecedeLedgerEdgesAndEmbeddedLedgersResolveFromTheirBundleFolder]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testExistingEdgesPrecedeLedgerEdgesAndEmbeddedLedgersResolveFromTheirBundleFolder]' passed (0.003 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testFileCyclesIncludeUnusedEmbeddedEntryLedgers]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testFileCyclesIncludeUnusedEmbeddedEntryLedgers]' passed (0.002 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testFixedFileDiscoverySafetyCeilingRemainsBoundedForDisconnectedEntries]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testFixedFileDiscoverySafetyCeilingRemainsBoundedForDisconnectedEntries]' passed (0.211 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testLedgerEscapesDecodeBeforePathGrammar]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testLedgerEscapesDecodeBeforePathGrammar]' passed (0.003 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testLedgerRejectsDuplicateEscapedKeysAndMalformedValuesAndGlyphs]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testLedgerRejectsDuplicateEscapedKeysAndMalformedValuesAndGlyphs]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testLongDirectoryOwnersResolveRepeatedSourcesOnceAndRefuseOverBoundTargetsAtTheFirstEdge]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testLongDirectoryOwnersResolveRepeatedSourcesOnceAndRefuseOverBoundTargetsAtTheFirstEdge]' passed (1.624 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testLongOwnerPathWithManyReferencesResolvesEveryReferenceInItsDirectory]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testLongOwnerPathWithManyReferencesResolvesEveryReferenceInItsDirectory]' passed (0.109 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testLoweredDefinitionDepthReferenceTraversalAndAttributePoliciesApplyToCompleteGraph]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testLoweredDefinitionDepthReferenceTraversalAndAttributePoliciesApplyToCompleteGraph]' passed (0.004 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testLoweredPolicyChargesOriginalPathBytesBeforePathGrammarAndEncodedBytesBeforeDecoding]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testLoweredPolicyChargesOriginalPathBytesBeforePathGrammarAndEncodedBytesBeforeDecoding]' passed (0.002 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testMissingRootAndLinkedChildReportNormalizedMissingPaths]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testMissingRootAndLinkedChildReportNormalizedMissingPaths]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testNestedParentPathsAndRefreshedChildrenRetainDeterministicIDs]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testNestedParentPathsAndRefreshedChildrenRetainDeterministicIDs]' passed (0.003 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testNestedProfileUsesProfileRecordPolicyWhileOrdinaryAndChildDocumentsKeepTheirOwnPolicy]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testNestedProfileUsesProfileRecordPolicyWhileOrdinaryAndChildDocumentsKeepTheirOwnPolicy]' passed (0.006 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testOnlyReachableSourcesDecode]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testOnlyReachableSourcesDecode]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testOuterRecognitionDoesNotUseCallerPlaneLimitBeforeByteAndLinePolicies]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testOuterRecognitionDoesNotUseCallerPlaneLimitBeforeByteAndLinePolicies]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testOverBoundLedgerEdgeIsRefusedWhileResolvingBeforeLaterRefusals]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testOverBoundLedgerEdgeIsRefusedWhileResolvingBeforeLaterRefusals]' passed (0.002 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testOwnerDirectoryResolutionKeepsParentDotAndGrammarSemantics]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testOwnerDirectoryResolutionKeepsParentDotAndGrammarSemantics]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testPathsNormalizeNFCAndParentsWithoutPercentDecoding]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testPathsNormalizeNFCAndParentsWithoutPercentDecoding]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testReachableEncodedByteAndSuppliedCountAndAggregatePathLimitsFailBeforeIndexingOrPublishing]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testReachableEncodedByteAndSuppliedCountAndAggregatePathLimitsFailBeforeIndexingOrPublishing]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testRefusalsFollowEntryIDThenGlyphDiscoveryOrder]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testRefusalsFollowEntryIDThenGlyphDiscoveryOrder]' passed (0.005 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testRepeatedCachedFilesAreStillCheckedAgainstFinalCompleteEntryDepth]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testRepeatedCachedFilesAreStillCheckedAgainstFinalCompleteEntryDepth]' passed (0.004 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testResolverOutputRebundlesWithOpaqueGlyphAndSourceFileAttributes]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testResolverOutputRebundlesWithOpaqueGlyphAndSourceFileAttributes]' passed (0.004 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testRootAndUnreachableSuppliedPathsUseTheLedgerPathGrammar]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testRootAndUnreachableSuppliedPathsUseTheLedgerPathGrammar]' passed (0.003 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testSelfAndAliasCyclesCompareNormalizedPaths]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testSelfAndAliasCyclesCompareNormalizedPaths]' passed (0.002 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testSimpleRepeatedFilesProduceOneDefinitionAndPreserveOrdinaryDocumentFields]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testSimpleRepeatedFilesProduceOneDefinitionAndPreserveOrdinaryDocumentFields]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testSourceFileAttributeBoundCountsNormalizedUTF8Bytes]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testSourceFileAttributeBoundCountsNormalizedUTF8Bytes]' passed (0.150 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testStandalonePathsAndLedgersPastTheOldRecordSizeAreSaved]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testStandalonePathsAndLedgersPastTheOldRecordSizeAreSaved]' passed (0.973 seconds). +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testTextAndUncompressedBinaryChildrenBundleIdenticallyWithoutExtensionRestrictions]' started. +Test Case '-[ThreeMDTests.DocumentFileCompositionTests testTextAndUncompressedBinaryChildrenBundleIdenticallyWithoutExtensionRestrictions]' passed (0.004 seconds). +Test Suite 'DocumentFileCompositionTests' passed at 2026-10-10 11:55:34.129. + Executed 39 tests, with 0 failures (0 unexpected) in 4.550 (4.553) seconds +Test Suite 'DocumentIdentityTests' started at 2026-10-10 11:55:34.129. +Test Case '-[ThreeMDTests.DocumentIdentityTests testAdoptionPreservesNamespaceMetadataAndDeterministicallySkipsExistingIDs]' started. +Test Case '-[ThreeMDTests.DocumentIdentityTests testAdoptionPreservesNamespaceMetadataAndDeterministicallySkipsExistingIDs]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentIdentityTests testCancelledIdentityAdoptionReturnsCancellation]' started. +Test Case '-[ThreeMDTests.DocumentIdentityTests testCancelledIdentityAdoptionReturnsCancellation]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentIdentityTests testDuplicateReferenceIdentityFailsWithinOwnerOnly]' started. +Test Case '-[ThreeMDTests.DocumentIdentityTests testDuplicateReferenceIdentityFailsWithinOwnerOnly]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentIdentityTests testDuplicatesAreRejectedRatherThanSilentlyRegenerated]' started. +Test Case '-[ThreeMDTests.DocumentIdentityTests testDuplicatesAreRejectedRatherThanSilentlyRegenerated]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentIdentityTests testExplicitIdentitiesRoundTripThroughTextAndBothBinaryBackends]' started. +Test Case '-[ThreeMDTests.DocumentIdentityTests testExplicitIdentitiesRoundTripThroughTextAndBothBinaryBackends]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentIdentityTests testIdentityAdoptionRespectsDocumentAndReferenceAttributeBudgets]' started. +Test Case '-[ThreeMDTests.DocumentIdentityTests testIdentityAdoptionRespectsDocumentAndReferenceAttributeBudgets]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentIdentityTests testRepeatedTargetsGainIndependentOwnerScopedReferenceIDs]' started. +Test Case '-[ThreeMDTests.DocumentIdentityTests testRepeatedTargetsGainIndependentOwnerScopedReferenceIDs]' passed (0.003 seconds). +Test Case '-[ThreeMDTests.DocumentIdentityTests testUnsafeAndEmptyExistingIDsAreRejectedWithExactPaths]' started. +Test Case '-[ThreeMDTests.DocumentIdentityTests testUnsafeAndEmptyExistingIDsAreRejectedWithExactPaths]' passed (0.001 seconds). +Test Suite 'DocumentIdentityTests' passed at 2026-10-10 11:55:34.136. + Executed 8 tests, with 0 failures (0 unexpected) in 0.007 (0.008) seconds +Test Suite 'DocumentStorageBoundsTests' started at 2026-10-10 11:55:34.136. +Test Case '-[ThreeMDTests.DocumentStorageBoundsTests testADocumentPastTheOldCeilingRoundTrips]' started. +Test Case '-[ThreeMDTests.DocumentStorageBoundsTests testADocumentPastTheOldCeilingRoundTrips]' passed (18.970 seconds). +Test Case '-[ThreeMDTests.DocumentStorageBoundsTests testCanceledTasksCannotReturnPartiallyEncodedOrDecodedDocuments]' started. +Test Case '-[ThreeMDTests.DocumentStorageBoundsTests testCanceledTasksCannotReturnPartiallyEncodedOrDecodedDocuments]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentStorageBoundsTests testCombinedScalarAndDirectiveBytesCannotBypassTheOutputBound]' started. +Test Case '-[ThreeMDTests.DocumentStorageBoundsTests testCombinedScalarAndDirectiveBytesCannotBypassTheOutputBound]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentStorageBoundsTests testLimitsArePositiveAndHaveNoAbsoluteCeiling]' started. +Test Case '-[ThreeMDTests.DocumentStorageBoundsTests testLimitsArePositiveAndHaveNoAbsoluteCeiling]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentStorageBoundsTests testPhysicalLinesAreBoundedBeforeParsingEvenForBlankInputs]' started. +Test Case '-[ThreeMDTests.DocumentStorageBoundsTests testPhysicalLinesAreBoundedBeforeParsingEvenForBlankInputs]' passed (0.008 seconds). +Test Case '-[ThreeMDTests.DocumentStorageBoundsTests testPlanePreflightIgnoresDirectivesInsideBothKindsOfFences]' started. +Test Case '-[ThreeMDTests.DocumentStorageBoundsTests testPlanePreflightIgnoresDirectivesInsideBothKindsOfFences]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentStorageBoundsTests testRecordBoundIncludesWholePlaneBodiesAndEscapedScalarLines]' started. +Test Case '-[ThreeMDTests.DocumentStorageBoundsTests testRecordBoundIncludesWholePlaneBodiesAndEscapedScalarLines]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentStorageBoundsTests testTextAndPortableBinaryAcceptExactByteBounds]' started. +Test Case '-[ThreeMDTests.DocumentStorageBoundsTests testTextAndPortableBinaryAcceptExactByteBounds]' passed (0.001 seconds). +Test Suite 'DocumentStorageBoundsTests' passed at 2026-10-10 11:55:53.119. + Executed 8 tests, with 0 failures (0 unexpected) in 18.982 (18.982) seconds +Test Suite 'DocumentStorageCompressionTests' started at 2026-10-10 11:55:53.119. +Test Case '-[ThreeMDTests.DocumentStorageCompressionTests testAppleLZFSECompressionIsDeterministicAndRoundTripsGeneralText]' started. +Test Case '-[ThreeMDTests.DocumentStorageCompressionTests testAppleLZFSECompressionIsDeterministicAndRoundTripsGeneralText]' passed (0.143 seconds). +Test Case '-[ThreeMDTests.DocumentStorageCompressionTests testCanceledCompressionAndDecompressionRemainCancellationErrors]' started. +Test Case '-[ThreeMDTests.DocumentStorageCompressionTests testCanceledCompressionAndDecompressionRemainCancellationErrors]' passed (0.002 seconds). +Test Case '-[ThreeMDTests.DocumentStorageCompressionTests testDeclaredOutputSizeCannotTruncateOrGrowDecompression]' started. +Test Case '-[ThreeMDTests.DocumentStorageCompressionTests testDeclaredOutputSizeCannotTruncateOrGrowDecompression]' passed (0.029 seconds). +Test Case '-[ThreeMDTests.DocumentStorageCompressionTests testEveryTruncationAndMalformedCompressionPayloadFailsWithoutPartialResults]' started. +Test Case '-[ThreeMDTests.DocumentStorageCompressionTests testEveryTruncationAndMalformedCompressionPayloadFailsWithoutPartialResults]' passed (0.002 seconds). +Test Case '-[ThreeMDTests.DocumentStorageCompressionTests testLargeFirstStreamDrainsMultipleChunksBeforeFinalMarkerAndRejectsConcatenation]' started. +Test Case '-[ThreeMDTests.DocumentStorageCompressionTests testLargeFirstStreamDrainsMultipleChunksBeforeFinalMarkerAndRejectsConcatenation]' passed (0.005 seconds). +Test Case '-[ThreeMDTests.DocumentStorageCompressionTests testLZFSERejectsTrailingAndConcatenatedStreamsWithValidChecksums]' started. +Test Case '-[ThreeMDTests.DocumentStorageCompressionTests testLZFSERejectsTrailingAndConcatenatedStreamsWithValidChecksums]' passed (0.000 seconds). +Test Suite 'DocumentStorageCompressionTests' passed at 2026-10-10 11:55:53.300. + Executed 6 tests, with 0 failures (0 unexpected) in 0.181 (0.181) seconds +Test Suite 'DocumentStorageDecimalTests' started at 2026-10-10 11:55:53.300. +Test Case '-[ThreeMDTests.DocumentStorageDecimalTests testCancellationDuringAnInvalidParseRemainsCancellationError]' started. +Test Case '-[ThreeMDTests.DocumentStorageDecimalTests testCancellationDuringAnInvalidParseRemainsCancellationError]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentStorageDecimalTests testLongMalformedDecimalRejectsReadableAndChecksummedBinaryWithoutBacktracking]' started. +Test Case '-[ThreeMDTests.DocumentStorageDecimalTests testLongMalformedDecimalRejectsReadableAndChecksummedBinaryWithoutBacktracking]' passed (0.002 seconds). +Test Suite 'DocumentStorageDecimalTests' passed at 2026-10-10 11:55:53.303. + Executed 2 tests, with 0 failures (0 unexpected) in 0.003 (0.003) seconds +Test Suite 'DocumentStorageStructuredTests' started at 2026-10-10 11:55:53.303. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testAmplifiedQuotedKeysAreRejectedByPhaseLBeforeAnyPhaseQParse]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testAmplifiedQuotedKeysAreRejectedByPhaseLBeforeAnyPhaseQParse]' passed (0.398 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testCanceledTasksReturnNoStructuredDocumentOrBytes]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testCanceledTasksReturnNoStructuredDocumentOrBytes]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testCancellationIsCheckedAtEveryStructuredCheckpoint]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testCancellationIsCheckedAtEveryStructuredCheckpoint]' passed (0.944 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testCanonicallyEquivalentKeysInOnePayloadMapAreInvalidDocuments]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testCanonicallyEquivalentKeysInOnePayloadMapAreInvalidDocuments]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testChecksumSlicingMatchesTheBytewiseDefinitionAtEveryAlignment]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testChecksumSlicingMatchesTheBytewiseDefinitionAtEveryAlignment]' passed (1.697 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testChunkedUTF8ValidationAgreesWithWholeValidationAcrossChunkBoundaries]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testChunkedUTF8ValidationAgreesWithWholeValidationAcrossChunkBoundaries]' passed (0.473 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testConcurrentTasksEncodeAndDecodeIndependently]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testConcurrentTasksEncodeAndDecodeIndependently]' passed (0.020 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testContainerInfoReportsRawHeaderFieldsWithoutValidation]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testContainerInfoReportsRawHeaderFieldsWithoutValidation]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testCountFramingDividesAndPrecedesThePlaneLimitAtTheLargestCounts]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testCountFramingDividesAndPrecedesThePlaneLimitAtTheLargestCounts]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testDecodeAcceptsDataSlicesWithANonzeroStartIndex]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testDecodeAcceptsDataSlicesWithANonzeroStartIndex]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testDecodedLengthBoundPrecedesTheChecksumAndDecompression]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testDecodedLengthBoundPrecedesTheChecksumAndDecompression]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testDecodingPeakMemoryGrowthStaysUnderThreeTimesTheInput]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testDecodingPeakMemoryGrowthStaysUnderThreeTimesTheInput]' passed (30.487 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testEightyEmptyPlanesDecodeUnderAnEncodedLimitTheirTextWouldExceed]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testEightyEmptyPlanesDecodeUnderAnEncodedLimitTheirTextWouldExceed]' passed (0.003 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testEveryGoldenIsByteIdenticalAndDecodesToTheBoundedTextDecode]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testEveryGoldenIsByteIdenticalAndDecodesToTheBoundedTextDecode]' passed (0.076 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testEveryVectorReportsItsCodeUnderItsLimits]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testEveryVectorReportsItsCodeUnderItsLimits]' passed (0.020 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testFrozenWhitespaceSetHoldsExactlyNineteenScalars]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testFrozenWhitespaceSetHoldsExactlyNineteenScalars]' passed (0.270 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testKeysAreOrderedByUTF8BytesWhichIsCodePointOrder]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testKeysAreOrderedByUTF8BytesWhichIsCodePointOrder]' passed (0.007 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testLongAttributeKeysAreComparedWithTheirLowercaseAcrossChunkEdges]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testLongAttributeKeysAreComparedWithTheirLowercaseAcrossChunkEdges]' passed (0.241 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testLZFSEStructuredPayloadsRoundTripAndKeepTheDecodedBound]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testLZFSEStructuredPayloadsRoundTripAndKeepTheDecodedBound]' passed (0.006 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testLZFSEStructuredStreamsMustEndOnceAndMatchTheDeclaredLength]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testLZFSEStructuredStreamsMustEndOnceAndMatchTheDeclaredLength]' passed (0.004 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testMetricsMatchTheTextWriterAtEveryExampleLimitEdge]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testMetricsMatchTheTextWriterAtEveryExampleLimitEdge]' passed (1.261 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testMetricsMatchTheTextWriterAtTheLimitEdgesOfGeneratedDocuments]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testMetricsMatchTheTextWriterAtTheLimitEdgesOfGeneratedDocuments]' passed (10.356 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testMutatedFilesGiveOneTypedOutcomeAndAcceptedOnesAreCanonical]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testMutatedFilesGiveOneTypedOutcomeAndAcceptedOnesAreCanonical]' passed (3.331 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testNumberFormsFollowTheCanonicalTableAndDecodeBitExactly]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testNumberFormsFollowTheCanonicalTableAndDecodeBitExactly]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testNumericPowersSpellAsTheSharedCanonicalNumbersAndRoundTripBitExactly]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testNumericPowersSpellAsTheSharedCanonicalNumbersAndRoundTripBitExactly]' passed (0.183 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testRandomBitPatternsTakeTheirCanonicalFormAndRoundTripBitExactly]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testRandomBitPatternsTakeTheirCanonicalFormAndRoundTripBitExactly]' passed (2.330 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testSegmentRulesAgreeWithTheTextParserOnRandomBodies]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testSegmentRulesAgreeWithTheTextParserOnRandomBodies]' passed (7.871 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testSegmentRulesMatchTheTextRoundTripOnHandCases]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testSegmentRulesMatchTheTextRoundTripOnHandCases]' passed (0.008 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testShortStringsChargeTheCancellationBudgetInEveryPass]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testShortStringsChargeTheCancellationBudgetInEveryPass]' passed (1.817 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testSizeGateHoldsForEveryExampleAndTheCorpus]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testSizeGateHoldsForEveryExampleAndTheCorpus]' passed (0.653 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testTextContainerWriterKeepsTheTwoZeroBytesAndHeaderChecks]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testTextContainerWriterKeepsTheTwoZeroBytesAndHeaderChecks]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testUnicodeSkewVectorsFollowTheRuntimeUnicodeData]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testUnicodeSkewVectorsFollowTheRuntimeUnicodeData]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testUTF8ValidityIsRepairedDecodingThatEqualsTheInputBytes]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testUTF8ValidityIsRepairedDecodingThatEqualsTheInputBytes]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testVarEncodesMinimallyAndDecodesEveryBoundary]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testVarEncodesMinimallyAndDecodesEveryBoundary]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testWorkedExamplesHoldTheBytesAndChecksumsOfTheSpecification]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testWorkedExamplesHoldTheBytesAndChecksumsOfTheSpecification]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testWriterAcceptanceEqualsValidationAndDecodeEqualsTheTextDecode]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testWriterAcceptanceEqualsValidationAndDecodeEqualsTheTextDecode]' passed (3.372 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testWriterCapsTheUncompressedContainerAtTheEncodedLimit]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testWriterCapsTheUncompressedContainerAtTheEncodedLimit]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testWriterOutputDecodesUnderTheSameLimitsToTheNormalizedDocument]' started. +Test Case '-[ThreeMDTests.DocumentStorageStructuredTests testWriterOutputDecodesUnderTheSameLimitsToTheNormalizedDocument]' passed (0.436 seconds). +Test Suite 'DocumentStorageStructuredTests' passed at 2026-10-10 11:56:59.577. + Executed 38 tests, with 0 failures (0 unexpected) in 66.270 (66.274) seconds +Test Suite 'DocumentStorageTests' started at 2026-10-10 11:56:59.577. +Test Case '-[ThreeMDTests.DocumentStorageTests testAllHeaderFieldsAndCorruptionAreChecked]' started. +Test Case '-[ThreeMDTests.DocumentStorageTests testAllHeaderFieldsAndCorruptionAreChecked]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentStorageTests testBinaryDecodeHandlesDataSlices]' started. +Test Case '-[ThreeMDTests.DocumentStorageTests testBinaryDecodeHandlesDataSlices]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentStorageTests testCheckedInCompressedCanopyRoundTripsToItsReadableDocument]' started. +Test Case '-[ThreeMDTests.DocumentStorageTests testCheckedInCompressedCanopyRoundTripsToItsReadableDocument]' passed (0.002 seconds). +Test Case '-[ThreeMDTests.DocumentStorageTests testCheckedInExtensionManifestDescribesTheActualSixArtifacts]' started. +Test Case '-[ThreeMDTests.DocumentStorageTests testCheckedInExtensionManifestDescribesTheActualSixArtifacts]' passed (0.002 seconds). +Test Case '-[ThreeMDTests.DocumentStorageTests testCheckedInPortableCanopyRoundTripsToItsReadableDocument]' started. +Test Case '-[ThreeMDTests.DocumentStorageTests testCheckedInPortableCanopyRoundTripsToItsReadableDocument]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.DocumentStorageTests testContainerPayloadMustBeValidUTF8AndThreeMDText]' started. +Test Case '-[ThreeMDTests.DocumentStorageTests testContainerPayloadMustBeValidUTF8AndThreeMDText]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentStorageTests testDirectDocumentValidationRejectsLossyOrAmbiguousSerialization]' started. +Test Case '-[ThreeMDTests.DocumentStorageTests testDirectDocumentValidationRejectsLossyOrAmbiguousSerialization]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentStorageTests testGeneralDocumentsPreserveUnicodeCustomAxesAndFractionalPositions]' started. +Test Case '-[ThreeMDTests.DocumentStorageTests testGeneralDocumentsPreserveUnicodeCustomAxesAndFractionalPositions]' passed (0.002 seconds). +Test Case '-[ThreeMDTests.DocumentStorageTests testPortableContainerFixedVector]' started. +Test Case '-[ThreeMDTests.DocumentStorageTests testPortableContainerFixedVector]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.DocumentStorageTests testStorageRetainsTextGrammarAndLegacySerializerPreservesLiteralQuotes]' started. +Test Case '-[ThreeMDTests.DocumentStorageTests testStorageRetainsTextGrammarAndLegacySerializerPreservesLiteralQuotes]' passed (0.000 seconds). +Test Suite 'DocumentStorageTests' passed at 2026-10-10 11:56:59.587. + Executed 10 tests, with 0 failures (0 unexpected) in 0.009 (0.010) seconds +Test Suite 'ExtensionConformanceTests' started at 2026-10-10 11:56:59.587. +Test Case '-[ThreeMDTests.ExtensionConformanceTests testCanonicalNumericBitPatternsMatchSharedSwiftFormattingVectors]' started. +Test Case '-[ThreeMDTests.ExtensionConformanceTests testCanonicalNumericBitPatternsMatchSharedSwiftFormattingVectors]' passed (0.007 seconds). +Test Case '-[ThreeMDTests.ExtensionConformanceTests testDocumentEnvelopeAndProfileGoldensMatchExactCanonicalBytes]' started. +Test Case '-[ThreeMDTests.ExtensionConformanceTests testDocumentEnvelopeAndProfileGoldensMatchExactCanonicalBytes]' passed (0.011 seconds). +Test Case '-[ThreeMDTests.ExtensionConformanceTests testSharedBinaryChecksumGoldensRejectCorruption]' started. +Test Case '-[ThreeMDTests.ExtensionConformanceTests testSharedBinaryChecksumGoldensRejectCorruption]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.ExtensionConformanceTests testSharedCompositionTransactionsKeepUnchangedDefinitionsAndRepeatedInstances]' started. +Test Case '-[ThreeMDTests.ExtensionConformanceTests testSharedCompositionTransactionsKeepUnchangedDefinitionsAndRepeatedInstances]' passed (0.011 seconds). +Test Case '-[ThreeMDTests.ExtensionConformanceTests testSharedDocumentTransactionsValidateFinalValuesAtomically]' started. +Test Case '-[ThreeMDTests.ExtensionConformanceTests testSharedDocumentTransactionsValidateFinalValuesAtomically]' passed (0.004 seconds). +Test Case '-[ThreeMDTests.ExtensionConformanceTests testSharedFailedTransactionsHaveStableCodesPathsAndNoPartialPublication]' started. +Test Case '-[ThreeMDTests.ExtensionConformanceTests testSharedFailedTransactionsHaveStableCodesPathsAndNoPartialPublication]' passed (0.008 seconds). +Test Case '-[ThreeMDTests.ExtensionConformanceTests testSharedIdentityAdoptionPreservesOpaqueFieldsAndOwnerScopes]' started. +Test Case '-[ThreeMDTests.ExtensionConformanceTests testSharedIdentityAdoptionPreservesOpaqueFieldsAndOwnerScopes]' passed (0.004 seconds). +Test Case '-[ThreeMDTests.ExtensionConformanceTests testStrictCompositionJSONRejectsCanonicallyEquivalentDuplicateKeys]' started. +Test Case '-[ThreeMDTests.ExtensionConformanceTests testStrictCompositionJSONRejectsCanonicallyEquivalentDuplicateKeys]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.ExtensionConformanceTests testUnicodeKeyOrderingGoldensPreserveOriginalSpellingAndExactBytes]' started. +Test Case '-[ThreeMDTests.ExtensionConformanceTests testUnicodeKeyOrderingGoldensPreserveOriginalSpellingAndExactBytes]' passed (0.002 seconds). +Test Case '-[ThreeMDTests.ExtensionConformanceTests testUnicodeSourceKeyCollisionsKeepFirstSpellingAndLastValue]' started. +Test Case '-[ThreeMDTests.ExtensionConformanceTests testUnicodeSourceKeyCollisionsKeepFirstSpellingAndLastValue]' passed (0.001 seconds). +Test Suite 'ExtensionConformanceTests' passed at 2026-10-10 11:56:59.638. + Executed 10 tests, with 0 failures (0 unexpected) in 0.050 (0.051) seconds +Test Suite 'HTMLRendererTests' started at 2026-10-10 11:56:59.638. +Test Case '-[ThreeMDTests.HTMLRendererTests testAmpersandEscaped]' started. +Test Case '-[ThreeMDTests.HTMLRendererTests testAmpersandEscaped]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.HTMLRendererTests testAxisEmittedInMeta]' started. +Test Case '-[ThreeMDTests.HTMLRendererTests testAxisEmittedInMeta]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.HTMLRendererTests testBodyRenderedAsMarkdown]' started. +Test Case '-[ThreeMDTests.HTMLRendererTests testBodyRenderedAsMarkdown]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.HTMLRendererTests testDecimalZInDataAttribute]' started. +Test Case '-[ThreeMDTests.HTMLRendererTests testDecimalZInDataAttribute]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.HTMLRendererTests testDoubleQuoteEscaped]' started. +Test Case '-[ThreeMDTests.HTMLRendererTests testDoubleQuoteEscaped]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.HTMLRendererTests testLabelRenderedAsHeading]' started. +Test Case '-[ThreeMDTests.HTMLRendererTests testLabelRenderedAsHeading]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.HTMLRendererTests testLabelSpecialCharsEscaped]' started. +Test Case '-[ThreeMDTests.HTMLRendererTests testLabelSpecialCharsEscaped]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.HTMLRendererTests testLessThanEscaped]' started. +Test Case '-[ThreeMDTests.HTMLRendererTests testLessThanEscaped]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.HTMLRendererTests testMissingTitleFallsBackToDefault]' started. +Test Case '-[ThreeMDTests.HTMLRendererTests testMissingTitleFallsBackToDefault]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.HTMLRendererTests testOutputContainsHeadAndBody]' started. +Test Case '-[ThreeMDTests.HTMLRendererTests testOutputContainsHeadAndBody]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.HTMLRendererTests testOutputIsStandaloneHTML]' started. +Test Case '-[ThreeMDTests.HTMLRendererTests testOutputIsStandaloneHTML]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.HTMLRendererTests testPlaneCountMatchesSections]' started. +Test Case '-[ThreeMDTests.HTMLRendererTests testPlaneCountMatchesSections]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.HTMLRendererTests testPreambleRenderedInSection]' started. +Test Case '-[ThreeMDTests.HTMLRendererTests testPreambleRenderedInSection]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.HTMLRendererTests testSectionCarriesAriaLabel]' started. +Test Case '-[ThreeMDTests.HTMLRendererTests testSectionCarriesAriaLabel]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.HTMLRendererTests testSectionCarriesDataZ]' started. +Test Case '-[ThreeMDTests.HTMLRendererTests testSectionCarriesDataZ]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.HTMLRendererTests testSingleQuoteEscaped]' started. +Test Case '-[ThreeMDTests.HTMLRendererTests testSingleQuoteEscaped]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.HTMLRendererTests testTitleEmittedInH1]' started. +Test Case '-[ThreeMDTests.HTMLRendererTests testTitleEmittedInH1]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.HTMLRendererTests testTitleEmittedInTitleElement]' started. +Test Case '-[ThreeMDTests.HTMLRendererTests testTitleEmittedInTitleElement]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.HTMLRendererTests testTitleSpecialCharsEscaped]' started. +Test Case '-[ThreeMDTests.HTMLRendererTests testTitleSpecialCharsEscaped]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.HTMLRendererTests testVersionEmittedInMeta]' started. +Test Case '-[ThreeMDTests.HTMLRendererTests testVersionEmittedInMeta]' passed (0.000 seconds). +Test Suite 'HTMLRendererTests' passed at 2026-10-10 11:56:59.643. + Executed 20 tests, with 0 failures (0 unexpected) in 0.004 (0.005) seconds +Test Suite 'InterchangeConformanceTests' started at 2026-10-10 11:56:59.643. +Test Case '-[ThreeMDTests.InterchangeConformanceTests testAdoptionAndDeterministicDocumentEditsHaveExactRevisionAndRejectReuse]' started. +Test Case '-[ThreeMDTests.InterchangeConformanceTests testAdoptionAndDeterministicDocumentEditsHaveExactRevisionAndRejectReuse]' passed (0.051 seconds). +Test Case '-[ThreeMDTests.InterchangeConformanceTests testASCIIFencePrefixesWithCombiningMarksKeepInnerDirectivesAsBody]' started. +Test Case '-[ThreeMDTests.InterchangeConformanceTests testASCIIFencePrefixesWithCombiningMarksKeepInnerDirectivesAsBody]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.InterchangeConformanceTests testCatalogIncludesEveryDeclaredExtensionSourceAndBinaryGolden]' started. +Test Case '-[ThreeMDTests.InterchangeConformanceTests testCatalogIncludesEveryDeclaredExtensionSourceAndBinaryGolden]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.InterchangeConformanceTests testCatalogRequiresEveryLegacySourceAndHasUniqueCompleteCases]' started. +Test Case '-[ThreeMDTests.InterchangeConformanceTests testCatalogRequiresEveryLegacySourceAndHasUniqueCompleteCases]' passed (0.020 seconds). +Test Case '-[ThreeMDTests.InterchangeConformanceTests testCombiningMarkEscapesChargeExactCanonicalUTF8OutputBytes]' started. +Test Case '-[ThreeMDTests.InterchangeConformanceTests testCombiningMarkEscapesChargeExactCanonicalUTF8OutputBytes]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.InterchangeConformanceTests testEveryInvalidCatalogSourceReportsItsRequiredTypedError]' started. +Test Case '-[ThreeMDTests.InterchangeConformanceTests testEveryInvalidCatalogSourceReportsItsRequiredTypedError]' passed (0.007 seconds). +Test Case '-[ThreeMDTests.InterchangeConformanceTests testEveryValidCatalogSourceAndLegacyOutputPreserveExactCanonicalBytes]' started. +Test Case '-[ThreeMDTests.InterchangeConformanceTests testEveryValidCatalogSourceAndLegacyOutputPreserveExactCanonicalBytes]' passed (0.057 seconds). +Test Case '-[ThreeMDTests.InterchangeConformanceTests testLegacySerializerPreservesRepresentableScalarQuotesAndFoundationEdgeWhitespace]' started. +Test Case '-[ThreeMDTests.InterchangeConformanceTests testLegacySerializerPreservesRepresentableScalarQuotesAndFoundationEdgeWhitespace]' passed (0.003 seconds). +Test Case '-[ThreeMDTests.InterchangeConformanceTests testScalarFieldSeparatorsAndSpaceTokensMatchBoundedPreflight]' started. +Test Case '-[ThreeMDTests.InterchangeConformanceTests testScalarFieldSeparatorsAndSpaceTokensMatchBoundedPreflight]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.InterchangeConformanceTests testScalarQuoteAndEscapeDelimitersPreserveAdjacentCombiningMarks]' started. +Test Case '-[ThreeMDTests.InterchangeConformanceTests testScalarQuoteAndEscapeDelimitersPreserveAdjacentCombiningMarks]' passed (0.002 seconds). +Test Case '-[ThreeMDTests.InterchangeConformanceTests testSharedDAGAndUnusedDefinitionsSurviveAdoptionAndRootReplacement]' started. +Test Case '-[ThreeMDTests.InterchangeConformanceTests testSharedDAGAndUnusedDefinitionsSurviveAdoptionAndRootReplacement]' passed (0.005 seconds). +Test Case '-[ThreeMDTests.InterchangeConformanceTests testStorageRejectsReservedASCIIDelimitersInsideCombiningGraphemes]' started. +Test Case '-[ThreeMDTests.InterchangeConformanceTests testStorageRejectsReservedASCIIDelimitersInsideCombiningGraphemes]' passed (0.000 seconds). +Test Suite 'InterchangeConformanceTests' passed at 2026-10-10 11:56:59.793. + Executed 12 tests, with 0 failures (0 unexpected) in 0.149 (0.150) seconds +Test Suite 'MarkdownRendererTests' started at 2026-10-10 11:56:59.793. +Test Case '-[ThreeMDTests.MarkdownRendererTests testAmpersandInParagraphIsEscaped]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testAmpersandInParagraphIsEscaped]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testBlankLineSeparatesParagraphs]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testBlankLineSeparatesParagraphs]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testBlockquote]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testBlockquote]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testBoldDoubleAsterisk]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testBoldDoubleAsterisk]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testBoldDoubleUnderscore]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testBoldDoubleUnderscore]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testBoldMidSentence]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testBoldMidSentence]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testCheckedTaskItemLowercase]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testCheckedTaskItemLowercase]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testCheckedTaskItemUppercase]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testCheckedTaskItemUppercase]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testDoubleQuoteInParagraphIsEscaped]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testDoubleQuoteInParagraphIsEscaped]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testFencedCodeBlock]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testFencedCodeBlock]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testFencedCodeBlockEscapesHTML]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testFencedCodeBlockEscapesHTML]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testFencedCodeBlockPreservesMarkdownLookingContent]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testFencedCodeBlockPreservesMarkdownLookingContent]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testFencedCodeBlockWithLanguage]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testFencedCodeBlockWithLanguage]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testH1]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testH1]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testH2]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testH2]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testH3]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testH3]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testH4]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testH4]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testH5]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testH5]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testH6]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testH6]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testHeadingFollowedByParagraph]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testHeadingFollowedByParagraph]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testHeadingRequiresSpaceAfterHash]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testHeadingRequiresSpaceAfterHash]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testInlineCode]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testInlineCode]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testInlineCodeDoesNotRenderMarkdown]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testInlineCodeDoesNotRenderMarkdown]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testInlineCodeEscapesHTML]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testInlineCodeEscapesHTML]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testItalicAsterisk]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testItalicAsterisk]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testItalicUnderscore]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testItalicUnderscore]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testLessThanInParagraphIsEscaped]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testLessThanInParagraphIsEscaped]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testLink]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testLink]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testLinkHrefIsEscaped]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testLinkHrefIsEscaped]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testLinkTextIsEscaped]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testLinkTextIsEscaped]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testMultiLineBlockquote]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testMultiLineBlockquote]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testMultiLineParagraphJoinsWithSpace]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testMultiLineParagraphJoinsWithSpace]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testOrderedList]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testOrderedList]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testParagraphWithBoldAndLink]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testParagraphWithBoldAndLink]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testSingleLineParagraph]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testSingleLineParagraph]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testSingleQuoteInParagraphIsEscaped]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testSingleQuoteInParagraphIsEscaped]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testUncheckedTaskItem]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testUncheckedTaskItem]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testUnorderedListAsterisk]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testUnorderedListAsterisk]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.MarkdownRendererTests testUnorderedListDash]' started. +Test Case '-[ThreeMDTests.MarkdownRendererTests testUnorderedListDash]' passed (0.000 seconds). +Test Suite 'MarkdownRendererTests' passed at 2026-10-10 11:56:59.801. + Executed 39 tests, with 0 failures (0 unexpected) in 0.005 (0.008) seconds +Test Suite 'ParseErrorMetadataTests' started at 2026-10-10 11:56:59.801. +Test Case '-[ThreeMDTests.ParseErrorMetadataTests testDuplicatePlaneMetadata]' started. +Test Case '-[ThreeMDTests.ParseErrorMetadataTests testDuplicatePlaneMetadata]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParseErrorMetadataTests testInvalidDirectiveMetadata]' started. +Test Case '-[ThreeMDTests.ParseErrorMetadataTests testInvalidDirectiveMetadata]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParseErrorMetadataTests testMissingVersionCode]' started. +Test Case '-[ThreeMDTests.ParseErrorMetadataTests testMissingVersionCode]' passed (0.000 seconds). +Test Suite 'ParseErrorMetadataTests' passed at 2026-10-10 11:56:59.801. + Executed 3 tests, with 0 failures (0 unexpected) in 0.000 (0.001) seconds +Test Suite 'ParserNumericTests' started at 2026-10-10 11:56:59.801. +Test Case '-[ThreeMDTests.ParserNumericTests testFiniteDecimalGrammarIsPreservedForEveryCoordinate]' started. +Test Case '-[ThreeMDTests.ParserNumericTests testFiniteDecimalGrammarIsPreservedForEveryCoordinate]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.ParserNumericTests testMalformedAndNonfiniteNumbersAreRejectedForEveryCoordinate]' started. +Test Case '-[ThreeMDTests.ParserNumericTests testMalformedAndNonfiniteNumbersAreRejectedForEveryCoordinate]' passed (0.002 seconds). +Test Suite 'ParserNumericTests' passed at 2026-10-10 11:56:59.804. + Executed 2 tests, with 0 failures (0 unexpected) in 0.002 (0.003) seconds +Test Suite 'ParserTests' started at 2026-10-10 11:56:59.804. +Test Case '-[ThreeMDTests.ParserTests testAxisDefaultsToLayer]' started. +Test Case '-[ThreeMDTests.ParserTests testAxisDefaultsToLayer]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testAxisRawValueNormalized]' started. +Test Case '-[ThreeMDTests.ParserTests testAxisRawValueNormalized]' passed (0.001 seconds). +Test Case '-[ThreeMDTests.ParserTests testDecimalZValue]' started. +Test Case '-[ThreeMDTests.ParserTests testDecimalZValue]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testDuplicatePositionThrows]' started. +Test Case '-[ThreeMDTests.ParserTests testDuplicatePositionThrows]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testEmptyDocumentProducesNoPlanes]' started. +Test Case '-[ThreeMDTests.ParserTests testEmptyDocumentProducesNoPlanes]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testFrontmatterIgnoresCommentLines]' started. +Test Case '-[ThreeMDTests.ParserTests testFrontmatterIgnoresCommentLines]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testFrontmatterStripsQuotedValues]' started. +Test Case '-[ThreeMDTests.ParserTests testFrontmatterStripsQuotedValues]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testInvalidDirectiveTokenThrows]' started. +Test Case '-[ThreeMDTests.ParserTests testInvalidDirectiveTokenThrows]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testKnownAxesMatchSpec]' started. +Test Case '-[ThreeMDTests.ParserTests testKnownAxesMatchSpec]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testLeadingBlankLinesBeforeFrontmatter]' started. +Test Case '-[ThreeMDTests.ParserTests testLeadingBlankLinesBeforeFrontmatter]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testMissingFrontmatterThrows]' started. +Test Case '-[ThreeMDTests.ParserTests testMissingFrontmatterThrows]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testMissingPlanePositionThrows]' started. +Test Case '-[ThreeMDTests.ParserTests testMissingPlanePositionThrows]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testMissingVersionThrows]' started. +Test Case '-[ThreeMDTests.ParserTests testMissingVersionThrows]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testNegativeZValue]' started. +Test Case '-[ThreeMDTests.ParserTests testNegativeZValue]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testNonNumericPositionThrows]' started. +Test Case '-[ThreeMDTests.ParserTests testNonNumericPositionThrows]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testNonNumericXThrows]' started. +Test Case '-[ThreeMDTests.ParserTests testNonNumericXThrows]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testNonNumericYThrows]' started. +Test Case '-[ThreeMDTests.ParserTests testNonNumericYThrows]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testParseErrorDescriptions]' started. +Test Case '-[ThreeMDTests.ParserTests testParseErrorDescriptions]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testParsesFrontmatter]' started. +Test Case '-[ThreeMDTests.ParserTests testParsesFrontmatter]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testParsesMultiplePlanes]' started. +Test Case '-[ThreeMDTests.ParserTests testParsesMultiplePlanes]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testParsesPlaneCoordinatesAndAttributes]' started. +Test Case '-[ThreeMDTests.ParserTests testParsesPlaneCoordinatesAndAttributes]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testPlainMarkdownBecomesSinglePlane]' started. +Test Case '-[ThreeMDTests.ParserTests testPlainMarkdownBecomesSinglePlane]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testPlaneAtZReturnsNilForMissingPosition]' started. +Test Case '-[ThreeMDTests.ParserTests testPlaneAtZReturnsNilForMissingPosition]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testPlaneBodyTrimsLeadingAndTrailingBlanks]' started. +Test Case '-[ThreeMDTests.ParserTests testPlaneBodyTrimsLeadingAndTrailingBlanks]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testPlanesByZAreSorted]' started. +Test Case '-[ThreeMDTests.ParserTests testPlanesByZAreSorted]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testPreambleBeforeFirstPlane]' started. +Test Case '-[ThreeMDTests.ParserTests testPreambleBeforeFirstPlane]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testReservedAttributeKeysNotInExtras]' started. +Test Case '-[ThreeMDTests.ParserTests testReservedAttributeKeysNotInExtras]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testRoundTripThroughSerializer]' started. +Test Case '-[ThreeMDTests.ParserTests testRoundTripThroughSerializer]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testRoundTripWithMetadataAndAttributes]' started. +Test Case '-[ThreeMDTests.ParserTests testRoundTripWithMetadataAndAttributes]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testRoundTripWithPreamble]' started. +Test Case '-[ThreeMDTests.ParserTests testRoundTripWithPreamble]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testUnclosedFrontmatterThrows]' started. +Test Case '-[ThreeMDTests.ParserTests testUnclosedFrontmatterThrows]' passed (0.000 seconds). +Test Case '-[ThreeMDTests.ParserTests testWindowsLineEndingsNormalized]' started. +Test Case '-[ThreeMDTests.ParserTests testWindowsLineEndingsNormalized]' passed (0.000 seconds). +Test Suite 'ParserTests' passed at 2026-10-10 11:56:59.811. + Executed 32 tests, with 0 failures (0 unexpected) in 0.005 (0.007) seconds +Test Suite '3mdPackageTests.xctest' passed at 2026-10-10 11:56:59.811. + Executed 322 tests, with 0 failures (0 unexpected) in 90.338 (90.361) seconds +Test Suite 'All tests' passed at 2026-10-10 11:56:59.811. + Executed 322 tests, with 0 failures (0 unexpected) in 90.338 (90.363) seconds +◇ Test run started. +↳ Testing Library Version: 1902 +↳ Target Platform: arm64e-apple-macos14.0 +✔ Test run with 0 tests in 0 suites passed after 0.001 seconds. + ✔ Step 3 done (1m 31.210s) + ▶️ Running task: js +bun install v1.4.0 (34cbb9a40) + +Checked 5 installs across 6 packages (no changes) [22.00ms] +$ tsc --noEmit +$ bun build ./src/index.ts --outdir ./dist --target node --format esm && tsc -p tsconfig.build.json +Bundled 9 modules in 16ms + + index.js 146.91 KB (entry point) + +bun test v1.4.0 (34cbb9a40) + +test/interchange.test.ts: +(pass) lossless cross-language interchange > raw parsing and bounded decoding use the literal Foundation whitespace set [20.73ms] +(pass) lossless cross-language interchange > Unicode whitespace fences do not invent directives during bounded preflight [1.95ms] +(pass) lossless cross-language interchange > UTF-8 decoding leaves BOM removal to the parser exactly once [0.26ms] +(pass) lossless cross-language interchange > source dictionary collisions retain first spelling and the last assignment in source order [8.95ms] +(pass) lossless cross-language interchange > legacy serialization preserves literal apostrophes, edge whitespace, quotes and backslashes [1.50ms] +(pass) lossless cross-language interchange > legacy number formatting and Unicode scalar key order agree with canonical wire writers [1.10ms] +(pass) lossless cross-language interchange > links preserve long finite targets, long labels and multiline labels [0.39ms] +(pass) lossless cross-language interchange > linear link scanning preserves reference regex matching for malformed nested candidates [2.32ms] + +test/structured.test.ts: +(pass) structured goldens (test-plan section 1) > the manifest lists 49 interchange anchors, 2 examples and 3 worked examples [0.08ms] +(pass) structured goldens (test-plan section 1) > axis-48: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [4.80ms] +(pass) structured goldens (test-plan section 1) > axis-49: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.69ms] +(pass) structured goldens (test-plan section 1) > axis-50: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.44ms] +(pass) structured goldens (test-plan section 1) > axis-51: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.47ms] +(pass) structured goldens (test-plan section 1) > axis-52: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.64ms] +(pass) structured goldens (test-plan section 1) > axis-53: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.40ms] +(pass) structured goldens (test-plan section 1) > axis-54: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.64ms] +(pass) structured goldens (test-plan section 1) > axis-55: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.56ms] +(pass) structured goldens (test-plan section 1) > axis-56: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.40ms] +(pass) structured goldens (test-plan section 1) > axis-57: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.55ms] +(pass) structured goldens (test-plan section 1) > combining-mark-delimiters: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [1.63ms] +(pass) structured goldens (test-plan section 1) > combining-mark-fences: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.68ms] +(pass) structured goldens (test-plan section 1) > combining-mark-scalars: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.99ms] +(pass) structured goldens (test-plan section 1) > composition-empty-root: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [3.66ms] +(pass) structured goldens (test-plan section 1) > composition-shared-dag-unused: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [8.15ms] +(pass) structured goldens (test-plan section 1) > empty-document: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.46ms] +(pass) structured goldens (test-plan section 1) > empty-planes: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.92ms] +(pass) structured goldens (test-plan section 1) > extension-composition-instances: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [4.61ms] +(pass) structured goldens (test-plan section 1) > extension-document-unicode: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.85ms] +(pass) structured goldens (test-plan section 1) > extension-unicode-key-order: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [1.12ms] +(pass) structured goldens (test-plan section 1) > extension-unicode-source-collision: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.35ms] +(pass) structured goldens (test-plan section 1) > fences-and-directives: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.38ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-attribute-numeric-stays-string: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.20ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-axis-default: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.46ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-axis-lowercased: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.33ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-bom: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.22ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-code-block-directive-safe: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.15ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-coordinates-attributes: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.24ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-crlf: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.17ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-decimal-negative-z: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.17ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-empty-body: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.11ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-empty-plane-body: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.13ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-escaped-quote-label: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.16ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-frontmatter-comments: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.26ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-indented-directive-is-body: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.26ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-leading-blank-lines: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.23ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-metadata-key-case-preserved: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.33ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-multi-plane: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.34ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-plane-prefix-not-directive: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.15ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-preamble-with-planes: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.25ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-repeated-directive-key-last-wins: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.15ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-single-plane-shorthand: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.29ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-version-1-0: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.31ms] +(pass) structured goldens (test-plan section 1) > legacy-valid-z-scientific-notation: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.40ms] +(pass) structured goldens (test-plan section 1) > mixed-coordinates: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.39ms] +(pass) structured goldens (test-plan section 1) > nfc-source-keys: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.26ms] +(pass) structured goldens (test-plan section 1) > scalar-quoting: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.44ms] +(pass) structured goldens (test-plan section 1) > unicode-exact-values: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.47ms] +(pass) structured goldens (test-plan section 1) > whitespace-crlf-bom: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.47ms] +(pass) structured goldens (test-plan section 1) > canopy: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.42ms] +(pass) structured goldens (test-plan section 1) > shared-grove: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [4.02ms] +(pass) structured goldens (test-plan section 1) > worked-document: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.35ms] +(pass) structured goldens (test-plan section 1) > worked-numbers: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.18ms] +(pass) structured goldens (test-plan section 1) > worked-keys: writer bytes, decode, re-encode, header, kind-1 sibling, SHA-256 [0.27ms] +(pass) structured goldens (test-plan section 1) > the worked document has the metrics of SPEC.md 11.3.17 and the annotated bytes [1.25ms] +(pass) structured vectors (test-plan section 2) > the manifest holds 156 vectors: 30 with limits, 25 ok, 131 typed errors [0.15ms] +(pass) structured vectors (test-plan section 2) > container-truncated-header (D4) gives invalidContainer [0.45ms] +(pass) structured vectors (test-plan section 2) > container-version-2 (D5) gives unsupportedVersion [0.20ms] +(pass) structured vectors (test-plan section 2) > container-kind-0 (D6) gives unsupportedPayloadKind [0.22ms] +(pass) structured vectors (test-plan section 2) > container-kind-3 (D6) gives unsupportedPayloadKind [0.08ms] +(pass) structured vectors (test-plan section 2) > container-kind-4 (D6) gives unsupportedPayloadKind [0.16ms] +(pass) structured vectors (test-plan section 2) > container-kind-255 (D6) gives unsupportedPayloadKind [0.09ms] +(pass) structured vectors (test-plan section 2) > container-kind-3-bad-crc (D6) gives unsupportedPayloadKind [0.07ms] +(pass) structured vectors (test-plan section 2) > container-compression-2 (D7) gives unsupportedCompression [0.10ms] +(pass) structured vectors (test-plan section 2) > container-flags (D8) gives unsupportedFlags [0.08ms] +(pass) structured vectors (test-plan section 2) > container-reserved (D9) gives nonzeroReserved [0.06ms] +(pass) structured vectors (test-plan section 2) > container-decoded-over-emax (D10) gives oversizedOutput [0.10ms] +(pass) structured vectors (test-plan section 2) > container-decoded-over-2dmax-bad-crc (D10) gives oversizedOutput [0.09ms] +(pass) structured vectors (test-plan section 2) > container-encoded-zero (D11) gives lengthMismatch [0.09ms] +(pass) structured vectors (test-plan section 2) > container-decoded-zero (D11) gives lengthMismatch [0.10ms] +(pass) structured vectors (test-plan section 2) > container-encoded-mismatch (D11) gives lengthMismatch [0.06ms] +(pass) structured vectors (test-plan section 2) > container-uncompressed-lengths-differ (D11) gives lengthMismatch [0.10ms] +(pass) structured vectors (test-plan section 2) > container-trailing-byte (D11) gives lengthMismatch [0.09ms] +(pass) structured vectors (test-plan section 2) > container-crc-field (D12) gives checksumMismatch [0.12ms] +(pass) structured vectors (test-plan section 2) > container-crc-payload (D12) gives checksumMismatch [0.09ms] +(pass) structured vectors (test-plan section 2) > container-lzfse-portable (D13) gives compressionUnavailable [0.10ms] +(pass) structured vectors (test-plan section 2) > var-non-minimal (V3) gives invalidContainer [0.19ms] +(pass) structured vectors (test-plan section 2) > var-non-minimal-zero (V3) gives invalidContainer [0.12ms] +(pass) structured vectors (test-plan section 2) > var-five-bytes (Str1) gives lengthMismatch [0.20ms] +(pass) structured vectors (test-plan section 2) > var-four-continuation-truncated (V1) gives lengthMismatch [0.18ms] +(pass) structured vectors (test-plan section 2) > var-truncated (V1) gives lengthMismatch [0.11ms] +(pass) structured vectors (test-plan section 2) > var-max-length (Str1) gives lengthMismatch [0.07ms] +(pass) structured vectors (test-plan section 2) > count-metadata (C) gives lengthMismatch [0.09ms] +(pass) structured vectors (test-plan section 2) > count-planes (C) gives lengthMismatch [0.09ms] +(pass) structured vectors (test-plan section 2) > count-attributes (C) gives lengthMismatch [0.19ms] +(pass) structured vectors (test-plan section 2) > count-planes-edge-ok (C) gives ok [0.13ms] +(pass) structured vectors (test-plan section 2) > count-planes-over-pmax-and-remaining (C) gives lengthMismatch [0.10ms] +(pass) structured vectors (test-plan section 2) > str-remaining-plus-one (Str1) gives lengthMismatch [0.12ms] +(pass) structured vectors (test-plan section 2) > str-remaining-before-limit (Str1) gives lengthMismatch [0.27ms] +(pass) structured vectors (test-plan section 2) > str-two-byte-var-exact-ok (Str1) gives ok [0.33ms] +(pass) structured vectors (test-plan section 2) > str-two-byte-var-plus-one (Str1) gives lengthMismatch [0.11ms] +(pass) structured vectors (test-plan section 2) > str-over-record (Str2) gives oversizedRecord [0.15ms] +(pass) structured vectors (test-plan section 2) > str-preamble-over-r-minus-1 (S7) gives oversizedRecord [0.11ms] +(pass) structured vectors (test-plan section 2) > utf8-scalar-overlong (Str3) gives invalidUTF8 [0.36ms] +(pass) structured vectors (test-plan section 2) > utf8-scalar-surrogate (Str3) gives invalidUTF8 [0.09ms] +(pass) structured vectors (test-plan section 2) > utf8-scalar-above-max (Str3) gives invalidUTF8 [0.08ms] +(pass) structured vectors (test-plan section 2) > utf8-scalar-truncated (Str3) gives invalidUTF8 [0.09ms] +(pass) structured vectors (test-plan section 2) > utf8-scalar-lone-continuation (Str3) gives invalidUTF8 [0.10ms] +(pass) structured vectors (test-plan section 2) > utf8-scalar-ff (Str3) gives invalidUTF8 [0.11ms] +(pass) structured vectors (test-plan section 2) > utf8-body-split (Str3) gives invalidUTF8 [0.07ms] +(pass) structured vectors (test-plan section 2) > utf8-before-line-break (Str3) gives invalidUTF8 [0.06ms] +(pass) structured vectors (test-plan section 2) > scalar-lf (Str4) gives invalidDocument [0.15ms] +(pass) structured vectors (test-plan section 2) > scalar-cr (Str4) gives invalidDocument [0.07ms] +(pass) structured vectors (test-plan section 2) > flags-document-bit2 (S1) gives invalidContainer [0.07ms] +(pass) structured vectors (test-plan section 2) > flags-document-bit7 (S1) gives invalidContainer [0.06ms] +(pass) structured vectors (test-plan section 2) > flags-plane-bit7 (P1) gives invalidContainer [0.06ms] +(pass) structured vectors (test-plan section 2) > flags-plane-z-form-0 (P1) gives invalidContainer [0.08ms] +(pass) structured vectors (test-plan section 2) > number-f32-integer (N) gives invalidContainer [0.07ms] +(pass) structured vectors (test-plan section 2) > number-f32-negative-zero (N) gives invalidContainer [0.07ms] +(pass) structured vectors (test-plan section 2) > number-f32-nan (N) gives invalidDocument [0.06ms] +(pass) structured vectors (test-plan section 2) > number-f32-infinity (N) gives invalidDocument [0.08ms] +(pass) structured vectors (test-plan section 2) > number-f32-truncated (N) gives lengthMismatch [0.09ms] +(pass) structured vectors (test-plan section 2) > number-f64-truncated (N) gives lengthMismatch [0.13ms] +(pass) structured vectors (test-plan section 2) > number-f64-integer (N) gives invalidContainer [0.09ms] +(pass) structured vectors (test-plan section 2) > number-f64-binary32 (N) gives invalidContainer [0.10ms] +(pass) structured vectors (test-plan section 2) > number-f64-negative-zero (N) gives invalidContainer [0.07ms] +(pass) structured vectors (test-plan section 2) > number-f64-nan (N) gives invalidDocument [0.07ms] +(pass) structured vectors (test-plan section 2) > number-f64-negative-infinity (N) gives invalidDocument [0.06ms] +(pass) structured vectors (test-plan section 2) > number-f64-int-boundary (N) gives invalidContainer [0.06ms] +(pass) structured vectors (test-plan section 2) > number-f32-two-pow-27-ok (N) gives ok [0.13ms] +(pass) structured vectors (test-plan section 2) > number-f64-two-pow-53-plus-2-ok (N) gives ok [0.17ms] +(pass) structured vectors (test-plan section 2) > number-f32-for-f64-value (N) gives ok [0.13ms] +(pass) structured vectors (test-plan section 2) > order-metadata-decreasing (S6) gives invalidContainer [0.10ms] +(pass) structured vectors (test-plan section 2) > order-metadata-identical (S6) gives invalidContainer [0.13ms] +(pass) structured vectors (test-plan section 2) > order-nfc-instead-of-bytes (S6) gives invalidContainer [0.11ms] +(pass) structured vectors (test-plan section 2) > order-utf16-instead-of-bytes (S6) gives invalidContainer [0.12ms] +(pass) structured vectors (test-plan section 2) > order-equivalent-keys (S6b) gives invalidDocument [0.09ms] +(pass) structured vectors (test-plan section 2) > order-equivalent-kelvin (S6b) gives invalidDocument [0.11ms] +(pass) structured vectors (test-plan section 2) > order-attributes-decreasing (P7) gives invalidContainer [0.11ms] +(pass) structured vectors (test-plan section 2) > order-attributes-equivalent (P7a) gives invalidDocument [0.08ms] +(pass) structured vectors (test-plan section 2) > order-keys-ok (S6) gives ok [0.20ms] +(pass) structured vectors (test-plan section 2) > field-empty-version (S2) gives invalidDocument [0.10ms] +(pass) structured vectors (test-plan section 2) > axis-uppercase (R2) gives invalidDocument [0.09ms] +(pass) structured vectors (test-plan section 2) > axis-leading-space (R2) gives invalidDocument [0.08ms] +(pass) structured vectors (test-plan section 2) > axis-trailing-tab (R2) gives invalidDocument [0.06ms] +(pass) structured vectors (test-plan section 2) > axis-trailing-nbsp (R2) gives invalidDocument [0.11ms] +(pass) structured vectors (test-plan section 2) > axis-non-ascii-uppercase (R2) gives invalidDocument [0.09ms] +(pass) structured vectors (test-plan section 2) > axis-unicode-ok (R2) gives ok [0.11ms] +(pass) structured vectors (test-plan section 2) > metadata-key-colon (R3) gives invalidDocument [0.07ms] +(pass) structured vectors (test-plan section 2) > metadata-key-hash (R3) gives invalidDocument [0.07ms] +(pass) structured vectors (test-plan section 2) > metadata-key-leading-space (R3) gives invalidDocument [0.08ms] +(pass) structured vectors (test-plan section 2) > metadata-key-trailing-ideographic-space (R3) gives invalidDocument [0.07ms] +(pass) structured vectors (test-plan section 2) > metadata-key-axis (R3) gives invalidDocument [0.07ms] +(pass) structured vectors (test-plan section 2) > metadata-key-title (R3) gives invalidDocument [0.08ms] +(pass) structured vectors (test-plan section 2) > metadata-key-version (R3) gives invalidDocument [0.10ms] +(pass) structured vectors (test-plan section 2) > metadata-key-empty-ok (R3) gives ok [0.16ms] +(pass) structured vectors (test-plan section 2) > attribute-key-empty (R9) gives invalidDocument [0.25ms] +(pass) structured vectors (test-plan section 2) > attribute-key-uppercase (R9) gives invalidDocument [0.24ms] +(pass) structured vectors (test-plan section 2) > attribute-key-label (R9) gives invalidDocument [0.21ms] +(pass) structured vectors (test-plan section 2) > attribute-key-z (R9) gives invalidDocument [0.07ms] +(pass) structured vectors (test-plan section 2) > attribute-key-equals (R9) gives invalidDocument [0.06ms] +(pass) structured vectors (test-plan section 2) > attribute-key-space (R9) gives invalidDocument [0.06ms] +(pass) structured vectors (test-plan section 2) > attribute-key-tab (R9) gives invalidDocument [0.06ms] +(pass) structured vectors (test-plan section 2) > attribute-key-leading-nbsp (R9) gives invalidDocument [0.08ms] +(pass) structured vectors (test-plan section 2) > attribute-key-sigma (R9) gives invalidDocument [0.06ms] +(pass) structured vectors (test-plan section 2) > duplicate-z (L0) gives invalidDocument [0.10ms] +(pass) structured vectors (test-plan section 2) > preamble-without-planes (S8) gives invalidDocument [0.11ms] +(pass) structured vectors (test-plan section 2) > too-many-planes (S8) gives tooManyPlanes [0.09ms] +(pass) structured vectors (test-plan section 2) > segment-empty-preamble (G1) gives invalidDocument [0.16ms] +(pass) structured vectors (test-plan section 2) > segment-trailing-cr (G2) gives invalidDocument [0.10ms] +(pass) structured vectors (test-plan section 2) > segment-inner-cr-ok (G2) gives ok [0.14ms] +(pass) structured vectors (test-plan section 2) > segment-crlf (G3) gives invalidDocument [0.11ms] +(pass) structured vectors (test-plan section 2) > segment-leading-blank (G4) gives invalidDocument [0.07ms] +(pass) structured vectors (test-plan section 2) > segment-trailing-blank (G4) gives invalidDocument [0.09ms] +(pass) structured vectors (test-plan section 2) > segment-leading-nbsp-line (G4) gives invalidDocument [0.10ms] +(pass) structured vectors (test-plan section 2) > segment-trailing-ideographic-line (G4) gives invalidDocument [0.11ms] +(pass) structured vectors (test-plan section 2) > segment-plane-line (G5) gives invalidDocument [0.07ms] +(pass) structured vectors (test-plan section 2) > segment-plane-directive (G5) gives invalidDocument [0.12ms] +(pass) structured vectors (test-plan section 2) > segment-plane-tab (G5) gives invalidDocument [0.09ms] +(pass) structured vectors (test-plan section 2) > segment-indented-plane-ok (G5) gives ok [0.15ms] +(pass) structured vectors (test-plan section 2) > segment-planet-ok (G5) gives ok [0.14ms] +(pass) structured vectors (test-plan section 2) > segment-fence-backtick-tilde-ok (G5) gives ok [0.15ms] +(pass) structured vectors (test-plan section 2) > segment-fence-tilde-closed (G5) gives invalidDocument [0.10ms] +(pass) structured vectors (test-plan section 2) > segment-fence-nbsp-indented-ok (G5) gives ok [0.20ms] +(pass) structured vectors (test-plan section 2) > segment-fence-open-not-final (G6) gives invalidDocument [0.13ms] +(pass) structured vectors (test-plan section 2) > segment-fence-open-final-ok (G6) gives ok [0.12ms] +(pass) structured vectors (test-plan section 2) > segment-fence-open-preamble (G6) gives invalidDocument [0.17ms] +(pass) structured vectors (test-plan section 2) > segment-bom-nul-ok (Str3) gives ok [0.14ms] +(pass) structured vectors (test-plan section 2) > phase-q-apostrophe (Q) gives invalidDocument [0.26ms] +(pass) structured vectors (test-plan section 2) > phase-q-double-quote (Q) gives invalidDocument [0.19ms] +(pass) structured vectors (test-plan section 2) > phase-q-paired-ok (Q) gives ok [0.31ms] +(pass) structured vectors (test-plan section 2) > phase-q-spaced-pair-ok (Q) gives ok [0.32ms] +(pass) structured vectors (test-plan section 2) > phase-q-quoted-space-ok (Q) gives ok [0.19ms] +(pass) structured vectors (test-plan section 2) > phase-q-swallow-next (Q) gives invalidDocument [0.18ms] +(pass) structured vectors (test-plan section 2) > phase-q-inject-z (Q) gives invalidDocument [0.18ms] +(pass) structured vectors (test-plan section 2) > phase-q-inject-label (Q) gives invalidDocument [0.21ms] +(pass) structured vectors (test-plan section 2) > phase-q-uppercase-quoted (Q) gives invalidDocument [0.11ms] +(pass) structured vectors (test-plan section 2) > limit-record-below-3 (L1) gives oversizedRecord [0.23ms] +(pass) structured vectors (test-plan section 2) > limit-frontmatter-line (L2) gives oversizedRecord [0.22ms] +(pass) structured vectors (test-plan section 2) > limit-directive-line (L3) gives oversizedRecord [0.22ms] +(pass) structured vectors (test-plan section 2) > limit-text-length (L4) gives oversizedOutput [0.12ms] +(pass) structured vectors (test-plan section 2) > limit-lines (L5) gives tooManyLines [0.12ms] +(pass) structured vectors (test-plan section 2) > precedence-l0-over-l3 (L0) gives invalidDocument [0.20ms] +(pass) structured vectors (test-plan section 2) > precedence-l3-over-l4 (L3) gives oversizedRecord [0.17ms] +(pass) structured vectors (test-plan section 2) > precedence-l4-over-l5 (L4) gives oversizedOutput [0.19ms] +(pass) structured vectors (test-plan section 2) > precedence-s-order (S9) gives invalidDocument [0.07ms] +(pass) structured vectors (test-plan section 2) > precedence-utf8-before-limits (S4) gives invalidUTF8 [0.08ms] +(pass) structured vectors (test-plan section 2) > end-trailing-byte (S10) gives lengthMismatch [0.10ms] +(pass) structured vectors (test-plan section 2) > bound-2dmax-exact (L4) gives oversizedOutput [0.07ms] +(pass) structured vectors (test-plan section 2) > eighty-planes-emax-1000 (L4) gives ok [0.24ms] +(pass) structured vectors (test-plan section 2) > edges-maximumDecodedBytes-at (L4) gives ok [0.37ms] +(pass) structured vectors (test-plan section 2) > edges-maximumDecodedBytes-below (L4) gives oversizedOutput [0.05ms] +(pass) structured vectors (test-plan section 2) > edges-maximumLines-at (L5) gives ok [0.10ms] +(pass) structured vectors (test-plan section 2) > edges-maximumLines-below (L5) gives tooManyLines [0.03ms] +(pass) structured vectors (test-plan section 2) > edges-maximumPlanes-at (S8) gives ok [0.07ms] +(pass) structured vectors (test-plan section 2) > edges-maximumPlanes-below (S8) gives tooManyPlanes [0.03ms] +(pass) structured vectors (test-plan section 2) > edges-maximumRecordBytes-at (L3) gives ok [0.09ms] +(pass) structured vectors (test-plan section 2) > edges-maximumRecordBytes-below (L3) gives oversizedRecord [0.03ms] +(pass) structured vectors (test-plan section 2) > edges-maximumEncodedBytes-at (D2) gives ok [0.08ms] +(pass) structured vectors (test-plan section 2) > edges-maximumEncodedBytes-below (D2) gives oversizedInput [0.08ms] +(pass) structured vectors (test-plan section 2) > preamble-record-31 (Str2) gives ok [0.08ms] +(pass) structured vectors (test-plan section 2) > preamble-record-30 (Str2) gives oversizedRecord [0.03ms] +(pass) structured unit checklist (test-plan section 3) > Var encodes and decodes minimally at every byte-count boundary [17.17ms] +(pass) structured unit checklist (test-plan section 3) > Var rejections V1 to V3 [0.55ms] +(pass) structured unit checklist (test-plan section 3) > number forms follow SPEC.md 11.3.3 and every encoding decodes bit for bit [0.52ms] +(pass) structured unit checklist (test-plan section 3) > CRC check value, slicing against a bytewise reference, and container checksums [78.91ms] +(pass) structured unit checklist (test-plan section 3) > chunked UTF-8 validation agrees with whole-string validation at every chunk boundary [12.55ms] +(pass) structured unit checklist (test-plan section 3) > segment rules G1 to G6 on hand cases [0.48ms] +(pass) structured unit checklist (test-plan section 3) > segment scanner agrees with the 2.0 parser round trip on 100,000 random bodies [1564.91ms] +(pass) structured unit checklist (test-plan section 3) > canonical text metrics equal the 2.0 writer on every Example and 100,000 generated documents [9950.91ms] +(pass) structured unit checklist (test-plan section 3) > byte-order keys: code point order equals UTF-8 byte order, never UTF-16 order [83.07ms] +(pass) structured unit checklist (test-plan section 3) > key equivalence matches normalize("NFC") on decode [0.74ms] +(pass) structured unit checklist (test-plan section 3) > numeric-powers.json: 4,318 canonical spellings [15.46ms] +(pass) structured unit checklist (test-plan section 3) > containerInfo reports raw header fields without validating them [0.75ms] +(pass) structured unit checklist (test-plan section 3) > encodeTextContainer keeps the 2.0 binary writer's bytes and error order [12.19ms] +(pass) structured unit checklist (test-plan section 3) > writer edges: W1b, the exact Emax cap, compression after the self-check [0.90ms] +(pass) structured unit checklist (test-plan section 3) > TypeScript writer: lone surrogates, equivalent-key merge, dropped values and __proto__ [0.86ms] +(pass) structured unit checklist (test-plan section 3) > the portable utf8Length path, where String.prototype.isWellFormed is missing, writes the same bytes [6.47ms] +(pass) structured unit checklist (test-plan section 3) > decoded values have the 2.0 bounded decoder's shape [0.26ms] +(pass) structured unit checklist (test-plan section 3) > Unicode skew vectors outside Unicode 13.0 (recorded for the runtime's Unicode data) [1.25ms] +(pass) structured unit checklist (test-plan section 3) > size gate G6 (perf-gate section 4) holds for the Examples and the committed large-input sizes [93.46ms] +(pass) structured unit checklist (test-plan section 3) > the package index exports exactly the two new storage names [0.46ms] +(pass) TypeScript chunked decoding never carries bytes into the next string > Bun: a truncated last chunk and the following string both report invalidUTF8 [27.83ms] +(pass) TypeScript chunked decoding never carries bytes into the next string > Node: the same two-call sequences on the current sources [131.85ms] +(pass) differential properties at CI volume (test-plan section 4) > P1, P2 and P3 over 10,410 mutants of every anchor and the kind-2 Examples (seed 0x51a7) [2363.24ms] +(pass) differential properties at CI volume (test-plan section 4) > P5: encode(D, L) succeeds exactly when decode(encode(D, L), L) does, and returns the normalized D [100.55ms] +(pass) differential properties at CI volume (test-plan section 4) > P6: binary acceptance equals validate under standard and lowered limits, and decode equals the text decode [804.06ms] +(pass) cancellation, resource bounds and buffer ownership (test-plan section 5) > before entry: a pre-aborted signal fails every storage entry point with its reason [0.20ms] +(pass) cancellation, resource bounds and buffer ownership (test-plan section 5) > every decode and encode check point aborts with the reason and leaves no partial result [33.11ms] +(pass) cancellation, resource bounds and buffer ownership (test-plan section 5) > mid-CRC on a 64 MiB input [301.50ms] +(pass) cancellation, resource bounds and buffer ownership (test-plan section 5) > inside a 1 MiB scalar scan and between the UTF-8 chunks of an 8 MiB body [190.80ms] +(pass) cancellation, resource bounds and buffer ownership (test-plan section 5) > before plane k of 65,536 and in Phase L [830.25ms] +(pass) cancellation, resource bounds and buffer ownership (test-plan section 5) > before and after a Phase Q parse [0.42ms] +(pass) cancellation, resource bounds and buffer ownership (test-plan section 5) > mid-emission and mid-self-check on encode [0.91ms] +(pass) cancellation, resource bounds and buffer ownership (test-plan section 5) > the result walk checks by bytes inside one plane of 700,000 attributes (standard limits) [1382.23ms] +(pass) cancellation, resource bounds and buffer ownership (test-plan section 5) > the equivalence checks of long decomposed keys check by bytes, metadata and attributes (standard limits) [557.26ms] +(pass) cancellation, resource bounds and buffer ownership (test-plan section 5) > the writer checks by work inside large maps: merge tests, sorts, the plan and the emission [1782.68ms] +Bun memory growth / input: body a: 2.61, body é: 2.60, body €: 2.34, body 😀: 2.61, planes: 2.13, attributes: 1.25 +(pass) cancellation, resource bounds and buffer ownership (test-plan section 5) > memory on Bun: resident growth under 4 times the input for the 64 MiB worst cases and an 8 MiB body [1932.37ms] +Node memory growth / input: body a: 2.10, body é: 2.12, body €: 1.78, body 😀: 2.14, planes: 2.85, attributes: 1.03 +(pass) cancellation, resource bounds and buffer ownership (test-plan section 5) > memory on Node: the same cases on the current sources [2206.19ms] +(pass) cancellation, resource bounds and buffer ownership (test-plan section 5) > amplification: 65,536 quoted-key planes over R are rejected before any Phase Q parse, in under a second [265.77ms] +(pass) cancellation, resource bounds and buffer ownership (test-plan section 5) > Phase S allocates nothing per key: 2,000,000 minimal attributes stay far below 4 times the input [775.50ms] +(pass) cancellation, resource bounds and buffer ownership (test-plan section 5) > buffer ownership: overwriting or slicing the caller's buffer never changes a decoded value [2.01ms] +(pass) cancellation, resource bounds and buffer ownership (test-plan section 5) > a kind-2 file whose uncompressed container exceeds Emax or 2 Dmax stops at D10 before the CRC [0.14ms] + +test/composition.test.ts: +(pass) bounded self-contained composition > safe ID grammar, duplicates, absent roots and unreachable missing targets fail [1.94ms] +(pass) bounded self-contained composition > cycles, unused cycles, cached depth and repeated-traversal occurrence limits fail [0.92ms] +(pass) bounded self-contained composition > counts, unique source bytes and per-reference UTF-8 attributes are bounded [0.30ms] +(pass) bounded self-contained composition > constructors enforce absolute integer limits and legitimate zero reference limits [0.07ms] +(pass) bounded self-contained composition > public graph codecs validate plain-object composition policies before reading or writing [0.16ms] +(pass) bounded self-contained composition > strict envelopes, schemas, unknown fields and JSON types are rejected [0.91ms] +(pass) bounded self-contained composition > duplicate escaped keys, nested records, numeric fields and trailing JSON fail before object decoding [0.73ms] +(pass) bounded self-contained composition > embedded paths and malformed unused sources stay local parse errors [0.48ms] +(pass) bounded self-contained composition > profile and escaped JSON bounds count the complete envelope [0.55ms] +(pass) bounded self-contained composition > opaque attributes preserve controls, Unicode and prototype-looking keys [0.44ms] +(pass) bounded self-contained composition > pre-aborted graph construction and codecs propagate cancellation [0.14ms] +(pass) bounded self-contained composition > new reference writers sort Unicode scalar keys and strict JSON rejects equivalent duplicate keys [1.29ms] + +test/conformance.test.ts: +(pass) conformance vectors > at least one valid and one invalid vector exist [0.31ms] +(pass) conformance vectors > invalid-duplicate-plane.json: two planes sharing the same z value are rejected [0.17ms] +(pass) conformance vectors > invalid-duplicate-z-decimal-forms.json: z=0 and z=0.0 are the same position [0.04ms] +(pass) conformance vectors > invalid-frontmatter-no-colon.json: frontmatter line without a colon separator is rejected [0.03ms] +(pass) conformance vectors > invalid-frontmatter-unclosed.json: frontmatter block that is never closed is rejected [0.02ms] +(pass) conformance vectors > invalid-missing-frontmatter.json: document without a frontmatter fence is rejected +(pass) conformance vectors > invalid-missing-plane-position.json: a plane directive with no z attribute is rejected [0.02ms] +(pass) conformance vectors > invalid-missing-version.json: frontmatter without the 3md version key is rejected [0.01ms] +(pass) conformance vectors > invalid-plane-token-no-equals.json: a plane attribute token with no equals sign is rejected (Swift throws; it is not skipped) [0.04ms] +(pass) conformance vectors > invalid-plane-x-not-number.json: a plane directive whose x is not a number is rejected [0.03ms] +(pass) conformance vectors > invalid-plane-z-not-number.json: a plane directive whose z is not a number is rejected [0.02ms] +(pass) conformance vectors > invalid-unterminated-quote.json: an unterminated quote in a directive is rejected [0.03ms] +(pass) conformance vectors > invalid-z-hex.json: hex z is rejected so Swift and TS agree [0.02ms] +(pass) conformance vectors > invalid-z-infinity.json: z=inf is rejected (non-finite) [0.01ms] +(pass) conformance vectors > invalid-z-nan.json: z=nan is rejected (non-finite, also closes the NaN dedup bypass) +(pass) conformance vectors > invalid-z-thousands-separator.json: thousands separators are rejected +(pass) conformance vectors > links-basic.json: a [[z=N]] reference resolves to the source z, target z, and existence [0.14ms] +(pass) conformance vectors > links-dangling.json: a reference to a missing plane is reported with targetExists false [0.01ms] +(pass) conformance vectors > links-decimal-target.json: a decimal target z is matched against a decimal plane z [0.01ms] +(pass) conformance vectors > links-invalid-ignored.json: non-finite targets and ordinary Markdown links are not cross-plane links +(pass) conformance vectors > links-multiple.json: multiple links in one body are returned left to right [0.01ms] +(pass) conformance vectors > links-with-text.json: a [[z=N|text]] reference captures the link text [0.01ms] +(pass) conformance vectors > valid-attribute-numeric-stays-string.json: non z/x/y attributes stay strings, not coerced [0.04ms] +(pass) conformance vectors > valid-axis-default.json: axis defaults to layer when omitted +(pass) conformance vectors > valid-axis-lowercased.json: axis value is trimmed and lowercased +(pass) conformance vectors > valid-bom.json: a leading UTF-8 BOM is stripped before parsing +(pass) conformance vectors > valid-code-block-directive-safe.json: a @plane line inside a fenced code block stays body text +(pass) conformance vectors > valid-coordinates-attributes.json: coordinates, label, and extra attributes are captured [0.02ms] +(pass) conformance vectors > valid-crlf.json: CRLF line endings are normalized to LF [0.01ms] +(pass) conformance vectors > valid-decimal-negative-z.json: z accepts negative and decimal values and keeps source order +(pass) conformance vectors > valid-empty-body.json: frontmatter only with no body yields no planes +(pass) conformance vectors > valid-empty-plane-body.json: a plane directive with no following content has an empty body +(pass) conformance vectors > valid-escaped-quote-label.json: escaped quotes inside a quoted label round-trip +(pass) conformance vectors > valid-frontmatter-comments.json: frontmatter skips comment and blank lines and strips quotes [0.01ms] +(pass) conformance vectors > valid-indented-directive-is-body.json: an indented @plane is body, not a directive [0.01ms] +(pass) conformance vectors > valid-leading-blank-lines.json: leading blank lines before the frontmatter fence are allowed +(pass) conformance vectors > valid-metadata-key-case-preserved.json: non-reserved frontmatter keys keep their case +(pass) conformance vectors > valid-multi-plane.json: valid multi-plane document with title, metadata, and preamble [0.02ms] +(pass) conformance vectors > valid-plane-prefix-not-directive.json: @planex is not a directive; the doc is single-plane shorthand +(pass) conformance vectors > valid-preamble-with-planes.json: preamble is preserved when planes follow and quoted attribute keeps spaces [0.03ms] +(pass) conformance vectors > valid-repeated-directive-key-last-wins.json: a repeated directive key takes the last value [0.02ms] +(pass) conformance vectors > valid-single-plane-shorthand.json: single-plane shorthand wraps body at z=0 when no directives +(pass) conformance vectors > valid-version-1-0.json: the 1.0 format marker parses, with version reported as 1.0 +(pass) conformance vectors > valid-z-scientific-notation.json: scientific notation in z parses as a decimal [0.02ms] +(pass) round trip: parse -> serialize -> parse > valid-attribute-numeric-stays-string.json: non z/x/y attributes stay strings, not coerced [0.11ms] +(pass) round trip: parse -> serialize -> parse > valid-axis-default.json: axis defaults to layer when omitted [0.02ms] +(pass) round trip: parse -> serialize -> parse > valid-axis-lowercased.json: axis value is trimmed and lowercased [0.01ms] +(pass) round trip: parse -> serialize -> parse > valid-bom.json: a leading UTF-8 BOM is stripped before parsing [0.01ms] +(pass) round trip: parse -> serialize -> parse > valid-code-block-directive-safe.json: a @plane line inside a fenced code block stays body text [0.02ms] +(pass) round trip: parse -> serialize -> parse > valid-coordinates-attributes.json: coordinates, label, and extra attributes are captured [0.05ms] +(pass) round trip: parse -> serialize -> parse > valid-crlf.json: CRLF line endings are normalized to LF [0.02ms] +(pass) round trip: parse -> serialize -> parse > valid-decimal-negative-z.json: z accepts negative and decimal values and keeps source order [0.01ms] +(pass) round trip: parse -> serialize -> parse > valid-empty-body.json: frontmatter only with no body yields no planes +(pass) round trip: parse -> serialize -> parse > valid-empty-plane-body.json: a plane directive with no following content has an empty body [0.01ms] +(pass) round trip: parse -> serialize -> parse > valid-escaped-quote-label.json: escaped quotes inside a quoted label round-trip [0.01ms] +(pass) round trip: parse -> serialize -> parse > valid-frontmatter-comments.json: frontmatter skips comment and blank lines and strips quotes [0.03ms] +(pass) round trip: parse -> serialize -> parse > valid-indented-directive-is-body.json: an indented @plane is body, not a directive [0.01ms] +(pass) round trip: parse -> serialize -> parse > valid-leading-blank-lines.json: leading blank lines before the frontmatter fence are allowed [0.01ms] +(pass) round trip: parse -> serialize -> parse > valid-metadata-key-case-preserved.json: non-reserved frontmatter keys keep their case [0.02ms] +(pass) round trip: parse -> serialize -> parse > valid-multi-plane.json: valid multi-plane document with title, metadata, and preamble [0.05ms] +(pass) round trip: parse -> serialize -> parse > valid-plane-prefix-not-directive.json: @planex is not a directive; the doc is single-plane shorthand +(pass) round trip: parse -> serialize -> parse > valid-preamble-with-planes.json: preamble is preserved when planes follow and quoted attribute keeps spaces [0.03ms] +(pass) round trip: parse -> serialize -> parse > valid-repeated-directive-key-last-wins.json: a repeated directive key takes the last value [0.01ms] +(pass) round trip: parse -> serialize -> parse > valid-single-plane-shorthand.json: single-plane shorthand wraps body at z=0 when no directives +(pass) round trip: parse -> serialize -> parse > valid-version-1-0.json: the 1.0 format marker parses, with version reported as 1.0 +(pass) round trip: parse -> serialize -> parse > valid-z-scientific-notation.json: scientific notation in z parses as a decimal [0.02ms] + +test/editing.test.ts: +(pass) portable atomic editing and diagnostics > adoption skips existing IDs, preserves id metadata and rejects unsafe or duplicated identities [0.72ms] +(pass) portable atomic editing and diagnostics > snapshots deep-copy and freeze values; reconstruction rejects a forged revision [1.01ms] +(pass) portable atomic editing and diagnostics > insert, move, remove and header replacements are one pure transaction [0.52ms] +(pass) portable atomic editing and diagnostics > later invalid operation rolls back; replacement identities, indices and missing targets are precise [0.51ms] +(pass) portable atomic editing and diagnostics > exact revisions reject NFC-equivalent bytes and expected-content budgets [0.40ms] +(pass) portable atomic editing and diagnostics > structurally typed snapshot revisions cannot replace the exact-content comparison [0.94ms] +(pass) portable atomic editing and diagnostics > operation, payload and final invalid-document policies return no partial result [0.59ms] +(pass) portable atomic editing and diagnostics > two NaN coordinate replacements reach invalid-document validation without a false duplicate [0.23ms] +(pass) portable atomic editing and diagnostics > graph patches allow forward definitions and final root swaps without flattening [1.86ms] +(pass) portable atomic editing and diagnostics > graph final failures identify the missing target or root and enforce scoped IDs [1.97ms] +(pass) portable atomic editing and diagnostics > source diagnostics carry only actual parser lines; value paths and truncation stay precise [0.46ms] +(pass) portable atomic editing and diagnostics > diagnostic payload preflight precedes expensive graph validation and retains owner paths [4.30ms] +(pass) portable atomic editing and diagnostics > all identity, transaction and diagnostic entry points honor pre-aborted signals [0.50ms] +(pass) portable atomic editing and diagnostics > public editor and diagnostic boundaries reject forged plain-object policies [0.32ms] + +test/storage.test.ts: +(pass) bounded portable storage > fixed envelope vectors match Swift and sliced data retains its byte offset [0.20ms] +(pass) bounded portable storage > existing Swift canopy and grove envelopes remain readable and byte-identical [1.83ms] +(pass) bounded portable storage > LZFSE is explicitly unavailable while unknown compression remains a different error [0.19ms] +(pass) bounded portable storage > header fields, checksums, trailing bytes and unsafe 64-bit lengths are checked [0.27ms] +(pass) bounded portable storage > the same header, checksum and payload checks hold for payload kind 2 [0.18ms] +(pass) bounded portable storage > resource constructors reject noninteger and nonpositive limits and accept any safe size [0.15ms] +(pass) bounded portable storage > a document past the old 64 MiB ceiling round-trips as text and as kind 2 [2464.71ms] +(pass) bounded portable storage > public storage boundaries validate structurally typed plain-object policies [0.23ms] +(pass) bounded portable storage > exact byte boundaries succeed; physical lines, planes and entire records are bounded [0.32ms] +(pass) bounded portable storage > preflight respects code fences and preserves the existing parser/serializer behavior [0.11ms] +(pass) bounded portable storage > direct lossy values and malformed decimals fail without changing legacy text APIs [3.08ms] +(pass) bounded portable storage > hostile interior and trailing ASCII whitespace remains exact through text and portable storage [28.56ms] +(pass) bounded portable storage > pre-aborted operations propagate the abort reason [0.20ms] +(pass) bounded portable storage > new canonical maps use Swift Unicode key equality, scalar order and original spelling [0.58ms] + +test/interchange-adapter.test.ts: +(pass) development files adapter limits > limit literals are judged by their correctly rounded IEEE double, like Swift and Rust [111.22ms] + +test/extensions.test.ts: +(pass) Swift portable extension conformance > all IEEE754 number vectors match Swift canonical formatting [1.18ms] +(pass) Swift portable extension conformance > Swift scientific notation starts strictly above the exact 2^53 boundary [0.07ms] +(pass) Swift portable extension conformance > canonical Unicode document text, envelope and revision are byte-identical to Swift [0.98ms] +(pass) Swift portable extension conformance > canonical composition preserves shared definitions, instance IDs and exact profile bytes [2.72ms] +(pass) Swift portable extension conformance > additive Swift Unicode key ordering and source-collision goldens match the portable codecs [1.65ms] +(pass) Swift portable extension conformance > identity adoption follows the Swift fixture and preserves ordinary id metadata [0.89ms] +(pass) Swift portable extension conformance > document transaction: atomic-coordinate-swap [0.42ms] +(pass) Swift portable extension conformance > document transaction: source-order-change [0.23ms] +(pass) Swift portable extension conformance > composition transaction: retarget-and-reorder-owner-instance [1.56ms] +(pass) Swift portable extension conformance > composition transaction: remove-one-repeated-target-instance [1.39ms] +(pass) Swift portable extension conformance > atomic failure: stale-document-revision [0.26ms] +(pass) Swift portable extension conformance > atomic failure: final-coordinate-conflict [0.14ms] +(pass) Swift portable extension conformance > atomic failure: changed-plane-identity [0.13ms] +(pass) Swift portable extension conformance > atomic failure: stale-composition-revision [0.05ms] +(pass) Swift portable extension conformance > atomic failure: final-reference-cycle [0.66ms] +(pass) Swift portable extension conformance > atomic failure: wrong-owner-reference-target [0.42ms] + +test/file-composition.test.ts: +(pass) explicit supplied-file composition > simple and repeated glyph links deduplicate files and refresh changed child bytes [1.75ms] +(pass) explicit supplied-file composition > nested parent paths and duplicate basenames resolve relative to each containing file [1.34ms] +(pass) explicit supplied-file composition > payload kind 1 children and bundles (the 2.0 binary bytes) still resolve [1.30ms] +(pass) explicit supplied-file composition > binary nested bundles retain unused entries, stable identities and opaque edges before new ledger edges [1.84ms] +(pass) explicit supplied-file composition > nested profile records use the outer composition policy while embedded ordinary records retain child bounds [2596.10ms] +(pass) explicit supplied-file composition > paths use NFC and Unicode scalar ordering rather than UTF16 or locale sorting [1.41ms] +(pass) explicit supplied-file composition > path grammar rejects escape, absolute paths, empty segments, controls and normalized aliases [0.63ms] +(pass) explicit supplied-file composition > strict ledger scanner rejects duplicate escaped keys, malformed JSON and invalid glyphs before values [0.48ms] +(pass) explicit supplied-file composition > missing files and malformed reachable storage retain distinct errors, unreachable storage is ignored [0.38ms] +(pass) explicit supplied-file composition > file cycles also fail when unused bundle entries form a cycle across files [1.35ms] +(pass) explicit supplied-file composition > supplied counts, original path bytes and reachable bytes use input limits before decoding [154.17ms] +(pass) explicit supplied-file composition > outer recognition applies child byte and line policies before its lowered plane ceiling [0.62ms] +(pass) explicit supplied-file composition > disconnected embedded ledgers use final entry depth rather than incoming file depth [0.91ms] +(pass) explicit supplied-file composition > repeated cached dependencies validate final depth after complete discovery [0.86ms] +(pass) explicit supplied-file composition > independent fixed64 discovery safety bounds disconnected file chains [59.10ms] +(pass) explicit supplied-file composition > lowered policies enforce final graph depth, imported entries, edges, conceptual traversal and final profile size [1.28ms] +(pass) explicit supplied-file composition > pre-aborted and cooperatively aborted operations propagate the caller's cancellation reason [1.02ms] +(pass) linked composition parity hardening > static resolve, ledger and resolvePath do not depend on their class binding [1.00ms] +(pass) linked composition parity hardening > owner directories keep parent, dot and grammar semantics [0.15ms] +(pass) linked composition parity hardening > a long owner path with many references resolves every reference in its directory [9.66ms] +(pass) linked composition parity hardening > refusals follow entry ID, then glyph, discovery order [1.20ms] +(pass) linked composition parity hardening > root and unreachable supplied paths use the ledger path grammar [0.82ms] +(pass) linked composition parity hardening > ledger escapes decode before path grammar [0.82ms] +(pass) linked composition parity hardening > self and alias cycles compare normalized paths [0.38ms] +(pass) linked composition parity hardening > a cached subtree is charged at its deeper occurrence against the discovery ceiling [50.83ms] +(pass) linked composition parity hardening > existing edges precede ledger edges; embedded ledgers resolve from their bundle folder; output rebundles [1.74ms] +(pass) linked composition parity hardening > the source-file attribute bound counts normalized UTF-8 bytes [12.81ms] +(pass) linked composition parity hardening > lowered policies charge original path bytes before path grammar; invalid limits are refused first [0.34ms] +(pass) linked composition parity hardening > an abort inside the ledger scanner propagates the caller's reason [2.48ms] +(pass) linked composition parity hardening > an abort inside the scalar path sort propagates the caller's reason [2.36ms] +(pass) early source-file attribute bound and long-directory owners > an over-bound ledger edge is refused while resolving, before later refusals [0.59ms] +(pass) early source-file attribute bound and long-directory owners > the attribute bound counts normalized directory prefix bytes [0.56ms] +(pass) early source-file attribute bound and long-directory owners > long-directory owners resolve repeated sources once and refuse over-bound targets at the first edge [261.65ms] + +test/links.test.ts: +(pass) links() > basic reference resolves source, target, and existence [0.80ms] +(pass) links() > captures optional link text [0.04ms] +(pass) links() > present-but-empty link text is the empty string [0.02ms] +(pass) links() > multiple links in one body are returned left to right [0.02ms] +(pass) links() > links across planes follow source order [0.02ms] +(pass) links() > dangling reference reports targetExists false [0.02ms] +(pass) links() > decimal target matches a decimal plane z [0.02ms] +(pass) links() > non-finite and non-link sequences are ignored [0.01ms] +(pass) links() > signed and exponent targets parse as finite decimals [0.02ms] +(pass) links() > a document with no links returns an empty array [0.01ms] +(pass) links() > danglingLinks filters only missing targets [0.04ms] +(pass) links() > linkGraph collapses repeated source-target pairs [0.09ms] +(pass) links() > linkGraph keeps dangling edge status [0.04ms] + + 431 pass + 0 fail + 764396 expect() calls +Ran 431 tests across 10 files. [31.55s] + ✔ Step 4 done (33.639s) + ▶️ Running task: rust + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.19s + Finished `test` profile [unoptimized + debuginfo] target(s) in 0.10s + Running unittests src/lib.rs (target/debug/deps/threemd-3e8d3a72ef8b0b84) + +running 18 tests +test checksum::tests::check_value_matches_the_specification ... ok +test structured::tests::var_round_trips_at_every_size_boundary_and_rejects_v1_to_v3 ... ok +test structured::tests::number_forms_follow_the_table_and_decode_bit_exactly ... ok +test structured::tests::equivalence_is_rejected_only_for_canonically_equal_distinct_keys ... ok +test structured::tests::line_feed_bits_mark_exactly_the_line_feeds ... ok +test structured::tests::checked_chars_stop_at_a_failed_check_and_keep_the_error ... ok +test structured::tests::long_key_hashes_and_nfc_forms_check_cancellation_on_their_input ... ok +test structured::tests::every_cancellation_check_cancels_decode_and_encode_without_a_result ... ok +test structured::tests::phase_s_checks_cancellation_within_long_keys_and_axes ... ok +test checksum::tests::slicing_matches_the_bytewise_reference_at_every_alignment ... ok +test structured::tests::cancellation_reaches_long_scans_and_every_plane ... ok +test structured::tests::lowercase_test_agrees_with_to_lowercase ... ok +test structured::tests::w2_checks_cancellation_between_short_keys_and_within_long_keys ... ok +test structured::tests::phase_q_normalizes_each_key_once_in_the_2_0_writer_order ... ok +test structured::tests::equivalence_matches_brute_force_and_compares_forms_only_when_hashes_meet ... ok +test structured::tests::cancellation_reaches_the_crc_of_a_64_mib_input ... ok +test structured::tests::phase_q_runs_only_after_phase_l_bounds_every_directive ... ok +test structured::tests::long_key_nfc_test_agrees_with_is_nfc_and_checks_every_chunk ... ok + +test result: ok. 18 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 4.66s + + Running tests/conformance.rs (target/debug/deps/conformance-283cd1b2cb105be9) + +running 1 test +test conformance_vectors_pass ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.01s + + Running tests/editing.rs (target/debug/deps/editing-997e6fa6b85c2c5a) + +running 9 tests +test direct_btree_maps_reject_ambiguous_canonically_equivalent_keys ... ok +test operation_payload_and_final_document_policies_are_enforced ... ok +test adopted_entries_report_the_specific_graph_error_that_adoption_wraps ... ok +test all_document_operations_preserve_source_order_and_header_fields ... ok +test identity_adoption_is_explicit_and_scoped ... ok +test graph_revision_roundtrip_diagnostics_and_cancellation ... ok +test document_operation_failures_are_structured_and_do_not_mutate_input ... ok +test all_composition_operations_validate_the_final_graph_atomically ... ok +test graph_failures_validate_counts_identity_and_reference_existence ... ok + +test result: ok. 9 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.01s + + Running tests/extensions.rs (target/debug/deps/extensions-4eb0504670bb68cf) + +running 15 tests +test binary_header_fields_and_corruption_are_rejected ... ok +test bounded_diagnostics_preserve_real_parser_lines_and_legacy_ids ... ok +test graph_validates_unused_entries_cycles_and_resource_limits ... ok +test canonical_decimal_ties_use_nearest_even_shortest_spelling ... ok +test storage_resource_policies_and_faithful_value_validation ... ok +test exact_utf8_revision_reopen_and_forged_snapshot_validation ... ok +test original_extension_artifacts_and_lzfse_unavailability ... ok +test swift_unicode_key_order_and_source_collision_semantics_match ... ok +test composition_json_is_strict_and_rejects_decoded_duplicate_keys ... ok +test cancellation_propagates_without_publishing_values ... ok +test swift_numeric_vectors_match_exact_storage_spelling ... ok +test swift_document_and_composition_goldens_are_byte_identical ... ok +test swift_adoption_transactions_and_failures_match_semantics ... ok +test every_signed_power_of_two_and_ten_matches_the_shared_canonical_spelling ... ok +test a_document_past_the_old_ceiling_round_trips ... ok + +test result: ok. 15 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 9.43s + + Running tests/file_composition.rs (target/debug/deps/file_composition-82fdc3545091eafc) + +running 30 tests +test owner_directory_resolution_keeps_parent_dot_and_grammar_semantics ... ok +test outer_recognition_preserves_child_byte_and_line_policy_precedence_over_planes ... ok +test lowered_policy_charges_original_path_bytes_before_grammar_and_rejects_invalid_limits_first ... ok +test outer_profile_records_are_independent_of_child_record_policy ... ok +test over_bound_ledger_edge_is_refused_while_resolving_before_later_refusals ... ok +test ledger_is_strict_json_with_ascii_glyph_validation_before_duplicate_checks ... ok +test missing_files_and_file_cycles_include_ledgers_in_unused_bundle_entries ... ok +test attribute_bound_counts_normalized_directory_prefix_bytes ... ok +test final_depth_checks_include_cached_dependencies_and_cancelled_operations_are_atomic ... ok +test existing_edges_precede_ledger_edges_and_embedded_ledgers_resolve_from_their_bundle_folder ... ok +test disconnected_embedded_ledgers_use_actual_entry_depth_and_repeated_cached_files ... ok +test ledger_escapes_decode_before_path_grammar ... ok +test nested_relative_paths_keep_duplicate_basenames_and_use_scalar_order ... ok +test resolver_output_rebundles_with_opaque_glyph_and_source_file_attributes ... ok +test repeated_cached_files_validate_final_depth_and_missing_discovery_precedence ... ok +test refusals_follow_entry_id_then_glyph_discovery_order ... ok +test repeated_links_are_deterministic_and_preserve_the_ordinary_document ... ok +test self_and_alias_cycles_compare_normalized_paths ... ok +test unreachable_content_is_ignored_but_every_supplied_path_is_validated ... ok +test root_and_unreachable_supplied_paths_use_the_ledger_path_grammar ... ok +test supplied_and_resolved_policies_are_checked_before_returning_a_bundle ... ok +test binary_children_and_nested_bundles_preserve_unused_entries_and_reference_ids ... ok +test source_file_attribute_bound_counts_normalized_utf8_bytes ... ok +test discovery_ceiling_is_the_standard_maximum_depth ... ok +test fixed_file_discovery_ceiling_bounds_disconnected_chains ... ok +test long_owner_path_with_many_references_resolves_every_reference_in_its_directory ... ok +test cached_subtree_is_charged_at_its_deeper_occurrence_against_the_discovery_ceiling ... ok +test long_directory_owners_resolve_repeated_sources_once_and_refuse_over_bound_targets_early ... ok +test project_paths_have_explicit_rules_and_bounded_standalone_work ... ok +test cancellation_from_another_thread_during_resolution_returns_no_result ... ok + +test result: ok. 30 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 1.69s + + Running tests/interchange.rs (target/debug/deps/interchange-1ce7f8e1fb0daa3c) + +running 5 tests +test bounded_parse_keeps_limits_and_explicit_cancellation ... ok +test source_unicode_aliases_keep_first_spelling_and_last_value_in_both_parsers ... ok +test legacy_serializer_preserves_quoted_apostrophes_and_boundary_whitespace ... ok +test raw_and_bounded_parsers_share_foundation_horizontal_whitespace ... ok +test large_unique_plane_sets_and_numeric_duplicate_equality_are_preserved ... ok + +test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.46s + + Running tests/structured.rs (target/debug/deps/structured-e12e8226d3e976db) + +running 24 tests +test p1_to_p4_every_mutant_reports_the_shared_outcome ... ignored, 102,600 decodes; run with --release -- --ignored +test container_info_reports_raw_fields_without_validation ... ok +test unicode_skew_vectors_follow_this_toolchains_data ... ok +test payload_kind_dispatch_and_the_decoded_length_bound ... ok +test worked_examples_have_the_specified_bytes ... ok +test writer_cap_negative_zero_and_compression_follow_w1_to_w6 ... ok +test a_truncated_tail_never_carries_into_the_next_string_or_call ... ok +test compositions_accept_kind_1_and_2_envelopes_and_refuse_kind_3 ... ok +test text_container_writer_keeps_the_2_0_bytes_and_error_order ... ok +test new_types_are_send_and_sync_and_codecs_run_from_32_threads ... ok +test every_golden_is_reproduced_byte_for_byte_and_decodes_to_the_text_decode ... ok +test var_prefixes_at_size_boundaries_round_trip_through_bodies ... ok +test every_vector_reports_its_code_under_its_limits ... ok +test number_forms_round_trip_bit_exactly_and_spell_canonically ... ok +test g6_kind_2_sizes_match_sizes_json ... ok +test keys_are_written_in_byte_order_and_equivalent_spellings_are_rejected ... ok +test chunked_utf8_validation_agrees_with_whole_string_validation ... ok +test cancellation_returns_no_value_and_leaves_inputs_reusable ... ok +test p5_p6_writer_acceptance_equals_validate_under_standard_limits ... ok +test p5_p6_writer_acceptance_equals_validate_under_lowered_limits ... ok +test metrics_equal_the_canonical_text_on_every_example ... ok +test p1_to_p4_mutants_report_the_shared_outcomes ... ok +test segment_rules_agree_with_the_text_round_trip_on_random_bodies ... ok +test metrics_equal_the_canonical_text_on_generated_documents ... ok + +test result: ok. 23 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 6.91s + + Running tests/structured_memory.rs (target/debug/deps/structured_memory-4f6ad24055334ee6) + +running 1 test +test kind_2_decoding_stays_under_four_times_the_input ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 9.58s + + Running unittests examples/interchange.rs (target/debug/examples/interchange-3e1831aec2fdc659) + +running 9 tests +test tests::hex_is_exact_and_rejects_uppercase_or_odd_input ... ok +test tests::document_adapter_edits_and_rejects_stale_patch_for_both_file_formats ... ok +test tests::malformed_protocol_keys_numbers_and_depth_precede_source_count ... ok +test tests::supplied_file_adapter_emits_reopenable_composition_outputs ... ok +test tests::supplied_file_adapter_rejects_malformed_protocol_and_maps_core_errors ... ok +test tests::composition_adapter_preserves_references_and_binary_parity ... ok +test tests::file_limits_are_strict_shapes_with_library_validated_values ... ok +test tests::oversized_requests_are_consumed_and_responses_are_atomic ... ok +test tests::supplied_file_count_precedes_source_shape_validation_but_not_top_level_validation ... ok + +test result: ok. 9 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.10s + + Finished `test` profile [unoptimized + debuginfo] target(s) in 0.03s + Doc-tests threemd + +running 4 tests +test src/lib.rs - ParseError::code (line 178) ... ok +test src/lib.rs - axis (line 67) ... ok +test src/storage.rs - storage::DocumentContainerInfo (line 216) ... ok +test src/lib.rs - (line 12) ... ok + +test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 1.57s + + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.02s + ✔ Step 5 done (35.809s) + ▶️ Running task: interchange +[0/1] Planning build +Building for debugging... +[0/3] Write swift-version--58304C5D6DBC2206.txt +Build of product 'threemd-interchange' complete! (0.21s) +{"cases":569,"compression":"none; optional Apple LZFSE excluded","imports":17991,"pairCounts":{"Rust -> Rust":1999,"Rust -> Swift":1999,"Rust -> TypeScript-Node":1999,"Swift -> Rust":1999,"Swift -> Swift":1999,"Swift -> TypeScript-Node":1999,"TypeScript-Node -> Rust":1999,"TypeScript-Node -> Swift":1999,"TypeScript-Node -> TypeScript-Node":1999},"passed":true,"producerConsumerPairs":9,"schema":"3md-interchange-receipt-1"} +Interchange evidence: /var/folders/5k/616qy7sj28l0d53k4c6w_4x00000gn/T/3md-interchange-071A812B-699B-49C2-AE1B-52282BBC1E37 + ✔ Step 6 done (58.685s) + ▶️ Running task: element-bundle +Bundled 10 modules in 16ms + + three-md.js 48.84 KB (entry point) + +element bundle is current (48840 bytes, no storage code) + ✔ Step 7 done (96ms) + ▶️ Running task: editor +bun install v1.4.0 (34cbb9a40) + +Checked 183 installs across 192 packages (no changes) [87.00ms] +$ vscode-tmgrammar-test -g syntaxes/3md.tmLanguage.json -g syntaxes/3md-links.injection.json -g tests/grammars/markdown.tmLanguage.json "tests/*.3md" +grammar not found for "source.yaml" +grammar not found for "text.html.derivative" +grammar not found for "source.css" +grammar not found for "text.html.basic" +grammar not found for "source.ini" +grammar not found for "source.java" +grammar not found for "source.lua" +grammar not found for "source.makefile" +grammar not found for "source.perl" +grammar not found for "source.r" +grammar not found for "source.ruby" +grammar not found for "source.php" +grammar not found for "source.sql" +grammar not found for "source.asp.vb.net" +grammar not found for "text.xml" +grammar not found for "text.xml.xsl" +grammar not found for "source.batchfile" +grammar not found for "source.clojure" +grammar not found for "source.coffee" +grammar not found for "source.c" +grammar not found for "source.cpp" +grammar not found for "source.diff" +grammar not found for "source.dockerfile" +grammar not found for "text.git-commit" +grammar not found for "text.git-rebase" +grammar not found for "source.go" +grammar not found for "source.groovy" +grammar not found for "text.pug" +grammar not found for "source.ignore" +grammar not found for "source.js" +grammar not found for "source.js.regexp" +grammar not found for "source.json" +grammar not found for "source.json.comments" +grammar not found for "source.json.lines" +grammar not found for "source.css.less" +grammar not found for "source.objc" +grammar not found for "source.swift" +grammar not found for "source.css.scss" +grammar not found for "source.perl.6" +grammar not found for "source.powershell" +grammar not found for "source.python" +grammar not found for "source.julia" +grammar not found for "source.regexp.python" +grammar not found for "source.rust" +grammar not found for "source.scala" +grammar not found for "source.shell" +grammar not found for "source.ts" +grammar not found for "source.tsx" +grammar not found for "source.cs" +grammar not found for "source.fsharp" +grammar not found for "source.dart" +grammar not found for "text.html.handlebars" +grammar not found for "text.log" +grammar not found for "source.erlang" +grammar not found for "source.elixir" +grammar not found for "text.tex.latex" +grammar not found for "text.bibtex" +grammar not found for "source.twig" +grammar not found for "source.yang" +grammar not found for "source.abap" +grammar not found for "source.rst" +✓ tests/cross-plane-link.3md run successfuly. +✓ tests/frontmatter.3md run successfuly. +✓ tests/markdown-body.3md run successfuly. +✓ tests/plane-directive.3md run successfuly. + ✔ Step 8 done (500ms) +✅ Lane verify completed (8 steps in 3m 41.135s) +⊘ Skipped 3 unchanged spec(s) (use --force/--no-cache to re-validate all) + ℹ Cache: /Users/leif/Development/_CorvidLabs/3md-edit-preview/.specsync/hashes.json + + +specs/ThreeMDViewer/ThreeMDViewer.spec.md + ✓ Frontmatter valid + ✓ All source files exist + ✓ All required sections present + ✓ 20/20 exports documented + ✓ All dependency specs exist + +4 specs checked: 4 passed, 0 warning(s), 0 failed +File coverage: 55/55 (100%) +LOC coverage: 21185/21185 (100%) +augur: config: loaded ./.augur.toml +From https://github.com/CorvidLabs/3md + + 051c408...3340e6c refs/notes/attest -> refs/notes/attest (forced update) +trust range: origin/leif/viewer-draft-navigation..HEAD +== lifecycle == +== contract == +== risk == +== provenance == +== atlas: off (Atlas publication was not enabled during adoption) == +trust gate passed (progressive provenance) diff --git a/hi/tools.md b/hi/tools.md index 85631cef..5cfa87fb 100644 --- a/hi/tools.md +++ b/hi/tools.md @@ -29,7 +29,9 @@ I want the editor extension to highlight a text .3md file from a VSIX I build lo - **VIEWER-3** I can browse the text examples in the hosted gallery. Those cards stay text. In the viewer I can find every text example in the repository, open an uncompressed .3mdb, open a composition profile, or open a folder of linked files. The page shows the decoded text in the element. Apple LZFSE stays unavailable. - **VIEWER-4** I can rely on the element and the VS Code surface staying on text. - **VIEWER-5** I can scrub, drag, and step through the planes of a text document in the element. Parsing stays with @corvidlabs/threemd. -- **VIEWER-6** The viewer keeps files on the left. Edit, the plane preview, and Cubes share the panel beside them and switch, and Cubes shows first, inside the window. On a narrow window, Files and the document take turns. The page does not switch render modes and does not autoplay. The opening document is a fenced character grid drawn as complete, lit cubes on the GPU that I can orbit and zoom. Their translucent fill keeps the glyph color, visible edges outline the cells, and gold edges mark the selected Z slice without repainting it. The dark stage, colors, and axes match Sculpt.3md, a single cell looks like a full cube, and about 1400 cubes stay responsive. Clicking a cube picks its slice, and the status bar shows the line, the axis, and the cube count. The document title stays visible, controls leave room for the stage on my phone, and the slice row scrolls to keep my selection visible. I can fit the sculpture, zoom with buttons, and orbit with the keyboard. Insert tools belong in Edit, and exports and conversion tools are together under Document. A document without cubes offers Preview so I can keep reading. GitHub open shows when it is busy and lets me try again after an error. I can point it at a public GitHub repo, folder, or file, or at a file or folder on this computer. Search looks at every line and opens that plane. I can turn Markdown headings into planes, pack opened files into one text document, and download that document as uncompressed kind 2. The element stays a text renderer. +- **VIEWER-6** The viewer keeps files on the left. Edit, Slice, the plane preview, and Cubes share the panel beside them and switch, and Cubes shows first, inside the window. On a narrow window, Files and the document take turns. The page does not switch render modes and does not autoplay. The opening document is a fenced character grid drawn as complete, lit cubes on the GPU that I can orbit and zoom. Their translucent fill keeps the glyph color, visible edges outline the cells, and gold edges mark the selected Z slice without repainting it. The dark stage, colors, and axes match Sculpt.3md, a single cell looks like a full cube, and about 1400 cubes stay responsive. Clicking a cube picks its slice, and the status bar shows the line, the axis, and the cube count. The document title stays visible, controls leave room for the stage on my phone, and the slice row scrolls to keep my selection visible. I can rotate it through full turns in every direction, choose Pan to move it, Shift-drag or right-drag to pan, and use two fingers to move and pinch to zoom. I can fit the sculpture back in the window, zoom with buttons or scroll, and use arrow keys to orbit or Shift-arrows to pan. Insert tools belong in Edit, and exports and conversion tools are together under Document. A document without cubes offers Preview so I can keep reading. GitHub open shows when it is busy and lets me try again after an error. I can point it at a public GitHub repo, folder, or file, or at a file or folder on this computer. Switching files or documents inside an open keeps my edits, caret, and selected plane. Edited files are marked, and I can filter the file list and use the keyboard to choose one. Opening a file or search result on my phone brings the document into view. Search and packing use my current edits. A failed open keeps my current files. Search looks at every line and opens that plane. I can turn Markdown headings into planes, pack opened files into one text document, and download that document as uncompressed kind 2. The element stays a text renderer. +- **VIEWER-7** I can choose X, Y or Z on the rotation sphere, drag around that axis, enter an exact degree step, and nudge the camera or pan by a number of cells. Free returns to ordinary orbit. These movements match Sculpt and keep my sculpture unchanged. +- **VIEWER-8** I can edit a rectangular sculpture in Slice with thumbnails, a large character grid, Draw, Erase and Fill, the Sculpt palette, sizes 1, 3 and 5, previous-slice ghosts, keyboard cells, grid zoom, and a live 3D reference. One drag is one undo step. Source edits share that history, and it follows my file or linked document when I switch. Only the cells I paint change; other source bytes remain intact. Unsupported documents explain how I can keep working in Edit. - **EDITOR-1** I can get syntax highlighting for a text .3md file in the editor extension, including frontmatter, @plane directives, cross-plane links, and Markdown plane bodies. - **EDITOR-2** I can build the extension locally as a VSIX. It is not published to a marketplace. - **EDITOR-3** The extension does not become a second parser with different rules. diff --git a/specs/ThreeMDViewer/ThreeMDViewer.spec.md b/specs/ThreeMDViewer/ThreeMDViewer.spec.md index 8c362502..483d7d50 100644 --- a/specs/ThreeMDViewer/ThreeMDViewer.spec.md +++ b/specs/ThreeMDViewer/ThreeMDViewer.spec.md @@ -1,6 +1,6 @@ --- module: ThreeMDViewer -version: 8 +version: 18 status: active files: - web/viewer.html @@ -23,7 +23,7 @@ depends_on: ## Purpose -ThreeMDViewer is the hosted and local viewer page. Files stay on the left. Edit, the plane preview, and Cubes share the panel beside them. One is visible at a time, and Cubes is the default, inside the window. The opening document is a small sculpture. Below 900px, Files and the document take turns. The page does not offer a render-mode switch and does not autoplay. Preview stays on one plane. Cubes draws a fenced character grid with Sculpt-style lit, translucent glyph fill and visible edges. Gold edges mark the selected Z slice without repainting its fill. The page opens a public GitHub repo, folder, or file, or a file or folder from this computer. Search reads every opened line and opens that plane. Markdown headings become planes. Opened files pack into one text document, and that document downloads as uncompressed kind 2. +ThreeMDViewer is the hosted and local viewer page. Files stay on the left. Edit, Slice, the plane preview, and Cubes share the panel beside them. One is visible at a time, and Cubes is the default, inside the window. The opening document is a small sculpture. Below 900px, Files and the document take turns. The page does not offer a render-mode switch and does not autoplay. Preview stays on one plane. Cubes draws a fenced character grid with Sculpt-style lit, translucent glyph fill and visible edges. Gold edges mark the selected Z slice without repainting its fill. The page opens a public GitHub repo, folder, or file, or a file or folder from this computer. Search reads every opened line and opens that plane. Markdown headings become planes. Opened files pack into one text document, and that document downloads as uncompressed kind 2. The `` element stays a text renderer. Decode, composition, linked folders, GitHub fetch, search, sections, pack, and kind 2 download belong to this page. The compact workspace gives the stage room on desktop and phone screens. The document title stays visible, insert tools appear in Edit, and the Document disclosure holds export and conversion actions. Fit, zoom buttons, keyboard camera control, and a scrolling slice row make the cube stage usable without a mouse. A document without a grid offers Preview. The ThreeMD library stays free of filesystem and network I/O. Human intent for this page is VIEWER-6 in `hi/tools.md`. @@ -33,7 +33,7 @@ The `` element stays a text renderer. Decode, composition, linked fold | Name | Description | |------|-------------| -| `viewer.html` | Files on the left. Edit, Preview, and Cubes share one panel and switch. Preview is the `` element held on one plane. Cubes is a page WebGL2 stage. The point field takes a public GitHub locator. Open file, open folder, and drop read local bytes. | +| `viewer.html` | Files on the left. Edit, Preview, Slice, and Cubes share one panel and switch. Preview is the `` element held on one plane. Cubes is a page WebGL2 stage. The point field takes a public GitHub locator. Open file, open folder, and drop read local bytes. | | `open-document.js` | The browser bundle built from `web/open-document.ts`. The page imports it. The element bundle stays `web/assets/three-md.js`. | ### Exported functions @@ -68,15 +68,29 @@ The `` element stays a text renderer. Decode, composition, linked fold ## Invariants -1. Files stay on the left. Edit, the plane preview, and Cubes share one panel, one is visible at a time, and Cubes is the default. The opening document is a small sculpture, and its cubes are inside the window. Below 900px, Files and the document take turns. The page does not switch render modes and does not autoplay. Choosing Preview renders the live plane view and holds it on one plane. Choosing Cubes draws a fenced character grid as lit cubes on a dark GPU stage. Web fill uses 0.5 opacity for visible faces under browser blending, compared with Sculpt’s native 0.35; glyph edges use 0.4, and selected edges use gold rgb(1, 0.79, 0.44) at 0.8. The background is rgb(0.065, 0.085, 0.10). All six cube faces are wound outward, back faces are culled, and faces shared with occupied neighbors are suppressed as in Sculpt. The cell scale is 0.98. X is the column, Y is the row with row 0 toward the top, and Z is the plane index. Orbit, zoom, and selection update camera or selection uniforms with one instanced draw, without scanning the document or uploading geometry. Click picking intersects full cube bounds and chooses the nearest hit. The camera follows Sculpt’s distance and scale with a fit margin that keeps complete cubes inside the pane. The status bar shows the caret, the axis, and the cube count. The element stays a text renderer. +1. Files stay on the left. Edit, Slice, the plane preview, and Cubes share one panel, one is visible at a time, and Cubes is the default. The opening document is a small sculpture, and its cubes are inside the window. Below 900px, Files and the document take turns. The page does not switch render modes and does not autoplay. Choosing Preview renders the live plane view and holds it on one plane. Choosing Cubes draws a fenced character grid as lit cubes on a dark GPU stage. Web fill uses 0.5 opacity for visible faces under browser blending, compared with Sculpt’s native 0.35; glyph edges use 0.4, and selected edges use gold rgb(1, 0.79, 0.44) at 0.8. The background is rgb(0.065, 0.085, 0.10). All six cube faces are wound outward, back faces are culled, and faces shared with occupied neighbors are suppressed as in Sculpt. The cell scale is 0.98. X is the column, Y is the row with row 0 toward the top, and Z is the plane index. Orbit, zoom, and selection update camera or selection uniforms with one instanced draw, without scanning the document or uploading geometry. Click picking intersects full cube bounds and chooses the nearest hit. The camera follows Sculpt’s distance and scale with a fit margin that keeps complete cubes inside the pane. The status bar shows the caret, the axis, and the cube count. The element stays a text renderer. 2. A public GitHub locator is accepted only when the host is `github.com`, `www.github.com`, or `raw.githubusercontent.com`, or when the input is an `owner/repo` name. A host string elsewhere in the URL is not a match. 3. A public load skips `node_modules`, keeps at most 400 files, and skips a file larger than 1.5 MB. The line index keeps at most 12,000 rows. 4. Search opens the plane for the chosen line. 5. Markdown headings become planes. Opened files pack into one text document. Kind 2 download writes uncompressed kind 2. 6. Apple LZFSE is refused. The element stays a text renderer. The library stays free of filesystem and network I/O. -7. The workspace SHALL keep infrequent export and conversion actions in the Document disclosure, show insert tools only in Edit, and show the document title in every view. Tabs and the single-row plane outline SHALL provide one tab stop per group, with arrow, Home, and End navigation. Fit SHALL restore yaw 0.6, pitch 0.35, and zoom 1 without changing source or the selected slice. Camera buttons and the focused canvas SHALL support bounded zoom, and arrow keys SHALL orbit the focused canvas. Camera controls SHALL sit below the drawing without covering cubes. A document without a cube grid and an unavailable WebGL2 context SHALL offer Preview while preserving the source. The Document disclosure closes after an action, outside click, or Escape; Escape returns focus to its summary. The source download shortcut keeps focus in Edit. GitHub open exposes a busy state, prevents duplicate submits, and recovers its controls even on failure. Zoom is bounded from 0.45 to 3.2. Camera controls use the canvas dimensions for framing and occupy a separate strip below it. +7. The workspace SHALL keep infrequent export and conversion actions in the Document disclosure, show insert tools only in Edit, and show the document title in every view. Tabs and the single-row plane outline SHALL provide one tab stop per group, with arrow, Home, and End navigation. Orbit SHALL rotate through full horizontal and vertical turns with a continuous camera basis at the poles. Pan mode, Shift-drag, and middle/right-drag SHALL move the view in screen space. Shift-arrow keys SHALL pan the focused canvas. Two-finger touch gestures SHALL pan and pinch to zoom. Wheel zoom SHALL respond proportionally to the gesture. Fit SHALL restore yaw 0.6, pitch 0.35, zoom 1, and zero pan without changing source or the selected slice. Camera buttons and the focused canvas SHALL support bounded zoom, and arrow keys SHALL orbit the focused canvas. Camera controls SHALL sit below the drawing without covering cubes. A document without a cube grid and an unavailable WebGL2 context SHALL offer Preview while preserving the source. The Document disclosure closes after an action, outside click, or Escape; Escape returns focus to its summary. The source download shortcut keeps focus in Edit. GitHub open exposes a busy state, prevents duplicate submits, and recovers its controls even on failure. Zoom is bounded from 0.5 to 2. Primary camera controls use the canvas dimensions for framing and occupy a separate strip below it. REQ-ThreeMDViewer-007 adds the corner axis sphere and precise movement disclosure. -The cube input keeps at most 12 distinct non-space characters, at most 64 columns and 64 rows per plane, and at most 4000 occupied cells. Space, dot, and tab are empty. Cube painting and erasing into source, 256 cubed volumes, sparse worlds, OBJ export, and changes to Sculpt are outside this pass. The page does not rebuild the element or open-document bundles. +8. File and composition-entry navigation SHALL preserve current edits, caret, and selected plane within the open collection. Edited documents SHALL be identified in every view. Opened files SHALL support filtering and keyboard navigation. Choosing a file or search result on a narrow screen SHALL reveal the document. Search and packing SHALL use current drafts. Failed local opens SHALL preserve the current collection. Explicit document navigation SHALL replace a stale source query with the current document hash. Drafts are in memory for the current collection. Download exports the current document and does not write the original file or clear its Edited marker. Opening another collection or refreshing clears these session drafts. Linked entries share their draft with the matching source file. Composition downloads remain exports of the selected document; edits do not rewrite the composition profile. + +The cube input keeps at most 12 distinct non-space characters, at most 64 columns and 64 rows per plane, and at most 4000 occupied cells. Space, dot, and tab are empty. Cube painting and erasing into source, 256 cubed volumes, sparse worlds, OBJ export, are outside this viewer pass. Native volume camera parity is a separately approved change in the same PR. The page does not rebuild the element or open-document bundles. + +### REQ-ThreeMDViewer-006 + +The browser and Sculpt volume camera SHALL expose the same full-turn orbit, screen-space pan, bounded proportional zoom, default Fit pose and camera-correct nearest-cube picking, with matched camera basis and documented coordinate conversion. + +Acceptance Criteria: + +- Both the web cube viewer and Sculpt volume canvas orbit through complete horizontal and vertical turns, using the same continuous camera basis at the poles and upside down. Drag sensitivity is 0.008 radians per point; web yaw is the negative of native yaw to account for its coordinate convention. +- Both volume cameras support screen-space pan without changing the document, mesh, slice, paint history or geometry revision. Native Shift-left, middle and right dragging pan; an explicit Pan button works in Orbit. Native scroll zoom and trackpad magnification respond proportionally. Browser Pan, modified mouse dragging and two-finger pan/pinch provide the equivalent controls. +- Zoom stays between 0.5 and 2 in both views. Fit restores the default matched pose (native yaw -0.6 / web yaw 0.6, pitch 0.35), zoom 1 and zero pan. The native CPU cube/ASCII projection, live GPU camera and picking all honor the same orbit and pan. +- Shared asymmetric fixture receipts compare camera bases and screen projections across native and browser views, including pole crossings, upside-down and panned cameras. Picking chooses the nearest cube after those movements and camera changes reuse geometry. Mac native regressions and browser Chromium/WebKit regressions cover the controls. +- Keep native painting, stroke freezing, CPU/export budgets and the browser one-draw cube mesh, colors, axes and bounded grid behavior. Keep app and viewer specifications and human intent synchronized. Sparse-world Explore, storage formats, parser APIs, package releases and trust policies remain outside this camera change. ## Behavioral Examples @@ -142,3 +156,19 @@ The cube input keeps at most 12 distinct non-space characters, at most 64 column | 2026-10-10 | ThreeMDViewer change | Draw every cube face. Each cell is a solid cube. | | 2026-10-09 | agent:codex | Match Sculpt fill, glyph edges, gold selected-slice edges, background, document axes, and camera framing; retain one instanced draw and geometry reuse. | | 2026-10-09 | agent:codex | Compact the workspace, group document actions, add Fit and accessible camera/slice controls, and clarify empty and loading states under Leif’s request to continue improving UI and UX. The layout definition remains an unapproved draft. | +| 2026-10-10 | agent:codex | Preserve file and composition drafts across navigation, expose edited state, and improve file filtering, keyboard navigation, mobile reveal, and current-document URLs in a follow-up PR after PR 92 merged. The definition remains an unapproved draft. | +| 2026-10-10 | agent:codex | Preserve the slice across editor refresh, sort file paths for consistent keyboard navigation, and compact small-phone spacing. Leif approved the final scope; verification, acceptance, and archiving are pending. | +| 2026-10-10 | SpecSync | put-edit-and-preview-in-the-same-viewer-panel-and-toggle-them-like-github-files-stay-on-the-left-edit-shows-first-below: Put Edit and Preview in the same viewer panel and toggle them like GitHub. Files stay on the left. Edit shows first. Below 900px, Files and the document take turns, and the document panel still switches Edit and Preview. | +| 2026-10-10 | SpecSync | keep-sculpt-and-web-cube-cameras-in-parity-with-unrestricted-orbit-and-screen-space-pan: Keep Sculpt and web cube cameras in parity with unrestricted orbit and screen-space pan | +| 2026-10-10 | SpecSync | bring-sculpt-slice-editing-to-the-browser-with-a-visual-grid-drawing-tools-undo-and-live-3d-reference: Bring Sculpt slice editing to the browser with a visual grid, drawing tools, undo and live 3D reference | +| 2026-10-10 | SpecSync | add-matching-x-y-z-axis-rotation-gizmos-and-precise-camera-steps-to-sculpt-and-the-viewer: Add matching X Y Z axis rotation gizmos and precise camera steps to Sculpt and the viewer | +| 2026-10-10 | agent:codex | Repair the frozen small drawable being stretched across Cubes after Slice or phone layout; update only changed bitmap dimensions and retain the context, geometry and camera. | +| 2026-10-10 | SpecSync | repair-blurry-cubes-and-slice-canvases-after-view-and-display-size-changes-while-retaining-the-webgl-context-and-camera: Repair blurry Cubes and Slice canvases after view and display-size changes while retaining the WebGL context and camera parity | + +## Slice and precise camera parity + +Slice uses the native character palette `#@*+ox:=-`, Draw/Erase square brushes 1/3/5, integer gap-free strokes and four-neighbor fill confined to the selected plane. Exact raw source offsets preserve all untouched bytes, including CRLF and prose. Eligibility requires complete, common rectangular grids, at most 64 by 64 cells, 256 planes, 4000 occupied cells and 1.5 MiB source. Empty grids can be edited. Rejected over-budget strokes restore the entire transaction. + +History is shared with source typing and attached to each draft state, including linked entries. It retains at most 100 snapshots per draft and 8 MiB across the current collection; no-op strokes add no entry. Pointer up, cancellation, lost capture and navigation finish the accepted transaction. Thumbnails, one-based coordinates, keyboard arrows/Space, explicit cell Apply, previous-slice ghosts and Fit/2x/4x/8x/16x grid zoom use the same state. The live reference reparents the existing WebGL canvas rather than allocating another context; 2D editing remains available without WebGL. Phone layouts scroll inside Slice with full-size touch targets. + +The volume camera shows colored X/Y/Z rings and Free/X/Y/Z constraints. A normalized quaternion composes document-axis rotation with continuous free orbit. Numerical rotation defaults to 15 degrees and pan to 0.25 cells, accepting only finite positive steps. Fit restores the default orientation and zero pan. Shared independent matrix-reference cases cover three-axis projection and picking; shared edit cases run through actual Sculpt workspaces and browser pointer gestures. diff --git a/specs/ThreeMDViewer/context.md b/specs/ThreeMDViewer/context.md index 6056b5e3..5f35cefd 100644 --- a/specs/ThreeMDViewer/context.md +++ b/specs/ThreeMDViewer/context.md @@ -7,7 +7,7 @@ spec: ThreeMDViewer.spec.md - The page is its own module. `ThreeMD` stays the library. `ThreeMDElement` stays the text renderer. `ThreeMDCLI` stays the command. - GitHub hosts are compared with `URL.hostname`. A substring match is not enough. - The page fetches. The library stays free of filesystem and network I/O. -- Edit, Preview, and Cubes share one panel. Files stay on the left. Cubes is the default. Below 900px, Files and the document take turns. Choosing Preview calls `render` so the element measures the panel. The element still receives source while Edit is showing. +- Edit, Preview, Slice, and Cubes share one panel. Files stay on the left. Cubes is the default. Below 900px, Files and the document take turns. Choosing Preview calls `render` so the element measures the panel. The element still receives source while Edit is showing. ## Files to Read First @@ -19,8 +19,8 @@ spec: ThreeMDViewer.spec.md ## Current Status -- PR 91 is on main. PR 92 shares Edit, Preview, and Cubes in one panel and adds Sculpt cube-stage parity plus the continuing UI and UX improvements. -- Definition approval for this layout change is not recorded yet. +- PR 91 is on main. PR 92 shares Edit, Preview, Slice, and Cubes in one panel and adds Sculpt cube-stage parity plus the continuing UI and UX improvements. +- Leif approved the final viewer scope on 2026-10-10 and authorized acceptance and archiving after successful verification. Current verification passed and supported scoped review/finalization archived both viewer and camera records for PR 93; Leif retains merge authority. ## Notes @@ -38,5 +38,27 @@ spec: ThreeMDViewer.spec.md - Sculpt was run locally and its Character orb compared in both live stages. Native and web screenshots are in `docs/evidence/viewer-sculpt-parity/`. This is agent visual verification, not Leif’s review or definition approval. - Leif directly requested continued UI and UX work on 2026-10-09. This covers the compact workspace and controls in the existing page scope; it does not record definition approval, human diff review, or a merge. -- The canvas occupies the space above the camera strip. Framing and picking use its actual client dimensions; changing view or viewport still does not resize an established WebGL bitmap. +- The canvas occupies the space above the camera strip. Framing and picking use its actual client dimensions; changing view or viewport updates the drawable to the displayed pane and capped device pixel ratio while retaining the established WebGL context and geometry. - Export and conversion actions use a native disclosure with natural button focus, Escape dismissal, and outside-click closure. The source download shortcut preserves editor focus. + +- PR 92 has merged. Leif requested a new fix PR for file navigation. Draft state belongs to the page and survives file and composition-entry switches within the current collection. It is not browser storage or a write to the source files. That follow-up was kept in draft until Leif's explicit 2026-10-10 scope approval. + +- File activation focuses the document before restoring its caret. Chromium clears a restored selection when the editor remains blurred; focus-first restoration passes in both engines. Packing uses the current draft of the active document for each opened file, without rewriting composition profiles. The line index is reused until a draft or the collection changes. + +- Linux WebKit exposed a delayed-render slice reset, native directory enumeration differences, and insufficient drawing space on a 320 by 740 phone. Source refresh now restores the selected slice, the file list sorts paths for consistent keyboard navigation, and narrow-screen padding leaves more stage space. Current macOS viewer and Linux UI runs passed; existing phone and focus assertions remain, with an added wait across the editor debounce. + +## Current camera parity + +Leif explicitly approved full native/browser camera parity and verified closure on 2026-10-10. Both volume canvases now use full yaw/pitch turns, continuous pole bases, session-only screen pan, zoom 0.5...2 and the matched default Fit pose. Native interactive cameras use complete-volume framing while default utility cameras retain historical preview scale. Shared projection/picking fixtures and current screenshots are in `docs/evidence/viewer-camera/`. Leif subsequently approved the X/Y/Z sphere, precise steps and browser Slice definition together; implementation and current verification are recorded in `docs/evidence/viewer-slice/`. + +## Slice and precise camera parity + +Slice uses the native character palette `#@*+ox:=-`, Draw/Erase square brushes 1/3/5, integer gap-free strokes and four-neighbor fill confined to the selected plane. Exact raw source offsets preserve all untouched bytes, including CRLF and prose. Eligibility requires complete, common rectangular grids, at most 64 by 64 cells, 256 planes, 4000 occupied cells and 1.5 MiB source. Empty grids can be edited. Rejected over-budget strokes restore the entire transaction. + +History is shared with source typing and attached to each draft state, including linked entries. It retains at most 100 snapshots per draft and 8 MiB across the current collection; no-op strokes add no entry. Pointer up, cancellation, lost capture and navigation finish the accepted transaction. Thumbnails, one-based coordinates, keyboard arrows/Space, explicit cell Apply, previous-slice ghosts and Fit/2x/4x/8x/16x grid zoom use the same state. The live reference reparents the existing WebGL canvas rather than allocating another context; 2D editing remains available without WebGL. Phone layouts scroll inside Slice with full-size touch targets. + +The volume camera shows colored X/Y/Z rings and Free/X/Y/Z constraints. A normalized quaternion composes document-axis rotation with continuous free orbit. Numerical rotation defaults to 15 degrees and pan to 0.25 cells, accepting only finite positive steps. Fit restores the default orientation and zero pan. Shared independent matrix-reference cases cover three-axis projection and picking; shared edit cases run through actual Sculpt workspaces and browser pointer gestures. + +## Shared 3D drawable resolution repair + +The previous frozen bitmap could initialize at 368x322 in a small view and stretch to 1099x911 after expansion. Drawable dimensions now follow the visible pane at up to 2x pixel density with the existing proportional 2048-edge cap. Only changed dimensions are assigned; context, GPU resources, pose and source remain installed. Chromium/WebKit density 1/2 regressions exercise phone, reference, full stage and capped large sizes. diff --git a/specs/ThreeMDViewer/requirements.md b/specs/ThreeMDViewer/requirements.md index 9350b19b..846e4912 100644 --- a/specs/ThreeMDViewer/requirements.md +++ b/specs/ThreeMDViewer/requirements.md @@ -12,8 +12,8 @@ spec: ThreeMDViewer.spec.md - **REQ-ThreeMDViewer-001** The viewer page SHALL present files, source, and the live plane view. It SHALL open a public GitHub repo, folder, or file, or a file or folder from this computer. Search SHALL read every opened line and open that plane. Markdown headings SHALL become planes. Opened files SHALL pack into one text document, and that document SHALL download as uncompressed kind 2. The `` element SHALL stay a text renderer. - **REQ-ThreeMDViewer-002** The page SHALL accept a GitHub locator only when the host is `github.com`, `www.github.com`, or `raw.githubusercontent.com`, or when the input is an `owner/repo` name. It SHALL NOT treat those names as a match when they appear only as a substring. A public load SHALL skip `node_modules`, SHALL keep at most 400 files, and SHALL skip a file larger than 1.5 MB. The line index SHALL keep at most 12,000 rows. Apple LZFSE SHALL be refused. The ThreeMD library SHALL stay free of filesystem and network I/O. -- **REQ-ThreeMDViewer-003** The viewer page SHALL show Edit, Preview, and Cubes in one panel. Exactly one of them SHALL be visible. Cubes SHALL be the default, and the opening document SHALL be a small sculpture whose cubes are inside the window. Files SHALL stay in the column beside that panel. Below 900px, Files and the document SHALL take turns, and the document panel SHALL still switch Edit, Preview, and Cubes. Choosing Preview SHALL render the live plane view. The workspace SHALL keep infrequent export and conversion actions in the Document disclosure, show insert tools only in Edit, and show the document title in every view. Tabs and the single-row plane outline SHALL provide one tab stop per group, with arrow, Home, and End navigation. -- **REQ-ThreeMDViewer-004** The viewer page SHALL NOT offer a render-mode switch and SHALL NOT autoplay. Preview SHALL stay on one plane. Cubes SHALL draw complete, nearly cell-sized cubes with WebGL2, lit glyph-colored fill at 0.5 opacity and visible glyph-colored edges. The selected Z slice SHALL have gold edges at 0.8 opacity while retaining its glyph fill. The background SHALL be rgb(0.065, 0.085, 0.10). X SHALL be the column, Y the text row with row 0 toward the top, and Z the plane index. Orbit, zoom, and slice selection SHALL reuse the installed geometry. Each redraw SHALL use one instanced draw. Fit SHALL restore yaw 0.6, pitch 0.35, and zoom 1 without changing source or the selected slice. Camera buttons and the focused canvas SHALL support bounded zoom, and arrow keys SHALL orbit the focused canvas. Camera controls SHALL sit below the drawing without covering cubes. A document without a cube grid and an unavailable WebGL2 context SHALL offer Preview while preserving the source. The element bundle SHALL stay a text renderer. +- **REQ-ThreeMDViewer-003** The viewer page SHALL show Edit, Preview, Cubes, and Slice in one panel. Exactly one main view SHALL be visible; Slice SHALL include a live 3D reference within its workspace. Cubes SHALL be the default, and the opening document SHALL be a small sculpture whose cubes are inside the window. Files SHALL stay in the column beside that panel. Below 900px, Files and the document SHALL take turns, and the document panel SHALL still switch Edit, Preview, Cubes, and Slice. Choosing Preview SHALL render the live plane view. The workspace SHALL keep infrequent export and conversion actions in the Document disclosure, show insert tools only in Edit, and show the document title in every view. Tabs and the single-row plane outline SHALL provide one tab stop per group, with arrow, Home, and End navigation. File and composition-entry navigation SHALL preserve current edits, caret, and selected plane within the open collection. Edited documents SHALL be identified in every view. Opened files SHALL support filtering and keyboard navigation. Choosing a file or search result on a narrow screen SHALL reveal the document. Search and packing SHALL use current drafts. Failed local opens SHALL preserve the current collection. Explicit document navigation SHALL replace a stale source query with the current document hash. The Slice workspace SHALL preserve the current selected plane, camera and source when entering or leaving the view. +- **REQ-ThreeMDViewer-004** The viewer page SHALL NOT offer a render-mode switch and SHALL NOT autoplay. Preview SHALL stay on one plane. Cubes SHALL draw complete, nearly cell-sized cubes with WebGL2, lit glyph-colored fill at 0.5 opacity and visible glyph-colored edges. The selected Z slice SHALL have gold edges at 0.8 opacity while retaining its glyph fill. The background SHALL be rgb(0.065, 0.085, 0.10). X SHALL be the column, Y the text row with row 0 toward the top, and Z the plane index. Orbit, zoom, and slice selection SHALL reuse the installed geometry. Each redraw SHALL use one instanced draw. Orbit SHALL rotate through full horizontal and vertical turns with a continuous camera basis at the poles. Pan mode, Shift-drag, and middle/right-drag SHALL move the view in screen space. Shift-arrow keys SHALL pan the focused canvas. Two-finger touch gestures SHALL pan and pinch to zoom. Wheel zoom SHALL respond proportionally to the gesture. Fit SHALL restore yaw 0.6, pitch 0.35, zoom 1, and zero pan without changing source or the selected slice. Camera buttons and the focused canvas SHALL support bounded zoom, and arrow keys SHALL orbit the focused canvas. Camera controls SHALL sit below the drawing without covering cubes. A document without a cube grid and an unavailable WebGL2 context SHALL offer Preview while preserving the source. The element bundle SHALL stay a text renderer. ## Constraints @@ -24,7 +24,7 @@ spec: ThreeMDViewer.spec.md ## Out of Scope - Parser, CLI, and element behavior. -- Cube painting or erasing into source, 256 cubed volumes, sparse worlds, OBJ export, and Sculpt app changes. +- Browser 3D cube painting, structural slice actions, volume resizing, 256 cubed volumes, sparse worlds and OBJ export. Sculpt changes are limited to the approved volume camera parity scope. - Gallery cards, which stay the curated text set. - Private GitHub repos, remote folder indexes beyond the public git tree, and Apple LZFSE. @@ -48,17 +48,16 @@ Acceptance Criteria: ### REQ-ThreeMDViewer-003 -The viewer page SHALL show Edit, Preview, and Cubes in one panel. Exactly one of them SHALL be visible. Cubes SHALL be the default, and the opening document SHALL be a small sculpture whose cubes are inside the window. Files SHALL stay in the column beside that panel. Below 900px, Files and the document SHALL take turns, and the document panel SHALL still switch Edit, Preview, and Cubes. Choosing Preview SHALL render the live plane view. The workspace SHALL keep infrequent export and conversion actions in the Document disclosure, show insert tools only in Edit, and show the document title in every view. Tabs and the single-row plane outline SHALL provide one tab stop per group, with arrow, Home, and End navigation. +The viewer page SHALL show Edit, Preview, Cubes, and Slice in one panel. Exactly one main view SHALL be visible; Slice SHALL include a live 3D reference within its workspace. Cubes SHALL be the default, and the opening document SHALL be a small sculpture whose cubes are inside the window. Files SHALL stay in the column beside that panel. Below 900px, Files and the document SHALL take turns, and the document panel SHALL still switch Edit, Preview, Cubes, and Slice. Choosing Preview SHALL render the live plane view. The workspace SHALL keep infrequent export and conversion actions in the Document disclosure, show insert tools only in Edit, and show the document title in every view. Tabs and the single-row plane outline SHALL provide one tab stop per group, with arrow, Home, and End navigation. File and composition-entry navigation SHALL preserve current edits, caret, and selected plane within the open collection. Edited documents SHALL be identified in every view. Opened files SHALL support filtering and keyboard navigation. Choosing a file or search result on a narrow screen SHALL reveal the document. Search and packing SHALL use current drafts. Failed local opens SHALL preserve the current collection. Explicit document navigation SHALL replace a stale source query with the current document hash. The Slice workspace SHALL preserve the current selected plane, camera and source when entering or leaving the view. Acceptance Criteria: -- At a desktop width, files stay visible. Cubes shows first, and the lit cubes are inside the window. Edit shows the editor and hides the cubes. Preview shows the live plane view and hides the editor. -- At 800px, Files and the document take turns. The document panel still switches Edit, Preview, and Cubes. -- Evidence is VIEWER-6 and the layout tests in `uitests/viewer.spec.mjs`. +- Existing default Cubes, Files navigation and Edit/Preview behavior remain; Slice is the additional main workspace and retains current selection, camera and draft. +- Existing draft, composition, phone and disclosure checks continue to pass alongside Slice tests. ### REQ-ThreeMDViewer-004 -The viewer page SHALL NOT offer a render-mode switch and SHALL NOT autoplay. Preview SHALL stay on one plane. Cubes SHALL draw complete, nearly cell-sized cubes with WebGL2, lit glyph-colored fill at 0.5 opacity and visible glyph-colored edges. The selected Z slice SHALL have gold edges at 0.8 opacity while retaining its glyph fill. The background SHALL be rgb(0.065, 0.085, 0.10). X SHALL be the column, Y the text row with row 0 toward the top, and Z the plane index. Orbit, zoom, and slice selection SHALL reuse the installed geometry. Each redraw SHALL use one instanced draw. Fit SHALL restore yaw 0.6, pitch 0.35, and zoom 1 without changing source or the selected slice. Camera buttons and the focused canvas SHALL support bounded zoom, and arrow keys SHALL orbit the focused canvas. Camera controls SHALL sit below the drawing without covering cubes. A document without a cube grid and an unavailable WebGL2 context SHALL offer Preview while preserving the source. The element bundle SHALL stay a text renderer. +The viewer page SHALL NOT offer a render-mode switch and SHALL NOT autoplay. Preview SHALL stay on one plane. Cubes SHALL draw complete, nearly cell-sized cubes with WebGL2, lit glyph-colored fill at 0.5 opacity and visible glyph-colored edges. The selected Z slice SHALL have gold edges at 0.8 opacity while retaining its glyph fill. The background SHALL be rgb(0.065, 0.085, 0.10). X SHALL be the column, Y the text row with row 0 toward the top, and Z the plane index. Orbit, zoom, and slice selection SHALL reuse the installed geometry. Each redraw SHALL use one instanced draw. Orbit SHALL rotate through full horizontal and vertical turns with a continuous camera basis at the poles. Pan mode, Shift-drag, and middle/right-drag SHALL move the view in screen space. Shift-arrow keys SHALL pan the focused canvas. Two-finger touch gestures SHALL pan and pinch to zoom. Wheel zoom SHALL respond proportionally to the gesture. Fit SHALL restore yaw 0.6, pitch 0.35, zoom 1, and zero pan without changing source or the selected slice. Camera buttons and the focused canvas SHALL support bounded zoom, and arrow keys SHALL orbit the focused canvas. Camera controls SHALL sit below the drawing without covering cubes. A document without a cube grid and an unavailable WebGL2 context SHALL offer Preview while preserving the source. The element bundle SHALL stay a text renderer. Acceptance Criteria: @@ -66,4 +65,44 @@ Acceptance Criteria: - A fenced grid draws on WebGL2, including about 1400 cubes. A single cell has filled faces from every side. Selection changes edge color while the face interior keeps its glyph color. Camera, zoom, and selection redraw without geometry uploads. Click picking selects the nearest visible cube’s Z slice. - X is the column, Y is the text row with row 0 toward the top, and Z is the plane index. Space, dot, and tab are empty. Keep the 64 by 64 per-plane and 4000-cell caps. - Evidence is VIEWER-6 and the cube tests in `uitests/viewer.spec.mjs`. +- The same 3D context and geometry remain installed when moving between Cubes and the Slice reference or changing display size. The drawable follows the visible pane size and device pixel ratio, bounded to 2x and a proportional 2048-pixel edge cap; unchanged sizes avoid bitmap reallocations. Small-to-large, phone/desktop and Retina transitions remain sharp without changing source, camera, slice or nearest picking. + +### REQ-ThreeMDViewer-006 + +The browser and Sculpt volume camera SHALL expose the same full-turn orbit, screen-space pan, bounded proportional zoom, default Fit pose and camera-correct nearest-cube picking, with matched camera basis and documented coordinate conversion. + +Acceptance Criteria: + +- Both the web cube viewer and Sculpt volume canvas orbit through complete horizontal and vertical turns, using the same continuous camera basis at the poles and upside down. Drag sensitivity is 0.008 radians per point; web yaw is the negative of native yaw to account for its coordinate convention. +- Both volume cameras support screen-space pan without changing the document, mesh, slice, paint history or geometry revision. Native Shift-left, middle and right dragging pan; an explicit Pan button works in Orbit. Native scroll zoom and trackpad magnification respond proportionally. Browser Pan, modified mouse dragging and two-finger pan/pinch provide the equivalent controls. +- Zoom stays between 0.5 and 2 in both views. Fit restores the default matched pose (native yaw -0.6 / web yaw 0.6, pitch 0.35), zoom 1 and zero pan. The native CPU cube/ASCII projection, live GPU camera and picking all honor the same orbit and pan. +- Shared asymmetric fixture receipts compare camera bases and screen projections across native and browser views, including pole crossings, upside-down and panned cameras. Picking chooses the nearest cube after those movements and camera changes reuse geometry. Mac native regressions and browser Chromium/WebKit regressions cover the controls. +- Keep native painting, stroke freezing, CPU/export budgets and the browser one-draw cube mesh, colors, axes and bounded grid behavior. Keep app and viewer specifications and human intent synchronized. Sparse-world Explore, storage formats, parser APIs, package releases and trust policies remain outside this camera change. + +### REQ-ThreeMDViewer-008 + +The browser SHALL offer a Sculpt-style Slice workspace that edits bounded character grids in the current document, preserves the surrounding source, and produces the same supported cell edits as Sculpt. + +Acceptance Criteria: + +- Add Slice beside Edit, Preview and Cubes while keeping Cubes as the default. Slice presents selectable thumbnails, a large editable grid, current one-based X/Y and slice coordinates, an interactive live 3D reference, and Expand back to Cubes. Selection and camera survive view switches; the reference reuses the existing WebGL context. +- Draw, Erase and Fill use the native palette # @ * + o x : = - and period for erased cells. Square brushes of size 1, 3 and 5 clip to the grid. Fast pointer movement follows the same integer line interpolation as SculptureWorkspace, with no gaps. Fill uses four-neighbor connectivity on the selected slice and ignores brush size. +- A drag is one undo step; no-op edits add no history. Undo and redo restore exact source and synchronize the grid and reference. Source typing and visual edits use coherent history, retained with each draft and shared by linked file/entry views. A new edit clears redo. History is bounded to 100 entries per draft and an 8 MiB collection budget without dropping the current source. Pointer release, cancel, lost capture or navigation finish the current accepted stroke and prevent late writes into another document. +- Arrow keys move the selected cell within bounds; Space applies the current tool. Explicit X/Y controls and Apply support precise keyboard editing. Grid zoom offers Fit, 2x, 4x, 8x and 16x with internal scrolling. Show previous slice overlays occupied cells only behind empty current cells, is unavailable on the first slice, and never mutates source. +- Eligible documents contain complete rectangular fenced ASCII grids with common dimensions, the native palette and period/space empty cells. Empty grids remain editable. Keep the viewer limits of 64 columns, 64 rows, 4000 occupied cells and 12 distinct render glyphs; visual editing additionally limits eligible documents to 256 slices and 1.5 MiB of source. Prose, invalid, ragged, tabbed, unsupported-glyph or over-budget documents retain Edit/Preview/Cubes as appropriate and explain why Slice editing is unavailable. A proposed edit that exceeds a limit is rejected without committing a partial transaction or adding undo history. +- Source edits replace only targeted grid characters, preserving frontmatter, plane coordinates, labels, other body content, fence markers and newline style byte for byte. Visual edits immediately participate in Edited markers, source download, kind 2 export, search and packing. They do not write original files, persist browser storage or rewrite a composition profile. +- Slice remains usable at 390x844 and 320x740 with touch targets, visible keyboard focus, named controls, an accessible selected-cell description and no page overflow. The 2D editor works without WebGL2; the reference explains GPU unavailability and preserves edits. The existing camera, file, composition, export and accessibility regressions continue to pass. +- Shared asymmetric edit fixtures verify native/browser Draw, Erase, Fill, clipped brushes, sparse diagonal input and undo/redo against independently specified final cells. Chromium and WebKit tests exercise actual pointer and keyboard flows, exact source preservation, empty grids, history boundaries, composition switching, downloads and phone layout. Evidence distinguishes automated checks, agent visual inspection, local Trust, remote CI and provenance limitations. + +### REQ-ThreeMDViewer-007 + +The viewer and Sculpt volume view SHALL provide matched document-axis rotation constraints and numerical rotation/pan steps alongside the camera sphere. + +Acceptance Criteria: + +- Both volume views show a small sphere with colored X, Y and Z rotation rings and accessible axis buttons. Choosing an axis constrains dragging and step buttons to rotation around that document axis; Free restores unconstrained orbit. +- Three-axis rotation preserves an orthonormal camera orientation and supports Z rotation without changing model cells, slice, Undo, files, or installed geometry. Native and browser use the same document-axis convention, including row Y and plane Z. +- Both views offer an editable rotation step in degrees (default 15 degrees) with minus and plus nudges, and an editable pan step in cells (default 0.25) with directional nudges. Values must be finite and positive; invalid input leaves the current camera unchanged. Fit resets the default pose and pan. +- Tests compare shared asymmetric projection and picking cases including Z rotation, full X/Y/Z turns, negative nudges and exact inverse steps; native live and scalar renderers agree. Camera controls remain usable on narrow screens and have keyboard labels and focus indication. +- Synchronize viewer and Sculpt contracts and intent, record actual current tests, and complete verified lifecycle closure only under Leif’s explicit approval of this new definition. Leif retains PR merge authority. Preserve storage, rendering budgets, parser APIs, releases and trust policy. diff --git a/specs/ThreeMDViewer/tasks.md b/specs/ThreeMDViewer/tasks.md index 53352d46..9fc34623 100644 --- a/specs/ThreeMDViewer/tasks.md +++ b/specs/ThreeMDViewer/tasks.md @@ -26,12 +26,27 @@ spec: ThreeMDViewer.spec.md ## Gaps - The previous page contract shipped in PR 91. -- Definition approval for the shared Edit and Preview panel is still open. +- Leif approved the final scope and verified closure on 2026-10-10; supported scoped review and finalization archived the viewer and camera changes. - The hosted page shows this layout after the branch merges. ## Review Sign-offs -- **Product**: previous page contract approved by user:0xLeif and shipped in PR 91. This layout change is not approved yet. -- **QA**: agent:codex local browser and visual verification; human review pending +- **Product**: previous page contract approved by user:0xLeif and shipped in PR 91. Leif approved the final layout and navigation scope on 2026-10-10 and authorized lifecycle closure after verification passes. +- **QA**: agent:codex current browser/native checks and visual observations; verified viewer and camera records archived. Scope approval does not claim independent human diff review. - **Design**: n/a -- **Dev**: pending +- **Dev**: agent:codex implementation and scoped review; current automated verification passed. + +- [x] Preserve file, linked-entry, invalid, and empty drafts with caret and selected plane across navigation. +- [x] Mark edits, filter files, navigate by keyboard, reveal phone documents, and avoid stale source queries. +- [x] Search and pack current drafts, and preserve the collection after a failed open. + +- [x] Preserve the selected slice across delayed source refresh and sort file paths for consistent keyboard navigation. +- [x] Compact small-phone spacing without reducing existing assertions. + +- [x] Match Sculpt and viewer full orbit through both poles with camera-only pan and proportional zoom. +- [x] Add shared asymmetric native/browser projection and picking fixtures. +- [x] Finish current cross-platform verification and lifecycle closure for the camera scope. +- [x] Implement the approved matching axis gizmo and numeric precision controls. +- [x] Add the approved browser Slice workspace and shared native/browser edit fixtures. +- [x] Verify current macOS browser, Linux CI, native and pinned Trust checks. +- [x] Complete current Slice and precise-axis lifecycle closure with actual agent:codex scoped review. diff --git a/specs/ThreeMDViewer/testing.md b/specs/ThreeMDViewer/testing.md index feeb1cbe..62b0d23a 100644 --- a/specs/ThreeMDViewer/testing.md +++ b/specs/ThreeMDViewer/testing.md @@ -9,7 +9,7 @@ spec: ThreeMDViewer.spec.md | `web/gather.test.ts` | bun | Section planes, pack, kind 2 round-trip, line plane index, search rank. | | `web/github-source.test.ts` | bun | Repo, folder, file, and raw locators. Host and path routing. Issues URL rejected. | | `web/open-document.test.ts` | bun | Text, composition, kind 1, kind 2, LZFSE refusal, linked folder. | -| `uitests/viewer.spec.mjs` | Playwright | Edit, Preview, and Cubes share one panel; full cube face pixels from all sides; glyph fill and gold edge selection; nearest slice picking; no camera/selection geometry uploads; about 1400 cubes; no console errors; narrow layout; kind 2, linked village, search, sections, composition; keyboard camera and slice controls; phone stage space; disclosure dismissal and both downloads; source shortcut focus; Preview empty state; GitHub busy/error recovery; GPU-unavailable guidance. | +| `uitests/viewer.spec.mjs` | Playwright | Edit, Preview, Slice, and Cubes share one panel; full cube face pixels from all sides; glyph fill and gold edge selection; nearest slice picking; no camera/selection geometry uploads; about 1400 cubes; no console errors; narrow layout; kind 2, linked village, search, sections, composition; keyboard camera and slice controls; phone stage space; disclosure dismissal and both downloads; source shortcut focus; Preview empty state; GitHub busy/error recovery; GPU-unavailable guidance. | ## Requirement evidence @@ -24,7 +24,7 @@ spec: ThreeMDViewer.spec.md - [x] Run Sculpt locally, orbit Character orb in Cubes, and compare the same orb in the refreshed local viewer. Screenshots: `docs/evidence/viewer-sculpt-parity/`. - [x] Inspect one-cell and starter sculptures for filled top, front, and side faces, visible edges, and pane framing. -- [x] Open `viewer.html`. On a wide window, files stay on the left and Edit, Preview, and Cubes switch in the panel beside them. On a narrow window, Files and the document take turns. +- [x] Open `viewer.html`. On a wide window, files stay on the left and Edit, Preview, Slice, and Cubes switch in the panel beside them. On a narrow window, Files and the document take turns. ## Edge Cases & Boundary Conditions @@ -34,10 +34,47 @@ spec: ThreeMDViewer.spec.md | Tree contains `node_modules` or a file over 1.5 MB | Those files are skipped. | | More than 400 text files, or more than 12,000 lines | The list stops at the cap and says so. | | Apple LZFSE bytes | The page refuses them and names `compressionUnavailable`. | -| Desktop width | Files stay visible while Edit, Preview, and Cubes switch. Preview shows the live plane view. | +| Desktop width | Files stay visible while Edit, Preview, Slice, and Cubes switch. Preview shows the live plane view. | | Width at or below 900px | Files and the document take turns. The document still switches Edit and Preview. | ## Continuing UI and UX verification - The viewer suite exercises the new controls in Chromium and WebKit. Binary export is compared as parsed document fields and plane bodies because decoding returns canonical text. Camera direction assertions are independent of font-driven aspect-ratio changes. - Live desktop dark, desktop light, Edit, and phone views are inspected and captured in `docs/evidence/viewer-ui/`. These are agent visual checks, not human approval. + +## File navigation fix + +The Chromium and WebKit viewer suite covers exact draft restoration, invalid and empty edits, the caret and slice, composition-entry independence, linked entry/file sharing, original-text edited markers, current-text download, search and pack, file filtering and keyboard selection, mobile document reveal, failed-open preservation, and stale source-query removal on navigation. Screenshots from live desktop and phone inspection are in `docs/evidence/viewer-navigation/`. These are agent checks and do not record human definition approval. + +## Closure regression coverage + +The file-draft test waits beyond the 160ms source-render debounce and checks that slice 1 survives before navigating. The phone keyboard test requires paths in alphabetical order before using End and Enter. The existing phone canvas, control separation, and overflow checks run unchanged at 390 by 844 and 320 by 740. The three original failures were reproduced and the targeted regression checks passed in Linux WebKit 1.61.1. The complete Linux hosted suite passed 190 tests with 8 existing skips in 2.1 minutes; the macOS viewer suite passed all 98 tests in 24.0 seconds. These are historical pre-closure results; the original viewer closure subsequently passed as recorded in the archived change. + +Closure implementation checks: macOS viewer 98 passed; Linux hosted UI 190 passed and 8 existing skips; Bun helper suite 15 passed; strict SpecSync 4 specs passed with zero warnings and full configured coverage; Hi 85 criteria with no problems; pinned element bundle drift passed at 48840 bytes. Logs remain local under /private/tmp/3md-viewer-closure-*. These historical checks preceded the original viewer and camera archives. Current Slice/axis checks are listed below. + +## Full camera parity + +`uitests/viewer.spec.mjs` covers complete yaw/pitch turns, continuous poles, unchanged GPU geometry, modified mouse and explicit Pan, Shift-arrow pan, wheel bounds, two-finger pinch/pan, pointer cancellation, Fit without slice/source changes, and the shared native/browser projection/picking fixture. Native `CameraParityTests`, `SculptureLiveVoxelTests` and `SculptureCanvasPointerTests` check matching transforms, scalar/live picking and camera-only input. Existing math example regressions verify compatible utility framing. Current results and limits are recorded in `docs/evidence/viewer-camera/README.md`; final Trust and lifecycle evidence remain separate. + +## Slice and precise camera parity + +Slice uses the native character palette `#@*+ox:=-`, Draw/Erase square brushes 1/3/5, integer gap-free strokes and four-neighbor fill confined to the selected plane. Exact raw source offsets preserve all untouched bytes, including CRLF and prose. Eligibility requires complete, common rectangular grids, at most 64 by 64 cells, 256 planes, 4000 occupied cells and 1.5 MiB source. Empty grids can be edited. Rejected over-budget strokes restore the entire transaction. + +History is shared with source typing and attached to each draft state, including linked entries. It retains at most 100 snapshots per draft and 8 MiB across the current collection; no-op strokes add no entry. Pointer up, cancellation, lost capture and navigation finish the accepted transaction. Thumbnails, one-based coordinates, keyboard arrows/Space, explicit cell Apply, previous-slice ghosts and Fit/2x/4x/8x/16x grid zoom use the same state. The live reference reparents the existing WebGL canvas rather than allocating another context; 2D editing remains available without WebGL. Phone layouts scroll inside Slice with full-size touch targets. + +The volume camera shows colored X/Y/Z rings and Free/X/Y/Z constraints. A normalized quaternion composes document-axis rotation with continuous free orbit. Numerical rotation defaults to 15 degrees and pan to 0.25 cells, accepting only finite positive steps. Fit restores the default orientation and zero pan. Shared independent matrix-reference cases cover three-axis projection and picking; shared edit cases run through actual Sculpt workspaces and browser pointer gestures. + + +## Current approved Slice and precise-axis verification + +2026-10-10: complete macOS UI 226 passed without skips or retries; Linux CI UI 218 passed with 8 existing platform-snapshot skips and no retries; configured native suite 637 passed and final parity selection 11 passed. Shared fixtures compare native workspace edits and actual browser gestures against independent expected rows and camera matrices. Logs and actual UI screenshots are in `docs/evidence/viewer-slice/`. Pinned Trust passed for implementation commit `8e9a0c4`; final archive-tip verification remains separate. Actual unsigned agent:codex provenance is recorded and does not satisfy the unchanged strict permitted-signature/reviewer policy. + +Both current approved changes were successfully finalized and archived on 2026-10-10. Their supported scoped review records identify agent:codex. Scope authorization and agent verification do not claim independent human review or a permitted signature. Exact final archive-head Trust and remote CI status are reported in PR #93; the implementation and test fixtures are unchanged from `8e9a0c4`. + +## Drawable resolution regression + +At 1x and 2x density, exercise a phone-initialized canvas, small Slice reference, expanded Cubes stage and larger-than-cap desktop. Assert actual WebGL drawing-buffer dimensions match proportional 2048-edge/2x bounds, with one context, no context-loss events, no geometry allocations/uploads and unchanged pose/source/selection. Existing pixel/projection/nearest-picking checks continue on both engines. + +2026-10-10: the post-resize full UI suite passed 230 tests; the final viewer suite including display-density listeners passed 130 tests; the final media-query/window-resize regressions passed 4 tests. No skips or retries. Actual browser bitmap/display measurements, screenshots, logs and implementation digests are in `docs/evidence/viewer-resolution/`; repository Trust and lifecycle verification remain separate. Native source is unchanged. + +Pinned Trust passed at implementation `95c1213` with Augur review risk 36 and configured soft provenance degradation. Strict root specs passed at 55/55 files and Hi at 87 criteria. Actual unsigned Codex provenance was recorded after the lane passed; unchanged strict signature/reviewer policy rejects it. Evidence is in `docs/evidence/viewer-resolution/`. Later lifecycle metadata does not change the HTML or tests. diff --git a/uitests/viewer.spec.mjs b/uitests/viewer.spec.mjs index cd71a2fa..0510d4af 100644 --- a/uitests/viewer.spec.mjs +++ b/uitests/viewer.spec.mjs @@ -1,4 +1,22 @@ import { test, expect } from "@playwright/test"; +import { mkdtemp, mkdir, writeFile, rm, readFile } from "node:fs/promises"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; + +const draftDocument = (title, body = "Original marker") => `---\n3md: 1.0\naxis: layer\ntitle: ${title}\n---\n@plane z=0 label="First"\n${body}\n@plane z=1 label="Second"\nSecond marker\n`; +async function openCollection(page, files) { + const directory = await mkdtemp(join(tmpdir(), "3md-viewer-drafts-")); + try { + for (const [path, text] of Object.entries(files)) { + const target = join(directory, path); + await mkdir(join(target, ".."), { recursive: true }); + await writeFile(target, text); + } + await page.locator("#folderInput").setInputFiles(directory); + await expect(page.locator("#fileList button")).toHaveCount(Object.keys(files).length); + } finally { await rm(directory, { recursive: true, force: true }); } +} +const openedFile = (page, name) => page.locator("#fileList button").filter({ has: page.locator(".file-name", { hasText: name }) }); // The official viewer/editor (web/viewer.html): live-edit any 3md and see it // render in the component, with shareable links. @@ -767,13 +785,183 @@ test.describe("viewer & editor (viewer.html)", () => { await page.locator("#cubeCanvas").press("Home"); expect(await matrix()).toEqual(initial); for (let i = 0; i < 12; i++) await page.locator("#cubeCanvas").press("+"); - await expect(page.locator("#cubeZoom")).toHaveText("320%"); + await expect(page.locator("#cubeZoom")).toHaveText("200%"); await expect(page.locator("#cubeZoomIn")).toBeDisabled(); await page.getByRole("button", { name: "Fit", exact: true }).click(); expect(await matrix()).toEqual(initial); expect(await page.evaluate(() => window.threeMd.source)).toBe(source); }); + test("full camera turns cross both poles continuously and retain geometry", async ({ page }) => { + await page.goto("/viewer.html"); + await viewerReady(page); + await page.waitForFunction(() => document.getElementById("cubeCanvas").dataset.renderer === "webgl2"); + await page.evaluate(() => { + const canvas = document.getElementById("cubeCanvas"); + const gl = canvas.__cubeGl; + canvas.__uploads = 0; + const upload = gl.bufferSubData.bind(gl); + gl.bufferSubData = (...args) => { canvas.__uploads++; return upload(...args); }; + }); + const source = await page.evaluate(() => window.threeMd.source); + // Pointer delivery uses the real event handler, including capture cancellation. + const drag = async (dx, dy) => page.dispatchEvent("#cubeCanvas", "pointerdown", { + pointerId: 91, pointerType: "mouse", button: 0, clientX: 150, clientY: 150, + }).then(() => page.dispatchEvent("#cubeCanvas", "pointermove", { + pointerId: 91, pointerType: "mouse", buttons: 1, clientX: 150 + dx, clientY: 150 + dy, + })).then(() => page.dispatchEvent("#cubeCanvas", "pointerup", { + pointerId: 91, pointerType: "mouse", button: 0, clientX: 150 + dx, clientY: 150 + dy, + })); + const matrix = () => page.evaluate(() => { + const gl = document.getElementById("cubeCanvas").__cubeGl; + const matrix = gl.getUniform(gl.getParameter(gl.CURRENT_PROGRAM), + gl.getUniformLocation(gl.getParameter(gl.CURRENT_PROGRAM), "uMvp")); + return [0, 1, 3].flatMap(row => { + const vector = [matrix[row], matrix[row + 4], matrix[row + 8]]; + const length = Math.hypot(...vector); + return vector.map(value => value / length); + }); + }); + const initial = await matrix(); + await drag(0, 2 * Math.PI / 0.008); + const full = await matrix(); + full.forEach((value, i) => expect(value).toBeCloseTo(initial[i], 4)); + await drag(2 * Math.PI / 0.008, 0); + const both = await matrix(); + both.forEach((value, i) => expect(value).toBeCloseTo(initial[i], 4)); + await drag(0, (Math.PI / 2 - 0.35 - 0.0001) / 0.008); + const before = await matrix(); + await drag(0, 0.0002 / 0.008); + const after = await matrix(); + expect(after.every(Number.isFinite)).toBe(true); + expect(Math.max(...after.map((v, i) => Math.abs(v - before[i])))).toBeLessThan(0.01); + await page.locator("#cubeCanvas").press("Home"); + expect(await page.evaluate(() => document.getElementById("cubeCanvas").__uploads)).toBe(0); + expect(await page.evaluate(() => window.threeMd.source)).toBe(source); + }); + + test("pan tools and modified dragging move only the camera and Fit recenters", async ({ page }) => { + await page.goto("/viewer.html"); + await viewerReady(page); + await page.waitForFunction(() => document.getElementById("cubeCanvas").dataset.renderer === "webgl2"); + const source = await page.evaluate(() => window.threeMd.source); + await page.locator("#outline button").nth(1).click(); + const state = () => page.evaluate(() => ({ ...document.getElementById("cubeCanvas").dataset, + slice: document.getElementById("lab").currentIndex })); + const initial = await state(); + for (const input of [{ button: 0, shiftKey: true }, { button: 1 }, { button: 2 }]) { + await page.dispatchEvent("#cubeCanvas", "pointerdown", { pointerId: 92, pointerType: "mouse", clientX: 100, clientY: 100, ...input }); + await page.dispatchEvent("#cubeCanvas", "pointermove", { pointerId: 92, pointerType: "mouse", clientX: 135, clientY: 125 }); + await page.dispatchEvent("#cubeCanvas", "pointerup", { pointerId: 92, pointerType: "mouse", clientX: 135, clientY: 125, ...input }); + const current = await state(); + expect(current.yaw).toBe(initial.yaw); + expect(current.pitch).toBe(initial.pitch); + expect(current.slice).toBe(initial.slice); + expect(Number(current.panX)).toBeLessThan(0); + expect(Number(current.panY)).toBeGreaterThan(0); + await page.locator("#cubeCanvas").press("Home"); + } + await page.getByRole("button", { name: "Pan", exact: true }).click(); + await expect(page.locator("#cubeCanvas")).toHaveAttribute("data-tool", "pan"); + await page.locator("#cubeCanvas").press("Shift+ArrowRight"); + expect(Number((await state()).panX)).toBeLessThan(0); + await page.locator("#cubeCanvas").press("Home"); + expect(Number((await state()).panX)).toBe(0); + expect(Number((await state()).panY)).toBe(0); + expect(await page.evaluate(() => window.threeMd.source)).toBe(source); + }); + + test("two fingers pan and pinch and a cancelled gesture cannot select a slice", async ({ page }) => { + await page.goto("/viewer.html"); + await viewerReady(page); + await page.waitForFunction(() => document.getElementById("cubeCanvas").dataset.renderer === "webgl2"); + const state = () => page.evaluate(() => ({ ...document.getElementById("cubeCanvas").dataset, + slice: document.getElementById("lab").currentIndex, zoom: document.getElementById("cubeZoom").textContent })); + const initial = await state(); + for (const [pointerId, clientX] of [[101, 100], [102, 200]]) { + await page.dispatchEvent("#cubeCanvas", "pointerdown", { pointerId, clientX, clientY: 150, pointerType: "touch", button: 0 }); + } + await page.dispatchEvent("#cubeCanvas", "pointermove", { pointerId: 102, clientX: 250, clientY: 180, pointerType: "touch" }); + const moved = await state(); + expect(moved.zoom).not.toBe(initial.zoom); + expect(moved.panX).not.toBe(initial.panX); + expect(moved.yaw).toBe(initial.yaw); + expect(moved.pitch).toBe(initial.pitch); + await page.dispatchEvent("#cubeCanvas", "pointercancel", { pointerId: 102, pointerType: "touch" }); + await page.dispatchEvent("#cubeCanvas", "pointerup", { pointerId: 101, clientX: 100, clientY: 150, pointerType: "touch" }); + expect((await state()).slice).toBe(initial.slice); + await page.locator("#cubeCanvas").press("Home"); + await expect(page.locator("#cubeZoom")).toHaveText("100%"); + }); + + test("browser camera projects and picks the shared native parity fixture", async ({ page }) => { + const { readFile } = await import("node:fs/promises"); + const fixture = JSON.parse(await readFile(new URL("../docs/evidence/viewer-camera/camera-parity.json", import.meta.url), "utf8")); + const [w, h, depth] = fixture.dimensions; + const planes = Array.from({ length: depth }, (_, z) => { + const rows = Array.from({ length: h }, (_, y) => Array.from({ length: w }, (_, x) => + fixture.cells.find(cell => cell.x === x && cell.y === y && cell.z === z)?.glyph || ".").join("")); + return `@plane z=${z}\n\`\`\`\n${rows.join("\n")}\n\`\`\`\n`; + }).join("\n"); + await page.goto("/viewer.html"); + await viewerReady(page); + await showEditor(page); + await page.fill("#editor", `---\n3md: 1.0\naxis: layer\ntitle: Camera parity\n---\n${planes}`); + await page.waitForTimeout(220); + await page.locator("#cubesTab").click(); + await page.evaluate(() => { + const canvas = document.getElementById("cubeCanvas"); + canvas.style.width = "400px"; + canvas.style.height = "320px"; + canvas.style.flex = "none"; + window.dispatchEvent(new Event("resize")); + }); + await page.waitForFunction(() => document.getElementById("cubeCanvas").dataset.cubes === "3"); + const drag = async (dx, dy) => { + await page.dispatchEvent("#cubeCanvas", "pointerdown", { pointerId: 93, pointerType: "mouse", button: 0, clientX: 100, clientY: 100 }); + await page.dispatchEvent("#cubeCanvas", "pointermove", { pointerId: 93, pointerType: "mouse", clientX: 100 + dx, clientY: 100 + dy }); + await page.dispatchEvent("#cubeCanvas", "pointerup", { pointerId: 93, pointerType: "mouse", button: 0, clientX: 100 + dx, clientY: 100 + dy }); + }; + for (const pose of fixture.cases) { + await page.locator("#cubeFit").click(); + await page.locator("#cubeOrbit").click(); + await drag((0.6 + pose.yaw) / 0.008, (pose.pitch - 0.35) / 0.008); + await page.dispatchEvent("#cubeCanvas", "wheel", { deltaY: -Math.log(pose.zoom) / 0.002 }); + if (pose.rotations) { + await page.locator("#cameraPrecision summary").click(); + for (const [axis, degrees] of pose.rotations) { + await page.locator(`#axisButtons [data-axis="${axis}"]`).click(); + await page.locator("#rotationStep").fill(String(Math.abs(degrees))); + await page.locator(degrees < 0 ? "#axisMinus" : "#axisPlus").click(); + } + await page.locator('#axisButtons [data-axis="free"]').click(); + await page.locator("#cameraPrecision summary").click(); + } + await page.locator("#cubePan").click(); + const pixelsPerCell = pose.scale; + await drag(-pose.panX * pixelsPerCell, pose.panY * pixelsPerCell); + const projected = await page.evaluate(cells => { + const canvas = document.getElementById("cubeCanvas"); + const gl = canvas.__cubeGl; + const program = gl.getParameter(gl.CURRENT_PROGRAM); + const m = gl.getUniform(program, gl.getUniformLocation(program, "uMvp")); + return cells.map(cell => { + const point = [cell.x - 4, 3 - cell.y, cell.z - 2, 1]; + const clip = [0, 1, 2, 3].map(row => point.reduce((sum, value, column) => sum + value * m[column * 4 + row], 0)); + return [(clip[0] / clip[3] + 1) * 200, (1 - clip[1] / clip[3]) * 160]; + }); + }, fixture.cells); + for (const [i, coordinates] of projected.entries()) { + coordinates.forEach((value, axis) => expect(value, pose.name).toBeCloseTo(pose.projected[i][axis], 2)); + } + await page.locator("#cubeOrbit").click(); + for (const [i, coordinates] of projected.entries()) { + await page.locator("#cubeCanvas").click({ position: { x: coordinates[0], y: coordinates[1] } }); + expect(await page.evaluate(() => document.getElementById("lab").currentIndex), pose.name).toBe(fixture.cells[i].z); + } + } + }); + test("phone layout leaves room for cubes and keeps controls outside the drawing", async ({ page }) => { await page.setViewportSize({ width: 390, height: 844 }); await page.goto("/viewer.html"); @@ -909,4 +1097,408 @@ test.describe("viewer & editor (viewer.html)", () => { expect(await page.evaluate(() => document.getElementById("lab").document.title)).toBe("Small sculpture"); }); + test("file switches preserve edited, invalid, and empty drafts with caret and slice", async ({ page }) => { + await page.goto("/viewer.html"); + await viewerReady(page); + await openCollection(page, { "a.3md": draftDocument("A"), "nested/b.3md": draftDocument("B") }); + await openedFile(page, "a.3md").click(); + await showEditor(page); + const original = await page.locator("#editor").inputValue(); + const changed = draftDocument("A edited", "Unique draft text"); + await page.fill("#editor", changed); + await page.evaluate(() => { + document.getElementById("editor").setSelectionRange(20, 25); + document.getElementById("lab").goTo(1); + }); + // Cross the 160ms editor debounce before navigation: refreshing source must + // retain the chosen slice, including on slower Linux WebKit runners. + await page.waitForTimeout(220); + expect(await page.evaluate(() => document.getElementById("lab").currentIndex)).toBe(1); + await openedFile(page, "b.3md").click(); + await openedFile(page, "a.3md").click(); + await expect(page.locator("#editor")).toHaveValue(changed); + expect(await page.evaluate(() => { + const ed = document.getElementById("editor"); + return { start: ed.selectionStart, end: ed.selectionEnd, plane: document.getElementById("lab").currentIndex }; + })).toEqual({ start: 20, end: 25, plane: 1 }); + await expect(page.locator("#draftState")).toBeVisible(); + await expect(openedFile(page, "a.3md")).toHaveAttribute("data-edited", "true"); + await page.click("#documentMenu summary"); + const downloadEvent = page.waitForEvent("download"); + await page.click("#dlBtn"); + const download = await downloadEvent; + expect(await readFile(await download.path(), "utf8")).toBe(changed); + await expect(page.locator("#draftState")).toBeVisible(); + for (const draft of ["invalid draft kept verbatim", ""]) { + await page.fill("#editor", draft); + await openedFile(page, "b.3md").click(); + await openedFile(page, "a.3md").click(); + await expect(page.locator("#editor")).toHaveValue(draft); + } + await page.fill("#editor", original); + await expect(page.locator("#draftState")).toBeHidden(); + await expect(openedFile(page, "a.3md")).toHaveAttribute("data-edited", "false"); + }); + + test("composition entry switches preserve each draft without copying it into another entry", async ({ page }) => { + await page.goto("/viewer.html"); + await viewerReady(page); + await page.waitForFunction(() => window.threeMdCatalogCount > 200); + await page.fill("#findExample", "Extensions/shared-grove.3md"); + await page.locator("#findList button", { hasText: "layer · Extensions/shared-grove.3md" }).click(); + await showEditor(page); + const rootId = await page.locator("#piece").inputValue(); + const rootSource = await page.locator("#editor").inputValue(); + const changedRoot = rootSource + "\nRoot draft marker\n"; + await page.fill("#editor", changedRoot); + await page.locator("#piece").focus(); + await page.selectOption("#piece", "canopy"); + await expect(page.locator("#piece")).toBeFocused(); + const canopySource = await page.locator("#editor").inputValue(); + expect(canopySource).not.toContain("Root draft marker"); + const changedCanopy = canopySource + "\nCanopy draft marker\n"; + await page.fill("#editor", changedCanopy); + await page.selectOption("#piece", rootId); + await expect(page.locator("#editor")).toHaveValue(changedRoot); + await page.selectOption("#piece", "canopy"); + await expect(page.locator("#editor")).toHaveValue(changedCanopy); + await page.click("#cubesTab"); + await expect(page.locator("#draftState")).toBeVisible(); + await expect(page.locator("#sourceName")).toBeVisible(); + }); + + test("linked entries and file navigation share the same draft", async ({ page }) => { + await page.goto("/viewer.html"); + await viewerReady(page); + const files = {}; + for (const path of ["scene.3md", "models/house.3md", "models/tree.3md", "models/tower.3md"]) { + files[path] = await readFile(new URL(`../Examples/LinkedVillage/${path}`, import.meta.url), "utf8"); + } + await openCollection(page, files); + await showEditor(page); + const rootId = await page.locator("#piece").inputValue(); + const houseId = await page.locator("#piece option").evaluateAll((options) => options.find((option) => option.textContent.endsWith("models/house.3md")).value); + await page.selectOption("#piece", houseId); + const changed = (await page.locator("#editor").inputValue()) + "\nLinked house draft\n"; + await page.fill("#editor", changed); + await openedFile(page, "house.3md").click(); + await expect(page.locator("#editor")).toHaveValue(changed); + const revised = changed + "From the file list\n"; + await page.fill("#editor", revised); + await openedFile(page, "scene.3md").click(); + await page.selectOption("#piece", rootId); + await page.selectOption("#piece", houseId); + await expect(page.locator("#editor")).toHaveValue(revised); + await expect(openedFile(page, "house.3md")).toHaveAttribute("data-edited", "true"); + }); + + test("search and packing use drafts rather than original file text", async ({ page }) => { + await page.goto("/viewer.html"); + await viewerReady(page); + await openCollection(page, { "a.3md": draftDocument("A"), "b.3md": draftDocument("B") }); + await openedFile(page, "a.3md").click(); + await showEditor(page); + const changed = draftDocument("A", "DraftOnlyNeedle9381"); + await page.fill("#editor", changed); + await openedFile(page, "b.3md").click(); + await page.fill("#findExample", "DraftOnlyNeedle9381"); + await page.locator("#findList button", { hasText: "DraftOnlyNeedle9381" }).click(); + await expect(page.locator("#editor")).toHaveValue(changed); + await page.click("#documentMenu summary"); + await page.click("#packBtn"); + expect(await page.locator("#editor").inputValue()).toContain("DraftOnlyNeedle9381"); + }); + + test("file filtering, keyboard selection, and phone opens reveal the document", async ({ page }) => { + await page.setViewportSize({ width: 390, height: 844 }); + await page.goto("/viewer.html"); + await viewerReady(page); + await page.getByRole("tab", { name: "Files", exact: true }).click(); + await openCollection(page, { "a.3md": draftDocument("A"), "nested/b.3md": draftDocument("B") }); + await expect(page.locator("#grid")).toHaveAttribute("data-show", "document"); + await page.getByRole("tab", { name: "Files", exact: true }).click(); + await page.fill("#fileFilter", "not-here"); + await expect(page.locator("#fileList")).toContainText("No files match"); + await page.locator("#fileFilter").press("Escape"); + await expect(page.locator("#fileList button")).toHaveCount(2); + await expect(page.locator("#fileList .file-name")).toHaveText(["a.3md", "b.3md"]); + await page.locator("#fileFilter").press("ArrowDown"); + await page.keyboard.press("End"); + await expect(openedFile(page, "b.3md")).toBeFocused(); + await page.keyboard.press("Enter"); + await expect(page.locator("#grid")).toHaveAttribute("data-show", "document"); + await expect(page.locator("#sourceName")).toHaveText("b.3md"); + await expect(page.locator("#cubeCanvas")).toBeFocused(); + expect(await page.evaluate(() => document.documentElement.scrollWidth)).toBeLessThanOrEqual(390); + await page.getByRole("tab", { name: "Files", exact: true }).click(); + await page.fill("#findExample", "Second marker"); + await page.locator("#findList button").filter({ hasText: "Second marker" }).first().click(); + await expect(page.locator("#grid")).toHaveAttribute("data-show", "document"); + expect(await page.evaluate(() => document.getElementById("lab").currentIndex)).toBe(1); + }); + + test("a failed local open preserves the collection and current draft", async ({ page }) => { + await page.goto("/viewer.html"); + await viewerReady(page); + await openCollection(page, { "a.3md": draftDocument("A"), "b.3md": draftDocument("B") }); + await openedFile(page, "a.3md").click(); + await showEditor(page); + const changed = draftDocument("A", "Keep after failed open"); + await page.fill("#editor", changed); + await page.locator("#fileInput").setInputFiles({ name: "broken.3md", mimeType: "text/plain", buffer: Buffer.from("invalid document") }); + await expect(page.locator("#status")).toHaveClass(/err/); + await page.waitForTimeout(350); // A pending editor render must not clear the open error. + await expect(page.locator("#status")).toHaveClass(/err/); + await expect(page.locator("#fileList button")).toHaveCount(2); + await expect(page.locator("#editor")).toHaveValue(changed); + await openedFile(page, "b.3md").click(); + await openedFile(page, "a.3md").click(); + await expect(page.locator("#editor")).toHaveValue(changed); + }); + + test("explicit document navigation removes stale source queries and reloads the chosen source", async ({ page }) => { + const old = draftDocument("Old source"); + await page.route("**/original-document.3md", (route) => route.fulfill({ status: 200, contentType: "text/plain", body: old })); + await page.goto("/viewer.html?src=original-document.3md&theme=dark"); + await viewerReady(page); + await expect(page.locator("#documentTitle")).toHaveText("Old source"); + await page.click("#cubeSample"); + expect(new URL(page.url()).searchParams.has("src")).toBe(false); + expect(new URL(page.url()).searchParams.get("theme")).toBe("dark"); + await page.reload(); + await viewerReady(page); + await expect(page.locator("#documentTitle")).toHaveText("Small sculpture"); + await openCollection(page, { "a.3md": draftDocument("A"), "b.3md": draftDocument("B") }); + await openedFile(page, "b.3md").click(); + await page.reload(); + await viewerReady(page); + await expect(page.locator("#documentTitle")).toHaveText("B"); + }); + +}); + +const sliceSource = grids => `---\n3md: 1.0\naxis: layer\ntitle: Slice parity\n---\n\n${grids.map((rows,z) => `@plane z=${z} label="Slice ${z+1}"\n\`\`\`\n${rows.join("\n")}\n\`\`\`\n`).join("\n")}`; +async function openSlice(page, source) { + await page.goto("/viewer.html"); await viewerReady(page); + await page.evaluate(text => window.threeMd.set(text), source); + await page.locator("#sliceTab").click(); + await expect(page.locator("#sliceGrid")).toBeVisible(); +} +async function sliceStroke(page, points, end = "pointerup") { + const rect = await page.locator("#sliceGrid").boundingBox(); + const dimensions = await page.locator("#sliceDimensions").textContent(); + const [w,h] = dimensions.match(/\d+/g).map(Number); + const at = ([x,y]) => ({pointerId:77,pointerType:"mouse",button:0,isPrimary:true,clientX:rect.x+(x+.5)*rect.width/w,clientY:rect.y+(y+.5)*rect.height/h}); + await page.dispatchEvent("#sliceGrid","pointerdown",at(points[0])); + for (const point of points.slice(1)) await page.dispatchEvent("#sliceGrid","pointermove",at(point)); + await page.dispatchEvent("#sliceGrid",end,at(points.at(-1))); +} + +test.describe("Sculpt Slice parity", () => { + test("shared native strokes, clipped brushes, four-neighbor fill and no-op undo", async ({page}) => { + const fixture = JSON.parse(await readFile(new URL("../docs/evidence/viewer-slice/slice-parity.json",import.meta.url),"utf8")); + for (const item of fixture.cases) { + await openSlice(page,sliceSource(item.initial)); + if(item.z) await page.getByRole("button",{name:`Slice ${item.z+1}`,exact:true}).click(); + await page.locator(`#sliceTool [data-tool="${item.tool}"]`).click(); + if(item.tool!=="erase") await page.getByRole("button",{name:`Paint ${item.glyph}`,exact:true}).click(); + if(item.tool!=="fill") await page.locator(`#sliceSize [data-size="${item.size}"]`).click(); + await sliceStroke(page,item.path); + expect(await page.evaluate(()=>window.threeMd.source),item.name).toBe(sliceSource(item.expected)); + if(JSON.stringify(item.initial)===JSON.stringify(item.expected)) await expect(page.locator("#sliceUndo")).toBeDisabled(); + else { + await page.locator("#sliceUndo").click(); expect(await page.evaluate(()=>window.threeMd.source)).toBe(sliceSource(item.initial)); + await expect(page.locator("#sliceUndo")).toBeDisabled(); await page.locator("#sliceRedo").click(); + expect(await page.evaluate(()=>window.threeMd.source)).toBe(sliceSource(item.expected)); + } + } + }); + test("grid edits preserve CRLF, labels, prose and downloads exactly",async({page})=>{ + const original=sliceSource([["...","..."],["...","..."]]).replace("@plane z=1", "@plane z=7.5").replace('```\n','Intro **kept**\n```ascii\n')+'\nAfter the grid.\n'; + const raw=original.replace(/\n/g,"\r\n"), expected=raw.replace('...\r\n...','.#.\r\n...'); + await openSlice(page,raw); await sliceStroke(page,[[1,0]],"pointercancel"); + expect(await page.evaluate(()=>window.threeMd.source)).toBe(expected); + await expect(page.locator("#draftState")).toBeVisible(); + await page.locator("#documentMenu summary").click(); + const download=page.waitForEvent("download"); await page.locator("#dlBtn").click(); + expect(await readFile(await (await download).path(),"utf8")).toBe(expected); + await page.locator("#documentMenu summary").press("Escape"); + await page.locator("#sliceUndo").click(); expect(await page.evaluate(()=>window.threeMd.source)).toBe(raw); + }); + test("keyboard cells, grid zoom, previous overlay and shared WebGL reference",async({page})=>{ + await openSlice(page,sliceSource([["#..","..."],["...","..."]])); + const initial=await page.evaluate(()=>{const c=document.getElementById("cubeCanvas");window.sliceContext=c.getContext("webgl2");return window.threeMd.source;}); + await page.getByRole("button",{name:"Slice 2",exact:true}).click(); await page.locator("#slicePrevious").check(); + expect(await page.evaluate(()=>window.threeMd.source)).toBe(initial); + await page.locator("#sliceGrid").press("ArrowRight"); await page.locator("#sliceGrid").press("ArrowDown"); await page.locator("#sliceGrid").press("Space"); + expect(await page.evaluate(()=>window.threeMd.source)).toBe(sliceSource([["#..","..."],["...",".#."]])); + await page.locator('#sliceZoom [data-zoom="4"]').click(); + expect(await page.evaluate(()=>document.getElementById("sliceScroll").scrollWidth > document.getElementById("sliceScroll").clientWidth)).toBe(true); + await page.locator("#sliceExpand").click(); await expect(page.locator("#cubesPane > #cubeCanvas")).toBeVisible(); + expect(await page.evaluate(()=>document.getElementById("cubeCanvas").getContext("webgl2")===window.sliceContext)).toBe(true); + expect(await page.evaluate(()=>document.getElementById("lab").currentIndex)).toBe(1); + }); + test("source typing and Slice share undo and retain it across file navigation",async({page})=>{ + await page.goto("/viewer.html");await viewerReady(page); + const one=sliceSource([["...","..."]]),two=sliceSource([["@@@","..."]]); + await openCollection(page,{"one.3md":one,"two.3md":two});await openedFile(page,"one.3md").click(); + await page.locator("#sliceTab").click();await sliceStroke(page,[[0,0]]); + await openedFile(page,"two.3md").click();await openedFile(page,"one.3md").click(); + expect(await page.evaluate(()=>window.threeMd.source)).toBe(one.replace('...\n...','#..\n...')); + await showEditor(page);await page.locator("#editor").press("ControlOrMeta+End");await page.locator("#editor").pressSequentially("prose"); + await page.locator("#editor").press("ControlOrMeta+z");expect(await page.evaluate(()=>window.threeMd.source)).toBe(one.replace('...\n...','#..\n...')); + await page.locator("#editor").press("ControlOrMeta+z");expect(await page.evaluate(()=>window.threeMd.source)).toBe(one); + await page.locator("#editor").press("ControlOrMeta+Shift+z");expect(await page.evaluate(()=>window.threeMd.source)).toBe(one.replace('...\n...','#..\n...')); + }); + test("unsupported grids stay readable and budget rejection restores the full stroke",async({page})=>{ + await page.goto("/viewer.html");await viewerReady(page);await page.evaluate(text=>window.threeMd.set(text),sliceSource([["xx","x"]]));await page.locator("#sliceTab").click(); + await expect(page.locator("#sliceUnavailable")).toContainText("rectangular");await expect(page.locator("#sliceWorkspace")).toBeHidden(); + const rows=Array.from({length:64},(_,y)=>y<62?'#'.repeat(64):'.'.repeat(64)); + const original=sliceSource([rows]);await page.evaluate(text=>window.threeMd.set(text),original); + await page.locator('#sliceSize [data-size="5"]').click();await sliceStroke(page,[[0,63],[63,63]]); + expect(await page.evaluate(()=>window.threeMd.source)).toBe(original);await expect(page.locator("#sliceUndo")).toBeDisabled();await expect(page.locator("#sliceMessage")).toContainText("restored"); + }); + test("phone Slice tools and axis controls stay usable without horizontal page overflow",async({page})=>{ + await openSlice(page,sliceSource([["...","..."],["...","..."]])); + for(const size of [{width:390,height:844},{width:320,height:740}]){ + await page.setViewportSize(size);await expect(page.locator("#sliceGrid")).toBeVisible();await sliceStroke(page,[[1,1]]); + expect(await page.evaluate(()=>document.body.scrollWidth<=innerWidth)).toBe(true); + } + await page.locator("#sliceExpand").click();await page.locator('#axisButtons [data-axis="2"]').click();await page.locator("#cameraPrecision summary").click(); + await page.locator("#axisPlus").click();expect(await page.evaluate(()=>document.body.scrollWidth<=innerWidth)).toBe(true); + }); + test("2D editing works with an unavailable WebGL reference",async({page})=>{ + await page.addInitScript(()=>{const get=HTMLCanvasElement.prototype.getContext;HTMLCanvasElement.prototype.getContext=function(type,...args){return type==='webgl2'?null:get.call(this,type,...args);};}); + await openSlice(page,sliceSource([["...","..."]]));await sliceStroke(page,[[2,1]]); + expect(await page.evaluate(()=>window.threeMd.source)).toBe(sliceSource([["...","..#"]]));await expect(page.locator("#sliceReferenceNote")).toContainText("WebGL2"); + }); + test("axis inverse, finite inputs, pan steps and Fit leave source and geometry intact",async({page})=>{ + await page.goto("/viewer.html");await viewerReady(page);const source=await page.evaluate(()=>window.threeMd.source); + await page.locator("#cameraPrecision summary").click();await page.locator('#axisButtons [data-axis="2"]').click(); + await page.locator("#axisPlus").click();const turned=await page.locator("#cubeCanvas").getAttribute("data-rotation"); + expect(JSON.parse(turned)[2]).not.toBe(0);await page.locator("#axisMinus").click();expect(JSON.parse(await page.locator("#cubeCanvas").getAttribute("data-rotation"))[2]).toBeCloseTo(0,12); + await page.locator("#rotationStep").fill("0");await page.locator("#axisPlus").click();await expect(page.locator("#rotationStep")).toHaveAttribute("aria-invalid","true"); + await page.getByRole("button",{name:"Pan right",exact:true}).click();await expect(page.locator("#cubeCanvas")).toHaveAttribute("data-pan-x","-0.25"); + await page.locator("#panStep").fill("-1");await page.getByRole("button",{name:"Pan right",exact:true}).click();await expect(page.locator("#cubeCanvas")).toHaveAttribute("data-pan-x","-0.25"); + await page.locator("#cubeFit").click();await expect(page.locator("#cubeCanvas")).toHaveAttribute("data-rotation","[0,0,0,1]");await expect(page.locator("#cubeCanvas")).toHaveAttribute("data-pan-x","0"); + expect(await page.evaluate(()=>window.threeMd.source)).toBe(source); + }); }); + + +test("Slice history drops only old snapshots at the per-draft and collection budgets", async ({page}) => { + await openSlice(page,sliceSource([["...","..."]])); + for (let index=0;index<104;index++) { + await page.locator(`#sliceTool [data-tool="${index%2 ? "erase" : "draw"}"]`).click(); + await page.locator("#sliceGrid").press("Space"); + } + for(let index=0;index<100;index++) await page.locator("#sliceUndo").click(); + await expect(page.locator("#sliceUndo")).toBeDisabled(); + expect(await page.evaluate(()=>window.threeMd.source)).toBe(sliceSource([["...","..."]])); + const large=sliceSource([["...","..."]])+"\n"+"a".repeat(800000)+"\n"; + await openCollection(page,{"a.3md":large,"b.3md":large,"c.3md":large,"d.3md":large}); + for(const name of ["a.3md","b.3md","c.3md","d.3md"]){ + await openedFile(page,name).click(); await page.locator("#sliceTab").click(); + await page.locator('#sliceTool [data-tool="draw"]').click(); await page.locator("#sliceGrid").press("Space"); + await page.locator("#sliceGrid").press("ArrowRight"); await page.locator("#sliceGrid").press("Space"); + } + await openedFile(page,"a.3md").click();await expect(page.locator("#sliceUndo")).toBeDisabled(); + expect((await page.evaluate(()=>window.threeMd.source)).includes("##." )).toBe(true); + await openedFile(page,"d.3md").click();await page.locator("#sliceUndo").click();await page.locator("#sliceUndo").click(); + expect(await page.evaluate(()=>window.threeMd.source)).toBe(large); +}); + +test("Slice navigation finishes a touch stroke and ignores its late pointer movement",async({page})=>{ + await page.goto("/viewer.html");await viewerReady(page); + const source=sliceSource([["...","..."]]);await openCollection(page,{"one.3md":source,"two.3md":source}); + await openedFile(page,"one.3md").click();await page.locator("#sliceTab").click(); + const rect=await page.locator("#sliceGrid").boundingBox(); + await page.dispatchEvent("#sliceGrid","pointerdown",{pointerId:83,pointerType:"touch",isPrimary:true,button:0,clientX:rect.x+rect.width/6,clientY:rect.y+rect.height/4}); + await openedFile(page,"two.3md").click(); + await page.dispatchEvent("#sliceGrid","pointermove",{pointerId:83,pointerType:"touch",clientX:rect.x+rect.width/2,clientY:rect.y+rect.height/4}); + await page.dispatchEvent("#sliceGrid","pointerup",{pointerId:83,pointerType:"touch"}); + expect(await page.evaluate(()=>window.threeMd.source)).toBe(source); + await openedFile(page,"one.3md").click();expect(await page.evaluate(()=>window.threeMd.source)).toBe(source.replace('...\n...','#..\n...')); + await page.locator("#sliceUndo").click();expect(await page.evaluate(()=>window.threeMd.source)).toBe(source); +}); + + +for (const density of [1, 2]) { + test(`shared cube drawable stays sharp through view/viewport changes at ${density}x density`, async ({ browser }) => { + const context = await browser.newContext({ viewport: { width: 390, height: 844 }, deviceScaleFactor: density }); + try { + const page = await context.newPage(); + await page.addInitScript(() => { + window.__cubeResolution = { contexts: 0, losses: 0, uploads: 0, allocations: 0 }; + const original = HTMLCanvasElement.prototype.getContext; + HTMLCanvasElement.prototype.getContext = function(type, ...args) { + if (this.id === "cubeCanvas" && type === "webgl2") window.__cubeResolution.contexts++; + return original.call(this, type, ...args); + }; + document.addEventListener("webglcontextlost", () => window.__cubeResolution.losses++, true); + const media = window.matchMedia.bind(window); + window.matchMedia = query => { + const result = media(query); + if (query.startsWith("(resolution:")) window.__cubeResolution.display = result; + return result; + }; + }); + await page.goto("/viewer.html"); await viewerReady(page); + await page.waitForFunction(() => document.getElementById("cubeCanvas").dataset.renderer === "webgl2"); + await page.locator("#outline button").nth(1).click(); + await page.locator('#axisButtons [data-axis="2"]').click(); + await page.locator("#cubeCanvas").press("ArrowRight"); + const source = await page.evaluate(() => window.threeMd.source); + const pose = await page.evaluate(() => { + const canvas = document.getElementById("cubeCanvas"), gl = canvas.__cubeGl; + window.__cubeResolution.gl = gl; + window.__cubeResolution.program = gl.getParameter(gl.CURRENT_PROGRAM); + const upload = gl.bufferSubData.bind(gl), allocate = gl.bufferData.bind(gl); + gl.bufferSubData = (...args) => { window.__cubeResolution.uploads++; return upload(...args); }; + gl.bufferData = (...args) => { window.__cubeResolution.allocations++; return allocate(...args); }; + return [canvas.dataset.rotation, canvas.dataset.yaw, canvas.dataset.pitch, canvas.dataset.panX, canvas.dataset.panY]; + }); + const sharp = async () => { + await expect.poll(() => page.evaluate(() => { + const canvas = document.getElementById("cubeCanvas"), gl = canvas.__cubeGl; + let w = Math.max(2, Math.floor(canvas.clientWidth * Math.min(devicePixelRatio, 2))); + let h = Math.max(2, Math.floor(canvas.clientHeight * Math.min(devicePixelRatio, 2))); + const limit = Math.min(1, 2048 / w, 2048 / h); + w = Math.max(2, Math.floor(w * limit)); h = Math.max(2, Math.floor(h * limit)); + return canvas.width === w && canvas.height === h && gl?.drawingBufferWidth === w && gl?.drawingBufferHeight === h; + })).toBe(true); + const state = await page.evaluate(() => { + const canvas = document.getElementById("cubeCanvas"), gl = canvas.__cubeGl, receipt = window.__cubeResolution; + return { sameContext: gl === receipt.gl, sameProgram: gl?.getParameter(gl.CURRENT_PROGRAM) === receipt.program, + contexts: receipt.contexts, losses: receipt.losses, uploads: receipt.uploads, allocations: receipt.allocations, + pose: [canvas.dataset.rotation, canvas.dataset.yaw, canvas.dataset.pitch, canvas.dataset.panX, canvas.dataset.panY] }; + }); + expect(state).toEqual({ sameContext: true, sameProgram: true, contexts: 1, losses: 0, uploads: 0, allocations: 0, pose }); + expect(await page.evaluate(() => window.threeMd.source)).toBe(source); + await expect(page.locator("#planeLive")).toHaveText("Plane 2 of 3: walls"); + }; + await sharp(); + for (const viewport of [{ width: 1440, height: 1000 }, { width: 3200, height: 2000 }, { width: 390, height: 844 }]) { + await page.locator("#sliceTab").click(); await sharp(); + await page.setViewportSize(viewport); await sharp(); + await page.locator("#sliceExpand").click(); await sharp(); + } + for (let i = 0; i < 3; i++) { + await page.locator("#sliceTab").click(); await sharp(); + await page.locator("#cubesTab").click(); await sharp(); + } + // A display-density change can leave the CSS size unchanged. + await page.evaluate(value => { + Object.defineProperty(window, "devicePixelRatio", { configurable: true, value }); + window.__cubeResolution.display.dispatchEvent(new Event("change")); + }, density === 1 ? 2 : 1); + await sharp(); + expect(await page.evaluate(() => window.__cubeResolution.display.media)).toBe(`(resolution: ${density === 1 ? 2 : 1}dppx)`); + await page.evaluate(value => { + Object.defineProperty(window, "devicePixelRatio", { configurable: true, value }); + window.dispatchEvent(new Event("resize")); + }, density); + await sharp(); + } finally { await context.close(); } + }); +} diff --git a/web/viewer.html b/web/viewer.html index 8433eeb3..eb69d9a8 100644 --- a/web/viewer.html +++ b/web/viewer.html @@ -125,7 +125,12 @@ .edittools{display:none;gap:8px;padding:8px 12px;border-bottom:1px solid var(--hairline);flex-shrink:0} .stage[data-show="edit"] .edittools{display:flex} .edittools .btn{font-size:11px;padding:6px 9px} - .document-title{flex:1;font-size:12px;color:var(--ink);text-transform:none;letter-spacing:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0} + .document-heading{flex:1;min-width:90px;display:flex;align-items:center;gap:8px} + .document-heading>div{min-width:0} + .document-source{display:block;font:10px var(--code-font);color:var(--text-faint);text-transform:none;letter-spacing:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin-top:3px} + .draft-state{font:11px var(--ui-font);color:var(--warning);text-transform:none;letter-spacing:0;flex-shrink:0} + .draft-state[hidden]{display:none} + .document-title{display:block;font-size:12px;color:var(--ink);text-transform:none;letter-spacing:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0} .piecewrap{display:flex;align-items:center;gap:8px;padding:7px 12px;border-bottom:1px solid var(--hairline);font-size:12px} .piecewrap[hidden]{display:none} .piecewrap select{max-width:none;min-width:0;flex:1} @@ -135,7 +140,13 @@ .grid{display:grid;grid-template-columns:minmax(180px,240px) minmax(0,1fr);gap:12px;align-items:stretch;flex:1;min-height:260px} .filelist{overflow:auto;flex:1;min-height:0} .filelist button,.filelist .empty{display:block;width:100%;text-align:left;font:inherit;font-size:12px;font-family:var(--code-font);padding:7px 12px;border:0;border-bottom:1px solid var(--hairline);background:transparent;color:var(--ink)} - .filelist button{cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis} + .filelist button{cursor:pointer;position:relative;padding:10px 24px 10px 12px;min-height:44px} + .filelist .file-name,.filelist .file-path{display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis} + .filelist .file-path{font:10px var(--code-font);color:var(--text-faint);margin-top:4px} + .filelist button[data-edited="true"]::after{content:"";position:absolute;right:12px;top:16px;width:6px;height:6px;border-radius:50%;background:var(--warning)} + .file-filter{margin:10px 12px;min-width:0;font:12px var(--ui-font);color:var(--ink);background:var(--paper);border:1px solid var(--hairline);border-radius:4px;padding:8px 10px} + .file-filter[hidden]{display:none} + .file-filter:focus-visible{outline:2px solid var(--sheen);outline-offset:2px} .filelist button:hover,.filelist button:focus-visible,.filelist button[aria-current="true"]{background:color-mix(in srgb,var(--sheen) 12%,var(--surface));outline:none} .filelist .empty{color:var(--text-faint);font-family:var(--ui-font);line-height:1.6;padding:16px 12px} .filelist .empty strong{display:block;font-size:13px;font-weight:500;color:var(--ink);margin-bottom:6px} @@ -182,6 +193,7 @@ .wrap:not([data-view="edit"]) #ideCursor{display:none} .cubes{position:relative;display:flex;flex-direction:column;background:#10161a;overflow:hidden} .cubes canvas{width:100%;height:0;flex:1;min-height:0;display:block;touch-action:none;cursor:grab} + .cubes canvas[data-tool="pan"]{cursor:move} .cubes canvas:active{cursor:grabbing} .cubes canvas:focus-visible{outline:2px solid var(--sheen);outline-offset:-3px} .cubesempty{position:absolute;inset:0;display:grid;place-items:center;align-content:center;gap:12px;padding:24px;text-align:center;color:#d7e4ea} @@ -197,6 +209,8 @@ .camera-controls .btn{border:0;background:transparent;color:inherit;min-width:34px;min-height:32px;padding:6px 10px;letter-spacing:0} .camera-controls .btn:hover{background:#2b3a42;color:#fff} .camera-controls .btn:disabled{opacity:.4;cursor:default} + .camera-controls .btn[aria-pressed="true"]{background:#35434b;color:#fff} + .camera-tools .btn{min-width:52px} .camera-controls output{min-width:44px;text-align:center;font:11px var(--code-font);color:#aebdc5} .cubesempty .empty-actions{display:flex;gap:8px;flex-wrap:wrap;justify-content:center} .cubesempty .btn{background:#1b2329;border-color:#35434b;color:#d7e4ea} @@ -277,15 +291,18 @@ .findwrap{grid-column:2 / 4;min-width:0} .toolbar>.btn{padding:9px 8px} .document-menu{grid-column:3;grid-row:2} - .toolbar .primary{grid-column:1 / 4;padding:9px} + .toolbar .primary{grid-column:1 / 3;grid-row:2;padding:9px} .document-menu summary{justify-content:center;padding:9px} .fileswitch{margin-bottom:8px} .pane .bar{padding:8px;gap:7px} .document-title{order:3;flex-basis:100%;font-size:11px} .pstab{padding:9px 13px} .editmeta #sourceName,.editmeta #counts{display:none} - .cube-tools{padding:7px 9px;gap:8px} + .cube-tools{padding:7px 9px;gap:6px;flex-wrap:wrap} + .cubehint{flex-basis:100%} + #cameraControls{margin-left:auto} .camera-controls .btn{min-width:40px;min-height:40px;padding:6px 8px} + .camera-tools .btn{min-width:0;padding:6px 7px;font-size:11px} .camera-controls output{min-width:40px} .cubehint{font-size:10px} .cubehint .mouse-hint{display:none} @@ -294,7 +311,7 @@ .hint{line-height:1.7;font-size:10px} .foot{font-size:10px} } - @media(max-width:380px){.headerlinks a{display:none}.pstab{padding:9px 10px}} + @media(max-width:380px){.cube-tools{padding:4px 9px;gap:4px}.wrap{padding:6px}.topbar{padding-bottom:4px}.headerlinks a{display:none}.pstab{padding:9px 10px}} .sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0} @@ -308,6 +325,63 @@ @media (prefers-color-scheme:dark){:root:not([data-theme="light"]) .corvid-theme-toggle .sun{display:none}:root:not([data-theme="light"]) .corvid-theme-toggle .moon{display:inline}} :root[data-theme="light"] .corvid-theme-toggle .sun{display:inline} :root[data-theme="light"] .corvid-theme-toggle .moon{display:none} + + .stage[data-show="slice"] .editor,.stage[data-show="slice"] .viewer,.stage[data-show="slice"] .cubes,.stage[data-show="slice"] .outline,.stage[data-show="slice"] .bar .editmeta{display:none} + .slice-pane{display:none;flex:1;min-height:0;padding:12px;background:var(--surface)} + .stage[data-show="slice"] .slice-pane{display:flex;flex-direction:column} + .axis-sphere{position:absolute;right:12px;top:12px;width:120px;padding:5px;background:var(--surface);border:1px solid var(--hairline);border-radius:12px;z-index:2} + .axis-sphere svg{display:block;width:76px;height:76px;margin:auto;touch-action:none;cursor:grab} + .axis-sphere path{fill:none;stroke-width:2;opacity:.65}.axis-sphere path[data-axis="0"]{stroke:#f27b7b}.axis-sphere path[data-axis="1"]{stroke:#8ebd86}.axis-sphere path[data-axis="2"]{stroke:#78b5eb} + .axis-sphere path.selected{stroke-width:4;opacity:1}.sphere-outline{fill:none;stroke:var(--hairline)} + .axis-buttons{display:flex;gap:2px}.axis-buttons button{font:inherit;font-size:11px;padding:5px 3px;min-width:22px;border:0;border-radius:4px;color:var(--ink);background:transparent;cursor:pointer} + .axis-buttons button[aria-pressed="true"]{background:var(--sheen-bright);color:#102221} + .camera-precision{position:absolute;left:12px;top:12px;z-index:3;padding:5px 10px;font-size:12px;background:var(--surface);border:1px solid var(--hairline);border-radius:8px;max-width:calc(100% - 140px)}.camera-precision summary{cursor:pointer;width:max-content;padding:5px 0} + .precision-fields{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-top:8px}.precision-fields label{display:flex;align-items:center;gap:8px}.precision-fields input{width:70px;padding:8px;background:var(--surface);color:var(--ink);border:1px solid var(--hairline);border-radius:5px} + @media(pointer:coarse){.camera-precision summary{min-height:44px}.axis-buttons button{min-height:44px}.axis-sphere{width:142px}.axis-buttons button{min-width:32px}} + .slice-workspace[hidden],.slice-buttons[hidden]{display:none} + .slice-workspace{display:grid;grid-template-columns:94px minmax(0,1fr) 214px;gap:16px;flex:1;min-height:0} + .slice-sidebar{display:flex;flex-direction:column;min-height:0;gap:8px} + .slice-sidebar strong,.slice-main strong{font-size:14px} + .slice-list{overflow:auto;display:flex;flex-direction:column;gap:4px;min-height:0} + .slice-thumb{display:flex;align-items:center;gap:8px;min-height:44px;border:1px solid transparent;background:transparent;color:var(--ink);border-radius:6px;padding:6px;cursor:pointer;font:inherit;font-size:12px} + .slice-thumb[aria-current="true"]{border-color:var(--sheen);background:var(--ink-06)} + .slice-thumb canvas{width:28px;height:28px;background:#161d20} + .slice-main{display:flex;flex-direction:column;gap:8px;min-width:0;min-height:0} + .slice-heading{display:flex;justify-content:space-between;align-items:center;font-size:12px} + .slice-zoom{display:flex;gap:4px;align-items:center;flex-wrap:wrap;font-size:11px;color:var(--text-faint)} + .slice-zoom button{padding:5px 9px;min-height:34px} + .slice-scroll{overflow:auto;flex:1;min-height:150px;background:#161d20;border:1px solid var(--hairline);border-radius:6px} + #sliceGrid{display:block;touch-action:none;outline-offset:-3px;margin:auto} + .slice-tools{display:flex;flex-direction:column;gap:12px;overflow:auto;min-height:0;font-size:12px} + .slice-reference{height:170px;position:relative;flex-shrink:0;background:#11161a;border-radius:8px;overflow:hidden} + .slice-reference #cubeCanvas{display:block;width:100%;height:100%;min-height:0} + .slice-reference-note{font-size:11px;line-height:1.4;color:var(--text-faint);margin:0} + .slice-buttons{display:flex;gap:4px;flex-wrap:wrap} + .slice-buttons button{min-height:40px;padding:7px 10px} + .slice-buttons button[aria-pressed="true"],.slice-zoom button[aria-pressed="true"]{border-color:var(--sheen);background:var(--ink-06)} + .slice-palette{display:grid;grid-template-columns:repeat(5,1fr);gap:5px} + .slice-palette button{font:18px var(--code-font);height:40px;padding:4px} + .slice-cell-controls{display:grid;grid-template-columns:1fr 1fr;gap:6px} + .slice-cell-controls label{display:flex;gap:5px;align-items:center} + .slice-cell-controls input{min-width:0;width:100%;padding:7px;color:var(--ink);background:var(--paper);border:1px solid var(--hairline);border-radius:4px} + .slice-cell-controls button{grid-column:1/-1;min-height:40px} + .slice-hint{font-size:11px;color:var(--text-faint);margin:0;line-height:1.4} + .slice-previous{display:flex;gap:7px;align-items:center;font-size:12px;min-height:30px} + #sliceUnavailable{padding:18px;max-width:65ch;font-size:13px;line-height:1.6} + #sliceMessage{font-size:12px;min-height:16px;color:var(--text-faint);margin-top:6px} + @media(max-width:1150px){.slice-workspace{grid-template-columns:72px minmax(0,1fr) 180px;gap:10px}} + @media(max-width:700px){ + .slice-pane{padding:8px;overflow:auto}.slice-workspace{display:flex;flex-direction:column;gap:10px;flex:none} + .slice-sidebar{flex-direction:row;align-items:center;flex-shrink:0}.slice-sidebar>span{display:none} + .slice-list{flex-direction:row;flex:1;overflow-x:auto}.slice-thumb{flex-shrink:0;min-width:52px} + .slice-main{height:330px;flex-shrink:0}.slice-tools{overflow:visible;display:grid;grid-template-columns:1fr 1fr;align-items:start} + .slice-reference{height:150px;grid-column:1/-1}.slice-reference-title,.slice-reference-note{grid-column:1/-1} + #sliceTool,#sliceSize,.slice-palette{grid-column:1/-1} + .slice-palette{grid-template-columns:repeat(5,minmax(44px,1fr))} + .slice-buttons button,.slice-palette button,.slice-zoom button{min-width:44px;min-height:44px} + .slice-hint{grid-column:1/-1}.slice-cell-controls{grid-column:1/-1}.slice-history{grid-column:1/-1} + } + @@ -368,6 +442,7 @@

3md viewer.

files
+
@@ -375,10 +450,11 @@

3md viewer.

+
- Small sculpture - source.3mdLn 1, Col 1 +
Small sculpturesource.3md
+ Ln 1, Col 1 —