Skip to content

PRD: Add a Report-a-Bug entry point with machine-managed bug sessions #249

Description

@jeonghun-jj-lee

PRD: Add a Report-a-Bug entry point with machine-managed bug sessions

Important

Problem

When Amicode misbehaves, reporting it means leaving the app, finding the right repo, and hand-assembling version/OS/run context — so bugs go unreported or arrive context-free. The report-a-bug skill already files intake-grade issues, but invoking it costs the user their current session's flow, and it only auto-collects run context from the session it runs in.

Approach

Add a Report-a-Bug entry point (a red bug-glyph icon button in the composer's bottom control row — right-anchored, immediately left of the send button — plus the amicode.reportBug palette command) that spawns a dedicated bug session — a single-purpose session pre-armed with the report-a-bug skill via the session command API — hosted in a collapsible dock above the composer (the todo-dock family) whose body is an iframe pinned to the bug session's route, with a context envelope (project, active run pointer, originating session) injected as session metadata so diagnostics survive the fresh session. Machine-managed lifecycle: archived when the report is filed (detected via a terminal sentinel line), hard-deleted if abandoned via the dock's close control; collapsing the dock never kills. Key reason: every seam already exists (session command API, the composer dock family, deck chat iframes, the app↔extension bridge, the sentinel-line idiom); the only new machinery is the dock component and the lifecycle handler.

Approaches Considered

  • Collapsible dock above the composer (chosen) — the todo-dock family seam: in-flow (no modal or focus-trap machinery), collapsible without killing, and the deck's chat-iframe precedent carries the content for free; user-chosen over the floating card.
  • Floating in-app card — matched the support-widget intent but was the only genuinely new UI machinery in the design; superseded by the dock.
  • Add-menu-adjacent composer slot — competed visually with composition controls; moved right-anchored beside send, where app-level chrome belongs (user-chosen).
  • Session-header ghost button — one row removed from the eyes at failure and renders only in an open session; the composer row is always present (drafts included). Superseded.
  • Beside editor tab (existing open-new-chat panel) — proven machinery, but a full editor tab rather than a lightweight surface, and close/filed signals cross two processes; rejected on UX fidelity.
  • Cold session with no context handoff — simplest, but run-context bugs would file degraded diagnostics and the skill's one-question rule forbids asking; rejected on filing quality.
  • Transcript-excerpt injection — richest context, but violates the skill's sanitize-by-construction posture; rejected on privacy architecture.
  • Sentinel-free filed detection (parse server events or tool calls / no auto-close) — fragile plumbing or silently dropped auto-close; rejected.
  • Palette-only entry — cheapest, but undiscoverable at the moment of failure; rejected.

Scope

  • In: composer button (v2 layout, left of send, danger-role red) + palette command; extension orchestration (create, arm, context envelope); bug-report dock + sentinel watcher (fork); lifecycle handler (archive-on-file, delete-on-abandon, single-open invariant); report-a-bug skill additions (envelope read, sentinel emit); public skills-bundle release including report-a-bug; runtime gate via boot param; CONTEXT.md term + lifecycle ADR.
  • Out: error-surface entry points (run-failure / error-boundary "report this") — follow-up once the core loop ships; deck-pane hosting — the dock covers the need; auto-detecting bugs — capture stays user-initiated by design; concurrent bug sessions — the single-open invariant instead.

Assumptions / Open Qs

  • The public skills bundle can cut a release including report-a-bug ahead of (or with) this feature; until then the button is gated off on Marketplace installs. The bundle release is the critical-path item.
  • The fork's vector icon family gains one bug glyph (none exists today), colored via the theme's existing semantic danger role (red; muted at rest, full on hover) — its first chrome use, a deliberate owner-sanctioned exception to single-accent chrome; full interaction-state contract in both themes, per the design-system skill.
  • The button targets the v2 composer (the layout Amicode serves); the legacy composer — whose attach button overlays the input and whose agent select sits in a tray below it — is not targeted.
  • Open: whether in-flight bug sessions are hidden from session lists before their terminal state (metadata marker + list filter — cheap) or transient visibility is acceptable.

Acceptance Criteria

  1. With the skill staged, a red bug-glyph icon button renders in the composer's bottom control row, immediately left of the send button; with it absent, no button renders — no dead affordance on Marketplace installs.
  2. Clicking the button expands the bug-report dock above the composer, hosting a new session whose first turn is the report-a-bug skill; the session's metadata carries the context envelope (project slug, active run-id pointer when present, originating session id).
  3. A second click while a bug dock is open reveals or re-expands the existing dock — never two bug sessions at once.
  4. When the skill files (either the gh path or the browser fallback), the dock shows the issue link, then auto-closes; the session is archived and absent from session lists.
  5. Closing the dock (its close control) before filing aborts any in-flight turn and hard-deletes the session; collapsing the dock (chevron) keeps the session alive. No trace of an abandoned session remains in history.
  6. A veto at the skill's confirm gate emits no sentinel: the dock stays open, and closing it thereafter deletes the session.
  7. The originating session is untouched on every path; the main chat continues uninterrupted while the dock is open.
  8. Extension unit tests cover orchestration and lifecycle; fork tests cover sentinel matching (filed / browser-fallback / no-match) and the button gate.

Key Decisions

  • Entry: icon button in the v2 composer's bottom control row, right-anchored immediately left of the send button (user-chosen placement), injected through an optional control slot following the composer's existing optional-control prop pattern; a new bug glyph in the app's vector icon family (never emoji), colored via the existing semantic danger token (v2-state-fg-danger — red-800 light / red-500 dark), muted at rest and full on hover, with the complete state contract (default/hover/active/focus-visible/disabled) in both themes, aria-label + tooltip so color is never the only signal; plus the amicode.reportBug palette command.
  • Arming: two-call idiom — create the session with metadata, then post the report-a-bug slash command; no synthetic clicks or composer prefill.
  • Context envelope: project slug + active run-id pointer (pointer-only, never absolute paths) + originating session id, as session metadata; the skill reads it in place of live-session context.
  • Filed detection: terminal sentinel line AMICODE_BUG_FILED <url> (the run-telemetry idiom) emitted by the skill after filing on both filing paths (filed-via-browser when there is no URL); an in-app watcher in the dock matches it and posts bug-filed over the bridge.
  • Lifecycle: filed → auto-close + archive; abandoned (dock close control) → abort + hard delete; collapse (chevron) never kills; one bug session at a time per window.
  • Distribution: bundle release + runtime gate (the boot param is set only when the skill is staged).
  • Bridge contracts: new message kinds amicode.reportBug (up), open-bug-report {sessionID} (down), bug-filed {sessionID, url} (up), bug-report-closed {sessionID} (up); all behind the existing strict allowlist posture.

Constraints & Invariants

  • One bug session at a time per window; the button reveals or re-expands rather than respawns.
  • Collapsing the dock never kills the bug session; only the close control (before filing) or filing itself ends it.
  • Run context travels as run-id pointers only, per the skill's sanitization invariants — no absolute paths, no log payloads beyond the skill's existing bounded tail.
  • Bug sessions never appear in session history in any state (archived on file, deleted on abandon; in-flight handling per the open question).
  • The button never renders when the skill is not staged.
  • The sentinel is emitted only after actual filing — never at the confirm gate.
  • The originating session is never modified, navigated, or closed by any bug-session path.

User Stories

  • A researcher whose solve stalls clicks the red bug icon beside the send button, answers one question in the dock above the composer, confirms the draft, and watches the dock close itself with the issue link — the main session never left the flow.
  • A researcher on a Marketplace install never sees the button until their skills bundle includes report-a-bug; when it does, the button appears with no extension update.
  • A reviewer receiving the filed issue finds the same diagnostics quality as an in-session filing (extension version, OS, engine pin, run-id pointer), because the envelope carried the run context across.

Modules & Interfaces

  • Fork: bug-report button — red bug-glyph icon button in the v2 composer's bottom row, right-anchored immediately left of send, exposed through an optional control slot on the prompt input and gated on the boot param; posts the report command over the bridge (reveals or re-expands the existing dock instead if one is open).
  • Fork: bug-report dock — a member of the composer's dock family (todo/question/permission/revert), animated expand/collapse; header bar carries the title, a collapse chevron (keeps the session alive), and a close control (posts bug-report-closed); body is an iframe pinned to the bug session's route (deck chat-iframe precedent); renders the terminal end-state with the issue link.
  • Fork: sentinel watcher — lives in the dock; watches the bug session's message stream for the sentinel; posts bug-filed on match.
  • Extension: report command + orchestrator — bridge allowlist entry; creates and arms the session; posts open-bug-report; enforces single-open.
  • Extension: lifecycle handlerbug-filed → archive + close dock; bug-report-closed before filing → abort + delete; delete on orchestration failure (no orphan sessions); ignores messages for unknown session ids.
  • Plugin: report-a-bug skill — reads the context envelope from session metadata when present; emits the sentinel after filing on both paths.
  • Bundle: public skills-bundle release including report-a-bug.

Testing Decisions

  • Extension: vitest over orchestration and lifecycle with the server API mocked at the fetch seam (create/arm/open, filed→archive, closed→abort+delete, single-open, unknown-id rejection).
  • Fork: unit tests for sentinel matching (filed, browser-fallback, no-match, veto), button gating on the boot param, and dock reveal-vs-respawn plus collapse-vs-close behavior.
  • Skill: sentinel presence in both filing paths as a release checklist item on the plugin side.
  • Manual QA: the full loop on a dev checkout (which stages the skill today); the gate verified by pointing at the old bundle.

Risks

  • Version skew (button present, skill absent) — mitigated by the runtime gate; the bundle release is the critical-path item.
  • Lifecycle surprise — deleting a session on close is unprecedented in the app; mitigated by the ADR and by deletion applying only to abandoned, never to filed, sessions.
  • Iframe depth (dock iframe inside the app inside the chat webview) — precedented by widget frames and the deck's chat iframes; the in-flow dock avoids modal focus-trap issues, and keyboard handling still gets explicit QA attention.
  • Cross-repo coordination (fork, extension, plugin land in concert) — mitigated by gating: every piece is inert until the boot param and the bundle align.
Prior Art / Patterns
  • The session command API (create + slash-command) — how skills are invoked programmatically; the same idiom the app uses for async prompts.
  • The composer dock family (todo / question / permission / revert docks) — collapsible, animated surfaces above the textbox; the dock shell's precedent (the question dock even proves interactive input in a dock).
  • Widget frames and the deck's URL-pinned chat iframes — the dock body's hosting precedent.
  • The app↔extension bridge with its strict allowlist — the command/message lane all four new message kinds ride.
  • AMICODE_* sentinel lines — the run-telemetry idiom the filed sentinel mirrors.
  • Session archive (soft-hide, excluded from lists by default) and hard delete (permanent, recursive) — the two lifecycle endpoints.
  • The fork patch-stack conventions — fork-side chrome ownership and boot-param feature gating.

Source

  • Designed via brainstorming + grill-with-docs (2026-08-03 session). Durable record: amicode repo ADR docs/adr/0004-bug-session-lifecycle.md + the CONTEXT.md "Bug session" term (both land with this issue).

Notes

  • report-a-bug is surface: public but absent from the pinned public skills bundle — the bundle release is a hard dependency of this feature lighting up for Marketplace users.
  • Follow-ups (not this issue): error-surface entry points; deck-pane hosting; reviewer-agent maturation of intake issues.

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions