426 Commits

Author SHA1 Message Date
Michael Ramos 70ad54dd70 chore: bump version to 0.16.7
For provenance purposes, this commit was AI assisted.
v0.16.7
2026-04-02 15:33:48 -07:00
Michael Ramos 1800c24d80 feat(gemini): add Gemini CLI plan review integration
* feat(gemini): add Gemini CLI plan review integration

Adds a new `apps/gemini-hook/` adapter that enables Plannotator plan
review for Gemini CLI users via the BeforeTool hook system.

The adapter reads the plan file from disk (Gemini provides a path, not
inline content), delegates to the shared @plannotator/server for the
browser-based review UI, and translates the decision back into Gemini's
hook output format.

Requires an upstream fix (google-gemini/gemini-cli#21802) that makes
`decision = "allow"` user policies work for exit_plan_mode, allowing
hooks to replace the built-in TUI approval dialog.

Includes:
- apps/gemini-hook/server/index.ts — stdin/stdout adapter
- apps/gemini-hook/hooks/ — policy TOML + settings snippet
- scripts/install.sh — Gemini binary download, policy install, settings config

For provenance purposes, this commit was AI assisted.

* refactor(gemini): use single binary with auto-detection instead of separate app

Removes apps/gemini-hook/ — the plannotator binary now auto-detects
Gemini CLI from stdin (plan_path = file on disk) vs Claude Code
(plan = inline content) and branches input parsing + output formatting.

Config fixtures live in apps/gemini/ (policy TOML + settings snippet).
Install script gates on ~/.gemini existing so Claude-only users are
unaffected.

For provenance purposes, this commit was AI assisted.

* test(gemini): add manual sandbox script for Gemini CLI integration

Three modes:
- --simulate: pipes BeforeTool JSON to hook, tests approve/deny output
- (default): runs local patched Gemini build
- --nightly: installs Gemini nightly and runs it

Backs up and restores ~/.gemini config on exit.

For provenance purposes, this commit was AI assisted.

* feat(gemini): add slash commands, marketing tab, and docs for Gemini CLI

- Add /plannotator-review and /plannotator-annotate slash commands (.toml)
- Install Gemini slash commands in all three install scripts (sh, ps1, cmd)
- Add Gemini tab to marketing landing page with icon
- Add Gemini CLI to top-level README install section
- Create apps/gemini/README.md with full setup and usage docs
- Remove stale dev:gemini script and regenerate bun.lock

For provenance purposes, this commit was AI assisted.

* fix(gemini): merge hook into existing settings.json instead of printing instructions

When ~/.gemini/settings.json already exists, use node to JSON-merge
the BeforeTool hook config rather than asking the user to do it manually.
Falls back to instructions only if node is unavailable.

For provenance purposes, this commit was AI assisted.

* fix(gemini): handle plan_filename rename and fix scoping bug

Gemini CLI nightly renamed plan_path to plan_filename in exit_plan_mode.
Accept both field names for forward/backward compatibility. Reconstruct
full plan path from transcript_path + session_id + plans/ + filename.

Also hoist planFilename variable out of try block so it's accessible
in the deny output path (was causing ReferenceError).

For provenance purposes, this commit was AI assisted.

* fix(gemini): dim approve button when annotations exist for Gemini CLI

Gemini's hook runner ignores systemMessage on the allow path, so
approve-with-feedback is silently dropped — same limitation as Claude
Code. Extend the existing UI gate to also apply for gemini-cli origin.

For provenance purposes, this commit was AI assisted.

* fix(gemini): add AGENT_CONFIG entry and fix sandbox simulate mode

Register "gemini-cli" in AGENT_CONFIG so the UI shows "Gemini CLI"
with proper badge styling instead of generic "Coding Agent" fallback.

Update sandbox simulate mode to match production input format:
use plan_filename instead of plan_path, include transcript_path,
and simulate the Gemini directory structure for path reconstruction.

For provenance purposes, this commit was AI assisted.
2026-04-02 15:24:10 -07:00
roman 2f3b2351a4 fix: install agent skills to ~/.agents/skills/ directory (#476)
Closes #471
2026-04-02 11:58:10 -07:00
Michael Ramos a48fd8afb5 chore: bump version to 0.16.6
For provenance purposes, this commit was AI assisted.
v0.16.6
2026-04-02 10:57:13 -07:00
rtsummit e642e25124 feat: add Perforce (P4) pending changelist diff support (#472)
* feat: add Perforce pending changelist diff support for code review

Introduce P4 support alongside existing Git backend via a VCS dispatch
layer (vcs.ts). Detects Git vs Perforce workspace automatically and
routes diff/file-content operations to the appropriate backend.

- Add p4-default and p4-changelist:<N> DiffType variants
- Add P4 runtime (p4.ts): workspace detection with TTL cache, changelist
  context, unified diff conversion, binary file exclusion, batch p4 where
- Add VCS dispatch layer (vcs.ts): auto-detect Git/P4, unified API
- Update review server and CLI entry point to use VCS dispatch
- Filter empty changelists from dropdown, disable staging for P4

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

* refactor: introduce VcsProvider interface for extensible VCS support

Replace hardcoded Git/P4 dispatch with a provider-based architecture.
Each VCS implements VcsProvider interface and registers in a providers
array — adding a new VCS only requires implementing the interface.

- Define VcsProvider with detect, ownsDiffType, getContext, runDiff,
  getFileContents, and optional stageFile/unstageFile/resolveCwd
- Create gitProvider and p4Provider as concrete implementations
- Replace isP4DiffType/gitAddFile/gitResetFile in review.ts with
  provider-based canStageFiles/stageFile/unstageFile/resolveVcsCwd
- Remove VCS-specific branching from review server endpoints

Note: GitContext interface is not renamed to VcsContext in this commit.
The rename touches too many files across the codebase (Pi extension,
OpenCode plugin, shared types, tests) and should be handled as a
separate pull request to keep the diff reviewable.

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

---------

Co-authored-by: rtsummit <rtsummit@abutton.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 10:49:24 -07:00
Stefan Kaufmann 6dabcc1dbb Add pi signal support - so other extensions can invoke the plannotator (#468)
* add pi signal support

* remove PLAN

* fix: pass cwd through to getGitContext in openCodeReview

getGitContext() was called without the custom cwd override, so the
initial diff was correct but live diff switching, file content, git-add,
and branch labels in the review UI would resolve against process.cwd()
instead of the caller-provided cwd.

For provenance purposes, this commit was AI assisted.

---------

Co-authored-by: Michael Ramos <mdramos8@gmail.com>
2026-04-02 10:49:05 -07:00
Sylvain DNS 2c5ebb5ad1 feat(review): prefill suggested code textarea with selected code (#470)
When user clicks "Add suggested code" button in an annotation comment, the textarea is now pre-filled with the original selected code, allowing them to edit from there instead of typing from scratch. The cursor is positioned at the end of the prefilled text using requestAnimationFrame to ensure proper focus after state updates.
2026-04-02 08:33:33 -07:00
Ben Limmer ada0d5f9c5 fix(review): expand file tree folders by default on initial render (#473) (#474) 2026-04-02 08:33:10 -07:00
Sylvain DNS ee8d181cf9 fix(review): hide annotation toolbar when suggestion modal is open (#469)
Prevent stacking dialogs by hiding the AnnotationToolbar when the SuggestionModal (expanded editor) is open, avoiding the original dialog from overlaying the fullpage dialog.
2026-04-02 08:31:42 -07:00
Michael Ramos 070f75f804 chore: bump version to 0.16.5
For provenance purposes, this commit was AI assisted.
v0.16.5
2026-04-01 22:13:51 -07:00
Michael Ramos 9ae034d2ea fix(ui): right resize handle no longer covers scrollbar (#354) (#465)
Commit 3ac3d5b swapped the touch area bias so side="right" extended 8px
leftward into the content area, covering the 6px scrollbar. Changed to
`left-0 -right-3` so the touch target has zero left encroachment and
extends entirely into the sidebar panel instead.

For provenance purposes, this commit was AI assisted.
2026-04-01 21:58:58 -07:00
Michael Ramos c8b9dafae1 fix(vscode): use absolute URL for README icon (#464)
* feat(vscode): prepare VS Code extension for marketplace publish

- Remove `private: true` to enable publishing
- Add homepage, galleryBanner, update category to AI, bump version
- Fix .vscodeignore monorepo leak (was packaging 548 files from parent workspace)
- Upgrade @vscode/vsce to ^3.7.1 (fixes .cjs entry point validation)
- Rewrite README for marketplace with CloudFront-hosted screenshots and GIF
- Replace 128x128 placeholder icon with proper 256x256 icon
- Add VS Code tab to marketing site hero section with marketplace link
- Add VS Code SVG icon to marketing assets

For provenance purposes, this commit was AI assisted.

* fix: clean up HeroSection linkEl reference and unused variable

For provenance purposes, this commit was AI assisted.

* fix(vscode): use absolute URL for README icon

Marketplace resolves relative paths against repo root, not the extension
subdirectory, causing a broken image.

For provenance purposes, this commit was AI assisted.
2026-04-01 20:59:49 -07:00
Michael Ramos 34ee462133 feat(vscode): marketplace publish + marketing VS Code tab (#463)
* feat(vscode): prepare VS Code extension for marketplace publish

- Remove `private: true` to enable publishing
- Add homepage, galleryBanner, update category to AI, bump version
- Fix .vscodeignore monorepo leak (was packaging 548 files from parent workspace)
- Upgrade @vscode/vsce to ^3.7.1 (fixes .cjs entry point validation)
- Rewrite README for marketplace with CloudFront-hosted screenshots and GIF
- Replace 128x128 placeholder icon with proper 256x256 icon
- Add VS Code tab to marketing site hero section with marketplace link
- Add VS Code SVG icon to marketing assets

For provenance purposes, this commit was AI assisted.

* fix: clean up HeroSection linkEl reference and unused variable

For provenance purposes, this commit was AI assisted.
2026-04-01 20:58:09 -07:00
Michael Ramos 6735266d66 chore: bump version to 0.16.4 v0.16.4 2026-04-01 15:08:26 -07:00
Michael Ramos 68418e2a35 feat(review): add dockview center workspace (#453)
* chore(review): add dockview-react dependency

* feat(review): add dockview center workspace

* fix(review): stabilize diff search navigation

* feat(review): add progressive file search UI

* feat(review): streamline header controls

* fix(review): portal annotation toolbar

* refactor(review): streamline header and action menus

* fix(review): make file header responsive

* fix(review): align split diff drag handle

* chore(review): hide review agents sidebar

* fix(review): remount diff viewer on file switch

* fix(review): wrap inline diff comments
2026-04-01 14:58:45 -07:00
Michael Ramos dc1190f963 feat(skill): compound planning Claude Code fallback + blog post (#461)
* feat(skill): add Claude Code fallback to compound planning skill

Plannotator remains the first-class data source. When users don't have a
Plannotator archive, the skill now falls back to extracting ExitPlanMode
denial reasons from Claude Code JSONL transcripts via a bundled parser.

Adds Source Selection section, per-phase fallback notes, a progressive
disclosure reference (references/claude-code-fallback.md), and the
extraction script (scripts/extract_exit_plan_mode_outcomes.py).

For provenance purposes, this commit was AI assisted.

* fix(skill): remove duplicate detection logic and fix fallback skip

Phase 0 was duplicating the Source Selection branching and telling
fallback mode to skip Previous Report Detection. Now Phase 0 defers
to the already-chosen mode and both paths proceed to report detection.

For provenance purposes, this commit was AI assisted.

* blog: add Continuously Improve Claude Code Plans post

Introduces compound planning to users — how denial feedback compounds
into better future plans, works for both Plannotator and plain Claude
Code users. Video placeholder included for later replacement.

For provenance purposes, this commit was AI assisted.

* blog: revise compound planning post and adjust prose typography

Rework blog copy, add looping video embeds from CloudFront media
bucket, simplify process overview, add install link. Bump prose
font-size to 0.95rem and line-height to 1.6 on desktop.

For provenance purposes, this commit was AI assisted.

* blog: move intro video, copy tweaks, video spacing

For provenance purposes, this commit was AI assisted.
2026-04-01 14:16:10 -07:00
Michael Ramos f8d4969e73 feat(hook): improvement hook context injection for planning (#459)
* feat(shared): add improvement hook reader utility

Adds a runtime-agnostic module for reading improvement hook files from
~/.plannotator/hooks/. Uses a hardcoded base path with an allowlist of
known hook files and a 50KB size cap to prevent runaway context injection.

Designed for cross-harness reuse (Claude Code, OpenCode, Pi, etc.).

For provenance purposes, this commit was AI assisted.

* feat(hook): wire up improve-context PreToolUse hook for EnterPlanMode

Adds a PreToolUse hook on EnterPlanMode that injects corrective planning
instructions into Claude's context at plan mode entry. The new
`plannotator improve-context` subcommand reads the improvement hook file
and returns additionalContext, or silently passes through if no file exists.

For provenance purposes, this commit was AI assisted.

* fix(skill): update compound skill improvement hook path

Moves the improvement hook file path from ~/.plannotator/compound/ to
~/.plannotator/hooks/compound/ to namespace hook-injectable files
separately from other plannotator data.

For provenance purposes, this commit was AI assisted.

* fix(shared): add legacy path fallback for improvement hook reader

Users who ran the compound skill before the path migration have their
improvement hook file at ~/.plannotator/compound/ instead of the new
~/.plannotator/hooks/compound/ path. Add a fallback that checks the
legacy path only when the new path is absent — if the new path exists
but is invalid (empty, oversized), no fallback occurs to prevent
resurrecting stale instructions.

Includes tests for new-path-wins, legacy-fallback, and
invalid-new-blocks-legacy scenarios.

For provenance purposes, this commit was AI assisted.
2026-04-01 13:16:55 -07:00
Michael Ramos 588b6a4de7 feat(review): support GitHub Enterprise and fix self-hosted GitLab MR diffs (#460)
* feat(review): support GitHub Enterprise and fix self-hosted GitLab MR diffs

Add `host` field to GitHub PR types and update URL parsing to accept any
host with `/pull/` pattern, enabling GitHub Enterprise Server URLs like
`ghe.company.com/owner/repo/pull/123`. All 8 `gh` CLI functions now pass
`--hostname` (for `gh api`/`gh auth`) and `HOST/OWNER/REPO` (for `gh pr`)
when targeting non-github.com hosts.

Replace broken `glab mr diff --hostname` invocation (glab mr subcommands
don't support --hostname) with `glab api .../diffs` which does. Diffs are
now reconstructed from structured API response instead of heuristic parsing
of bare diff output.

Closes #348
Closes #457

For provenance purposes, this commit was AI assisted.

* fix(review): remove destructive regex from GitLab paginated JSON parser

glab api --paginate already returns a single merged JSON array, so the
regex that replaced ][  with , was unnecessary and could corrupt diff
content containing array indexing patterns like arr[i][j].

For provenance purposes, this commit was AI assisted.
2026-04-01 11:40:20 -07:00
Michael Ramos 2829a3f64d feat(skill): compound planning — incremental reports, agent routing, improvement hook (#455)
* feat(skill): incremental reports, Haiku/Sonnet agents, and improvement hook

Enhance the compound planning skill with three capabilities:
- Detect previous reports and offer incremental analysis (only new files since last report), with versioned output filenames (v2, v3, etc.)
- Use Haiku agents for extraction (faster, cheaper) and Sonnet for reduction, with two-stage reduce for large datasets
- Add Phase 6 improvement hook that writes corrective prompts to ~/.plannotator/compound/ for automatic injection into future planning sessions

For provenance purposes, this commit was AI assisted.

* refactor(skill): drop redundant annotation files, read only denied plans

Denied files already contain the full plan + reviewer feedback after a ---
separator. Annotation files are exact subsets of this content — reading both
double-counts feedback. Simplifies extraction to a single prompt type.

For provenance purposes, this commit was AI assisted.

* fix(skill): raise two-stage reduce threshold from 7 to 21 extraction files

Single-stage reduce is sufficient for most datasets. The previous threshold
of 7 caused unnecessary partial reduce + final synthesis overhead (~13 min
vs ~5-8 min single-stage) for typical archive sizes.

For provenance purposes, this commit was AI assisted.
2026-03-31 23:20:52 -07:00
Michael Ramos 46fa92712c feat: add Clean Contrast, Code Fork, and Midnight themes (#454)
Three new themes derived from Cursor's color palettes. Code Fork supports
both dark and light modes; Clean Contrast and Midnight are dark-only.

For provenance purposes, this commit was AI assisted.
2026-03-31 22:27:17 -07:00
Michael Ramos 41f78295ba Reset review scroll on file switch (#452) 2026-03-31 20:50:18 -07:00
Stefan Kaufmann fc4e634789 feat(pi): support phase config files (#446)
* allow Plannotator phase configs in pi-extension

* fix tool name
2026-03-31 15:22:29 -07:00
Ben Limmer cce877d3c4 fix(review): resolve repo root for untracked file discovery (#450)
git ls-files scopes to the CWD subtree and returns CWD-relative paths,
unlike git diff HEAD which covers the full repo with root-relative paths.
When the hook process inherits a subdirectory CWD, untracked files outside
that subtree are silently dropped and paths for files inside it are wrong.

Resolve the repo root via rev-parse --show-toplevel and use it as the CWD
for both git ls-files and git diff --no-index in getUntrackedFileDiffs.

Fixes #449
2026-03-31 11:08:44 -07:00
Michael Ramos d8a67beb1c feat: agentic review — background job runner with SSE streaming (#443)
* feat(server): add agent job manager with process lifecycle and SSE streaming

Introduces the backend for agentic review — a server-agnostic job runner
that spawns agent processes, monitors their lifecycle via proc.exited, and
broadcasts status updates over a dedicated SSE stream.

New files:
- packages/shared/agent-jobs.ts: runtime-agnostic types, SSE helpers, state machine
- packages/server/agent-jobs.ts: Bun HTTP adapter with spawn/kill/SSE/REST routes

Wired into the review server with late-bound serverUrl, killAll on stop
and process exit for defense-in-depth cleanup. Capability detection via
Bun.which() for Claude Code, Codex CLI, and shell.

For provenance purposes, this commit was AI assisted.

* feat(ui): add Review Agents tab with job management and live status

Adds the client-side UI for agentic review:
- useAgentJobs hook: SSE primary with polling fallback, capabilities fetch
- AgentsTab: shared component with provider dropdown, job cards, kill controls
- ReviewAgentsIcon: magnifying glass with cog icon
- ReviewPanel: new "Review Agents" tab conditional on detected capabilities
- App.tsx: initializes hook and passes props to ReviewPanel

Jobs show live elapsed time, status badges, annotation counts per source,
and expandable error details. Stub command (sleep 10-30s) for initial testing.

For provenance purposes, this commit was AI assisted.

* fix(server): narrow proc.stderr type to satisfy TS

Bun types proc.stderr as ReadableStream | number. Add typeof guard
to narrow before passing to Response constructor.

For provenance purposes, this commit was AI assisted.

* fix(server): prevent stdout deadlock, stderr pipe stall, and worktree cwd mismatch

- Change stdout from "pipe" to "ignore" — agents post findings via the
  annotations API, not stdout. Unconsumed pipe buffer caused deadlock.
- Drain stderr continuously instead of reading after exit — prevents
  pipe-full stall on chatty agents.
- Make agent getCwd worktree-aware using the same currentDiffType check
  the AI endpoints use, so agents spawn in the correct checkout.
- Exclude 'agents' tab from PR context fetch guard in ReviewPanel.

For provenance purposes, this commit was AI assisted.

* feat(pi): mirror agent-job endpoints in Pi review server

Add apps/pi-extension/server/agent-jobs.ts — a Node.js port of the Bun
agent-jobs handler using child_process.spawn, res.write() SSE, and
execFileSync for capability detection.

Wire into serverReview.ts: route delegation, killAll in stop(),
process.on("exit") guard, worktree-aware getCwd, and serverUrl
late-binding. Add agent-jobs to vendor.sh for shared type vendoring.

For provenance purposes, this commit was AI assisted.

* fix(agents): harden agent jobs — listener leak, provider allowlist, Windows support, docs

- Use process.once instead of process.on to prevent exit listener accumulation
- Validate provider against known capabilities before spawning (rejects unknown providers)
- Use platform-aware which/where for CLI detection on Windows
- Broadcast jobs:cleared event from kill-all endpoint (was dead client code)
- Document all /api/agents/* endpoints in CLAUDE.md Review Server table

For provenance purposes, this commit was AI assisted.

* fix(agents): SSE ref reset, jobs:cleared divergence, exit listener cleanup

- Reset receivedSnapshotRef/fallbackRef on re-mount so polling fallback
  activates correctly on subsequent tab switches
- Remove jobs:cleared broadcast from kill-all — killAll() already fires
  individual job:completed events, so the UI shows status transitions
  instead of going blank
- Store exit handler ref so stop() can removeListener, preventing
  accumulation in long-lived hosts (OpenCode, Pi)

For provenance purposes, this commit was AI assisted.
2026-03-31 10:06:18 -07:00
foxytanuki ab9cae3488 cli: clarify no-arg usage and add top-level help (#448) 2026-03-31 09:36:10 -07:00
Michael Ramos fad822e6ca chore: bump version to 0.16.2 v0.16.2 2026-03-30 21:49:08 -07:00
Michael Ramos ede10fef9c feat(ui): cross-file annotation visibility and adaptive navigation (#444)
- Shared CountBadge component replacing heavy TOC accent circles
- Per-file annotation count badges in FileBrowser and VaultBrowser
- Folder aggregate counts from descendant files
- Summary header showing total annotations across files
- Dot indicators on Files/Vault sidebar tabs when annotations exist
- Adaptive back button text (file list / file / message / plan)
- Cross-file annotation indicator in right panel with flash highlight
- Fix directory prefix matching bug (startsWith without trailing slash)
- Move flash animation CSS to shared theme stylesheet

For provenance purposes, this commit was AI assisted.
2026-03-30 21:39:00 -07:00
Michael Ramos 7435be0639 feat(ui): draggable comment popover and annotation toolbar (#442)
Makes the CommentPopover and AnnotationToolbar draggable by their headers via a shared `useDraggable` hook. Users can reposition popovers that land awkwardly near viewport edges.

- New `useDraggable` hook reads rendered position via getBoundingClientRect on drag start
- 3px movement threshold prevents interfering with button clicks
- CommentPopover: suppresses scroll/resize tracking after drag, resets on anchor change
- AnnotationToolbar: both comment and Ask AI modes are draggable
- Clamps position to keep at least 50px visible on screen

For provenance purposes, this commit was AI assisted.
2026-03-30 19:02:04 -07:00
Michael Ramos 6b84ce4107 feat(review): custom diff font family and size overrides (#441)
* feat(review): custom font family and size overrides for code review diffs

Add Code Font and Code Font Size settings to the review Display tab,
letting users override the theme's monospace font in the diff viewer.

Supports 9 fonts (Fira Code, Hack, IBM Plex Mono, Inconsolata,
JetBrains Mono, Red Hat Mono, Roboto Mono, Source Code Pro, Atkinson
Hyperlegible Mono) loaded on demand from Google Fonts / jsDelivr CDN.
Font size uses a continuous slider (8–24px) with a Reset button.

Settings persist via cookies and sync to ~/.plannotator/config.json
under diffOptions.fontFamily / diffOptions.fontSize, matching the
existing config pattern.

For provenance purposes, this commit was AI assisted.

* fix(review): line-height scaling, inline annotation font coverage, and comment card cleanup

- Add line-height: 1.5 alongside font-size in Pierre shadow DOM so large sizes don't clip
- Include .review-comment-body selectors in font override CSS so inline annotation code spans get the custom font
- Simplify comment card: remove drop shadow, left border accent, translateX hover; use tight border with subtle hover

For provenance purposes, this commit was AI assisted.
2026-03-30 13:45:37 -07:00
Michael Ramos b0980ef928 fix(opencode): remove verbose logs that flood the TUI (#440)
Remove writeRemoteShareLink stderr output from the OpenCode plugin —
the base64 share URL was flooding the TUI on remote sessions. Also
strip leftover console.log debug statements from the PR viewed files
feature in the review server.

Closes #435

For provenance purposes, this commit was AI assisted.
2026-03-30 10:51:27 -07:00
Michael Ramos a633e70597 chore: bump version to 0.16.1 v0.16.1 2026-03-30 09:13:52 -07:00
foxytanuki 16756e082b fix(server): keep external annotation SSE streams alive (#439) 2026-03-30 08:49:34 -07:00
Michael Ramos a88da925de chore: bump version to 0.16.0 v0.16.0 2026-03-29 22:13:09 -07:00
Michael Ramos e0dd5783b2 fix(ui): type cleanse — fix stale types, missing initializer fields, React 19 compat
- CommentPopover: add width to position state type (was returned but not declared)
- Settings: add missing ObsidianSettings fields (filenameSeparator, autoSave, vaultBrowserEnabled)
- Settings: add missing planWidth to UIPreferences initializer
- Viewer: use React.ElementType for dynamic heading tag
- useLinkedDoc: use SidebarTab instead of string for sidebar.open
- useActiveSection: accept RefObject<HTMLElement | null> (React 19)
- useInputMethodSwitch: pass explicit undefined to useRef
- package.json: add exports for config, ImageAnnotator, sidebar/*, plan-diff/*
- types.d.ts: add __APP_VERSION__ global declaration

For provenance purposes, this commit was AI assisted.
2026-03-29 21:43:00 -07:00
Aviad Shiber 14f8bdba62 feat: bot callback URL params with componentized toolbar buttons (#416)
Adds ?cb=<encoded_url>&ct=<token> URL params for bot-initiated plan review callbacks.
When a bot posts a Plannotator share link with these params, Approve/Feedback buttons
appear and POST the user's decision (with annotated plan URL) back to the bot.

Changes:
- callback.ts: parse callback config from URL search/hash params, execute POST
- ToolbarButtons.tsx: extract shared FeedbackButton/ApproveButton components (6 instances → 2 components)
- sharing.ts: strip ?cb=&ct= from hash before decompressing share payload
- App.tsx: callback buttons gated on isSharedSession + shareUrl readiness
- 19 tests covering config parsing, URL validation, presigned URL preservation, and POST execution

Co-authored-by: aviadshiber <aviadshiber@users.noreply.github.com>

For provenance purposes, this commit was AI assisted.
2026-03-29 21:08:41 -07:00
Michael Ramos df76f9ea63 copy: change "any agent" to "your agents" in hero tagline
For provenance purposes, this commit was AI assisted.
2026-03-29 20:59:52 -07:00
Michael Ramos 1f7ff288b5 feat(marketing): add GitHub Copilot to harness selector on landing page
For provenance purposes, this commit was AI assisted.
2026-03-29 20:54:32 -07:00
Michael Ramos 75a6d8f2a5 chore: replace CLAUDE.md with symlink to AGENTS.md
Single source of truth — edit AGENTS.md, both Claude Code and other
agents see the same instructions.

For provenance purposes, this commit was AI assisted.
2026-03-29 20:39:51 -07:00
Michael Ramos 7c82a3e01b chore: untrack .claude/skills/release — source of truth is .agents/skills/
Symlinked from ~/.claude/skills/ to the repo's .agents/skills/ directory
so changes are reflected instantly without copying.

For provenance purposes, this commit was AI assisted.
2026-03-29 20:35:42 -07:00
Michael Ramos 9937bf8b86 fix(skill): trim compound skill description under 250-char limit (#430)
Use `disable-model-invocation: true` frontmatter instead of contradictory
prose that both listed trigger phrases and said "do not trigger automatically".

Closes #412

For provenance purposes, this commit was AI assisted.
2026-03-29 20:30:54 -07:00
Michael Ramos 4627f75426 feat: external annotations API with real-time SSE (#400)
Adds a general-purpose External Annotations API that allows external programs (linters, AI tools, security scanners) to push annotations into a live Plannotator session via HTTP, with real-time delivery over SSE.

## What's included

- **Shared core** (`packages/shared/external-annotation.ts`): types, in-memory store, input validation, SSE serialization
- **Server handlers**: Bun + Pi implementations with full CRUD (GET/POST/PATCH/DELETE) + SSE streaming
- **Client hook** (`useExternalAnnotations`): EventSource with polling fallback, optimistic updates
- **Editor integration**: two-array state model (local + external), content-aware dedup, ID-based routing
- **Persistence**: source field preserved through share URLs and crash-recovery drafts
- **Docs**: new Integrations category with API overview page, updated API reference

## API surface

All three servers (plan, review, annotate) expose:
- `GET /api/external-annotations/stream` - SSE stream
- `GET /api/external-annotations` - JSON snapshot (polling fallback)
- `POST /api/external-annotations` - Add annotations (single or batch)
- `PATCH /api/external-annotations?id=` - Update fields
- `DELETE /api/external-annotations` - Remove by id, source, or clear all

For provenance purposes, this commit was AI assisted.
2026-03-29 17:18:31 -07:00
Kiwi 9b69d17580 test: cover PR/MR platform helpers (#426) 2026-03-29 15:41:02 -07:00
Michael Ramos 2ae4f2a292 fix(parser): indented fences, trailing text, table detection, and escaped pipes (#429)
Three fixes to parseMarkdownToBlocks and one to table cell rendering:

1. Indented closing fences — allow leading whitespace so `  ``` ` inside
   list items closes the code block instead of swallowing to EOF.
2. Trailing text after closing fence — drop end-of-line anchor so
   ` ``` some text` still closes the block.
3. False table detection — require lines start with `|` instead of
   matching any line with 2+ pipe characters.
4. Escaped pipes in table cells — split on unescaped `|` only, so
   `\|` renders as a literal pipe instead of creating extra columns.

Closes #427

For provenance purposes, this commit was AI assisted.
2026-03-29 13:25:17 -07:00
Michael Ramos 9b016da4ae feat(review): diff display options with ConfigStore integration (#428)
* feat(config): add DiffOptions to PlannotatorConfig with deep-merge support

Extends the server-side config system to support diff display options
namespaced under `diffOptions` in ~/.plannotator/config.json. The
saveConfig deep-merge ensures partial writes (e.g. changing only
overflow) don't clobber sibling keys.

For provenance purposes, this commit was AI assisted.

* feat(server): accept diffOptions in POST /api/config handlers

All six server handlers (plan, review, annotate x Bun + Pi) now
whitelist diffOptions alongside displayName, forwarding it to
saveConfig for deep-merged disk persistence.

For provenance purposes, this commit was AI assisted.

* feat(config): register diff display settings with deep-merge write batching

Adds 6 diff option settings to the ConfigStore registry (diffStyle,
diffOverflow, diffIndicators, diffLineDiffType, diffShowLineNumbers,
diffShowBackground), all synced to disk under the diffOptions namespace.

Fixes write batching for nested server keys — replaces Object.assign
with deepMerge so rapid changes to multiple diff options within the
300ms debounce window don't clobber each other. Includes legacy cookie
migration for the old review-diff-style key.

For provenance purposes, this commit was AI assisted.

* feat(review): wire diff display options through to @pierre/diffs

Migrates diffStyle from raw cookie storage to ConfigStore. Reads all 6
diff options via useConfigValue and forwards them to FileDiff: overflow,
diffIndicators, lineDiffType, disableLineNumbers, disableBackground.

Adds a Scroll/Wrap toolbar toggle alongside the existing Split/Unified
toggle. Disables the custom resizable split dragger in wrap mode since
Pierre manages its own grid layout. Fixes the unsafeCSS grid override
to only target scroll mode, preventing per-character wrapping in split
view.

For provenance purposes, this commit was AI assisted.

* feat(review): add Display tab to review-mode Settings dialog

Adds a Display tab when Settings is in review mode, exposing all 6 diff
options: Diff Style, Line Overflow, Change Indicators, Inline Diff
Granularity, Show Line Numbers, and Show Diff Background. Changes take
effect immediately and persist via ConfigStore (cookie + disk).

Extracts reusable SegmentedControl and ToggleSwitch helpers for the
review display controls.

For provenance purposes, this commit was AI assisted.

* chore: update bun.lock

For provenance purposes, this commit was AI assisted.

* fix(review): reapply search highlights after display option changes

Add new diff display props to the search highlight and scroll-to-match
effect dependency arrays so highlights are restored after Pierre re-renders.

For provenance purposes, this commit was AI assisted.
2026-03-29 13:20:22 -07:00
Stacey Haffner a0a6edd323 feat: print support with export menu integration and keyboard shortcut (#420)
* feat: add print stylesheet for white paper output

- Create packages/ui/styles/print.css with @media print rules
- White background and black text for paper output
- Monochrome code blocks for readability on white paper
- Hide UI chrome (annotations, toolbars, sidebars) during print
- Proper typography for headers, code, tables, lists, blockquotes
- Page break rules to avoid orphaned content
- Support for diagrams (Mermaid, Graphviz) in print
- Import print.css in packages/ui/theme.css

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat: add Print button to toolbar

- Add Print button next to Export button in plan editor toolbar
- Triggers window.print() for native browser print dialog
- Shows printer icon + 'Print' label (icon-only on mobile)
- Tooltip: 'Print plan (Ctrl+P)'
- Uses muted button styling consistent with other toolbar buttons

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: rewrite print.css selectors to match real DOM structure

Code review found the original selectors used class names that don't
exist in the actual component tree. Fixed:

- Target header.sticky / header.h-12 (not generic 'header')
- Target aside elements directly (SidebarContainer + AnnotationPanel)
- Target .annotation-toolbar (portalled floating toolbar)
- Target .fixed overlays (modals, export dialog)
- Target article element (Viewer renders <article>, not <main>)
- Target .bg-grid for background pattern removal
- Flatten .h-screen height for print flow
- Simplified hljs monochrome rule to [class*='hljs']

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: print stylesheet — hide all toolbar UI, fix code block colors

Issues fixed from user testing:
- Header toolbar (Export/Print/Settings) now hidden via 'header' selector
- AnnotationToolstrip (Select/Markup) hidden via '.flex-wrap'
- Action buttons (Images/Comment/Copy) hidden via '.float-right'
- Code block copy buttons hidden via '.group > button.absolute'
- Fenced code blocks: override github-dark.css hljs theme to monochrome
  with light background (#f5f5f5) and dark text (#1a1a1a)
- Inline code: solid light gray background with visible border
- All text forced to solid black (override theme muted/foreground vars)
- hljs span elements explicitly overridden for print

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: aggressive code block print overrides for dark theme

- Override CSS custom properties (--muted, --foreground, etc.) in print
- Use both background AND background-color on pre/code elements
- Target pre[class], code[class], code.hljs with higher specificity
- Explicitly list every hljs- class for monochrome override
- Ensures github-dark.css hljs theme is fully overridden in print

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: use JS beforeprint/afterprint class for code block print styling

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: add visibilitychange fallback for Firefox print cleanup

Firefox may not fire afterprint when print preview is closed without
printing, leaving the .plannotator-print class stuck on <html>. This
adds a visibilitychange listener that removes the class when the user
returns to the page, plus cleanup on unmount.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* refactor: extract usePrintMode hook, replace brittle CSS selectors with data attributes

- Extract print event listeners from App.tsx into packages/ui/hooks/usePrintMode.ts
- Add data-print-region attributes to layout elements (root, content, document, article)
- Add data-print-hide attribute to Viewer action buttons
- Replace .h-screen, .flex-1.flex.overflow-hidden, .bg-card, .bg-grid, .float-right,
  .flex-wrap selectors with stable data-attribute and semantic element selectors
- Follows existing hook patterns (useIsMobile, useDismissOnOutsideAndEscape, etc.)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: hide annotation toolstrip and repo badges in print output

Added data-print-hide to the AnnotationToolstrip wrapper and the
repo/branch badges div inside the article.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: collapse top whitespace gap in print output

Zero out article padding, add margin/padding reset to data-print-hide
elements, and collapse first h1 top margin for a tight print layout.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat: move print button into export menu and add Ctrl/Cmd+P shortcut

* chore: remove accidentally introduced annotate command files

Remove apps/hook/commands/annotate.md and apps/opencode-plugin/commands/annotate.md
that were unintentionally added in the print-styling PR.

For provenance purposes, this commit was AI assisted.

---------

Co-authored-by: Yecats <Yecats@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Michael Ramos <mdramos8@gmail.com>
2026-03-29 11:04:32 -07:00
Stacey Haffner 08fcaaf086 feat: Interactive checkboxes with annotation tracking (#423)
* feat: interactive checkboxes — click to toggle with annotation

Checkboxes in rendered markdown task lists are now clickable.
Toggling is visual-only (does not modify source markdown) and
automatically creates a comment annotation noting the change.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: uncheck checkbox removes override and deletes annotation (undo)

When toggling back to the original state, the checkbox override is
deleted and the associated annotation is removed — acting as an undo.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: address all code review issues for checkbox feature

1. Fix annotation prefix collision: match on blockId field instead of
   string prefix to avoid block-1 matching block-10, block-11 etc.
2. Fix rapid toggle orphans: delete ALL existing checkbox annotations
   for the block before creating a new one, preventing duplicates.
3. Fix stale overrides: useEffect cleans up checkboxOverrides entries
   when their block IDs no longer exist in the current blocks array.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: use actionable annotation text for checkbox toggles

Annotations now read 'Mark as completed: {item}' or 'Mark as not
completed: {item}' so the AI knows to action on them.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: include section heading in checkbox annotation for disambiguation

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: revert checkbox override when annotation is deleted from panel

When a user deletes a checkbox annotation via the annotation panel,
the checkboxOverrides entry is now cleared so the checkbox reverts
to its original visual state. Previously only toggling the checkbox
itself would revert the override.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* refactor: extract removeAnnotation to avoid redundant override cleanup in checkbox toggle

* refactor: extract useCheckboxOverrides hook from App.tsx

---------

Co-authored-by: Yecats <Yecats@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-29 09:43:03 -07:00
Stacey Haffner 2d90d381c9 fix: Detect calling agent via env vars and centralize agent config (#418)
* fix: detect calling agent via env vars for correct badge display

Add prioritized agent detection chain: CODEX_THREAD_ID (codex) >
COPILOT_CLI (copilot-cli) > default (claude-code). All subcommands
use the shared detectedOrigin constant. Display name updated from
'Copilot CLI' to 'GitHub Copilot'. TypeScript origin union type
updated to include 'copilot-cli'.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* refactor: centralize agent config into @plannotator/shared/agents

- Create packages/shared/agents.ts as single source of truth for Origin type,
  agent display names (AGENT_CONFIG), getAgentName(), and getAgentBadge()
- Replace all inline origin type unions across 8 files with Origin import
- Type detectedOrigin and ServerOptions.origin as Origin for compile-time safety
- Add @plannotator/shared dependency to @plannotator/editor package.json
- Adding a new agent is now a one-file change to AGENT_CONFIG

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: restore gitContext in startReviewServer call

Accidentally removed alongside the origin refactor. Without it, local
code reviews lose branch detection, diff-type switching, and CWD resolution.

For provenance purposes, this commit was AI assisted.

---------

Co-authored-by: Yecats <Yecats@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Michael Ramos <mdramos8@gmail.com>
2026-03-28 16:37:56 -07:00
Michael Ramos 8280cc0aca perf(opencode): lazy-load HTML to fix plugin startup time (#411)
* perf(opencode): lazy-load HTML to cut plugin startup from ~160ms to ~35ms

The two SPA HTML files (~20 MB combined) were inlined as string literals
via Bun's `with { type: "text" }` imports, forcing Bun to parse a 21 MB
bundle at module load time. Replace with lazy readFileSync getters and
background preload during plugin init, reducing the bundle to 0.81 MB.

Closes #410

For provenance purposes, this commit was AI assisted.

* test: add OpenCode plugin startup benchmark script

Measures real-world startup time across three scenarios:
no plugin, published npm, and local optimized. Uses
`opencode run` for non-interactive measurement and parses
log timing.

For provenance purposes, this commit was AI assisted.

* fix(bench): resolve project dir to repo root and auto-build before scenario 3

PROJECT_DIR pointed to tests/ instead of the repo root, so the local
plugin path was invalid and scenario 3 silently measured a no-plugin run.
Also auto-run build:opencode when dist/index.js is missing.

For provenance purposes, this commit was AI assisted.
2026-03-27 20:09:09 -07:00
Michael Ramos 111934f658 chore: update release skill with Copilot/OpenCode version files and Pi parity gate
For provenance purposes, this commit was AI assisted.
2026-03-27 13:56:37 -07:00
Stacey Haffner 15af1c40eb Add GitHub Copilot CLI integration (#409)
* feat: add GitHub Copilot CLI integration

Add full Copilot CLI support via a new plugin (apps/copilot/) with:
- preToolUse hook intercepting exit_plan_mode for plan review
- copilot-plan subcommand with correct permissionDecision output format
- copilot-last subcommand parsing events.jsonl for last message annotation
- Copilot CLI session parser (copilot-session.ts)
- Plugin manifest, hooks.json, and slash commands
- UI origin branding (blue badge for Copilot CLI)
- Marketplace entry for plugin discovery
- README install section

Key design decisions:
- Intercepts exit_plan_mode (not create) to avoid double-review
- Uses sessionId (with fallback) to locate plan.md from session state
- Follows Codex integration pattern: same CLI binary, new plugin dir

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: handle actual Copilot CLI preToolUse input format (toolCalls array)

The Copilot CLI hook input uses { toolCalls: [{ name, args }] } format
instead of the documented { toolName, toolArgs } format. The filter was
checking event.toolName (always undefined), causing exit_plan_mode to
pass through unintercepted. Now extracts tool name from either format.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Revert "fix: handle actual Copilot CLI preToolUse input format (toolCalls array)"

This reverts commit b214bc02c58fc5d8f305b128457099afb2ea6ecc.

* fix: use absolute path in hooks.json for reliable binary discovery

The hook subprocess inherits the PATH from when Copilot CLI was started,
which may not include the plannotator binary directory. Using the full
absolute path via env vars ensures the hook always finds the binary.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Finishing the feature

* fix: remove Copilot CLI plugin from Claude Code marketplace.json

.claude-plugin/marketplace.json is for Claude Code's plugin marketplace.
The Copilot CLI plugin has its own install path and doesn't belong here.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: align Copilot CLI plugin with official spec

- Add .github/plugin/marketplace.json for Copilot CLI plugin discovery
- Change allowed-tools from Bash() to shell() syntax in commands
- Respect COPILOT_HOME env var in session path discovery
- Update plugin.json version to 0.14.5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Yecats <Yecats@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: stahaff <222254525+stahaff@users.noreply.github.com>
2026-03-27 10:20:49 -07:00