jj-stack 0.1.4__tar.gz → 0.1.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (246) hide show
  1. {jj_stack-0.1.4 → jj_stack-0.1.5}/.github/workflows/ci.yml +3 -3
  2. {jj_stack-0.1.4 → jj_stack-0.1.5}/.github/workflows/release.yml +3 -3
  3. {jj_stack-0.1.4 → jj_stack-0.1.5}/CONTRIBUTING.md +11 -9
  4. {jj_stack-0.1.4 → jj_stack-0.1.5}/PKG-INFO +6 -5
  5. {jj_stack-0.1.4 → jj_stack-0.1.5}/README.md +5 -4
  6. {jj_stack-0.1.4 → jj_stack-0.1.5}/check.py +2 -2
  7. {jj_stack-0.1.4 → jj_stack-0.1.5}/complexity-budget.toml +1 -1
  8. {jj_stack-0.1.4 → jj_stack-0.1.5}/docs/guides/close-or-separate.md +4 -3
  9. {jj_stack-0.1.4 → jj_stack-0.1.5}/docs/guides/merge-and-sync.md +47 -21
  10. {jj_stack-0.1.4 → jj_stack-0.1.5}/docs/guides/review-a-stack.md +6 -5
  11. {jj_stack-0.1.4 → jj_stack-0.1.5}/docs/guides/submit-and-update.md +4 -3
  12. {jj_stack-0.1.4 → jj_stack-0.1.5}/docs/guides/working-on-github.md +4 -0
  13. {jj_stack-0.1.4 → jj_stack-0.1.5}/docs/internals/design.md +45 -27
  14. {jj_stack-0.1.4 → jj_stack-0.1.5}/docs/internals/releasing.md +4 -4
  15. {jj_stack-0.1.4 → jj_stack-0.1.5}/docs/json-output.schema.json +87 -0
  16. {jj_stack-0.1.4 → jj_stack-0.1.5}/docs/mental-model.md +7 -11
  17. {jj_stack-0.1.4 → jj_stack-0.1.5}/docs/quick-start.md +7 -10
  18. {jj_stack-0.1.4 → jj_stack-0.1.5}/docs/reference/automation.md +2 -0
  19. {jj_stack-0.1.4 → jj_stack-0.1.5}/docs/reference/bookmarks-and-selection.md +4 -4
  20. {jj_stack-0.1.4 → jj_stack-0.1.5}/docs/reference/configuration.md +5 -4
  21. {jj_stack-0.1.4 → jj_stack-0.1.5}/docs/reference/json-output.md +32 -5
  22. {jj_stack-0.1.4 → jj_stack-0.1.5}/docs/tool-comparison.md +8 -8
  23. {jj_stack-0.1.4 → jj_stack-0.1.5}/docs/troubleshooting.md +36 -28
  24. {jj_stack-0.1.4 → jj_stack-0.1.5}/justfile +1 -0
  25. {jj_stack-0.1.4 → jj_stack-0.1.5}/pyproject.toml +2 -9
  26. jj_stack-0.1.5/release-notes/v0.1.5.md +28 -0
  27. {jj_stack-0.1.4 → jj_stack-0.1.5}/scripts/describe_with_claude.py +0 -2
  28. {jj_stack-0.1.4 → jj_stack-0.1.5}/scripts/describe_with_codex.py +0 -2
  29. {jj_stack-0.1.4 → jj_stack-0.1.5}/scripts/describe_with_editor.py +0 -8
  30. {jj_stack-0.1.4 → jj_stack-0.1.5}/scripts/describe_with_prompt.py +0 -2
  31. {jj_stack-0.1.4 → jj_stack-0.1.5}/skills/jj-stack/SKILL.md +9 -6
  32. {jj_stack-0.1.4 → jj_stack-0.1.5}/skills/jj-stack/references/recovery.md +25 -12
  33. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/cli.py +69 -142
  34. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/cli_help.py +2 -4
  35. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/commands/_json_status.py +13 -11
  36. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/commands/checkout.py +15 -25
  37. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/commands/cleanup/actions.py +17 -37
  38. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/commands/cleanup/command.py +40 -48
  39. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/commands/doctor.py +5 -7
  40. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/commands/list_.py +29 -35
  41. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/commands/merge/command.py +98 -85
  42. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/commands/merge/github_stack.py +103 -120
  43. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/commands/merge/plan.py +15 -37
  44. jj_stack-0.1.5/src/jj_stack/commands/merge/wait.py +202 -0
  45. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/commands/relink.py +7 -8
  46. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/commands/submit/auto_close.py +1 -18
  47. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/commands/submit/changes.py +7 -5
  48. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/commands/submit/command.py +327 -232
  49. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/commands/submit/descriptions.py +0 -3
  50. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/commands/submit/editor.py +35 -38
  51. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/commands/submit/github_stack.py +8 -8
  52. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/commands/submit/inputs.py +4 -10
  53. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/commands/submit/models.py +1 -11
  54. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/commands/submit/prs.py +3 -5
  55. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/commands/submit/publication.py +2 -3
  56. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/commands/sync.py +7 -12
  57. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/commands/sync_apply.py +10 -10
  58. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/commands/sync_prs.py +1 -1
  59. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/commands/unstack.py +18 -31
  60. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/commands/view.py +48 -48
  61. jj_stack-0.1.5/src/jj_stack/commands/view_details.py +142 -0
  62. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/completion.py +17 -38
  63. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/config.py +12 -31
  64. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/console.py +36 -104
  65. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/errors.py +1 -7
  66. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/formatting.py +2 -20
  67. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/github/client.py +216 -146
  68. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/github/error_messages.py +8 -53
  69. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/jj/client.py +50 -32
  70. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/jj/settings.py +3 -1
  71. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/models/github.py +20 -3
  72. jj_stack-0.1.5/src/jj_stack/models/github_details.py +88 -0
  73. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/models/tracking.py +1 -9
  74. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/stack/change_state.py +37 -55
  75. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/stack/convergence.py +82 -49
  76. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/stack/github_stack_safety.py +1 -1
  77. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/stack/pr_branches.py +5 -4
  78. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/stack/pr_facts.py +13 -30
  79. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/stack/reporting.py +21 -0
  80. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/stack/selected.py +11 -2
  81. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/stack/selection.py +5 -3
  82. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/stack/status.py +2 -6
  83. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/state/migrations.py +2 -1
  84. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/state/operation_lock.py +6 -11
  85. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/state/store.py +26 -40
  86. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/ui.py +1 -22
  87. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/conftest.py +2 -2
  88. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/integration/test_checkout_command.py +20 -30
  89. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/integration/test_cleanup_command.py +0 -28
  90. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/integration/test_jj_stack.py +14 -0
  91. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/integration/test_list_command.py +16 -5
  92. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/integration/test_merge_command.py +157 -53
  93. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/integration/test_submit_command.py +99 -9
  94. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/integration/test_sync_command.py +24 -8
  95. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/integration/test_unstack_command.py +1 -1
  96. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/integration/test_view_command.py +85 -1
  97. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/property/test_submit_property_scenarios.py +1 -1
  98. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/run_submit_property_scenarios.py +1 -0
  99. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/support/fake_github.py +270 -129
  100. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/support/integration_helpers.py +6 -18
  101. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/support/json_schema.py +5 -6
  102. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/support/output_assertions.py +0 -10
  103. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/support/pytest_concurrency.py +1 -14
  104. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/support/stack_edit_scenarios.py +0 -2
  105. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/support/stack_machine.py +104 -41
  106. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_change_state.py +2 -2
  107. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_cli.py +3 -18
  108. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_cli_dispatch.py +1 -1
  109. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_completion.py +1 -16
  110. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_describe_with_prompt_script.py +0 -20
  111. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_errors.py +0 -14
  112. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_github_client.py +131 -56
  113. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_github_models.py +3 -17
  114. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_github_resolution.py +2 -14
  115. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_github_stack_planning.py +0 -24
  116. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_jj_client.py +5 -90
  117. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_merge.py +0 -53
  118. jj_stack-0.1.5/tests/unit/test_merge_wait.py +101 -0
  119. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_operation_lock.py +0 -21
  120. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_pr_branches.py +9 -20
  121. jj_stack-0.1.5/tests/unit/test_pr_refs.py +34 -0
  122. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_relink.py +10 -8
  123. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_stack_path.py +0 -8
  124. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_submit.py +5 -9
  125. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_submit_editor.py +3 -45
  126. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_ui.py +10 -13
  127. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_view.py +30 -8
  128. {jj_stack-0.1.4 → jj_stack-0.1.5}/tools/check_jj_release_updates.py +6 -10
  129. jj_stack-0.1.5/uv.lock +740 -0
  130. jj_stack-0.1.4/tests/unit/test_cleanup.py +0 -20
  131. jj_stack-0.1.4/tests/unit/test_divergence.py +0 -15
  132. jj_stack-0.1.4/tests/unit/test_pr_refs.py +0 -51
  133. jj_stack-0.1.4/uv.lock +0 -915
  134. {jj_stack-0.1.4 → jj_stack-0.1.5}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  135. {jj_stack-0.1.4 → jj_stack-0.1.5}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  136. {jj_stack-0.1.4 → jj_stack-0.1.5}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  137. {jj_stack-0.1.4 → jj_stack-0.1.5}/.github/SECURITY.md +0 -0
  138. {jj_stack-0.1.4 → jj_stack-0.1.5}/.github/dependabot.yml +0 -0
  139. {jj_stack-0.1.4 → jj_stack-0.1.5}/.github/pull_request_template.md +0 -0
  140. {jj_stack-0.1.4 → jj_stack-0.1.5}/.github/workflows/block-pr-base-merges.yml +0 -0
  141. {jj_stack-0.1.4 → jj_stack-0.1.5}/.github/workflows/check-jj-release-updates.yml +0 -0
  142. {jj_stack-0.1.4 → jj_stack-0.1.5}/.github/workflows/codeql.yml +0 -0
  143. {jj_stack-0.1.4 → jj_stack-0.1.5}/.gitignore +0 -0
  144. {jj_stack-0.1.4 → jj_stack-0.1.5}/AGENTS.md +0 -0
  145. {jj_stack-0.1.4 → jj_stack-0.1.5}/CLAUDE.md +0 -0
  146. {jj_stack-0.1.4 → jj_stack-0.1.5}/LICENSE +0 -0
  147. {jj_stack-0.1.4 → jj_stack-0.1.5}/NOTICE +0 -0
  148. {jj_stack-0.1.4 → jj_stack-0.1.5}/docs/AGENTS.md +0 -0
  149. {jj_stack-0.1.4 → jj_stack-0.1.5}/docs/README.md +0 -0
  150. {jj_stack-0.1.4 → jj_stack-0.1.5}/docs/guides/continue-a-stack.md +0 -0
  151. {jj_stack-0.1.4 → jj_stack-0.1.5}/docs/guides/multiple-stacks.md +0 -0
  152. {jj_stack-0.1.4 → jj_stack-0.1.5}/docs/guides/revise.md +0 -0
  153. {jj_stack-0.1.4 → jj_stack-0.1.5}/docs/internals/AGENTS.md +0 -0
  154. {jj_stack-0.1.4 → jj_stack-0.1.5}/docs/internals/README.md +0 -0
  155. {jj_stack-0.1.4 → jj_stack-0.1.5}/docs/internals/code-reviews.md +0 -0
  156. {jj_stack-0.1.4 → jj_stack-0.1.5}/docs/internals/property-testing.md +0 -0
  157. {jj_stack-0.1.4 → jj_stack-0.1.5}/docs/internals/testing-philosophy.md +0 -0
  158. {jj_stack-0.1.4 → jj_stack-0.1.5}/docs/reference/commands.md +0 -0
  159. {jj_stack-0.1.4 → jj_stack-0.1.5}/docs/reference/descriptions.md +0 -0
  160. {jj_stack-0.1.4 → jj_stack-0.1.5}/evals/jj-stack-skill.md +0 -0
  161. {jj_stack-0.1.4 → jj_stack-0.1.5}/release-notes/v0.1.2.md +0 -0
  162. {jj_stack-0.1.4 → jj_stack-0.1.5}/release-notes/v0.1.3.md +0 -0
  163. {jj_stack-0.1.4 → jj_stack-0.1.5}/release-notes/v0.1.4.md +0 -0
  164. {jj_stack-0.1.4 → jj_stack-0.1.5}/scripts/README.md +0 -0
  165. {jj_stack-0.1.4 → jj_stack-0.1.5}/skills/jj-stack/agents/openai.yaml +0 -0
  166. {jj_stack-0.1.4 → jj_stack-0.1.5}/skills/jj-stack/references/multi-stack.md +0 -0
  167. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/__init__.py +0 -0
  168. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/__main__.py +0 -0
  169. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/bootstrap.py +0 -0
  170. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/commands/__init__.py +0 -0
  171. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/commands/in_use.py +0 -0
  172. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/commands/merge/__init__.py +0 -0
  173. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/commands/submit/__init__.py +0 -0
  174. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/commands/submit/default_pr_text.py +0 -0
  175. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/commands/submit/managed_comments.py +0 -0
  176. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/commands/submit/overview_comments.py +0 -0
  177. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/commands/submit/render.py +0 -0
  178. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/commands/submit/revision_comments.py +0 -0
  179. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/concurrency.py +0 -0
  180. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/github/__init__.py +0 -0
  181. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/github/auth.py +0 -0
  182. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/github/overview_comments.py +0 -0
  183. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/github/pr_refs.py +0 -0
  184. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/github/resolution.py +0 -0
  185. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/github/stack_availability.py +0 -0
  186. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/identifiers.py +0 -0
  187. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/jj/__init__.py +0 -0
  188. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/jj/cli_args.py +0 -0
  189. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/jj/colors.py +0 -0
  190. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/models/__init__.py +0 -0
  191. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/models/git.py +0 -0
  192. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/models/stack.py +0 -0
  193. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/pr_branch_namespace.py +0 -0
  194. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/stack/__init__.py +0 -0
  195. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/stack/convergence_models.py +0 -0
  196. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/stack/convergence_observation.py +0 -0
  197. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/stack/divergence.py +0 -0
  198. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/stack/global_convergence.py +0 -0
  199. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/stack/observation.py +0 -0
  200. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/stack/path.py +0 -0
  201. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/stack/preparation.py +0 -0
  202. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/stack/repo.py +0 -0
  203. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/stack/trunk.py +0 -0
  204. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/stack/trunk_evidence.py +0 -0
  205. {jj_stack-0.1.4 → jj_stack-0.1.5}/src/jj_stack/state/__init__.py +0 -0
  206. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/__init__.py +0 -0
  207. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/integration/__init__.py +0 -0
  208. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/integration/conftest.py +0 -0
  209. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/integration/submit_command_helpers.py +0 -0
  210. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/integration/test_boundary_conditions.py +0 -0
  211. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/integration/test_doctor_command.py +0 -0
  212. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/integration/test_fake_github_contracts.py +0 -0
  213. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/integration/test_relink_command.py +0 -0
  214. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/run_live_github.py +0 -0
  215. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/support/__init__.py +0 -0
  216. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/support/change_helpers.py +0 -0
  217. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/support/contexts.py +0 -0
  218. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/support/submit_faults.py +0 -0
  219. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/support/tracking.py +0 -0
  220. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/__init__.py +0 -0
  221. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_bootstrap.py +0 -0
  222. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_check_script.py +0 -0
  223. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_checkout.py +0 -0
  224. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_concurrency.py +0 -0
  225. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_config.py +0 -0
  226. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_default_pr_text.py +0 -0
  227. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_describe_with_editor_script.py +0 -0
  228. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_github_auth.py +0 -0
  229. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_github_error_messages.py +0 -0
  230. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_in_use_command.py +0 -0
  231. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_jj_settings.py +0 -0
  232. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_live_github_runner.py +0 -0
  233. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_pr_facts.py +0 -0
  234. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_property_runner.py +0 -0
  235. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_property_scenarios.py +0 -0
  236. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_selected.py +0 -0
  237. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_stack_status.py +0 -0
  238. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_store.py +0 -0
  239. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_submit_descriptions.py +0 -0
  240. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_sync.py +0 -0
  241. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_trunk_evidence.py +0 -0
  242. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_unstack.py +0 -0
  243. {jj_stack-0.1.4 → jj_stack-0.1.5}/tests/unit/test_view_entrypoint.py +0 -0
  244. {jj_stack-0.1.4 → jj_stack-0.1.5}/tools/check_complexity.py +0 -0
  245. {jj_stack-0.1.4 → jj_stack-0.1.5}/tools/check_release_artifacts.py +0 -0
  246. {jj_stack-0.1.4 → jj_stack-0.1.5}/tools/install-jj-release.sh +0 -0
