Skip to content

feat(session): artifacts panel and inline annotations#42

Merged
setkyar merged 9 commits into
mainfrom
feature/artifact
Jun 5, 2026
Merged

feat(session): artifacts panel and inline annotations#42
setkyar merged 9 commits into
mainfrom
feature/artifact

Conversation

@setkyar
Copy link
Copy Markdown
Contributor

@setkyar setkyar commented Jun 4, 2026

Summary

Adds an in-browser review surface to the session viewer via the right sidebar (Scratchpad / Artifacts / Annotations tabs). The motivation: a long agent session produces files and decisions buried in a linear transcript — this makes the outputs easy to find, preview, and review, and lets you push structured feedback straight back to the agent.

  • Artifacts panel — a path-keyed, edit-aware registry reconstructs each file's latest state from the structured tool calls (write/edit, plus a conservative mv/git mv/rm recognizer; arbitrary shell is intentionally left alone). Source view with copy/download, sandboxed HTML/SVG preview and inline Markdown preview, and a help (?) modal that explains the bash-staleness limitation in plain language.
  • Artifacts settings & filter — two server-backed settings (artifacts:enabled, artifacts:include, default *.md, *.html) let users hide the Artifacts tab entirely or scope it to specific paths. Filtering is a pure frontend pass over the unchanged registry (artifact-filter.js): matching file artifacts are kept; loose chat snippets are dropped whenever a filter is active; the empty state links to Settings when artifacts are hidden. Disabling hides the tab and falls back to Scratchpad.
  • Annotations — offset-anchored highlights on transcript messages and artifact source, persisted in SQLite (/api/annotations, GET/POST/DELETE) and synced across tabs via an annotations SSE snapshot. Mobile-friendly selection → note-modal flow (selectionchange trigger for touch). "Send notes to pi" groups notes by file with line numbers and fills the composer with a directive framing.
  • Backend/infra — new annotations table + handlers; SQLite pool capped to one connection (SetMaxOpenConns(1)) so concurrent writers queue instead of hitting "database is locked".
  • Docs — new artifacts.md / annotations.md sequence-flow deep-dives (artifacts.md now covers the filtering model); architecture docs and AGENTS.md updated for the new endpoint, SSE event, and frontend modules.

Related issue

Closes #

Type of change

  • feat — new feature
  • fix — bug fix
  • docs — documentation only
  • refactor — code change that neither fixes a bug nor adds a feature
  • style — formatting / UI styling, no behavior change
  • test — adding or updating tests
  • chore — build, tooling, or maintenance

Live vs. Export

  • Considered both the live app and the export snapshot
  • Kept internal/ui/live_templates/ in sync with web/src/session/ changes
  • No live-only chrome (Vite scripts, active composer, SSE/API) leaked into export — the artifacts/annotations hosts render only when IsLive, so the layers are no-ops in exported Gist snapshots

Testing

  • make check passes (test + build + vet)
  • Frontend tests (vitest) cover the change — registry/panel/filter, annotation range/api/layer, tab controller (445 tests)
  • Go tests (go test ./...) cover the change — annotations_test.go (create/list/upsert/delete/validation/scoping)
  • UI changes verified in a browser — Playwright E2E (artifacts.spec.ts incl. include-filter / empty-state / disabled-tab cases, annotations.spec.ts) across desktop, mobile, and iPad projects

setkyar added 8 commits June 4, 2026 14:27
Surface a session's substantial outputs and a review loop in the right
sidebar (Scratchpad / Artifacts / Annotations tabs):

- Artifacts: path-keyed, edit-aware registry that reconstructs each file's
  latest state from write/edit and simple mv/git mv/rm; sandboxed HTML/SVG and
  inline Markdown preview; copy/download; a help (?) modal explaining the bash
  staleness limitation.
- Annotations: offset-anchored highlights on transcript messages and artifact
  source, persisted in SQLite (/api/annotations) and synced across tabs via an
  `annotations` SSE snapshot; a mobile-friendly selection → note-modal flow; and
  "send notes to pi" that formats notes (file path + line numbers) into the
  composer. Serialize SQLite writes (SetMaxOpenConns(1)) and disable e2e
  auto-title noise.
Add artifacts and annotations sequence-flow docs; update architecture docs
(backend handler map + SQLite tables + SSE events, frontend module list,
system overview) and AGENTS.md to reflect the new /api/annotations endpoint,
the `annotations` SSE event, and the new web/src/session/ modules.
Surface two server-backed settings (artifacts:enabled, artifacts:include,
default *.md, *.html) so users can hide the Artifacts tab or scope it to
specific paths. Filtering is a pure frontend pass over the unchanged registry:
matching file artifacts are kept, chat snippets are dropped when any filter is
active, and the panel's empty state links to Settings when artifacts are hidden.
Disabling hides the tab entirely (falling back to Scratchpad).
The .right-sidebar-tab { display: inline-flex } rule overrode the [hidden]
attribute, so disabling "Show Artifacts panel" set tab.hidden but the tab stayed
visible. Add a .right-sidebar-tab[hidden] { display: none } rule. Reorder the
tabs to Scratchpad / Annotations / Artifacts. Strengthen the disabled-tab E2E to
assert real visibility (not just the property) so it catches this class of CSS bug.
Listen for the storage event in the session page and re-run the artifact filter
when artifacts:enabled/include changes in another tab, so toggling on /settings
takes effect without reloading the open session. E2E drives a second tab.
# Conflicts:
#	internal/ui/live_templates/styles/settings.css
…e is saved

Saving a note now fires an onCreate callback that opens the right sidebar if it's
collapsed and switches to the Annotations tab, so the just-created note is always
visible where it lands.
…ile send

On mobile the right sidebar is a full-screen overlay, so "Send N notes to pi"
now fires an onSend callback that collapses the sidebar (mobile only) before the
just-filled composer is focused, leaving it visible and ready to type into.
@setkyar
Copy link
Copy Markdown
Contributor Author

setkyar commented Jun 5, 2026

Annotation panel UX: reveal on save + mobile send

Two follow-up commits improving how the right sidebar behaves around annotations:

2b6dd4f — reveal the panel on the Annotations tab when a note is saved

  • Saving a note now fires an onCreate callback that opens the right sidebar if it's collapsed and switches to the Annotations tab, so the just-created note is always visible where it lands.
  • New open-only openSidebar() on the right-sidebar controller (won't toggle an already-open panel shut).

6ca883a — collapse the sidebar and focus the composer on mobile send

  • On mobile the right sidebar is a full-screen overlay, so "Send N notes to pi" now fires an onSend callback that collapses the sidebar (mobile only, max-width: 900px) before the just-filled composer is focused — leaving it visible and ready to type into. Desktop keeps the sidebar in place.
  • New collapseSidebar() on the controller.

Tests

  • Unit (annotation-layer.test.js): onCreate fires on save; onSend fires once and runs before focus.
  • E2E (annotations.spec.ts): reveal-on-save (starts collapsed, asserts it opens on the Notes tab); layout-aware mobile-send test (mobile projects assert collapse + composer focused; desktop/iPad-landscape assert the sidebar stays put). All 35 annotation E2E cases pass across 7 browser projects.
  • make check green; docs updated in docs/sequence-flows/annotations.md.

Resolve import-block conflict in web/src/session/session.js by keeping both the
artifacts/annotations imports (this branch) and the load-earlier banner import
(origin/main).
@setkyar setkyar merged commit 34e7d76 into main Jun 5, 2026
2 checks passed
@setkyar setkyar deleted the feature/artifact branch June 5, 2026 05:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant