Commit Graph

1098 Commits

Author SHA1 Message Date
Michael Ramos 908ea9cf32 refactor: shared feedback templates + preserve plan title on deny (#296) (#298)
* refactor: shared feedback templates across all integrations

The deny/feedback prompts sent to LLM agents were duplicated as inline
string templates in hook, opencode-plugin, and pi-extension — each with
different tone and framing. The hook's directive style (from #224) was
the most effective at getting agents to address feedback. This extracts
all feedback text into @plannotator/shared/feedback-templates and has
every integration import from the single source of truth.

Closes #215 follow-up (propagates fix to OpenCode and Pi).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: rewrite feedback template tests around contracts not implementation

Tests now verify: cross-integration consistency, verbatim feedback
preservation, empty input handling, and that approved messages don't
contain directive language. Wording can change freely without breaking
tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: instruct agent to preserve plan title on resubmission (#296)

Version history slugs are derived from the plan's first # heading.
When the agent renames the heading after a deny, the version chain
breaks and the user loses diffs. The deny template now tells the
agent not to change the title unless explicitly asked.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* style: improve plan deny preamble readability

Break the dense single-paragraph preamble into structured sections:
verdict, directive, and rules list. Easier for agents to parse.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: add missing @plannotator/shared workspace dependency

Hook and OpenCode plugin imported from @plannotator/shared/feedback-templates
without declaring it as a dependency. Worked locally but failed in CI.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* revert: remove code review and annotate from shared templates

Scope-crept into code review/annotate feedback which introduced a double
heading regression and dropped integration-specific strings. Reverts those
paths to their original inline strings; shared module now only covers
plan deny feedback.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: restore Pi plan file hint and vendor template for source installs

Add optional planFilePath to planDenyFeedback so Pi can tell the agent
to read the plan file before editing. Check in a vendored copy of the
template so Pi source installs work without running build:pi first.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 19:38:22 -07:00
sercan tor 6cde39507b feat: add file-scoped comments to /plannotator-review (#303)
* feat(review): add file-scoped comments in code review (#302)

* refactor: reuse CommentPopover for file comment form

Replace the custom popover implementation in FileHeader (~88 lines of
hand-rolled state, click-outside, and escape handling) with the existing
CommentPopover component from packages/ui. This gives us expand-to-dialog
mode, image attachments, scroll-aware positioning, and keyboard shortcuts
for free, while saving ~62 net lines.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Michael Ramos <mdramos8@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 14:58:48 -07:00
Michael Ramos e1bd27aae4 feat: custom theme system with 18 built-in themes (#294)
* feat: custom theme system with 15 built-in themes

Consolidate CSS theming into a single source of truth (packages/ui/theme.css)
and introduce a multi-theme architecture where each theme defines both dark
and light mode variants. Users can pick a color palette (theme) and separately
toggle dark/light mode within it.

- Extract shared color tokens, Tailwind bridge, and base styles into packages/ui/theme.css
- Replace hardcoded oklch values with token references (oklch from var syntax)
- Fix 3 light-mode bugs in review-editor diff colors
- Create 15 built-in themes: Plannotator (default), Claude+, Soft Pop, Adwaita,
  Caffeine, Cyberdyne, Cyberfunk, Doom 64, Dracula, Gruvbox, PaulMillr,
  Quantum Rose, Solar Dusk, Terminal, Tinacious
- Expand ThemeProvider to manage colorTheme + mode independently
- Add Theme tab to Settings with mode toggle, search, and swatch grid
- Dark-only themes (Dracula, Terminal, etc.) suppress light class to prevent
  broken styling; light-only themes (Tinacious) force it
- Cookie persistence: plannotator-color-theme for palette, existing key for mode
- Include theme conversion script for FinSitter theme adaptation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: refine themes, add Catppuccin/Rosé Pine/Monokai Pro/Synthwave 84/Tokyo Night

Theme curation:
- Replace Cyberdyne with Synthwave '84 (from robb0wen/synthwave-vscode)
- Replace Cyberfunk with Catppuccin (Mocha dark + Latte light), Rosé Pine
  (dark + Dawn light), Monokai Pro (dark only), Tokyo Night (Storm + Day)
- Rewrite Gruvbox from canonical source (morhetz/gruvbox)
- Rewrite Adwaita from canonical VS Code theme (piousdeer/vscode-adwaita)
- Rewrite PaulMillr from Ghostty canonical palette

Theme fixes:
- Fix faded Send Feedback button on Solar Dusk, Quantum Rose, Caffeine
  (accent colors were too dark/invisible at 15% opacity)
- Fix Dracula/Terminal/PaulMillr/Tinacious light mode breakage — dark-only
  themes now suppress .light class via modeSupport in ThemeProvider
- Fix code block backgrounds — use --code-bg token instead of --muted
- Add faint green grid overlay for Terminal theme
- Alphabetize theme registry (Plannotator first)

Code review diff theming:
- Pass theme colors into @pierre/diffs shadow DOM via unsafeCSS prop
- Dynamic themeType based on resolved mode

18 built-in themes: Plannotator, Absolutely, Adwaita, Caffeine, Catppuccin,
Doom 64, Dracula, Gruvbox, Monokai Pro, PaulMillr, Quantum Rose, Rosé Pine,
Soft Pop, Solar Dusk, Synthwave '84, Terminal, Tinacious, Tokyo Night

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: increase settings modal height for theme grid visibility

Remove 340px cap on theme grid, bump content area from 70vh to 85vh
so all themes are visible without scrolling.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor: memoize ThemeProvider context, deduplicate Mode type, clean up DiffViewer

From /simplify review:
- Export Mode type from ThemeProvider, import in ThemeTab (was duplicated)
- Add resolvedMode to context — consumers no longer re-query matchMedia
- Memoize context value with useMemo, setters with useCallback (prevents
  unnecessary re-renders of all useTheme consumers)
- Consolidate DiffViewer's two pierre state vars into single object
- Use resolvedMode from context in DiffViewer instead of classList check
- Format crammed single-line extended tokens in 4 theme CSS files

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: prevent FOUC, fix system mode stale read, restore marketing theme class

P1: Marketing site inline script now sets theme-{name} class on <html>
    before first paint (reads plannotator-color-theme cookie). Without this,
    CSS tokens under .theme-* selectors were never active.

P2: System mode effect now re-reads matchMedia.matches immediately when
    entering system mode, not just on future changes. Fixes stale resolvedMode
    when OS preference changed while pinned to explicit dark/light.

P3: ThemeProvider applies theme class synchronously during render (not in
    a passive useEffect) to prevent flash of unstyled content on hard refresh.
    Also extracted resolveThemeClasses to module scope to avoid useCallback.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add Quick Copy button, fix import icon, comment out agent badge

- Add Quick Copy button to annotation panel footer (splits horizontally
  with existing Quick Share). Copies annotations wrapped with the deny
  preamble so output is paste-ready for agent sessions.
- Export Modal annotations copy also wraps with deny preamble
- Extract wrapFeedbackForAgent() utility in parser.ts as single source
  of truth for the preamble text
- Fix desktop import icon to match mobile (arrow-into-document, not download)
- Comment out code review agent badge — unreliable across multiple harnesses

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 21:26:51 -07:00
Michael Ramos 54e951e2f7 fix: don't ask agent to address feedback on LGTM approval (#293)
* fix: don't ask agent to address feedback on LGTM approval (#284)

When the reviewer approves with no annotations, send a neutral
"Code review completed — no changes requested." message instead of
the contradictory "LGTM" + "Please address this feedback."

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: use explicit approved flag instead of annotations.length heuristic

The previous fix inferred LGTM from an empty annotations array, but
VS Code editor annotations are carried in feedbackMarkdown without
populating the annotations array — causing real review comments to be
misclassified as approvals. Thread an explicit `approved` boolean from
the UI through the review server to all three integrations.

Closes #284

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: append assertive instruction to review feedback output

When the reviewer submits actual feedback, append "The reviewer has
identified issues above. You must address all of them." so the agent
treats annotations with urgency rather than soft-acknowledging them.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: annotate unused LGTM feedback string

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 17:58:57 -07:00
Michael Ramos f5705cdb9c fix: non-blocking browser launch in Pi extension (Linux) (#292)
* fix: use non-blocking spawn for browser launch in Pi extension

execSync(xdg-open ...) blocks the Node.js event loop, preventing the
HTTP server from responding to the browser's initial request on Linux
desktops where xdg-open doesn't immediately exit.

Closes #288

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: handle async spawn errors in Pi openBrowser

spawn() reports missing-command failures asynchronously via an 'error'
event. Without a listener, a bad PLANNOTATOR_BROWSER or missing
xdg-open crashes the Pi process. Add child.once("error", () => {})
to swallow it silently, matching the original execSync try/catch
behavior.

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 17:40:44 -07:00
Michael Ramos d2238ac736 Context for video demos 2026-03-13 19:06:50 -07:00
Michael Ramos 574d7af3da Enhance README with Code Review section and title update
Updated description to include 'Code' in the title and added a new section for Code Review.
2026-03-13 18:59:55 -07:00
Marcelo Terreiro Prado d7ccc55f33 feat: configurable Bear tags + fix double-title bug (#283)
* feat: configurable Bear tags + fix double-title bug

- Fix double title: strip H1 from Bear note body since `title` URL
  param already carries it
- Add custom tags setting (comma-separated, kebab-case) with
  auto-normalization; empty = auto-generated tags (existing behavior)
- Add tag position setting: prepend (after title) or append (default)
- Settings UI in Bear tab with inputs matching existing design
- Dev mock: add /api/approve + /api/save-notes handlers for Bear
  testing in dev mode

* revert: drop dev-mock-api changes

* fix: simplify H1 stripping regex — no wording assumption

* test: add Bear integration tests + restore JSDoc comments

* refactor: export Bear helpers from integrations, import in tests

* test: use dummy title in Bear tests
2026-03-12 16:30:51 -07:00
Itay Grubman 7817c46d71 fix: suppress native mobile context menu on text selection (#281) 2026-03-12 16:15:51 -07:00
Michael Ramos 8b8487db3e docs: add AGENTS.md (copy of CLAUDE.md)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 01:29:32 -07:00
Michael Ramos ddb5d53906 docs: tighten sharing section in README
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 01:23:44 -07:00
Michael Ramos 0accd5c31f chore: remove unneeded scripts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 01:21:50 -07:00
Michael Ramos 74ccf42fbe chore: bump version to 0.12.0
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
v0.12.0
2026-03-12 01:09:21 -07:00
Michael Ramos e65c4aedee fix: clear Pi jiti cache and add Pi section to install output
Clear /tmp/jiti on install to avoid stale cached Pi extension. Add a
PI USERS section to the post-install output with the install command.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 01:04:04 -07:00
Michael Ramos 7417f49076 feat: add new settings indicator for Plan Width and Quick Labels
Pulsing dot on the Settings gear button and "new" pill badges on the
Display and Labels tabs signal newly added settings. Dismissed on first
open via cookie-based version gating.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 01:04:00 -07:00
Michael Ramos fbd4ee4f06 Remove non-critical welcome dialogs (#280)
* chore: remove non-critical welcome dialogs

Remove UI Features Setup, Plan Diff Marketing, and What's New v0.11.0
dialogs from the first-run cascade. Only the Permission Mode Setup
dialog remains as it's the only one that affects agent behavior.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: extract demo plan content to separate file

Moves the 334-line PLAN_CONTENT string from App.tsx to demoPlan.ts to reduce clutter.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 00:27:16 -07:00
Michael Ramos 0ad1cce653 chore: move demo diagram sections below SQL code block
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 23:44:12 -07:00
Itay Grubman 9a23c249b2 feat: add quick label selection mode for one-click annotations (#272)
* feat: add quick annotation labels for one-click preset feedback

Add preset label chips (Needs tests, Security concern, Break this up, etc.)
that allow instant annotation without typing. Includes ⚡ toolbar button,
Alt+1..8 keyboard shortcuts, label customization in Settings, and label
summary in export output.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: add quick label selection mode for one-click annotations

* feat: redesign quick label picker UX and add label tips

- Redesign FloatingQuickLabelPicker as a vertical context-menu style list
  with cursor-anchored positioning (appears at mouseup point, not selection center)
- Unify label dropdown: toolbar and quick-label mode now share the same
  FloatingQuickLabelPicker component (removed duplicate InlineQuickLabelDropdown)
- Fix above/below flip positioning (follow CommentPopover pattern with
  conditional translateY)
- Add label tips: optional instruction text on QuickLabel that gets injected
  into agent feedback as a blockquote below the label
- Add tip editor in Settings with three visual states (empty/editing/filled)
- Add "Missing overview" default label with a tip for requesting narrative context
- Extend keyboard shortcuts from Alt+1-8 to Alt+1-9
- Suppress input method toggle (Alt) when label picker is open
- Reorder default labels: Clarify this, Needs tests, Consider edge cases,
  Missing overview, Security concern, Break this up, Wrong order, Discuss first,
  Nice approach

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: curate default labels, add cyan/amber colors, bare digit shortcuts

Finalize the 10 default quick labels based on user feedback data:
clarify, overview, verify, example, patterns, alternatives, regression,
out-of-scope, tests, nice-approach. Each label gets a unique color
(added cyan and amber to the palette). Bare digit keys (1-0) now apply
labels when the picker is open, Alt+N still works everywhere. Tip editor
cursor starts at beginning for readability.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: prevent duplicate annotation when digit key fires both toolbar and picker handlers

When the quick label picker is open from the toolbar's zap button,
let FloatingQuickLabelPicker own all keyboard input instead of both
components handling the same keypress.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Michael Ramos <mdramos8@gmail.com>
2026-03-11 23:39:46 -07:00
김영준E e51abc6fd5 feat: render diagrams by default in plan review (#279) 2026-03-11 23:13:01 -07:00
dgrissen2 59724b7fe2 fix: enable linked doc navigation in annotate mode (#276)
The annotate server was missing the /api/doc endpoint, so clicking
.md links (e.g., [see other](sibling.md)) in annotated files showed
"Failed to connect to server" — the request fell through to the SPA
catch-all and returned HTML instead of JSON.

Three changes:

1. annotate.ts — Add /api/doc route, auto-injecting the source
   file's parent directory as ?base= so relative links resolve
   from the correct location.

2. reference-handlers.ts — handleDoc() now accepts an optional
   ?base= query param and tries resolving relative paths against
   it before falling back to the project-root glob search.

3. App.tsx — handleOpenLinkedDoc passes the current file's
   directory as ?base= when navigating linked-doc → linked-doc,
   so chained relative links resolve correctly.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 23:10:54 -07:00
dgrissen2 2d1016a3fd feat: render markdown images with lightbox zoom (#271)
Adds full inline image rendering to the Viewer for both annotate and
plan review modes. Previously, ![alt](path) syntax was treated as plain
text.

## What changed

### Viewer.tsx
- Added `![alt](path)` regex to InlineMarkdown before the link pattern.
  Images starting with `!` were silently falling through to plain text
  because `!` was not in the special-character scan set — added it.
- Added `imageBaseDir` prop (flows Viewer → BlockRenderer → InlineMarkdown)
  so relative image paths in markdown resolve against the annotated file's
  directory rather than the server's cwd.
- Added `onImageClick` callback (same prop chain) to open lightbox on click.
- Added `ImageLightbox` component: full-screen dark backdrop, image scaled
  to 90vw/85vh with object-contain, alt text caption, closes on Escape or
  backdrop click. Portaled to document.body.
- Images render with `cursor-zoom-in` to hint they're clickable.

### App.tsx
- Captures `filePath` from `/api/plan` response (already sent by annotate
  server) and derives `imageBaseDir` (directory of the markdown file).
- Passes `imageBaseDir` to `<Viewer>`.

### ImageThumbnail.tsx
- `getImageSrc()` now accepts an optional `base` parameter. For relative
  local paths, appends `&base=<dir>` to the `/api/image` query string.

### shared-handlers.ts
- `handleImage` falls back to resolving the path relative to a `base`
  query param when the primary path doesn't exist and the path is relative.
  Covers the common case of `![chart](./images/chart.png)` in a markdown
  file opened from an arbitrary directory.

## Behavior
- Remote URLs (https://...) render directly, no proxy.
- Absolute local paths route through /api/image as before.
- Relative paths resolve against the markdown file's directory via ?base=.
- Click any image → lightbox. Escape or click outside → dismiss.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Michael Ramos <mdramos8@gmail.com>
2026-03-11 18:48:05 -07:00
Itay Grubman c0076621ac feat: add quick annotation labels for one-click preset feedback (#268)
Add preset label chips (Needs tests, Security concern, Break this up, etc.)
that allow instant annotation without typing. Includes ⚡ toolbar button,
Alt+1..8 keyboard shortcuts, label customization in Settings, and label
summary in export output.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Michael Ramos <mdramos8@gmail.com>
2026-03-11 16:49:30 -07:00
Itay Grubman 5437a37da9 feat: add mobile compatibility (#260)
* feat: add mobile compatibility

- Add responsive hamburger menu with all header actions (MobileMenu)
- Annotation panel renders as full-screen overlay on mobile with backdrop and close button
- Panel starts closed on mobile (<768px)
- Touch support for resize handles, pinpoint annotations, and toolstrip buttons
- Mobile text selection creates annotations via highlighter.fromRange() bridge
- Card action buttons always visible on touch devices (hover:none media query)
- Settings modal uses horizontal tab bar on mobile
- CommentPopover width capped to viewport on small screens
- Replace mousedown with pointerdown for touch-compatible click-outside handling
- Add useIsMobile reactive hook for breakpoint detection
- Desktop layout (>=768px) unchanged

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: mobile layout polish — panel gap, button overlap, responsive labels

- AnnotationPanel: fix bottom gap on mobile overlay (inset-y-12 → top-12 bottom-0)
- Viewer: push in-plan action buttons below badges on mobile (mt-6), add
  clear-right before frontmatter, show short labels (Comment/Copy) on mobile
- App: reduce mobile horizontal padding to 8px (px-2)
- test-hook.sh: build review before hook to fix missing dist error

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: add plan width display setting with compact/default/wide options

Adds a configurable plan width preference (compact 832px, default 1040px,
wide 1280px) with an abstract layout preview in Settings. Dynamic max-width
flows through to Viewer, PlanDiffViewer, and the toolstrip. Default is
compact to preserve existing behavior.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Michael Ramos <mdramos8@gmail.com>
2026-03-11 16:25:48 -07:00
김영준E 33c7c0be00 feat: Add Graphviz diagram rendering in plan mode (#266)
* feat: add Graphviz rendering for plan mode

Support graphviz/dot/gv fenced blocks in the shared viewer and add a Graphviz sample diagram to PLAN_CONTENT for quick validation.

* fix: use imperative wheel listener with passive:false in GraphvizBlock
2026-03-11 07:40:26 -07:00
김영준E 5b28def742 feat: Improve Mermaid diagram viewing experience (#264)
* fix: stabilize Mermaid fullscreen rendering and Safari fit behavior

* fix: block browser zoom and preserve fullscreen Mermaid wheel zoom

* refactor: simplify Mermaid pinch zoom event handling
2026-03-11 07:39:15 -07:00
Barbaros G. f650ef9cb0 fix: open browser in SSH remote when PLANNOTATOR_BROWSER is set (#259) (#274)
When VS Code extension sets PLANNOTATOR_BROWSER, always call openBrowser()
even in remote sessions, so the extension's open-in-vscode handler is used.
2026-03-11 07:37:25 -07:00
김영준E 41059d8e43 fix: Support Windows markdown paths in CLI annotate flow (#267)
* fix(annotate): support Windows markdown paths in CLI annotate flow

* fix tmp path

* fix resolve-file.ts

* Update command to use EXE_PATH variable

* Update command path for plugin hooks in install.ps1

* test: add core test suite for path resolution, storage, remote detection, and install scripts

- resolve-file: absolute paths, relative paths, case-insensitive search, ignored dirs, extension filtering, ambiguity, Windows separators
- storage: slug generation, tilde expansion, version history, deduplication
- remote: env var detection (PLANNOTATOR_REMOTE, SSH_TTY), port config and validation
- image: tmpdir usage, extension validation
- install scripts: JSON structure validation, checksum verification, arch detection, full exe path in hooks

79 tests, 35ms

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* ci: add test workflow and gate release builds on tests

- New test.yml: runs `bun test` on PRs and pushes to main
- release.yml: tests must pass before build job runs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: resolve pre-existing test failures for CI compatibility

- project.test.ts: make repo name assertion portable (works in CI where
  checkout dir differs from local dev)
- vscode mock: add missing APIs needed by editor-annotations.ts
  (comments, languages, Range, CodeActionKind, decorations)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* test: remove Viewer.test.tsx and happy-dom dependency

Tests didn't exercise any application code — they manually constructed
DOM elements inline and verified DOM API behavior, not Viewer.tsx logic.
The mock highlighter didn't simulate real hljs, and one test could never
fail due to its try/catch structure.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: use targeted markdown glob and restore clean lockfile

- Replace **/* glob with **/*.[mM][dD]{,[xX]} to only scan markdown
  files during case-insensitive search (avoids iterating every file)
- Restore package.json key ordering from main, only removing happy-dom
- Regenerate bun.lock from main's base to eliminate version drift

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* test: drop redundant test and fix weak assertion

- Remove redundant PLANNOTATOR_REMOTE=TRUE test (already covered by true)
- Fix UPLOAD_DIR assertion that would pass even with hardcoded /tmp

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Michael Ramos <mdramos8@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 17:47:07 -07:00
Michael Ramos 1480915f67 fix: detect OS for update banner install command (#265) (#270)
Windows users were always shown the bash install command. Now uses
navigator.platform to show the PowerShell command on Windows.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 08:53:05 -07:00
Michael Ramos b6bec6943b feat: add Pi origin support to code review UI (#263)
* feat: add Pi origin support to code review UI and update banner

Pi users were seeing "OpenCode" badge and getting the wrong update
command. Adds 'pi' to origin types in review/annotate servers, shows
violet "Pi" badge in code review header, and copies the correct
`pi install` command in the update banner.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: update Pi extension from install scripts when pi is available

The install scripts now check if `pi` is on PATH and run
`pi install npm:@plannotator/pi-extension` to update the extension.
Silent for users without Pi installed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 23:41:29 -07:00
Michael Ramos 709e9ffaa1 docs: remove redundant encryption note, update Codex description
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 20:51:18 -07:00
Michael Ramos 3f51dbf72a docs: add Codex support (#261)
* docs: add Codex support documentation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs(codex): note plan mode not yet supported

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs(codex): move plan mode notice to top

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: note plan mode not yet supported in Codex sections

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: remove redundant Codex description line

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs(codex): lead with supported features

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs(codex): use ! prefix for shell commands

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 20:49:06 -07:00
Michael Ramos bd8268de6c chore: bump version to 0.11.4
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
v0.11.4
2026-03-09 07:40:50 -07:00
Michael Ramos d29dd08c13 feat: git add files from code review UI (#257)
* feat: add per-file git add from code review UI (#254)

Adds the ability to `git add` individual files directly from the code
review interface. Users can stage approved files then switch to the new
"Unstaged changes" diff view to see only remaining work.

- POST /api/git-add endpoint with worktree support
- gitAddFile/gitResetFile utilities in packages/server/git.ts
- "Staged changes" and "Unstaged changes" added to diff type dropdown
- useGitAdd hook encapsulating all staging state and API logic
- "Git Add" / "Added" toggle button in FileHeader (next to Viewed)
- Visual indicator (left border) for staged files in sidebar FileTree

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* style: use green background tint for staged files instead of left border

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: support staged/unstaged diffs in worktrees and display stage errors

Adds "staged" and "unstaged" to worktree sub-type allowlists (server parser,
client parser, and runGitDiff switch), displays stageError in FileHeader,
and documents /api/git-add in CLAUDE.md.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: clean up git add feature — fix stale closure, timeout leak, dedup validation

- useGitAdd: use ref for stagedFiles to stabilize stageFile callback,
  clear error timeout on reset, drop unnecessary useMemo
- App.tsx: wrap onFileViewed in useCallback
- FileTree: merge duplicate staged count conditionals
- review.ts: reuse exported validateFilePath for /api/file-content

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 07:31:17 -07:00
Michael Ramos 8201fe3537 fix(vscode): reuse IPC server port across restarts (#252) (#256)
Persist the IPC port in workspaceState and try to rebind to it on
activation so restored terminals still have a valid PLANNOTATOR_VSCODE_PORT.
Falls back to a random port if the preferred one is taken.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 06:56:03 -07:00
dgrissen2 190f7ec412 feat: clipboard paste for per-annotation images & fix absolute path resolution (#255)
Add capture-phase paste listener to AttachmentsButton so users can
Cmd+V / Ctrl+V images directly into per-annotation attachments when
the popover is open. Uses stopPropagation to prevent the global paste
handler in App.tsx from also processing the event. Adds a platform-aware
keyboard shortcut hint in the drop zone.

Also fixes a regression from #237 where resolveMarkdownFile rejected
absolute paths outside the project root. The original behavior allowed
any absolute path the user explicitly provided; the security boundary
should only apply to relative path / bare filename search.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-09 06:35:03 -07:00
Itay Grubman 2a461380b1 feat: bidirectional scroll navigation between annotations and highlights (#253)
* feat: bidirectional scroll navigation between annotations and highlights

When reviewing long plans with many annotations, it's hard to visually
connect which annotation card corresponds to which highlighted line.

- Click annotation card → scrolls content to the highlight + applies
  a bright cyan "focused" color for visibility
- Click highlighted text → scrolls the right panel to bring the
  corresponding annotation card into view
- Works with both web-highlighter and manually created (shared/imported)
  annotations
- Handles edge cases: global comments (no highlight), multi-node
  selections, already-visible elements

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: scroll to center and skip focus on annotation creation

- Change scrollIntoView block from 'nearest' to 'center' so targets
  appear prominently in the middle of the viewport
- Track just-created annotation IDs to skip scroll+focus effect when
  a new annotation is added (user is already looking at it)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 06:31:33 -07:00
renovate[bot] d259748645 chore(deps): update github actions (#251)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-09 06:20:48 -07:00
renovate[bot] d23c730d62 chore(deps): update github actions (#250)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-09 06:20:40 -07:00
Michael Ramos c19097dc52 Remove accidentally committed test markdown file (#249)
The test-markdown-highlighting.md file was a test artifact that
shouldn't have been committed to the project root.
2026-03-08 21:34:31 -07:00
Michael Ramos c7532863c6 chore: bump version to 0.11.3
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
v0.11.3
2026-03-08 16:31:51 -07:00
Michael Ramos 933f44737e feat: split worktree/diff-type into separate controls (#248)
* feat: split worktree/diff-type into separate controls

The single dropdown that mixed diff type selection (uncommitted, last-commit,
branch) with worktree switching was confusing — entering a worktree silently
replaced all dropdown options with no persistent indicator of which worktree
was active.

Split into two controls:
- Context dropdown: switches between main repo and worktrees (only shown
  when worktrees exist, highlighted when a worktree is active)
- View dropdown: always shows the same diff type options regardless of context

Server changes:
- GitContext now exposes worktrees as a separate field
- Removed getWorktreeDiffOptions() and back-to-main sentinel handling
- Simplified /api/diff/switch (no more diffOptions replacement)

Client changes:
- New activeWorktreePath state + handleWorktreeSwitch callback
- handleDiffSwitch composes worktree prefix from context automatically
- Derived activeDiffBase strips worktree prefix for dropdown display

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: derive activeWorktreePath from diffType instead of separate state

Eliminates redundant state — activeWorktreePath and activeDiffBase are
now both derived in a single useMemo from the composite diffType string.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: move DiffOption, WorktreeInfo, GitContext to @plannotator/shared

Eliminates duplicate interface definitions across server and client.
Types now live in packages/shared/types.ts and are imported by both
packages/server/git.ts and packages/review-editor/.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 16:15:14 -07:00
Michael Ramos 472e17be3d feat: expandable diff context in code review (#247)
* feat: expandable diff context in code review (closes #243)

Switch from PatchDiff to FileDiff component from @pierre/diffs to enable
GitHub-style "show more lines" buttons between hunks. The library handles
all expansion UI when provided full file contents via oldLines/newLines.

- Add /api/file-content endpoint to serve old/new file content per diff type
- Add getFileContentsForDiff() helper with ref mapping for all diff types
- Parse patch client-side via getSingularPatch(), augment with file contents
- Update @pierre/diffs from 1.0.4 to 1.0.11 (scroll sync fix, no breaking changes)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: upgrade @pierre/diffs to beta, re-parse patch with full file contents

The previous approach spread file content arrays onto a partial-mode
FileDiffMetadata, causing hunk index mismatches and Shiki decoration
errors. Now uses processFile() to re-parse the patch with oldFile/newFile
so hunk indices are computed against the full file (isPartial: false),
which is required for expansion to work correctly.

Also fixes a flash error on file switch by tagging fileContents with the
filePath they were fetched for, preventing stale contents from being
paired with the wrong patch during the render before useEffect fires.

- Upgrade @pierre/diffs from ^1.0.x to ^1.1.0-beta.19 in all workspaces
- Add test fixtures for disjoint hunks, deleted/renamed/new files

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: abort stale file-content fetches, validate path params

- Add AbortController to file-content fetch effect to cancel in-flight
  requests when switching files
- Reject path traversal (.. or absolute paths) on /api/file-content
- Document /api/file-content endpoint in CLAUDE.md

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 14:00:43 -07:00
Michael Ramos 47bfc4bfd4 feat: hierarchical folder tree in code review sidebar (#246)
Group changed files by directory with collapsible folders, aggregate
+/- stats per folder, and auto-expand on keyboard navigation.
Single-child directories collapse (e.g., src/utils/ as one node).
Falls back to flat list for single-directory diffs.

Closes #161

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 17:20:08 -08:00
Michael Ramos 93159240a7 chore: pin deploy.yml actions to SHAs + add Renovate (#244)
* chore: pin GitHub Actions to SHAs and add Renovate config

Pin all actions in deploy.yml to full commit SHAs to prevent tag
force-push supply chain attacks. Upgrade actions/checkout from v4
to v6.0.2 to match release.yml.

Add renovate.json scoped to GitHub Actions only — weekly grouped
PRs with automerge, zero noise from npm dependencies.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: move renovate.json to .github/renovate.json

Reduces root directory clutter. Renovate supports this path natively.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 16:44:25 -08:00
Michael Ramos a6361356b9 chore: bump version to 0.11.2
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
v0.11.2
2026-03-07 12:38:06 -08:00
Michael Ramos dcb979c08f test: add light mode code block fixture to test-hook.sh
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 12:36:34 -08:00
Michael Ramos 819948c724 docs: add editor annotations and shared package to CLAUDE.md
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 12:26:59 -08:00
Michael Ramos cb4de46636 feat: VS Code editor annotations + theme integration (#239)
* feat: add shared EditorAnnotation type

Single source of truth for the editor annotation interface,
imported by both @plannotator/server and @plannotator/ui.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: editor annotation server endpoints

In-memory store with POST/GET/DELETE endpoints for editor annotations.
The array lives in the handler closure and dies with the server session.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: editor annotation UI — polling hook, card, panel, and export

- useEditorAnnotations hook with auto-disable polling (500ms interval)
- EditorAnnotationCard with file path, code preview, and comment
- AnnotationPanel conditionally renders editor annotation section
- exportEditorAnnotations formats annotations for Claude feedback
- App.tsx wires hook, includes in output memo and send feedback gate

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: VS Code extension editor annotation command

Cmd+Shift+. or right-click to capture selected text as an annotation.
POSTs through the cookie proxy to the plannotator server. Adds amber
left-border decorations on annotated lines, cleared on panel close.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: inline comment threads, lightbulb menu, and stronger decorations

Replace showInputBox with VS Code CommentController for inline annotation
threads anchored to selected code. Add CodeActionProvider for lightbulb
discoverability. Stronger decoration styling with gutter icon.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: VS Code theme integration for webview

Bridge VS Code CSS variables to Plannotator's CSS variable system via
postMessage between wrapper page and proxied iframe. Automatically adopts
the active VS Code color theme (dark/light/custom) without touching any
UI components or CSS files.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: gate editor annotation polling behind VS Code detection

Only poll /api/editor-annotations when running inside a VS Code webview
(window.__PLANNOTATOR_VSCODE). Browser and shared URL users now have
zero network cost from the editor annotations feature. Also fixes poll
interval from 500ms to 2000ms.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: faster polling, prevent unnecessary re-renders, unify HTTP helper

- Poll interval 2s → 500ms for snappier annotation pickup
- Shallow equality check on annotation IDs prevents React re-renders
  when poll data is unchanged
- Merge postToProxy/deleteFromProxy into single requestProxy function

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: editor annotations support in code review

Wire existing editor annotation infrastructure into the review flow
so VS Code users can annotate files outside the diff during code review.

- Add editor annotation endpoints to review server (same 3-line pattern)
- Call useEditorAnnotations hook in review App.tsx
- Display editor annotations in ReviewPanel with "Editor" divider
- Include editor annotations in feedback export and gating logic

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 12:25:02 -08:00
Michael Ramos 411e1b932d feat: support git worktrees in code review (#241)
feat: support git worktrees in code review (#196)

Adds full worktree support to the code review flow:

- Detects worktrees via `git worktree list --porcelain` and surfaces them in the diff dropdown
- Selecting a worktree enters "worktree mode" with scoped diff options (uncommitted, last commit, vs main)
- "Back to main repo" restores the original dropdown
- Handles initial commits gracefully (no HEAD~1 crash)

Closes #196
2026-03-07 10:06:55 -08:00
Michael Ramos c2037b78bf feat: --browser CLI flag & session discovery (#242)
* feat: add --browser CLI flag and session discovery (#135)

- Add `--browser <name>` global flag to override which browser opens
  (sets PLANNOTATOR_BROWSER, works with existing openBrowser() logic)
- Add `plannotator sessions` subcommand to list active server sessions
  with `--open [N]` to reopen in browser and `--clean` to prune stale entries
- Track active sessions in ~/.plannotator/sessions/<pid>.json with
  automatic stale cleanup via PID liveness checks
- Register/unregister sessions in all three server modes (plan, review, annotate)
- Export ./sessions and ./project from @plannotator/server package

Closes #135

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* test: add integration test for session discovery

Non-interactive test script that validates:
- Session file creation/cleanup lifecycle
- Session file content (all fields)
- `plannotator sessions` listing, --open, --clean
- Stale PID auto-cleanup

Also syncs bun.lock versions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: add --browser flag and session discovery to configuration page

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: add troubleshooting page

Covers lost tabs (sessions --open), data storage locations,
browser issues, and hook not firing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 09:45:33 -08:00