@@ -18,7 +18,7 @@ jobs:
18
18
  uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
19
19
 
20
20
  - name: Set up uv
21
- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
21
+ uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
22
22
  with:
23
23
  python-version: "3.14"
24
24
 
@@ -52,7 +52,7 @@ jobs:
52
52
  uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
53
53
 
54
54
  - name: Set up uv
55
- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
55
+ uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
56
56
  with:
57
57
  python-version: ${{ matrix.python-version }}
58
58
 
@@ -79,7 +79,7 @@ jobs:
79
79
  uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
80
80
 
81
81
  - name: Set up uv
82
- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
82
+ uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
83
83
  with:
84
84
  python-version: "3.14"
85
85
 
@@ -34,7 +34,7 @@ jobs:
34
34
  ref: ${{ inputs.release_tag || github.ref }}
35
35
 
36
36
  - name: Set up uv
37
- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
37
+ uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
38
38
  with:
39
39
  python-version: "3.14"
40
40
 
@@ -94,7 +94,7 @@ jobs:
94
94
 
95
95
  steps:
96
96
  - name: Set up uv
97
- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
97
+ uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
98
98
  with:
99
99
  python-version: "3.14"
100
100
 
@@ -127,7 +127,7 @@ jobs:
127
127
 
128
128
  steps:
129
129
  - name: Set up uv
130
- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
130
+ uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
131
131
  with:
132
132
  python-version: "3.14"
133
133
 
@@ -39,20 +39,22 @@ just check
39
39
  ```
40
40
 
41
41
  Pyrefly is the default type checker, including a second pass targeting Windows. To select ty
42
- or mypy for the current platform instead, use `--type-checker` or its short form, `-t`:
42
+ for the current platform instead, use `--type-checker` or its short form, `-t`:
43
43
 
44
44
  ```console
45
45
  just check -t ty
46
- just check -t mypy
47
46
  ```
48
47
 
49
- Repeat the option to run several in the given order, for example
50
- `just check -t pyrefly -t ty -t mypy`. The runner installs the selected checkers from the lockfile,
51
- checks `src`, `tests`, `tools`, and `check.py`, and runs the usual Ruff and pytest checks. It stops
52
- at the first failed check. ty and mypy are optional during development and can report issues
53
- that Pyrefly does not; their failures are reported normally. Plain `just check` and CI continue
54
- to use Pyrefly. Before a release, follow the
55
- [requirement for all three type checkers to pass](docs/internals/releasing.md#qualify-the-candidate).
48
+ Repeat the option to run several in the given order, for example `just check -t pyrefly -t ty`.
49
+ The runner installs the selected checkers from the lockfile, checks `src`, `tests`, `tools`, and
50
+ `check.py`, and runs the usual Ruff and pytest checks. It stops at the first failed check. ty is
51
+ optional during development and can report issues that Pyrefly does not; its failures are
52
+ reported normally. Plain `just check` and CI continue to use Pyrefly. Before a release, follow the
53
+ [requirement for both type checkers to pass](docs/internals/releasing.md#qualify-the-candidate).
54
+
55
+ mypy is deliberately not part of the toolchain. It fixes a variable's type at its first
56
+ assignment and rejects a later assignment of another type, which Pyrefly and ty accept, so
57
+ keeping it green required annotations whose only purpose was to satisfy mypy.
56
58
 
57
59
  Run focused tests while you iterate:
58
60
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: jj-stack
3
- Version: 0.1.4
3
+ Version: 0.1.5
4
4
  Summary: Stacked GitHub pull requests for Jujutsu
5
5
  Project-URL: Homepage, https://www.serpentine.com/software/jj-stack/
6
6
  Project-URL: Documentation, https://www.serpentine.com/software/jj-stack/
@@ -99,10 +99,11 @@ your edit.
99
99
  2. Run `jj-stack submit`.
100
100
  3. Revise, add, remove, or reorder the changes locally as reviews come in.
101
101
  4. Run `jj-stack submit` again to refresh GitHub.
102
- 5. Run `jj-stack merge --pull-request <last-pr-to-merge> --method squash` when the bottom
103
- portion is ready. Choose a merge method your repo allows. Queues choose their own method.
104
- 6. After a queued merge or a merge made through GitHub finishes, run
105
- `jj-stack sync <head-change-id>`.
102
+ 5. Run `jj-stack merge` when the PRs at the bottom are ready. Pass `--pull-request <pr>` to
103
+ stop at an earlier PR, and `--method` to choose a merge method your repo allows. The command
104
+ waits for GitHub, including its merge queue, then updates your local stack and remaining PRs.
105
+ 6. If you used `--no-wait`, interrupted the wait, or merged through GitHub, run
106
+ `jj-stack sync <head-change-id>` after GitHub finishes.
106
107
 
107
108
  `view`, `submit`, `merge`, and `sync` accept a change ID when you need to select a stack other
108
109
  than the one ending at the working copy.
@@ -71,10 +71,11 @@ your edit.
71
71
  2. Run `jj-stack submit`.
72
72
  3. Revise, add, remove, or reorder the changes locally as reviews come in.
73
73
  4. Run `jj-stack submit` again to refresh GitHub.
74
- 5. Run `jj-stack merge --pull-request <last-pr-to-merge> --method squash` when the bottom
75
- portion is ready. Choose a merge method your repo allows. Queues choose their own method.
76
- 6. After a queued merge or a merge made through GitHub finishes, run
77
- `jj-stack sync <head-change-id>`.
74
+ 5. Run `jj-stack merge` when the PRs at the bottom are ready. Pass `--pull-request <pr>` to
75
+ stop at an earlier PR, and `--method` to choose a merge method your repo allows. The command
76
+ waits for GitHub, including its merge queue, then updates your local stack and remaining PRs.
77
+ 6. If you used `--no-wait`, interrupted the wait, or merged through GitHub, run
78
+ `jj-stack sync <head-change-id>` after GitHub finishes.
78
79
 
79
80
  `view`, `submit`, `merge`, and `sync` accept a change ID when you need to select a stack other
80
81
  than the one ending at the working copy.
@@ -20,7 +20,7 @@ VENV_PYTHON = (
20
20
  )
21
21
  PytestJobs = int | Literal["auto"]
22
22
  _TYPE_CHECK_TARGETS = ("src", "tests", "tools", "check.py")
23
- _TYPE_CHECKERS = ("pyrefly", "ty", "mypy")
23
+ _TYPE_CHECKERS = ("pyrefly", "ty")
24
24
  _FRAGILE_TEST_OUTPUT_PATTERNS: tuple[tuple[str, re.Pattern[str]], ...] = (
25
25
  (
26
26
  "use output assertion helpers instead of exact captured output equality",
@@ -79,7 +79,7 @@ def _build_checks(
79
79
  )
80
80
  type_checks: list[tuple[str, tuple[str, ...]]] = []
81
81
  for checker in type_checkers:
82
- command = ("-m", checker) if checker == "mypy" else ("-m", checker, "check")
82
+ command = ("-m", checker, "check")
83
83
  type_checks.append((checker, (*command, *_TYPE_CHECK_TARGETS)))
84
84
  if checker == "pyrefly":
85
85
  type_checks.append(
@@ -13,7 +13,7 @@ governed_c901 = 0
13
13
 
14
14
  [pytest]
15
15
  fixed_property = 9
16
- merge_recovery = 60
16
+ merge_recovery = 63
17
17
 
18
18
  [labels]
19
19
  production = "Production"
@@ -57,9 +57,10 @@ jj-stack cleanup <head-change-id>
57
57
 
58
58
  ### If cleanup keeps a branch
59
59
 
60
- Cleanup keeps a PR branch while another open or reopenable closed PR uses it as its base. The
61
- message names the dependent PR. Retarget an open PR to trunk. For a closed PR, either reopen and
62
- retarget it or delete its head branch if you no longer need to reopen it. Then rerun cleanup.
60
+ Cleanup keeps a PR branch while another PR still uses it as its base: an open PR, or a closed PR
61
+ that GitHub could still reopen. The message names that PR. Retarget an open PR to trunk. For a
62
+ closed PR, either reopen and retarget it, or delete its head branch if you no longer need to
63
+ reopen it. Then rerun cleanup.
63
64
 
64
65
  A branch also stays while an unmerged PR in a GitHub stack needs it. Remove that stack with
65
66
  `jj-stack unstack` before retrying cleanup.
@@ -11,8 +11,8 @@ stack. Once the PRs have merged, `jj-stack sync` updates your local stack and an
11
11
  pull requests.
12
12
 
13
13
  GitHub can perform the merge immediately or put it through a merge queue. An immediate merge
14
- is called a **direct merge**, and `jj-stack merge` runs the sync automatically in this case.
15
- For a queued merge, you run `sync` yourself after GitHub finishes.
14
+ is called a **direct merge**. In both cases, `jj-stack merge` waits for completion and runs
15
+ the sync automatically.
16
16
 
17
17
  ## Before merging
18
18
 
@@ -28,11 +28,27 @@ jj-stack merge <head-change-id>
28
28
  that their PR branches and pull requests have not moved unexpectedly. GitHub decides whether
29
29
  checks, approvals, conflicts, and repo rules allow the merge.
30
30
 
31
+ `jj-stack list` and `jj-stack view` show review decisions, checks, and GitHub's merge-state
32
+ warnings separately. `review required` means GitHub still requires a review. A PR can be
33
+ approved with passing checks and still show `merge blocked`, for example when review
34
+ conversations remain unresolved.
35
+
36
+ To inspect unresolved review threads and failed or pending checks, including links, run:
37
+
38
+ ```console
39
+ jj-stack view --verbose <head-change-id>
40
+ ```
41
+
42
+ Verbose output includes thread excerpts, even for outdated threads. If GitHub reports a blocker
43
+ without exposing a specific reason, the output says so and links to the PR. Checks are the
44
+ results GitHub has received; a required check that has not reported yet is absent. Even without
45
+ a warning, approval and passing checks do not guarantee that GitHub will accept a merge.
46
+
31
47
  ## Choose a merge method
32
48
 
33
- Direct merges happen immediately on GitHub. If your repo allows only one merge method, `merge`
34
- uses it automatically. With several allowed methods and an unsigned stack, it prefers rebase,
35
- then squash, then a merge commit. Choose an allowed method with `--method`, or set a default once:
49
+ For a direct merge, `merge` uses your repo's only allowed merge method if there is just one.
50
+ With several allowed methods and an unsigned stack, it prefers rebase, then squash, then a merge
51
+ commit. Choose an allowed method with `--method`, or set a default once:
36
52
 
37
53
  ```console
38
54
  jj config set --repo jj-stack.merge_method squash
@@ -64,7 +80,7 @@ For example, in A → B → C, suppose the PRs are #1, #2, and #3. To merge only
64
80
  jj-stack merge --pull-request 1 --method squash
65
81
  ```
66
82
 
67
- After a direct merge, PR #1 is merged, PR #2 targets `main`, and PR #3 still targets PR #2's
83
+ After the command finishes, PR #1 is merged, PR #2 targets `main`, and PR #3 still targets PR #2's
68
84
  branch. Both remaining PRs keep their numbers and discussions:
69
85
 
70
86
  ```mermaid
@@ -83,7 +99,8 @@ proceed because all three PRs belong to the same GitHub stack.
83
99
 
84
100
  After GitHub merges some or all of your pull requests, `sync` fetches the updated trunk and
85
101
  rebases your remaining changes onto it. It removes any obsolete local copies of the merged
86
- changes, updates the remaining PRs, and deletes PR branches that are no longer needed.
102
+ changes, updates the remaining PRs, and deletes PR branches that are no longer needed. If your
103
+ working copy is on a merged change, `sync` first moves it to a new empty change on trunk.
87
104
 
88
105
  Select the stack by its head change ID or by any linked pull request:
89
106
 
@@ -95,8 +112,8 @@ jj-stack sync --pull-request <pr>
95
112
  `sync --pull-request` updates the complete local stack containing the named PR, including
