Widget page-context extraction — Pattern A (bake) + Pattern B (extract)

Date: 2026-05-21 · Status: Pattern A shipped for cockpit · Pattern B parked

The question Dan asked

“Given that it has context living within, how will it access that thinking, without spoon feeding it all”

The ask-opus widget mounts on a page. The page has rich content (analyst headline, money map, deadlines, actions on the cockpit). The widget by default passes ONLY a short data-context-hint to the Worker — Opus sees the label but not the data. Opus correctly refuses to invent priorities on an active claim. The data is RIGHT THERE on the page, but it’s not reaching Opus.

How to fix without spoon-feeding everything via author-written hints?

Two layered patterns

Pattern A — BAKE (build-time spoon-feed)

   The render script knows the structured data already.
   Pipe a compact summary of it into data-context-hint.
   ─────────────────────────────────────────────────────

   sidecar.json + analyst.md       (the data, structured)
            │
            ▼
   pa_claim_cockpit_render.py     (the render script)
            │
            ▼  builds build_claim_context_summary()
            │  ~600 chars: identity + event + headline +
            │             money map + top deadline + top 3 actions
            ▼
   <div data-ask-opus
        data-context-id="claim-046414618"
        data-context-hint="<the 600-char summary>">
            │
            ▼  widget reads the attribute, sends to Worker
            ▼  on every /api/ask call
            │
   Worker injects into system prompt → Opus sees facts

Pros: Cheap. Deterministic. Ships today. Uses existing widget API (no widget rebuild). One render script change.

Cons: Only as fresh as the last cockpit render. Author has to decide UPFRONT what’s contextually relevant (claim identity + money map vs. fine-grained details). Each new widget host needs its own render script to bake context.

Status: SHIPPED for cockpit 2026-05-21 (commit 02616cf). Cockpit now passes ~600 chars of structured facts on every Opus call.

Pattern B — EXTRACT (runtime DOM scrape via data-opus-context)

�STASH3�

Pros: - Always fresh — reads live DOM state, no rendering staleness - Portable — any page can host the widget by tagging its elements - Author declares “what matters” not “what to say” — no synopsis decisions baked in - Composable with other widget patterns (countdown / cost calculator) — same data-* discipline - Cleanly handles same-page edits — widget re-reads on every call

Cons: - Requires widget rebuild (one-time) - Authors must tag elements with data-opus-context (small editorial discipline) - Slightly larger network payload per /api/ask (structured context vs. one string)

Status: PARKED for later. Build when: - Second non-cockpit page wants to host the widget (e.g. equipment record, contractor record) - Cockpit needs context that goes beyond the bake-summary (e.g. “what does the analyst say about THIS action?”) - A widget call needs to see edits-since-publish (rare; cockpit edits trigger republish)

How the two patterns layer

They’re not mutually exclusive — they layer:

�STASH6�

This is the same shape as the static-site / living-brain separation (per user_static_site_plus_living_brains_stack.md): the BAKE happens at publish time, the EXTRACT happens at read time. Both feed the same model.

Implementation sketch for Pattern B

Widget changes (ask-opus-worker/public/widget.js)

�STASH9�

Worker changes (ask-opus-worker/src/index.ts)

function buildContextPrefix(hint: string, pageContext: Record<string, any>): string {{
  const lines: string[] = [];
  if (hint) lines.push(`Page summary (baked at publish):\n${{hint}}`);
  if (pageContext && Object.keys(pageContext).length > 0) {{
    lines.push(`\nLive page elements (read at request time):`);
    for (const [k, v] of Object.entries(pageContext)) {{
      const value = Array.isArray(v) ? v.map(x => `  - ${{x}}`).join('\n') : `  ${{v}}`;
      lines.push(`${{k}}:\n${{value}}`);
    }}
  }}
  return lines.join('\n\n');
}}

Author discipline (per-page editorial)

Each page that hosts the widget tags its contextually-relevant elements:

   Element                          data-opus-context value
   ────────────                     ────────────────────────
   Analyst headline                 analyst-headline
   Money map figures                money-map
   Each deadline pill               deadline
   Each action card                 action
   "Last touched" timestamp         last-touched
   Status pill                      status
   Vendor card                      vendor (if cross-referenced)

The naming is intentional and reusable across page types — same analyst-headline key works for ANY claim cockpit; same last-touched works for any asset record.

Compounding effect

Once Pattern B ships, every NEW widget host gets context automatically:

  1. Author writes the page (HTML for an equipment record, contractor record, claim cockpit, etc.)
  2. Author tags relevant elements with data-opus-context="<key>"
  3. Author embeds <div data-ask-opus> + the widget <script>
  4. No render-script integration needed — Pattern B handles context on its own
  5. Opus understands the page

That’s the elegant outcome Dan was pointing at: “how will it access that thinking, without spoon feeding it all.” Pattern B is the answer — authors tag, widget extracts, Opus sees.

Resume conditions for Pattern B

Build when:

  1. Second non-cockpit widget host — e.g. equipment record wants Opus help; cockpit-specific Pattern A render script doesn’t help here
  2. Cockpit needs context beyond the baked summary — e.g. specific section text, full analyst markdown
  3. Cross-page Opus sessions — e.g. “what’s the relationship between this claim and the BMW vehicle record?” needs to see both pages’ context
  4. Edit-then-ask workflow — author edits a cockpit element in DevTools / browser, asks Opus immediately; bake-summary lags but DOM is current
  5. Audrey / dogwood / dare pages want the widget — building Pattern A render scripts for each brand is repetitive; Pattern B scales

Estimated effort: ~2-3 hours (widget rebuild + Worker prompt-integration + first canonical page taggings).

Sibling memories + sketches

The aphorism

Bake the canonical summary; extract the live context. Authors declare what matters; widget handles the plumbing; Opus sees both stable structure and current state. The HTML is the substrate; the page-context is the question’s data dictionary.

Source: parked_sketch_widget_page_context_extraction_2026-05-21.md · Rendered 2026-05-21 12:11