See docs/architecture.md for the contract this roadmap delivers against. Phase order reflects the consolidation around dual host integration patterns (drawer mode for CMS-style hosts, overlay mode for spatial-pin hosts).
- Repo + monorepo layout
- License (Apache 2.0)
-
packages/widget/with floating bug button v0 -
apps/playground/with widget loaded -
docs/architecture.md - CI workflow
- GitHub issues per major feature
- Branch protection on
main(enabled 2026-05-20, post-extraction, with two production consumers depending on the repo)
- Unified
Annotationtype with discriminatedanchorunion (route + spatial) - Three adapter contracts:
ApiAdapter,AuthAdapter,ThemeAdapter - In-memory adapter (playground default)
- localStorage adapter (browser-only, prototype-friendly)
- Dual render modes:
drawer(route-anchored) +overlay(spatial pins) - Click-to-mark mode toggle, wired to the existing v0 bug button (playground integration)
- [~] Triple-selector anchoring:
@medv/finder+ W3C text-quote + viewport shipped; XPath fallback deferred to v0.2 - Spatial anchor capture (x, y percent, clamped to canvas bounds)
- Compose / edit / delete primitives
- Resolution + reopen verbs (
resolved_prcolumn) - Overlap tracking (
related_ids+dup_of) - CSS custom property theme contract; host pages override at
:root - Playground exercises both render modes against the in-memory adapter
Scaffold landed in travisEATSbugs commit 28f78c3 (19 files, 3,198 insertions; 27/27 tests pass; ~17 KB gzipped). Playground integration landed in a follow-up commit.
-
@travisbreaks/travisEATSbugs-cloudflarepackage: D1-backedApiAdapterwith full CRUD + UpdatePatch discrimination + audit log table (16/16 tests green, 10 KB ESM) -
@travisbreaks/travisEATSbugs-httppackage: fetch-backedApiAdapterwith REST contract + Authorization header + extra headers (12/12 tests green, 3 KB ESM) - Migrations consolidate the page-notes schema evolution (base + resolution + overlap) into a single
001_annotations.sqlwith the unified anchor union schema - Cloudflare Worker live at
https://eats.travisfixes.com(deployed 2026-05-16). D1travisEATSbugsprovisioned (id9118617e-0f72-401a-82e3-f1031648cb22), both migrations applied remotely, secrets (SHARE_TOKEN_SECRET,ANTHROPIC_API_KEY,MEMBER_TOKENS) attached viawrangler secret putfrom keychain. Custom domain bound via CF API; cert auto-provisioned. Smoke tests green: unauth 401, member 200, POST round-trip persists,/triagereturns a real Claude classification end-to-end. - Tokenized unguessable share-link mode: HMAC-SHA256 sign + verify primitive at
apps/worker/src/share-token.ts; worker auth accepts share tokens as scoped-reporter identity. Tested with tamper-detection + expiry edge cases. - Reporter name prompt on first comment:
localStorageReporterAuthAdapter +setReporterName/clearReporterNamehelpers +reporterPromptconfig on drawer + overlay. Prompt blocks compose until a name is set; on submit, name persists to localStorage and adapters withsetCurrentUserswap identity at runtime. Playground demo at?reporter. - Audit log hook: widget-side
onAuditcallback inWidgetOpts(fires on create/update/delete via the exportedwrapWithAudithelper) + adapter-sideannotation_audit_logtable (worker writes on every mutation). Both layers independent; hosts pick either, both, or neither. - Bug-button auto-wire:
init({ onToggle })callback inbug-mode.tscloses the manual shadow-root-attach workaround. Playground uses it as the canonical pattern.
v0.2 complete (2026-05-16): widget + adapters + worker + share-link tokens + reporter prompt + audit log + bug-button auto-wire + live worker at eats.travisfixes.com.
- Reference adapter (Pivotal's
eats-bugs-adapter.ts) satisfying ApiAdapter + AuthAdapter + ThemeAdapter against a host CMS auth + D1 binding - Swapped Pivotal's hand-rolled
<PageNotesDrawer />for<AnnotationWidget renderMode="drawer" adapter={hostAdapter} />(2026-05-18 in commit 62c323f via PR #167) - Preserved the existing
page_notestable; widget reads same schema through the adapter - Smoke suite green (28/28 in Pivotal)
- Staged on preview deploy first, dogfooded by Cole, then promoted
- End-user sees no behavior change
v0.3 complete (2026-05-18): Pivotal is the canonical reference consumer at 0.0.7-alpha.0 in production.
- Reference adapter for a spatial-pin consumer (LS's
eats-bugs-adapter.ts; merged via lions-share PR #60) - Lion's Share uses
AnnotationPageModefor click-to-pin overlay (deployed at 0.0.3-alpha.0 on lionsshare.travisfixes.com) - Per-host tinted theme via CSS custom properties: Pivotal red
#EC2127, LS Mane orange#C04618. Note: drawer + helper overlays still need full host-palette inheritance, tracked indocs/per-host-theming-2026-05-20.md.
v0.4 complete (2026-05-19): LS deployed at 0.0.3-alpha.0; vendor bump to 0.0.7 sits on a docs branch pending merge + canary deploy under the Phase 2 plan.
- Screenshot capture (
modern-screenshot):defaultScreenshotCapture+wrapWithScreenshothelpers inscreenshot.ts;screenshotCaptureoption onWidgetOptsplumbs through. Widget facade composes screenshot + audit wraps so drawer / overlay don't need to know. Adapters carry theAnnotation.screenshotfield. Default uses a data URL (demo-grade); hosts inject R2-upload variants for production. - AI triage
onCreatehook (opt-in, noANTHROPIC_API_KEY= no AI call): widget-sidewrapWithTriage+httpTriagehelpers; worker-sidePOST /triageroute calls Claude (Sonnet 4.6 by default) with tool-use forced structured output, returns{ severity, category, suggestedAssignee?, dupeOf?, rationale }. Result writes back via a discriminated{ triage }UpdatePatch variant; persisted in dedicated columns via migration002_triage.sql. Reporter-mode (share-link) tokens get 403 on the triage route; only member tokens can spend Anthropic credits. - Sticky-note Motion polish (vanilla CSS, no Framer Motion dep): paper-grain texture via inline-SVG
feTurbulencedata URL (6% alpha) on.draft+ sidebar.cardsurfaces. Per-marker rest tilt in [-0.5deg, 0.5deg] deterministic via djb2 hash ofidso tilt stays stable across re-renders. Hover lift on markers + cards (composite-only transform + deeper shadow). Drag-to-reposition on spatial pins via pointer-capture; below the 5 px threshold the marker click-toggles selection, above it commits via a new{ anchor: AnnotationAnchor }UpdatePatch variant. The same variant lets route-anchored annotations be re-wired to a new selector / xpath when a stale CSS selector falls through. All motion gated onprefers-reduced-motion. - Real-DOM anchoring fully hardened against page mutations: triple-selector now full (CSS via
@medv/finder+ XPath + W3C text-quote + viewport box). Hosts that need to re-anchor a stale CSS selector can fall through to XPath or text-quote. - W3C Web Annotation Data Model conversion finalized:
toW3C+fromW3Chelpers inpackages/widget/src/w3c.ts. Emits spec-valid JSON-LD with@context: http://www.w3.org/ns/anno.jsonld,type: Annotation,motivation(commenting, or[commenting, assessing]for severity=high),TextualBodybody,SpecificResourcetarget. Selector union maps cleanly:selector->CssSelector,xpath->XPathSelector,textQuote->TextQuoteSelector,viewport->FragmentSelectorwith pixelxywh=, spatial pins ->FragmentSelectorwithxywh=percent:conforming to W3C Media Fragments. Non-spec domain fields (state, severity, resolvedPR, triage, etc.) hang off ateb:extextension block so consumers that don't know us still parse the document as a stock W3C annotation, and round-trip is lossless for consumers that do. Spec-only annotations missingteb:extimport cleanly with state defaulted toopen. 16 unit tests cover round-trip + selector mapping + spec field-name conformance.
v0.5 complete (2026-05-16): all 6 items shipped.
Real-world Cole-driven iteration inside Pivotal. Six releases in 48 hours.
- 0.0.2-alpha.0 (B1): Sticky-note pins now page-scoped across soft navigation. New
route-watcher.tspatcheshistory.pushState+replaceState(idempotent); drawer + page-mode subscribe and re-callrefresh()on every route change. Closed the bug where pins from/bookings/Arendered on top of/bookings/B. - 0.0.3-alpha.0 (F1): Optional kind radios (
bug/feature/note) + Clear button in compose UI.AnnotationKindtype,Annotation.kind?field, drawer + page-mode compose rows of radio pills with state reset on submit. Adapters that ignore the field stay backwards compatible. - 0.0.3-extra: Re-export
AnnotationKindfrom@travisbreaks/travisEATSbugspackage root so adapter consumers (Pivotal) drop their local union duplicate. - 0.0.4-alpha.0 (F2): Drawer kind filter pills (
All/Bug/Feature/Note/Unclassified) with live count badges. Per-pin kind coloring on page-mode (teb-pin-bugred,teb-pin-featureblue,teb-pin-noteslate;teb-pin-stalegray wins). Pinaria-labelcarries kind for screen readers. - 0.0.5-alpha.0 (B2): Hide orphan pins entirely. Selector-no-longer-resolves pins no longer stack in a vertical column on the viewport edge. Drawer list still surfaces every note for the route.
- 0.0.6-alpha.0 (B3): Pin durability via fall-through chain (selector -> xpath -> textQuote -> viewport
elementFromPoint). Capture-time Tailwind-utility veto prevents@medv/finderfrom picking ambiguous utility-class selectors.resolveTargetForAnchor()returns{ target, via }so future host code can auto-heal anchors. - 0.0.7-alpha.0 (F3): Right-rail drawer layout option (
layout: 'right-rail') matching Pivotal's AI chat sidebar shape and the legacyPageNotesDrawer. New options:railWidth,backdrop. Floating layout unchanged (backwards compatible). Slide-in animation, left border + leftward drop shadow.
These are captured Pivotal-side patterns + new strategic requirements that have not yet landed in canonical TEB. They guide the next releases.
docs/per-host-theming-2026-05-20.md: drawer + helper overlays don't inherit host palette like the button does. Convert hardcoded colors indrawer.ts(andbug-mode.ts,page-mode.ts,overlay.ts) to CSS custom properties (--teb-surface-1,--teb-surface-2,--teb-muted, etc.). Estimated 5hr; targets 0.0.8-alpha.docs/note-threads-2026-05-20.md: two-way per-note communication. Cole files a note, admin asks a clarifying question, note becomes a thread. Newpage_note_messagestable, adapter methods (listMessages,addMessage), threaded inbox UI, in-app indicator. Email/SMS dispatch is paid-tier (lands inteb-cloud). Targets 0.0.12 or later.docs/client-facing-tenancy.md: Phase A6 multi-tenant pilot for LSD. Ratified decisions D1-D4 baked into doc. Per-tenant routing via embed token, R2-hosted brand assets, per-tenant version pinning (LS = canary), auth-gated production widget (no random visitor sees zero).
Phase 1 of the TEB OSS uplift. Three releases over the sprint.
- 0.0.8-alpha.0 (F4): bug-button + hint-ribbon config. Four Pivotal shadow-DOM workarounds upstreamed (button offset, size, animation modes, hint-ribbon offset). PR #34.
- 0.0.9-alpha.0 (B4): worker bulk ingest endpoint.
POST /annotations/bulk(member-token only, MAX_BULK_ITEMS=200, per-item error isolation). Brain-dump ingest path is now a public API. PR #35. - 0.0.10-alpha.0 (F5): TEB MCP server (
apps/mcp-server/). 4 tools:list_annotations,get_annotation,resolve_annotation,reopen_annotation. Stdio transport. Wires into Claude Code viaclaude mcp add teb npx @travisbreaks/travisEATSbugs-mcp. PR #36.
v0.10 complete (2026-05-20): originally onMutate was scoped for 0.0.9 and the MCP server was scoped for 0.0.11; both collapsed forward because wrapWithAudit already covered the onMutate use case, and the MCP server was ready ahead of schedule. The 0.0.10 version bump on widget + adapter-cloudflare + adapter-http aligns all public packages to the same canonical version.
- GitHub Issues two-way sync (comment becomes issue, issue close writes back to pin)
- Linear two-way sync
- Jira two-way sync
- Slack notification webhook
PR link-back specifically (resolved_pr column) ships earlier as a core primitive in v0.1. The v0.6 work is the full bidirectional ticket-sync layer on top.
- Public npm release
- Documentation site at
eats.travisfixes.com - Marketing site (live at travismakes.org/travis-eats-bugs/)
- Live demo
- Example integrations (React, Vue, Svelte, vanilla)
- Real-time collab via Yjs over Cloudflare Durable Objects
- Mobile-app SDK (React Native, native iOS/Android)
- Drawable annotation mode (Excalidraw embed)
- Session replay for bug repro