jj-stack 0.1.2__tar.gz → 0.1.4__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 (322) hide show
  1. jj_stack-0.1.4/.github/ISSUE_TEMPLATE/bug_report.yml +59 -0
  2. jj_stack-0.1.4/.github/ISSUE_TEMPLATE/config.yml +11 -0
  3. jj_stack-0.1.4/.github/ISSUE_TEMPLATE/feature_request.yml +32 -0
  4. {jj_stack-0.1.2 → jj_stack-0.1.4}/.github/SECURITY.md +2 -2
  5. jj_stack-0.1.4/.github/pull_request_template.md +19 -0
  6. {jj_stack-0.1.2 → jj_stack-0.1.4}/.github/workflows/ci.yml +10 -14
  7. {jj_stack-0.1.2 → jj_stack-0.1.4}/.github/workflows/codeql.yml +2 -2
  8. {jj_stack-0.1.2 → jj_stack-0.1.4}/.github/workflows/release.yml +1 -1
  9. {jj_stack-0.1.2 → jj_stack-0.1.4}/.gitignore +2 -0
  10. {jj_stack-0.1.2 → jj_stack-0.1.4}/AGENTS.md +22 -19
  11. jj_stack-0.1.4/CONTRIBUTING.md +92 -0
  12. {jj_stack-0.1.2 → jj_stack-0.1.4}/PKG-INFO +83 -95
  13. jj_stack-0.1.4/README.md +158 -0
  14. {jj_stack-0.1.2 → jj_stack-0.1.4}/check.py +58 -22
  15. {jj_stack-0.1.2 → jj_stack-0.1.4}/complexity-budget.toml +7 -5
  16. jj_stack-0.1.4/docs/AGENTS.md +57 -0
  17. {jj_stack-0.1.2 → jj_stack-0.1.4}/docs/README.md +7 -7
  18. jj_stack-0.1.4/docs/guides/close-or-separate.md +89 -0
  19. jj_stack-0.1.4/docs/guides/continue-a-stack.md +89 -0
  20. jj_stack-0.1.4/docs/guides/merge-and-sync.md +181 -0
  21. jj_stack-0.1.4/docs/guides/multiple-stacks.md +167 -0
  22. jj_stack-0.1.4/docs/guides/review-a-stack.md +70 -0
  23. jj_stack-0.1.4/docs/guides/revise.md +87 -0
  24. jj_stack-0.1.4/docs/guides/submit-and-update.md +97 -0
  25. jj_stack-0.1.4/docs/guides/working-on-github.md +56 -0
  26. jj_stack-0.1.4/docs/internals/AGENTS.md +20 -0
  27. jj_stack-0.1.4/docs/internals/README.md +45 -0
  28. jj_stack-0.1.4/docs/internals/code-reviews.md +78 -0
  29. jj_stack-0.1.4/docs/internals/design.md +752 -0
  30. jj_stack-0.1.4/docs/internals/property-testing.md +14 -0
  31. jj_stack-0.1.4/docs/internals/releasing.md +118 -0
  32. {jj_stack-0.1.2 → jj_stack-0.1.4}/docs/internals/testing-philosophy.md +29 -12
  33. {jj_stack-0.1.2 → jj_stack-0.1.4}/docs/json-output.schema.json +25 -2
  34. jj_stack-0.1.4/docs/mental-model.md +130 -0
  35. jj_stack-0.1.4/docs/quick-start.md +197 -0
  36. jj_stack-0.1.4/docs/reference/automation.md +127 -0
  37. jj_stack-0.1.4/docs/reference/bookmarks-and-selection.md +127 -0
  38. {jj_stack-0.1.2 → jj_stack-0.1.4}/docs/reference/commands.md +15 -19
  39. jj_stack-0.1.4/docs/reference/configuration.md +127 -0
  40. jj_stack-0.1.4/docs/reference/descriptions.md +94 -0
  41. jj_stack-0.1.4/docs/reference/json-output.md +190 -0
  42. jj_stack-0.1.4/docs/tool-comparison.md +128 -0
  43. jj_stack-0.1.4/docs/troubleshooting.md +280 -0
  44. {jj_stack-0.1.2 → jj_stack-0.1.4}/evals/jj-stack-skill.md +5 -5
  45. {jj_stack-0.1.2 → jj_stack-0.1.4}/justfile +8 -6
  46. {jj_stack-0.1.2 → jj_stack-0.1.4}/pyproject.toml +16 -4
  47. {jj_stack-0.1.2 → jj_stack-0.1.4}/release-notes/v0.1.2.md +1 -1
  48. jj_stack-0.1.4/release-notes/v0.1.3.md +27 -0
  49. jj_stack-0.1.4/release-notes/v0.1.4.md +23 -0
  50. {jj_stack-0.1.2 → jj_stack-0.1.4}/scripts/describe_with_claude.py +5 -5
  51. {jj_stack-0.1.2 → jj_stack-0.1.4}/scripts/describe_with_codex.py +5 -5
  52. {jj_stack-0.1.2 → jj_stack-0.1.4}/scripts/describe_with_prompt.py +3 -4
  53. {jj_stack-0.1.2 → jj_stack-0.1.4}/skills/jj-stack/SKILL.md +50 -37
  54. jj_stack-0.1.4/skills/jj-stack/references/multi-stack.md +91 -0
  55. {jj_stack-0.1.2 → jj_stack-0.1.4}/skills/jj-stack/references/recovery.md +27 -24
  56. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/bootstrap.py +24 -48
  57. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/cli.py +189 -277
  58. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/cli_help.py +56 -70
  59. jj_stack-0.1.4/src/jj_stack/commands/_json_status.py +62 -0
  60. jj_stack-0.1.4/src/jj_stack/commands/checkout.py +615 -0
  61. jj_stack-0.1.4/src/jj_stack/commands/cleanup/actions.py +265 -0
  62. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/commands/cleanup/command.py +247 -262
  63. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/commands/doctor.py +149 -112
  64. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/commands/in_use.py +6 -9
  65. jj_stack-0.1.4/src/jj_stack/commands/list_.py +524 -0
  66. jj_stack-0.1.4/src/jj_stack/commands/merge/command.py +401 -0
  67. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/commands/merge/github_stack.py +50 -93
  68. jj_stack-0.1.4/src/jj_stack/commands/merge/plan.py +269 -0
  69. jj_stack-0.1.4/src/jj_stack/commands/relink.py +232 -0
  70. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/commands/submit/auto_close.py +18 -23
  71. jj_stack-0.1.4/src/jj_stack/commands/submit/changes.py +153 -0
  72. jj_stack-0.1.4/src/jj_stack/commands/submit/command.py +586 -0
  73. jj_stack-0.1.4/src/jj_stack/commands/submit/descriptions.py +342 -0
  74. jj_stack-0.1.4/src/jj_stack/commands/submit/editor.py +277 -0
  75. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/commands/submit/github_stack.py +22 -53
  76. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/commands/submit/inputs.py +70 -31
  77. jj_stack-0.1.4/src/jj_stack/commands/submit/managed_comments.py +38 -0
  78. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/commands/submit/models.py +42 -82
  79. jj_stack-0.1.4/src/jj_stack/commands/submit/overview_comments.py +123 -0
  80. jj_stack-0.1.4/src/jj_stack/commands/submit/prs.py +207 -0
  81. jj_stack-0.1.4/src/jj_stack/commands/submit/publication.py +279 -0
  82. jj_stack-0.1.4/src/jj_stack/commands/submit/render.py +139 -0
  83. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/commands/submit/revision_comments.py +23 -38
  84. jj_stack-0.1.4/src/jj_stack/commands/sync.py +464 -0
  85. jj_stack-0.1.4/src/jj_stack/commands/sync_apply.py +439 -0
  86. jj_stack-0.1.4/src/jj_stack/commands/sync_prs.py +118 -0
  87. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/commands/unstack.py +75 -83
  88. jj_stack-0.1.4/src/jj_stack/commands/view.py +778 -0
  89. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/completion.py +5 -8
  90. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/concurrency.py +23 -15
  91. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/config.py +73 -44
  92. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/console.py +109 -73
  93. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/errors.py +48 -2
  94. jj_stack-0.1.4/src/jj_stack/formatting.py +103 -0
  95. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/github/client.py +364 -257
  96. jj_stack-0.1.4/src/jj_stack/github/error_messages.py +134 -0
  97. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/github/pr_refs.py +35 -1
  98. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/github/resolution.py +50 -21
  99. jj_stack-0.1.4/src/jj_stack/identifiers.py +23 -0
  100. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/jj/cli_args.py +0 -3
  101. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/jj/client.py +288 -389
  102. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/jj/colors.py +26 -91
  103. jj_stack-0.1.4/src/jj_stack/jj/settings.py +63 -0
  104. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/models/github.py +43 -37
  105. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/models/stack.py +14 -19
  106. jj_stack-0.1.4/src/jj_stack/models/tracking.py +52 -0
  107. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/pr_branch_namespace.py +13 -10
  108. jj_stack-0.1.4/src/jj_stack/stack/change_state.py +709 -0
  109. jj_stack-0.1.4/src/jj_stack/stack/convergence.py +519 -0
  110. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/stack/convergence_models.py +17 -23
  111. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/stack/convergence_observation.py +36 -36
  112. jj_stack-0.1.4/src/jj_stack/stack/divergence.py +20 -0
  113. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/stack/github_stack_safety.py +23 -37
  114. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/stack/global_convergence.py +80 -99
  115. jj_stack-0.1.4/src/jj_stack/stack/observation.py +174 -0
  116. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/stack/path.py +48 -38
  117. jj_stack-0.1.4/src/jj_stack/stack/pr_branches.py +148 -0
  118. jj_stack-0.1.4/src/jj_stack/stack/pr_facts.py +200 -0
  119. jj_stack-0.1.4/src/jj_stack/stack/preparation.py +84 -0
  120. jj_stack-0.1.4/src/jj_stack/stack/repo.py +71 -0
  121. jj_stack-0.1.4/src/jj_stack/stack/reporting.py +182 -0
  122. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/stack/selected.py +70 -55
  123. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/stack/selection.py +16 -58
  124. jj_stack-0.1.4/src/jj_stack/stack/status.py +255 -0
  125. jj_stack-0.1.4/src/jj_stack/stack/trunk.py +48 -0
  126. jj_stack-0.1.4/src/jj_stack/stack/trunk_evidence.py +51 -0
  127. jj_stack-0.1.4/src/jj_stack/state/migrations.py +57 -0
  128. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/state/operation_lock.py +54 -28
  129. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/state/store.py +25 -51
  130. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/ui.py +5 -15
  131. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/conftest.py +28 -0
  132. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/integration/conftest.py +0 -18
  133. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/integration/submit_command_helpers.py +0 -32
  134. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/integration/test_boundary_conditions.py +8 -14
  135. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/integration/test_checkout_command.py +150 -66
  136. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/integration/test_cleanup_command.py +154 -67
  137. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/integration/test_doctor_command.py +61 -39
  138. jj_stack-0.1.4/tests/integration/test_fake_github_contracts.py +114 -0
  139. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/integration/test_jj_stack.py +103 -63
  140. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/integration/test_list_command.py +53 -54
  141. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/integration/test_merge_command.py +128 -92
  142. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/integration/test_relink_command.py +33 -37
  143. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/integration/test_submit_command.py +442 -362
  144. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/integration/test_sync_command.py +339 -160
  145. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/integration/test_unstack_command.py +37 -32
  146. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/integration/test_view_command.py +106 -111
  147. jj_stack-0.1.4/tests/property/test_submit_property_scenarios.py +105 -0
  148. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/run_live_github.py +5 -9
  149. jj_stack-0.1.4/tests/run_submit_property_scenarios.py +122 -0
  150. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/support/change_helpers.py +11 -3
  151. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/support/contexts.py +2 -5
  152. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/support/fake_github.py +145 -121
  153. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/support/integration_helpers.py +105 -48
  154. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/support/stack_edit_scenarios.py +0 -6
  155. jj_stack-0.1.4/tests/support/stack_machine.py +1291 -0
  156. jj_stack-0.1.4/tests/support/submit_faults.py +91 -0
  157. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/support/tracking.py +1 -1
  158. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/unit/test_bootstrap.py +3 -37
  159. jj_stack-0.1.4/tests/unit/test_change_state.py +201 -0
  160. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/unit/test_check_script.py +2 -39
  161. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/unit/test_checkout.py +1 -1
  162. jj_stack-0.1.4/tests/unit/test_cleanup.py +20 -0
  163. jj_stack-0.1.4/tests/unit/test_cli.py +166 -0
  164. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/unit/test_cli_dispatch.py +22 -7
  165. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/unit/test_completion.py +7 -6
  166. jj_stack-0.1.4/tests/unit/test_config.py +81 -0
  167. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/unit/test_describe_with_editor_script.py +4 -20
  168. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/unit/test_describe_with_prompt_script.py +4 -29
  169. jj_stack-0.1.4/tests/unit/test_divergence.py +15 -0
  170. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/unit/test_errors.py +5 -8
  171. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/unit/test_github_client.py +339 -117
  172. jj_stack-0.1.4/tests/unit/test_github_error_messages.py +52 -0
  173. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/unit/test_github_models.py +28 -7
  174. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/unit/test_github_resolution.py +28 -11
  175. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/unit/test_github_stack_planning.py +20 -32
  176. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/unit/test_in_use_command.py +4 -3
  177. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/unit/test_jj_client.py +136 -198
  178. jj_stack-0.1.4/tests/unit/test_jj_settings.py +86 -0
  179. jj_stack-0.1.4/tests/unit/test_merge.py +227 -0
  180. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/unit/test_operation_lock.py +19 -2
  181. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/unit/test_pr_branches.py +43 -31
  182. jj_stack-0.1.4/tests/unit/test_pr_facts.py +112 -0
  183. jj_stack-0.1.4/tests/unit/test_property_runner.py +53 -0
  184. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/unit/test_relink.py +19 -30
  185. jj_stack-0.1.4/tests/unit/test_selected.py +44 -0
  186. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/unit/test_stack_path.py +27 -50
  187. jj_stack-0.1.4/tests/unit/test_stack_status.py +152 -0
  188. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/unit/test_store.py +38 -64
  189. jj_stack-0.1.4/tests/unit/test_submit.py +176 -0
  190. jj_stack-0.1.4/tests/unit/test_submit_descriptions.py +121 -0
  191. jj_stack-0.1.2/tests/unit/test_submit_descriptions.py → jj_stack-0.1.4/tests/unit/test_submit_editor.py +26 -108
  192. jj_stack-0.1.4/tests/unit/test_trunk_evidence.py +95 -0
  193. jj_stack-0.1.4/tests/unit/test_ui.py +154 -0
  194. jj_stack-0.1.4/tests/unit/test_view.py +299 -0
  195. jj_stack-0.1.4/tests/unit/test_view_entrypoint.py +212 -0
  196. {jj_stack-0.1.2 → jj_stack-0.1.4}/tools/check_complexity.py +6 -7
  197. {jj_stack-0.1.2 → jj_stack-0.1.4}/tools/check_jj_release_updates.py +2 -2
  198. jj_stack-0.1.4/tools/install-jj-release.sh +176 -0
  199. jj_stack-0.1.4/uv.lock +915 -0
  200. jj_stack-0.1.2/README.md +0 -170
  201. jj_stack-0.1.2/docs/AGENTS.md +0 -75
  202. jj_stack-0.1.2/docs/guides/close-or-separate.md +0 -70
  203. jj_stack-0.1.2/docs/guides/continue-a-stack.md +0 -57
  204. jj_stack-0.1.2/docs/guides/merge-and-sync.md +0 -146
  205. jj_stack-0.1.2/docs/guides/multiple-stacks.md +0 -113
  206. jj_stack-0.1.2/docs/guides/review-a-stack.md +0 -60
  207. jj_stack-0.1.2/docs/guides/revise.md +0 -54
  208. jj_stack-0.1.2/docs/guides/submit-and-update.md +0 -111
  209. jj_stack-0.1.2/docs/guides/working-on-github.md +0 -55
  210. jj_stack-0.1.2/docs/internals/AGENTS.md +0 -30
  211. jj_stack-0.1.2/docs/internals/README.md +0 -22
  212. jj_stack-0.1.2/docs/internals/code-reviews.md +0 -113
  213. jj_stack-0.1.2/docs/internals/design.md +0 -952
  214. jj_stack-0.1.2/docs/internals/implementation-strategy.md +0 -117
  215. jj_stack-0.1.2/docs/internals/property-testing.md +0 -54
  216. jj_stack-0.1.2/docs/internals/releasing.md +0 -71
  217. jj_stack-0.1.2/docs/mental-model.md +0 -66
  218. jj_stack-0.1.2/docs/quick-start.md +0 -131
  219. jj_stack-0.1.2/docs/reference/automation.md +0 -133
  220. jj_stack-0.1.2/docs/reference/bookmarks-and-selection.md +0 -149
  221. jj_stack-0.1.2/docs/reference/configuration.md +0 -75
  222. jj_stack-0.1.2/docs/reference/descriptions.md +0 -84
  223. jj_stack-0.1.2/docs/reference/json-output.md +0 -165
  224. jj_stack-0.1.2/docs/tool-comparison.md +0 -215
  225. jj_stack-0.1.2/docs/troubleshooting.md +0 -197
  226. jj_stack-0.1.2/skills/jj-stack/references/multi-stack.md +0 -84
  227. jj_stack-0.1.2/src/jj_stack/commands/_cleanup_actions.py +0 -331
  228. jj_stack-0.1.2/src/jj_stack/commands/_json_status.py +0 -85
  229. jj_stack-0.1.2/src/jj_stack/commands/checkout.py +0 -669
  230. jj_stack-0.1.2/src/jj_stack/commands/cleanup/shared.py +0 -62
  231. jj_stack-0.1.2/src/jj_stack/commands/cleanup/stale.py +0 -79
  232. jj_stack-0.1.2/src/jj_stack/commands/list_.py +0 -695
  233. jj_stack-0.1.2/src/jj_stack/commands/merge/command.py +0 -389
  234. jj_stack-0.1.2/src/jj_stack/commands/merge/models.py +0 -96
  235. jj_stack-0.1.2/src/jj_stack/commands/merge/plan.py +0 -108
  236. jj_stack-0.1.2/src/jj_stack/commands/merge/preconditions.py +0 -157
  237. jj_stack-0.1.2/src/jj_stack/commands/merge/render.py +0 -52
  238. jj_stack-0.1.2/src/jj_stack/commands/relink.py +0 -228
  239. jj_stack-0.1.2/src/jj_stack/commands/submit/changes.py +0 -90
  240. jj_stack-0.1.2/src/jj_stack/commands/submit/command.py +0 -893
  241. jj_stack-0.1.2/src/jj_stack/commands/submit/comments.py +0 -62
  242. jj_stack-0.1.2/src/jj_stack/commands/submit/descriptions.py +0 -663
  243. jj_stack-0.1.2/src/jj_stack/commands/submit/overview_comments.py +0 -189
  244. jj_stack-0.1.2/src/jj_stack/commands/submit/prs.py +0 -449
  245. jj_stack-0.1.2/src/jj_stack/commands/submit/render.py +0 -135
  246. jj_stack-0.1.2/src/jj_stack/commands/sync.py +0 -512
  247. jj_stack-0.1.2/src/jj_stack/commands/sync_apply.py +0 -484
  248. jj_stack-0.1.2/src/jj_stack/commands/view.py +0 -1187
  249. jj_stack-0.1.2/src/jj_stack/formatting.py +0 -134
  250. jj_stack-0.1.2/src/jj_stack/github/error_messages.py +0 -89
  251. jj_stack-0.1.2/src/jj_stack/identifiers.py +0 -7
  252. jj_stack-0.1.2/src/jj_stack/models/tracking.py +0 -93
  253. jj_stack-0.1.2/src/jj_stack/stack/change_status.py +0 -223
  254. jj_stack-0.1.2/src/jj_stack/stack/convergence.py +0 -488
  255. jj_stack-0.1.2/src/jj_stack/stack/pr_branches.py +0 -123
  256. jj_stack-0.1.2/src/jj_stack/stack/pr_facts.py +0 -167
  257. jj_stack-0.1.2/src/jj_stack/stack/repo.py +0 -95
  258. jj_stack-0.1.2/src/jj_stack/stack/status.py +0 -665
  259. jj_stack-0.1.2/src/jj_stack/stack/trunk_evidence.py +0 -170
  260. jj_stack-0.1.2/src/jj_stack/state/migrations.py +0 -63
  261. jj_stack-0.1.2/tests/property/test_submit_property_scenarios.py +0 -328
  262. jj_stack-0.1.2/tests/run_submit_property_scenarios.py +0 -240
  263. jj_stack-0.1.2/tests/support/submit_property_harness.py +0 -1168
  264. jj_stack-0.1.2/tests/support/submit_property_scenarios.py +0 -1199
  265. jj_stack-0.1.2/tests/unit/conftest.py +0 -14
  266. jj_stack-0.1.2/tests/unit/test_change_status.py +0 -86
  267. jj_stack-0.1.2/tests/unit/test_change_status_topology.py +0 -113
  268. jj_stack-0.1.2/tests/unit/test_cleanup.py +0 -191
  269. jj_stack-0.1.2/tests/unit/test_cli.py +0 -298
  270. jj_stack-0.1.2/tests/unit/test_config.py +0 -172
  271. jj_stack-0.1.2/tests/unit/test_list.py +0 -25
  272. jj_stack-0.1.2/tests/unit/test_merge.py +0 -167
  273. jj_stack-0.1.2/tests/unit/test_property_runner.py +0 -50
  274. jj_stack-0.1.2/tests/unit/test_selection.py +0 -24
  275. jj_stack-0.1.2/tests/unit/test_stack_status.py +0 -237
  276. jj_stack-0.1.2/tests/unit/test_submit.py +0 -350
  277. jj_stack-0.1.2/tests/unit/test_trunk_evidence.py +0 -171
  278. jj_stack-0.1.2/tests/unit/test_ui.py +0 -240
  279. jj_stack-0.1.2/tests/unit/test_view.py +0 -397
  280. jj_stack-0.1.2/tests/unit/test_view_entrypoint.py +0 -252
  281. jj_stack-0.1.2/tools/install-jj-release.sh +0 -266
  282. jj_stack-0.1.2/uv.lock +0 -587
  283. {jj_stack-0.1.2 → jj_stack-0.1.4}/.github/dependabot.yml +0 -0
  284. {jj_stack-0.1.2 → jj_stack-0.1.4}/.github/workflows/block-pr-base-merges.yml +0 -0
  285. {jj_stack-0.1.2 → jj_stack-0.1.4}/.github/workflows/check-jj-release-updates.yml +0 -0
  286. {jj_stack-0.1.2 → jj_stack-0.1.4}/CLAUDE.md +0 -0
  287. {jj_stack-0.1.2 → jj_stack-0.1.4}/LICENSE +0 -0
  288. {jj_stack-0.1.2 → jj_stack-0.1.4}/NOTICE +0 -0
  289. {jj_stack-0.1.2 → jj_stack-0.1.4}/scripts/README.md +0 -0
  290. {jj_stack-0.1.2 → jj_stack-0.1.4}/scripts/describe_with_editor.py +0 -0
  291. {jj_stack-0.1.2 → jj_stack-0.1.4}/skills/jj-stack/agents/openai.yaml +0 -0
  292. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/__init__.py +0 -0
  293. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/__main__.py +0 -0
  294. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/commands/__init__.py +0 -0
  295. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/commands/merge/__init__.py +0 -0
  296. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/commands/submit/__init__.py +0 -0
  297. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/commands/submit/default_pr_text.py +0 -0
  298. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/github/__init__.py +0 -0
  299. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/github/auth.py +0 -0
  300. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/github/overview_comments.py +0 -0
  301. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/github/stack_availability.py +0 -0
  302. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/jj/__init__.py +0 -0
  303. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/models/__init__.py +0 -0
  304. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/models/git.py +0 -0
  305. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/stack/__init__.py +0 -0
  306. {jj_stack-0.1.2 → jj_stack-0.1.4}/src/jj_stack/state/__init__.py +0 -0
  307. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/__init__.py +0 -0
  308. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/integration/__init__.py +0 -0
  309. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/support/__init__.py +0 -0
  310. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/support/json_schema.py +0 -0
  311. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/support/output_assertions.py +0 -0
  312. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/support/pytest_concurrency.py +0 -0
  313. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/unit/__init__.py +0 -0
  314. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/unit/test_concurrency.py +0 -0
  315. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/unit/test_default_pr_text.py +0 -0
  316. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/unit/test_github_auth.py +0 -0
  317. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/unit/test_live_github_runner.py +0 -0
  318. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/unit/test_pr_refs.py +0 -0
  319. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/unit/test_property_scenarios.py +0 -0
  320. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/unit/test_sync.py +0 -0
  321. {jj_stack-0.1.2 → jj_stack-0.1.4}/tests/unit/test_unstack.py +0 -0
  322. {jj_stack-0.1.2 → jj_stack-0.1.4}/tools/check_release_artifacts.py +0 -0
