570 Commits

Author SHA1 Message Date
Michael Ramos 9bf46e11f3 chore: bump version to 0.24.2 2026-07-21 13:10:42 -07:00
Michael Ramos 8e27a25d31 fix(review): expand collapsed guide files when jumping via section file chips (#1103)
Guide section file chips scrolled directly to the target diff card, so a
file collapsed by marking it viewed landed on its bare header with no code.
Route the chip click through the existing guideRevealFile channel (the same
path used by sidebar annotation clicks and AI line citations) via a new
onGuideRevealFile setter on ReviewState, so the target expands, focuses,
and scrolls in the same order as the other two jump paths.
2026-07-21 13:08:09 -07:00
Michael Ramos 5ef89a0a2e fix(config): coerce quoted boolean strings in config.json resolvers (#1102)
~/.plannotator/config.json is hand-edited, so boolean settings often
arrive as quoted strings ("cursorSandbox": "false"). The resolvers
passed the raw JSON value through, so a quoted "false" reached strict
=== false checks downstream as a string and silently kept the default
behavior. Concretely, the Cursor sandbox opt-out added for NixOS users
in #1095 did nothing when set via config.json with quotes, even though
the equivalent env var accepts the string form.

Add a coerceConfigBoolean helper and apply it to the config-file branch
of resolveUseGlimpse, resolveAnnotateHistory, resolveUseJina, and
resolveCursorSandbox. Real booleans pass through, "true"/"false"/
"1"/"0" strings (any case) coerce, and anything else falls back to
the default. Env-var branches and their precedence are unchanged.
resolveSharingEnabled is left alone: it is keyed on the string sentinel
"disabled" and already fails safe.

Pi picks the fix up automatically via apps/pi-extension/vendor.sh.
2026-07-21 13:08:06 -07:00
Michael Ramos f9a6c1e39d feat: annotate accepts YAML, JSON, TOML and other plain-text files (#1099)
* feat(annotate): accept common plain-text config formats (.yaml, .json, .toml, …)

Annotate previously rejected every file that wasn't .md/.mdx/.txt (or
.html/.htm), even though the pipeline reads files as UTF-8 text and
renders anything. Widen the accepted set to unambiguously plain-text
config/data formats: .yaml .yml .json .jsonc .json5 .toml .ini .cfg
.conf .properties .csv .tsv .log .xml .env.example. They render exactly
the way .txt renders today.

- New single source of truth: packages/core/annotatable.ts
  (ANNOTATABLE_TEXT_REGEX / ANNOTATABLE_DOC_REGEX + predicates),
  re-exported through @plannotator/shared/resolve-file and vendored into
  the Pi extension.
- .env stays excluded (commonly holds secrets; annotate history copies
  file contents into the data dir). Source-code extensions stay with
  code review.
- Single-file accept + bare-filename fuzzy search widen in
  resolveMarkdownFile; folder discovery and the file-browser listing
  widen in all three runtimes (hook CLI, OpenCode, Pi).
- /api/doc gains a `doc=1` param set by the file browser so extensions
  that overlap CODE_FILE_REGEX (.yaml/.json/.toml/.ini/.xml) render as
  annotatable documents there while code-file links inside documents
  keep the syntax-highlighted popout.
- Error messages now list the wider set; docs updated (AGENTS.md,
  marketing annotate page).

Closes #1029

Claude-Session: https://claude.ai/code/session_01YXkgsNucxDwAL4GdR4XYRk

* fix(annotate): frontmatter, size caps, edit-guard, and skill docs from review

Review fixes for #1099:

- Frontmatter: `--- … ---` stripping is a markdown convention; for
  non-markdown annotatable sources (multi-document YAML, .txt starting
  with ---) the delimiters are real content. parseMarkdownToBlocks gains
  a { frontmatter } option and the editor keys it off the active
  document's path via shouldStripFrontmatter() (strip for .md/.mdx and
  pathless/converted sources; keep raw for other annotatable text).
- Size caps: new shared MAX_ANNOTATABLE_FILE_BYTES (2MB — same limit the
  code-file popout always had) now guards the annotate CLI single-file
  read in all three runtimes and the /api/doc document branches in both
  servers. Also applies to .md/.txt (behavior change for pathological
  inputs; previously unbounded).
- Editing guard: mid-edit file opens gate on isSourceSaveFilePath
  (.md/.mdx/.txt) instead of the wider annotatable set — config files
  are view-only, so switching to one mid-edit no longer silently
  downgrades "Done editing" to feedback-only edits.
- Skill docs: plannotator-annotate SKILL.md (core + Kiro) now mention
  the plain-text config formats.

Claude-Session: https://claude.ai/code/session_01YXkgsNucxDwAL4GdR4XYRk
2026-07-20 15:33:42 -07:00
Michael Ramos 6fbf0ef560 fix: align Codex model catalog and reasoning efforts with the current Codex CLI (#1096)
* fix(agents): align Codex model catalog and reasoning efforts with Codex CLI 0.144

- Remove gpt-5.3-codex from the Codex model picker: saved picks of it are
  already force-migrated to the fallback (ChatGPT-account Codex rejects it),
  so offering it was incoherent. The 5.2/5.1 family stays — those models
  remain available to API-key Codex users.
- Per-model reasoning-effort gating: the catalog (now in
  packages/ui/utils/codexModels.ts, re-exported from AgentsTab) carries each
  model's supported efforts and default effort from the CLI catalog. The
  reasoning pickers only offer the selected model's efforts, including the
  new max/ultra tiers on the GPT-5.6 family, and useAgentSettings clamps an
  unsupported saved effort to the model's catalog default before it reaches
  the pickers or a launch payload.
- Drop `minimal` everywhere: no current Codex model supports it. Saved
  perModel reasoning entries migrate minimal -> low, and the guide repair
  launch no longer hardcodes it.
- Ask AI: bump the codex-app-server static fallback model and DEFAULT_MODEL
  from gpt-5.4 to gpt-5.6-sol (runtime model/list discovery still replaces
  the fallback and already carries per-model efforts; added Max/Ultra labels).

Claude-Session: https://claude.ai/code/session_01YXkgsNucxDwAL4GdR4XYRk

* fix(agents): prune API-shut-down Codex models per OpenAI deprecations

OpenAI's API deprecations page schedules an API-level shutdown on
2026-07-23 for gpt-5.2-codex (-> gpt-5.5), gpt-5.1-codex-max (-> gpt-5.5),
and gpt-5.1-codex-mini (-> gpt-5.4-mini) — dead for ALL auth modes, not
just ChatGPT accounts — so they leave the picker and saved picks migrate:
the first two to the surface fallback (already gpt-5.5), codex-mini to
gpt-5.4-mini with its perModel preference carried under the new key (same
pattern as the gpt-5.6 -> gpt-5.6-sol rename).

gpt-5.2 stays selectable with no migration: it was retired from the
ChatGPT product (steered to 5.5) but the API still serves it, so API-key
Codex users retain it.

Claude-Session: https://claude.ai/code/session_01YXkgsNucxDwAL4GdR4XYRk
2026-07-20 11:54:09 -07:00
Michael Ramos 461ab64f92 feat(ui): soften pinpoint hover feedback (#1097) 2026-07-20 11:35:02 -07:00
Jos Dirksen 9ee7cb48ac fix(review): Collapse viewed files in guided review (#1068)
* fix(review): collapse viewed guided files

* fix(review): expand a collapsed guide file when a sidebar jump targets it

The per-file viewed-collapse unmounts the diff body, so an annotation click
or AI line citation targeting a collapsed file would scroll to the section
but silently fail to reveal the line. Mirror GuideSectionCard's token-keyed
reveal effect at the file level.

Claude-Session: https://claude.ai/code/session_01YXkgsNucxDwAL4GdR4XYRk

---------

Co-authored-by: Michael Ramos <mdramos8@gmail.com>
2026-07-20 11:32:51 -07:00
Raúl a5c701db01 fix(review): use canonical GPT-5.6 Sol model ID (#1076)
Migrate saved review, tour, and guide Codex preferences from gpt-5.6 to gpt-5.6-sol so existing selections continue to launch.
2026-07-20 10:58:34 -07:00
Michael Ramos 9ddb87abb4 feat(data-dir): fall back to $XDG_DATA_HOME/plannotator when ~/.plannotator does not exist (#1093)
New resolution order for the Plannotator data directory:

  1. PLANNOTATOR_DATA_DIR (unchanged, top priority, ~ expansion)
  2. ~/.plannotator when it already exists (legacy default — existing
     installs never move)
  3. $XDG_DATA_HOME/plannotator when XDG_DATA_HOME is set to a
     non-empty absolute path
  4. ~/.plannotator (default for everyone else)

This is git's legacy-first pattern: the XDG branch only fires for fresh
installs whose user has explicitly set XDG_DATA_HOME. The XDG spec's
implicit ~/.local/share default is deliberately NOT applied, and the
directory stays monolithic (no config/data/cache split).

Mirrored in every private copy of the resolver: the Amp plugin,
scripts/install.sh, scripts/install.ps1, and scripts/install.cmd. The
Pi runtime picks the change up automatically via vendor.sh. Docs updated
in README.md, AGENTS.md/CLAUDE.md, and the marketing env-var reference.

Claude-Session: https://claude.ai/code/session_01YXkgsNucxDwAL4GdR4XYRk
2026-07-20 08:55:12 -07:00
Michael Ramos c645999761 fix(review): allow disabling Cursor sandbox via PLANNOTATOR_CURSOR_SANDBOX for systems where it cannot start (#1095)
The Cursor review engine hardcodes `--sandbox enabled` when launching the
`agent` CLI. On systems where Cursor's sandbox cannot start (NixOS,
AppArmor-restricted Linux) that hard-fails every job with "Sandbox mode is
enabled but not available on this system", and the flag overrides the
user's own `agent sandbox disable` configuration.

Default is unchanged: review jobs still pass `--sandbox enabled` as part
of their read-only posture. Setting PLANNOTATOR_CURSOR_SANDBOX=0 (or
`{ "cursorSandbox": false }` in ~/.plannotator/config.json; the env var
wins) omits the flag pair entirely — never `--sandbox disabled` — so the
user's own Cursor Agent sandbox configuration governs. Resolution follows
the established env-plus-config pattern via resolveCursorSandbox() in
packages/shared/config.ts, applied at the buildMarkerCommand call sites in
both the Bun server (review.ts, guide-review.ts) and the Pi server
(serverReview.ts; guide-review is vendored, with the new ../config import
rewritten in vendor.sh).

Closes #1094

Claude-Session: https://claude.ai/code/session_01YXkgsNucxDwAL4GdR4XYRk
2026-07-20 08:54:43 -07:00
Michael Ramos 2594b374d2 chore: bump version to 0.24.1
Claude-Session: https://claude.ai/code/session_01YXkgsNucxDwAL4GdR4XYRk
2026-07-20 01:56:34 -07:00
Michael Ramos 8a6288b9fe fix(annotate): resolve explicit ../ paths that escape the project root
plannotator annotate ../docs/plan.md failed with a misleading 'File type
not supported: .md' because resolveMarkdownFile rejected any relative path
resolving outside the project root, even when the file existed and was a
supported type. The CLI then found the file on disk and mislabeled the
resolver miss as a type error.

An explicit path the user types (one containing a separator, including ../)
is now honored when it exists, matching the trust already given to absolute
paths. Bare filenames stay restricted to the in-root fuzzy search, so a
stray notes.md cannot resolve into a parent directory.

Closes #1085.

Claude-Session: https://claude.ai/code/session_01YXkgsNucxDwAL4GdR4XYRk
2026-07-20 01:55:10 -07:00
Michael Ramos a9e608d7b6 chore: bump version to 0.24.0
Claude-Session: https://claude.ai/code/session_01YXkgsNucxDwAL4GdR4XYRk
2026-07-19 22:50:01 -07:00
Michael Ramos e27771eb71 fix: bound workspace repo discovery so symlink escapes can't stall startup
Workspace discovery follows symlinks since #1060, which means the walk can
leave the workspace root by design. A link into a huge unrelated tree was
enumerated synchronously before the server bound its port, hanging startup
with no output. The walk now shares the PLANNOTATOR_FILE_BROWSER_MAX_FILES
budget: it visits at most that many directories and returns what it found.
Symlinked repos are still discovered under the default budget.

Claude-Session: https://claude.ai/code/session_01YXkgsNucxDwAL4GdR4XYRk
2026-07-19 22:47:46 -07:00
Michael Ramos 98fa3b2173 Restore production Totman favicon (#1081) 2026-07-19 13:07:34 -07:00
Michael Ramos d5f8676def Merge pull request #1030 from leoreisdias/feat/add-review-comment-expand-modal
feat(review): Add expanded review comment editor
2026-07-18 19:52:58 -07:00
Michael Ramos 324bb5f095 fix(review): make header responsive (#1073) 2026-07-17 21:51:17 -07:00
Michael Ramos fa294b12e4 feat(review): add PR and MR artifact gallery (#1055)
Adds a first-class artifact gallery and annotation workflow for GitHub pull requests and GitLab merge requests, including images, GIFs, video timestamps, rendered HTML, Markdown, provenance-aware feedback, authenticated provider resources, and reliable CDN/media handling.
2026-07-17 21:25:23 -07:00
Michael Ramos ef9b8e1c9e Place open-in selector after file context (#1072) 2026-07-17 20:55:43 -07:00
Michael Ramos 8597ca3563 Use the tight-fit Totman favicon (#1071) 2026-07-17 19:14:23 -07:00
Michael Ramos cb9a59856c fix(review): harden expanded comment editor 2026-07-17 07:57:15 -07:00
Leonardo R. Dias 267e42d62b Add expanded review comment editor 2026-07-17 07:57:15 -07:00
Michael Ramos 56df64c751 Add modern GitButler review support (#1067)
Adds current-architecture GitButler workspace, stack, and branch review support across Bun and Pi while preserving the existing Git, JJ, and P4 paths.

Co-authored-by: Dan Susman <56033661+dansusman@users.noreply.github.com>
2026-07-17 07:37:50 -07:00
Michael Ramos 95ac6cd2f8 Use the production Totman favicon (#1066) 2026-07-16 16:04:01 -07:00
Michael Ramos 0d5d1fc628 fix: surface Pi provider errors in reviews (#1061) 2026-07-16 14:15:31 -07:00
Michael Ramos 467c11b29f fix: discover symlinked workspace repositories (#1060) 2026-07-16 14:15:27 -07:00
Michael Ramos d0665571c7 Fix OpenCode plan review cancellation cleanup (#1064) 2026-07-16 14:15:23 -07:00
Michael Ramos 8e9a359a8f fix(review): make remote discovery noninteractive (#1062) 2026-07-16 14:15:11 -07:00
Michael Ramos 60b5e8d31a Narrow review feedback validation to submitted findings (#1065) 2026-07-16 14:15:07 -07:00
iury souza 13309e322b feat(server): support bounded port ranges (#1042)
* feat(server): support bounded port ranges

* fix(server): harden bounded port retries

* fix(server): preserve non-range port behavior

---------

Co-authored-by: Michael Ramos <mdramos8@gmail.com>
2026-07-16 06:31:52 -07:00
buihongduc132 5b2756b0c7 fix(server): return JSON 404 for unknown /api/* routes instead of HTML (#748)
* fix(server): return JSON 404 for unknown /api/* routes instead of HTML

All three servers (plan, review, annotate) serve the SPA HTML for any
unmatched route. This means hitting /api/nonexistent returns the full
HTML page with 200 OK — confusing for API clients and wasteful.

Now unknown /api/* paths get a proper JSON 404 response before the SPA
fallback kicks in. Non-API paths (like /some/random/path) still serve
HTML for SPA routing as before.

Tested on all three server types.

* fix(server): guard unknown API routes across runtimes

---------

Co-authored-by: buihongduc132 <buihongduc132@gmail.com>
Co-authored-by: Michael Ramos <mdramos8@gmail.com>
2026-07-16 06:31:30 -07:00
Vladyslav Hrabovyi 92c311ab1d fix(review): show System theme coherently across UI (#1015)
Use one shared Light/Dark/System registry across review, plan, annotate, Settings, and published UI consumers. Preserve the public Mode contract, scope wider menu geometry to theme pickers, and keep constrained palettes coherent in rendering and previews.

Co-authored-by: Vladyslav Hrabovyi <vladyslav.hrabovyii@gmail.com>
Co-authored-by: sasha <kredich05@gmail.com>
2026-07-15 22:39:52 -07:00
Michael Ramos 29513e1984 chore: bump version to 0.23.1
Claude-Session: https://claude.ai/code/session_01K9G9vurTg1v5uD37GbDMpP
2026-07-12 14:37:49 -07:00
Dillon Mulroy 1f70937d51 fix(ui): keep Ask AI input visible after responses (#1035)
* fix(ui): keep Ask AI input visible after responses

Long completed responses caused the h-full chat flex item to retain its automatic minimum height, pushing the follow-up composer below the sidebar viewport. Let the panel consume the remaining flex space with min-h-0 so only the message area scrolls.

* chore: remove Ask AI browser harness
2026-07-10 17:02:38 -07:00
Michael Ramos 7f0c36028b fix(server): bound startup file discovery (#1036)
* fix(server): bound startup file discovery (#978)

* test: observe the server's own warm cache key so the ordering tests actually pin the fix

Review finding: both bind-before-warm ordering tests raced against
observeWarmState(projectRoot), but on macOS mkdtempSync returns /var/...
while the chdir'd server warms under the realpath /private/var/... —
a different warmFileListCache key. The tests therefore raced a FRESH
warm (always pending at observation time) and passed on the OLD broken
code too. Observing process.cwd() inside onReady uses the server's real
key. Verified: with old resolve-file/server code checked out, all four
ordering tests now fail; on the fix they pass (17/17 across both files).

Claude-Session: https://claude.ai/code/session_01SFy9fY27SA8g5BtotWPi1G
2026-07-10 10:18:01 -07:00
Michael Ramos 69ca6d546c chore: bump version to 0.23.0
Claude-Session: https://claude.ai/code/session_01SFy9fY27SA8g5BtotWPi1G
2026-07-10 08:35:21 -07:00
Michael Ramos 977f4ce582 fix: final QA sweep fixes — file-browser cap priority, OpenCode project scoping, spotlight Alt-Alt dismiss
Fixes for the three-agent adversarial sweep findings:

- reference-handlers.ts: seed the user's modified/untracked files BEFORE
  the bulk walk — the 5000-file cap (d3c9de1e) filled in raw readdir order
  and could silently drop the exact files the user just edited from the
  annotate browser (and the truncated latch broke the merge loop on its
  first iteration).
- opencode commands.ts: pass `project` to startAnnotateServer at both
  call sites (annotate + annotate-last) via detectProjectName, matching
  the hook and Pi runtimes — OpenCode annotate history no longer lands in
  the shared "_unknown" bucket.
- App.tsx: the Alt-Alt destination double-tap now dismisses the
  DestinationSpotlight — the coachmark advertised that exact gesture but
  its own keydown handler deliberately ignores modifiers, so performing
  the tip left the dim overlay stranded.
- annotate.ts + pi mirror: degradation notice now reads "warning: annotate
  history unavailable" so OpenCode's logCliWarnings forwarder (which
  filters on \bwarn(ing)?\b) actually surfaces it.
- cli-bridge.ts: a rejected showToast un-marks the URL (the other delivery
  path can retry) and logs the failure instead of being fully silent.
- test.yml: register packages/editor/editableDocumentsHook.test.tsx (7
  draft/conflict tests, DOM-gated since #936, never ran in CI). Repo-wide
  sweep confirms all 19 DOM-gated test files are now registered.

Gates: DOM batch 102/0 across 19 files, review+server 507/0, opencode 70/0,
install harness 85/0, full typecheck incl. strict-consumer, review build OK.

Claude-Session: https://claude.ai/code/session_01SFy9fY27SA8g5BtotWPi1G
2026-07-10 06:50:40 -07:00
Michael Ramos abceed3f0b chore(server): align annotate-history degradation log with the [plannotator] prefix convention
Claude-Session: https://claude.ai/code/session_01SFy9fY27SA8g5BtotWPi1G
2026-07-10 06:19:59 -07:00
Michael Ramos f022cf2302 fix(review): spotlight re-measures on header reflow, yields to keyboard use, fixes GitLab article
Adversarial self-review findings on 1f7d08f5: (1) the cutout was measured
once + on window resize only, so async header siblings (platform error
banner, partial-diff notice) shifting the destination button left the ring
on empty space — now also re-measured on a 250ms interval while the
transient overlay is up. (2) The capture-phase Escape handler plus the z-90
click-trap could strand a keyboard-opened surface (search at z-50) dimmed
and unclickable underneath — now ANY non-modifier keypress dismisses the
spotlight, with only Escape stopping propagation (topmost-overlay
semantics); shortcuts proceed and their surfaces never open under the dim.
(3) "a MR" → "an MR" for GitLab via a vowel-sound article check.

Claude-Session: https://claude.ai/code/session_01SFy9fY27SA8g5BtotWPi1G
2026-07-10 06:19:20 -07:00
Michael Ramos 51710b1804 fix(review): remove automatic platform attribution (#1033)
Co-authored-by: Leonardo R. Dias <47978193+leoreisdias@users.noreply.github.com>
2026-07-10 06:15:41 -07:00
Michael Ramos 7d583df980 fix(server): unwritable data dir degrades annotate/sessions instead of failing startup
QA probe: with PLANNOTATOR_DATA_DIR on a read-only mount, `plannotator
annotate file.md` crashed before the UI opened — twice. (1) #961's
saveToHistory call on annotate open was unguarded, so the new version-diff
enhancement gated startup that was stateless at v0.22.0; now wrapped
(both the Bun server and the Pi mirror) and degrades to no-version-diff
with a stderr notice. (2) registerSession's mkdir/writeFileSync (pre-existing
since #795) threw after the server was already listening; the session
registry only powers `plannotator sessions` discovery, so it is now
best-effort, and unregisterSession/listSessions tolerate an unwritable
sessions dir too. Verified: read-only data dir now starts, serves
/api/plan with no versionInfo, and prints the session URL.

Claude-Session: https://claude.ai/code/session_01SFy9fY27SA8g5BtotWPi1G
2026-07-10 06:07:45 -07:00
Michael Ramos 1f7d08f59a feat(review): one-time spotlight on the PR feedback-destination switcher
First-time PR reviewers get a driver.js-style coachmark (zero new
dependencies: rounded cutout + oversized box-shadow dim, portaled to body)
pointing at the header's Agent/GitHub destination dropdown, explaining that
feedback can post to the PR or go to the agent session and can be switched
at any time (Alt Alt). Cookie-gated one-time flag
(plannotator-review-dest-spotlight-seen, versioned) mirroring the
guide-intro/review-setup gates. Renders strictly after the first-run dialog
chain (guide intro → look-and-feel → review setup) has cleared and only in
PR mode; opening the destination menu organically also marks it seen.
Escape/click-anywhere/Got-it dismiss. GitLab-aware copy via
platformLabel/mrLabel.

Claude-Session: https://claude.ai/code/session_01SFy9fY27SA8g5BtotWPi1G
2026-07-10 06:04:41 -07:00
Michael Ramos e5fcc4153c fix(opencode): surface session URLs via tui.showToast — app.log never reaches the TUI
QA traced the repeatedly-regressed remote-URL invariant to its root cause on
OpenCode: every URL path (logPlannotatorReady, the cli-bridge stderr
forwarder, and the ready-file poller) funneled exclusively through
client.app.log, which OpenCode documents as "write a log entry to the server
logs" — it is never rendered in the TUI. Remote users therefore never saw
the session URL. All three paths now ALSO call tui.showToast (the SDK's
visible surface), best-effort with optional chaining so older hosts without
/tui/show-toast no-op. A shared per-run toastedUrls set dedupes the stderr
and ready-file deliveries so one session never stacks two toasts.

Also: recognize the current binary's "Plannotator session ready" stderr
phrasing in formatUserFacingCliStderrLine (the old "Open this link" match no
longer fires; only the bare-URL line was being forwarded), and add
data-print-hide to the resize-handle cursor tooltip portal so print.css hides
it (QA print-clipping finding).

Claude-Session: https://claude.ai/code/session_01SFy9fY27SA8g5BtotWPi1G
2026-07-10 05:59:45 -07:00
Kushida ee28f1a428 fix: handle Windows install and review edge cases (#1021) 2026-07-10 05:54:19 -07:00
Michael Ramos 4934ab6218 feat(ui): add GPT-5.6 family (sol alias, terra, luna) to the Codex job model catalog
The launchable-jobs Codex catalog (review jobs, tour, guide, GuideEmptyState)
is a hardcoded list, so yesterday's GPT-5.6 release was missing from the
selectors. Ask AI needs no change — the codex-app-server provider discovers
models dynamically via model/list. The server passes -m through verbatim
(codex-review.ts), so the catalog addition is the complete fix. Defaults stay
on gpt-5.5. Also relocks bun.lock's workspace entry for ui 0.28.0 (missed in
the bump commit).

Claude-Session: https://claude.ai/code/session_01SFy9fY27SA8g5BtotWPi1G
2026-07-10 05:51:13 -07:00
BrandonNoad f5390956e5 fix(ui): focus comment textarea reliably via ref callback (#1031)
The CommentPopover focus effect scheduled a setTimeout(0) keyed on [mode],
but in popover mode the textarea only renders after `position` is measured
by a later effect. Whether the 0ms timer fires before or after that commit
is engine-dependent task ordering: Chromium commits the re-render first, so
focus lands; WebKit fires the timer first, so textareaRef.current is still
null and the comment editor opens unfocused (reproduced in a WKWebView host
— the glimpseui integration — where users had to tab or click into the
field for every annotation).

Focus from a ref callback on the textarea instead: it runs exactly when the
element mounts, so there is nothing to race. Mode switches (popover/dialog)
still refocus because the textarea remounts. The deferred focus and
caret-to-end behavior are preserved; isConnected guards the popover closing
before the timer fires.
2026-07-10 05:32:02 -07:00
Yusuf Emre Boyraz 6cf36bd852 fix: disambiguate OpenCode model labels by provider (#1024)
fetchModels() built the dropdown label from the model name alone,
so models with identical names from different providers (e.g.
deepseek-v4-pro via DeepSeek vs. via OpenRouter) were indistinguishable
in the UI even though their ids were already unique.

Fixes #988
2026-07-10 05:31:40 -07:00
Michael Ramos f9d58c1e3e chore(ui): 0.28.0 — frozen markdown diff HANDOFF/README docs (version bumped with the feature)
Documents the 0.28.0 round for the Workspaces consumer: the
components/MarkdownDiff shim (frozen two-revision diff — newer revision as
the real document, deletions projected in place, toolbar/overview/gutter),
the byte contract on MarkdownDiffHandle (exact input strings incl. CRLF),
the frozen state/view edit rejection, and the extensions composition with
its capture-once caveat. Adds the supported-imports row and the 0.28.0
dependency note (wrapper ^0.4.0, engine ^0.8.0, new @codemirror/merge peer).

Publish is manual and owner-gated per HANDOFF (bun pm pack, then
npm publish --provenance, ui only — core is unchanged at 0.22.0).
2026-07-09 23:34:56 -07:00
Michael Ramos 4bbb0f3aff feat(ui): re-export MarkdownDiff through the ui surface (engine 0.8.0 / wrapper 0.4.0)
Adds components/MarkdownDiff.tsx, a theme-bridging shim over
@plannotator/markdown-editor's frozen two-revision diff, mirroring the
MarkdownEditor shim exactly: ThemeProvider mode bridge, plannotator.css
theme import, extensions passthrough (wikiLinks composes), gridEnabled ->
the same design-system card chrome. Hosts import it from
@plannotator/ui/components/MarkdownDiff; AtomicDiffEditor and
@plannotator/atomic-editor stay off the allowlist.

Deps: @plannotator/markdown-editor ^0.4.0, @plannotator/atomic-editor
^0.8.0 (single lockfile copy each), plus @codemirror/merge — the engine's
new required peer — declared directly per the CM6 single-copy discipline.

Tests pin the seam end-to-end: public export surface + types, byte-exact
getMarkdown()/getOriginalMarkdown() incl. CRLF/trailing-space fixtures,
contenteditable="false" frozen contract, change navigation, wiki-link
composition through the shim, and theme/host-class forwarding. The
strict-consumer tsconfig now typechecks the new module.
2026-07-09 23:34:45 -07:00
Michael Ramos 2f1d6a94a9 feat(ui): re-export slashCommands and selectionToolbar through the MarkdownEditor surface 2026-07-09 16:42:46 -07:00