96
113
  changes above it. The selected PR can already be merged.
97
114
 
98
- For a PR outside a GitHub stack, `sync` can also close the PR and clean up after its submitted
99
- commit reaches trunk through an external fast-forward push.
115
+ If someone pushes a PR's submitted commit straight to trunk instead of merging the PR, `sync`
116
+ closes that PR and cleans up, provided the PR is not part of a GitHub stack.
100
117
 
101
118
  If no PR has merged, no submitted commit has reached trunk, and GitHub has not rebased the stack,
102
119
  `sync` leaves the pull requests unchanged. Run `jj-stack submit` explicitly when you want to
@@ -107,19 +124,25 @@ changes may still depend on the original local changes. `sync` rebases that work
107
124
  squashed result and removes the old copies. Other merge methods also need `sync` to update
108
125
  the remaining PRs and remove unused branches.
109
126
 
110
- ### Direct merges
127
+ ### Merge queues
111
128
 
112
- For a direct merge, `merge` waits for GitHub to finish and runs `sync` before it returns.
113
- Your local stack and remaining PRs are then ready for you to keep working.
129
+ GitHub tests each queued PR on a temporary merge commit that combines it with the PRs ahead of
130
+ it, so those checks appear on that commit rather than on the PR's own Checks tab. While waiting,
131
+ `merge` shows each PR's queue position and the state of those checks.
114
132
 
115
- ### Merge queues
133
+ If GitHub removes a PR from the queue, `merge` stops, reports GitHub's reason, links to the
134
+ checks on that commit, and names the next step. See [queue removal recovery][queue-removal].
116
135
 
117
- When a merge queue is in use, `merge` returns once GitHub accepts the PRs into the queue.
118
- They may still be waiting to merge at that point. Wait until GitHub reports that the merge
119
- has finished, then run `sync` for that stack.
136
+ [queue-removal]: ../troubleshooting.md#a-stack-was-removed-from-the-merge-queue
120
137
 
121
138
  While any selected pull request is queued, `jj-stack submit` refuses to update the stack and
