jj-stack 0.1.0__tar.gz → 0.1.2__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.0 → jj_stack-0.1.2}/.github/workflows/ci.yml +3 -3
- {jj_stack-0.1.0 → jj_stack-0.1.2}/.github/workflows/codeql.yml +2 -2
- {jj_stack-0.1.0 → jj_stack-0.1.2}/.github/workflows/release.yml +55 -15
- {jj_stack-0.1.0 → jj_stack-0.1.2}/AGENTS.md +13 -22
- {jj_stack-0.1.0 → jj_stack-0.1.2}/PKG-INFO +39 -11
- {jj_stack-0.1.0 → jj_stack-0.1.2}/README.md +36 -10
- {jj_stack-0.1.0 → jj_stack-0.1.2}/check.py +10 -2
- {jj_stack-0.1.0 → jj_stack-0.1.2}/complexity-budget.toml +1 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/docs/README.md +2 -1
- {jj_stack-0.1.0 → jj_stack-0.1.2}/docs/guides/continue-a-stack.md +4 -4
- {jj_stack-0.1.0 → jj_stack-0.1.2}/docs/guides/merge-and-sync.md +11 -11
- {jj_stack-0.1.0 → jj_stack-0.1.2}/docs/guides/review-a-stack.md +9 -3
- {jj_stack-0.1.0 → jj_stack-0.1.2}/docs/guides/submit-and-update.md +7 -0
- jj_stack-0.1.2/docs/guides/working-on-github.md +55 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/docs/internals/code-reviews.md +2 -2
- {jj_stack-0.1.0 → jj_stack-0.1.2}/docs/internals/design.md +39 -19
- {jj_stack-0.1.0 → jj_stack-0.1.2}/docs/internals/implementation-strategy.md +13 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/docs/internals/property-testing.md +2 -2
- jj_stack-0.1.2/docs/internals/releasing.md +71 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/docs/json-output.schema.json +8 -0
- jj_stack-0.1.2/docs/quick-start.md +131 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/docs/reference/automation.md +6 -6
- jj_stack-0.1.2/docs/reference/bookmarks-and-selection.md +149 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/docs/reference/commands.md +4 -1
- {jj_stack-0.1.0 → jj_stack-0.1.2}/docs/reference/configuration.md +10 -1
- jj_stack-0.1.2/docs/reference/descriptions.md +84 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/docs/reference/json-output.md +15 -8
- jj_stack-0.1.2/docs/tool-comparison.md +215 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/docs/troubleshooting.md +0 -7
- jj_stack-0.1.2/justfile +60 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/pyproject.toml +10 -5
- jj_stack-0.1.2/release-notes/v0.1.2.md +34 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/skills/jj-stack/SKILL.md +15 -4
- {jj_stack-0.1.0 → jj_stack-0.1.2}/skills/jj-stack/references/recovery.md +13 -9
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/cli.py +9 -5
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/commands/_cleanup_actions.py +34 -92
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/commands/_json_status.py +1 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/commands/checkout.py +39 -38
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/commands/cleanup/command.py +108 -149
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/commands/list_.py +79 -51
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/commands/merge/command.py +31 -27
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/commands/merge/github_stack.py +26 -7
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/commands/merge/models.py +2 -3
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/commands/merge/plan.py +0 -1
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/commands/merge/preconditions.py +17 -22
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/commands/relink.py +49 -31
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/commands/submit/auto_close.py +3 -1
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/commands/submit/command.py +199 -86
- jj_stack-0.1.2/src/jj_stack/commands/submit/comments.py +62 -0
- jj_stack-0.1.2/src/jj_stack/commands/submit/default_pr_text.py +54 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/commands/submit/descriptions.py +118 -25
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/commands/submit/github_stack.py +47 -4
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/commands/submit/inputs.py +49 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/commands/submit/models.py +5 -2
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/commands/submit/overview_comments.py +74 -63
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/commands/submit/prs.py +27 -39
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/commands/submit/render.py +12 -6
- jj_stack-0.1.2/src/jj_stack/commands/submit/revision_comments.py +166 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/commands/sync.py +13 -11
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/commands/sync_apply.py +16 -6
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/commands/unstack.py +6 -6
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/commands/view.py +83 -47
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/completion.py +1 -1
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/console.py +15 -2
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/errors.py +4 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/formatting.py +47 -8
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/github/client.py +476 -94
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/github/overview_comments.py +0 -6
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/github/resolution.py +0 -6
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/jj/client.py +23 -50
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/models/github.py +37 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/models/tracking.py +5 -27
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/stack/change_status.py +7 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/stack/convergence.py +17 -30
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/stack/convergence_observation.py +5 -15
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/stack/github_stack_safety.py +11 -19
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/stack/global_convergence.py +13 -18
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/stack/path.py +0 -2
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/stack/pr_branches.py +1 -4
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/stack/pr_facts.py +36 -34
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/stack/repo.py +4 -4
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/stack/selected.py +13 -7
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/stack/selection.py +27 -12
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/stack/status.py +16 -62
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/stack/trunk_evidence.py +11 -15
- jj_stack-0.1.2/src/jj_stack/state/migrations.py +63 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/state/store.py +6 -32
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/ui.py +23 -1
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/integration/submit_command_helpers.py +0 -57
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/integration/test_boundary_conditions.py +0 -8
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/integration/test_cleanup_command.py +19 -60
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/integration/test_doctor_command.py +8 -20
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/integration/test_jj_stack.py +46 -25
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/integration/test_list_command.py +19 -10
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/integration/test_relink_command.py +19 -11
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/integration/test_submit_command.py +228 -42
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/integration/test_sync_command.py +6 -4
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/integration/test_view_command.py +9 -9
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/property/test_submit_property_scenarios.py +16 -31
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/run_submit_property_scenarios.py +2 -2
- jj_stack-0.1.2/tests/support/contexts.py +49 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/support/fake_github.py +117 -15
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/support/integration_helpers.py +87 -42
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/support/submit_property_harness.py +13 -25
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/support/submit_property_scenarios.py +100 -45
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/support/tracking.py +0 -6
- jj_stack-0.1.2/tests/unit/conftest.py +14 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/test_change_status.py +5 -15
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/test_change_status_topology.py +10 -20
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/test_check_script.py +13 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/test_cleanup.py +14 -41
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/test_cli.py +1 -4
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/test_cli_dispatch.py +1 -4
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/test_completion.py +3 -0
- jj_stack-0.1.2/tests/unit/test_default_pr_text.py +56 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/test_github_client.py +177 -24
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/test_github_models.py +27 -5
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/test_github_stack_planning.py +35 -3
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/test_in_use_command.py +1 -4
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/test_jj_client.py +25 -150
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/test_pr_branches.py +3 -24
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/test_relink.py +10 -14
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/test_stack_status.py +22 -132
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/test_store.py +84 -19
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/test_submit.py +41 -44
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/test_submit_descriptions.py +19 -2
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/test_trunk_evidence.py +4 -19
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/test_ui.py +24 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/test_view.py +146 -116
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/test_view_entrypoint.py +10 -3
- {jj_stack-0.1.0 → jj_stack-0.1.2}/uv.lock +44 -42
- jj_stack-0.1.0/docs/gh-stack.md +0 -38
- jj_stack-0.1.0/docs/guides/working-on-github.md +0 -52
- jj_stack-0.1.0/docs/internals/releasing.md +0 -47
- jj_stack-0.1.0/docs/quick-start.md +0 -91
- jj_stack-0.1.0/docs/reference/descriptions.md +0 -59
- jj_stack-0.1.0/tests/unit/entrypoint_test_helpers.py +0 -37
- {jj_stack-0.1.0 → jj_stack-0.1.2}/.github/SECURITY.md +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/.github/dependabot.yml +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/.github/workflows/block-pr-base-merges.yml +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/.github/workflows/check-jj-release-updates.yml +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/.gitignore +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/CLAUDE.md +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/LICENSE +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/NOTICE +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/docs/AGENTS.md +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/docs/guides/close-or-separate.md +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/docs/guides/multiple-stacks.md +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/docs/guides/revise.md +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/docs/internals/AGENTS.md +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/docs/internals/README.md +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/docs/internals/testing-philosophy.md +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/docs/mental-model.md +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/evals/jj-stack-skill.md +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/scripts/README.md +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/scripts/describe_with_claude.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/scripts/describe_with_codex.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/scripts/describe_with_editor.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/scripts/describe_with_prompt.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/skills/jj-stack/agents/openai.yaml +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/skills/jj-stack/references/multi-stack.md +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/__init__.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/__main__.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/bootstrap.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/cli_help.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/commands/__init__.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/commands/cleanup/shared.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/commands/cleanup/stale.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/commands/doctor.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/commands/in_use.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/commands/merge/__init__.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/commands/merge/render.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/commands/submit/__init__.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/commands/submit/changes.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/concurrency.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/config.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/github/__init__.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/github/auth.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/github/error_messages.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/github/pr_refs.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/github/stack_availability.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/identifiers.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/jj/__init__.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/jj/cli_args.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/jj/colors.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/models/__init__.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/models/git.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/models/stack.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/pr_branch_namespace.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/stack/__init__.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/stack/convergence_models.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/state/__init__.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/src/jj_stack/state/operation_lock.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/__init__.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/conftest.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/integration/__init__.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/integration/conftest.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/integration/test_checkout_command.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/integration/test_merge_command.py +1 -1
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/integration/test_unstack_command.py +1 -1
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/run_live_github.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/support/__init__.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/support/change_helpers.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/support/json_schema.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/support/output_assertions.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/support/pytest_concurrency.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/support/stack_edit_scenarios.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/__init__.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/test_bootstrap.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/test_checkout.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/test_concurrency.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/test_config.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/test_describe_with_editor_script.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/test_describe_with_prompt_script.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/test_errors.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/test_github_auth.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/test_github_resolution.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/test_list.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/test_live_github_runner.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/test_merge.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/test_operation_lock.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/test_pr_refs.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/test_property_runner.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/test_property_scenarios.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/test_selection.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/test_stack_path.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/test_sync.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tests/unit/test_unstack.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tools/check_complexity.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tools/check_jj_release_updates.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/tools/check_release_artifacts.py +0 -0
- {jj_stack-0.1.0 → jj_stack-0.1.2}/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@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
|
|
22
22
|
with:
|
|
23
23
|
python-version: "3.14"
|
|
24
24
|
|
|
@@ -51,7 +51,7 @@ jobs:
|
|
|
51
51
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
52
52
|
|
|
53
53
|
- name: Set up uv
|
|
54
|
-
uses: astral-sh/setup-uv@
|
|
54
|
+
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
|
|
55
55
|
with:
|
|
56
56
|
python-version: ${{ matrix.python-version }}
|
|
57
57
|
|
|
@@ -78,7 +78,7 @@ jobs:
|
|
|
78
78
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
79
79
|
|
|
80
80
|
- name: Set up uv
|
|
81
|
-
uses: astral-sh/setup-uv@
|
|
81
|
+
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
|
|
82
82
|
with:
|
|
83
83
|
python-version: "3.14"
|
|
84
84
|
|
|
@@ -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.7
|
|
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.7
|
|
@@ -5,6 +5,11 @@ on:
|
|
|
5
5
|
tags:
|
|
6
6
|
- "v*"
|
|
7
7
|
workflow_dispatch:
|
|
8
|
+
inputs:
|
|
9
|
+
release_tag:
|
|
10
|
+
description: Existing tag to publish to production; leave empty for TestPyPI
|
|
11
|
+
required: false
|
|
12
|
+
type: string
|
|
8
13
|
|
|
9
14
|
permissions:
|
|
10
15
|
contents: read
|
|
@@ -26,22 +31,36 @@ jobs:
|
|
|
26
31
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
27
32
|
with:
|
|
28
33
|
fetch-depth: 0
|
|
34
|
+
ref: ${{ inputs.release_tag || github.ref }}
|
|
29
35
|
|
|
30
36
|
- name: Set up uv
|
|
31
|
-
uses: astral-sh/setup-uv@
|
|
37
|
+
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
|
|
32
38
|
with:
|
|
33
39
|
python-version: "3.14"
|
|
34
40
|
|
|
35
41
|
- name: Verify tag matches package version
|
|
36
|
-
if:
|
|
42
|
+
if: github.event_name == 'push' || inputs.release_tag != ''
|
|
37
43
|
env:
|
|
38
|
-
RELEASE_TAG: ${{ github.ref_name }}
|
|
39
|
-
run:
|
|
44
|
+
RELEASE_TAG: ${{ inputs.release_tag || github.ref_name }}
|
|
45
|
+
run: |
|
|
46
|
+
test "$RELEASE_TAG" = "v$(uv version --short)"
|
|
47
|
+
test "$(git rev-parse HEAD)" = "$(git rev-parse "refs/tags/$RELEASE_TAG^{commit}")"
|
|
40
48
|
|
|
41
49
|
- name: Verify tagged commit is on main
|
|
42
|
-
if:
|
|
50
|
+
if: github.event_name == 'push' || inputs.release_tag != ''
|
|
43
51
|
run: git merge-base --is-ancestor HEAD refs/remotes/origin/main
|
|
44
52
|
|
|
53
|
+
- name: Verify release notes
|
|
54
|
+
if: github.event_name == 'push' || inputs.release_tag != ''
|
|
55
|
+
env:
|
|
56
|
+
RELEASE_TAG: ${{ inputs.release_tag || github.ref_name }}
|
|
57
|
+
run: |
|
|
58
|
+
release_notes="release-notes/$RELEASE_TAG.md"
|
|
59
|
+
if ! test -s "$release_notes"; then
|
|
60
|
+
echo "::error file=$release_notes::Add human-written release notes for $RELEASE_TAG"
|
|
61
|
+
exit 1
|
|
62
|
+
fi
|
|
63
|
+
|
|
45
64
|
- name: Install jj
|
|
46
65
|
run: echo "$(tools/install-jj-release.sh "$JJ_VERSION")" >> "$GITHUB_PATH"
|
|
47
66
|
|
|
@@ -52,7 +71,7 @@ jobs:
|
|
|
52
71
|
run: uv build
|
|
53
72
|
|
|
54
73
|
- name: Test built distributions
|
|
55
|
-
run: python tools/check_release_artifacts.py
|
|
74
|
+
run: uv run --no-project --python 3.14 python tools/check_release_artifacts.py
|
|
56
75
|
|
|
57
76
|
- name: Upload distributions
|
|
58
77
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
@@ -63,7 +82,7 @@ jobs:
|
|
|
63
82
|
retention-days: 7
|
|
64
83
|
|
|
65
84
|
publish-testpypi:
|
|
66
|
-
if: github.event_name == 'workflow_dispatch'
|
|
85
|
+
if: github.event_name == 'workflow_dispatch' && inputs.release_tag == ''
|
|
67
86
|
needs: build
|
|
68
87
|
runs-on: ubuntu-latest
|
|
69
88
|
timeout-minutes: 10
|
|
@@ -75,7 +94,7 @@ jobs:
|
|
|
75
94
|
|
|
76
95
|
steps:
|
|
77
96
|
- name: Set up uv
|
|
78
|
-
uses: astral-sh/setup-uv@
|
|
97
|
+
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
|
|
79
98
|
with:
|
|
80
99
|
python-version: "3.14"
|
|
81
100
|
|
|
@@ -94,7 +113,9 @@ jobs:
|
|
|
94
113
|
dist/*
|
|
95
114
|
|
|
96
115
|
publish-pypi:
|
|
97
|
-
if:
|
|
116
|
+
if: >-
|
|
117
|
+
(github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')) ||
|
|
118
|
+
(github.event_name == 'workflow_dispatch' && inputs.release_tag != '')
|
|
98
119
|
needs: build
|
|
99
120
|
runs-on: ubuntu-latest
|
|
100
121
|
timeout-minutes: 10
|
|
@@ -106,7 +127,7 @@ jobs:
|
|
|
106
127
|
|
|
107
128
|
steps:
|
|
108
129
|
- name: Set up uv
|
|
109
|
-
uses: astral-sh/setup-uv@
|
|
130
|
+
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
|
|
110
131
|
with:
|
|
111
132
|
python-version: "3.14"
|
|
112
133
|
|
|
@@ -131,6 +152,11 @@ jobs:
|
|
|
131
152
|
contents: write
|
|
132
153
|
|
|
133
154
|
steps:
|
|
155
|
+
- name: Check out release
|
|
156
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
157
|
+
with:
|
|
158
|
+
ref: ${{ inputs.release_tag || github.ref }}
|
|
159
|
+
|
|
134
160
|
- name: Download distributions
|
|
135
161
|
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
136
162
|
with:
|
|
@@ -140,10 +166,24 @@ jobs:
|
|
|
140
166
|
- name: Publish GitHub release
|
|
141
167
|
env:
|
|
142
168
|
GH_TOKEN: ${{ github.token }}
|
|
143
|
-
RELEASE_TAG: ${{ github.ref_name }}
|
|
169
|
+
RELEASE_TAG: ${{ inputs.release_tag || github.ref_name }}
|
|
144
170
|
run: |
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
171
|
+
release_notes="release-notes/$RELEASE_TAG.md"
|
|
172
|
+
if gh release view "$RELEASE_TAG" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then
|
|
173
|
+
expected_notes="$(cat "$release_notes")"
|
|
174
|
+
published_notes="$(
|
|
175
|
+
gh release view "$RELEASE_TAG" --repo "$GITHUB_REPOSITORY" \
|
|
176
|
+
--json body --jq .body
|
|
177
|
+
)"
|
|
178
|
+
if test "$published_notes" != "$expected_notes"; then
|
|
179
|
+
echo "::error file=$release_notes::Published notes do not match $release_notes"
|
|
180
|
+
exit 1
|
|
181
|
+
fi
|
|
182
|
+
for artifact in dist/*; do
|
|
183
|
+
gh release verify-asset "$RELEASE_TAG" "$artifact" \
|
|
184
|
+
--repo "$GITHUB_REPOSITORY"
|
|
185
|
+
done
|
|
186
|
+
else
|
|
187
|
+
gh release create "$RELEASE_TAG" dist/* --repo "$GITHUB_REPOSITORY" \
|
|
188
|
+
--verify-tag --notes-file "$release_notes" --title "$RELEASE_TAG"
|
|
148
189
|
fi
|
|
149
|
-
gh release upload "$RELEASE_TAG" --repo "$GITHUB_REPOSITORY" --clobber dist/*
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
# Work in progress
|
|
2
|
-
|
|
3
|
-
This project is under heavy development. Do not make any attempt to write backwards
|
|
4
|
-
compatibility code, migration code, or the like.
|
|
5
|
-
|
|
6
1
|
## Complexity control
|
|
7
2
|
|
|
8
3
|
- A replacement is incomplete until it deletes the mechanism it supersedes in the same change.
|
|
@@ -13,10 +8,9 @@ compatibility code, migration code, or the like.
|
|
|
13
8
|
external mutation to the identity and version observed while planning when the platform
|
|
14
9
|
supports a conditional write or lease. Re-observe only when an earlier mutation invalidates a
|
|
15
10
|
precondition or when an observed trigger or platform contract requires it.
|
|
16
|
-
- Apply the cumulative complexity budgets after every code slice.
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
budget file.
|
|
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
|
|
13
|
+
design stop that requires explicit review, not routine maintenance of the budget file.
|
|
20
14
|
- If the same subsystem needs a third consecutive hardening change, stop patching it and
|
|
21
15
|
re-derive the design from the core invariants.
|
|
22
16
|
|
|
@@ -25,8 +19,8 @@ compatibility code, migration code, or the like.
|
|
|
25
19
|
- This is a `jj` repo. Do not use `git` to work on the repo itself.
|
|
26
20
|
- Do not use git worktree-based agent isolation in this repo. For isolated parallel work, use
|
|
27
21
|
`jj workspace` instead.
|
|
28
|
-
- Run the CLI locally with `
|
|
29
|
-
|
|
22
|
+
- Run the CLI locally with `just run ...` instead of invoking the module or virtualenv path
|
|
23
|
+
directly.
|
|
30
24
|
- Hard-wrap code and markdown files at 98 columns unless a file uses a different convention.
|
|
31
25
|
|
|
32
26
|
# Commit messages
|
|
@@ -38,7 +32,7 @@ compatibility code, migration code, or the like.
|
|
|
38
32
|
- Hard-wrap commit message bodies at 72 columns.
|
|
39
33
|
- The body should explain the motivation for the change, the intended behavior or design outcome,
|
|
40
34
|
and any important scope or design constraints.
|
|
41
|
-
- Do not use the body to narrate the code or to record routine validation such as
|
|
35
|
+
- Do not use the body to narrate the code or to record routine validation such as `just check`.
|
|
42
36
|
- Prefer explaining why the commit exists and what rule or user-visible behavior it is enforcing.
|
|
43
37
|
|
|
44
38
|
# Documentation
|
|
@@ -47,9 +41,10 @@ compatibility code, migration code, or the like.
|
|
|
47
41
|
rules and the public/internal split. Built-in `--help` text is held to the same standard as
|
|
48
42
|
the user docs: assume jj/git familiarity, avoid `jj-stack` internal design jargon.
|
|
49
43
|
- The web version of the user docs normally lives in the sibling jj repository at
|
|
50
|
-
`$(jj root)/../website`. When user-facing docs change here,
|
|
51
|
-
|
|
52
|
-
website update in that repository as well; preserve unrelated work in
|
|
44
|
+
`$(jj root)/../website`. When user-facing docs change here, run `just website`, inspect the
|
|
45
|
+
corresponding website changes, and update them as needed. If the change here is committed,
|
|
46
|
+
commit the corresponding website update in that repository as well; preserve unrelated work in
|
|
47
|
+
either working copy.
|
|
53
48
|
- Active internal docs use ordinary technical language too. Introduce a project-specific term
|
|
54
49
|
only when it names a real type, field, or enduring rule, define it at first use, and prefer
|
|
55
50
|
describing concrete inputs and effects.
|
|
@@ -76,13 +71,9 @@ compatibility code, migration code, or the like.
|
|
|
76
71
|
|
|
77
72
|
# Testing
|
|
78
73
|
|
|
79
|
-
- Run
|
|
80
|
-
a test run.
|
|
81
|
-
- Run
|
|
82
|
-
code change.
|
|
83
|
-
- For focused test runs, do not use plain `uv run pytest ...`; it can miss the repo's package
|
|
84
|
-
path in this project layout. First run `uv sync --locked`, then invoke pytest through the repo
|
|
85
|
-
virtualenv, for example `.venv/bin/python -m pytest tests/unit/test_jj_client.py`.
|
|
74
|
+
- Run `just check` for the default local Ruff, type-check, and test pass before finishing a code
|
|
75
|
+
change. Docs-only edits under `docs/` do not require a test run.
|
|
76
|
+
- Run focused tests with `just test`, for example `just test tests/unit/test_jj_client.py`.
|
|
86
77
|
- Before adding, modifying, removing, or reviewing tests, fixtures, helpers, or property
|
|
87
78
|
scenarios, read and follow
|
|
88
79
|
[docs/internals/testing-philosophy.md](docs/internals/testing-philosophy.md). Add or retain
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: jj-stack
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
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/
|
|
7
|
+
Project-URL: Changelog, https://github.com/bos/jj-stack/releases
|
|
7
8
|
Project-URL: Repository, https://github.com/bos/jj-stack
|
|
8
9
|
Project-URL: Issues, https://github.com/bos/jj-stack/issues
|
|
9
10
|
License-Expression: Apache-2.0
|
|
@@ -20,6 +21,7 @@ Classifier: Topic :: Software Development :: Version Control
|
|
|
20
21
|
Classifier: Topic :: Software Development :: Version Control :: Git
|
|
21
22
|
Requires-Python: >=3.14
|
|
22
23
|
Requires-Dist: httpxyz<0.32,>=0.31.0
|
|
24
|
+
Requires-Dist: markdown-it-py<5,>=4.0.0
|
|
23
25
|
Requires-Dist: pydantic<3,>=2.13.3
|
|
24
26
|
Requires-Dist: rich<16,>=15.0.0
|
|
25
27
|
Description-Content-Type: text/markdown
|
|
@@ -35,31 +37,51 @@ matching PRs.
|
|
|
35
37
|
### Requirements
|
|
36
38
|
|
|
37
39
|
- Python 3.14 or newer
|
|
38
|
-
- `uv`
|
|
39
40
|
- `jj` 0.44.0 or newer
|
|
40
41
|
- GitHub authentication
|
|
41
42
|
|
|
42
43
|
### Install
|
|
43
44
|
|
|
44
|
-
Install `jj-stack` from PyPI:
|
|
45
|
+
Install `jj-stack` from PyPI with `uv` in an isolated tool environment (recommended):
|
|
45
46
|
|
|
46
47
|
```bash
|
|
47
48
|
uv tool install jj-stack
|
|
48
49
|
```
|
|
49
50
|
|
|
50
|
-
|
|
51
|
-
`uv tool update-shell`.
|
|
51
|
+
`pipx` provides another isolated installation:
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
```bash
|
|
54
|
+
pipx install jj-stack
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
You can also use `pip` inside an activated virtual environment:
|
|
54
58
|
|
|
55
59
|
```bash
|
|
56
|
-
|
|
60
|
+
python -m pip install jj-stack
|
|
57
61
|
```
|
|
58
62
|
|
|
59
|
-
|
|
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
|
+
```
|
|
60
74
|
|
|
61
|
-
|
|
62
|
-
|
|
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.
|
|
63
85
|
|
|
64
86
|
### Submit your first stack
|
|
65
87
|
|
|
@@ -126,7 +148,7 @@ merge queues, cleanup, and working with multiple stacks.
|
|
|
126
148
|
- [Configuration](https://www.serpentine.com/software/jj-stack/reference/configuration/)
|
|
127
149
|
- [Writing PR descriptions](https://www.serpentine.com/software/jj-stack/reference/descriptions/)
|
|
128
150
|
- [Troubleshooting](https://www.serpentine.com/software/jj-stack/troubleshooting/)
|
|
129
|
-
- [
|
|
151
|
+
- [Tool comparison](https://www.serpentine.com/software/jj-stack/tool-comparison/)
|
|
130
152
|
- [JSON output](https://www.serpentine.com/software/jj-stack/reference/json-output/)
|
|
131
153
|
- [Automation and exit codes](https://www.serpentine.com/software/jj-stack/reference/automation/)
|
|
132
154
|
|
|
@@ -138,6 +160,12 @@ jj-stack <command> --help
|
|
|
138
160
|
jj-stack help --all
|
|
139
161
|
```
|
|
140
162
|
|
|
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
|
+
|
|
141
169
|
## Coding agent integration
|
|
142
170
|
|
|
143
171
|
Install the bundled skill to teach coding agents to work with local `jj` stacks and refresh their
|
|
@@ -9,31 +9,51 @@ matching PRs.
|
|
|
9
9
|
### Requirements
|
|
10
10
|
|
|
11
11
|
- Python 3.14 or newer
|
|
12
|
-
- `uv`
|
|
13
12
|
- `jj` 0.44.0 or newer
|
|
14
13
|
- GitHub authentication
|
|
15
14
|
|
|
16
15
|
### Install
|
|
17
16
|
|
|
18
|
-
Install `jj-stack` from PyPI:
|
|
17
|
+
Install `jj-stack` from PyPI with `uv` in an isolated tool environment (recommended):
|
|
19
18
|
|
|
20
19
|
```bash
|
|
21
20
|
uv tool install jj-stack
|
|
22
21
|
```
|
|
23
22
|
|
|
24
|
-
|
|
25
|
-
`uv tool update-shell`.
|
|
23
|
+
`pipx` provides another isolated installation:
|
|
26
24
|
|
|
27
|
-
|
|
25
|
+
```bash
|
|
26
|
+
pipx install jj-stack
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
You can also use `pip` inside an activated virtual environment:
|
|
28
30
|
|
|
29
31
|
```bash
|
|
30
|
-
|
|
32
|
+
python -m pip install jj-stack
|
|
31
33
|
```
|
|
32
34
|
|
|
33
|
-
|
|
35
|
+
To upgrade an installation made with `uv`, rerun its command with `--force`. If the command is
|
|
36
|
+
not on your shell `PATH`, run `uv tool update-shell`.
|
|
37
|
+
|
|
38
|
+
### Invoke it as `jj stack`
|
|
39
|
+
|
|
40
|
+
Add a command alias to your user configuration with `jj config edit --user`:
|
|
41
|
+
|
|
42
|
+
```toml
|
|
43
|
+
[aliases]
|
|
44
|
+
stack = ["util", "exec", "--", "jj-stack"]
|
|
45
|
+
```
|
|
34
46
|
|
|
35
|
-
|
|
36
|
-
|
|
47
|
+
For tab completion of both `jj-stack` and `jj stack`, add the output of `jj-stack completion` to
|
|
48
|
+
your shell startup file:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
eval "$(jj-stack completion zsh --jj-alias stack)"
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`bash` and `fish` work the same way. See
|
|
55
|
+
[Configuration](https://www.serpentine.com/software/jj-stack/reference/configuration/) for more
|
|
56
|
+
setup options.
|
|
37
57
|
|
|
38
58
|
### Submit your first stack
|
|
39
59
|
|
|
@@ -100,7 +120,7 @@ merge queues, cleanup, and working with multiple stacks.
|
|
|
100
120
|
- [Configuration](https://www.serpentine.com/software/jj-stack/reference/configuration/)
|
|
101
121
|
- [Writing PR descriptions](https://www.serpentine.com/software/jj-stack/reference/descriptions/)
|
|
102
122
|
- [Troubleshooting](https://www.serpentine.com/software/jj-stack/troubleshooting/)
|
|
103
|
-
- [
|
|
123
|
+
- [Tool comparison](https://www.serpentine.com/software/jj-stack/tool-comparison/)
|
|
104
124
|
- [JSON output](https://www.serpentine.com/software/jj-stack/reference/json-output/)
|
|
105
125
|
- [Automation and exit codes](https://www.serpentine.com/software/jj-stack/reference/automation/)
|
|
106
126
|
|
|
@@ -112,6 +132,12 @@ jj-stack <command> --help
|
|
|
112
132
|
jj-stack help --all
|
|
113
133
|
```
|
|
114
134
|
|
|
135
|
+
## Development
|
|
136
|
+
|
|
137
|
+
Contributor workflows live in the [`justfile`](justfile). With `uv`, `jj`, and `just` installed,
|
|
138
|
+
run `just` to list the setup, formatting, focused test, verification, documentation, and release
|
|
139
|
+
recipes.
|
|
140
|
+
|
|
115
141
|
## Coding agent integration
|
|
116
142
|
|
|
117
143
|
Install the bundled skill to teach coding agents to work with local `jj` stacks and refresh their
|
|
@@ -18,6 +18,7 @@ VENV_PYTHON = (
|
|
|
18
18
|
REPO_ROOT / ".venv" / (Path("Scripts/python.exe") if os.name == "nt" else Path("bin/python"))
|
|
19
19
|
)
|
|
20
20
|
PytestJobs = int | Literal["auto"]
|
|
21
|
+
_PYREFLY_TARGETS = ("src", "tests", "tools", "check.py")
|
|
21
22
|
_FRAGILE_TEST_OUTPUT_PATTERNS: tuple[tuple[str, re.Pattern[str]], ...] = (
|
|
22
23
|
(
|
|
23
24
|
"use output assertion helpers instead of exact captured output equality",
|
|
@@ -77,10 +78,17 @@ def _build_checks(
|
|
|
77
78
|
return (
|
|
78
79
|
("ruff", ("-m", "ruff", "check")),
|
|
79
80
|
("ruff-format", ("-m", "ruff", "format", "--check")),
|
|
80
|
-
("pyrefly", ("-m", "pyrefly", "check")),
|
|
81
|
+
("pyrefly", ("-m", "pyrefly", "check", *_PYREFLY_TARGETS)),
|
|
81
82
|
(
|
|
82
83
|
"pyrefly-windows",
|
|
83
|
-
(
|
|
84
|
+
(
|
|
85
|
+
"-m",
|
|
86
|
+
"pyrefly",
|
|
87
|
+
"check",
|
|
88
|
+
"--python-platform",
|
|
89
|
+
"win32",
|
|
90
|
+
*_PYREFLY_TARGETS,
|
|
91
|
+
),
|
|
84
92
|
),
|
|
85
93
|
("pytest", pytest_command),
|
|
86
94
|
)
|
|
@@ -49,6 +49,7 @@ governed = [
|
|
|
49
49
|
"src/jj_stack/commands/sync.py",
|
|
50
50
|
"src/jj_stack/commands/sync_apply.py",
|
|
51
51
|
"src/jj_stack/models/tracking.py",
|
|
52
|
+
"src/jj_stack/state/migrations.py",
|
|
52
53
|
"src/jj_stack/state/store.py",
|
|
53
54
|
"src/jj_stack/stack/trunk_evidence.py",
|
|
54
55
|
"src/jj_stack/stack/convergence.py",
|
|
@@ -23,12 +23,13 @@ web navigation and presentation.
|
|
|
23
23
|
## Reference and troubleshooting
|
|
24
24
|
|
|
25
25
|
- [Command reference](reference/commands.md)
|
|
26
|
+
- [Bookmarks and stack selection](reference/bookmarks-and-selection.md)
|
|
26
27
|
- [Configuration](reference/configuration.md)
|
|
27
28
|
- [Pull request descriptions](reference/descriptions.md)
|
|
28
29
|
- [Automation and agents](reference/automation.md)
|
|
29
30
|
- [JSON output](reference/json-output.md)
|
|
30
31
|
- [Troubleshooting](troubleshooting.md)
|
|
31
|
-
- [`jj-stack`
|
|
32
|
+
- [Compare `jj-stack` with other tools](tool-comparison.md)
|
|
32
33
|
|
|
33
34
|
The built-in help is the exact flag and alias reference:
|
|
34
35
|
|
|
@@ -30,9 +30,8 @@ Choose any pull request in your stack:
|
|
|
30
30
|
jj-stack checkout --pull-request <pr>
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
-
`checkout` follows
|
|
34
|
-
|
|
35
|
-
selected pull request's change.
|
|
33
|
+
`checkout` follows that pull request down to the bottom of its stack, fetches those commits,
|
|
34
|
+
records which local change belongs to each pull request, and runs `jj edit` on its change.
|
|
36
35
|
|
|
37
36
|
To start a new change on top instead of editing that change directly, run:
|
|
38
37
|
|
|
@@ -54,4 +53,5 @@ jj-stack submit <head-change-id>
|
|
|
54
53
|
```
|
|
55
54
|
|
|
56
55
|
`relink` is a repair command for this specific mismatch. It verifies that your pull request's
|
|
57
|
-
branch belongs to
|
|
56
|
+
branch belongs to the local change you chose; it cannot attach an unrelated pull request to new
|
|
57
|
+
work.
|
|
@@ -52,9 +52,9 @@ After GitHub merges some or all of your pull requests, `sync` fetches trunk, rem
|
|
|
52
52
|
changes from your local history if needed, rebases your remaining changes, updates your remaining
|
|
53
53
|
pull requests, and removes your PR branches when they are no longer needed.
|
|
54
54
|
|
|
55
|
-
If
|
|
56
|
-
there are no merged changes and leaves the pull requests unchanged. Run
|
|
57
|
-
you want to publish local changes.
|
|
55
|
+
If none of the pull requests in your stack has merged and GitHub has not rebased the stack,
|
|
56
|
+
`sync` reports that there are no merged changes and leaves the pull requests unchanged. Run
|
|
57
|
+
`submit` explicitly when you want to publish local changes.
|
|
58
58
|
|
|
59
59
|
What does “removes the merged changes from your local history” mean? If GitHub uses a merge
|
|
60
60
|
commit or rebase merge for your pull requests, it preserves their `jj` change IDs, and
|
|
@@ -69,16 +69,16 @@ not need to run another cleanup command.
|
|
|
69
69
|
|
|
70
70
|
### Merge queues
|
|
71
71
|
|
|
72
|
-
When `merge` uses a merge queue, it returns successfully once GitHub accepts
|
|
73
|
-
|
|
74
|
-
|
|
72
|
+
When `merge` uses a merge queue, it returns successfully once GitHub accepts the pull requests
|
|
73
|
+
you asked it to merge. This does not mean trunk has changed. Wait until GitHub reports that your
|
|
74
|
+
stack has merged. Then run `sync` with the head of your stack:
|
|
75
75
|
|
|
76
76
|
```console
|
|
77
77
|
jj-stack sync <head-change-id>
|
|
78
78
|
```
|
|
79
79
|
|
|
80
|
-
If you run either command while one of
|
|
81
|
-
|
|
80
|
+
If you run either command while one of those pull requests is queued, `submit` and `sync` leave
|
|
81
|
+
your stack unchanged.
|
|
82
82
|
|
|
83
83
|
### Merges outside jj-stack
|
|
84
84
|
|
|
@@ -113,9 +113,9 @@ to it. It also removes branches, comments, and saved pull-request links for merg
|
|
|
113
113
|
local changes are gone. If one stack cannot be updated, jj-stack explains why and continues with
|
|
114
114
|
independent stacks.
|
|
115
115
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
PR branch and the rewritten contents can be verified.
|
|
116
|
+
`sync --all` and `sync <head-change-id>` do not rebase a stack merely because trunk advanced.
|
|
117
|
+
`sync <head-change-id>` also recognizes a completed native GitHub stack rebase because GitHub
|
|
118
|
+
moved every PR branch and the rewritten contents can be verified.
|
|
119
119
|
|
|
120
120
|
## If `merge` fails after GitHub merges your pull requests
|
|
121
121
|
|
|
@@ -11,11 +11,17 @@ locally; reviewers work with native stacked pull requests on GitHub.
|
|
|
11
11
|
|
|
12
12
|
## Read the stack map
|
|
13
13
|
|
|
14
|
-
GitHub shows the ordered stack and each pull request's position. Start at the bottom,
|
|
15
|
-
|
|
16
|
-
the diff for that layer, not the cumulative diff from the
|
|
14
|
+
GitHub shows the ordered stack and each pull request's position. Start at the bottom, where the
|
|
15
|
+
stack branches from its base branch, and move upward. Each pull request's **Files changed** view
|
|
16
|
+
is the diff for that layer, not the cumulative diff from the base branch. Review and approve each
|
|
17
17
|
layer independently, while reading a higher layer with its dependencies in mind.
|
|
18
18
|
|
|
19
|
+
From a checkout that tracks the stack, you can print the same order before opening GitHub:
|
|
20
|
+
|
|
21
|
+
```console
|
|
22
|
+
jj-stack view --pull-request <pr>
|
|
23
|
+
```
|
|
24
|
+
|
|
19
25
|
## Review and merge in order
|
|
20
26
|
|
|
21
27
|
Comments, requested changes, approvals, CODEOWNERS, and required checks remain per pull request.
|
|
@@ -78,6 +78,12 @@ previously approved or asked for changes (i.e. revoking the approved state of yo
|
|
|
78
78
|
jj-stack submit --re-request
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
+
## PR history
|
|
82
|
+
|
|
83
|
+
To make it easier for a reader to understand how a pull request has changed over time, when you
|
|
84
|
+
run `submit` to update a PR that you have submitted before, `jj-stack` will keep a comment up to
|
|
85
|
+
date on the PR that shows its most recent versions, with a link to the diff for each update.
|
|
86
|
+
|
|
81
87
|
## What the `submit` command changes
|
|
82
88
|
|
|
83
89
|
| Surface | Effect |
|
|
@@ -86,6 +92,7 @@ jj-stack submit --re-request
|
|
|
86
92
|
| PR branches | Created or updated |
|
|
87
93
|
| Pull requests | Created or updated |
|
|
88
94
|
| Pull request order | Updated to match the local change order |
|
|
95
|
+
| Pull request comments | Revision history maintained |
|
|
89
96
|
| Other local stacks | Not changed |
|
|
90
97
|
|
|
91
98
|
With `jj`, you can easily move your changes between existing stacks. However, GitHub allows each
|