@@ -0,0 +1,59 @@
1
+ name: Bug report
2
+ description: Report incorrect or surprising jj-stack behavior.
3
+ labels: ["bug"]
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: |
8
+ Before filing, check [Troubleshooting](https://www.serpentine.com/software/jj-stack/troubleshooting/).
9
+ Many errors end with a `Hint:` that resolves them.
10
+
11
+ Do not paste private repository contents, tokens, or internal URLs.
12
+ - type: textarea
13
+ id: what-happened
14
+ attributes:
15
+ label: What happened
16
+ description: What you ran, what you expected, and what jj-stack did instead.
17
+ placeholder: |
18
+ I ran `jj-stack submit` on a three-change stack and expected ...
19
+ Instead it ...
20
+ validations:
21
+ required: true
22
+ - type: textarea
23
+ id: repro
24
+ attributes:
25
+ label: Steps to reproduce
26
+ description: >-
27
+ The local stack shape and the commands you ran, in order. `jj log` output for the
28
+ affected stack is usually the most useful thing you can include.
29
+ validations:
30
+ required: true
31
+ - type: textarea
32
+ id: doctor
33
+ attributes:
34
+ label: Output of `jj-stack doctor`
35
+ description: Run it in the affected repo. It reports repo setup, GitHub access, and leftovers.
36
+ render: console
37
+ validations:
38
+ required: false
39
+ - type: input
40
+ id: jj-stack-version
41
+ attributes:
42
+ label: jj-stack version
43
+ description: Output of `jj-stack --version`.
44
+ validations:
45
+ required: true
46
+ - type: input
47
+ id: jj-version
48
+ attributes:
49
+ label: jj version
50
+ description: Output of `jj --version`.
51
+ validations:
52
+ required: true
53
+ - type: input
54
+ id: platform
55
+ attributes:
56
+ label: Operating system
57
+ placeholder: macOS 15.5, Ubuntu 24.04, Windows 11
58
+ validations:
59
+ required: true
@@ -0,0 +1,11 @@
1
+ blank_issues_enabled: true
2
+ contact_links:
3
+ - name: Documentation
4
+ url: https://www.serpentine.com/software/jj-stack/
5
+ about: Guides, command reference, configuration, and automation.
6
+ - name: Troubleshooting
7
+ url: https://www.serpentine.com/software/jj-stack/troubleshooting/
8
+ about: Recovery steps for the common failure symptoms, organized by what you saw.
9
+ - name: Report a security vulnerability
10
+ url: https://github.com/bos/jj-stack/security/advisories/new
11
+ about: Use private vulnerability reporting. Do not open a public issue.
@@ -0,0 +1,32 @@
1
+ name: Feature request
2
+ description: Suggest a capability or a change to an existing one.
3
+ labels: ["enhancement"]
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: |
8
+ jj-stack is deliberately opinionated: one `jj` change is one pull request, and it owns the
9
+ generated PR branches. [Compare tools](https://www.serpentine.com/software/jj-stack/tool-comparison/)
10
+ explains what that rules out. A request that conflicts with those choices may still be
11
+ worth making — say why the stance should change.
12
+ - type: textarea
13
+ id: problem
14
+ attributes:
15
+ label: The problem
16
+ description: The workflow you are trying to complete, and where jj-stack gets in the way.
17
+ validations:
18
+ required: true
19
+ - type: textarea
20
+ id: proposal
21
+ attributes:
22
+ label: What you would like instead
23
+ description: The behavior you want. Include the command and output you imagine, if you have one.
24
+ validations:
25
+ required: true
26
+ - type: textarea
27
+ id: alternatives
28
+ attributes:
29
+ label: What you do today
30
+ description: The workaround you currently use, and why it is not good enough.
31
+ validations:
32
+ required: false
@@ -8,8 +8,8 @@ This project is under active development. Security fixes are supported on `main`
8
8
 
9
9
  Please do not report security vulnerabilities in public GitHub issues.
10
10
 
11
- Use GitHub's private vulnerability reporting for this repo if it is enabled. If you cannot
12
- use private reporting, contact the maintainers directly and include:
11
+ Use [private vulnerability reporting](https://github.com/bos/jj-stack/security/advisories/new),
12
+ which is enabled for this repo. Include:
13
13
 
14
14
  - a description of the issue
15
15
  - steps to reproduce or a proof of concept
@@ -0,0 +1,19 @@
1
+ <!--
2
+ See CONTRIBUTING.md. For a substantial change, please open an issue first.
3
+ Commit subjects use `scope: summary`; explain why in the body, wrapped at 72 columns.
4
+ -->
5
+
6
+ ## What this changes
7
+
8
+ <!-- The user-visible behavior or rule this adds, alters, or fixes. -->
9
+
10
+ ## Why
11
+
12
+ <!-- The motivation. For a fix, the symptom that is gone. -->
13
+
14
+ ## Checks
15
+
16
+ - [ ] `just check` passes
17
+ - [ ] `just complexity` passes, or the pull request explains why a budget must change
18
+ - [ ] Documentation updated, or not required by the rules in `AGENTS.md`
19
+ - [ ] Website snapshot refreshed with `just website` if user-facing docs or `--help` changed
@@ -23,11 +23,12 @@ jobs:
23
23
  python-version: "3.14"
24
24
 
25
25
  - name: Install tokei
26
- env:
27
- # Must match TOKEI_VERSION in tools/check_complexity.py; the budgets are baselined
28
- # against this exact counter. 14.0.0 publishes no prebuilt binaries, so build it.
29
- TOKEI_VERSION: 14.0.0
30
- run: cargo install tokei --locked --version "$TOKEI_VERSION"
26
+ run: |
27
+ TOKEI_VERSION="$(
28
+ uv run --no-project --python 3.14 python -c \
29
+ 'from tools.check_complexity import TOKEI_VERSIONS; print(TOKEI_VERSIONS[-1])'
30
+ )"
31
+ cargo install tokei --locked --version "^$TOKEI_VERSION"
31
32
 
32
33
  - name: Install project environment
33
34
  run: uv sync --locked
@@ -39,7 +40,7 @@ jobs:
39
40
  strategy:
40
41
  fail-fast: false
41
42
  matrix:
42
- jj-version: ["v0.44.0"]
43
+ jj-version: ["v0.45.1"]
43
44
  os: [ubuntu-latest, macos-latest, windows-latest]
44
45
  python-version: ["3.14"]
45
46
  runs-on: ${{ matrix.os }}
@@ -71,7 +72,7 @@ jobs:
71
72
  submit-property-smoke:
72
73
  runs-on: ubuntu-latest
73
74
  env:
74
- JJ_VERSION: v0.44.0
75
+ JJ_VERSION: v0.45.1
75
76
 
76
77
  steps:
77
78
  - name: Check out repo
@@ -85,11 +86,6 @@ jobs:
85
86
  - name: Install jj
86
87
  run: echo "$(tools/install-jj-release.sh "$JJ_VERSION")" >> "$GITHUB_PATH"
87
88
 
88
- - name: Run submit property smoke scenarios
89
+ - name: Run generated client and server sequences
89
90
  run: >-
90
- tests/run_submit_property_scenarios.py 10 --random-seed -n auto
91
- --stack-join-scenarios 5
92
- --lifecycle-scenarios 10
93
- --stack-move-scenarios 5
94
- --retry-scenarios 5
95
- --drift-scenarios 21
91
+ tests/run_submit_property_scenarios.py 5 --steps 20 --shards 8 --random-seed -n auto
@@ -23,10 +23,10 @@ jobs:
23
23
  uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
24
24
 
25
25
  - name: Initialize CodeQL
26
- uses: github/codeql-action/init@v4.37.7
26
+ uses: github/codeql-action/init@v4.37.9
27
27
  with:
28
28
  languages: python
29
29
  build-mode: none
30
30
 
31
31
  - name: Analyze
32
- uses: github/codeql-action/analyze@v4.37.7
32
+ uses: github/codeql-action/analyze@v4.37.9
@@ -19,7 +19,7 @@ concurrency:
19
19
  cancel-in-progress: false
20
20
 
21
21
  env:
22
- JJ_VERSION: v0.44.0
22
+ JJ_VERSION: v0.45.1
23
23
 
24
24
  jobs:
25
25
  build:
@@ -10,3 +10,5 @@ htmlcov/
10
10
  .uv-cache/
11
11
  .venv
12
12
  .venv/
13
+
14
+ .hypothesis/
@@ -1,15 +1,15 @@
1
- ## Complexity control
1
+ # Complexity control
2
2
 
3
3
  - A replacement is incomplete until it deletes the mechanism it supersedes in the same change.
4
- Do not add a temporary parallel model with a promise to remove it in a later cleanup slice.
5
- - Define each jj-stack-owned durable policy fact once and store it one way. Shared observation or
6
- storage code must not create a second path for deciding or changing it.
4
+ Do not keep a parallel model for a later cleanup.
5
+ - Store each persistent fact in one form, with one owner. Shared observation and storage code
6
+ must not introduce competing policy decisions.
7
7
  - Batch independent read-only facts, but keep dependent mutations in order. Bind an irreversible
8
8
  external mutation to the identity and version observed while planning when the platform
9
9
  supports a conditional write or lease. Re-observe only when an earlier mutation invalidates a
10
10
  precondition or when an observed trigger or platform contract requires it.
11
- - Apply the cumulative complexity budgets after every code slice. Run `just complexity` locally
12
- when the pinned `tokei` is installed; CI invokes the underlying checker. A budget increase is a
11
+ - Check the cumulative complexity budgets after each code change. Run `just complexity` locally
12
+ when a supported `tokei` is installed; CI invokes the underlying checker. A budget increase is a
13
13
  design stop that requires explicit review, not routine maintenance of the budget file.
14
14
  - If the same subsystem needs a third consecutive hardening change, stop patching it and
15
15
  re-derive the design from the core invariants.
@@ -22,6 +22,7 @@
22
22
  - Run the CLI locally with `just run ...` instead of invoking the module or virtualenv path
23
23
  directly.
24
24
  - Hard-wrap code and markdown files at 98 columns unless a file uses a different convention.
25
+ Release-note prose follows `docs/internals/releasing.md` and is intentionally unwrapped.
25
26
 
26
27
  # Commit messages
27
28
 
@@ -37,25 +38,26 @@
37
38
 
38
39
  # Documentation
39
40
 
40
- - User-facing docs live in `docs/`. See [docs/AGENTS.md](docs/AGENTS.md) for the vocabulary
41
- rules and the public/internal split. Built-in `--help` text is held to the same standard as
42
- the user docs: assume jj/git familiarity, avoid `jj-stack` internal design jargon.
41
+ - User-facing docs live in `docs/`, except for contributor notes in `docs/internals/`. See
42
+ [docs/AGENTS.md](docs/AGENTS.md) for the vocabulary rules and the public/internal split.
43
+ Built-in `--help` text is held to the same standard as the user docs: assume jj/git familiarity,
44
+ avoid `jj-stack` internal design jargon.
43
45
  - The web version of the user docs normally lives in the sibling jj repository at
44
46
  `$(jj root)/../website`. When user-facing docs change here, run `just website`, inspect the
45
47
  corresponding website changes, and update them as needed. If the change here is committed,
46
48
  commit the corresponding website update in that repository as well; preserve unrelated work in
47
49
  either working copy.
48
50
  - Active internal docs use ordinary technical language too. Introduce a project-specific term
49
- only when it names a real type, field, or enduring rule, define it at first use, and prefer
51
+ only when it names an existing type, field, or enduring rule, define it at first use, and prefer
50
52
  describing concrete inputs and effects.
51
- - `design.md` and `implementation-strategy.md` describe the current product and architecture, not
52
- completed slices or abandoned mechanisms. Keep implementation history in `jj` commits.
53
- - Default to code and tests only. Update documentation only when a change intentionally adds or
54
- changes a supported product rule or user workflow, or makes a specific existing statement
55
- materially inaccurate. A bug and its fix are not by themselves a documentation trigger.
53
+ - Internal design and strategy documents describe the current product and architecture. Keep
54
+ implementation history in `jj` commits.
55
+ - For implementation work, update documentation when a change adds or alters a supported rule or
56
+ workflow, or makes an existing statement inaccurate. A bug fix alone does not require a docs
57
+ change. Documentation reviews and corrections can also address clarity, duplication, and gaps.
56
58
  - When documentation is required, update only the affected source: `design.md` for an enduring
57
- product rule, user docs or `--help` for user guidance, and `implementation-strategy.md` for an
58
- architecture, tooling, or test-layer strategy change.
59
+ product rule, user docs or `--help` for user guidance, and the relevant testing document for
60
+ test strategy.
59
61
 
60
62
  # Behaviour changes
61
63
 
@@ -66,8 +68,9 @@
66
68
  the other way around: evaluate a documented behavior on its merits before extending it, and
67
69
  prefer deleting case-specific rules that follow from the principles over adding new ones. Never
68
70
  add durable transaction or replay state; recovery is observational (see design.md).
69
- - Preserve the core invariants: the `jj` DAG determines stack topology, local cache is sparse,
70
- GitHub pull requests are derived from the local `jj` stack, and ambiguous linkage fails closed.
71
+ - Preserve the core invariants: the `jj` DAG determines stack topology, tracking stores only PR
72
+ links and submitted commits, GitHub PRs follow the local stack, and ambiguous linkage stops
73
+ mutation.
71
74
 
72
75
  # Testing
73
76
 
@@ -0,0 +1,92 @@
1
+ # Contributing
2
+
3
+ Thanks for your interest in `jj-stack`.
4
+
5
+ ## Before you start
6
+
7
+ Open an issue before writing a substantial change. `jj-stack` is deliberately opinionated about
8
+ what it manages and what it leaves to `jj`, so a feature that fits your workflow may still be out
9
+ of scope. [Compare tools](docs/tool-comparison.md) explains the stance and its trade-offs.
10
+
11
+ Bug reports, documentation corrections, and small focused fixes are welcome without prior
12
+ discussion.
13
+
14
+ ## Development setup
15
+
16
+ You need `uv`, Git, `jj` 0.45.1 or newer, and `just`. The project requires Python 3.14 or newer;
17
+ `uv` can provide the interpreter when it creates the locked development environment:
18
+
19
+ ```console
20
+ just setup
21
+ ```
22
+
23
+ Run `just` on its own to list every recipe.
24
+
25
+ ## Working on a change
26
+
27
+ Run the CLI from your checkout with `just run ...` rather than invoking the module or the
28
+ virtualenv path directly:
29
+
30
+ ```console
31
+ just run view
32
+ ```
33
+
34
+ Before finishing a code change, run the standard Ruff, type-check, and test pass. Docs-only edits
35
+ under `docs/` do not require it:
36
+
37
+ ```console
38
+ just check
39
+ ```
40
+
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`:
43
+
44
+ ```console
45
+ just check -t ty
46
+ just check -t mypy
47
+ ```
48
+
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).
56
+
57
+ Run focused tests while you iterate:
58
+
59
+ ```console
60
+ just test tests/unit/test_jj_client.py
61
+ ```
62
+
63
+ CI also enforces the cumulative complexity budgets. Check them locally with `just complexity`
64
+ when a supported `tokei` is installed. Raising a budget is a design decision, not routine
65
+ maintenance — say why in the pull request.
66
+
67
+ If your change touches user-facing guides or references, refresh the website snapshot with
68
+ `just website` and include the resulting change in the sibling `website` repository.
69
+
70
+ ## Conventions
71
+
72
+ [`AGENTS.md`](AGENTS.md) is the working agreement for this repo, and it applies to human
73
+ contributors too. It covers commit message format, the 98-column wrap, when documentation
74
+ changes are required, and where each kind of documentation belongs. The internal notes under
75
+ [`docs/internals/`](docs/internals/) cover the design, testing philosophy, and review standard.
76
+
77
+ The short version:
78
+
79
+ - Write commit subjects as `scope: summary`, lowercase, no trailing period.
80
+ - Explain *why* the change exists in the body, wrapped at 72 columns.
81
+ - Add tests at the narrowest layer that covers a distinct risk; consolidate overlapping coverage
82
+ rather than adding parallel cases.
83
+ - For code changes, update docs when supported rules, workflows, or existing statements change.
84
+ Documentation corrections and editorial improvements are welcome independently.
85
+
86
+ ## Submitting
87
+
88
+ Pull requests go to `main`. `jj-stack` is developed with `jj-stack`, so a stacked series of small
89
+ changes is easy to review and very welcome.
90
+
91
+ By contributing, you agree that your contributions are licensed under the
92
+ [Apache License 2.0](LICENSE).
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: jj-stack
3
- Version: 0.1.2
3
+ Version: 0.1.4
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/
@@ -20,7 +20,7 @@ Classifier: Programming Language :: Python :: 3.14
20
20
  Classifier: Topic :: Software Development :: Version Control
21
21
  Classifier: Topic :: Software Development :: Version Control :: Git
22
22
  Requires-Python: >=3.14
23
- Requires-Dist: httpxyz<0.32,>=0.31.0
23
+ Requires-Dist: httpx2<3,>=2.12.0
24
24
  Requires-Dist: markdown-it-py<5,>=4.0.0
25
25
  Requires-Dist: pydantic<3,>=2.13.3
26
26
  Requires-Dist: rich<16,>=15.0.0
@@ -29,64 +29,26 @@ Description-Content-Type: text/markdown
29
29
  # jj-stack: manage stacked GitHub PRs with jj
30
30
 
31
31
  `jj-stack` turns a linear series of local `jj` changes into a stack of GitHub pull requests.
32
- Rewrite, split, squash, or reorder the changes with `jj`, then let `jj-stack` update the
33
- matching PRs.
32
+ Rewrite, split, squash, or reorder the changes with `jj`, then run `jj-stack submit` to update
33
+ GitHub. Existing PRs follow their change IDs, keeping comments and review history together.
34
34
 
35
35
  ## Quick start
36
36
 
37
- ### Requirements
37
+ You need Python 3.14 or newer, `jj` 0.45.1 or newer, and a repo on github.com where you can push
38
+ branches and open pull requests. `jj-stack` uses `GITHUB_TOKEN`, then `GH_TOKEN`, then your GitHub
39
+ CLI login for authentication.
38
40
 
39
- - Python 3.14 or newer
40
- - `jj` 0.44.0 or newer
41
- - GitHub authentication
42
-
43
- ### Install
44
-
45
- Install `jj-stack` from PyPI with `uv` in an isolated tool environment (recommended):
41
+ Install with `uv`:
46
42
 
47
43
  ```bash
48
44
  uv tool install jj-stack
49
45
  ```
50
46
 
51
- `pipx` provides another isolated installation:
52
-
53
- ```bash
54
- pipx install jj-stack
55
- ```
56
-
57
- You can also use `pip` inside an activated virtual environment:
58
-
59
- ```bash
60
- python -m pip install jj-stack
61
- ```
62
-
63
- To upgrade an installation made with `uv`, rerun its command with `--force`. If the command is
64
- not on your shell `PATH`, run `uv tool update-shell`.
65
-
66
- ### Invoke it as `jj stack`
67
-
68
- Add a command alias to your user configuration with `jj config edit --user`:
69
-
70
- ```toml
71
- [aliases]
72
- stack = ["util", "exec", "--", "jj-stack"]
73
- ```
74
-
75
- For tab completion of both `jj-stack` and `jj stack`, add the output of `jj-stack completion` to
76
- your shell startup file:
77
-
78
- ```bash
79
- eval "$(jj-stack completion zsh --jj-alias stack)"
80
- ```
81
-
82
- `bash` and `fish` work the same way. See
83
- [Configuration](https://www.serpentine.com/software/jj-stack/reference/configuration/) for more
84
- setup options.
85
-
86
47
  ### Submit your first stack
87
48
 
88
- Start with a linear series of local `jj` changes on top of `trunk()`. In a new repo, check
89
- the setup and apply the safe local fixes:
49
+ Start with a linear series of local `jj` changes on top of `trunk()`. Authenticate with
50
+ `gh auth login`, or supply a token in `GITHUB_TOKEN` or `GH_TOKEN`. Check the repo setup and
51
+ apply the safe local fixes:
90
52
 
91
53
  ```bash
92
54
  jj-stack doctor --fix
@@ -109,20 +71,27 @@ refresh. Use `jj-stack list` to see every tracked stack in the repo.
109
71
 
110
72
  ## Mental model
111
73
 
112
- The local `jj` DAG determines which changes form a stack and their order. On GitHub, each change
113
- gets a stable PR branch and a PR; every PR targets the PR branch below it, except the
114
- bottom PR, which targets trunk by default:
74
+ Your local `jj` history determines which changes form a stack and their order. On GitHub, each
75
+ change gets a stable PR branch and a PR. The bottom PR targets trunk by default, and each PR
76
+ above it targets the PR branch below:
115
77
 
116
78
  ```text
117
- jj-stack/add-ui-... -> PR #3 (base: jj-stack/add-api-...)
118
- jj-stack/add-api-... -> PR #2 (base: jj-stack/refactor-model-...)
119
- jj-stack/refactor-model-... -> PR #1 (base: main)
120
- main -> trunk
79
+ Local changes: trunk() <- A <- B <- C
80
+ GitHub PRs: main <- PR #1 <- PR #2 <- PR #3
121
81
  ```
122
82
 
123
- The PR branches normally stay out of your local bookmark view. When you rewrite a change,
124
- `jj-stack` updates that change's existing PR branch and PR, along with the PR branches and PRs for
125
- dependent changes.
83
+ Each PR's diff shows only the changes it adds on top of its base, so reviewers can consider
84
+ one change at a time. `jj-stack` manages the PR branches for you, and they normally stay out
85
+ of your local bookmark view.
86
+
87
+ When you rewrite a change, its change ID still connects it to the same PR. Submitting again
88
+ updates that PR and the PRs for any dependent changes, preserving their discussions.
89
+
90
+ To select a stack, pass the change ID of its head (the top change). `jj-stack` follows the
91
+ head's parents back to trunk to find the rest. If you don't name a head, it uses your working
92
+ copy when it has both a description and changes, or its parent otherwise. After editing a
93
+ lower change, pass the head's ID to `jj-stack submit` so the update includes the changes above
94
+ your edit.
126
95
 
127
96
  ## Everyday workflow
128
97
 
@@ -130,8 +99,9 @@ dependent changes.
130
99
  2. Run `jj-stack submit`.
131
100
  3. Revise, add, remove, or reorder the changes locally as reviews come in.
132
101
  4. Run `jj-stack submit` again to refresh GitHub.
133
- 5. Run `jj-stack merge` when the changes at the bottom are ready.
134
- 6. After a queued or externally initiated merge finishes, run
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
135
105
  `jj-stack sync <head-change-id>`.
136
106
 
137
107
  `view`, `submit`, `merge`, and `sync` accept a change ID when you need to select a stack other
@@ -140,19 +110,58 @@ than the one ending at the working copy.
140
110
  See the [user guide](https://www.serpentine.com/software/jj-stack/) for drafts, descriptions,
141
111
  merge queues, cleanup, and working with multiple stacks.
142
112
 
113
+ ## Optional setup
114
+
115
+ ### Invoke it as `jj stack`
116
+
117
+ Add a command alias to your user configuration with `jj config edit --user`:
118
+
119
+ ```toml
120
+ [aliases]
121
+ stack = ["util", "exec", "--", "jj-stack"]
122
+ ```
123
+
124
+ For tab completion of both `jj-stack` and `jj stack`, add the output of `jj-stack completion` to
125
+ your shell startup file:
126
+
127
+ ```bash
128
+ eval "$(jj-stack completion zsh --jj-alias stack)"
129
+ ```
130
+
131
+ `bash` and `fish` work the same way. See
132
+ [Configuration](https://www.serpentine.com/software/jj-stack/reference/configuration/) for more
133
+ setup options.
134
+
135
+ ### Other installation options
136
+
137
+ `pipx` provides another isolated installation:
138
+
139
+ ```bash
140
+ pipx install jj-stack
141
+ ```
142
+
143
+ You can also use `pip` inside an activated virtual environment:
144
+
145
+ ```bash
146
+ python -m pip install jj-stack
147
+ ```
148
+
149
+ To upgrade an installation made with `uv`, run `uv tool upgrade jj-stack`. If the command is
150
+ not on your shell `PATH`, run `uv tool update-shell`.
151
+
143
152
  ## Learn more
144
153
 
145
- - [Mental model](https://www.serpentine.com/software/jj-stack/mental-model/)
146
- - [Quick start](https://www.serpentine.com/software/jj-stack/quick-start/)
147
- - [Everyday workflows](https://www.serpentine.com/software/jj-stack/guides/submit-and-update/)
154
+ - [How jj-stack works](https://www.serpentine.com/software/jj-stack/mental-model/)
155
+ - [Submit and update](https://www.serpentine.com/software/jj-stack/guides/submit-and-update/)
156
+ - [Merge and sync](https://www.serpentine.com/software/jj-stack/guides/merge-and-sync/)
157
+ - [Multiple stacks](https://www.serpentine.com/software/jj-stack/guides/multiple-stacks/)
148
158
  - [Configuration](https://www.serpentine.com/software/jj-stack/reference/configuration/)
149
159
  - [Writing PR descriptions](https://www.serpentine.com/software/jj-stack/reference/descriptions/)
150
160
  - [Troubleshooting](https://www.serpentine.com/software/jj-stack/troubleshooting/)
151
- - [Tool comparison](https://www.serpentine.com/software/jj-stack/tool-comparison/)
152
- - [JSON output](https://www.serpentine.com/software/jj-stack/reference/json-output/)
153
- - [Automation and exit codes](https://www.serpentine.com/software/jj-stack/reference/automation/)
161
+ - [Compare tools](https://www.serpentine.com/software/jj-stack/tool-comparison/)
162
+ - [Automation](https://www.serpentine.com/software/jj-stack/reference/automation/)
154
163
 
155
- The built-in help is the canonical flag reference:
164
+ For all flags and aliases, use the built-in help:
156
165
 
157
166
  ```bash
158
167
  jj-stack --help
@@ -160,39 +169,18 @@ jj-stack <command> --help
160
169
  jj-stack help --all
161
170
  ```
162
171
 
163
- ## Development
164
-
165
- Contributor workflows live in the [`justfile`](justfile). With `uv`, `jj`, and `just` installed,
166
- run `just` to list the setup, formatting, focused test, verification, documentation, and release
167
- recipes.
168
-
169
172
  ## Coding agent integration
170
173
 
171
- Install the bundled skill to teach coding agents to work with local `jj` stacks and refresh their
172
- GitHub PRs safely:
174
+ Install the bundled skill to give coding agents instructions for working with `jj-stack`:
173
175
 
174
176
  ```bash
175
177
  gh skill install bos/jj-stack jj-stack
176
178
  ```
177
179
 
178
- See the [skill source](https://github.com/bos/jj-stack/blob/main/skills/jj-stack/SKILL.md). In
179
- my evaluations with Codex and Claude Code, agents with the `jj-stack` skill succeeded in 11/12
180
- scenarios versus 6/12 without it, with one critical error versus four, using 60% fewer failed
181
- command attempts and 18% fewer tool calls. (The critical error was due to Claude Haiku
182
- understanding a rule and ignoring it. I haven't figured out how to get smaller Claude models to
183
- behave better, and I don't personally use them.)
184
-
185
- ## Performance
186
-
187
- Although `jj-stack` is written in Python, this does not significantly affect its speed.
188
- The real determinants of its performance are the GitHub API and the `jj` command.
180
+ The [skill source](skills/jj-stack/SKILL.md) and [evaluation notes](evals/jj-stack-skill.md) are
181
+ included in this repo.
189
182
 
190
- The GitHub API is *slow*; a single roundtrip takes many hundreds of milliseconds. `jj-stack`
191
- reduces its impact with:
192
-
193
- - GraphQL batch requests where possible
194
- - concurrent use of the GitHub REST API
195
- - periodic audits that its queries are minimal in extent
183
+ ## Development
196
184
 
197
- In pursuit of good performance, `jj-stack` also batches calls to `jj` and minimizes the amount
198
- of work those calls must do.
185
+ With `uv`, `jj`, and `just` installed, run `just` to list the development workflows. See
186
+ [CONTRIBUTING.md](CONTRIBUTING.md) for setup and validation instructions.