122
- `jj-stack sync` leaves it unchanged.
139
+ `jj-stack sync` leaves it unchanged; rerun `jj-stack merge` to resume waiting.
140
+
141
+ ### Leaving before GitHub finishes
142
+
143
+ Use `--no-wait` to return as soon as GitHub accepts the request, or press Ctrl-C to stop
144
+ waiting. Neither cancels the request. Rerun the same `jj-stack merge` to keep watching it, or run
145
+ `jj-stack sync <head-change-id>` once GitHub finishes.
123
146
 
124
147
  ### Merges outside jj-stack
125
148
 
@@ -163,19 +186,22 @@ jj-stack sync <head-change-id>
163
186
  ```
164
187
 
165
188
  If only cleanup failed, run the `jj-stack cleanup --pull-request <pr>` commands in the hint.
166
- The local changes may already be gone, so their former head cannot select the remaining cleanup.
189
+ The hint names each PR because the merged local changes may already be gone.
167
190
 
168
191
  Your pull requests are already merged, so do not retry `jj-stack merge`.
169
192
 
170
193
  ## When trunk moves without one of your pull requests merging
171
194
 
172
- `sync` handles completed GitHub merges and stack rebases. If trunk merely advanced, fetch it,
173
- rebase your changes with `jj` if needed, then submit the rewritten changes:
195
+ `jj-stack sync` handles completed GitHub merges and stack rebases. If trunk merely advanced,
196
+ fetch it, rebase your changes with `jj` if needed, then submit the rewritten changes:
174
197
 
175
198
  ```console
176
199
  jj git fetch
177
- jj rebase -s '<bottom-change-id>' -o 'trunk()'
200
+ jj rebase -b '<change-id>' -o 'trunk()'
178
201
  jj-stack submit <head-change-id>
179
202
  ```
180
203
 
204
+ Use any change in the stack with `-b`; jj finds its base and moves the whole stack, including
205
+ forks. You can even omit `-b` to use jj's default of `@`.
206
+
181
207
  Rebase when your work needs the latest trunk or GitHub requires it before merging.
@@ -29,7 +29,7 @@ version appears first and is marked **current**. Use **Changes from previous ver
29
29
  what changed in that update. Use **Submitted commit** to inspect the exact commit published for
30
30
  that version.
31
31
 
32
- The comment lists recent available versions. If you missed several updates, follow their diff
32
+ The comment lists the most recent versions. If you missed several updates, follow their diff
33
33
  links in order; use the PR's **Files changed** tab to review the current layer as a whole.
34
34
 
35
35
  ## Review and merge in order
@@ -58,10 +58,11 @@ each PR.
58
58
 
59
59
  ## Merge queues
60
60
 
61
- GitHub adds a stack's pull requests to the queue in dependency order. Removing or ejecting a PR
62
- also removes every PR above it. Resolve the cause, then add the stack to the queue again. Wait
63
- until the merge completes before running `jj-stack sync`. See GitHub's
64
- [merge queue guidance][github-queue].
61
+ GitHub adds a stack's pull requests to the queue in dependency order. If GitHub removes a PR, it
62
+ also removes every PR above it; `jj-stack merge` stops, reports the reason, and names the next
63
+ step. Fix the cause and rerun the same `jj-stack merge` command. See
64
+ [queue removal recovery](../troubleshooting.md#a-stack-was-removed-from-the-merge-queue) and
65
+ GitHub's [merge queue guidance][github-queue].
65
66
 
66
67
  [github-review]: https://docs.github.com/en/pull-requests/how-tos/review-pull-requests/reviewing-stacked-pull-requests
67
68
  [github-merge]: https://docs.github.com/en/pull-requests/how-tos/merge-and-close-pull-requests/merging-stacked-pull-requests
@@ -87,10 +87,11 @@ look again:
87
87
  jj-stack submit --re-request
88
88
  ```
89
89
 
90
- ## PR history
90
+ ## Revision history
91
91
 
92
- After updates, jj-stack maintains a comment on each PR listing its recent versions with links
93
- to the diffs. Reviewers can use it to see what changed since their last review.
92
+ After updates, jj-stack maintains a **Revision history** comment on each PR. It lists the PR's
93
+ recent versions with links to the diff between each version and the next, so reviewers can see
94
+ what changed since their last review.
94
95
 
95
96
  For edits made directly on GitHub, see [work with a stack on GitHub](working-on-github.md).
96
97
  If you move changes between stacks, follow
@@ -52,5 +52,9 @@ both from the local `jj` history. To change the base or order, make that change
52
52
  submit again. To remove the GitHub stack while leaving the PRs open, see
