feat(readme): redesign README (#891)
* feat(readme): redesign README — hero banner, agent icons, simplified install - New centered hero: banner, tagline, theme-aware agent icon row (picture/prefers-color-scheme), demo links - Intro paragraph naming all nine supported agents - Feature cards with screenshots; dedicated Annotate HTML Artifacts, Code review, and Sharing sections - Install collapsed to one shared installer + per-agent table covering all nine agents, linking each app README - New Try it section for manual invocation after install - Fixed Codex plan-mode claim (supported via Stop hook), completed PLANNOTATOR_ORIGIN values, fixed demo links and typos - Added Integrations, Remote/SSH, Security, and Configuration sections * feat(readme): consolidate command examples into a Commands section - Annotate HTML Artifacts is now screenshot-only - Drop the duplicate code review screenshot (code-review-thumbnail.png removed) - New Commands section: Annotate, Code review, and CLI groups * fix(readme): point doc-review demo at Pi video, drop wrong code review demo link * style(readme): plain-language pass - No em dashes anywhere; split into sentences or swapped for colons/commas - Rewrote the intro: integration with the agent session is now explicit (plugs into hooks/commands, feedback lands back in the live session) - Varied repeated phrasing between the two feature cards - Integration labels use colons instead of dashes * style(readme): simplify feedback phrasing in hero and feature card * feat(readme): add Plan mode note and sessions command to Commands section * feat(readme): sharing beta link and Workspaces signup CTA badge * style(readme): drop divider between feature table and HTML artifacts section * style(readme): bump banner width 512 -> 640 * style(readme): fix agent icon sizing - Crop Pi icon viewBox to glyph bounds (was 40% padding) - Render Amp at 32px to offset its thin mark * style(readme): bump Amp icon to 38px for visual parity * fix(readme): strip em-based size attrs from Amp icon so it scales The svg root had width/height of 1em plus an inline style, the only icon in the set with relative sizing. SVG-as-image resolves em at a fixed 16px and the drawing stayed pinned there regardless of the img height. Removed the attrs, back to the uniform 28px row height. * style(readme): width=100% on feature table images * style(readme): cmux-style 40/60 feature table with middle-aligned text * style(readme): split feature rows into separate tables so zigzag keeps 40/60 * style(readme): single feature table, text left 40 / image right 60, no zigzag * style(readme): tighten intro and feature card copy * style(readme): remove stray space before period * style(readme): another round of copy edits * chore: remove internal docs notes, move readme-assets to .github/assets - Deleted docs/ (three internal handoff notes, nothing referenced them) - README media now lives in .github/assets/ instead of a root-level folder - All 18 asset links in README updated * style(readme): split intro into two paragraphs * feat(readme): live collaboration teaser in Sharing, tighten encryption copy * style(readme): retitle Sharing & Multiplayer, rework CTA badge to banner palette with balloon * feat(readme): updated annotate and review screenshots * feat(readme): updated HTML artifact screenshot * feat(readme): swap HTML artifact screenshot for v2 * feat(readme): restore share workflow sentence and Codex command note * docs(agents): document bun link workflow for local plannotator command * style(readme): trim Windows note from Codex command tip * feat(readme): one-line AI features note under feature table
|
After Width: | Height: | Size: 128 KiB |
|
After Width: | Height: | Size: 85 KiB |
|
After Width: | Height: | Size: 84 KiB |
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Amp</title><path d="M15.087 23.18L12.03 24l-2.097-7.823-5.738 5.738-2.251-2.251 5.718-5.719-7.769-2.082.82-3.057 11.294 3.08 3.08 11.295z" fill="#F34E3F"></path><path d="M19.505 18.762l-3.057.82-2.564-9.573-9.572-2.564.819-3.057 11.295 3.079 3.08 11.295z" fill="#F34E3F"></path><path d="M23.893 14.374l-3.057.82-2.565-9.572L8.7 3.057 9.52 0l11.295 3.08 3.079 11.294z" fill="#F34E3F"></path></svg>
|
||||
|
After Width: | Height: | Size: 463 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 32 32"><path d="m6.283 21.28 6.293-3.531.106-.306-.106-.171h-.307l-1.051-.065-3.596-.097-3.118-.13-3.021-.162-.761-.161-.712-.94.073-.469.639-.429.916.08 2.023.138 3.037.209 2.203.13 3.263.339h.518l.073-.21-.177-.129-.138-.13-3.142-2.129-3.401-2.25-1.782-1.296-.963-.656-.486-.616-.21-1.343.875-.963 1.175.08.3.08 1.19.915 2.542 1.967 3.319 2.445.486.404.194-.138.024-.097-.218-.365-1.806-3.263-1.926-3.32-.857-1.375-.227-.825c-.08-.339-.138-.624-.138-.972L8.384.177 8.935 0l1.328.177.56.486.824 1.887 1.337 2.972 2.073 4.04.607 1.199.324 1.11.121.339h.21v-.194l.17-2.276.315-2.795.307-3.596.106-1.012.501-1.214.995-.657.778.372.639.916-.088.591-.381 2.471-.745 3.87-.485 2.591h.282l.324-.324 1.311-1.74 2.203-2.754.972-1.093 1.133-1.207.728-.574h1.376l1.013 1.505-.454 1.555-1.416 1.797-1.175 1.522-1.685 2.268-1.051 1.814.097.144.25-.023 3.805-.81 2.056-.372 2.454-.421 1.11.518.12.527-.436 1.078-2.624.648-3.077.615-4.582 1.084-.057.041.065.08 2.065.195.883.047h2.162l4.025.3 1.052.696.63.851-.106.647-1.619.825-2.186-.518-5.1-1.214-1.75-.436h-.242v.145l1.458 1.425 2.671 2.412 3.346 3.11.17.769-.43.607-.453-.065-2.939-2.211-1.134-.996-2.568-2.162h-.17v.227l.591.866 3.125 4.697.162 1.441-.226.468-.81.283-.89-.162-1.829-2.568-1.888-2.891-1.522-2.592-.186.106-.898 9.677-.421.495-.972.371-.81-.615-.43-.996.43-1.967.518-2.568.422-2.041.38-2.535.226-.842-.015-.056-.185.023-1.912 2.624-2.906 3.928-2.3 2.462-.551.218-.954-.494.088-.883.533-.787 3.184-4.049 1.919-2.509 1.24-1.449-.009-.21h-.073l-8.455 5.49-1.505.194-.648-.607.08-.995.307-.324 2.542-1.749-.009.008z" style="fill:#d97757;"/></svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 16 KiB |
@@ -0,0 +1 @@
|
||||
<svg fill="white" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>GithubCopilot</title><path d="M19.245 5.364c1.322 1.36 1.877 3.216 2.11 5.817.622 0 1.2.135 1.592.654l.73.964c.21.278.323.61.323.955v2.62c0 .339-.173.669-.453.868C20.239 19.602 16.157 21.5 12 21.5c-4.6 0-9.205-2.583-11.547-4.258-.28-.2-.452-.53-.453-.868v-2.62c0-.345.113-.679.321-.956l.73-.963c.392-.517.974-.654 1.593-.654l.029-.297c.25-2.446.81-4.213 2.082-5.52 2.461-2.54 5.71-2.851 7.146-2.864h.198c1.436.013 4.685.323 7.146 2.864zm-7.244 4.328c-.284 0-.613.016-.962.05-.123.447-.305.85-.57 1.108-1.05 1.023-2.316 1.18-2.994 1.18-.638 0-1.306-.13-1.851-.464-.516.165-1.012.403-1.044.996a65.882 65.882 0 00-.063 2.884l-.002.48c-.002.563-.005 1.126-.013 1.69.002.326.204.63.51.765 2.482 1.102 4.83 1.657 6.99 1.657 2.156 0 4.504-.555 6.985-1.657a.854.854 0 00.51-.766c.03-1.682.006-3.372-.076-5.053-.031-.596-.528-.83-1.046-.996-.546.333-1.212.464-1.85.464-.677 0-1.942-.157-2.993-1.18-.266-.258-.447-.661-.57-1.108-.32-.032-.64-.049-.96-.05zm-2.525 4.013c.539 0 .976.426.976.95v1.753c0 .525-.437.95-.976.95a.964.964 0 01-.976-.95v-1.752c0-.525.437-.951.976-.951zm5 0c.539 0 .976.426.976.95v1.753c0 .525-.437.95-.976.95a.964.964 0 01-.976-.95v-1.752c0-.525.437-.951.976-.951zM7.635 5.087c-1.05.102-1.935.438-2.385.906-.975 1.037-.765 3.668-.21 4.224.405.394 1.17.657 1.995.657h.09c.649-.013 1.785-.176 2.73-1.11.435-.41.705-1.433.675-2.47-.03-.834-.27-1.52-.63-1.813-.39-.336-1.275-.482-2.265-.394zm6.465.394c-.36.292-.6.98-.63 1.813-.03 1.037.24 2.06.675 2.47.968.957 2.136 1.104 2.776 1.11h.044c.825 0 1.59-.263 1.995-.657.555-.556.765-3.187-.21-4.224-.45-.468-1.335-.804-2.385-.906-.99-.088-1.875.058-2.265.394zM12 7.615c-.24 0-.525.015-.84.044.03.16.045.336.06.526l-.001.159a2.94 2.94 0 01-.014.25c.225-.022.425-.027.612-.028h.366c.187 0 .387.006.612.028-.015-.146-.015-.277-.015-.409.015-.19.03-.365.06-.526a9.29 9.29 0 00-.84-.044z"></path></svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
@@ -0,0 +1 @@
|
||||
<svg fill="#24292f" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>GithubCopilot</title><path d="M19.245 5.364c1.322 1.36 1.877 3.216 2.11 5.817.622 0 1.2.135 1.592.654l.73.964c.21.278.323.61.323.955v2.62c0 .339-.173.669-.453.868C20.239 19.602 16.157 21.5 12 21.5c-4.6 0-9.205-2.583-11.547-4.258-.28-.2-.452-.53-.453-.868v-2.62c0-.345.113-.679.321-.956l.73-.963c.392-.517.974-.654 1.593-.654l.029-.297c.25-2.446.81-4.213 2.082-5.52 2.461-2.54 5.71-2.851 7.146-2.864h.198c1.436.013 4.685.323 7.146 2.864zm-7.244 4.328c-.284 0-.613.016-.962.05-.123.447-.305.85-.57 1.108-1.05 1.023-2.316 1.18-2.994 1.18-.638 0-1.306-.13-1.851-.464-.516.165-1.012.403-1.044.996a65.882 65.882 0 00-.063 2.884l-.002.48c-.002.563-.005 1.126-.013 1.69.002.326.204.63.51.765 2.482 1.102 4.83 1.657 6.99 1.657 2.156 0 4.504-.555 6.985-1.657a.854.854 0 00.51-.766c.03-1.682.006-3.372-.076-5.053-.031-.596-.528-.83-1.046-.996-.546.333-1.212.464-1.85.464-.677 0-1.942-.157-2.993-1.18-.266-.258-.447-.661-.57-1.108-.32-.032-.64-.049-.96-.05zm-2.525 4.013c.539 0 .976.426.976.95v1.753c0 .525-.437.95-.976.95a.964.964 0 01-.976-.95v-1.752c0-.525.437-.951.976-.951zm5 0c.539 0 .976.426.976.95v1.753c0 .525-.437.95-.976.95a.964.964 0 01-.976-.95v-1.752c0-.525.437-.951.976-.951zM7.635 5.087c-1.05.102-1.935.438-2.385.906-.975 1.037-.765 3.668-.21 4.224.405.394 1.17.657 1.995.657h.09c.649-.013 1.785-.176 2.73-1.11.435-.41.705-1.433.675-2.47-.03-.834-.27-1.52-.63-1.813-.39-.336-1.275-.482-2.265-.394zm6.465.394c-.36.292-.6.98-.63 1.813-.03 1.037.24 2.06.675 2.47.968.957 2.136 1.104 2.776 1.11h.044c.825 0 1.59-.263 1.995-.657.555-.556.765-3.187-.21-4.224-.45-.468-1.335-.804-2.385-.906-.99-.088-1.875.058-2.265.394zM12 7.615c-.24 0-.525.015-.84.044.03.16.045.336.06.526l-.001.159a2.94 2.94 0 01-.014.25c.225-.022.425-.027.612-.028h.366c.187 0 .387.006.612.028-.015-.146-.015-.277-.015-.409.015-.19.03-.365.06-.526a9.29 9.29 0 00-.84-.044z"></path></svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 59 KiB |
|
After Width: | Height: | Size: 46 KiB |
@@ -0,0 +1,11 @@
|
||||
<svg width="1200" height="1200" viewBox="0 0 1200 1200" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="1200" height="1200" rx="260" fill="#9046FF"/>
|
||||
<mask id="mask0_1106_4856" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="272" y="202" width="655" height="796">
|
||||
<path d="M926.578 202.793H272.637V997.857H926.578V202.793Z" fill="white"/>
|
||||
</mask>
|
||||
<g mask="url(#mask0_1106_4856)">
|
||||
<path d="M398.554 818.914C316.315 1001.03 491.477 1046.74 620.672 940.156C658.687 1059.66 801.052 970.473 852.234 877.795C964.787 673.567 919.318 465.357 907.64 422.374C827.637 129.443 427.623 128.946 358.8 423.865C342.651 475.544 342.402 534.18 333.458 595.051C328.986 625.86 325.507 645.488 313.83 677.785C306.873 696.424 297.68 712.819 282.773 740.645C259.915 783.881 269.604 867.113 387.87 823.883L399.051 818.914H398.554Z" fill="white"/>
|
||||
<path d="M636.123 549.353C603.328 549.353 598.359 510.097 598.359 486.742C598.359 465.623 602.086 448.977 609.293 438.293C615.504 428.852 624.697 424.131 636.123 424.131C647.555 424.131 657.492 428.852 664.447 438.541C672.398 449.474 676.623 466.12 676.623 486.742C676.623 525.998 661.471 549.353 636.375 549.353H636.123Z" fill="black"/>
|
||||
<path d="M771.24 549.353C738.445 549.353 733.477 510.097 733.477 486.742C733.477 465.623 737.203 448.977 744.41 438.293C750.621 428.852 759.814 424.131 771.24 424.131C782.672 424.131 792.609 428.852 799.564 438.541C807.516 449.474 811.74 466.12 811.74 486.742C811.74 525.998 796.588 549.353 771.492 549.353H771.24Z" fill="black"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 32 32"><clipPath id="a"><path d="M0 0h32v32H0z"/></clipPath><g clip-path="url(#a)"><path d="M3 32V0h26v32zM22 7H10v18h12z" style="fill:#fff"/><path d="M10 13h12v12H10z" style="fill:#5a5858"/></g></svg>
|
||||
|
After Width: | Height: | Size: 276 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 32 32"><clipPath id="a"><path d="M0 0h32v32H0z"/></clipPath><g clip-path="url(#a)"><path d="M3 32V0h26v32zM22 7H10v18h12z" style="fill:#131010"/><path d="M10 13h12v12H10z" style="fill:#cfcecd"/></g></svg>
|
||||
|
After Width: | Height: | Size: 279 B |
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="165.29 165.29 469.43 469.43">
|
||||
<!-- P shape: outer boundary clockwise, inner hole counter-clockwise -->
|
||||
<path fill="#fff" fill-rule="evenodd" d="
|
||||
M165.29 165.29
|
||||
H517.36
|
||||
V400
|
||||
H400
|
||||
V517.36
|
||||
H282.65
|
||||
V634.72
|
||||
H165.29
|
||||
Z
|
||||
M282.65 282.65
|
||||
V400
|
||||
H400
|
||||
V282.65
|
||||
Z
|
||||
"/>
|
||||
<!-- i dot -->
|
||||
<path fill="#fff" d="M517.36 400 H634.72 V634.72 H517.36 Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 489 B |
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="165.29 165.29 469.43 469.43">
|
||||
<!-- P shape: outer boundary clockwise, inner hole counter-clockwise -->
|
||||
<path fill="#131010" fill-rule="evenodd" d="
|
||||
M165.29 165.29
|
||||
H517.36
|
||||
V400
|
||||
H400
|
||||
V517.36
|
||||
H282.65
|
||||
V634.72
|
||||
H165.29
|
||||
Z
|
||||
M282.65 282.65
|
||||
V400
|
||||
H400
|
||||
V282.65
|
||||
Z
|
||||
"/>
|
||||
<!-- i dot -->
|
||||
<path fill="#131010" d="M517.36 400 H634.72 V634.72 H517.36 Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 495 B |
|
After Width: | Height: | Size: 173 KiB |
|
After Width: | Height: | Size: 874 KiB |
@@ -0,0 +1,17 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="400" height="44" role="img" aria-label="Beta is ending. Sign up for Workspaces.">
|
||||
<defs>
|
||||
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
|
||||
<stop offset="0%" stop-color="#191a33"/>
|
||||
<stop offset="100%" stop-color="#2b2452"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="shine" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stop-color="#c8c5ea" stop-opacity="0.12"/>
|
||||
<stop offset="100%" stop-color="#c8c5ea" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect width="400" height="44" rx="22" fill="url(#bg)"/>
|
||||
<rect x="0.5" y="0.5" width="399" height="43" rx="21.5" fill="none" stroke="#6f66b8" stroke-opacity="0.55"/>
|
||||
<rect x="1" y="1" width="398" height="21" rx="21" fill="url(#shine)"/>
|
||||
<text x="20" y="30" font-size="19">🎈</text>
|
||||
<text x="218" y="28" text-anchor="middle" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif" font-size="15" font-weight="600" fill="#e6e4f7">Beta is ending · <tspan fill="#f0a64f">Sign up for Workspaces</tspan> →</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -539,6 +539,8 @@ bun run dev:marketing # Marketing site
|
||||
bun run dev:vscode # VS Code extension (watch mode)
|
||||
```
|
||||
|
||||
**Local `plannotator` command:** run `bun link` once in the checkout to make the global `plannotator` command use this repo's source (`apps/hook/server/index.ts`) instead of an installed release binary. Commands like `plannotator review` then reflect local changes immediately. Rebuild the bundled HTML when changing UI code (see Build below).
|
||||
|
||||
## Build
|
||||
|
||||
```bash
|
||||
|
||||
@@ -1,97 +1,216 @@
|
||||
<p align="center">
|
||||
<img src="apps/marketing/public/og-image.webp" alt="Plannotator" width="80%" />
|
||||
<img src=".github/assets/banner.webp" alt="Plannotator" width="640" />
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
<p align="center">
|
||||
<strong>Everything you need to annotate and stay in the loop with your agents</strong><br/>
|
||||
<strong>Doc Review • Code Review • HTML Artifacts</strong><br/>
|
||||
<sub>Annotate plans, specs, markdown, and HTML before implementation. Review diffs and PRs. Send feedback to your agent.</sub>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<img src=".github/assets/icons/amp.svg" alt="Amp" title="Amp" height="28" />
|
||||
<img src=".github/assets/icons/claude.svg" alt="Claude Code" title="Claude Code" height="28" />
|
||||
<img src=".github/assets/icons/codex.png" alt="Codex" title="Codex" height="28" />
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset=".github/assets/icons/copilot-dark.svg" />
|
||||
<img src=".github/assets/icons/copilot-light.svg" alt="Copilot CLI" title="Copilot CLI" height="28" />
|
||||
</picture>
|
||||
<img src=".github/assets/icons/droid.png" alt="Droid" title="Droid" height="28" />
|
||||
<img src=".github/assets/icons/gemini.png" alt="Gemini CLI" title="Gemini CLI" height="28" />
|
||||
<img src=".github/assets/icons/kiro.svg" alt="Kiro" title="Kiro" height="28" />
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset=".github/assets/icons/opencode-dark.svg" />
|
||||
<img src=".github/assets/icons/opencode-light.svg" alt="OpenCode" title="OpenCode" height="28" />
|
||||
</picture>
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset=".github/assets/icons/pi-dark.svg" />
|
||||
<img src=".github/assets/icons/pi-light.svg" alt="Pi" title="Pi" height="28" />
|
||||
</picture>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://www.youtube.com/watch?v=a_AT7cEN_9I">Watch the og demo</a> · <a href="https://plannotator.ai/docs/getting-started/installation/">Installation guide</a> · <a href="https://plannotator.ai/">Official site</a>
|
||||
</p>
|
||||
|
||||
# Plannotator
|
||||
|
||||
Review AI-agent plans and code diffs in a browser. Add inline annotations, send structured feedback back to your agent, and share encrypted review links with teammates. Works with **Claude Code**, **Copilot CLI**, **Gemini CLI**, **OpenCode**, **Pi**, **Codex**, **Droid**, and **Amp**.
|
||||
Plannotator is a local, browser-based review surface for AI coding agents: Claude Code, Codex, Copilot CLI, Gemini CLI, OpenCode, Kiro, Droid, Amp, and Pi.
|
||||
|
||||
**It plugs directly into your agent** through its hooks and commands. When the agent proposes a plan, html, or finishes writing code, the work opens in your browser and you mark it up, comment, and send feedback directly to the agent. Your feedback is sent directly to the agent for it to act on it.
|
||||
|
||||
**Plan Mode Demos:**
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center" width="50%">
|
||||
<h3>Claude Code</h3>
|
||||
<a href="https://www.youtube.com/watch?v=a_AT7cEN_9I">
|
||||
<img src="apps/marketing/public/youtube.png" alt="Claude Code Demo" width="100%" />
|
||||
</a>
|
||||
<p><a href="https://www.youtube.com/watch?v=a_AT7cEN_9I">Watch Demo</a></p>
|
||||
<td width="40%" valign="middle">
|
||||
|
||||
### Review documents, plans, and agent messages
|
||||
|
||||
Annotate plans, specs, messages, html, then send the feedback to your agent.
|
||||
|
||||
<p><strong>Demo:</strong> <a href="https://youtu.be/XqFun9XCXPw">Plan review with Pi</a></p>
|
||||
|
||||
</td>
|
||||
<td align="center" width="50%">
|
||||
<h3>OpenCode</h3>
|
||||
<a href="https://youtu.be/_N7uo0EFI-U">
|
||||
<img src="apps/marketing/public/youtube-opencode.png" alt="OpenCode Demo" width="100%" />
|
||||
</a>
|
||||
<p><a href="https://youtu.be/_N7uo0EFI-U">Watch Demo</a></p>
|
||||
<td width="60%">
|
||||
|
||||
<img src=".github/assets/annotate.webp" alt="Annotate UI with inline annotations" width="100%" />
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" valign="middle">
|
||||
|
||||
### Code Review
|
||||
|
||||
Review local changes or remote PRs. Comment on diffs, suggest code. Your comments go back to the agent. Works with git, jj, p4, GitHub, and GitLab.
|
||||
|
||||
</td>
|
||||
<td width="60%">
|
||||
|
||||
<img src=".github/assets/review.webp" alt="Code review with file tree and side-by-side diff" width="100%" />
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
**Annotate:** Plans, specs, folders, files, urls. send feedback directly to agents.
|
||||
**AI built in:** ask AI about anything you're reviewing, or launch AI reviews that post comments to the diff.
|
||||
|
||||
**New:** [Code Review](https://x.com/backnotprop/status/2031145299738263567?s=20)
|
||||
|
||||
- send your feedback to agents
|
||||
- built-in:
|
||||
- ask ai
|
||||
- agent code reviews
|
||||
## Annotate HTML Artifacts
|
||||
|
||||
### Features
|
||||
<p align="center">
|
||||
<img src=".github/assets/html.webp" alt="Annotating a rendered HTML artifact" width="720" />
|
||||
</p>
|
||||
|
||||
<table>
|
||||
<tr><td><strong>Visual Plan Review</strong></td><td>Built-in hook</td><td>Approve or deny agent plans with inline annotations and Ask AI side chat</td></tr>
|
||||
<tr><td><strong>Plan Diff</strong></td><td>Automatic</td><td>See what changed when the agent revises a plan</td></tr>
|
||||
<tr><td><strong>Code Review</strong></td><td><code>/plannotator-review</code></td><td>View git diffs or remote PRs. Package annotations and ask AI about the code as you review.</td></tr>
|
||||
<tr><td><strong>Annotate Any File</strong></td><td><code>/plannotator-annotate <file|folder|url></code></td><td>Annotate markdown, HTML, URLs, or folders, ask AI about the active document, and send feedback to your agent</td></tr>
|
||||
<tr><td><strong>Annotate Last Message</strong></td><td><code>/plannotator-last</code></td><td>Annotate the agent's last response and send structured feedback</td></tr>
|
||||
</table>
|
||||
---
|
||||
|
||||
#### Sharing Plans
|
||||
## Commands
|
||||
|
||||
Plannotator lets you privately share plans, annotations, and feedback with colleagues. For example, a colleague can annotate a shared plan, and you can import their feedback to send directly back to the coding agent.
|
||||
<sub>On Codex, swap the slash commands for `!plannotator …` (e.g. `!plannotator review`) or the `$plannotator-*` skills.</sub>
|
||||
|
||||
**Small plans** are encoded entirely in the URL hash. No server involved, nothing stored anywhere.
|
||||
### Annotate
|
||||
|
||||
**Large plans** use a short link service with **end-to-end encryption**. Your plan is encrypted with AES-256-GCM in your browser before upload. The server stores only ciphertext it cannot read. The decryption key lives only in the URL you share. Pastes auto-delete after 7 days.
|
||||
```
|
||||
/plannotator-annotate README.md # Local markdown file
|
||||
/plannotator-annotate src/ # Browse and annotate files in a folder
|
||||
/plannotator-annotate https://docs.rs/… # Fetch and annotate any URL
|
||||
/plannotator-annotate report.html --render-html # Render HTML as-is instead of converting
|
||||
/plannotator-last # Annotate the agent's last message
|
||||
```
|
||||
|
||||
- Zero-knowledge storage, similar to [PrivateBin](https://privatebin.info/)
|
||||
- Fully open source and **self-hostable** ([see docs](https://plannotator.ai/docs/guides/sharing-and-collaboration/))
|
||||
### Code review
|
||||
|
||||
```
|
||||
/plannotator-review # Review uncommitted changes
|
||||
/plannotator-review <github-pr-url> # Review a GitHub pull request
|
||||
/plannotator-review <gitlab-mr-url> # Review a GitLab merge request
|
||||
```
|
||||
|
||||
### Plan mode
|
||||
|
||||
No command needed. Plan mode is wired in through each harness's hooks. Any time your agent creates a plan, the markdown review surface opens for you.
|
||||
|
||||
### CLI
|
||||
|
||||
```
|
||||
plannotator sessions # List active Plannotator sessions
|
||||
plannotator sessions --open 1 # Reopen a session in the browser
|
||||
plannotator archive # Browse saved plan decisions read-only
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Sharing & Multiplayer
|
||||
|
||||
<p align="center">
|
||||
<a href="https://room.plannotator.ai/">
|
||||
<img src=".github/assets/sharing.png" alt="Sharing portal with upload options" width="720" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<sub>Beta: <a href="https://room.plannotator.ai/">room.plannotator.ai</a></sub>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://plannotator.ai/workspaces">
|
||||
<img src=".github/assets/workspaces-cta.svg" alt="Beta is ending. Sign up for Workspaces." height="44" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
Share a plan with a teammate and they can annotate it themselves. Import their feedback and send it straight back to your agent.
|
||||
|
||||
**Small plans** are encoded entirely in the URL hash. No server involved. The data lives in the link itself.
|
||||
|
||||
**Large plans** go through a short-link service, encrypted in your browser with AES-256-GCM. The server stores only ciphertext, and the key never leaves the URL fragment. Pastes auto-delete after 7 days.
|
||||
|
||||
Same model as [PrivateBin](https://privatebin.info/). The paste service is [self-hostable](https://plannotator.ai/docs/guides/sharing-and-collaboration/).
|
||||
|
||||
Sharing can be disabled entirely with `PLANNOTATOR_SHARE=disabled`.
|
||||
|
||||
**Coming next:** live collaboration. Teammates and their agents working through the same plan or review together, in real time. It arrives in Workspaces once the room beta wraps. [Sign up here](https://plannotator.ai/workspaces).
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Install
|
||||
|
||||
- [Claude Code](#install-for-claude-code)
|
||||
- [Copilot CLI](#install-for-copilot-cli)
|
||||
- [Gemini CLI](#install-for-gemini-cli)
|
||||
- [OpenCode](#install-for-opencode)
|
||||
- [Pi](#install-for-pi)
|
||||
- [Codex](#install-for-codex)
|
||||
- [Droid](#install-for-droid)
|
||||
|
||||
## Install for Claude Code
|
||||
|
||||
**Install the `plannotator` command:**
|
||||
|
||||
**macOS / Linux / WSL:**
|
||||
One installer covers almost every agent. It installs the `plannotator` binary, auto-detects your installed agents, and configures hooks, skills, and slash commands for each:
|
||||
|
||||
```bash
|
||||
# macOS / Linux / WSL
|
||||
curl -fsSL https://plannotator.ai/install.sh | bash
|
||||
```
|
||||
|
||||
**Windows PowerShell:**
|
||||
|
||||
```powershell
|
||||
# Windows PowerShell
|
||||
irm https://plannotator.ai/install.ps1 | iex
|
||||
```
|
||||
|
||||
**Then in Claude Code:**
|
||||
Then finish the step for your agent:
|
||||
|
||||
```
|
||||
/plugin marketplace add backnotprop/plannotator
|
||||
```
|
||||
| Agent | After the installer | Details |
|
||||
|---|---|---|
|
||||
| **Amp** | Copy [`plannotator.ts`](apps/amp-plugin/plannotator.ts) into `~/.config/amp/plugins/`, then `plugins: reload`. Workflows live in the command palette. | [README](apps/amp-plugin/README.md) |
|
||||
| **Claude Code** | `/plugin marketplace add backnotprop/plannotator`, then `/plugin install plannotator@plannotator`. Restart Claude Code. | [README](apps/hook/README.md) |
|
||||
| **Codex** | Nothing. Plan review is enabled automatically via Codex's experimental `Stop` hook (macOS/Linux/WSL; Codex hooks are disabled on Windows). `$plannotator-review`, `$plannotator-annotate`, and `$plannotator-last` skills included. | [README](apps/codex/README.md) |
|
||||
| **Copilot CLI** | `/plugin marketplace add backnotprop/plannotator`, then `/plugin install plannotator-copilot@plannotator`. Restart. Plan review activates in plan mode (`Shift+Tab`). | [README](apps/copilot/README.md) |
|
||||
| **Droid** | `droid plugin marketplace add https://github.com/backnotprop/plannotator`, then `droid plugin install plannotator@plannotator`. Commands only, no plan interception yet. | [README](apps/droid-plugin/README.md) |
|
||||
| **Gemini CLI** | Nothing. The hook, policy, and slash commands are configured automatically. Requires Gemini CLI 0.36.0+. | [README](apps/gemini/README.md) |
|
||||
| **Kiro CLI** | Nothing. Skills and an example agent are installed automatically. Try `kiro-cli chat --agent plannotator`. | [README](apps/kiro-cli/README.md) |
|
||||
| **OpenCode** | Add `"plugin": ["@plannotator/opencode@latest"]` to `opencode.json`. Restart OpenCode. | [README](apps/opencode-plugin/README.md) |
|
||||
| **Pi** | Skip the installer. Just `pi install npm:@plannotator/pi-extension`. Start Pi with `--plan`, or toggle with `/plannotator`. | [README](apps/pi-extension/README.md) |
|
||||
|
||||
Restart Claude Code after plugin install.
|
||||
Full walkthroughs live in the [installation docs](https://plannotator.ai/docs/getting-started/installation/).
|
||||
|
||||
<details>
|
||||
<summary>Pin a specific version or verify provenance</summary>
|
||||
<summary>Claude Code: manual hook setup (without the plugin system)</summary>
|
||||
|
||||
Add to `~/.claude/settings.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"PermissionRequest": [
|
||||
{
|
||||
"matcher": "ExitPlanMode",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "plannotator",
|
||||
"timeout": 345600
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Pin a specific version</summary>
|
||||
|
||||
```bash
|
||||
curl -fsSL https://plannotator.ai/install.sh | bash -s -- --version vX.Y.Z
|
||||
@@ -101,203 +220,160 @@ curl -fsSL https://plannotator.ai/install.sh | bash -s -- --version vX.Y.Z
|
||||
& ([scriptblock]::Create((irm https://plannotator.ai/install.ps1))) -Version vX.Y.Z
|
||||
```
|
||||
|
||||
Every released binary ships with a SHA256 sidecar (verified automatically). [SLSA provenance](https://slsa.dev/) verification is supported from v0.17.2 onwards — see the [installation docs](https://plannotator.ai/docs/getting-started/installation/#verifying-your-install) for details.
|
||||
|
||||
</details>
|
||||
|
||||
See [apps/hook/README.md](apps/hook/README.md) for detailed installation instructions including a `manual hook` approach.
|
||||
### Try it
|
||||
|
||||
The fastest way to see what Plannotator does is to invoke it yourself, right now, from your agent:
|
||||
|
||||
```
|
||||
/plannotator-last # annotate the agent's last reply
|
||||
/plannotator-review # review your current diff, PR-style
|
||||
/plannotator-annotate report.html # annotate any file, folder, or URL
|
||||
```
|
||||
|
||||
(Slash commands in most agents; `$plannotator-*` skills in Codex, command palette in Amp.)
|
||||
|
||||
Plan review needs no command at all. The next time your agent proposes a plan, it opens in your browser automatically.
|
||||
|
||||
---
|
||||
|
||||
## Install for Copilot CLI
|
||||
## How it works
|
||||
|
||||
**Install the `plannotator` command:**
|
||||
### Plan review
|
||||
|
||||
**macOS / Linux / WSL:**
|
||||
```
|
||||
Agent calls ExitPlanMode
|
||||
-> PermissionRequest hook fires
|
||||
-> Local server reads plan from hook input
|
||||
-> Browser opens with review UI
|
||||
-> You annotate and approve/deny
|
||||
-> Approve: agent proceeds
|
||||
-> Deny: structured feedback sent to agent
|
||||
-> Agent revises, plan diff shows what changed
|
||||
```
|
||||
|
||||
### Code review
|
||||
|
||||
```
|
||||
You run /plannotator-review
|
||||
-> git diff captures changes (or PR fetched by URL)
|
||||
-> Browser opens with diff viewer
|
||||
-> Annotate lines, stage/unstage files
|
||||
-> Send feedback: returned to agent session
|
||||
-> Approve: "LGTM" sent
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Integrations
|
||||
|
||||
**VS Code**: Open plans in editor tabs, view diffs inline, add annotations from the editor gutter. Install from the [VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=backnotprop.plannotator-webview).
|
||||
|
||||
**Obsidian**: Auto-save approved plans to a vault with YAML frontmatter, tags from the plan title, and backlinks for graph connectivity. Configure in Plannotator's Settings panel.
|
||||
|
||||
**Bear**: Save plans as Bear notes with nested tags and project metadata.
|
||||
|
||||
**GitHub / GitLab**: Pass any PR or MR URL to `/plannotator-review` and review it with the full diff viewer, annotations, and file tree.
|
||||
|
||||
---
|
||||
|
||||
## Remote / SSH / devcontainer
|
||||
|
||||
Plannotator auto-detects SSH sessions and switches to a fixed port. For explicit control:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://plannotator.ai/install.sh | bash
|
||||
export PLANNOTATOR_REMOTE=1
|
||||
export PLANNOTATOR_PORT=9999 # forward this port
|
||||
```
|
||||
|
||||
**Windows PowerShell:**
|
||||
|
||||
```powershell
|
||||
irm https://plannotator.ai/install.ps1 | iex
|
||||
```
|
||||
|
||||
**Then in Copilot CLI:**
|
||||
VS Code devcontainers forward the port automatically (check the Ports tab). For raw SSH, add to `~/.ssh/config`:
|
||||
|
||||
```
|
||||
/plugin marketplace add backnotprop/plannotator
|
||||
/plugin install plannotator-copilot@plannotator
|
||||
Host your-server
|
||||
LocalForward 9999 localhost:9999
|
||||
```
|
||||
|
||||
Restart Copilot CLI after plugin install. Plan review activates automatically when you use plan mode (`Shift+Tab` to enter plan mode).
|
||||
|
||||
See [apps/copilot/README.md](apps/copilot/README.md) for details.
|
||||
|
||||
---
|
||||
|
||||
## Install for Gemini CLI
|
||||
## Security
|
||||
|
||||
**Install the `plannotator` command:**
|
||||
Every released binary ships with a SHA256 sidecar. [SLSA provenance](https://slsa.dev/) attestations are available from v0.17.2.
|
||||
|
||||
**macOS / Linux / WSL:**
|
||||
To verify on install:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://plannotator.ai/install.sh | bash
|
||||
curl -fsSL https://plannotator.ai/install.sh | bash -s -- --verify-attestation
|
||||
```
|
||||
|
||||
**Windows PowerShell:**
|
||||
|
||||
```powershell
|
||||
irm https://plannotator.ai/install.ps1 | iex
|
||||
```
|
||||
|
||||
The installer auto-detects Gemini CLI (checks for `~/.gemini`) and configures the plan review hook and policy. It also installs `/plannotator-review` and `/plannotator-annotate` slash commands.
|
||||
|
||||
**Then in Gemini CLI:**
|
||||
|
||||
```
|
||||
/plan # Enter plan mode — plans open in your browser
|
||||
/plannotator-review # Code review for current changes
|
||||
/plannotator-review <pr-url> # Review a GitHub pull request
|
||||
/plannotator-annotate <file.md> # Annotate a markdown file
|
||||
```
|
||||
|
||||
Requires Gemini CLI 0.36.0 or later.
|
||||
|
||||
See [apps/gemini/README.md](apps/gemini/README.md) for details.
|
||||
|
||||
---
|
||||
|
||||
## Install for OpenCode
|
||||
|
||||
Add to your `opencode.json`:
|
||||
Requires `gh` installed and authenticated. Can also be set persistently in `~/.plannotator/config.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"plugin": ["@plannotator/opencode@latest"]
|
||||
}
|
||||
{ "verifyAttestation": true }
|
||||
```
|
||||
|
||||
**Run the install script** to get `/plannotator-review`:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://plannotator.ai/install.sh | bash
|
||||
```
|
||||
|
||||
**Windows:**
|
||||
```powershell
|
||||
irm https://plannotator.ai/install.ps1 | iex
|
||||
```
|
||||
|
||||
This also clears any cached plugin versions. Then restart OpenCode.
|
||||
See the [verification docs](https://plannotator.ai/docs/getting-started/installation/#verifying-your-install) for details.
|
||||
|
||||
---
|
||||
|
||||
## Install for Pi
|
||||
## Configuration
|
||||
|
||||
```bash
|
||||
pi install npm:@plannotator/pi-extension
|
||||
```
|
||||
Settings are saved in cookies (not localStorage) because each hook invocation runs on a random port. You can also set options through environment variables or `~/.plannotator/config.json`.
|
||||
|
||||
Then start Pi with `--plan` to enter plan mode, or toggle it during a session with `/plannotator`.
|
||||
|
||||
See [apps/pi-extension/README.md](apps/pi-extension/README.md) for full usage details, commands, and flags.
|
||||
| Variable | Description |
|
||||
|---|---|
|
||||
| `PLANNOTATOR_REMOTE` | `1`/`true` for remote mode, `0`/`false` for local, unset for SSH auto-detection |
|
||||
| `PLANNOTATOR_PORT` | Fixed port (default: random locally, `19432` remote) |
|
||||
| `PLANNOTATOR_BROWSER` | Custom browser to open plans in |
|
||||
| `PLANNOTATOR_SHARE` | `disabled` to turn off URL sharing |
|
||||
| `PLANNOTATOR_SHARE_URL` | Custom base URL for share links (self-hosted portal) |
|
||||
| `PLANNOTATOR_PASTE_URL` | Base URL of the paste service API |
|
||||
| `PLANNOTATOR_ORIGIN` | Override agent detection: `claude-code`, `amp`, `droid`, `opencode`, `codex`, `copilot-cli`, `gemini-cli`, `kiro-cli`, `pi` |
|
||||
| `PLANNOTATOR_JINA` | `0`/`false` to disable Jina Reader for URL annotation |
|
||||
| `JINA_API_KEY` | Jina Reader API key for higher rate limits |
|
||||
|
||||
---
|
||||
|
||||
## Install for Codex
|
||||
|
||||
**Install the `plannotator` command:**
|
||||
|
||||
**macOS / Linux / WSL:**
|
||||
## Development
|
||||
|
||||
```bash
|
||||
curl -fsSL https://plannotator.ai/install.sh | bash
|
||||
bun install
|
||||
|
||||
bun run dev:hook # Plan review server
|
||||
bun run dev:review # Code review editor
|
||||
bun run dev:marketing # Marketing site (plannotator.ai)
|
||||
bun run dev:vscode # VS Code extension (watch mode)
|
||||
```
|
||||
|
||||
The installer also enables Codex Stop hooks when Codex is installed or `~/.codex` already exists. Restart Codex Desktop
|
||||
after installing or changing hooks.
|
||||
|
||||
**Windows PowerShell:**
|
||||
|
||||
```powershell
|
||||
irm https://plannotator.ai/install.ps1 | iex
|
||||
```
|
||||
|
||||
Codex plan review is automatic on macOS, Linux, and WSL. Codex hooks are currently disabled on Windows in the official Codex docs, so the Windows installer does not enable them automatically; the direct `!plannotator` commands still work.
|
||||
|
||||
**Then in Codex — feedback flows back into the agent loop automatically:**
|
||||
|
||||
```
|
||||
$plannotator-review # Code review skill for current changes
|
||||
$plannotator-annotate # Annotate a markdown file, URL, or folder
|
||||
$plannotator-last # Annotate the last agent message
|
||||
```
|
||||
|
||||
```
|
||||
!plannotator review # Code review for current changes
|
||||
!plannotator review <pr-url> # Review a GitHub pull request
|
||||
!plannotator annotate file.md # Annotate a markdown file
|
||||
!plannotator last # Annotate the last agent message
|
||||
```
|
||||
|
||||
Plan review uses Codex's experimental `Stop` hook on macOS, Linux, and WSL.
|
||||
|
||||
See [apps/codex/README.md](apps/codex/README.md) for details.
|
||||
|
||||
---
|
||||
|
||||
## Install for Droid
|
||||
|
||||
**Install the `plannotator` command:**
|
||||
|
||||
**macOS / Linux / WSL:**
|
||||
### Build
|
||||
|
||||
```bash
|
||||
curl -fsSL https://plannotator.ai/install.sh | bash
|
||||
bun run build # Main targets (hook + opencode)
|
||||
bun run build:hook # Single-file HTML for the hook server
|
||||
bun run build:review # Code review editor
|
||||
bun run build:opencode # OpenCode plugin
|
||||
bun run build:vscode # VS Code extension
|
||||
```
|
||||
|
||||
**Windows PowerShell:**
|
||||
|
||||
```powershell
|
||||
irm https://plannotator.ai/install.ps1 | iex
|
||||
```
|
||||
|
||||
**Then in Droid:**
|
||||
Build order matters. The hook build copies pre-built HTML from `apps/review/dist/`. If you change UI code in `packages/ui/`, `packages/editor/`, or `packages/review-editor/`, rebuild the review app first:
|
||||
|
||||
```bash
|
||||
droid plugin marketplace add https://github.com/backnotprop/plannotator
|
||||
droid plugin install plannotator@plannotator
|
||||
bun run --cwd apps/review build && bun run build:hook
|
||||
```
|
||||
|
||||
This Droid plugin is commands-only. It adds:
|
||||
Test the plugin locally:
|
||||
|
||||
```text
|
||||
/plannotator-review
|
||||
/plannotator-annotate <file|folder|url>
|
||||
/plannotator-last
|
||||
```bash
|
||||
claude --plugin-dir ./apps/hook
|
||||
```
|
||||
|
||||
It does not currently intercept Droid's planning flow.
|
||||
Full binary build:
|
||||
|
||||
See [apps/droid-plugin/README.md](apps/droid-plugin/README.md) for details.
|
||||
```bash
|
||||
bun run --cwd apps/review build && bun run build:hook && \
|
||||
bun build apps/hook/server/index.ts --compile --outfile ~/.local/bin/plannotator
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## How It Works
|
||||
|
||||
When your AI agent finishes planning, Plannotator:
|
||||
|
||||
1. Opens the Plannotator UI in your browser
|
||||
2. Lets you annotate the plan visually (delete, insert, replace, comment)
|
||||
3. Lets you ask AI about the plan or a highlighted selection when a provider is available
|
||||
4. **Approve** → Agent proceeds with implementation
|
||||
5. **Request changes** → Your annotations are sent back as structured feedback
|
||||
|
||||
(Similar flow for code review, except you can also comment on specific lines of code diffs)
|
||||
|
||||
---
|
||||
|
||||
@@ -305,30 +381,6 @@ When your AI agent finishes planning, Plannotator:
|
||||
|
||||
Copyright 2025-2026 backnotprop
|
||||
|
||||
This project is licensed under either of
|
||||
Dual-licensed under [Apache 2.0](LICENSE-APACHE) or [MIT](LICENSE-MIT) at your option.
|
||||
|
||||
- [Apache License, Version 2.0](LICENSE-APACHE) ([http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0))
|
||||
- [MIT license](LICENSE-MIT) ([http://opensource.org/licenses/MIT](http://opensource.org/licenses/MIT))
|
||||
|
||||
at your option.
|
||||
|
||||
### Contribution
|
||||
|
||||
Unless you explicitly state otherwise, any contribution intentionally submitted
|
||||
for inclusion in this project by you, as defined in the Apache-2.0 license,
|
||||
shall be dual licensed as above, without any additional terms or conditions.
|
||||
|
||||
## Development
|
||||
|
||||
To make the global `plannotator` command run from this checkout:
|
||||
|
||||
```bash
|
||||
bun install
|
||||
bun link
|
||||
```
|
||||
|
||||
After linking, commands like `plannotator review` use `apps/hook/server/index.ts` from your local repo. Rebuild the bundled HTML when changing UI code:
|
||||
|
||||
```bash
|
||||
bun run --cwd apps/review build && bun run build:hook
|
||||
```
|
||||
Contributions are dual-licensed under the same terms unless you explicitly state otherwise.
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
# Adversarial Rubric
|
||||
|
||||
Last Updated: 2026-04-17
|
||||
|
||||
This rubric captures the main adversarial and drift vectors for Plannotator's review and annotation surfaces. It is intended for milestone reviews, especially for UI state changes that can unintentionally cross plan, annotate, archive, and review modes.
|
||||
|
||||
## Data Boundaries
|
||||
|
||||
| Boundary | Format | Validation | Failure Mode |
|
||||
| --- | --- | --- | --- |
|
||||
| `/api/plan`, `/api/feedback`, `/api/draft`, `/api/upload` between browser and Bun server | JSON, multipart form data, markdown text | Per-endpoint parsing in `packages/server/index.ts`, `packages/server/annotate.ts`, `packages/server/shared-handlers.ts` | Invalid payloads can silently fall back to demo/empty state or reject late in the flow |
|
||||
| Linked-doc file resolution via `/api/doc` and Obsidian doc endpoints | Relative/absolute markdown paths | `packages/server/reference-handlers.ts`, `packages/shared/resolve-file.ts` normalize and constrain paths | Path confusion can open the wrong file or expose unintended content if guards drift |
|
||||
| Share/import URLs and paste payloads | URL hash, compressed JSON, encrypted blobs | `packages/ui/utils/sharing.ts` parses, decompresses, decrypts, and reconstructs annotations | Malformed share payloads can break annotation restore or produce partial state |
|
||||
| External annotations stream and snapshot APIs | SSE + JSON annotations | `packages/server/external-annotations.ts`, shared annotation types in `packages/shared/external-annotation.ts` | Unsanitized/invalid annotation payloads can corrupt UI state or highlight bookkeeping |
|
||||
| Cookie-backed UI preferences | Strings in `document.cookie` | `packages/ui/utils/storage.ts`, `packages/ui/utils/uiPreferences.ts`, `packages/ui/config/settings.ts` coerce to enums/bools | Invalid cookie values can create inconsistent mode/layout defaults across sessions |
|
||||
|
||||
## Type Coercion Vectors
|
||||
|
||||
| Coercion | Location | Risk | Test Exists? |
|
||||
| --- | --- | --- | --- |
|
||||
| Cookie string → boolean / enum | `packages/ui/utils/uiPreferences.ts`, `packages/ui/config/settings.ts` | Invalid values can silently select unsafe defaults or inconsistent layout state | Partial |
|
||||
| URL hash / paste payload → structured annotations | `packages/ui/utils/sharing.ts` | Malformed arrays or unexpected tuple shapes can restore incomplete/shifted annotations | Partial |
|
||||
| Query/path input → resolved markdown path | `packages/shared/resolve-file.ts` | Separator normalization and basename fallback can drift from intended trust boundary | Yes |
|
||||
| External annotation JSON → internal annotation model | `packages/shared/external-annotation.ts` | Missing/extra fields can degrade rendering or selection restoration | Partial |
|
||||
| Resize/cap values → persisted panel widths | `packages/ui/hooks/useResizablePanel.ts` | Invalid saved widths can distort layout or hide controls | No |
|
||||
|
||||
## Trust Assumptions
|
||||
|
||||
| Assumption | What Breaks | Severity | Test Exists? |
|
||||
| --- | --- | --- | --- |
|
||||
| Annotate-only UI changes will not leak into plan/review/archive modes | Hidden controls or layout regressions in other surfaces | HIGH | No |
|
||||
| Session-scoped UI modes restore the user’s prior layout exactly | Users lose sidebar/panel context or hidden state drifts | HIGH | No |
|
||||
| Shared workspace aliases stay aligned across app Vite configs | Local builds fail even though workspace packages compile | MEDIUM | No |
|
||||
| Linked-doc navigation only needs the sidebar capabilities it declares | Runtime mismatches if hook expectations drift | MEDIUM | No |
|
||||
| Cookie defaults are benign when malformed or missing | Surprising startup state, especially around sidebar and panel behavior | LOW | Partial |
|
||||
|
||||
## Cascade Risks
|
||||
|
||||
| Cascade Point | Blast Radius | Isolation | Test Exists? |
|
||||
| --- | --- | --- | --- |
|
||||
| Viewer/layout mode toggles in `packages/editor/App.tsx` | Can affect annotate, plan, linked-doc, archive, and sticky-header behavior at once | Manual branching by `annotateMode`, `archiveMode`, `isPlanDiffActive` | No |
|
||||
| Sticky header lane width calculations | Reader chrome can diverge from document width and overlay controls incorrectly | Separate `StickyHeaderLane` component with measured widths | No |
|
||||
| Linked-doc state swap and cached annotations | Annotation state can leak between source doc and linked doc | `useLinkedDoc` caches/restores per file | No |
|
||||
| External annotation highlight replay | DOM highlights can desync when switching linked docs or diff mode | `useExternalAnnotationHighlights` and explicit reset hooks | Partial |
|
||||
|
||||
## Registry Drift Risks
|
||||
|
||||
| Registry | Code Location | Drift Detection | Last Verified |
|
||||
| --- | --- | --- | --- |
|
||||
| Hook/review app workspace aliases | `apps/hook/vite.config.ts`, `apps/review/vite.config.ts` | Manual build of both apps | 2026-04-17 |
|
||||
| Public API endpoint docs vs runtime endpoints | `AGENTS.md`, marketing docs, `packages/server/*.ts` | Manual review + endpoint additions in PR review | 2026-04-17 |
|
||||
| Shared package exports vs app imports | `packages/shared/package.json` and app/package imports | Typecheck/build | 2026-04-17 |
|
||||
| UI preference keys vs Settings UI | `packages/ui/utils/uiPreferences.ts`, `packages/ui/components/Settings.tsx` | Manual review | 2026-04-17 |
|
||||
|
||||
## Learned Vectors
|
||||
|
||||
| Vector | Source Milestone | Category | Recurrence |
|
||||
| --- | --- | --- | --- |
|
||||
| Session-scoped layout modes can mutate hidden panel state unless every reopen path exits the mode first | `feat/annotate-wide-mode` | Cascade / Trust Assumption | Likely |
|
||||
| Annotate-only controls must be explicitly gated to avoid leaking into plan/review surfaces through shared components | `feat/annotate-wide-mode` | Trust Assumption | Likely |
|
||||
| Build-time alias drift can look like a feature regression even when the code change is correct | `feat/annotate-wide-mode` | Registry Drift | Likely |
|
||||
@@ -1,254 +0,0 @@
|
||||
# Issue 694 Code Navigation Recap
|
||||
|
||||
Issue: https://github.com/backnotprop/plannotator/issues/694
|
||||
|
||||
## What The User Is Asking For
|
||||
|
||||
The feature request asks for IDE-like semantic code navigation inside the Plannotator code review UI. The examples in the issue are:
|
||||
|
||||
- Ctrl/Cmd-click an identifier to find references.
|
||||
- Show references in a sidebar.
|
||||
- Peek definition.
|
||||
- Navigate to definitions, references, and implementations without leaving the review context.
|
||||
|
||||
The user-facing value is not "AST parsing" by itself. The value is that while reviewing a diff, a reviewer can quickly answer: where is this symbol defined, where else is it used, and what related code should I inspect before annotating?
|
||||
|
||||
## Current Plannotator Context
|
||||
|
||||
Plannotator already has the right UI surface to capture the interaction:
|
||||
|
||||
- The code review UI renders diffs through `@pierre/diffs`.
|
||||
- Pierre exposes token-level events with line number, character range, token text, token DOM element, and diff side.
|
||||
- Plannotator already wires Pierre token clicks into the annotation toolbar.
|
||||
- The review server already serves old/new file contents for changed files through `/api/file-content`.
|
||||
- Dockview already gives us a natural place to add a "References" or "Peek Definition" panel.
|
||||
|
||||
Important constraint: Pierre does not provide semantic code intelligence. It can tell us "the user clicked this token at this location." It cannot tell us where the symbol is defined or referenced. That needs a separate backend resolver.
|
||||
|
||||
## PR Diff Constraints
|
||||
|
||||
PR mode matters because code navigation depends on which version of the repository we are asking about.
|
||||
|
||||
Layer PR diffs are platform diffs. In that mode, Plannotator has the patch and can fetch file contents from GitHub/GitLab by SHA, but it may not have a complete local repository to search.
|
||||
|
||||
Full-stack PR mode and local review mode can use a local checkout/worktree. Those modes are much better for repo-wide code navigation because the backend can run local search tools against actual files.
|
||||
|
||||
The practical rule should be:
|
||||
|
||||
- Platform-only PR mode: support changed-file/current-diff navigation and clear degradation.
|
||||
- Local checkout/worktree mode: support repo-wide references and likely definitions.
|
||||
|
||||
## What We Explored
|
||||
|
||||
### Full LSP
|
||||
|
||||
Bundling and running language servers inside Plannotator is not a good MVP path. It is heavyweight, language-specific, expensive to bundle, harder to sandbox, and can be slow or brittle across arbitrary user repos.
|
||||
|
||||
LSP can remain an optional future accuracy tier if a project already has the needed tooling installed.
|
||||
|
||||
### SCIP / LSIF
|
||||
|
||||
SCIP is the right shape for precise code intelligence if an index already exists. It can represent definitions, references, and richer symbol relationships. But generating SCIP indexes means invoking language-specific indexers, which brings back the same cost problem as LSP.
|
||||
|
||||
Good future path: consume SCIP when present. Do not generate it by default in the MVP.
|
||||
|
||||
### Tree-sitter / Stack Graphs
|
||||
|
||||
Tree-sitter can parse source and identify syntax cheaply. Stack Graphs can model scope and name resolution for supported languages. This is more principled than regex search, but it still requires language grammars, queries, and integration work.
|
||||
|
||||
Good future path: use this to improve definitions and ranking. Not needed for the first useful version.
|
||||
|
||||
### Universal Ctags
|
||||
|
||||
Universal Ctags can produce a symbol index for definitions across many languages. It is lightweight compared with LSP, but it is not guaranteed to be installed. On this machine, only the older Xcode `ctags` is present, not Universal Ctags.
|
||||
|
||||
Good future path: detect Universal Ctags if available and use it as a definition indexer.
|
||||
|
||||
### Ripgrep
|
||||
|
||||
Ripgrep is the best MVP foundation:
|
||||
|
||||
- It is commonly installed in developer environments.
|
||||
- It is very fast.
|
||||
- It needs no index.
|
||||
- It respects ignore files by default.
|
||||
- It can return JSON output.
|
||||
- It is easy to cap, timeout, and cancel.
|
||||
|
||||
On this repo, exact whole-word JSON searches over roughly 800 tracked files completed around 20-25ms. That is fast enough to use lazily on click.
|
||||
|
||||
## Recommended MVP
|
||||
|
||||
Build a search-based code navigation backend first.
|
||||
|
||||
Flow:
|
||||
|
||||
1. Pierre emits a token interaction: file path, side, line, char range, token text.
|
||||
2. Frontend sends that to the server.
|
||||
3. Server runs a bounded exact-symbol `rg` search for references.
|
||||
4. Server runs a second bounded search for likely definitions using simple language-aware regex patterns.
|
||||
5. Server ranks results.
|
||||
6. Server returns snippets, result kind, confidence, elapsed time, and whether results were capped.
|
||||
7. Frontend can later render this in a polished IDE-like sidebar or peek panel.
|
||||
|
||||
Example endpoint:
|
||||
|
||||
```ts
|
||||
POST /api/code-nav/resolve
|
||||
{
|
||||
symbol: "startReviewServer",
|
||||
filePath: "packages/server/review.ts",
|
||||
line: 134,
|
||||
charStart: 22,
|
||||
side: "new",
|
||||
language: "typescript"
|
||||
}
|
||||
```
|
||||
|
||||
Example response:
|
||||
|
||||
```ts
|
||||
{
|
||||
backend: "search",
|
||||
complete: true,
|
||||
definitions: [
|
||||
{
|
||||
kind: "definition",
|
||||
confidence: "likely",
|
||||
filePath: "packages/server/review.ts",
|
||||
line: 134,
|
||||
column: 22,
|
||||
snippet: "export async function startReviewServer("
|
||||
}
|
||||
],
|
||||
references: [
|
||||
{
|
||||
kind: "reference",
|
||||
filePath: "apps/hook/server/index.ts",
|
||||
line: 516,
|
||||
column: 23,
|
||||
snippet: "const server = await startReviewServer({"
|
||||
}
|
||||
],
|
||||
stats: {
|
||||
elapsedMs: 24,
|
||||
capped: false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Definition Heuristics
|
||||
|
||||
For the MVP, definitions should be "likely definitions," not falsely marketed as perfect semantic answers.
|
||||
|
||||
For TypeScript/JavaScript, patterns can cover:
|
||||
|
||||
- `function symbol`
|
||||
- `async function symbol`
|
||||
- `export function symbol`
|
||||
- `export async function symbol`
|
||||
- `const symbol =`
|
||||
- `let symbol =`
|
||||
- `var symbol =`
|
||||
- `class symbol`
|
||||
- `interface symbol`
|
||||
- `type symbol`
|
||||
- `enum symbol`
|
||||
- `symbol(` inside object/class method contexts
|
||||
|
||||
Other language patterns can be added incrementally:
|
||||
|
||||
- Python: `def symbol`, `class symbol`
|
||||
- Go: `func symbol`, `func (...) symbol`, `type symbol`
|
||||
- Rust: `fn symbol`, `struct symbol`, `enum symbol`, `trait symbol`, `impl`
|
||||
|
||||
The backend should label these as `likely_definition` unless a stronger backend produced the result.
|
||||
|
||||
## Ranking
|
||||
|
||||
Ranking matters more than perfect completeness in the MVP.
|
||||
|
||||
Recommended ranking:
|
||||
|
||||
1. Exact match in the current file.
|
||||
2. Exact match in changed files.
|
||||
3. Likely definition in the same directory.
|
||||
4. Likely definition in imported/exported files.
|
||||
5. Same language/extension.
|
||||
6. Test files lower unless clicked symbol came from a test.
|
||||
7. Docs and generated files lower.
|
||||
8. Everything else.
|
||||
|
||||
The server should return capped results rather than trying to be exhaustive.
|
||||
|
||||
## Performance Rules
|
||||
|
||||
The backend should be lazy, bounded, and cancelable.
|
||||
|
||||
- No startup indexing.
|
||||
- Do no work until the user asks for code navigation.
|
||||
- Use current diff/current file matches immediately in memory.
|
||||
- Run `rg` with exact whole-word matching.
|
||||
- Cap result count.
|
||||
- Cap files searched.
|
||||
- Apply a short timeout.
|
||||
- Cancel stale searches when the user clicks another symbol.
|
||||
- Cache recent symbol queries per repo state.
|
||||
- Respect `.gitignore` and skip `node_modules`, `dist`, build outputs, binary files, and vendored directories.
|
||||
- Return partial results if a search is capped or times out.
|
||||
|
||||
This keeps the feature cheap for normal use and prevents pathological repos from freezing the review server.
|
||||
|
||||
## Backend Capability Tiers
|
||||
|
||||
The capability model should be explicit:
|
||||
|
||||
1. `search`: always available if `rg` is present. Provides exact references and likely definitions.
|
||||
2. `ctags`: optional if Universal Ctags is installed. Improves definitions.
|
||||
3. `tree-sitter`: optional later. Improves symbol classification and local scoping.
|
||||
4. `scip`: optional if an index is already present. Provides precise code intelligence.
|
||||
5. `lsp`: optional future integration only, never required for baseline behavior.
|
||||
|
||||
The UI can show this honestly:
|
||||
|
||||
- "References" for exact search matches.
|
||||
- "Likely definition" for regex/ctags results.
|
||||
- "Precise definition" only when a precise backend produced it.
|
||||
|
||||
## What This Enables On The Frontend
|
||||
|
||||
Once this backend exists, the frontend can become more IDE-like without depending on heavyweight infrastructure:
|
||||
|
||||
- Ctrl/Cmd-click a token in the Pierre diff.
|
||||
- Hover with modifier key to show that the token is navigable.
|
||||
- Show references in a sidebar panel.
|
||||
- Show a peek definition panel.
|
||||
- Jump to a changed-file result in the existing diff view.
|
||||
- Open unchanged-file results in a read-only source preview panel.
|
||||
- Highlight all visible references in the current diff.
|
||||
- Add annotations directly from search/navigation results.
|
||||
|
||||
The frontend can be polished later. The backend only needs to return stable, fast, ranked results.
|
||||
|
||||
## Non-Goals For The MVP
|
||||
|
||||
- Do not bundle language servers.
|
||||
- Do not build a full repo index on server startup.
|
||||
- Do not promise perfect semantic correctness.
|
||||
- Do not require Universal Ctags, Tree-sitter, SCIP, or language-specific tools.
|
||||
- Do not make platform-only PR mode pretend it has full repo navigation when no local checkout exists.
|
||||
|
||||
## Final Recommendation
|
||||
|
||||
Implement the first version as:
|
||||
|
||||
```text
|
||||
Pierre token click
|
||||
-> /api/code-nav/resolve
|
||||
-> bounded rg references
|
||||
-> regex-ranked likely definitions
|
||||
-> snippets + confidence labels
|
||||
-> sidebar/peek-ready response
|
||||
```
|
||||
|
||||
This gives users most of the value they are asking for while keeping Plannotator lightweight. It also creates a clean upgrade path: richer backends can be added later without changing the frontend contract.
|
||||
@@ -1,340 +0,0 @@
|
||||
# Semantic Diff Handoff
|
||||
|
||||
PR: https://github.com/backnotprop/plannotator/pull/871
|
||||
|
||||
Branch: `feat/sem-diff`
|
||||
|
||||
## What Was Built
|
||||
|
||||
This PR adds a semantic diff overview to the code review UI. Instead of starting reviewers in a raw file list, Plannotator can now show a compact entity-level overview like:
|
||||
|
||||
```txt
|
||||
packages/ui/components/Settings.tsx
|
||||
added function isBuiltInFont
|
||||
modified function ReviewDisplayTab
|
||||
```
|
||||
|
||||
The view is backed by the Ataraxy `sem` CLI. Plannotator sends the active review patch to `sem diff --patch --format json`, receives structured JSON, then renders grouped semantic rows in a Dockview panel.
|
||||
|
||||
The semantic diff panel is intended to be the default landing view when sem is available. The existing `All files` panel remains available directly underneath it in the file tree.
|
||||
|
||||
## Main User Flow
|
||||
|
||||
1. The review server creates or updates `currentPatch`.
|
||||
2. The server chooses a semantic diff cwd:
|
||||
- workspace root for workspace reviews
|
||||
- PR worktree/local checkout if present
|
||||
- local Git/JJ repo cwd when available
|
||||
- neutral scratch directory for patch-only reviews
|
||||
3. The server runs `sem diff --patch --format json` with `currentPatch` on stdin.
|
||||
4. The server parses sem JSON into `SemanticDiffResponse`.
|
||||
5. The UI fetches `/api/semantic-diff`.
|
||||
6. The semantic panel renders file groups and entity rows.
|
||||
7. Clicking a semantic row opens the existing diff file view and selects the relevant line range.
|
||||
|
||||
The important architectural rule is:
|
||||
|
||||
```txt
|
||||
review mode -> currentPatch -> sem diff --patch -> semantic overview UI
|
||||
```
|
||||
|
||||
Local code improves cwd/blob resolution, but patch-only mode still works from hunk content.
|
||||
|
||||
## How It Was Built
|
||||
|
||||
### Shared Sem Runner
|
||||
|
||||
Source:
|
||||
|
||||
- `packages/shared/semantic-diff.ts`
|
||||
- `packages/shared/semantic-diff-types.ts`
|
||||
- `packages/shared/semantic-diff.test.ts`
|
||||
|
||||
Responsibilities:
|
||||
|
||||
- Resolve the sem binary.
|
||||
- Prefer `PLANNOTATOR_SEM_PATH` when explicitly configured.
|
||||
- Prefer the managed Plannotator sidecar under the user data dir.
|
||||
- Fall back to PATH only after managed sem.
|
||||
- Avoid executing repo-local sem packages from reviewed code.
|
||||
- On Windows, do not spawn bare `sem`; require an absolute resolved `sem.exe`, managed sem, or explicit env path.
|
||||
- Run `sem diff --patch --format json`.
|
||||
- Normalize optional `fileExt` and `fileExts` query filters.
|
||||
- Parse sem JSON into stable Plannotator response types.
|
||||
- Cache responses by patch, cwd, and file extension filter.
|
||||
|
||||
### Bun Review Server
|
||||
|
||||
Source:
|
||||
|
||||
- `packages/server/review.ts`
|
||||
- `packages/server/review-workspace.test.ts`
|
||||
|
||||
Responsibilities:
|
||||
|
||||
- Advertise semantic diff availability in `/api/diff` and diff-switch responses.
|
||||
- Serve parsed semantic diff from `GET /api/semantic-diff`.
|
||||
- Track the active `currentPatch`.
|
||||
- Resolve semantic cwd independently from agent cwd.
|
||||
- Cache sem availability per cwd.
|
||||
- Cache semantic diff results for the active patch.
|
||||
|
||||
### Pi/Node Review Server Mirror
|
||||
|
||||
Source:
|
||||
|
||||
- `apps/pi-extension/server/serverReview.ts`
|
||||
- `apps/pi-extension/server.test.ts`
|
||||
- `apps/pi-extension/vendor.sh`
|
||||
|
||||
Responsibilities:
|
||||
|
||||
- Mirror the Bun server semantic diff behavior.
|
||||
- Vendor shared semantic diff modules into `apps/pi-extension/generated/`.
|
||||
- Keep route parity for `/api/semantic-diff`.
|
||||
|
||||
### GitHub and GitLab PR Inputs
|
||||
|
||||
GitHub source:
|
||||
|
||||
- `packages/shared/pr-github.ts`
|
||||
|
||||
GitLab source:
|
||||
|
||||
- `packages/shared/pr-gitlab.ts`
|
||||
- `packages/shared/pr-gitlab.test.ts`
|
||||
|
||||
Important GitLab note:
|
||||
|
||||
- GitLab now uses `raw_diffs`, not reconstructed JSON diffs.
|
||||
- This preserves collapsed/generated file content and binary diff markers.
|
||||
- Public GitLab fixture testing showed JSON reconstruction missed binary changes and could omit collapsed generated files.
|
||||
|
||||
## Frontend Asset Map
|
||||
|
||||
### Review App Entrypoints
|
||||
|
||||
- `apps/review/index.html`
|
||||
- `apps/review/index.tsx`
|
||||
- `apps/review/vite.config.ts`
|
||||
- `apps/review/dist/index.html` after build
|
||||
|
||||
The review app imports the review editor package and builds a single-file review UI.
|
||||
|
||||
### Hook App Bundled Review HTML
|
||||
|
||||
- `apps/hook/index.html`
|
||||
- `apps/hook/index.tsx`
|
||||
- `apps/hook/vite.config.ts`
|
||||
- `apps/hook/dist/review.html` after build
|
||||
|
||||
`apps/hook/dist/review.html` is the bundled review editor HTML copied from the review build during hook build.
|
||||
|
||||
### Main Review UI Wiring
|
||||
|
||||
- `packages/review-editor/App.tsx`
|
||||
|
||||
Key responsibilities:
|
||||
|
||||
- Tracks `semanticDiffAvailable`.
|
||||
- Opens semantic diff as the initial default panel when advertised.
|
||||
- Falls back to `All files` if initial semantic load errors.
|
||||
- Applies semantic diff availability updates after diff switches and PR switches.
|
||||
- Passes semantic diff state and handlers through `ReviewStateContext`.
|
||||
|
||||
### Semantic Diff Panel
|
||||
|
||||
- `packages/review-editor/dock/panels/ReviewSemanticDiffPanel.tsx`
|
||||
|
||||
Key responsibilities:
|
||||
|
||||
- Fetches `GET /api/semantic-diff`.
|
||||
- Handles loading, empty, error, unavailable, and ready states.
|
||||
- Groups semantic changes by file path.
|
||||
- Renders the terminal-like semantic diff rows.
|
||||
- Opens the existing diff file panel when a row is clicked.
|
||||
- Converts semantic line metadata into Plannotator line selection.
|
||||
|
||||
### Dockview Registration
|
||||
|
||||
- `packages/review-editor/dock/reviewPanelTypes.ts`
|
||||
- `packages/review-editor/dock/reviewPanelComponents.ts`
|
||||
- `packages/review-editor/dock/ReviewStateContext.tsx`
|
||||
|
||||
Key responsibilities:
|
||||
|
||||
- Defines `REVIEW_PANEL_TYPES.SEMANTIC_DIFF`.
|
||||
- Defines `REVIEW_SEMANTIC_DIFF_PANEL_ID`.
|
||||
- Registers `ReviewSemanticDiffPanel` as a Dockview component.
|
||||
- Exposes semantic diff state and callbacks to panel components.
|
||||
|
||||
### Left File Tree Entry
|
||||
|
||||
- `packages/review-editor/components/FileTree.tsx`
|
||||
|
||||
Key responsibilities:
|
||||
|
||||
- Shows the `Semantic diff` navigation entry above `All files`.
|
||||
- Only shows it when `semanticDiffAvailable` is true.
|
||||
- Keeps file selection inactive while semantic diff or all-files overview is active.
|
||||
|
||||
### PR Switch Hook Type Wiring
|
||||
|
||||
- `packages/review-editor/hooks/usePRStack.ts`
|
||||
|
||||
Key responsibilities:
|
||||
|
||||
- Carries semantic diff advert data through PR scope/switch responses.
|
||||
- Uses shared `SemanticDiffAdvert` from `@plannotator/shared/semantic-diff-types`.
|
||||
|
||||
### Semantic Diff Styles
|
||||
|
||||
- `packages/review-editor/index.css`
|
||||
|
||||
Relevant CSS block:
|
||||
|
||||
- `.semantic-diff-panel`
|
||||
- `.semantic-diff-terminal`
|
||||
- `.semantic-diff-file`
|
||||
- `.semantic-diff-row`
|
||||
- `.semantic-diff-symbol-*`
|
||||
- `.semantic-diff-summary`
|
||||
- `.semantic-diff-retry`
|
||||
- `.semantic-diff-loading`
|
||||
- `.semantic-diff-error`
|
||||
- `.semantic-diff-empty`
|
||||
|
||||
The styling intentionally mirrors sem's terminal output shape: file boxes, pipe glyphs, change symbols, entity type, entity name, and status label.
|
||||
|
||||
## API Surface
|
||||
|
||||
### `GET /api/diff`
|
||||
|
||||
Now includes:
|
||||
|
||||
```ts
|
||||
semanticDiff?: {
|
||||
available: boolean;
|
||||
semVersion?: string;
|
||||
semSource?: string;
|
||||
}
|
||||
```
|
||||
|
||||
### `GET /api/semantic-diff`
|
||||
|
||||
Returns one of:
|
||||
|
||||
- `SemanticDiffOkResponse`
|
||||
- `SemanticDiffUnavailableResponse`
|
||||
- `SemanticDiffErrorResponse`
|
||||
|
||||
Optional query filters:
|
||||
|
||||
- `?fileExt=.ts`
|
||||
- `?fileExts=.ts,.tsx`
|
||||
|
||||
### Diff Switch and PR Switch Responses
|
||||
|
||||
These responses also include the semantic diff advert when available:
|
||||
|
||||
- `/api/diff/switch`
|
||||
- `/api/pr-diff-scope`
|
||||
- `/api/pr-switch`
|
||||
|
||||
## Install And Binary Behavior
|
||||
|
||||
Installer changes install sem as an optional sidecar dependency. Semantic diff is non-fatal:
|
||||
|
||||
- If sem is available, the semantic diff UI can open.
|
||||
- If sem is unavailable, Plannotator hides/falls back to the existing all-files diff path.
|
||||
- If sem errors during initial auto-open, the UI falls back to `All files`.
|
||||
|
||||
Relevant installer files:
|
||||
|
||||
- `scripts/install.sh`
|
||||
- `scripts/install.ps1`
|
||||
- `scripts/install.cmd`
|
||||
|
||||
Managed sem path:
|
||||
|
||||
```txt
|
||||
<plannotator data dir>/vendor/sem/<version>/sem
|
||||
<plannotator data dir>/vendor/sem/<version>/sem.exe
|
||||
```
|
||||
|
||||
## Review Modes Covered
|
||||
|
||||
### Local Git/JJ
|
||||
|
||||
Uses the local repo cwd and active VCS patch.
|
||||
|
||||
### Workspace / Multi-Repo
|
||||
|
||||
Aggregates child repo patches with workspace-prefixed paths, then runs sem from the workspace root. Sem can fall back to hunk content when child repo blob SHAs are not resolvable from the parent.
|
||||
|
||||
### GitHub PR
|
||||
|
||||
Uses `gh pr diff` patch text. If local checkout/worktree exists, semantic diff runs from that cwd. Otherwise it runs from scratch.
|
||||
|
||||
### GitLab MR
|
||||
|
||||
Uses GitLab `raw_diffs` via `glab api`, preserving raw unified patch text and binary markers.
|
||||
|
||||
### PR Full-Stack
|
||||
|
||||
Requires local checkout/worktree to create the full-stack patch. Once `currentPatch` exists, semantic diff uses the same pipeline.
|
||||
|
||||
### Raw / Shared / Patch-Only
|
||||
|
||||
Runs sem from a neutral scratch cwd with patch text on stdin.
|
||||
|
||||
## Verification Run
|
||||
|
||||
Latest local verification after the final hardening pass:
|
||||
|
||||
```sh
|
||||
bun test
|
||||
# 1357 pass, 0 fail
|
||||
|
||||
bunx tsc --noEmit -p packages/shared/tsconfig.json
|
||||
bunx tsc --noEmit -p packages/server/tsconfig.json
|
||||
bunx tsc --noEmit -p packages/ui/tsconfig.json
|
||||
bunx tsc --noEmit -p apps/pi-extension/tsconfig.json
|
||||
|
||||
bun run build:pi
|
||||
|
||||
git diff --check
|
||||
```
|
||||
|
||||
All passed.
|
||||
|
||||
## Useful Public GitLab Fixtures
|
||||
|
||||
These were used to validate GitLab patch behavior without running the full app:
|
||||
|
||||
- Normal TypeScript: `https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/merge_requests/3226`
|
||||
- Renamed TypeScript: `https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/merge_requests/3220`
|
||||
- Rename plus new TypeScript: `https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/merge_requests/3059`
|
||||
- TS plus Vue: `https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/merge_requests/3176`
|
||||
- Binary marker: `https://gitlab.com/gitlab-org/gitlab-ui/-/merge_requests/4794`
|
||||
- Binary add/delete: `https://gitlab.com/gitlab-org/gitlab-ui/-/merge_requests/4448`
|
||||
|
||||
## Current Known Tradeoffs
|
||||
|
||||
- Workspace semantic diff runs once against the aggregated workspace patch. This is simple and works for normal hunk-backed changes, but a future precision improvement could run sem per child repo and merge/prefix the semantic results.
|
||||
- Checkout-less PR and raw-patch reviews rely on hunk content rather than local blob resolution. This is expected and still useful.
|
||||
- Sem language coverage is controlled by sem itself. Unsupported file extensions can still fall back to chunk-style behavior inside sem.
|
||||
|
||||
## Final PR State At Handoff
|
||||
|
||||
PR:
|
||||
|
||||
```txt
|
||||
https://github.com/backnotprop/plannotator/pull/871
|
||||
```
|
||||
|
||||
Implementation head before this handoff doc was added:
|
||||
|
||||
```txt
|
||||
13d44b02d6cf6c1fd050cbf552bd494f2a729e5a
|
||||
```
|
||||