Files
gbrain/eval/cli
Garry TanandClaude Opus 4.7 f0649e2f32 feat(eval): Phase 3 world.html explorer + eval:* CLI surface
Contributor DX magical moment. Static HTML explorer renders the full
canonical world (240 entities) as an explorable tree, opens in any browser,
zero install. Every string HTML-entity-encoded (XSS-safe — direct vuln
class per eng pass 2, confidence 9/10).

Added:
  eval/generators/world-html.ts         — renderer (~240 LOC; single-file
                                          HTML with inline CSS + minimal JS)
  eval/generators/world-html.test.ts    — 16 tests (XSS + rendering correctness)
  eval/cli/world-view.ts                — render + open in default browser
  eval/cli/query-validate.ts            — CLI wrapper for queries/validator
  eval/cli/query-new.ts                 — scaffold a query template

Modified:
  package.json                          — 7 new eval:* scripts
  .gitignore                            — ignore generated world.html

package.json scripts shipped:
  bun run test:eval                 all eval unit tests (57 pass)
  bun run eval:run                  full 4-adapter N=5 side-by-side
  bun run eval:run:dev              N=1 fast dev iteration
  bun run eval:world:view           render world.html + open in browser
  bun run eval:world:render         render only (CI-friendly, --no-open)
  bun run eval:query:validate       validate built-in T5+T5.5 (or a file path)
  bun run eval:query:new            scaffold a new Query JSON template
  bun run eval:type-accuracy        per-link-type accuracy report

XSS safety:
  escapeHtml() encodes the 5 critical chars (& < > " '). Tested directly
  with representative Opus-generated attacks:
    <img src=x onerror=alert('xss')>  → &lt;img src=x onerror=alert(&#39;xss&#39;)&gt;
    <script>fetch('/steal')</script>  → &lt;script&gt;fetch(&#39;/steal&#39;)&lt;/script&gt;
  Ledger metadata (generated_at, model) also escaped — covers the less
  obvious attack surface where Opus could emit tag-like content into the
  metadata file.

world.html structure:
  - Left rail: entities grouped by type with counts (companies, people,
    meetings, concepts), alphabetical within type
  - Right pane: per-entity cards with title + slug + compiled_truth +
    timeline + canonical _facts as collapsed JSON
  - URL fragment deep-links (#people/alice-chen)
  - Sticky rail on desktop; responsive stack on mobile
  - Vanilla JS for active-link highlighting on scroll (no framework)

Generated file: ~1MB for 240 entities (full prose). Gitignored; rebuild
with `bun run eval:world:view`. Regeneration is ~50ms.

Contributor TTHW (Tier 5.5 query authoring):
  1. bun run eval:world:view                         # see entities
  2. bun run eval:query:new --tier externally-authored --author "@me"
  3. edit template with real slug + query text
  4. bun run eval:query:validate path/to/file.json
  5. submit PR

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 00:15:18 +08:00
..