53
53
  [separate a stack](close-or-separate.md#remove-a-github-stack).
54
54
 
55
+ Do not enable auto-merge, shown as **Merge when ready** with a merge queue, on a pull request
56
+ you will stack more changes on. GitHub refuses to add such a PR to a stack, so the next submit
57
+ stops until you disable it.
58
+
55
59
  For reviewer and repo configuration guidance, see
56
60
  [review and merge a stack on GitHub](review-a-stack.md).
@@ -175,7 +175,7 @@ through a merge queue.
175
175
  | `submit` | Create PRs and refresh the selected stack; only this command publishes new changes. |
176
176
  | `sync` | Update a local stack after a merge or native GitHub stack rebase. |
177
177
  | `sync --all` | Sync stacks after merges and finish eligible PRs without local copies. |
178
- | `merge` | Request a GitHub merge; run sync after a direct merge completes. |
178
+ | `merge` | Request a GitHub merge; wait for completion and run sync unless `--no-wait` is used. |
179
179
  | `unstack` | Remove a GitHub stack; `--local` instead forgets local tracking. |
180
180
  | `cleanup` | Remove eligible artifacts and links; optionally close explicitly selected PRs. |
181
181
  | `checkout` | Adopt existing PRs and edit the selected change in the current workspace. |
@@ -186,7 +186,7 @@ through a merge queue.
186
186
 
187
187
  `jj` owns general history editing. There is no standalone `jj-stack rebase` command.
188
188
 
189
- `sync` and `merge` fetch before planning, including during `--dry-run`. A direct merge fetches
189
+ `sync` and `merge` fetch before planning, including during `--dry-run`. A merge that waits fetches
190
190
  again after GitHub completes it. `checkout --pull-request` fetches when the selected PR's head
191
191
  commit is not already local. Other commands do not fetch. Commands evaluate `trunk()` after any
192
192
  fetch they perform; without a fetch, they use the locally available trunk.
@@ -245,10 +245,11 @@ removed, so `in-use` continues to report adoption. `view`, `list`, and `in-use`
245
245
  An unreadable or invalid file blocks commands that load it and names the path to move aside before
246
246
  using `checkout` or `relink` to restore links. A newer unsupported schema requires an upgrade.
247
247
 
248
- Mutating commands serialize per repo. An interruption can leave completed external effects even
249
- if the command reports failure. A retry computes what remains from current observations; it never
250
- replays a saved plan or selector. The submitted baseline records an acknowledged commit, not
251
- pending work.
248
+ Mutating commands serialize per repo while they observe and mutate. A command that waits for
249
+ GitHub, an editor, or a describe helper releases that serialization while it waits and observes
250
+ again before it mutates. An interruption can leave completed external effects even if the command
251
+ reports failure. A retry computes what remains from current observations; it never replays a
252
+ saved plan or selector. The submitted baseline records an acknowledged commit, not pending work.
252
253
 
253
254
  ## Policies
254
255
 
@@ -368,11 +369,22 @@ queue object or a `MERGE_QUEUE` branch rule. If that lookup fails, `merge` stops
368
369
  error before requesting anything. It sends the explicit action `merge_queue` when a queue is
369
370
  found and `direct_merge` otherwise.
370
371
 
371
- A `merged` result means a direct merge completed; `merge` then fetches and syncs the whole
372
- selected stack before returning, including changes above the last merged PR and commits GitHub
373
- rewrote. An `enqueued` result means GitHub accepted the selected PRs into the queue. The command
374
- succeeds, but the user must wait for the queued merge to finish before running `sync`. A rejection
375
- leaves local changes unchanged.
372
+ `merge` waits for completion by default, then fetches and syncs the whole selected stack before
373
+ returning, including changes above the last merged PR and commits GitHub rewrote. An `enqueued`
374
+ result means GitHub accepted the PRs into the queue; waiting continues by observing every selected
375
+ PR until all report merged. Observations must still match the planned PR identities and submitted
376
+ heads. Queue progress is shown but never determines merge eligibility. GitHub removes a queue
377
+ entry before it records the merge, so an open, unqueued PR with no recorded non-merge reason
378
+ still counts as merging until that state persists; a recorded reason other than a merge is a
379
+ removal. A removal stops the wait without local changes, reports the recorded reason and the
380
+ temporary merge commit, and names the next step: `sync` when a lower PR already merged, otherwise
381
+ the same `merge` again.
382
+
383
+ `--no-wait` returns after GitHub accepts the request; the user runs `sync` once GitHub merges.
384
+ Interrupting a wait does not cancel the request. Rerunning `merge` for the same action and
385
+ expected head resumes waiting; a different action or expected head stops. A queue request's merge
386
+ method is not part of that identity because the queue chooses it. Queue waiting has no deadline;
387
+ polling a direct merge request does. A rejection leaves local changes unchanged.
376
388
 
377
389
  Automatic reconciliation identifies the containing stack by the full change ID of the head
378
390
  resolved before the merge request. It does not reinterpret the original revset
@@ -416,8 +428,8 @@ routing for the trunk branch, it does not preflight approvals, checks, conflicts
416
428
  state across the repo. GitHub applies those rules to the requested GitHub stack or
417
429
  single-PR mutation, and `jj-stack` reports the result.
418
430
 
419
- A rejected merge must explain what the user can do next: rebase onto trunk, resolve, and submit
420
- again for a conflict; address the failing check or repo rule on GitHub otherwise.
431
+ A rejected merge preserves GitHub's reason and says what to do next: rebase onto trunk, resolve,
432
+ and submit again for a conflict; address the reported issue on GitHub and retry otherwise.
421
433
 
422
434
  ### Trunk evidence and sync
423
435
 
@@ -469,9 +481,10 @@ It rebases surviving changes onto trunk even when they contain conflicts. If a s
469
481
  change remains conflicted, the local rebase stays in place but its PR is not updated. The
470
482
  user resolves the conflict with `jj` and runs `submit` for the remaining stack.
471
483
 
472
- If a workspace directly has an obsolete merged change checked out, `sync` does not remove that
484
+ If another workspace has an obsolete merged change checked out, `sync` does not remove that
473
485
  change. Its diagnostic identifies the workspace and gives commands to move it to trunk or forget
474
- it and move its directory to the trash. A workspace on a surviving child does not block its
486
+ it and move its directory to the trash. The current workspace moves to a new empty change on
487
+ trunk before its merged change is removed. A workspace on a surviving child does not block its
475
488
  ordinary rebase.
476
489
 
477
490
  If another local path still depends on a merged change after the rebase, `sync` leaves the
@@ -488,13 +501,13 @@ merges. A matching full change ID on trunk identifies the successor rather than
488
501
  an arbitrary visible side copy. When trunk has no matching change ID, `sync` removes the
489
502
  old local change without relabeling that commit.
490
503
 
491
- When GitHub merges part of a stack and rewrites the remaining PRs, GitHub's rewrite of
492
- each remaining change starts from its submitted baseline. If every remaining local change is still
493
- at its baseline, `sync` uses the commits GitHub reports rather than replaying equivalent
494
- diffs; if any remaining change has local edits, `sync` adopts none, rebases the remaining changes
495
- onto trunk, records GitHub's reported heads as their baselines, and republishes them. It
496
- accepts those heads and bases only while a merged PR in the same GitHub stack matches its saved
497
- record and its merge result is on trunk.
504
+ When GitHub merges part of a stack, each remaining PR is either rewritten from its submitted
505
+ baseline or left at its submitted commit. `sync` uses the commits GitHub reports, rather than
506
+ replaying equivalent diffs, only if every remaining local change is still at its baseline and
507
+ GitHub rewrote every remaining PR. Otherwise it adopts none, rebases the remaining changes onto
508
+ trunk, records GitHub's reported heads as their baselines, and republishes them. It accepts those
509
+ heads and bases only while a merged PR in the same GitHub stack matches its saved record and its
510
+ merge result is on trunk.
498
511
 
499
512
  #### Native GitHub stack rebase
500
513
 
@@ -674,7 +687,12 @@ changes that explicit submit boundaries placed in several native GitHub stacks.
674
687
  not segment the path by GitHub resource or infer an omitted submit boundary.
675
688
 
676
689
  Both report whether an open PR has a merge-queue entry; position and intermediate queue phases
677
- are not modeled.
690
+ are not shown.
691
+
692
+ Both report GitHub's merge state for an open PR alongside its reviews and checks. GitHub computes
693
+ that state lazily, so an unknown state is not reported or polled. `view --verbose` also reads
694
+ unresolved review threads and check results for open, non-draft, non-queued PRs with no reported
695
+ problem, discarding a PR's details if its head changes during the lookup.
678
696
 
679
697
  Neither command guesses. A change with no saved PR identity is reported as not submitted,
680
698
  even if a PR happens to use the branch name that change would generate. A saved PR is always
@@ -689,10 +707,10 @@ Empty, undescribed, conflicted, and merge changes produce warnings, but do not b
689
707
  a report incomplete. A merge warning states that only the first-parent path is shown.
690
708
 
691
709
  `view` and `list` share the rule for incomplete reports: an unmerged divergent change, ambiguous
692
- PR, failed PR lookup, broken saved link, or unobserved saved PR state makes the report incomplete.
693
- A per-change lookup failure affects only its row; a failure before rows can be built returns its
694
- own error code. When several local changes claim one branch, `list` warns and skips live
695
- inspection for that branch. These incomplete reports exit 10.
710
+ PR, failed PR or detail lookup, broken saved link, or unobserved saved PR state makes the report
711
+ incomplete. A per-change lookup failure affects only its row; a failure before rows can be built
712
+ returns its own error code. When several local changes claim one branch, `list` warns and skips
713
+ live inspection for that branch. These incomplete reports exit 10.
696
714
 
697
715
  `view` and `submit` render stack rows through the user's `jj log` formatting. `--json`
698
716
  follows [`docs/json-output.schema.json`](../json-output.schema.json) and exposes no cache state,
@@ -52,17 +52,17 @@ GitHub preserves source line breaks in Release bodies. This is an exception to t
52
52
 
53
53
  ## Qualify the candidate
54
54
 
55
- Set the version in `pyproject.toml` and finish the release changes and notes. Pyrefly, ty, and
56
- mypy must all pass before publishing a release. Run all three type checkers and both local gates:
55
+ Set the version in `pyproject.toml` and finish the release changes and notes. Pyrefly and ty
56
+ must both pass before publishing a release. Run both type checkers and both local gates:
57
57
 
58
58
  ```console
59
- just check -t pyrefly -t ty -t mypy
59
+ just check -t pyrefly -t ty
60
60
  just release-check
61
61
  just artifact-check
62
62
  ```
63
63
 
64
64
  The combined check stops at the first failure. Resolve the reported type errors and rerun it
65
- until all three checkers pass. `just release-check` alone runs only the default Pyrefly checks.
65
+ until both checkers pass. `just release-check` alone runs only the default Pyrefly checks.
66
66
 
67
67
  `release-check` runs the standard checks, complexity checker, and live GitHub suite. It requires
68
68
  a `tokei` version supported by [the complexity checker](../../tools/check_complexity.py), plus a
@@ -65,6 +65,7 @@
65
65
  "draft",
66
66
  "approved",
67
67
  "changes_requested",
68
+ "review_required",
68
69
  "merged",
69
70
  "closed",
70
71
  "missing",
@@ -149,12 +150,23 @@
149
150
  "properties": {
150
151
  "checks": {
151
152
  "type": "string",
153
+ "description": "Combined result of the checks GitHub has received; passing does not mean every required check has run.",
152
154
  "enum": [
153
155
  "passed",
154
156
  "failed",
155
157
  "pending"
156
158
  ]
157
159
  },
160
+ "merge_state_status": {
161
+ "type": "string",
162
+ "description": "GitHub's reported mergeStateStatus; independent of reviews and checks."
163
+ },
164
+ "merge_details": {
165
+ "$ref": "#/$defs/mergeDetails"
166
+ },
167
+ "merge_details_error": {
168
+ "type": "string"
169
+ },
158
170
  "number": {
159
171
  "type": "integer",
160
172
  "minimum": 1
@@ -165,6 +177,81 @@
165
177
  }
166
178
  }
167
179
  },
