The change ID kpqxywon stays the same even if you:
Rebase onto a different parent
Amend the change
Squash with other changes
Split into multiple changes
This stability makes it perfect for attaching review metadata.
Unified Critique Model
In jjj, code review is attached to solutions, not directly to changes. A solution may have one or more jj changes associated with it. Review requests and critiques are unified into a single model: critiques with a reviewer field.
When you assign reviewers at solution creation (using --reviewer), jjj automatically creates review-type critiques for each reviewer. These critiques must be resolved (typically by addressing them with an LGTM comment) before the solution can be accepted.
Comment Relocation
When code changes, jjj intelligently relocates comments using:
Exact match (fast path): Line number + content hash match
Fuzzy match: Similarity scoring finds new location (70% threshold)
Orphaned: Comment marked as unresolved if context disappears
This is powered by context fingerprinting using SHA-256 hashing.
Basic Workflow
1. Assign Reviewers
You can assign reviewers when creating a solution, or add them later using critiques.
Addressing a review critique is the sign-off. The critique’s resolution records the reviewer’s approval with a timestamp.
4. Author: Respond to Critiques
Check what critiques are open:
Terminal window
jjjcritiquelist--solution"JWT"--statusopen
For each critique, address it, dismiss it, or validate it:
Terminal window
# Fix the issue and mark as addressed
jjjcritiqueaddress"constant-time"
# Or dismiss with explanation
jjjcritiquereply"localStorage""The token is stored in an httpOnly cookie, not localStorage. See the solution's approach section."
jjjcritiquedismiss"localStorage"
After addressing critiques, request re-review if needed by creating a new review critique:
Terminal window
jjjcritiquenew"JWT""Re-review requested after fixes"--reviewer@alice
5. Submit
Once all critiques are resolved and reviews are in, submit the solution:
Terminal window
jjjsubmit
jjj submit checks:
All critiques on the solution are resolved (addressed, dismissed, or validated)
All assigned reviewers have signed off (if reviewers are assigned)
The problem has no open sub-problems (if accepting would solve the parent problem)
If any check fails, submit will explain what is still needed. Use --force to bypass the gates in emergencies (this sets the force_accepted flag on the solution).
Unified Gate to Acceptance
jjj uses a unified critique model where all feedback — including review requests — are critiques:
Critique Type
What it represents
How to resolve
Regular critique
A flaw or issue in the approach
Address, dismiss, or validate
Review critique (has --reviewer)
A review request from a specific person
Reviewer addresses it (LGTM) or raises issues
All critiques must be resolved before a solution can be accepted. Review critiques are resolved when the assigned reviewer addresses them, which serves as the sign-off.
This unified model means:
A solution with any open critique (regular or review) cannot be accepted
Review requests and issue critiques follow the same lifecycle
The --reviewer field distinguishes review requests from issue critiques
Landing Changes
Since jjj decouples review from the forge (GitHub/GitLab), “merging” is updating the main branch.
Direct Landing
Terminal window
# Rebase onto latest main
jjgitfetch
jjrebase-rkpqxywon-dmain
# Advance main bookmark
jjbookmarksetmain-rkpqxywon
# Push
jjgitpush-bmain
jjgitpush-bjjj# Push review metadata
Hybrid Workflow (GitHub/GitLab)
If your team requires Pull Requests for CI gating or compliance:
Push your change as a bookmark:
Terminal window
jjbookmarksetmy-solution-rkpqxywon
jjgitpush-bmy-solution
Open a PR on GitHub/GitLab targeting main.
Paste jjj solution show "JWT" output in the PR description to show it has been reviewed and critiques resolved.
Merge via the forge’s UI.
In the hybrid flow, review and critique happen in jjj. The GitHub PR is used for CI checks and the merge button.
The original code context is gone. jjj detects the content change and marks the critique’s location as orphaned, signaling that the code was modified (likely in response to the critique).
Best Practices
Review Early, Review Often
Request reviews for work-in-progress solutions to get feedback before you invest heavily in an approach.
Keep Solutions Focused
Smaller solutions are faster to review and easier to critique precisely. Aim for solutions that address one problem clearly.
Use Solution-Based Bookmarks
Name your jj bookmarks using a meaningful name to make changes easy to find:
jj bookmark set solution/jwt-auth
Respond to All Critiques
Every critique must be resolved before acceptance. Either:
Fix the issue and mark as addressed
Reply with your reasoning and dismiss
Acknowledge the flaw and validate (then refute the solution)
Write Clear Descriptions
Include context in your solution’s approach field so reviewers understand the “why”:
jj describe -m "Add bcrypt password hashing
Replaces SHA-256 with bcrypt for better security.
Uses DEFAULT_COST (12) for work factor.
Addresses: password security problem"
Troubleshooting
Critique Locations Not Relocating
If critique locations do not update after rebase:
Check context: Did you completely rewrite the section?
View orphaned critiques: jjj critique list --solution "JWT"
Re-create if needed: Raise a new critique at the correct location
Submit Fails
If jjj submit reports unresolved critiques or missing sign-offs:
Terminal window
# Check what is blocking
jjjcritiquelist--solution"JWT"--statusopen
jjjsolutionshow"JWT"# Shows reviewer and sign-off status