jj-stack 0.1.3__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.
- {jj_stack-0.1.3 → jj_stack-0.1.5}/.github/workflows/ci.yml +7 -12
- {jj_stack-0.1.3 → jj_stack-0.1.5}/.github/workflows/codeql.yml +2 -2
- {jj_stack-0.1.3 → jj_stack-0.1.5}/.github/workflows/release.yml +3 -3
- {jj_stack-0.1.3 → jj_stack-0.1.5}/.gitignore +2 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/AGENTS.md +21 -19
- {jj_stack-0.1.3 → jj_stack-0.1.5}/CONTRIBUTING.md +26 -6
- {jj_stack-0.1.3 → jj_stack-0.1.5}/PKG-INFO +83 -97
- jj_stack-0.1.5/README.md +159 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/check.py +55 -18
- {jj_stack-0.1.3 → jj_stack-0.1.5}/complexity-budget.toml +2 -1
- jj_stack-0.1.5/docs/AGENTS.md +57 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/docs/README.md +5 -6
- jj_stack-0.1.5/docs/guides/close-or-separate.md +90 -0
- jj_stack-0.1.5/docs/guides/continue-a-stack.md +89 -0
- jj_stack-0.1.5/docs/guides/merge-and-sync.md +207 -0
- jj_stack-0.1.5/docs/guides/multiple-stacks.md +167 -0
- jj_stack-0.1.5/docs/guides/review-a-stack.md +71 -0
- jj_stack-0.1.5/docs/guides/revise.md +87 -0
- jj_stack-0.1.5/docs/guides/submit-and-update.md +98 -0
- jj_stack-0.1.5/docs/guides/working-on-github.md +60 -0
- jj_stack-0.1.5/docs/internals/AGENTS.md +20 -0
- jj_stack-0.1.5/docs/internals/README.md +45 -0
- jj_stack-0.1.5/docs/internals/code-reviews.md +78 -0
- jj_stack-0.1.5/docs/internals/design.md +770 -0
- jj_stack-0.1.5/docs/internals/property-testing.md +14 -0
- jj_stack-0.1.5/docs/internals/releasing.md +118 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/docs/internals/testing-philosophy.md +29 -12
- {jj_stack-0.1.3 → jj_stack-0.1.5}/docs/json-output.schema.json +111 -1
- jj_stack-0.1.5/docs/mental-model.md +126 -0
- jj_stack-0.1.5/docs/quick-start.md +194 -0
- jj_stack-0.1.5/docs/reference/automation.md +129 -0
- jj_stack-0.1.5/docs/reference/bookmarks-and-selection.md +127 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/docs/reference/commands.md +15 -19
- jj_stack-0.1.5/docs/reference/configuration.md +128 -0
- jj_stack-0.1.5/docs/reference/descriptions.md +94 -0
- jj_stack-0.1.5/docs/reference/json-output.md +217 -0
- jj_stack-0.1.5/docs/tool-comparison.md +128 -0
- jj_stack-0.1.5/docs/troubleshooting.md +288 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/evals/jj-stack-skill.md +5 -5
- {jj_stack-0.1.3 → jj_stack-0.1.5}/justfile +9 -6
- {jj_stack-0.1.3 → jj_stack-0.1.5}/pyproject.toml +8 -3
- {jj_stack-0.1.3 → jj_stack-0.1.5}/release-notes/v0.1.2.md +1 -1
- jj_stack-0.1.5/release-notes/v0.1.4.md +23 -0
- jj_stack-0.1.5/release-notes/v0.1.5.md +28 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/scripts/describe_with_claude.py +0 -2
- {jj_stack-0.1.3 → jj_stack-0.1.5}/scripts/describe_with_codex.py +0 -2
- {jj_stack-0.1.3 → jj_stack-0.1.5}/scripts/describe_with_editor.py +0 -8
- {jj_stack-0.1.3 → jj_stack-0.1.5}/scripts/describe_with_prompt.py +0 -2
- {jj_stack-0.1.3 → jj_stack-0.1.5}/skills/jj-stack/SKILL.md +58 -42
- {jj_stack-0.1.3 → jj_stack-0.1.5}/skills/jj-stack/references/multi-stack.md +33 -29
- jj_stack-0.1.5/skills/jj-stack/references/recovery.md +117 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/bootstrap.py +13 -18
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/cli.py +194 -391
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/cli_help.py +36 -31
- jj_stack-0.1.5/src/jj_stack/commands/_json_status.py +64 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/commands/checkout.py +185 -235
- jj_stack-0.1.5/src/jj_stack/commands/cleanup/actions.py +245 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/commands/cleanup/command.py +226 -293
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/commands/doctor.py +103 -93
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/commands/in_use.py +4 -4
- jj_stack-0.1.5/src/jj_stack/commands/list_.py +518 -0
- jj_stack-0.1.5/src/jj_stack/commands/merge/command.py +414 -0
- jj_stack-0.1.5/src/jj_stack/commands/merge/github_stack.py +292 -0
- jj_stack-0.1.5/src/jj_stack/commands/merge/plan.py +247 -0
- jj_stack-0.1.5/src/jj_stack/commands/merge/wait.py +202 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/commands/relink.py +52 -63
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/commands/submit/auto_close.py +16 -38
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/commands/submit/changes.py +20 -67
- jj_stack-0.1.5/src/jj_stack/commands/submit/command.py +681 -0
- jj_stack-0.1.5/src/jj_stack/commands/submit/descriptions.py +339 -0
- jj_stack-0.1.5/src/jj_stack/commands/submit/editor.py +274 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/commands/submit/github_stack.py +19 -58
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/commands/submit/inputs.py +57 -36
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/commands/submit/managed_comments.py +8 -7
- jj_stack-0.1.5/src/jj_stack/commands/submit/models.py +151 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/commands/submit/overview_comments.py +22 -52
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/commands/submit/prs.py +47 -86
- jj_stack-0.1.5/src/jj_stack/commands/submit/publication.py +278 -0
- jj_stack-0.1.5/src/jj_stack/commands/submit/render.py +139 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/commands/submit/revision_comments.py +9 -13
- jj_stack-0.1.5/src/jj_stack/commands/sync.py +459 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/commands/sync_apply.py +128 -185
- jj_stack-0.1.5/src/jj_stack/commands/sync_prs.py +118 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/commands/unstack.py +48 -67
- jj_stack-0.1.5/src/jj_stack/commands/view.py +778 -0
- jj_stack-0.1.5/src/jj_stack/commands/view_details.py +142 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/completion.py +20 -46
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/concurrency.py +21 -13
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/config.py +39 -75
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/console.py +123 -155
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/errors.py +46 -6
- jj_stack-0.1.5/src/jj_stack/formatting.py +85 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/github/client.py +379 -298
- jj_stack-0.1.5/src/jj_stack/github/error_messages.py +89 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/github/pr_refs.py +5 -10
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/github/resolution.py +8 -6
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/identifiers.py +7 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/jj/cli_args.py +0 -3
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/jj/client.py +256 -408
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/jj/colors.py +26 -91
- jj_stack-0.1.5/src/jj_stack/jj/settings.py +65 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/models/github.py +54 -31
- jj_stack-0.1.5/src/jj_stack/models/github_details.py +88 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/models/stack.py +11 -15
- jj_stack-0.1.5/src/jj_stack/models/tracking.py +44 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/pr_branch_namespace.py +2 -2
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/stack/change_state.py +182 -204
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/stack/convergence.py +210 -167
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/stack/convergence_models.py +16 -24
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/stack/convergence_observation.py +36 -36
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/stack/github_stack_safety.py +4 -4
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/stack/global_convergence.py +60 -62
- jj_stack-0.1.5/src/jj_stack/stack/observation.py +174 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/stack/path.py +37 -38
- jj_stack-0.1.5/src/jj_stack/stack/pr_branches.py +149 -0
- jj_stack-0.1.5/src/jj_stack/stack/pr_facts.py +183 -0
- jj_stack-0.1.5/src/jj_stack/stack/preparation.py +84 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/stack/repo.py +18 -19
- jj_stack-0.1.5/src/jj_stack/stack/reporting.py +203 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/stack/selected.py +39 -30
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/stack/selection.py +18 -32
- jj_stack-0.1.5/src/jj_stack/stack/status.py +251 -0
- jj_stack-0.1.5/src/jj_stack/stack/trunk.py +48 -0
- jj_stack-0.1.5/src/jj_stack/stack/trunk_evidence.py +51 -0
- jj_stack-0.1.5/src/jj_stack/state/migrations.py +58 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/state/operation_lock.py +19 -24
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/state/store.py +45 -84
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/ui.py +1 -22
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/conftest.py +24 -3
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/integration/conftest.py +0 -18
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/integration/submit_command_helpers.py +0 -10
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/integration/test_boundary_conditions.py +1 -1
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/integration/test_checkout_command.py +40 -62
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/integration/test_cleanup_command.py +35 -60
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/integration/test_doctor_command.py +36 -47
- jj_stack-0.1.5/tests/integration/test_fake_github_contracts.py +114 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/integration/test_jj_stack.py +69 -26
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/integration/test_list_command.py +56 -56
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/integration/test_merge_command.py +254 -131
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/integration/test_relink_command.py +7 -5
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/integration/test_submit_command.py +338 -214
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/integration/test_sync_command.py +179 -143
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/integration/test_unstack_command.py +18 -35
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/integration/test_view_command.py +122 -60
- jj_stack-0.1.5/tests/property/test_submit_property_scenarios.py +105 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/run_live_github.py +1 -1
- jj_stack-0.1.5/tests/run_submit_property_scenarios.py +123 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/support/change_helpers.py +1 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/support/contexts.py +1 -3
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/support/fake_github.py +338 -172
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/support/integration_helpers.py +39 -67
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/support/json_schema.py +5 -6
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/support/output_assertions.py +0 -10
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/support/pytest_concurrency.py +1 -14
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/support/stack_edit_scenarios.py +0 -2
- jj_stack-0.1.5/tests/support/stack_machine.py +1354 -0
- jj_stack-0.1.5/tests/support/submit_faults.py +91 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/support/tracking.py +1 -1
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/unit/test_bootstrap.py +1 -35
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/unit/test_change_state.py +19 -45
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/unit/test_check_script.py +2 -26
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/unit/test_checkout.py +1 -1
- jj_stack-0.1.5/tests/unit/test_cli.py +151 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/unit/test_cli_dispatch.py +5 -25
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/unit/test_completion.py +4 -20
- jj_stack-0.1.5/tests/unit/test_config.py +81 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/unit/test_describe_with_editor_script.py +4 -20
- jj_stack-0.1.5/tests/unit/test_describe_with_prompt_script.py +22 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/unit/test_errors.py +5 -22
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/unit/test_github_client.py +159 -67
- jj_stack-0.1.5/tests/unit/test_github_error_messages.py +52 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/unit/test_github_models.py +25 -19
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/unit/test_github_resolution.py +8 -19
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/unit/test_github_stack_planning.py +6 -27
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/unit/test_in_use_command.py +4 -3
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/unit/test_jj_client.py +96 -243
- jj_stack-0.1.5/tests/unit/test_jj_settings.py +86 -0
- jj_stack-0.1.5/tests/unit/test_merge.py +174 -0
- jj_stack-0.1.5/tests/unit/test_merge_wait.py +101 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/unit/test_operation_lock.py +0 -21
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/unit/test_pr_branches.py +29 -49
- jj_stack-0.1.5/tests/unit/test_pr_facts.py +112 -0
- jj_stack-0.1.5/tests/unit/test_pr_refs.py +34 -0
- jj_stack-0.1.5/tests/unit/test_property_runner.py +53 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/unit/test_relink.py +21 -31
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/unit/test_selected.py +2 -2
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/unit/test_stack_path.py +12 -55
- jj_stack-0.1.5/tests/unit/test_stack_status.py +152 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/unit/test_store.py +37 -38
- jj_stack-0.1.5/tests/unit/test_submit.py +172 -0
- jj_stack-0.1.5/tests/unit/test_submit_descriptions.py +121 -0
- jj_stack-0.1.5/tests/unit/test_submit_editor.py +164 -0
- jj_stack-0.1.5/tests/unit/test_trunk_evidence.py +95 -0
- jj_stack-0.1.5/tests/unit/test_ui.py +151 -0
- jj_stack-0.1.5/tests/unit/test_view.py +321 -0
- jj_stack-0.1.5/tests/unit/test_view_entrypoint.py +212 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tools/check_complexity.py +6 -7
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tools/check_jj_release_updates.py +6 -10
- jj_stack-0.1.5/uv.lock +740 -0
- jj_stack-0.1.3/README.md +0 -173
- jj_stack-0.1.3/docs/AGENTS.md +0 -85
- jj_stack-0.1.3/docs/guides/close-or-separate.md +0 -73
- jj_stack-0.1.3/docs/guides/continue-a-stack.md +0 -66
- jj_stack-0.1.3/docs/guides/merge-and-sync.md +0 -149
- jj_stack-0.1.3/docs/guides/multiple-stacks.md +0 -113
- jj_stack-0.1.3/docs/guides/review-a-stack.md +0 -60
- jj_stack-0.1.3/docs/guides/revise.md +0 -54
- jj_stack-0.1.3/docs/guides/submit-and-update.md +0 -106
- jj_stack-0.1.3/docs/guides/working-on-github.md +0 -55
- jj_stack-0.1.3/docs/internals/AGENTS.md +0 -30
- jj_stack-0.1.3/docs/internals/README.md +0 -22
- jj_stack-0.1.3/docs/internals/code-reviews.md +0 -113
- jj_stack-0.1.3/docs/internals/design.md +0 -980
- jj_stack-0.1.3/docs/internals/implementation-strategy.md +0 -126
- jj_stack-0.1.3/docs/internals/property-testing.md +0 -54
- jj_stack-0.1.3/docs/internals/releasing.md +0 -119
- jj_stack-0.1.3/docs/mental-model.md +0 -66
- jj_stack-0.1.3/docs/quick-start.md +0 -131
- jj_stack-0.1.3/docs/reference/automation.md +0 -133
- jj_stack-0.1.3/docs/reference/bookmarks-and-selection.md +0 -149
- jj_stack-0.1.3/docs/reference/configuration.md +0 -75
- jj_stack-0.1.3/docs/reference/descriptions.md +0 -84
- jj_stack-0.1.3/docs/reference/json-output.md +0 -167
- jj_stack-0.1.3/docs/tool-comparison.md +0 -215
- jj_stack-0.1.3/docs/troubleshooting.md +0 -211
- jj_stack-0.1.3/skills/jj-stack/references/recovery.md +0 -101
- jj_stack-0.1.3/src/jj_stack/commands/_cleanup_actions.py +0 -352
- jj_stack-0.1.3/src/jj_stack/commands/_json_status.py +0 -115
- jj_stack-0.1.3/src/jj_stack/commands/cleanup/shared.py +0 -61
- jj_stack-0.1.3/src/jj_stack/commands/cleanup/stale.py +0 -79
- jj_stack-0.1.3/src/jj_stack/commands/list_.py +0 -692
- jj_stack-0.1.3/src/jj_stack/commands/merge/command.py +0 -370
- jj_stack-0.1.3/src/jj_stack/commands/merge/github_stack.py +0 -331
- jj_stack-0.1.3/src/jj_stack/commands/merge/models.py +0 -106
- jj_stack-0.1.3/src/jj_stack/commands/merge/plan.py +0 -108
- jj_stack-0.1.3/src/jj_stack/commands/merge/preconditions.py +0 -169
- jj_stack-0.1.3/src/jj_stack/commands/merge/render.py +0 -54
- jj_stack-0.1.3/src/jj_stack/commands/submit/command.py +0 -850
- jj_stack-0.1.3/src/jj_stack/commands/submit/comments.py +0 -64
- jj_stack-0.1.3/src/jj_stack/commands/submit/descriptions.py +0 -637
- jj_stack-0.1.3/src/jj_stack/commands/submit/models.py +0 -207
- jj_stack-0.1.3/src/jj_stack/commands/submit/render.py +0 -124
- jj_stack-0.1.3/src/jj_stack/commands/sync.py +0 -507
- jj_stack-0.1.3/src/jj_stack/commands/view.py +0 -1041
- jj_stack-0.1.3/src/jj_stack/formatting.py +0 -133
- jj_stack-0.1.3/src/jj_stack/github/error_messages.py +0 -79
- jj_stack-0.1.3/src/jj_stack/models/tracking.py +0 -93
- jj_stack-0.1.3/src/jj_stack/stack/pr_branches.py +0 -123
- jj_stack-0.1.3/src/jj_stack/stack/pr_facts.py +0 -203
- jj_stack-0.1.3/src/jj_stack/stack/status.py +0 -544
- jj_stack-0.1.3/src/jj_stack/stack/trunk.py +0 -25
- jj_stack-0.1.3/src/jj_stack/stack/trunk_evidence.py +0 -149
- jj_stack-0.1.3/src/jj_stack/state/migrations.py +0 -63
- jj_stack-0.1.3/tests/property/test_submit_property_scenarios.py +0 -382
- jj_stack-0.1.3/tests/run_submit_property_scenarios.py +0 -246
- jj_stack-0.1.3/tests/support/submit_property_harness.py +0 -1117
- jj_stack-0.1.3/tests/support/submit_property_scenarios.py +0 -1075
- jj_stack-0.1.3/tests/unit/conftest.py +0 -14
- jj_stack-0.1.3/tests/unit/test_cleanup.py +0 -72
- jj_stack-0.1.3/tests/unit/test_cli.py +0 -297
- jj_stack-0.1.3/tests/unit/test_config.py +0 -193
- jj_stack-0.1.3/tests/unit/test_describe_with_prompt_script.py +0 -67
- jj_stack-0.1.3/tests/unit/test_divergence.py +0 -15
- jj_stack-0.1.3/tests/unit/test_list.py +0 -25
- jj_stack-0.1.3/tests/unit/test_merge.py +0 -244
- jj_stack-0.1.3/tests/unit/test_pr_refs.py +0 -51
- jj_stack-0.1.3/tests/unit/test_property_runner.py +0 -50
- jj_stack-0.1.3/tests/unit/test_selection.py +0 -9
- jj_stack-0.1.3/tests/unit/test_stack_status.py +0 -260
- jj_stack-0.1.3/tests/unit/test_submit.py +0 -253
- jj_stack-0.1.3/tests/unit/test_submit_descriptions.py +0 -354
- jj_stack-0.1.3/tests/unit/test_trunk_evidence.py +0 -169
- jj_stack-0.1.3/tests/unit/test_ui.py +0 -270
- jj_stack-0.1.3/tests/unit/test_view.py +0 -368
- jj_stack-0.1.3/tests/unit/test_view_entrypoint.py +0 -252
- jj_stack-0.1.3/uv.lock +0 -595
- {jj_stack-0.1.3 → jj_stack-0.1.5}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/.github/SECURITY.md +0 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/.github/dependabot.yml +0 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/.github/pull_request_template.md +0 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/.github/workflows/block-pr-base-merges.yml +0 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/.github/workflows/check-jj-release-updates.yml +0 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/CLAUDE.md +0 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/LICENSE +0 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/NOTICE +0 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/release-notes/v0.1.3.md +0 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/scripts/README.md +0 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/skills/jj-stack/agents/openai.yaml +0 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/__init__.py +0 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/__main__.py +0 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/commands/__init__.py +0 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/commands/merge/__init__.py +0 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/commands/submit/__init__.py +0 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/commands/submit/default_pr_text.py +0 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/github/__init__.py +0 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/github/auth.py +0 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/github/overview_comments.py +0 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/github/stack_availability.py +0 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/jj/__init__.py +0 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/models/__init__.py +0 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/models/git.py +0 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/stack/__init__.py +0 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/stack/divergence.py +0 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/src/jj_stack/state/__init__.py +0 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/__init__.py +0 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/integration/__init__.py +0 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/support/__init__.py +0 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/unit/__init__.py +0 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/unit/test_concurrency.py +0 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/unit/test_default_pr_text.py +0 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/unit/test_github_auth.py +0 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/unit/test_live_github_runner.py +0 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/unit/test_property_scenarios.py +0 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/unit/test_sync.py +0 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tests/unit/test_unstack.py +0 -0
- {jj_stack-0.1.3 → jj_stack-0.1.5}/tools/check_release_artifacts.py +0 -0
- {jj_stack-0.1.3 → 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@
|
|
21
|
+
uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
|
|
22
22
|
with:
|
|
23
23
|
python-version: "3.14"
|
|
24
24
|
|
|
@@ -26,9 +26,9 @@ jobs:
|
|
|
26
26
|
run: |
|
|
27
27
|
TOKEI_VERSION="$(
|
|
28
28
|
uv run --no-project --python 3.14 python -c \
|
|
29
|
-
'from tools.check_complexity import
|
|
29
|
+
'from tools.check_complexity import TOKEI_VERSIONS; print(TOKEI_VERSIONS[-1])'
|
|
30
30
|
)"
|
|
31
|
-
cargo install tokei --locked --version "
|
|
31
|
+
cargo install tokei --locked --version "^$TOKEI_VERSION"
|
|
32
32
|
|
|
33
33
|
- name: Install project environment
|
|
34
34
|
run: uv sync --locked
|
|
@@ -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@
|
|
55
|
+
uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
|
|
56
56
|
with:
|
|
57
57
|
python-version: ${{ matrix.python-version }}
|
|
58
58
|
|
|
@@ -79,18 +79,13 @@ jobs:
|
|
|
79
79
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
80
80
|
|
|
81
81
|
- name: Set up uv
|
|
82
|
-
uses: astral-sh/setup-uv@
|
|
82
|
+
uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
|
|
83
83
|
with:
|
|
84
84
|
python-version: "3.14"
|
|
85
85
|
|
|
86
86
|
- name: Install jj
|
|
87
87
|
run: echo "$(tools/install-jj-release.sh "$JJ_VERSION")" >> "$GITHUB_PATH"
|
|
88
88
|
|
|
89
|
-
- name: Run
|
|
89
|
+
- name: Run generated client and server sequences
|
|
90
90
|
run: >-
|
|
91
|
-
tests/run_submit_property_scenarios.py
|
|
92
|
-
--stack-join-scenarios 5
|
|
93
|
-
--lifecycle-scenarios 10
|
|
94
|
-
--stack-move-scenarios 5
|
|
95
|
-
--retry-scenarios 5
|
|
96
|
-
--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.
|
|
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.
|
|
32
|
+
uses: github/codeql-action/analyze@v4.37.9
|
|
@@ -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@
|
|
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@
|
|
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@
|
|
130
|
+
uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
|
|
131
131
|
with:
|
|
132
132
|
python-version: "3.14"
|
|
133
133
|
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
|
|
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
|
|
5
|
-
-
|
|
6
|
-
|
|
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
|
-
-
|
|
12
|
-
when
|
|
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.
|
|
@@ -38,25 +38,26 @@
|
|
|
38
38
|
|
|
39
39
|
# Documentation
|
|
40
40
|
|
|
41
|
-
- User-facing docs live in `docs
|
|
42
|
-
rules and the public/internal split.
|
|
43
|
-
the user docs: assume jj/git familiarity,
|
|
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.
|
|
44
45
|
- The web version of the user docs normally lives in the sibling jj repository at
|
|
45
46
|
`$(jj root)/../website`. When user-facing docs change here, run `just website`, inspect the
|
|
46
47
|
corresponding website changes, and update them as needed. If the change here is committed,
|
|
47
48
|
commit the corresponding website update in that repository as well; preserve unrelated work in
|
|
48
49
|
either working copy.
|
|
49
50
|
- Active internal docs use ordinary technical language too. Introduce a project-specific term
|
|
50
|
-
only when it names
|
|
51
|
+
only when it names an existing type, field, or enduring rule, define it at first use, and prefer
|
|
51
52
|
describing concrete inputs and effects.
|
|
52
|
-
-
|
|
53
|
-
|
|
54
|
-
-
|
|
55
|
-
|
|
56
|
-
|
|
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.
|
|
57
58
|
- When documentation is required, update only the affected source: `design.md` for an enduring
|
|
58
|
-
product rule, user docs or `--help` for user guidance, and
|
|
59
|
-
|
|
59
|
+
product rule, user docs or `--help` for user guidance, and the relevant testing document for
|
|
60
|
+
test strategy.
|
|
60
61
|
|
|
61
62
|
# Behaviour changes
|
|
62
63
|
|
|
@@ -67,8 +68,9 @@
|
|
|
67
68
|
the other way around: evaluate a documented behavior on its merits before extending it, and
|
|
68
69
|
prefer deleting case-specific rules that follow from the principles over adding new ones. Never
|
|
69
70
|
add durable transaction or replay state; recovery is observational (see design.md).
|
|
70
|
-
- Preserve the core invariants: the `jj` DAG determines stack topology,
|
|
71
|
-
|
|
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.
|
|
72
74
|
|
|
73
75
|
# Testing
|
|
74
76
|
|
|
@@ -13,7 +13,8 @@ discussion.
|
|
|
13
13
|
|
|
14
14
|
## Development setup
|
|
15
15
|
|
|
16
|
-
You need `uv`, `jj` 0.45.1 or newer, and `just`.
|
|
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:
|
|
17
18
|
|
|
18
19
|
```console
|
|
19
20
|
just setup
|
|
@@ -30,12 +31,31 @@ virtualenv path directly:
|
|
|
30
31
|
just run view
|
|
31
32
|
```
|
|
32
33
|
|
|
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:
|
|
34
36
|
|
|
35
37
|
```console
|
|
36
38
|
just check
|
|
37
39
|
```
|
|
38
40
|
|
|
41
|
+
Pyrefly is the default type checker, including a second pass targeting Windows. To select ty
|
|
42
|
+
for the current platform instead, use `--type-checker` or its short form, `-t`:
|
|
43
|
+
|
|
44
|
+
```console
|
|
45
|
+
just check -t ty
|
|
46
|
+
```
|
|
47
|
+
|
|
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.
|
|
58
|
+
|
|
39
59
|
Run focused tests while you iterate:
|
|
40
60
|
|
|
41
61
|
```console
|
|
@@ -43,10 +63,10 @@ just test tests/unit/test_jj_client.py
|
|
|
43
63
|
```
|
|
44
64
|
|
|
45
65
|
CI also enforces the cumulative complexity budgets. Check them locally with `just complexity`
|
|
46
|
-
when
|
|
66
|
+
when a supported `tokei` is installed. Raising a budget is a design decision, not routine
|
|
47
67
|
maintenance — say why in the pull request.
|
|
48
68
|
|
|
49
|
-
If your change touches user-facing
|
|
69
|
+
If your change touches user-facing guides or references, refresh the website snapshot with
|
|
50
70
|
`just website` and include the resulting change in the sibling `website` repository.
|
|
51
71
|
|
|
52
72
|
## Conventions
|
|
@@ -62,8 +82,8 @@ The short version:
|
|
|
62
82
|
- Explain *why* the change exists in the body, wrapped at 72 columns.
|
|
63
83
|
- Add tests at the narrowest layer that covers a distinct risk; consolidate overlapping coverage
|
|
64
84
|
rather than adding parallel cases.
|
|
65
|
-
-
|
|
66
|
-
|
|
85
|
+
- For code changes, update docs when supported rules, workflows, or existing statements change.
|
|
86
|
+
Documentation corrections and editorial improvements are welcome independently.
|
|
67
87
|
|
|
68
88
|
## Submitting
|
|
69
89
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: jj-stack
|
|
3
|
-
Version: 0.1.
|
|
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/
|
|
@@ -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
|
|
33
|
-
|
|
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
|
-
|
|
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
|
-
|
|
40
|
-
- `jj` 0.45.1 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()`.
|
|
89
|
-
|
|
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
|
|
@@ -110,19 +72,26 @@ refresh. Use `jj-stack list` to see every tracked stack in the repo.
|
|
|
110
72
|
## Mental model
|
|
111
73
|
|
|
112
74
|
Your local `jj` history determines which changes form a stack and their order. On GitHub, each
|
|
113
|
-
change gets a stable PR branch and a PR
|
|
114
|
-
|
|
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
|
-
|
|
118
|
-
|
|
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
|
-
|
|
124
|
-
`jj-stack`
|
|
125
|
-
|
|
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,9 +99,11 @@ 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
|
|
134
|
-
|
|
135
|
-
|
|
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.
|
|
136
107
|
|
|
137
108
|
`view`, `submit`, `merge`, and `sync` accept a change ID when you need to select a stack other
|
|
138
109
|
than the one ending at the working copy.
|
|
@@ -140,19 +111,58 @@ than the one ending at the working copy.
|
|
|
140
111
|
See the [user guide](https://www.serpentine.com/software/jj-stack/) for drafts, descriptions,
|
|
141
112
|
merge queues, cleanup, and working with multiple stacks.
|
|
142
113
|
|
|
114
|
+
## Optional setup
|
|
115
|
+
|
|
116
|
+
### Invoke it as `jj stack`
|
|
117
|
+
|
|
118
|
+
Add a command alias to your user configuration with `jj config edit --user`:
|
|
119
|
+
|
|
120
|
+
```toml
|
|
121
|
+
[aliases]
|
|
122
|
+
stack = ["util", "exec", "--", "jj-stack"]
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
For tab completion of both `jj-stack` and `jj stack`, add the output of `jj-stack completion` to
|
|
126
|
+
your shell startup file:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
eval "$(jj-stack completion zsh --jj-alias stack)"
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
`bash` and `fish` work the same way. See
|
|
133
|
+
[Configuration](https://www.serpentine.com/software/jj-stack/reference/configuration/) for more
|
|
134
|
+
setup options.
|
|
135
|
+
|
|
136
|
+
### Other installation options
|
|
137
|
+
|
|
138
|
+
`pipx` provides another isolated installation:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
pipx install jj-stack
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
You can also use `pip` inside an activated virtual environment:
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
python -m pip install jj-stack
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
To upgrade an installation made with `uv`, run `uv tool upgrade jj-stack`. If the command is
|
|
151
|
+
not on your shell `PATH`, run `uv tool update-shell`.
|
|
152
|
+
|
|
143
153
|
## Learn more
|
|
144
154
|
|
|
145
|
-
- [
|
|
146
|
-
- [
|
|
147
|
-
- [
|
|
155
|
+
- [How jj-stack works](https://www.serpentine.com/software/jj-stack/mental-model/)
|
|
156
|
+
- [Submit and update](https://www.serpentine.com/software/jj-stack/guides/submit-and-update/)
|
|
157
|
+
- [Merge and sync](https://www.serpentine.com/software/jj-stack/guides/merge-and-sync/)
|
|
158
|
+
- [Multiple stacks](https://www.serpentine.com/software/jj-stack/guides/multiple-stacks/)
|
|
148
159
|
- [Configuration](https://www.serpentine.com/software/jj-stack/reference/configuration/)
|
|
149
160
|
- [Writing PR descriptions](https://www.serpentine.com/software/jj-stack/reference/descriptions/)
|
|
150
161
|
- [Troubleshooting](https://www.serpentine.com/software/jj-stack/troubleshooting/)
|
|
151
|
-
- [
|
|
152
|
-
- [
|
|
153
|
-
- [Automation and exit codes](https://www.serpentine.com/software/jj-stack/reference/automation/)
|
|
162
|
+
- [Compare tools](https://www.serpentine.com/software/jj-stack/tool-comparison/)
|
|
163
|
+
- [Automation](https://www.serpentine.com/software/jj-stack/reference/automation/)
|
|
154
164
|
|
|
155
|
-
|
|
165
|
+
For all flags and aliases, use the built-in help:
|
|
156
166
|
|
|
157
167
|
```bash
|
|
158
168
|
jj-stack --help
|
|
@@ -160,42 +170,18 @@ jj-stack <command> --help
|
|
|
160
170
|
jj-stack help --all
|
|
161
171
|
```
|
|
162
172
|
|
|
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
173
|
## Coding agent integration
|
|
170
174
|
|
|
171
|
-
Install the bundled skill to
|
|
172
|
-
GitHub PRs safely:
|
|
175
|
+
Install the bundled skill to give coding agents instructions for working with `jj-stack`:
|
|
173
176
|
|
|
174
177
|
```bash
|
|
175
178
|
gh skill install bos/jj-stack jj-stack
|
|
176
179
|
```
|
|
177
180
|
|
|
178
|
-
|
|
179
|
-
|
|
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. Treat that as a small pilot rather than a published
|
|
182
|
-
benchmark:
|
|
183
|
-
[`evals/jj-stack-skill.md`](https://github.com/bos/jj-stack/blob/main/evals/jj-stack-skill.md)
|
|
184
|
-
gives the evaluation design, but this repo does not include the traces behind those numbers.
|
|
185
|
-
(The critical error was due to Claude Haiku understanding a rule and ignoring it. I haven't
|
|
186
|
-
figured out how to get smaller Claude models to behave better, and I don't personally use them.)
|
|
187
|
-
|
|
188
|
-
## Performance
|
|
189
|
-
|
|
190
|
-
Although `jj-stack` is written in Python, this does not significantly affect its speed.
|
|
191
|
-
The real determinants of its performance are the GitHub API and the `jj` command.
|
|
181
|
+
The [skill source](skills/jj-stack/SKILL.md) and [evaluation notes](evals/jj-stack-skill.md) are
|
|
182
|
+
included in this repo.
|
|
192
183
|
|
|
193
|
-
|
|
194
|
-
reduces its impact with:
|
|
195
|
-
|
|
196
|
-
- GraphQL batch requests where possible
|
|
197
|
-
- concurrent use of the GitHub REST API
|
|
198
|
-
- periodic audits that its queries are minimal in extent
|
|
184
|
+
## Development
|
|
199
185
|
|
|
200
|
-
|
|
201
|
-
|
|
186
|
+
With `uv`, `jj`, and `just` installed, run `just` to list the development workflows. See
|
|
187
|
+
[CONTRIBUTING.md](CONTRIBUTING.md) for setup and validation instructions.
|
jj_stack-0.1.5/README.md
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# jj-stack: manage stacked GitHub PRs with jj
|
|
2
|
+
|
|
3
|
+
`jj-stack` turns a linear series of local `jj` changes into a stack of GitHub pull requests.
|
|
4
|
+
Rewrite, split, squash, or reorder the changes with `jj`, then run `jj-stack submit` to update
|
|
5
|
+
GitHub. Existing PRs follow their change IDs, keeping comments and review history together.
|
|
6
|
+
|
|
7
|
+
## Quick start
|
|
8
|
+
|
|
9
|
+
You need Python 3.14 or newer, `jj` 0.45.1 or newer, and a repo on github.com where you can push
|
|
10
|
+
branches and open pull requests. `jj-stack` uses `GITHUB_TOKEN`, then `GH_TOKEN`, then your GitHub
|
|
11
|
+
CLI login for authentication.
|
|
12
|
+
|
|
13
|
+
Install with `uv`:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
uv tool install jj-stack
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### Submit your first stack
|
|
20
|
+
|
|
21
|
+
Start with a linear series of local `jj` changes on top of `trunk()`. Authenticate with
|
|
22
|
+
`gh auth login`, or supply a token in `GITHUB_TOKEN` or `GH_TOKEN`. Check the repo setup and
|
|
23
|
+
apply the safe local fixes:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
jj-stack doctor --fix
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Inspect the stack that ends at your working copy:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
jj-stack
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Create one GitHub PR per local change:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
jj-stack submit
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Revise the changes locally with `jj` and rerun `jj-stack submit` whenever the stack is ready to
|
|
42
|
+
refresh. Use `jj-stack list` to see every tracked stack in the repo.
|
|
43
|
+
|
|
44
|
+
## Mental model
|
|
45
|
+
|
|
46
|
+
Your local `jj` history determines which changes form a stack and their order. On GitHub, each
|
|
47
|
+
change gets a stable PR branch and a PR. The bottom PR targets trunk by default, and each PR
|
|
48
|
+
above it targets the PR branch below:
|
|
49
|
+
|
|
50
|
+
```text
|
|
51
|
+
Local changes: trunk() <- A <- B <- C
|
|
52
|
+
GitHub PRs: main <- PR #1 <- PR #2 <- PR #3
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Each PR's diff shows only the changes it adds on top of its base, so reviewers can consider
|
|
56
|
+
one change at a time. `jj-stack` manages the PR branches for you, and they normally stay out
|
|
57
|
+
of your local bookmark view.
|
|
58
|
+
|
|
59
|
+
When you rewrite a change, its change ID still connects it to the same PR. Submitting again
|
|
60
|
+
updates that PR and the PRs for any dependent changes, preserving their discussions.
|
|
61
|
+
|
|
62
|
+
To select a stack, pass the change ID of its head (the top change). `jj-stack` follows the
|
|
63
|
+
head's parents back to trunk to find the rest. If you don't name a head, it uses your working
|
|
64
|
+
copy when it has both a description and changes, or its parent otherwise. After editing a
|
|
65
|
+
lower change, pass the head's ID to `jj-stack submit` so the update includes the changes above
|
|
66
|
+
your edit.
|
|
67
|
+
|
|
68
|
+
## Everyday workflow
|
|
69
|
+
|
|
70
|
+
1. Write code as a series of local `jj` changes.
|
|
71
|
+
2. Run `jj-stack submit`.
|
|
72
|
+
3. Revise, add, remove, or reorder the changes locally as reviews come in.
|
|
73
|
+
4. Run `jj-stack submit` again to refresh GitHub.
|
|
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.
|
|
79
|
+
|
|
80
|
+
`view`, `submit`, `merge`, and `sync` accept a change ID when you need to select a stack other
|
|
81
|
+
than the one ending at the working copy.
|
|
82
|
+
|
|
83
|
+
See the [user guide](https://www.serpentine.com/software/jj-stack/) for drafts, descriptions,
|
|
84
|
+
merge queues, cleanup, and working with multiple stacks.
|
|
85
|
+
|
|
86
|
+
## Optional setup
|
|
87
|
+
|
|
88
|
+
### Invoke it as `jj stack`
|
|
89
|
+
|
|
90
|
+
Add a command alias to your user configuration with `jj config edit --user`:
|
|
91
|
+
|
|
92
|
+
```toml
|
|
93
|
+
[aliases]
|
|
94
|
+
stack = ["util", "exec", "--", "jj-stack"]
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
For tab completion of both `jj-stack` and `jj stack`, add the output of `jj-stack completion` to
|
|
98
|
+
your shell startup file:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
eval "$(jj-stack completion zsh --jj-alias stack)"
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
`bash` and `fish` work the same way. See
|
|
105
|
+
[Configuration](https://www.serpentine.com/software/jj-stack/reference/configuration/) for more
|
|
106
|
+
setup options.
|
|
107
|
+
|
|
108
|
+
### Other installation options
|
|
109
|
+
|
|
110
|
+
`pipx` provides another isolated installation:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
pipx install jj-stack
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
You can also use `pip` inside an activated virtual environment:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
python -m pip install jj-stack
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
To upgrade an installation made with `uv`, run `uv tool upgrade jj-stack`. If the command is
|
|
123
|
+
not on your shell `PATH`, run `uv tool update-shell`.
|
|
124
|
+
|
|
125
|
+
## Learn more
|
|
126
|
+
|
|
127
|
+
- [How jj-stack works](https://www.serpentine.com/software/jj-stack/mental-model/)
|
|
128
|
+
- [Submit and update](https://www.serpentine.com/software/jj-stack/guides/submit-and-update/)
|
|
129
|
+
- [Merge and sync](https://www.serpentine.com/software/jj-stack/guides/merge-and-sync/)
|
|
130
|
+
- [Multiple stacks](https://www.serpentine.com/software/jj-stack/guides/multiple-stacks/)
|
|
131
|
+
- [Configuration](https://www.serpentine.com/software/jj-stack/reference/configuration/)
|
|
132
|
+
- [Writing PR descriptions](https://www.serpentine.com/software/jj-stack/reference/descriptions/)
|
|
133
|
+
- [Troubleshooting](https://www.serpentine.com/software/jj-stack/troubleshooting/)
|
|
134
|
+
- [Compare tools](https://www.serpentine.com/software/jj-stack/tool-comparison/)
|
|
135
|
+
- [Automation](https://www.serpentine.com/software/jj-stack/reference/automation/)
|
|
136
|
+
|
|
137
|
+
For all flags and aliases, use the built-in help:
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
jj-stack --help
|
|
141
|
+
jj-stack <command> --help
|
|
142
|
+
jj-stack help --all
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Coding agent integration
|
|
146
|
+
|
|
147
|
+
Install the bundled skill to give coding agents instructions for working with `jj-stack`:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
gh skill install bos/jj-stack jj-stack
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
The [skill source](skills/jj-stack/SKILL.md) and [evaluation notes](evals/jj-stack-skill.md) are
|
|
154
|
+
included in this repo.
|
|
155
|
+
|
|
156
|
+
## Development
|
|
157
|
+
|
|
158
|
+
With `uv`, `jj`, and `just` installed, run `just` to list the development workflows. See
|
|
159
|
+
[CONTRIBUTING.md](CONTRIBUTING.md) for setup and validation instructions.
|