180
+ "mergeDetails": {
181
+ "type": "object",
182
+ "additionalProperties": false,
183
+ "required": [
184
+ "unresolved_threads",
185
+ "checks"
186
+ ],
187
+ "properties": {
188
+ "unresolved_threads": {
189
+ "type": "array",
190
+ "items": {
191
+ "type": "object",
192
+ "additionalProperties": false,
193
+ "required": [
194
+ "is_outdated",
195
+ "path",
196
+ "line",
197
+ "body",
198
+ "url"
199
+ ],
200
+ "properties": {
201
+ "is_outdated": {
202
+ "type": "boolean"
203
+ },
204
+ "path": {
205
+ "type": "string"
206
+ },
207
+ "line": {
208
+ "type": [
209
+ "integer",
210
+ "null"
211
+ ]
212
+ },
213
+ "body": {
214
+ "type": "string"
215
+ },
216
+ "url": {
217
+ "type": [
218
+ "string",
219
+ "null"
220
+ ],
221
+ "format": "uri"
222
+ }
223
+ }
224
+ }
225
+ },
226
+ "checks": {
227
+ "type": "array",
228
+ "items": {
229
+ "type": "object",
230
+ "additionalProperties": false,
231
+ "required": [
232
+ "name",
233
+ "state",
234
+ "url"
235
+ ],
236
+ "properties": {
237
+ "name": {
238
+ "type": "string"
239
+ },
240
+ "state": {
241
+ "type": "string"
242
+ },
243
+ "url": {
244
+ "type": [
245
+ "string",
246
+ "null"
247
+ ],
248
+ "format": "uri"
249
+ }
250
+ }
251
+ }
252
+ }
253
+ }
254
+ },
168
255
  "stackRow": {
169
256
  "type": "object",
170
257
  "additionalProperties": false,