What shipped: Phase 3 of v0.1.6. The single registerBasesView registration per Settled #2 + Ch 30. The launch-market Coverage Matrix recipe instance now has a renderer.
What's NOT in Phase 3 (Phases 4-5 pending):
- Recipe-picker UX + embedded
\``base` block insertion (Phase 4) - Opt-in materialization command + sparse-pivot guard with
COUNT(*)pre-execution estimate (Phase 5)
Prerequisite: Obsidian 1.10.0 or later (the public registerBasesView API). On older versions, the plugin loads but shows a Notice; everything else works.
The test-vault ships with the Hot Reload community plugin installed and Crosswalker registered for auto-reload (.hotreload marker file in the plugin directory). When the dev workflow rebuilds main.js, Hot Reload will pick it up automatically — no manual reload needed.
If Hot Reload isn't running (you disabled it, fresh vault, etc.), you MUST manually reload after every rebuild:
- Settings → Community plugins → toggle Crosswalker off, then on, OR
- Ctrl+R inside the dev console (Ctrl+Shift+I → Console → Ctrl+R)
Without a reload, Obsidian keeps the OLD plugin code in memory regardless of what's on disk. Bugs that have been fixed will still appear to be present.
-
bun run test→ 201/201 pass (added 37 new for Phase 3: 31 pivot-grid + 6 reference-base-files) -
bun run build→ clean -
bun run check:fixtures-drift→ no drift
Setup: fresh test vault (or delete _crosswalker/views/coverage-matrix.base if it exists).
Steps:
- Reload the plugin (or start Obsidian fresh)
- Wait for
onLayoutReady(a few seconds after vault opens) - Open
_crosswalker/views/coverage-matrix.base— should exist - Open
_crosswalker/views/folder — verify it was auto-created
Expected: file exists with the reference content (filters + formulas + 2 views: crosswalker-pivot + Bases-native table fallback).
Prerequisite: complete Phase 2 Scenario 1 (import the SSSOM fixture so _crosswalker/mappings/csf-to-iso27001/ has 11 junction notes).
Steps:
- Open
_crosswalker/views/coverage-matrix.basein Obsidian (the.basefile from Scenario 1) - The view picker should show
Coverage matrix(thecrosswalker-pivotcustom view) ANDMappings table(Bases-native fallback) - Switch to
Coverage matrix
Expected:
- 11 rows × 1 col grid (subject_id × object_id) — but ISO 27001 has 9 distinct objects so it'll be ~11 × 9 with mostly-empty cells
- Cells show
1where a mapping exists,—(em-dash) where empty - Footer shows
11 rows × 9 cols · 11 entries · range 1–1
If you don't see the custom view in the picker:
- Settings → Core plugins → verify Bases is enabled
- Check Obsidian version is 1.10.0+
- Check dev console for Notice text (
Crosswalker: pivot view requires Obsidian 1.10.0...orCrosswalker: enable the Bases core plugin...)
Steps:
- With the Coverage matrix view active, open the right-rail view options
- Should see 8 controls:
- Rows by (property picker; default
subject_id) - Cols by (property picker; default
object_id) - Cell aggregation (dropdown: count / count_distinct / sum / avg / min / max / first / last)
- Cell value (for non-count ops) (property picker)
- Empty cells (dropdown: gap / blank / zero)
- Heatmap shading (toggle)
- Row sort (asc / desc / none)
- Col sort (asc / desc / none)
- Rows by (property picker; default
- Change Empty cells to
zero→ verify empty cells now show0instead of— - Change Cell aggregation to
count_distinct→ verify cell count is the same (each (subject, object) pair has 1 row) - Change Rows by to
predicate_idand Cols by tosource_framework→ verify 5 rows (STRM predicates) × 1 col (csf) - Toggle Heatmap shading → verify cells get color shading proportional to value
Steps:
- Edit
_crosswalker/views/coverage-matrix.base— change one of the formulas or add a comment - Save the file
- Reload the plugin (
Ctrl+Rin dev console, or disable + re-enable in settings) - Re-open
_crosswalker/views/coverage-matrix.base
Expected: your edit is preserved. The plugin's first-run writer skips files that already exist (per Settled #3 — preserves user edits).
Steps:
- Settings → Core plugins → disable Bases
- Reload Crosswalker plugin (disable + re-enable in Settings → Community plugins)
- Watch for a Notice
Expected: a Notice appears: Crosswalker: enable the Bases core plugin (Settings → Core plugins → Bases) to use the pivot view. Other features still work.
The plugin still loads; everything else (import, queryCrosswalk, etc.) still works. Re-enable Bases to restore the pivot view.
Steps: this is harder to trigger with the small fixture. Skip unless you have a large SSSOM dataset (>250K mappings).
Expected when triggered: a warning callout above the pivot table reading Sparse pivot: NxM = X cells. Consider narrowing.... Hard guard with COUNT(*) pre-estimate is Phase 5 work.
Steps:
- Open the Coverage matrix view; note the cell counts
- Reload Obsidian
- Re-open the same
.basefile
Expected: identical pivot output. The view is pure-function over Bases entries; no hidden state.
- Empty Bases filter (no entries match) → "No entries match the Bases filter" empty-state message
- Missing rowsBy or colsBy in view options → "Configure the pivot view: set ..." empty-state
- Cells with non-numeric values + numeric agg op (sum/avg) → returns null (filtered NaN)
- CSS adapts to dark mode + community themes (uses Obsidian theme variables)
- Mobile (Obsidian iOS/Android via Capacitor) → view renders but be mindful of horizontal-scroll on wide pivots
- ❌ Recipe-picker modal that inserts an embedded
\``base` block from a recipe template (Phase 4) - ❌
Crosswalker: Materialize this recipecommand writing to_crosswalker/audit/<recipe>/<timestamp>.md(Phase 5) - ❌ Sparse-pivot HARD guard (pre-execution
COUNT(*)estimate) — soft warning only in Phase 3 - ❌
crosswalkerHierarchysecond custom view (graduates to v0.1.7-v0.1.8 per Ch 30) - ❌
crosswalkerGraph(Cytoscape.js) — v0.2
- Scenario 1: reference
.basefile created on first run in_crosswalker/views/ - Scenario 2: pivot view renders against SSSOM-imported junction notes
- Scenario 3: all 8 view options work; empty / cellOp / heatmap toggles change rendering
- Scenario 4: idempotent re-write preserves user edits
- Scenario 5: Bases-disabled fallback Notice appears with helpful text
- Scenario 7: deterministic reload — identical output
If all green: ready to start Phase 4 (recipe-picker UX).
| Change | Path |
|---|---|
| CREATED | src/views/bases-api.ts (registerBasesView wrapper; gated on Obsidian 1.10+) |
| CREATED | src/views/pivot-grid.ts (pure data-shaping helper; 31 unit tests) |
| CREATED | src/views/crosswalker-pivot-view.ts (Component subclass; DOM renderer) |
| CREATED | src/views/reference-base-files.ts (idempotent first-run writer; 6 unit tests) |
| CREATED | templates/coverage-matrix.base (source-of-truth reference template) |
| CREATED | tests/pivot-grid.test.ts (31 unit tests) |
| CREATED | tests/reference-base-files.test.ts (6 unit tests) |
| MODIFIED | tests/e2e/crosswalker-pivot-view.spec.ts (filled in pending tests with documentation) |
| MODIFIED | src/main.ts (registerCrosswalkerPivotView() + onLayoutReady writeReferenceBaseFiles call) |
| MODIFIED | styles.css (pivot grid styling) |