From 8c6526cc17ccea6539cf36493e248b383a0c5287 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Jacob=20Read=20IV=20=E2=80=94=20Creator=20of=20?= =?UTF-8?q?=C4=80ML=E2=84=A2?= Date: Tue, 13 Oct 2026 20:36:28 -0700 Subject: [PATCH] Preserve vector positions under atlas filters --- docs/dispatch-matrix.html | 1 + docs/dispatch-matrix.js | 32 +++++++++++++++++++++++-------- test/dispatch-matrix-view.test.js | 5 ++++- 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/docs/dispatch-matrix.html b/docs/dispatch-matrix.html index d58ad9cd..d13fa9af 100644 --- a/docs/dispatch-matrix.html +++ b/docs/dispatch-matrix.html @@ -18,6 +18,7 @@ .method{border-top:1px solid var(--line);padding:35px 0 60px;display:grid;grid-template-columns:.8fr 1.2fr;gap:30px}.method h2{margin:0;font-size:clamp(1.9rem,3vw,2.7rem);letter-spacing:-.04em}.method p{color:var(--muted);margin:0 0 14px}.method code{color:var(--mint);overflow-wrap:anywhere}.method a{font-weight:700}.foot{border-top:1px solid var(--line);padding:25px 0 55px;color:var(--muted);font-size:.78rem} @media(max-width:850px){.hero{grid-template-columns:1fr;gap:25px;padding:50px 0}.totals{grid-template-columns:repeat(2,1fr)}.lenses{grid-template-columns:1fr}.lens{min-height:0}.path{grid-template-columns:repeat(2,1fr)}.method{grid-template-columns:1fr}} @media(max-width:520px){.wrap{width:min(100% - 28px,1300px)}.top{align-items:flex-start;flex-direction:column}.top nav{gap:11px}.hero{padding-top:43px}.hero h1{font-size:clamp(3.55rem,15vw,5.8rem)}.hero-aside{padding-left:16px}.totals{gap:7px;margin-bottom:55px}.total{padding:16px;min-height:127px}.total strong{font-size:2.7rem}.section-heading{display:block}.section-heading p{margin-top:13px}.board{padding:17px}.filters label,.filters select{flex:1;min-width:135px}.filters output{width:100%;margin-left:0}.path,.bindings{grid-template-columns:1fr}.path-item{min-height:0}.case{margin-bottom:55px}} + .cell-placeholder{height:26px;border:1px dashed #426170;border-radius:6px;opacity:.55} @media(prefers-reduced-motion:reduce){html{scroll-behavior:auto}.lens{transition:none}} diff --git a/docs/dispatch-matrix.js b/docs/dispatch-matrix.js index c7b5861c..8f950242 100644 --- a/docs/dispatch-matrix.js +++ b/docs/dispatch-matrix.js @@ -50,6 +50,14 @@ export function visibleMatrixIndices(report, policy = "all", status = "all") { (status === "all" || row.receipt.execution_status === status) ? [index] : []); } +export function matrixGroupSlots(policy, approval, visibleIndices) { + const visible = new Set(visibleIndices); + return MATRIX_AXES.claim.flatMap(claim => MATRIX_AXES.callback.map(callback => { + const index = matrixIndex(policy, approval, claim, callback); + return visible.has(index) ? index : null; + })); +} + export function matrixInsights(report) { return { spent_and_blocked: report.rows.filter(row => row.receipt.execution_status === "blocked" && @@ -115,7 +123,9 @@ if (typeof document !== "undefined" && document.getElementById("matrix-grid")) { "The tool callback was not entered in this local vector."; const values = [ ["01 / HOST POLICY", `${label(receipt.policy_decision)} · exact-match decision`], - ["02 / APPROVAL HOOK", `${row.approval_requests} request · ${label(row.approval)} fixture`], + ["02 / APPROVAL HOOK", row.approval_requests ? + `${row.approval_requests} request · ${label(row.approval)} fixture` : + `0 requests · configured ${label(row.approval)} hook not called`], ["03 / ONE-USE CLAIM", `${row.claim_attempts} attempt · ${row.claims_consumed} consumed`], ["04 / TOOL CALLBACK", `${row.callback_count} entry · ${row.fixture_writes} local marker write`] ]; @@ -144,21 +154,27 @@ if (typeof document !== "undefined" && document.getElementById("matrix-grid")) { const group = element("div", "approval-group", ""); group.append(element("h4", "", label(approvalName))); const cells = element("div", "cells", ""); - for (const claimName of MATRIX_AXES.claim) for (const callbackName of MATRIX_AXES.callback) { - const index = matrixIndex(policyName, approvalName, claimName, callbackName); - if (!visibleSet.has(index)) continue; + let matches = 0; + for (const index of matrixGroupSlots(policyName, approvalName, visible)) { + if (index === null) { + const placeholder = element("span", "cell-placeholder", ""); + placeholder.setAttribute("aria-hidden", "true"); + cells.append(placeholder); + continue; + } + matches++; const row = report.rows[index]; - const button = element("button", "vector", callbackName === "return" ? "↗" : "!"); + const button = element("button", "vector", row.callback === "return" ? "↗" : "!"); button.type = "button"; button.dataset.index = String(index); button.dataset.status = row.receipt.execution_status; - button.setAttribute("aria-label", `Vector ${index + 1}: ${[policyName, approvalName, claimName, callbackName].map(label).join(", ")}; ${row.receipt.execution_status}`); + button.setAttribute("aria-label", `Vector ${index + 1}: ${[policyName, approvalName, row.claim, row.callback].map(label).join(", ")}; ${row.receipt.execution_status}`); button.setAttribute("aria-pressed", "false"); - button.title = `${label(claimName)} / ${label(callbackName)} → ${row.receipt.execution_status}`; + button.title = `${label(row.claim)} / ${label(row.callback)} → ${row.receipt.execution_status}`; button.addEventListener("click", () => showCase(index)); cells.append(button); } - if (!cells.children.length) cells.append(element("span", "empty", "No matches")); + if (!matches) cells.replaceChildren(element("span", "empty", "No matches")); group.append(cells); col.append(group); } diff --git a/test/dispatch-matrix-view.test.js b/test/dispatch-matrix-view.test.js index 53242c88..d057e434 100644 --- a/test/dispatch-matrix-view.test.js +++ b/test/dispatch-matrix-view.test.js @@ -1,7 +1,7 @@ import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; import test from "node:test"; -import { inspectMatrix, MATRIX_AXES, matrixIndex, matrixInsights, matrixSelection, matrixUrl, +import { inspectMatrix, MATRIX_AXES, matrixGroupSlots, matrixIndex, matrixInsights, matrixSelection, matrixUrl, visibleMatrixIndices } from "../docs/dispatch-matrix.js"; const report = JSON.parse(readFileSync(new URL("../docs/action-dispatch-matrix.json", import.meta.url), "utf8")); @@ -16,6 +16,9 @@ test("the atlas indexes every vector and filters the actual checked-in outcomes" assert.equal(visibleMatrixIndices(report, "deny", "blocked").length, 48); assert.equal(visibleMatrixIndices(report, "deny", "unknown").length, 0); assert.equal(visibleMatrixIndices(report, "requires_approval", "unknown").length, 2); + assert.deepEqual(matrixGroupSlots("requires_approval", "match", + visibleMatrixIndices(report, "requires_approval", "unknown")), + [null, 97, null, null, null, null, null, null], "filtering keeps callback and claim positions"); assert.throws(() => visibleMatrixIndices(report, "unknown_policy"), RangeError); });