* fix(review): detect JJ mutable line-of-work base Use JJ's mutable-stack revset to find the line boundary directly instead of inferring a parent from bookmark ordering, which is ambiguous because JJ has no current bookmark. * fix(review): harden the JJ line-of-work base inference Maintainer follow-up on the line-of-work base detection. Skip the bookmarks `jj git push --change` generates. They name one change, not a line of work, and they do reach the fork point: a colleague's pushed change bookmark arrives as an untracked remote bookmark, which makes its commit immutable and therefore a candidate base, so the reviewer was told they were comparing against `push-vmopwunwxopv@origin`. The commit id is used instead. Pass a full commit id through `jjCompareTargetRevset` as a revision. It has no separators, so the commit-id fallback was being wrapped as `bookmarks(exact:"<sha>")`, which resolves to no revisions and made the whole Line of work diff fail. Fall back to `trunk()` instead of throwing. The only live caller is `getJjContext` on the review startup path, which has no handler above it, so a throw aborted `plannotator review` with a stack trace before the server was built rather than reporting anything. That also covers a `jj` too old for `fork_point`/`reachable`. Make the query explicitly single-record with `latest(..., 1)`. The parser reads one record, and bookmark preference (remote before local) is only meaningful within one commit, so the tie-break belongs in the revset rather than in a silent "first row wins" slice. Isolate the real-jj test behind its own JJ_CONFIG. It was reading the developer's real config, where `[signing] behavior = "own"` alone makes it fail with a GPG error. Live fixtures cover the generated-push-bookmark stack, the untracked remote push bookmark, and a stacked local bookmark. --------- Co-authored-by: Michael Ramos <mdramos8@gmail.com>
Tests
This directory contains manual testing scripts for Plannotator.
Manual Browser UI Smokes (tests/manual/local/)
These are local-only scripts for launching Plannotator UI flows with fixture data so you can manually verify them in a browser. They are not automated CI tests.
Plan review UI smoke tests:
./tests/manual/local/test-hook.sh # Claude Code simulation
./tests/manual/local/test-hook-2.sh # OpenCode origin badge test
./tests/manual/local/test-codex-plan-review-e2e.sh # Real Codex Stop-hook flow in disposable HOME
Code review UI:
./tests/manual/local/test-opencode-review.sh # Code review UI test
./tests/manual/local/test-worktree-review.sh # Worktree support test (creates sandbox with 4 worktrees)
See UI-TESTING.md for detailed UI testing documentation.
The end-to-end, user-centered Vim controls matrix lives in manual/vim-ux-smoke.md. It covers real Markdown and raw-HTML navigation, selection, annotation, focus recovery, HUD behavior, and native-control compatibility.
Integration & Utility Tests (manual/local/)
These scripts test integrations, releases, and provide utilities.
Binary release testing:
./tests/manual/local/test-binary.sh # Test installed binary from ~/.local/bin/
Tests the installed plannotator binary to verify releases work correctly.
Bulk plan testing (Obsidian integration):
./tests/manual/local/test-bulk-plans.sh # Iterate through ~/.claude/plans/
Opens each .md file from ~/.claude/plans/ in Plannotator. Great for testing Obsidian integration with multiple
plans.
OpenCode integration sandbox:
./tests/manual/local/sandbox-opencode.sh [--disable-sharing] [--keep] [--no-git]
Creates a temporary sandbox with a sample React/TypeScript project, initializes git with uncommitted changes, sets up the local OpenCode plugin, and launches OpenCode for full integration testing.
Options:
--disable-sharing: Createsopencode.jsonwith sharing disabled--keep: Don't clean up sandbox on exit--no-git: Skip git initialization (tests non-git fallback)
Codex Stop-hook end-to-end harness:
./tests/manual/local/test-codex-plan-review-e2e.sh [--keep] [--skip-build]
Builds the hook and review apps, creates a disposable HOME plus sample git repo, copies your Codex auth.json,
enables hooks, and runs a real codex exec against the sample project. The script writes logs, rollout paths,
history indices, and session URLs into an artifact directory under the temp root.
Tips:
- Set
PLANNOTATOR_BROWSER=/usr/bin/truewhen you want to drive the opened plan-review session with Playwright instead of auto-opening a browser. - The validated workflow is: run the script in one terminal, then point Playwright at the printed session URL from a second terminal.
Obsidian utility:
./tests/manual/local/fix-vault-links.sh /path/to/vault/plannotator
Adds Obsidian backlinks ([[Plannotator Plans]]) to existing plan files in your vault.
SSH Remote Testing (manual/ssh/)
Tests SSH session detection and port forwarding for remote development scenarios.
cd tests/manual/ssh/
docker-compose up -d
./test-ssh.sh
See manual/ssh/DOCKER_SSH_TEST.md for detailed setup instructions.