Skip to content

Air-gapped briefing zip — self-contained distraction-free Storyboard renderer (SPA) #631

Description

@IanMayo

Problem

The MVP storyboarding suite (#215#218) lets analysts capture a guided walk-through inside VS Code, but the in-panel playback always renders inside the analyst's working chrome (panels, sidebars, command palette). For stakeholder briefings — especially on air-gapped operational networks where neither VS Code nor a hosted web app is available — there is no way to hand someone a finished Storyboard and have them watch it.

The Out of Scope lists in specs/215, specs/217, and specs/218 all defer "dedicated distraction-free briefing renderer" as a phase-2 follow-up.

Proposed Solution

Ship the briefing renderer as a self-contained, air-gappable zip — a tiny static SPA that opens in any modern browser by double-clicking index.html, with no server, no extension host, no network calls.

Zip contents:

  • index.html + bundled JS / CSS (minified, no CDN refs)
  • features.geojson — the plot's FeatureCollection, which already contains the Storyboard and Scene features (StoryboardFeature / SceneFeature per shared/schemas/src/linkml/storyboard.yaml). Storyboards are not a separate document; they live alongside tracks / points / polygons inside the plot's GeoJSON.
  • item.json + assets/ — the STAC item metadata and Scene thumbnail assets (per Add idea 050: Restore previously-open plots on VS Code startup #174's properties.debrief:assets map), so the renderer can resolve thumbnails the same way the VS Code host does.
  • tiles/ — cached basemap tiles covering the bounding box of every Scene's viewport, pre-fetched at zip-build time so playback works offline.
  • The build command takes a Storyboard ID parameter (since one plot may contain multiple StoryboardFeatures). The renderer reads features.geojson, filters to the chosen Storyboard's children Scenes (and any non-Storyboard features the Scenes reference for display), and plays back that subset.

Renderer UX:

  • Single Storyboard per zip (MVP — picker for multi-Storyboard plots is out of scope).
  • Read-only — no Scene editing, no capture, no description editing.
  • Present / minimal toggle (interview decision):
    • Present mode (default): full chrome hidden — just the map, the active Scene's title + description overlay, and a tiny floating transport (Prev / Play-Pause / Next).
    • Minimal mode: keeps the transport visible plus a small scrub-bar / Scene counter; still no sidebar.
  • Existing playback semantics from Fix four VS Code extension regressions: temporal rendering and tool offering #217: flyTo + time-slider tween between Scenes, scrub-window lock, on-map Scene rectangle highlight.
  • Honours Implement technology novelty detection to prevent duplicate entries #258 capture state: Full / Trail displayMode per-Scene.

Build pipeline:

  • New VS Code command "Export Storyboard as briefing zip…" on a Storyboard's overflow menu (the command knows which Storyboard you're on, so it scopes the export to that one).
  • The command serialises the plot's features.geojson + item.json, copies Scene-thumbnail assets, pre-fetches the tile range covering all the chosen Storyboard's Scenes, bundles the SPA, and writes the zip to a user-chosen path.
  • SPA source lives at apps/briefing-renderer/ and builds via Vite to a single static bundle (target ≤ 5 MB before tile assets).

Success Criteria

Constraints

  • Offline-first per CONSTITUTION Article I — no CDN refs, no network calls at runtime, no telemetry.
  • Article II.1 — Storyboard and Scene shapes are LinkML-derived and live as Features inside features.geojson; the briefing renderer must not re-declare or duplicate these shapes.
  • Article IV.1 (services never touch UI) — the zip renderer is a frontend; the zip builder command may need a small services-side helper (tile pre-fetch loop) routed through services/stac/ or similar rather than file-writing directly from the extension. To be settled during /speckit.plan.
  • Article XV TypeScript strict on the new app.
  • Reuses the shared playback engine from Fix four VS Code extension regressions: temporal rendering and tool offering #217 (extract to @debrief/components/playback/ if not already) so logic is not duplicated.
  • Honours Implement technology novelty detection to prevent duplicate entries #258 displayMode capture; depends on Add range-time-plot tool specification (v1.0) #263 (time-range Scenes) for time-range Scene support.

Out of Scope

  • Multi-Storyboard zips with picker — single Storyboard per zip in MVP. Aggregating multiple Storyboards is a phase-3 enhancement.
  • Editing inside the zip — strictly read-only. No capture, rename, delete, copy-to-other.
  • Hosted / shared-URL briefing — only the zip distribution shape is in scope. A apps/web-shell/ /briefing/:id route is a possible future enhancement but explicitly out of scope here.
  • Video / GIF export — see Spec #055: Track-Position to Track Range/Bearing Tool #265 (research spike).
  • Audio narration / annotation track — phase-3.
  • Real-time collaboration on a briefing — phase-3, same status as in the parent epic.
  • Tile selection beyond a simple bounding-box per Scene — multi-zoom-level fully-recursive pre-fetch is in scope; bespoke per-Scene tile choice is not.

Dependencies


Originally captured under epic item #229 in BACKLOG.md; promoted via /interview 229 (2026-05-19) — epic was split into three independent items.

Edited 2026-05-19: corrected zip-contents description — Storyboards live as StoryboardFeature / SceneFeature inside the plot's features.geojson, not as a separate storyboard.json document.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions