This commit is contained in:
2026-07-12 21:26:08 +08:00
commit 9dd41afd48
502 changed files with 129901 additions and 0 deletions
@@ -0,0 +1,86 @@
# Phase 0.2 Existing Graph Baseline
Date: 2026-06-18
Branch: `codex/large-graph-performance-experience`
Task: `0.2`
## Scope
This report captures the current graph behavior and performance baseline before changing graph behavior for the large-graph performance plan.
## Verification
| Check | Result | Evidence |
|---|---:|---|
| Graph engine test | Pass | `npm run test --workspace=@llm-wiki/graph-engine`: 274 tests, 58 suites, 0 failures |
| Graph engine typecheck | Pass | `npm run typecheck --workspace=@llm-wiki/graph-engine` |
| Graph engine build | Pass | `npm run build --workspace=@llm-wiki/graph-engine` |
| Workbench web test | Pass | `npm run test --workspace=@llm-wiki-agent/web`: 29 tests, 12 suites, 0 failures |
| Workbench web typecheck | Pass | `npm run typecheck --workspace=@llm-wiki-agent/web` |
| Stage 4.5 offline browser regression | Pass | `GRAPH_STAGE_4_5_CHROME_EXECUTABLE=<Playwright Chromium> bash tests/graph-browser-stage-4-5.regression-1.sh --target offline` |
## Browser Artifact
Dense wheel artifact:
- JSON: `docs/graph/performance/artifacts/2026-06-18-phase-0-2/stage-4.5-offline-dense-wheel.json`
- Screenshot: `docs/graph/performance/artifacts/2026-06-18-phase-0-2/stage-4.5-offline-dense-wheel.png`
- Navigation screenshot: `docs/graph/performance/artifacts/2026-06-18-phase-0-2/stage-4.5-offline-navigation.png`
Recorded sample:
| Viewport | Duration | Frames | Idle FPS | Wheel FPS | Minimum FPS | Transform changed |
|---|---:|---:|---:|---:|---:|---|
| 1440x960 | 3004 ms | 157 | 13.6 | 52.3 | 12.0 | true |
Important limitation: the current dense fixture has 200 nodes and 231 edges. This is useful as a regression baseline, but it does not prove 1000, 5000, or 10000 node smoothness.
## Current Rendering Behavior
- The current graph renderer is DOM/SVG.
- Nodes are DOM `button` elements in a node layer.
- Edges are SVG `path` elements in an edge layer.
- Community washes are SVG ellipses.
- Pan and zoom are applied through one content-layer transform.
- Motion frames update node positions, edge paths, community wash geometry, and minimap points.
- Search, type filters, community hover, node selection, reader state, and selection panels are all currently coupled to the same DOM/SVG renderer path.
## Current Interaction Semantics
The current behavior remains the pre-new-design behavior:
- Plain node click opens the reader-style node detail state.
- Shift-click builds a multi-node selection.
- Community legend click selects/focuses community nodes.
- Blank double-click fits the graph.
- Escape closes reader/selection state and clears graph highlights.
- Offline graph uses an in-graph reader panel; workbench graph opens the right drawer.
This is intentionally recorded as baseline behavior, not as the desired final interaction model.
## Baseline Bottleneck Class
The obvious large-graph risk is DOM/SVG update volume.
Reasons:
- Every visible node is a live DOM element.
- Every visible edge is a live SVG path.
- Rebuild/paint replaces the graph root and remounts controls.
- Motion frames recompute renderable graph state and update many DOM/SVG attributes.
- Hover, search, filter, community emphasis, and selection use DOM state/class updates across visible graph elements.
For small and medium scoped views, this is still appropriate. For 5000+ or 10000+ global views, the likely bottleneck is not one single function; it is the total cost of DOM node count, SVG path count, repeated attribute/class writes, and full repaint/remount paths.
## Test Harness Note
The first run of `tests/graph-browser-stage-4-5.regression-1.sh --target offline` exposed two harness issues:
- Playwright's normal click waited indefinitely for the offline theme button to become stable even though the button was visible, stationary, and not covered.
- The script's default system Chrome path failed in this environment during launch/cleanup. Installing Playwright Chromium and setting `GRAPH_STAGE_4_5_CHROME_EXECUTABLE` to the Playwright browser path produced a passing run.
The theme-button step was adjusted in the test harness to use forced click for this specific control. Product behavior was not changed.
## Next Baseline Gap
Phase 1 must add deterministic 1000, 5000, 10000, oversized-community, many-small-communities, many-search-hits, and many-Pin fixtures. Until those measurements exist, this report should be treated as the current small/dense-fixture baseline only.
@@ -0,0 +1,85 @@
# Phase 1.3 DOM/SVG Large Graph Baseline
Date: 2026-06-18
Branch: `codex/large-graph-performance-experience`
Task: `1.3`
Renderer: current DOM/SVG
## Scope
This report summarizes the current DOM/SVG renderer against the generated large-graph performance fixtures. It does not choose the final renderer route. It turns the raw runner output into provisional thresholds for the next phases.
## Commands
- `git log --oneline -15`
- `npm run test --workspace=@llm-wiki/graph-engine`
- `GRAPH_LARGE_PERF_ARTIFACT_DIR=/tmp/llm-wiki-graph-large-perf-task-1-3 bash tests/graph-browser-large-performance.regression-1.sh`
## Artifact
Machine-readable result:
- `/tmp/llm-wiki-graph-large-perf-task-1-3/large-graph-performance-results.json`
The artifact contains 47 fixed-schema records across 5 graph shapes.
## Result Table
| Shape | Nodes | Edges | DOM nodes | Initial | Wheel | Pan | Hover | Search | Click | Drawer | Community | Return | Cycle |
|---|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|
| nodes-1000-sparse | 1000 | 1400 | 7249 | pass (900.4 ms) | pass (1016.8 ms, 60 FPS) | pass (130.5 ms) | pass (65.1 ms) | pass (189.2 ms) | pass (452.8 ms) | pass (857.1 ms) | pass (3122.9 ms) | pass (1389.1 ms) |
| nodes-1000-dense | 1000 | 12000 | 7249 | pass (1008.4 ms) | pass (1007.2 ms, 59.6 FPS) | pass (129.2 ms) | pass (57.2 ms) | pass (205.2 ms) | pass (519.8 ms) | pass (867.9 ms) | pass (3279.1 ms) | pass (1432 ms) |
| nodes-5000-sparse | 5000 | 6500 | 27399 | pass (4615.6 ms) | pass (1013.5 ms, 51.3 FPS) | pass (142.5 ms) | pass (145 ms) | pass (942.2 ms) | pass (2488.8 ms) | pass (5229.1 ms) | pass (4022.2 ms) | not run |
| nodes-10000-aggregation | 10000 | 14000 | 52649 | pass (8836 ms) | pass (1004.9 ms, 36.8 FPS) | fail:timeout (-) | pass (3784.6 ms) | fail:timeout (-) | pass (4390.7 ms) | pass (13895.1 ms) | pass (4387 ms) | not run |
| oversized-community | 3000 | 7000 | 17224 | pass (15788.6 ms) | pass (1005 ms, 12.9 FPS) | pass (247 ms) | pass (131.5 ms) | pass (3342.5 ms) | pass (8498.3 ms) | pass (27055.3 ms) | pass (9611.6 ms) | not run |
## Recorded Failures
- nodes-10000-aggregation / pan: timeout
- nodes-10000-aggregation / node_click: timeout
## Bottleneck Class
The primary bottleneck class is DOM/SVG update volume. The evidence is structural and measured:
- 1000-node global view creates about 7,249 DOM nodes and remains mostly responsive.
- 5000-node global view creates about 27,399 DOM nodes; it still completes the key actions, but initial render and community entry move into multi-second territory.
- 10000-node global view creates about 52,649 DOM nodes. In this run, pan and node click timed out, while drawer open and community entry were already multi-second actions in the prior 1.2 run.
- Oversized community keeps 3000 nodes present and creates about 17,224 DOM nodes; community entry exposes 1800 nodes, which is too large for a card-heavy reading surface.
Secondary bottlenecks are interaction-state churn and community focus expansion. Search itself is still comparatively cheap, but click-to-reader, drawer open, enter-community, and return-global become slow because they update many DOM/SVG elements and remount or restyle large visible sets.
## Provisional Thresholds
These thresholds are intentionally provisional. They are gates for Phase 4/6 comparison, not final product promises.
| Metric | Provisional pass threshold | Notes |
|---|---:|---|
| Initial render, 1000 nodes | <= 1500 ms | Current 1000 sparse/dense passed. |
| Initial render, 5000 nodes | <= 5000 ms | Current 5000 sparse passed but is close enough to watch. |
| Initial render, 10000 nodes | <= 8000 ms | Current 10000 exceeded this; global path needs degradation or another renderer. |
| Wheel zoom | >= 30 FPS and p95 <= 35 ms | 1000 and 5000 passed; low FPS is a failure class. |
| Pan | <= 300 ms or explicit failure class | 10000 timed out in this run. |
| Hover | <= 500 ms | All measured shapes passed here. |
| Search highlight | <= 500 ms | Current search is not the first bottleneck. |
| Node click | <= 800 ms for 1000, <= 1500 ms for 5000, <= 2000 ms for 10000 | 10000 timed out in this run. |
| Drawer open | <= 1000 ms for 1000, <= 2500 ms for 5000, <= 3000 ms for 10000 | Prior 1.2 result showed 10000 drawer open can reach 7600 ms. |
| Enter community | <= 1500 ms for normal community, <= 3000 ms for large/oversized community | 10000 and oversized community exceed the target. |
| Return global | <= 3500 ms for 1000, <= 5000 ms for 5000, <= 5000 ms for 10000 | Current 1000 is already near the limit. |
| Repeated cycle memory growth | <= 10 MB for 1000-node cycle | Current 1000 cycle showed no growth in available memory field. |
## Interpretation
The current renderer is acceptable for small graph and community reading, but it is not a proven 10000+ global renderer. The next implementation phases should keep DOM/SVG for community/detail views while treating 5000/10000 global browsing as requiring budget enforcement, aggregation, or a different global rendering route.
## Phase 4.1 Render Budgets
These budgets are the first shared graph-layer caps derived from the DOM/SVG bottleneck class above. They are not the final large-graph renderer decision; they prevent the current renderer from producing card-heavy or edge-heavy global output while Phase 6 evaluates the global route.
| View | Max visible nodes | Max visible edges | Max labels | Max full cards | Max interaction-time updates |
|---|---:|---:|---:|---:|---:|
| Global | 10000 | 1000 | 40 | 0 | 1200 |
| Community focus | 2500 | 1500 | 120 | 60 | 1800 |
Overflow is reported by the shared render model for nodes, edges, labels, cards, and interaction updates so drawer/list states can expose omitted detail without forcing it onto the canvas. Selection, search results, and Pin hints may promote priority, but they do not raise these caps.
@@ -0,0 +1,97 @@
# Phase 1.4 Disposable Validation Gate
Date: 2026-06-18
Branch: `codex/large-graph-performance-experience`
Task: `1.4`
## Purpose
This note closes the Phase 1 validation gate before product behavior changes. It records how generated large graphs are measured, how real graph snapshots should be handled, which browser environment is usable, what stress limits are realistic, and which assumptions must stay portable for a future desktop app.
## Validation Result
The current offline graph entry can load generated large graph shapes without new product-code integration. The dedicated runner builds temporary offline HTML from generated graph data, opens it in Playwright Chromium, records fixed-schema measurements, and writes artifacts outside git.
Evidence:
- `tests/browser/graph-large-performance.ts`
- `tests/graph-browser-large-performance.regression-1.sh`
- `/tmp/llm-wiki-graph-large-perf-task-1-2/large-graph-performance-results.json`
- `/tmp/llm-wiki-graph-large-perf-task-1-3/large-graph-performance-results.json`
- `docs/graph/performance/2026-06-18-phase-1-3-dom-svg-large-baseline.md`
## Real Graph Source And Privacy Policy
Generated fixtures are the default reproducible source for Phase 1 and should remain committed only as generator code, not as large JSON outputs.
A real graph snapshot may be added later only as an uncommitted or sanitized artifact:
- Owner: the developer running the benchmark exports it from a local knowledge base.
- Location: `/tmp/llm-wiki-real-graph-snapshot-<date>/graph-data.json` or another ignored local path.
- Git policy: real snapshots are excluded from git unless explicitly anonymized and reviewed.
- Privacy handling: remove source paths, personal names, private project names, raw content, and unique file-system paths before sharing or committing.
- Reproduction: record node/edge/community counts, largest community size, search-hit count, Pin count, export command, hash of sanitized data, and benchmark artifact path.
- If the real graph contains private data and cannot be anonymized, use the generated `real-snapshot-proxy` shape instead.
## Edge Count Caps
The stress goal is to measure product-like behavior, not arbitrary impossible graphs. Current caps for this plan:
| Shape | Node cap | Edge cap | Reason |
|---|---:|---:|---|
| 1000 sparse | 1000 | 1400 | Baseline navigation and interaction. |
| 1000 dense | 1000 | 12000 | Dense local relation pressure while still fitting current visible edge budget. |
| 5000 sparse | 5000 | 6500 | Large global map with realistic sparse connectivity. |
| 5000 dense | 5000 | 60000 | Stress candidate, not default runner path. |
| 10000 aggregation | 10000 | 14000 | Target global browsing shape. |
| 10000 high-edge | 10000 | 90000 | Stress candidate for renderer trials, not required for every smoke run. |
| oversized-community | 3000 | 7000 | Tests one oversized community without pretending all cards can stay visible. |
The current DOM/SVG renderer visibly caps rendered edges at 1000 in the measured global view. That is useful evidence, but it is not a final large-graph solution.
## Browser Environment
Measured browser environment is available. Performance phases are not blocked.
- Runner command: `GRAPH_LARGE_PERF_ARTIFACT_DIR=/tmp/llm-wiki-graph-large-perf-task-1-3 bash tests/graph-browser-large-performance.regression-1.sh`
- Browser package path: resolved through `npx --yes -p playwright`.
- Executable path: `/Users/kangjiaqi/Library/Caches/ms-playwright/chromium-1228/chrome-mac-arm64/Google Chrome for Testing.app/Contents/MacOS/Google Chrome for Testing`.
- Local ports: not required for the offline generated graph runner. Workbench browser checks may still need local ports in later phases.
- Browser plugin fallback: allowed only for functional visual checks when scriptable checks fail; it cannot replace performance artifacts.
## Trial Dependency Path
No production dependency was added in Phase 1. Playwright was used through temporary `npx --yes -p playwright` resolution and local browser cache for measurement.
For Phase 6:
- Sigma/Graphology and vis-network may be installed only for isolated renderer trials when the current task requires them.
- Any package change must be recorded in the progress decision log before it lands.
- Production adoption remains blocked until the Phase 6 route decision.
- At most one production global graph route may survive. Aggregation-first may be a staged chosen route, but it must not become a second parallel global graph product.
## Oversized Community Semantics
For Phase 4 tests, "complete community presence" must not mean rendering every internal item as a full card at once. It may mean:
- A visible community container or outline.
- Representative core nodes as cards.
- Remaining members as points, count badges, or an internal list in the drawer.
- Search hits, selected objects, and pinned objects remain visible or explicitly represented.
- A clear action to drill into a bounded community reading surface.
The oversized-community fixture has 3000 nodes, 7000 edges, 15 communities, and one 1800-node community. Current DOM/SVG behavior exposes too many card-like nodes for this shape and recorded slow entry/return behavior in Phase 1.3.
## Desktop-App Compatibility Guardrails
Graph semantics must remain reusable if the product later moves into a desktop shell. Avoid binding product logic to browser-only assumptions:
- Do not store graph semantics only in DOM attributes. DOM attributes may mirror state for rendering/tests, but graph identity, selection, search, Pin, filter, and community rules belong in shared graph-engine data structures.
- Do not make `window`, `document`, `localStorage`, URL routing, or CSS selectors the source of truth for graph behavior.
- Keep file-system paths and workspace paths behind host adapters; shared graph semantics should use object ids, community ids, and wiki-relative ids.
- Renderer candidates may use Canvas/WebGL/browser APIs, but semantic contracts must stay independent enough to run behind a desktop webview or native shell bridge.
- Persisted Pin/layout state should stay serializable and portable, not tied to one browser storage implementation.
## Throwaway Code Policy
Phase 1 did not leave throwaway validation code in product paths. The generated graph runner became a deliberate test harness under `tests/browser/`; temporary graph HTML and JSON artifacts remain under `/tmp` and are not committed.
@@ -0,0 +1,168 @@
# Phase 2.4 Global Renderer Trial Matrix
Date: 2026-06-18
Branch: `codex/large-graph-performance-experience`
Task: `2.4`
## Purpose
This note defines the trial boundary before any global large-graph renderer candidate is installed, measured, or wired into the product. The project will compare WebGL, Canvas, and no-new-dependency aggregation with the same data, semantics, graph shapes, and performance records. It will ship at most one production global graph route.
Current DOM/SVG remains the known route for small graphs, community reading, offline detail, and UI-rich cards. It is not assumed to be the final 10000+ global route.
## Non-Negotiable Route Rule
Only one production global large-graph route may survive the decision phase.
- Candidate trials may coexist only in isolated harness code and measurement artifacts.
- The workbench must not expose multiple global graph experiences as parallel product modes.
- Aggregation-first may be selected as a staged production route if it wins the decision, but it must not become a permanent second route next to a WebGL or Canvas global renderer.
- DOM/SVG can remain for community/detail surfaces even if a different route wins for the global map.
## Shared Trial Inputs
Every candidate must consume the Phase 2 shared renderer adapter contract before product-specific behavior is evaluated.
Required semantic inputs:
- Object ids: node id, community id, aggregation id.
- State: selected object, search hits, Pin hints, focused community, filters.
- Aggregation metadata: contained node ids, selected internal node ids, search-hit ids, pinned ids, total count.
- Drawer targets: node summary, community summary, excluded aggregation object.
- Commands: enter community, show object, clear temporary object, open detail/read, set fixed position.
Required graph shapes:
| Shape | Nodes | Edge cap | Required in Phase 6? | Purpose |
|---|---:|---:|---|---|
| real-snapshot-proxy | 1000 | 1600 | yes | Proxy for a realistic medium wiki graph. |
| nodes-1000-sparse | 1000 | 1400 | yes | Baseline interaction and correctness. |
| nodes-1000-dense | 1000 | 12000 | yes | Dense local relation pressure. |
| nodes-5000-sparse | 5000 | 6500 | yes | First large global target. |
| nodes-5000-dense | 5000 | 60000 | yes | Edge-heavy 5000-node pressure. |
| nodes-10000-aggregation | 10000 | 14000 | yes | Primary 10000+ global target. |
| nodes-10000-high-edge | 10000 | 90000 | yes | Extreme edge pressure for the renderer decision. |
| oversized-community | 3000 | 7000 | yes | One huge community without full-card rendering. |
| many-small-communities | 5000 | 6000 | yes | Many tiny communities and legend/container pressure. |
| many-search-hits | 5000 | 7000 | yes | Search highlight pressure. |
| many-pin-nodes | 5000 | 7000 | yes | Pin/selected preservation pressure. |
## Candidate Matrix
| Candidate | Technology | Trial role | Strength to prove | Main rejection reasons | Dependency status |
|---|---|---|---|---|---|
| Sigma/Graphology | WebGL + graph model | First global renderer candidate | 5000/10000 point map remains smooth while preserving llm-wiki selection/search/Pin/drawer semantics | Semantic contract cannot be preserved, desktop webview risk is too high, memory grows across cycles, integration forces a second product logic path, performance does not beat aggregation enough | Requires explicit trial dependency approval before package changes. |
| vis-network | Canvas | Strong comparison candidate | Canvas path handles large global interactions with less integration cost than WebGL | Built-in interaction model fights llm-wiki drawer/community/search semantics, layout ownership becomes opaque, Pin/fixed-position behavior is unstable, performance or memory falls below WebGL/aggregation | Requires explicit trial dependency approval before package changes. |
| Aggregation fallback | Current stack, no new dependency | No-new-dependency fallback or staged route | 10000+ global map is useful by showing communities, skeleton edges, selected/search/Pin markers, and overflow lists without full node detail | Users lose too much spatial context, search/Pin/selected objects are not discoverable, container interactions feel like a separate product, oversized communities remain slow | No dependency approval required. |
## Required Metrics
Every measured candidate must produce fixed-schema artifacts comparable to the Phase 1 DOM/SVG baseline.
Required action records:
- initial render
- wheel zoom FPS and p95 frame time
- pan
- hover or nearest-object inspect
- search highlight
- point select
- container select
- drawer open
- enter community
- return global
- repeated cycle memory growth for every required shape
Required metadata fields:
- renderer id
- candidate version and package versions, if any
- graph shape
- node count
- edge count
- community count
- largest community size
- search hit count
- Pin count
- visible object count
- browser environment
- artifact path
- pass/fail
- failure class and detail
## Provisional Acceptance Table
These thresholds are comparison gates, not final product promises.
| Metric | 1000 nodes | 5000 nodes | 10000 nodes | Notes |
|---|---:|---:|---:|---|
| Initial render | <= 1500 ms | <= 5000 ms | <= 8000 ms | Current DOM/SVG exceeded the 10000 target. |
| Wheel zoom | >= 30 FPS | >= 30 FPS | >= 30 FPS | Lower result must record `fps_below_floor`. |
| Pan | <= 300 ms | <= 500 ms | <= 800 ms | Timeout is a blocking failure for a candidate route. |
| Search highlight | <= 500 ms | <= 800 ms | <= 1200 ms | Search must update highlight/markers without full graph relayout. |
| Point select | <= 800 ms | <= 1500 ms | <= 2000 ms | Must open lightweight summary target, not full reading by default. |
| Container select | <= 1000 ms | <= 2000 ms | <= 2500 ms | Community/aggregation selection must keep global context. |
| Drawer open | <= 1000 ms | <= 2500 ms | <= 3000 ms | Long content rendering is not part of global lightweight drawer. |
| Return global | <= 3500 ms | <= 5000 ms | <= 5000 ms | Route must not rebuild unnecessary detail. |
| Repeated cycle memory growth | <= 50 MB | <= 75 MB | <= 100 MB | If the browser cannot expose memory, record that explicitly instead of silently passing. |
## Browser Verification Boundary
Scripted browser trials remain the route-decision evidence because they generate repeatable JSON artifacts across all graph shapes and actions.
The Codex Browser plugin is an approved fallback for human-like visual and interaction checks when a local Playwright package or Chrome path is unavailable. It can validate that a page opens, visible graph controls respond, and the lightweight drawer flow matches user expectations. It must not replace the fixed-schema performance artifacts for renderer selection, because route decisions need comparable records across WebGL, Canvas, and aggregation fallback candidates.
## Desktop-App Compatibility Checks
The later desktop app direction means a candidate cannot win by hiding product logic in browser-only surfaces.
Required checks:
- Graph meaning remains in graph-engine data, not DOM attributes or renderer internals.
- Host integration can be driven by ids, serializable state, and commands.
- Pin/layout state remains portable and wiki-relative.
- Candidate-specific event handling does not own product decisions such as open detail, enter community, or selected object policy.
- The route can run inside a desktop webview or be wrapped behind a native shell bridge without rewriting graph semantics.
## Trial Harness Boundary
Allowed in Phase 6:
- Isolated candidate harness modules.
- Temporary renderer pages or browser fixtures under `tests/browser/`.
- Measurement reports under `docs/graph/performance/`.
- Trial dependencies after explicit approval is recorded.
Not allowed before the route decision:
- Switching the workbench production global view to a candidate renderer.
- Adding a production dependency for the final app route.
- Leaving multiple candidate renderers active as user-facing modes.
- Recomputing graph product semantics inside candidate-specific code.
## Dependency Approval Record Needed
If Phase 6 needs trial packages, the progress decision log must record exact approval before package changes land.
Expected approval entry format:
```text
Task 6.x dependency approval: install <package names and versions> only for isolated renderer trial harness; no production adoption until Phase 6.4 route decision.
```
Expected package classes:
- Sigma/Graphology trial: `sigma`, `graphology`, and any narrowly required layout/helper package.
- vis-network trial: `vis-network` or the maintained package name selected at trial time.
- Aggregation fallback: no package expected.
## Decision Output
Phase 6.4 must produce one of these outcomes:
- Integrate Sigma/Graphology as the single global large-graph route in a future implementation plan.
- Integrate vis-network as the single global large-graph route in a future implementation plan.
- Ship aggregation-first as the single staged global route, with explicit limits and follow-up research.
- Reject all candidates and continue renderer research with recorded failure reasons.
The decision report must include accepted route, rejected alternatives, evidence artifact paths, unresolved risks, and whether community/detail DOM/SVG remains unchanged.
@@ -0,0 +1,71 @@
# Phase 6.1 Sigma/Graphology WebGL Trial
Date: 2026-06-19
Branch: `codex/large-graph-performance-experience`
Task: `6.1`
Renderer: isolated Sigma/Graphology WebGL trial
## Scope
This report evaluates Sigma/Graphology as the first global large-graph renderer candidate. It does not switch the production workbench graph path. Current DOM/SVG remains the rich small-graph and community-reading path until the Phase 6.4 route decision.
The trial uses the shared graph adapter contract so object ids, community ids, search hits, Pin hints, selected objects, and aggregation markers remain portable across later browser or desktop shells.
## Commands
- `git log --oneline -15`
- `npm run test --workspace=@llm-wiki/graph-engine`
- `npm install -w @llm-wiki/graph-engine -D sigma@3.0.3 graphology@0.26.0`
- `node --import tsx --check tests/browser/graph-sigma-graphology-trial.ts`
- `node --import tsx --test packages/graph-engine/test/sigma-trial-adapter.test.ts`
- `GRAPH_SIGMA_TRIAL_ARTIFACT_DIR=/tmp/llm-wiki-graph-sigma-trial-task-6-1 bash tests/graph-sigma-graphology-trial.regression-1.sh`
## Artifacts
Machine-readable result:
- `/tmp/llm-wiki-graph-sigma-trial-task-6-1/sigma-graphology-trial-results.json`
The artifact contains 47 fixed-schema records across 5 graph shapes.
## Post-Review Harness Hardening
The original result table below is now treated as a historical isolation baseline. After review, the Sigma trial harness was hardened so a run fails when any action record fails, any failure class is present, any required action is missing, any requested shape is missing, or the wrapper only produced a JSON file without valid contents.
The default shape set was expanded from 5 shapes to the full 11-shape stress matrix: realistic proxy, 1000 sparse/dense, 5000 sparse/dense, 10000 aggregation/high-edge, oversized community, many small communities, many search hits, and many Pin nodes. Repeated interaction/memory cycles now run on every requested shape instead of only 1000-node shapes.
Interaction timing now waits for visible render completion after scripted actions. Sigma uses animation-frame completion checks after search, selection, drawer, community, and return-global actions. A hardened rerun is required before using these numbers as final production-integration evidence.
## Result Table
| Shape | Nodes | Edges | DOM nodes | Initial | Wheel | Pan | Search | Point | Container | Drawer | Community | Return | Cycle |
|---|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|
| nodes-1000-sparse | 1000 | 1400 | 18 | pass (146.2 ms) | pass (60.2 FPS) | pass (274.0 ms) | pass (9.4 ms) | pass (2.9 ms) | pass (4.5 ms) | pass (0.7 ms) | pass (7.6 ms) | pass (2.1 ms) | pass (0 MB growth) |
| nodes-1000-dense | 1000 | 12000 | 18 | pass (116.7 ms) | pass (60.6 FPS) | pass (268.1 ms) | pass (11.5 ms) | pass (8.3 ms) | pass (6.7 ms) | pass (0.5 ms) | pass (9.0 ms) | pass (7.1 ms) | pass (0 MB growth) |
| nodes-5000-sparse | 5000 | 6500 | 18 | pass (175.3 ms) | pass (60.5 FPS) | pass (269.3 ms) | pass (23.4 ms) | pass (13.0 ms) | pass (8.5 ms) | pass (0.6 ms) | pass (11.8 ms) | pass (12.0 ms) | not run |
| nodes-10000-aggregation | 10000 | 14000 | 18 | pass (289.1 ms) | pass (60.9 FPS) | pass (272.5 ms) | pass (40.9 ms) | pass (14.6 ms) | pass (18.5 ms) | pass (0.5 ms) | pass (19.0 ms) | pass (13.0 ms) | not run |
| oversized-community | 3000 | 7000 | 18 | pass (140.6 ms) | pass (60.7 FPS) | pass (268.2 ms) | pass (14.7 ms) | pass (6.9 ms) | pass (6.9 ms) | pass (0.5 ms) | pass (8.7 ms) | pass (6.0 ms) | not run |
## Comparison To Current DOM/SVG Baseline
| Shape | DOM/SVG initial | Sigma initial | DOM/SVG wheel | Sigma wheel | DOM/SVG notable failure |
|---|---:|---:|---:|---:|---|
| nodes-1000-sparse | 900.4 ms | 146.2 ms | 60.0 FPS | 60.2 FPS | none |
| nodes-1000-dense | 1008.4 ms | 116.7 ms | 59.6 FPS | 60.6 FPS | none |
| nodes-5000-sparse | 4615.6 ms | 175.3 ms | 51.3 FPS | 60.5 FPS | none |
| nodes-10000-aggregation | 8836.0 ms | 289.1 ms | 36.8 FPS | 60.9 FPS | pan and node click timeout |
| oversized-community | 15788.6 ms | 140.6 ms | 12.9 FPS | 60.7 FPS | near unusable wheel FPS |
## Interpretation
Sigma/Graphology is a strong candidate for the global browsing route. The trial keeps DOM output constant, handles 10000 nodes without the DOM/SVG timeout classes, and preserves the shared semantic contract.
This is still not the final route decision. Phase 6 must also compare vis-network Canvas and the no-new-dependency aggregation fallback before selecting one production global renderer path. The trial also uses a minimal drawer and simple visual update model; production integration still needs design-fit, input semantics, theming, accessibility, and desktop packaging checks.
## Acceptance Evidence
- Historical shapes measured: 1000 sparse, 1000 dense, 5000 sparse, 10000 aggregation, and oversized-community.
- Hardened default shapes now include the full 11-shape stress matrix.
- Required actions are now enforced for every requested shape: initial render, pan, zoom, search highlight, point select, container select, drawer open, enter community, return global, and repeated memory cycle.
- Behavior parity test passed: `node --import tsx --test packages/graph-engine/test/sigma-trial-adapter.test.ts`.
- No production workbench renderer path was switched.
@@ -0,0 +1,78 @@
# Phase 6.2 vis-network Canvas Trial
Date: 2026-06-19
Branch: `codex/large-graph-performance-experience`
Task: `6.2`
Renderer: isolated vis-network Canvas trial
## Scope
This report evaluates vis-network as the Canvas comparison candidate. It does not switch the production workbench graph path. Current DOM/SVG remains the rich small-graph and community-reading path until the Phase 6.4 route decision.
The trial uses the same graph shapes and interaction actions as the Sigma/Graphology trial. It also uses a shared graph-engine adapter contract so object ids, community ids, search hits, Pin hints, selected objects, and aggregation markers remain portable.
## Commands
- `git log --oneline -15`
- `npm run test --workspace=@llm-wiki/graph-engine`
- `npm install -w @llm-wiki/graph-engine -D vis-network`
- `node --import tsx --check tests/browser/graph-vis-network-trial.ts`
- `node --import tsx --test packages/graph-engine/test/vis-network-trial-adapter.test.ts`
- `GRAPH_VIS_TRIAL_ARTIFACT_DIR=/tmp/llm-wiki-graph-vis-trial-task-6-2 bash tests/graph-vis-network-trial.regression-1.sh`
## Artifacts
Machine-readable result:
- `/tmp/llm-wiki-graph-vis-trial-task-6-2/vis-network-trial-results.json`
The artifact contains 47 fixed-schema records across 5 graph shapes.
## Post-Review Harness Hardening
The original result table below is now treated as a historical isolation baseline. After review, the vis-network trial harness was hardened so a run fails when any action record fails, any failure class is present, any required action is missing, any requested shape is missing, or the wrapper only produced a JSON file without valid contents.
The default shape set was expanded from 5 shapes to the full 11-shape stress matrix: realistic proxy, 1000 sparse/dense, 5000 sparse/dense, 10000 aggregation/high-edge, oversized community, many small communities, many search hits, and many Pin nodes. Repeated interaction/memory cycles now run on every requested shape instead of only 1000-node shapes.
Interaction timing now waits for visible render completion after scripted actions. vis-network uses `afterDrawing` completion checks for render-affecting actions; the earlier timeout-based ready fallback was removed so a page cannot be marked ready without a completed draw. A hardened rerun is required before using these numbers as final production-integration evidence.
## Result Table
| Shape | Nodes | Edges | DOM nodes | Initial | Wheel | Pan | Search | Point | Container | Drawer | Community | Return | Cycle |
|---|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|
| nodes-1000-sparse | 1000 | 1400 | 20 | pass (117.6 ms) | pass (60.4 FPS) | pass (266.4 ms) | pass (28.0 ms) | pass (18.1 ms) | pass (9.3 ms) | pass (0.6 ms) | pass (7.3 ms) | pass (2.4 ms) | pass (0 MB growth) |
| nodes-1000-dense | 1000 | 12000 | 20 | pass (215.2 ms) | pass (60.4 FPS) | pass (292.0 ms) | pass (40.8 ms) | pass (49.4 ms) | pass (24.7 ms) | pass (0.6 ms) | pass (24.5 ms) | pass (8.4 ms) | pass (0 MB growth) |
| nodes-5000-sparse | 5000 | 6500 | 20 | pass (263.0 ms) | pass (60.2 FPS) | pass (274.3 ms) | pass (81.7 ms) | pass (66.3 ms) | pass (33.3 ms) | pass (0.4 ms) | pass (32.5 ms) | pass (9.8 ms) | not run |
| nodes-10000-aggregation | 10000 | 14000 | 20 | pass (456.5 ms) | pass (60.9 FPS) | pass (331.6 ms) | pass (148.0 ms) | pass (138.3 ms) | pass (91.0 ms) | pass (5.2 ms) | pass (94.6 ms) | pass (19.3 ms) | not run |
| oversized-community | 3000 | 7000 | 20 | pass (216.5 ms) | pass (60.5 FPS) | pass (270.5 ms) | pass (63.1 ms) | pass (46.4 ms) | pass (27.1 ms) | pass (0.5 ms) | pass (25.8 ms) | pass (7.0 ms) | not run |
## Comparison To Sigma And DOM/SVG
| Shape | DOM/SVG initial | Sigma initial | vis-network initial | Sigma search | vis-network search | Sigma point | vis-network point |
|---|---:|---:|---:|---:|---:|---:|---:|
| nodes-1000-sparse | 900.4 ms | 146.2 ms | 117.6 ms | 9.4 ms | 28.0 ms | 2.9 ms | 18.1 ms |
| nodes-1000-dense | 1008.4 ms | 116.7 ms | 215.2 ms | 11.5 ms | 40.8 ms | 8.3 ms | 49.4 ms |
| nodes-5000-sparse | 4615.6 ms | 175.3 ms | 263.0 ms | 23.4 ms | 81.7 ms | 13.0 ms | 66.3 ms |
| nodes-10000-aggregation | 8836.0 ms | 289.1 ms | 456.5 ms | 40.9 ms | 148.0 ms | 14.6 ms | 138.3 ms |
| oversized-community | 15788.6 ms | 140.6 ms | 216.5 ms | 14.7 ms | 63.1 ms | 6.9 ms | 46.4 ms |
Both candidate renderers remove the current DOM/SVG bottleneck class for global browsing. vis-network keeps wheel zoom near 60 FPS on all required shapes, but it is slower than Sigma/Graphology for search, point selection, and container/community updates in this isolated harness.
## Integration Risks
- vis-network owns more of the interaction and selection model by default. The trial disables physics and routes selection through explicit shared commands to avoid fighting llm-wiki drawer/community/search semantics.
- Layout ownership can become opaque if production integration enables vis-network physics or stabilization. Pin and fixed-position behavior should remain owned by graph-engine, not by vis-network runtime state.
- The Canvas route depends on DataSet mutation patterns. Search and selection are still acceptable in this trial, but they scale worse than the Sigma candidate on the same data.
- Desktop packaging is plausible because the semantic layer remains outside the renderer, but production integration would need a strict adapter boundary to prevent product logic from moving into vis-network callbacks.
## Interpretation
vis-network is a viable Canvas comparison candidate, but this trial does not currently beat Sigma/Graphology on the important semantic-update actions. It remains in the Phase 6 comparison set until the aggregation fallback and final route decision are recorded.
## Acceptance Evidence
- Historical shapes measured: 1000 sparse, 1000 dense, 5000 sparse, 10000 aggregation, and oversized-community.
- Hardened default shapes now include the full 11-shape stress matrix.
- Required actions are now enforced for every requested shape: initial render, pan, zoom, search highlight, point select, container select, drawer open, enter community, return global, and repeated memory cycle.
- Behavior parity test passed: `node --import tsx --test packages/graph-engine/test/vis-network-trial-adapter.test.ts`.
- No production workbench renderer path was switched.
@@ -0,0 +1,72 @@
# Phase 6.3 Aggregation Fallback Trial
Date: 2026-06-19
Branch: `codex/large-graph-performance-experience`
Task: `6.3`
Renderer: no-new-dependency aggregation fallback trial
## Scope
This report evaluates the no-new-dependency fallback route using the current graph-engine budget and aggregation semantics. It does not switch the production workbench graph path.
The trial renders lightweight global points, capped skeleton edges, capped labels, aggregation containers, and a lightweight drawer. It intentionally does not render global cards. This tests whether the current stack can provide a fast structural overview without pretending it is a full 10000+ detailed renderer.
## Commands
- `git log --oneline -15`
- `npm run test --workspace=@llm-wiki/graph-engine`
- `node --import tsx --check tests/browser/graph-aggregation-fallback-trial.ts`
- `node --import tsx --test packages/graph-engine/test/aggregation-fallback-trial-adapter.test.ts`
- `GRAPH_AGGREGATION_TRIAL_ARTIFACT_DIR=/tmp/llm-wiki-graph-aggregation-trial-task-6-3 bash tests/graph-aggregation-fallback-trial.regression-1.sh`
## Artifacts
Machine-readable result:
- `/tmp/llm-wiki-graph-aggregation-trial-task-6-3/aggregation-fallback-trial-results.json`
The artifact contains 47 fixed-schema records across 5 graph shapes.
## Post-Review Harness Hardening
The original result table below is now treated as a historical isolation baseline. After review, the aggregation fallback trial harness was hardened so a run fails when any action record fails, any failure class is present, any required action is missing, any requested shape is missing, or the wrapper only produced a JSON file without valid contents.
The default shape set was expanded from 5 shapes to the full 11-shape stress matrix: realistic proxy, 1000 sparse/dense, 5000 sparse/dense, 10000 aggregation/high-edge, oversized community, many small communities, many search hits, and many Pin nodes. Repeated interaction/memory cycles now run on every requested shape instead of only 1000-node shapes.
Interaction timing now waits for animation-frame completion after scripted actions. The aggregation fallback still uses internal `zoomBy` and `panBy` helpers for zoom and pan, so its zoom/pan numbers are useful for current-stack fallback pressure but are not directly equivalent to the real mouse-input measurements in the Sigma and vis-network trials.
## Result Table
| Shape | Nodes | Edges | DOM nodes | Visible nodes | Visible edges | Labels | Cards | Initial | Wheel | Search | Hidden interaction objects |
|---|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|
| nodes-1000-sparse | 1000 | 1400 | 2053 | 1000 | 1000 | 40 | 0 | pass (71.7 ms) | pass (60.2 FPS) | pass (12.0 ms) | 34 |
| nodes-1000-dense | 1000 | 12000 | 2053 | 1000 | 1000 | 40 | 0 | pass (66.1 ms) | pass (60.1 FPS) | pass (11.4 ms) | 34 |
| nodes-5000-sparse | 5000 | 6500 | 6103 | 5000 | 1000 | 40 | 0 | pass (136.4 ms) | pass (60.7 FPS) | pass (64.2 ms) | 4034 |
| nodes-10000-aggregation | 10000 | 14000 | 11153 | 10000 | 1000 | 40 | 0 | pass (185.9 ms) | pass (60.6 FPS) | pass (184.6 ms) | 9034 |
| oversized-community | 3000 | 7000 | 4068 | 3000 | 1000 | 40 | 0 | pass (92.2 ms) | pass (60.2 FPS) | pass (40.6 ms) | 2034 |
## Comparison To Renderer Candidates
| Shape | Sigma initial | vis-network initial | Aggregation initial | Sigma search | vis-network search | Aggregation search |
|---|---:|---:|---:|---:|---:|---:|
| nodes-1000-sparse | 146.2 ms | 117.6 ms | 71.7 ms | 9.4 ms | 28.0 ms | 12.0 ms |
| nodes-1000-dense | 116.7 ms | 215.2 ms | 66.1 ms | 11.5 ms | 40.8 ms | 11.4 ms |
| nodes-5000-sparse | 175.3 ms | 263.0 ms | 136.4 ms | 23.4 ms | 81.7 ms | 64.2 ms |
| nodes-10000-aggregation | 289.1 ms | 456.5 ms | 185.9 ms | 40.9 ms | 148.0 ms | 184.6 ms |
| oversized-community | 140.6 ms | 216.5 ms | 92.2 ms | 14.7 ms | 63.1 ms | 40.6 ms |
## Product Interpretation
Aggregation fallback is fast enough for a structural global overview. It keeps global cards at zero, caps labels at 40, caps visible edges at 1000, and preserves selected/search/Pin/container semantics through the shared adapter.
It is not equivalent to a full global renderer. At 10000 nodes it hides 9034 interaction-time objects and depends on the drawer/list layer to expose omitted detail. That is acceptable as a fallback or staged route, but not enough by itself for rich 10000+ exploration if the product wants direct large-map inspection with full relation density.
## Acceptance Evidence
- Historical shapes measured: 1000 sparse, 1000 dense, 5000 sparse, 10000 aggregation, and oversized-community.
- Hardened default shapes now include the full 11-shape stress matrix.
- Required actions are now enforced for every requested shape: initial render, pan, zoom, search highlight, point select, container select, drawer open, enter community, return global, and repeated memory cycle.
- Required fallback elements present: aggregation containers, skeleton edges, selected/search/Pin markers, and lightweight drawer overflow path.
- Behavior parity test passed: `node --import tsx --test packages/graph-engine/test/aggregation-fallback-trial-adapter.test.ts`.
- No new dependency was added for this task.
- No production workbench renderer path was switched.
@@ -0,0 +1,94 @@
# Phase 6.4 Global Renderer Route Decision
Date: 2026-06-19
Branch: `codex/large-graph-performance-experience`
Task: `6.4`
## Decision
Select Sigma/Graphology WebGL as the future single global large-graph renderer integration route.
This task records the route decision only. It does not switch the production workbench renderer, add a production renderer path, or remove the current DOM/SVG renderer. Current DOM/SVG remains the rich small-graph and community-reading path.
Post-review status: this remains the current route preference, not a final production integration proof. The original Phase 6 tables were produced by the first isolated harness. The hardened harness now requires the full 11-shape matrix, complete action coverage, failed-record detection, large-shape repeated cycles, and render-completion waits. The next production integration plan must rerun the hardened trials before treating the Sigma choice as locked.
## Why Sigma/Graphology Wins
Sigma/Graphology is the best fit for the product goal: smooth 5000+ / 10000+ global browsing while preserving llm-wiki graph semantics outside the renderer.
Measured evidence:
| Shape | Sigma initial | Sigma wheel | Sigma search | Sigma point select | Sigma container select |
|---|---:|---:|---:|---:|---:|
| nodes-1000-sparse | 146.2 ms | 60.2 FPS | 9.4 ms | 2.9 ms | 4.5 ms |
| nodes-1000-dense | 116.7 ms | 60.6 FPS | 11.5 ms | 8.3 ms | 6.7 ms |
| nodes-5000-sparse | 175.3 ms | 60.5 FPS | 23.4 ms | 13.0 ms | 8.5 ms |
| nodes-10000-aggregation | 289.1 ms | 60.9 FPS | 40.9 ms | 14.6 ms | 18.5 ms |
| oversized-community | 140.6 ms | 60.7 FPS | 14.7 ms | 6.9 ms | 6.9 ms |
The historical trial also kept DOM output constant at 18 nodes, passed behavior parity for object ids, community ids, search hits, Pin hints, selected objects, and aggregation markers, and did not switch the production renderer path.
## Rejected Alternatives
### vis-network Canvas
vis-network is viable, but it is not the chosen route.
Reasons:
- It was slower than Sigma/Graphology on semantic updates that matter to llm-wiki: search, point select, and container/community updates.
- On the 10000-node shape, vis-network search took 148.0 ms versus Sigma/Graphology at 40.9 ms.
- On the 10000-node shape, vis-network point select took 138.3 ms versus Sigma/Graphology at 14.6 ms.
- vis-network owns more built-in selection, physics, stabilization, and interaction behavior. That creates higher risk that product semantics drift into renderer callbacks instead of staying in `packages/graph-engine/`.
vis-network remains a measured fallback candidate if a future Sigma integration hits a hard blocker, but it should not be integrated in parallel.
### Aggregation-Only Fallback
Aggregation-only is not enough to become the full global large-graph route.
Reasons:
- It is very fast for a structural overview, including 185.9 ms initial render and 60.6 FPS wheel zoom on the 10000-node shape.
- It intentionally caps visible edges at 1000, labels at 40, cards at 0, and hides thousands of interaction-time objects at large sizes.
- On the 10000-node shape it hid 9034 interaction-time objects, so it depends on drawer/list overflow to expose omitted detail.
Aggregation remains a required degradation strategy inside the future global route: keep global cards at zero, cap labels and edges, preserve selected/search/Pin objects, and use drawer overflow for omitted detail. It must not become a second permanent global graph product beside Sigma/Graphology.
### Current DOM/SVG As Global Renderer
Current DOM/SVG is rejected as the final 5000+ / 10000+ global renderer.
Reasons:
- The Phase 1 baseline showed 10000-node initial render at 8836.0 ms, wheel zoom at 36.8 FPS, and pan/node-click timeout classes.
- Oversized-community DOM/SVG wheel zoom was 12.9 FPS.
- DOM/SVG remains appropriate for small graphs, scoped community reading, offline detail, and UI-rich card surfaces.
## Integration Boundary For The Next Plan
The next implementation plan should integrate Sigma/Graphology only for global large-graph browsing, behind the shared renderer adapter boundary.
Required boundaries:
- `packages/graph-engine/` remains the owner of object ids, community ids, search, filters, Pin, selection, aggregation, budgets, and drawer command semantics.
- Sigma/Graphology owns only global drawing, viewport interaction, and renderer-level hit projection through a shared adapter.
- Workbench receives the same lightweight node summary, community summary, open-detail, enter-community, return-global, and unavailable/excluded payloads it receives today.
- Community reading continues to use the current DOM/SVG rich path unless a later plan proves a different scoped renderer.
- Desktop compatibility remains a guardrail: renderer integration may use browser/WebGL APIs internally, but graph semantics must stay serializable and portable across a desktop webview or shell bridge.
- Aggregation budgets remain active in the global route so 10000+ views do not reintroduce full-card or unlimited-edge rendering.
## Next Plan Direction
The next plan should integrate Sigma/Graphology as the single production global renderer route only after a hardened rerun confirms the full 11-shape matrix. DOM/SVG should remain the community-reading renderer.
It should not integrate vis-network or ship a separate aggregation-only global product in parallel. If Sigma/Graphology integration fails on a hard blocker, the plan should stop and record the blocker before considering vis-network or aggregation-first as a replacement route.
## Acceptance Evidence
- Sigma/Graphology historically measured the first 5 graph shapes with 47 fixed-schema records and 0 errors.
- vis-network historically measured the same first 5 shapes and was rejected with semantic update and ownership-risk evidence.
- Aggregation fallback historically measured the same first 5 shapes and was retained only as degradation strategy and fallback evidence, not as a full global renderer.
- Post-review harness now requires the full 11-shape matrix and blocks failed records instead of accepting result-file existence.
- No production renderer path was added or switched.
- No unapproved production dependency was adopted by this task.
@@ -0,0 +1,102 @@
# Sigma Global Renderer Production Integration Result
Date: 2026-06-19
Branch: `codex/sigma-global-renderer-integration`
Plan: `docs/plans/2026-06-19-sigma-global-renderer-integration-phased-plan.md`
## Result
Sigma/Graphology is now the production global graph renderer route for the graph-engine facade.
The final route boundary is:
- Global route: Sigma/Graphology through `sigma-global`.
- Community reading and rich detail route: DOM/SVG through `dom-svg-community`.
- Small abnormal fallback: DOM/SVG through `dom-svg-small-fallback`, only after Sigma is unavailable and the graph is below the safety threshold.
- Large abnormal fallback: aggregation safety view through `aggregation-safety-fallback`.
There is no user-visible old/new renderer switch. The old DOM/SVG global path is not a normal global main path.
## Phase 0 Gate
The implementation started only after the plan review gate cleared:
- The plan review report ended with `NO UNRESOLVED DECISIONS`.
- The implementation branch was `codex/sigma-global-renderer-integration`.
- Baseline graph-engine tests passed before production renderer work started.
## Production Evidence
The strongest production-path artifact so far is:
- `/tmp/llm-wiki-sigma-global-production-task-6-2/sigma-global-production-results.json`
Summary:
- Renderer: `sigma-global-production`.
- Production path: `true`.
- Browser: `148.0.7778.96`.
- Build commit recorded in artifact: `d2e857f`.
- Shapes: 11.
- Records: 110.
- Failed records: 0.
- Artifact schema: `1.0.0`.
- Required schema, thresholds, browser, build, run timestamp, loading-state, and production-path fields are present on every record.
Covered shapes:
- `real-snapshot-proxy`
- `nodes-1000-sparse`
- `nodes-1000-dense`
- `nodes-5000-sparse`
- `nodes-5000-dense`
- `nodes-10000-aggregation`
- `nodes-10000-high-edge`
- `oversized-community`
- `many-small-communities`
- `many-search-hits`
- `many-pin-nodes`
## Hard Gate Summary
| Gate | Production result |
|---|---:|
| Failed records | 0 |
| Wheel FPS floor | min 60.2, required >= 45 |
| Drag FPS floor | min 60.3, required >= 45 |
| Wheel frame p95 | max 17.6 ms, required <= 22.3 ms |
| Drag frame p95 | max 17.6 ms, required <= 22.3 ms |
| Initial render duration | max 0.2 ms, threshold recorded per action |
| Search duration | max 37.7 ms, threshold recorded per action |
| Drawer duration | max 82.0 ms, threshold recorded per action |
| Return global duration | max 70.5 ms, threshold recorded per action |
| Repeated-cycle memory growth | max 6.4 MB, threshold recorded per action |
| Loading state | `sigma-global-ready` on global records |
`enter_community` intentionally moves through the community route, so its loading-state set includes the non-global transition state as well as `sigma-global-ready`. Return-global records prove the production route returns to Sigma successfully.
## Route And Fallback Boundary
The facade owns renderer route switching. Workbench and offline callers continue to use `createGraphEngine` and do not receive a renderer selector.
Fallback policy:
- If Sigma is available, global graph browsing uses Sigma.
- If Sigma is unavailable for a small graph, DOM/SVG is allowed only as the emergency small fallback.
- If Sigma is unavailable for a graph above 2000 nodes, 4000 edges, or 500 nodes in one community, the route uses aggregation safety fallback instead of DOM/SVG.
- The aggregation safety view is a minimum usable failure state, not a second global graph product.
## Historical Context
Earlier comparison documents remain valid as historical evidence:
- `2026-06-19-phase-6-1-sigma-graphology-trial.md` measured the isolated Sigma candidate.
- `2026-06-19-phase-6-2-vis-network-trial.md` measured vis-network as a rejected comparison route.
- `2026-06-19-phase-6-3-aggregation-fallback-trial.md` measured aggregation as a fallback strategy.
- `2026-06-19-phase-6-4-global-renderer-route-decision.md` selected Sigma/Graphology as the route to integrate.
Those documents should not be read as current production state. This document records the production integration result.
## Residual Risk
This result is proven on the local Chromium/Playwright environment and recorded artifacts. Task 7.3 must still rerun the full final acceptance list and produce the final production-path artifact for plan closure.
@@ -0,0 +1,9 @@
{
"viewport": "1440x960",
"durationMs": 3004,
"frames": 157,
"idleFps": 13.6,
"fps": 52.3,
"minimumInteractionFps": 12,
"transformChanged": true
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 233 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 KiB