Skip to content

Commit 3605153

Browse files
dcostencoclaude
andauthored
fix(dashboard): repair the parse-dead inline script; real screenshots; README sweep (#136)
THE BUG: commit 01ccc88 (2026-05-29, the XSS fix) wrote data-id=''' + escapeHtml(p.id) + ''' into the dashboard's inline script — a SyntaxError that killed the ENTIRE script at parse time. Every dashboard from May 29 to today rendered 'Loading projects...' forever: the project selector, graph, ledger, everything dead. Found while capturing a README screenshot; the picture would not load, and the reason was real. The irony: the ES5 lint exists precisely for quote-escaping traps, the offending commit even used the data-id pattern the lint recommends — and the lint stayed green, because it pattern-matches known traps instead of parsing. Pattern lists cannot enumerate typos. THE FIX: data-id="..." (escapeHtml escapes double quotes, so the attribute stays injection-safe). Verified live: project list populates, graph renders, zero page errors. THE GUARD: lint-dashboard-es5 now renders the BUILT dashboard HTML and node --checks every inline script block, placed before the legacy exit path (the first version ran after process.exit(0) — a placebo). Proven A/B on the real defect: broken source exits 1 naming the line, fixed source exits 0. ALSO: - README hero + docs images are now REAL captures of the running v20.8.0 dashboard (scrubbed HOME, authored demo data — no private content; visually inspected), replacing the generated mockup. - What's New gained the missing 20.7–20.8.0 section. - Dead BFCL blog link -> the canonical leaderboard URL. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent f12c5fa commit 3605153

5 files changed

Lines changed: 76 additions & 4 deletions

File tree

README.md

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
[![Models on HuggingFace](https://img.shields.io/badge/🤗-prism--coder-yellow)](https://huggingface.co/dcostenco)
99

1010
<p align="center">
11-
<img src="docs/v11_hivemind_multi_agent_dashboard.jpg" alt="Prism Coder — Mind Palace Dashboard with Knowledge Graph and Multi-Agent Hivemind" width="700" />
11+
<img src="docs/mind-palace-dashboard-v20.8.png" alt="Prism Mind Palace dashboard v20.8.0 — project state with handoff summary, pending TODOs, intent health, neural graph, and time-travel history" width="700" />
1212
</p>
1313

1414
Prism Coder is an [MCP server](https://modelcontextprotocol.io) that gives Claude, Cursor, and other AI tools long-term memory that survives across sessions. It ships with the open-weight `prism-coder` model fleet (2B–27B) for fast, offline tool-routing — no cloud required.
@@ -116,6 +116,29 @@ or by re-enabling after each run.
116116
<details>
117117
<summary>Release history (optional)</summary>
118118

119+
## What's New in v20.7 – v20.8.0
120+
121+
- **First run proves the memory instead of describing it**`session_bootstrap`
122+
seeds one demo memory and shows it *recalled from disk*, so the save→recall
123+
loop is felt in session 1. One-shot, contained in its own `prism-demo`
124+
project, removable with one call.
125+
- **Dashboard fixed** — a quoting typo (shipped 2026-05-29) killed the inline
126+
script at parse time, so every dashboard since rendered "Loading projects..."
127+
forever. Fixed, and the ES5 lint now `node --check`s the built inline script
128+
so an unparseable dashboard can never ship again.
129+
- **Trusted Publishing** — npm releases authenticate via GitHub OIDC. No stored
130+
token to expire or leak, and every release carries a signed [provenance
131+
attestation](https://docs.npmjs.com/generating-provenance-statements) — you
132+
can verify the tarball you install was built from this repo by CI
133+
(`npm audit signatures`).
134+
- **TLS enforced for cloud sync** — a remote `http://` storage URL is upgraded
135+
to `https://` instead of silently sending session content in the clear.
136+
- **Codex plugin collision + enabled-state detection**`prism connect` skips
137+
its own registration only when a plugin *actually* provides `prism-mcp`
138+
(cache present **and** enabled), preventing both duplicate and missing
139+
servers.
140+
- Windows CI stabilized; registry/npm listings realigned and deduplicated.
141+
119142
## What's New in v20.6.0
120143

121144
### Delivery Is Not a Suggestion
@@ -604,7 +627,7 @@ Your AI agent forgets everything between sessions. Prism fixes that — and adds
604627
Every conversation feeds a persistent store. The next session loads the right context automatically — no re-explaining.
605628

606629
<p align="center">
607-
<img src="docs/mind-palace-dashboard.png" alt="Mind Palace Dashboard — project state, neural graph, pending TODOs" width="700" />
630+
<img src="docs/mind-palace-dashboard-v20.8-full.png" alt="Mind Palace Dashboard — full page: session ledger, memory analytics, lifecycle controls, background scheduler" width="700" />
608631
</p>
609632

610633
The dashboard shows your current project state, pending TODOs, intent health, and a neural knowledge graph — all built automatically from your agent sessions.
@@ -730,7 +753,7 @@ draft that may need correction—to Synalux for authenticated deterministic
730753
correction. Advertised custom host tools remain local. Set
731754
`route_guard: "local"` for a fully on-device route path.
732755

733-
| Model | Ollama tag | Size | [BFCL](https://gorilla.cs.berkeley.edu/blogs/12_bfcl_v3_multi_turn.html) Accuracy | Role | Automatic routing tier |
756+
| Model | Ollama tag | Size | [BFCL](https://gorilla.cs.berkeley.edu/leaderboard.html) Accuracy | Role | Automatic routing tier |
734757
|---|---|---|---|---|---|
735758
| Qwen3.5-4B Q3_K_M | `prism-coder:2b` | 2.3 GB | 99.1% × 3 seeds | iPhone / mobile first gate | Free |
736759
| Qwen3.5-4B Q4_K_M | `prism-coder:4b` | 3.4 GB | 100% × 3 seeds | Verifier | Free |
604 KB
Loading
439 KB
Loading

scripts/lint-dashboard-es5.cjs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,59 @@ lines.forEach((raw, i) => {
8989
}
9090
});
9191

92+
// ── 3. Parse the OUTPUT, not just pattern-match the source ──────────────────
93+
// The 2026-05-29 XSS fix used the exact data-id pattern this lint recommends,
94+
// but typo'd the quoting (data-id=''' + …) — a plain SyntaxError that killed
95+
// the whole inline script. Every dashboard from May 29 to Aug 7 rendered
96+
// "Loading projects..." forever, and this lint stayed green because it looks
97+
// for known traps, not for validity. Pattern lists cannot enumerate typos;
98+
// node --check can. So: extract every quoted-string fragment concatenation is
99+
// impossible statically, but the assembled inline <script> in the BUILT html
100+
// is checkable. If the dashboard has been built, render it and syntax-check
101+
// each inline block; skip silently when dist/ is absent (pre-build lint runs).
102+
(function syntaxCheckBuiltDashboard() {
103+
const path = require('path');
104+
const fs = require('fs');
105+
const { execFileSync } = require('child_process');
106+
const os = require('os');
107+
const distUi = path.join(__dirname, '..', 'dist', 'dashboard', 'ui.js');
108+
if (!fs.existsSync(distUi)) return; // not built yet — CI lints post-build
109+
let html;
110+
try {
111+
const ui = require(distUi);
112+
const render = ui.renderDashboardHTML || ui.default;
113+
if (typeof render !== 'function') return;
114+
html = String(render('lint'));
115+
} catch { return; } // rendering needs runtime state — do not fail the lint on that
116+
const blocks = [...html.matchAll(/<script[^>]*>([\s\S]*?)<\/script>/g)]
117+
.map(m => m[1]).filter(b => b.trim());
118+
let bad = 0;
119+
for (const [i, block] of blocks.entries()) {
120+
const tmp = path.join(os.tmpdir(), `dash-lint-${process.pid}-${i}.js`);
121+
fs.writeFileSync(tmp, block);
122+
try {
123+
execFileSync(process.execPath, ['--check', tmp], { stdio: 'pipe' });
124+
} catch (e) {
125+
bad++;
126+
console.error(`✗ inline <script> block ${i} fails to parse:`);
127+
console.error(String(e.stderr).split('\n').slice(0, 3).join('\n'));
128+
} finally {
129+
fs.unlinkSync(tmp);
130+
}
131+
}
132+
if (bad) {
133+
console.error(`${bad} inline script block(s) have syntax errors — the dashboard JS dies at parse time.`);
134+
process.exit(1);
135+
} else {
136+
console.log(`✓ ${blocks.length} built inline script block(s) parse cleanly`);
137+
}
138+
})();
139+
92140
if (errors === 0) {
93141
console.log('[dashboard-es5] OK — no ES6 or quote-escape violations found.');
94142
process.exit(0);
95143
} else {
96144
console.error(`[dashboard-es5] FAIL — ${errors} violation(s) found. Fix before committing.`);
97145
process.exit(1);
98146
}
147+

src/dashboard/ui.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1857,7 +1857,7 @@ function loadPipelines() {
18571857
html += '<div style="font-size:0.72rem;color:var(--accent-rose);margin-top:0.35rem;padding:0.3rem 0.5rem;background:rgba(244,63,94,0.08);border-radius:4px">⚠ ' + escapeHtml(p.error.slice(0, 200)) + '</div>';
18581858
}
18591859
if (isActive) {
1860-
html += '<div style="margin-top:0.5rem"><button onclick="abortPipeline(this.dataset.id)" data-id=''' + escapeHtml(p.id) + ''' class="cleanup-btn" style="font-size:0.72rem">🛑 Abort Pipeline</button></div>';
1860+
html += '<div style="margin-top:0.5rem"><button onclick="abortPipeline(this.dataset.id)" data-id="' + escapeHtml(p.id) + '" class="cleanup-btn" style="font-size:0.72rem">🛑 Abort Pipeline</button></div>';
18611861
}
18621862
html += '</div>';
18631863
}

0 commit comments

Comments
 (0)