jj-stack 0.1.4__tar.gz → 0.1.6__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.4 → jj_stack-0.1.6}/.github/workflows/ci.yml +24 -3
- {jj_stack-0.1.4 → jj_stack-0.1.6}/.github/workflows/release.yml +3 -3
- {jj_stack-0.1.4 → jj_stack-0.1.6}/CONTRIBUTING.md +11 -9
- {jj_stack-0.1.4 → jj_stack-0.1.6}/PKG-INFO +6 -5
- {jj_stack-0.1.4 → jj_stack-0.1.6}/README.md +5 -4
- {jj_stack-0.1.4 → jj_stack-0.1.6}/check.py +2 -2
- {jj_stack-0.1.4 → jj_stack-0.1.6}/complexity-budget.toml +2 -2
- {jj_stack-0.1.4 → jj_stack-0.1.6}/docs/guides/close-or-separate.md +4 -3
- {jj_stack-0.1.4 → jj_stack-0.1.6}/docs/guides/merge-and-sync.md +42 -21
- {jj_stack-0.1.4 → jj_stack-0.1.6}/docs/guides/review-a-stack.md +6 -5
- {jj_stack-0.1.4 → jj_stack-0.1.6}/docs/guides/submit-and-update.md +4 -3
- {jj_stack-0.1.4 → jj_stack-0.1.6}/docs/guides/working-on-github.md +4 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/docs/internals/README.md +2 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/docs/internals/design.md +66 -34
- jj_stack-0.1.6/docs/internals/property-testing.md +35 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/docs/internals/releasing.md +4 -4
- {jj_stack-0.1.4 → jj_stack-0.1.6}/docs/internals/testing-philosophy.md +2 -1
- {jj_stack-0.1.4 → jj_stack-0.1.6}/docs/json-output.schema.json +185 -1
- {jj_stack-0.1.4 → jj_stack-0.1.6}/docs/mental-model.md +7 -11
- {jj_stack-0.1.4 → jj_stack-0.1.6}/docs/quick-start.md +7 -10
- {jj_stack-0.1.4 → jj_stack-0.1.6}/docs/reference/automation.md +6 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/docs/reference/bookmarks-and-selection.md +4 -4
- {jj_stack-0.1.4 → jj_stack-0.1.6}/docs/reference/configuration.md +10 -4
- {jj_stack-0.1.4 → jj_stack-0.1.6}/docs/reference/json-output.md +74 -5
- {jj_stack-0.1.4 → jj_stack-0.1.6}/docs/tool-comparison.md +8 -8
- {jj_stack-0.1.4 → jj_stack-0.1.6}/docs/troubleshooting.md +36 -28
- {jj_stack-0.1.4 → jj_stack-0.1.6}/justfile +1 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/pyproject.toml +3 -9
- jj_stack-0.1.6/release-notes/v0.1.5.md +28 -0
- jj_stack-0.1.6/release-notes/v0.1.6.md +14 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/scripts/describe_with_claude.py +0 -2
- {jj_stack-0.1.4 → jj_stack-0.1.6}/scripts/describe_with_codex.py +0 -2
- {jj_stack-0.1.4 → jj_stack-0.1.6}/scripts/describe_with_editor.py +0 -8
- {jj_stack-0.1.4 → jj_stack-0.1.6}/scripts/describe_with_prompt.py +0 -2
- {jj_stack-0.1.4 → jj_stack-0.1.6}/skills/jj-stack/SKILL.md +9 -6
- {jj_stack-0.1.4 → jj_stack-0.1.6}/skills/jj-stack/references/recovery.md +25 -12
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/bootstrap.py +11 -6
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/cli.py +127 -161
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/cli_help.py +6 -7
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/commands/_json_status.py +11 -11
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/commands/checkout.py +15 -25
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/commands/cleanup/actions.py +17 -37
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/commands/cleanup/command.py +81 -48
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/commands/doctor.py +5 -7
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/commands/list_.py +32 -56
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/commands/merge/command.py +132 -86
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/commands/merge/github_stack.py +107 -119
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/commands/merge/plan.py +16 -37
- jj_stack-0.1.6/src/jj_stack/commands/merge/wait.py +202 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/commands/relink.py +7 -8
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/commands/submit/auto_close.py +1 -18
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/commands/submit/changes.py +74 -23
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/commands/submit/command.py +329 -232
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/commands/submit/descriptions.py +9 -8
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/commands/submit/editor.py +35 -38
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/commands/submit/github_stack.py +8 -8
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/commands/submit/inputs.py +4 -10
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/commands/submit/models.py +1 -11
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/commands/submit/prs.py +3 -5
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/commands/submit/publication.py +2 -3
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/commands/sync.py +93 -21
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/commands/sync_apply.py +14 -18
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/commands/sync_prs.py +1 -1
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/commands/unstack.py +18 -31
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/commands/view.py +41 -51
- jj_stack-0.1.6/src/jj_stack/commands/view_details.py +85 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/completion.py +17 -38
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/config.py +12 -31
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/console.py +134 -120
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/errors.py +1 -7
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/formatting.py +2 -20
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/github/auth.py +9 -6
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/github/client.py +399 -159
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/github/error_messages.py +8 -53
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/identifiers.py +15 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/jj/client.py +134 -63
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/jj/settings.py +12 -8
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/models/github.py +21 -3
- jj_stack-0.1.6/src/jj_stack/models/github_details.py +97 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/models/tracking.py +1 -9
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/stack/change_state.py +49 -60
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/stack/convergence.py +86 -61
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/stack/convergence_models.py +2 -4
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/stack/github_stack_safety.py +19 -1
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/stack/global_convergence.py +35 -32
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/stack/pr_branches.py +5 -4
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/stack/pr_facts.py +13 -34
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/stack/repo.py +14 -6
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/stack/reporting.py +36 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/stack/selected.py +13 -12
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/stack/selection.py +5 -3
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/stack/status.py +46 -9
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/state/migrations.py +2 -1
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/state/operation_lock.py +6 -11
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/state/store.py +26 -40
- jj_stack-0.1.6/src/jj_stack/timing.py +63 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/ui.py +5 -24
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/conftest.py +2 -2
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/integration/test_checkout_command.py +20 -30
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/integration/test_cleanup_command.py +0 -52
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/integration/test_jj_stack.py +20 -24
- jj_stack-0.1.6/tests/integration/test_jsonl_output.py +38 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/integration/test_list_command.py +100 -46
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/integration/test_merge_command.py +190 -53
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/integration/test_submit_command.py +157 -21
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/integration/test_sync_command.py +160 -8
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/integration/test_unstack_command.py +1 -1
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/integration/test_view_command.py +85 -3
- jj_stack-0.1.6/tests/property/test_submit_property_scenarios.py +152 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/run_submit_property_scenarios.py +42 -20
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/support/fake_github.py +475 -161
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/support/integration_helpers.py +6 -18
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/support/json_schema.py +21 -9
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/support/output_assertions.py +0 -10
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/support/pytest_concurrency.py +1 -14
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/support/stack_edit_scenarios.py +0 -2
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/support/stack_machine.py +317 -102
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/support/submit_faults.py +12 -1
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_change_state.py +2 -2
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_cli.py +3 -18
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_cli_dispatch.py +48 -1
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_completion.py +1 -16
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_describe_with_prompt_script.py +0 -20
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_errors.py +0 -14
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_github_client.py +213 -65
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_github_models.py +3 -17
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_github_resolution.py +2 -14
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_github_stack_planning.py +0 -27
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_jj_client.py +17 -94
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_merge.py +0 -55
- jj_stack-0.1.6/tests/unit/test_merge_wait.py +101 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_operation_lock.py +0 -21
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_pr_branches.py +9 -20
- jj_stack-0.1.6/tests/unit/test_pr_refs.py +34 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_property_runner.py +20 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_relink.py +10 -8
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_stack_path.py +0 -8
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_submit.py +7 -9
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_submit_descriptions.py +21 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_submit_editor.py +3 -45
- jj_stack-0.1.6/tests/unit/test_timing.py +27 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_ui.py +26 -15
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_view.py +73 -8
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tools/check_jj_release_updates.py +6 -10
- jj_stack-0.1.6/uv.lock +740 -0
- jj_stack-0.1.4/docs/internals/property-testing.md +0 -14
- jj_stack-0.1.4/tests/property/test_submit_property_scenarios.py +0 -105
- jj_stack-0.1.4/tests/unit/test_cleanup.py +0 -20
- jj_stack-0.1.4/tests/unit/test_divergence.py +0 -15
- jj_stack-0.1.4/tests/unit/test_pr_refs.py +0 -51
- jj_stack-0.1.4/uv.lock +0 -915
- {jj_stack-0.1.4 → jj_stack-0.1.6}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/.github/SECURITY.md +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/.github/dependabot.yml +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/.github/pull_request_template.md +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/.github/workflows/block-pr-base-merges.yml +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/.github/workflows/check-jj-release-updates.yml +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/.github/workflows/codeql.yml +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/.gitignore +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/AGENTS.md +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/CLAUDE.md +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/LICENSE +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/NOTICE +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/docs/AGENTS.md +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/docs/README.md +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/docs/guides/continue-a-stack.md +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/docs/guides/multiple-stacks.md +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/docs/guides/revise.md +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/docs/internals/AGENTS.md +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/docs/internals/code-reviews.md +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/docs/reference/commands.md +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/docs/reference/descriptions.md +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/evals/jj-stack-skill.md +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/release-notes/v0.1.2.md +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/release-notes/v0.1.3.md +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/release-notes/v0.1.4.md +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/scripts/README.md +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/skills/jj-stack/agents/openai.yaml +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/skills/jj-stack/references/multi-stack.md +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/__init__.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/__main__.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/commands/__init__.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/commands/in_use.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/commands/merge/__init__.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/commands/submit/__init__.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/commands/submit/default_pr_text.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/commands/submit/managed_comments.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/commands/submit/overview_comments.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/commands/submit/render.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/commands/submit/revision_comments.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/concurrency.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/github/__init__.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/github/overview_comments.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/github/pr_refs.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/github/resolution.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/github/stack_availability.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/jj/__init__.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/jj/cli_args.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/jj/colors.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/models/__init__.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/models/git.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/models/stack.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/pr_branch_namespace.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/stack/__init__.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/stack/convergence_observation.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/stack/divergence.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/stack/observation.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/stack/path.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/stack/preparation.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/stack/trunk.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/stack/trunk_evidence.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/src/jj_stack/state/__init__.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/__init__.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/integration/__init__.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/integration/conftest.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/integration/submit_command_helpers.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/integration/test_boundary_conditions.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/integration/test_doctor_command.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/integration/test_fake_github_contracts.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/integration/test_relink_command.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/run_live_github.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/support/__init__.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/support/change_helpers.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/support/contexts.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/support/tracking.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/__init__.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_bootstrap.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_check_script.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_checkout.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_concurrency.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_config.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_default_pr_text.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_describe_with_editor_script.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_github_auth.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_github_error_messages.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_in_use_command.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_jj_settings.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_live_github_runner.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_pr_facts.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_property_scenarios.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_selected.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_stack_status.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_store.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_sync.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_trunk_evidence.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_unstack.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tests/unit/test_view_entrypoint.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tools/check_complexity.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/tools/check_release_artifacts.py +0 -0
- {jj_stack-0.1.4 → jj_stack-0.1.6}/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
|
|
|
@@ -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
|
|
|
@@ -65,6 +65,27 @@ jobs:
|
|
|
65
65
|
fi
|
|
66
66
|
printf '%s\n' "$install_dir" >> "$GITHUB_PATH"
|
|
67
67
|
|
|
68
|
+
- name: Install current Git
|
|
69
|
+
if: runner.os == 'macOS'
|
|
70
|
+
# The runner image's formula list can predate the current Git release.
|
|
71
|
+
run: |
|
|
72
|
+
brew update
|
|
73
|
+
brew install git
|
|
74
|
+
|
|
75
|
+
- name: Check Git version
|
|
76
|
+
shell: bash
|
|
77
|
+
run: |
|
|
78
|
+
git --version
|
|
79
|
+
# Git 2.56 changed which refs a push by URL updates. Other runners keep their own
|
|
80
|
+
# Git so older versions stay covered, but this one must run the newer behavior.
|
|
81
|
+
if [[ "$RUNNER_OS" == macOS ]]; then
|
|
82
|
+
IFS=. read -r major minor _ <<< "$(git --version | awk '{print $3}')"
|
|
83
|
+
if (( major < 2 || (major == 2 && minor < 56) )); then
|
|
84
|
+
echo "::error::The macOS job needs Git 2.56 or newer; found $(git --version)."
|
|
85
|
+
exit 1
|
|
86
|
+
fi
|
|
87
|
+
fi
|
|
88
|
+
|
|
68
89
|
- name: Run local verification suite
|
|
69
90
|
shell: bash
|
|
70
91
|
run: ./check.py
|
|
@@ -79,7 +100,7 @@ jobs:
|
|
|
79
100
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
80
101
|
|
|
81
102
|
- name: Set up uv
|
|
82
|
-
uses: astral-sh/setup-uv@
|
|
103
|
+
uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
|
|
83
104
|
with:
|
|
84
105
|
python-version: "3.14"
|
|
85
106
|
|
|
@@ -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
|
|
|
@@ -39,20 +39,22 @@ just check
|
|
|
39
39
|
```
|
|
40
40
|
|
|
41
41
|
Pyrefly is the default type checker, including a second pass targeting Windows. To select ty
|
|
42
|
-
|
|
42
|
+
for the current platform instead, use `--type-checker` or its short form, `-t`:
|
|
43
43
|
|
|
44
44
|
```console
|
|
45
45
|
just check -t ty
|
|
46
|
-
just check -t mypy
|
|
47
46
|
```
|
|
48
47
|
|
|
49
|
-
Repeat the option to run several in the given order, for example
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
48
|
+
Repeat the option to run several in the given order, for example `just check -t pyrefly -t ty`.
|
|
49
|
+
The runner installs the selected checkers from the lockfile, checks `src`, `tests`, `tools`, and
|
|
50
|
+
`check.py`, and runs the usual Ruff and pytest checks. It stops at the first failed check. ty is
|
|
51
|
+
optional during development and can report issues that Pyrefly does not; its failures are
|
|
52
|
+
reported normally. Plain `just check` and CI continue to use Pyrefly. Before a release, follow the
|
|
53
|
+
[requirement for both type checkers to pass](docs/internals/releasing.md#qualify-the-candidate).
|
|
54
|
+
|
|
55
|
+
mypy is deliberately not part of the toolchain. It fixes a variable's type at its first
|
|
56
|
+
assignment and rejects a later assignment of another type, which Pyrefly and ty accept, so
|
|
57
|
+
keeping it green required annotations whose only purpose was to satisfy mypy.
|
|
56
58
|
|
|
57
59
|
Run focused tests while you iterate:
|
|
58
60
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: jj-stack
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.6
|
|
4
4
|
Summary: Stacked GitHub pull requests for Jujutsu
|
|
5
5
|
Project-URL: Homepage, https://www.serpentine.com/software/jj-stack/
|
|
6
6
|
Project-URL: Documentation, https://www.serpentine.com/software/jj-stack/
|
|
@@ -99,10 +99,11 @@ your edit.
|
|
|
99
99
|
2. Run `jj-stack submit`.
|
|
100
100
|
3. Revise, add, remove, or reorder the changes locally as reviews come in.
|
|
101
101
|
4. Run `jj-stack submit` again to refresh GitHub.
|
|
102
|
-
5. Run `jj-stack merge
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
102
|
+
5. Run `jj-stack merge` when the PRs at the bottom are ready. Pass `--pull-request <pr>` to
|
|
103
|
+
stop at an earlier PR, and `--method` to choose a merge method your repo allows. The command
|
|
104
|
+
waits for GitHub, including its merge queue, then updates your local stack and remaining PRs.
|
|
105
|
+
6. If you used `--no-wait`, interrupted the wait, or merged through GitHub, run
|
|
106
|
+
`jj-stack sync <head-change-id>` after GitHub finishes.
|
|
106
107
|
|
|
107
108
|
`view`, `submit`, `merge`, and `sync` accept a change ID when you need to select a stack other
|
|
108
109
|
than the one ending at the working copy.
|
|
@@ -71,10 +71,11 @@ your edit.
|
|
|
71
71
|
2. Run `jj-stack submit`.
|
|
72
72
|
3. Revise, add, remove, or reorder the changes locally as reviews come in.
|
|
73
73
|
4. Run `jj-stack submit` again to refresh GitHub.
|
|
74
|
-
5. Run `jj-stack merge
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
74
|
+
5. Run `jj-stack merge` when the PRs at the bottom are ready. Pass `--pull-request <pr>` to
|
|
75
|
+
stop at an earlier PR, and `--method` to choose a merge method your repo allows. The command
|
|
76
|
+
waits for GitHub, including its merge queue, then updates your local stack and remaining PRs.
|
|
77
|
+
6. If you used `--no-wait`, interrupted the wait, or merged through GitHub, run
|
|
78
|
+
`jj-stack sync <head-change-id>` after GitHub finishes.
|
|
78
79
|
|
|
79
80
|
`view`, `submit`, `merge`, and `sync` accept a change ID when you need to select a stack other
|
|
80
81
|
than the one ending at the working copy.
|
|
@@ -20,7 +20,7 @@ VENV_PYTHON = (
|
|
|
20
20
|
)
|
|
21
21
|
PytestJobs = int | Literal["auto"]
|
|
22
22
|
_TYPE_CHECK_TARGETS = ("src", "tests", "tools", "check.py")
|
|
23
|
-
_TYPE_CHECKERS = ("pyrefly", "ty"
|
|
23
|
+
_TYPE_CHECKERS = ("pyrefly", "ty")
|
|
24
24
|
_FRAGILE_TEST_OUTPUT_PATTERNS: tuple[tuple[str, re.Pattern[str]], ...] = (
|
|
25
25
|
(
|
|
26
26
|
"use output assertion helpers instead of exact captured output equality",
|
|
@@ -79,7 +79,7 @@ def _build_checks(
|
|
|
79
79
|
)
|
|
80
80
|
type_checks: list[tuple[str, tuple[str, ...]]] = []
|
|
81
81
|
for checker in type_checkers:
|
|
82
|
-
command = ("-m", checker
|
|
82
|
+
command = ("-m", checker, "check")
|
|
83
83
|
type_checks.append((checker, (*command, *_TYPE_CHECK_TARGETS)))
|
|
84
84
|
if checker == "pyrefly":
|
|
85
85
|
type_checks.append(
|
|
@@ -57,9 +57,10 @@ jj-stack cleanup <head-change-id>
|
|
|
57
57
|
|
|
58
58
|
### If cleanup keeps a branch
|
|
59
59
|
|
|
60
|
-
Cleanup keeps a PR branch while another
|
|
61
|
-
message names
|
|
62
|
-
retarget it or delete its head branch if you no longer need to
|
|
60
|
+
Cleanup keeps a PR branch while another PR still uses it as its base: an open PR, or a closed PR
|
|
61
|
+
that GitHub could still reopen. The message names that PR. Retarget an open PR to trunk. For a
|
|
62
|
+
closed PR, either reopen and retarget it, or delete its head branch if you no longer need to
|
|
63
|
+
reopen it. Then rerun cleanup.
|
|
63
64
|
|
|
64
65
|
A branch also stays while an unmerged PR in a GitHub stack needs it. Remove that stack with
|
|
65
66
|
`jj-stack unstack` before retrying cleanup.
|
|
@@ -11,8 +11,8 @@ stack. Once the PRs have merged, `jj-stack sync` updates your local stack and an
|
|
|
11
11
|
pull requests.
|
|
12
12
|
|
|
13
13
|
GitHub can perform the merge immediately or put it through a merge queue. An immediate merge
|
|
14
|
-
is called a **direct merge
|
|
15
|
-
|
|
14
|
+
is called a **direct merge**. In both cases, `jj-stack merge` waits for completion and runs
|
|
15
|
+
the sync automatically.
|
|
16
16
|
|
|
17
17
|
## Before merging
|
|
18
18
|
|
|
@@ -28,11 +28,22 @@ jj-stack merge <head-change-id>
|
|
|
28
28
|
that their PR branches and pull requests have not moved unexpectedly. GitHub decides whether
|
|
29
29
|
checks, approvals, conflicts, and repo rules allow the merge.
|
|
30
30
|
|
|
31
|
+
`jj-stack list` and `jj-stack view` show review decisions, checks, and specific merge warnings.
|
|
32
|
+
`needs review` means GitHub still requires a review.
|
|
33
|
+
|
|
34
|
+
To inspect unresolved review threads and failed or pending checks, including links, run:
|
|
35
|
+
|
|
36
|
+
```console
|
|
37
|
+
jj-stack view --verbose <head-change-id>
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Verbose output includes thread excerpts, even for outdated threads.
|
|
41
|
+
|
|
31
42
|
## Choose a merge method
|
|
32
43
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
44
|
+
For a direct merge, `merge` uses your repo's only allowed merge method if there is just one.
|
|
45
|
+
With several allowed methods and an unsigned stack, it prefers rebase, then squash, then a merge
|
|
46
|
+
commit. Choose an allowed method with `--method`, or set a default once:
|
|
36
47
|
|
|
37
48
|
```console
|
|
38
49
|
jj config set --repo jj-stack.merge_method squash
|
|
@@ -64,7 +75,7 @@ For example, in A → B → C, suppose the PRs are #1, #2, and #3. To merge only
|
|
|
64
75
|
jj-stack merge --pull-request 1 --method squash
|
|
65
76
|
```
|
|
66
77
|
|
|
67
|
-
After
|
|
78
|
+
After the command finishes, PR #1 is merged, PR #2 targets `main`, and PR #3 still targets PR #2's
|
|
68
79
|
branch. Both remaining PRs keep their numbers and discussions:
|
|
69
80
|
|
|
70
81
|
```mermaid
|
|
@@ -83,7 +94,8 @@ proceed because all three PRs belong to the same GitHub stack.
|
|
|
83
94
|
|
|
84
95
|
After GitHub merges some or all of your pull requests, `sync` fetches the updated trunk and
|
|
85
96
|
rebases your remaining changes onto it. It removes any obsolete local copies of the merged
|
|
86
|
-
changes, updates the remaining PRs, and deletes PR branches that are no longer needed.
|
|
97
|
+
changes, updates the remaining PRs, and deletes PR branches that are no longer needed. If your
|
|
98
|
+
working copy is on a merged change, `sync` first moves it to a new empty change on trunk.
|
|
87
99
|
|
|
88
100
|
Select the stack by its head change ID or by any linked pull request:
|
|
89
101
|
|
|
@@ -95,8 +107,8 @@ jj-stack sync --pull-request <pr>
|
|
|
95
107
|
`sync --pull-request` updates the complete local stack containing the named PR, including
|
|
96
108
|
changes above it. The selected PR can already be merged.
|
|
97
109
|
|
|
98
|
-
|
|
99
|
-
|
|
110
|
+
If someone pushes a PR's submitted commit straight to trunk instead of merging the PR, `sync`
|
|
111
|
+
closes that PR and cleans up, provided the PR is not part of a GitHub stack.
|
|
100
112
|
|
|
101
113
|
If no PR has merged, no submitted commit has reached trunk, and GitHub has not rebased the stack,
|
|
102
114
|
`sync` leaves the pull requests unchanged. Run `jj-stack submit` explicitly when you want to
|
|
@@ -107,19 +119,25 @@ changes may still depend on the original local changes. `sync` rebases that work
|
|
|
107
119
|
squashed result and removes the old copies. Other merge methods also need `sync` to update
|
|
108
120
|
the remaining PRs and remove unused branches.
|
|
109
121
|
|
|
110
|
-
###
|
|
122
|
+
### Merge queues
|
|
111
123
|
|
|
112
|
-
|
|
113
|
-
|
|
124
|
+
GitHub tests each queued PR on a temporary merge commit that combines it with the PRs ahead of
|
|
125
|
+
it, so those checks appear on that commit rather than on the PR's own Checks tab. While waiting,
|
|
126
|
+
`merge` shows each PR's queue position and the state of those checks.
|
|
114
127
|
|
|
115
|
-
|
|
128
|
+
If GitHub removes a PR from the queue, `merge` stops, reports GitHub's reason, links to the
|
|
129
|
+
checks on that commit, and names the next step. See [queue removal recovery][queue-removal].
|
|
116
130
|
|
|
117
|
-
|
|
118
|
-
They may still be waiting to merge at that point. Wait until GitHub reports that the merge
|
|
119
|
-
has finished, then run `sync` for that stack.
|
|
131
|
+
[queue-removal]: ../troubleshooting.md#a-stack-was-removed-from-the-merge-queue
|
|
120
132
|
|
|
121
133
|
While any selected pull request is queued, `jj-stack submit` refuses to update the stack and
|
|
122
|
-
`jj-stack sync` leaves it unchanged.
|
|
134
|
+
`jj-stack sync` leaves it unchanged; rerun `jj-stack merge` to resume waiting.
|
|
135
|
+
|
|
136
|
+
### Leaving before GitHub finishes
|
|
137
|
+
|
|
138
|
+
Use `--no-wait` to return as soon as GitHub accepts the request, or press Ctrl-C to stop
|
|
139
|
+
waiting. Neither cancels the request. Rerun the same `jj-stack merge` to keep watching it, or run
|
|
140
|
+
`jj-stack sync <head-change-id>` once GitHub finishes.
|
|
123
141
|
|
|
124
142
|
### Merges outside jj-stack
|
|
125
143
|
|
|
@@ -163,19 +181,22 @@ jj-stack sync <head-change-id>
|
|
|
163
181
|
```
|
|
164
182
|
|
|
165
183
|
If only cleanup failed, run the `jj-stack cleanup --pull-request <pr>` commands in the hint.
|
|
166
|
-
The
|
|
184
|
+
The hint names each PR because the merged local changes may already be gone.
|
|
167
185
|
|
|
168
186
|
Your pull requests are already merged, so do not retry `jj-stack merge`.
|
|
169
187
|
|
|
170
188
|
## When trunk moves without one of your pull requests merging
|
|
171
189
|
|
|
172
|
-
`sync` handles completed GitHub merges and stack rebases. If trunk merely advanced,
|
|
173
|
-
rebase your changes with `jj` if needed, then submit the rewritten changes:
|
|
190
|
+
`jj-stack sync` handles completed GitHub merges and stack rebases. If trunk merely advanced,
|
|
191
|
+
fetch it, rebase your changes with `jj` if needed, then submit the rewritten changes:
|
|
174
192
|
|
|
175
193
|
```console
|
|
176
194
|
jj git fetch
|
|
177
|
-
jj rebase -
|
|
195
|
+
jj rebase -b '<change-id>' -o 'trunk()'
|
|
178
196
|
jj-stack submit <head-change-id>
|
|
179
197
|
```
|
|
180
198
|
|
|
199
|
+
Use any change in the stack with `-b`; jj finds its base and moves the whole stack, including
|
|
200
|
+
forks. You can even omit `-b` to use jj's default of `@`.
|
|
201
|
+
|
|
181
202
|
Rebase when your work needs the latest trunk or GitHub requires it before merging.
|
|
@@ -29,7 +29,7 @@ version appears first and is marked **current**. Use **Changes from previous ver
|
|
|
29
29
|
what changed in that update. Use **Submitted commit** to inspect the exact commit published for
|
|
30
30
|
that version.
|
|
31
31
|
|
|
32
|
-
The comment lists recent
|
|
32
|
+
The comment lists the most recent versions. If you missed several updates, follow their diff
|
|
33
33
|
links in order; use the PR's **Files changed** tab to review the current layer as a whole.
|
|
34
34
|
|
|
35
35
|
## Review and merge in order
|
|
@@ -58,10 +58,11 @@ each PR.
|
|
|
58
58
|
|
|
59
59
|
## Merge queues
|
|
60
60
|
|
|
61
|
-
GitHub adds a stack's pull requests to the queue in dependency order.
|
|
62
|
-
also removes every PR above it
|
|
63
|
-
|
|
64
|
-
[
|
|
61
|
+
GitHub adds a stack's pull requests to the queue in dependency order. If GitHub removes a PR, it
|
|
62
|
+
also removes every PR above it; `jj-stack merge` stops, reports the reason, and names the next
|
|
63
|
+
step. Fix the cause and rerun the same `jj-stack merge` command. See
|
|
64
|
+
[queue removal recovery](../troubleshooting.md#a-stack-was-removed-from-the-merge-queue) and
|
|
65
|
+
GitHub's [merge queue guidance][github-queue].
|
|
65
66
|
|
|
66
67
|
[github-review]: https://docs.github.com/en/pull-requests/how-tos/review-pull-requests/reviewing-stacked-pull-requests
|
|
67
68
|
[github-merge]: https://docs.github.com/en/pull-requests/how-tos/merge-and-close-pull-requests/merging-stacked-pull-requests
|
|
@@ -87,10 +87,11 @@ look again:
|
|
|
87
87
|
jj-stack submit --re-request
|
|
88
88
|
```
|
|
89
89
|
|
|
90
|
-
##
|
|
90
|
+
## Revision history
|
|
91
91
|
|
|
92
|
-
After updates, jj-stack maintains a comment on each PR
|
|
93
|
-
to the
|
|
92
|
+
After updates, jj-stack maintains a **Revision history** comment on each PR. It lists the PR's
|
|
93
|
+
recent versions with links to the diff between each version and the next, so reviewers can see
|
|
94
|
+
what changed since their last review.
|
|
94
95
|
|
|
95
96
|
For edits made directly on GitHub, see [work with a stack on GitHub](working-on-github.md).
|
|
96
97
|
If you move changes between stacks, follow
|
|
@@ -52,5 +52,9 @@ both from the local `jj` history. To change the base or order, make that change
|
|
|
52
52
|
submit again. To remove the GitHub stack while leaving the PRs open, see
|
|
53
53
|
[separate a stack](close-or-separate.md#remove-a-github-stack).
|
|
54
54
|
|
|
55
|
+
Do not enable auto-merge, shown as **Merge when ready** with a merge queue, on a pull request
|
|
56
|
+
you will stack more changes on. GitHub refuses to add such a PR to a stack, so the next submit
|
|
57
|
+
stops until you disable it.
|
|
58
|
+
|
|
55
59
|
For reviewer and repo configuration guidance, see
|
|
56
60
|
[review and merge a stack on GitHub](review-a-stack.md).
|
|
@@ -43,3 +43,5 @@ describe current behavior and rationale; commit history records how the design c
|
|
|
43
43
|
- [jj/client.py](../../src/jj_stack/jj/client.py) provides jj queries and mutations;
|
|
44
44
|
[github/client.py](../../src/jj_stack/github/client.py) handles GitHub requests.
|
|
45
45
|
[state/store.py](../../src/jj_stack/state/store.py) reads and writes tracking data.
|
|
46
|
+
- [timing.py](../../src/jj_stack/timing.py) records the per-call durations that `--time-output`
|
|
47
|
+
reports. Start a performance investigation by running the slow command with that flag.
|
|
@@ -128,7 +128,9 @@ rewrite is not mistaken for a local copy. Two untracked remote bookmarks pointin
|
|
|
128
128
|
commit prevent this exception, even if both are in the reserved namespace. Trunk, tags, and
|
|
129
129
|
bookmarks outside the namespace still make their targets immutable. If the submitted commit and
|
|
130
130
|
one local rewrite are both visible, the submitted commit is treated as the submitted snapshot
|
|
131
|
-
rather than a second local candidate.
|
|
131
|
+
rather than a second local candidate. Rewrites that a command has already planned run with jj's
|
|
132
|
+
immutability check disabled: an immutability revset that names a namespace bookmark would
|
|
133
|
+
resurrect the hidden commit it points at when jj rewrites that commit's ancestor.
|
|
132
134
|
|
|
133
135
|
An unknown or mismatched bookmark creates no ownership. It remains untouched and does not block an
|
|
134
136
|
independent stack. `submit` refuses to claim a colliding visible name for a new PR, while remote
|
|
@@ -175,7 +177,7 @@ through a merge queue.
|
|
|
175
177
|
| `submit` | Create PRs and refresh the selected stack; only this command publishes new changes. |
|
|
176
178
|
| `sync` | Update a local stack after a merge or native GitHub stack rebase. |
|
|
177
179
|
| `sync --all` | Sync stacks after merges and finish eligible PRs without local copies. |
|
|
178
|
-
| `merge` | Request a GitHub merge; run sync
|
|
180
|
+
| `merge` | Request a GitHub merge; wait for completion and run sync unless `--no-wait` is used. |
|
|
179
181
|
| `unstack` | Remove a GitHub stack; `--local` instead forgets local tracking. |
|
|
180
182
|
| `cleanup` | Remove eligible artifacts and links; optionally close explicitly selected PRs. |
|
|
181
183
|
| `checkout` | Adopt existing PRs and edit the selected change in the current workspace. |
|
|
@@ -186,7 +188,7 @@ through a merge queue.
|
|
|
186
188
|
|
|
187
189
|
`jj` owns general history editing. There is no standalone `jj-stack rebase` command.
|
|
188
190
|
|
|
189
|
-
`sync` and `merge` fetch before planning, including during `--dry-run`. A
|
|
191
|
+
`sync` and `merge` fetch before planning, including during `--dry-run`. A merge that waits fetches
|
|
190
192
|
again after GitHub completes it. `checkout --pull-request` fetches when the selected PR's head
|
|
191
193
|
commit is not already local. Other commands do not fetch. Commands evaluate `trunk()` after any
|
|
192
194
|
fetch they perform; without a fetch, they use the locally available trunk.
|
|
@@ -245,10 +247,11 @@ removed, so `in-use` continues to report adoption. `view`, `list`, and `in-use`
|
|
|
245
247
|
An unreadable or invalid file blocks commands that load it and names the path to move aside before
|
|
246
248
|
using `checkout` or `relink` to restore links. A newer unsupported schema requires an upgrade.
|
|
247
249
|
|
|
248
|
-
Mutating commands serialize per repo
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
250
|
+
Mutating commands serialize per repo while they observe and mutate. A command that waits for
|
|
251
|
+
GitHub, an editor, or a describe helper releases that serialization while it waits and observes
|
|
252
|
+
again before it mutates. An interruption can leave completed external effects even if the command
|
|
253
|
+
reports failure. A retry computes what remains from current observations; it never replays a
|
|
254
|
+
saved plan or selector. The submitted baseline records an acknowledged commit, not pending work.
|
|
252
255
|
|
|
253
256
|
## Policies
|
|
254
257
|
|
|
@@ -368,15 +371,27 @@ queue object or a `MERGE_QUEUE` branch rule. If that lookup fails, `merge` stops
|
|
|
368
371
|
error before requesting anything. It sends the explicit action `merge_queue` when a queue is
|
|
369
372
|
found and `direct_merge` otherwise.
|
|
370
373
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
374
|
+
`merge` waits for completion by default, then fetches and syncs the whole selected stack before
|
|
375
|
+
returning, including changes above the last merged PR and commits GitHub rewrote. An `enqueued`
|
|
376
|
+
result means GitHub accepted the PRs into the queue; waiting continues by observing every selected
|
|
377
|
+
PR until all report merged. Observations must still match the planned PR identities and submitted
|
|
378
|
+
heads. Queue progress is shown but never determines merge eligibility. GitHub removes a queue
|
|
379
|
+
entry before it records the merge, so an open, unqueued PR with no recorded non-merge reason
|
|
380
|
+
still counts as merging until that state persists; a recorded reason other than a merge is a
|
|
381
|
+
removal. A removal stops the wait without local changes, reports the recorded reason and the
|
|
382
|
+
temporary merge commit, and names the next step: `sync` when a lower PR already merged, otherwise
|
|
383
|
+
the same `merge` again.
|
|
384
|
+
|
|
385
|
+
`--no-wait` returns after GitHub accepts the request; the user runs `sync` once GitHub merges.
|
|
386
|
+
Interrupting a wait does not cancel the request. Rerunning `merge` for the same action and
|
|
387
|
+
expected head resumes waiting; a different action or expected head stops. A queue request's merge
|
|
388
|
+
method is not part of that identity because the queue chooses it. Queue waiting has no deadline;
|
|
389
|
+
polling a direct merge request does. A rejection leaves local changes unchanged.
|
|
376
390
|
|
|
377
391
|
Automatic reconciliation identifies the containing stack by the full change ID of the head
|
|
378
|
-
resolved before the merge request. It does not reinterpret the original revset
|
|
379
|
-
|
|
392
|
+
resolved before the merge request. It does not reinterpret the original revset after fetching
|
|
393
|
+
the changed trunk. If the fetch leaves that head with no visible commit, the local copies are
|
|
394
|
+
already gone, and the follow-up runs only cleanup for the merged PRs.
|
|
380
395
|
|
|
381
396
|
GitHub merge success and local reconciliation are separate outcomes. If GitHub completes the
|
|
382
397
|
merge but the automatic sync stops, `merge` returns the sync failure status and says that the
|
|
@@ -416,8 +431,8 @@ routing for the trunk branch, it does not preflight approvals, checks, conflicts
|
|
|
416
431
|
state across the repo. GitHub applies those rules to the requested GitHub stack or
|
|
417
432
|
single-PR mutation, and `jj-stack` reports the result.
|
|
418
433
|
|
|
419
|
-
A rejected merge
|
|
420
|
-
again for a conflict; address the
|
|
434
|
+
A rejected merge preserves GitHub's reason and says what to do next: rebase onto trunk, resolve,
|
|
435
|
+
and submit again for a conflict; address the reported issue on GitHub and retry otherwise.
|
|
421
436
|
|
|
422
437
|
### Trunk evidence and sync
|
|
423
438
|
|
|
@@ -435,8 +450,11 @@ work reached this repo's trunk:
|
|
|
435
450
|
`sync` may use either result. `sync --all` uses each rewritten merge result to select and
|
|
436
451
|
reconcile its affected local paths; it does not apply one PR's evidence to unrelated work. It
|
|
437
452
|
continues with independent stacks when one is blocked. If no local copy remains, it uses that
|
|
438
|
-
evidence only for ordinary cleanup
|
|
439
|
-
|
|
453
|
+
evidence only for ordinary cleanup, or syncs the local stack still holding the open PRs of the
|
|
454
|
+
same GitHub stack, which cleans up the merged PR itself. A `sync` whose selected change has a
|
|
455
|
+
saved link but no visible commit after the fetch runs only cleanup for the merged PRs of that
|
|
456
|
+
change's GitHub stack. A native GitHub stack rebase without a merge requires `sync` for that
|
|
457
|
+
stack; `sync --all` discovers work from merge evidence.
|
|
440
458
|
|
|
441
459
|
When an unmerged local change sits below a submitted change whose submitted commit or merge result
|
|
442
460
|
is on trunk, `sync` stops without mutation. Rebasing would silently decide whether that local
|
|
@@ -469,9 +487,10 @@ It rebases surviving changes onto trunk even when they contain conflicts. If a s
|
|
|
469
487
|
change remains conflicted, the local rebase stays in place but its PR is not updated. The
|
|
470
488
|
user resolves the conflict with `jj` and runs `submit` for the remaining stack.
|
|
471
489
|
|
|
472
|
-
If
|
|
490
|
+
If another workspace has an obsolete merged change checked out, `sync` does not remove that
|
|
473
491
|
change. Its diagnostic identifies the workspace and gives commands to move it to trunk or forget
|
|
474
|
-
it and move its directory to the trash.
|
|
492
|
+
it and move its directory to the trash. The current workspace moves to a new empty change on
|
|
493
|
+
trunk before its merged change is removed. A workspace on a surviving child does not block its
|
|
475
494
|
ordinary rebase.
|
|
476
495
|
|
|
477
496
|
If another local path still depends on a merged change after the rebase, `sync` leaves the
|
|
@@ -488,13 +507,15 @@ merges. A matching full change ID on trunk identifies the successor rather than
|
|
|
488
507
|
an arbitrary visible side copy. When trunk has no matching change ID, `sync` removes the
|
|
489
508
|
old local change without relabeling that commit.
|
|
490
509
|
|
|
491
|
-
When GitHub merges part of a stack
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
510
|
+
When GitHub merges part of a stack, each remaining PR is either rewritten from its submitted
|
|
511
|
+
baseline or left at its submitted commit. `sync` uses the commits GitHub reports, rather than
|
|
512
|
+
replaying equivalent diffs, only if every remaining local change is still at its baseline and
|
|
513
|
+
GitHub rewrote every remaining PR. Otherwise it adopts none, rebases the remaining changes onto
|
|
514
|
+
trunk, records GitHub's reported heads as their baselines, and republishes them. It accepts those
|
|
515
|
+
heads and bases only while a merged PR in the same GitHub stack matches its saved record and its
|
|
516
|
+
merge result is on trunk. GitHub roots the rewritten PRs on trunk's tip at the time of the
|
|
517
|
+
rewrite, which may be past the merge result, so the rewritten chain's base must be on trunk at or
|
|
518
|
+
after that merge result rather than exactly at it.
|
|
498
519
|
|
|
499
520
|
#### Native GitHub stack rebase
|
|
500
521
|
|
|
@@ -551,8 +572,9 @@ they do not block the mutation because they are no longer active.
|
|
|
551
572
|
### Derived artifacts
|
|
552
573
|
|
|
553
574
|
A subsequent submit refreshes a PR description only if it still matches the last automated PR
|
|
554
|
-
description. Otherwise it is preserved; explicitly supplied text still takes effect.
|
|
555
|
-
|
|
575
|
+
description. Otherwise it is preserved; explicitly supplied text still takes effect. A saved
|
|
576
|
+
baseline this repo never held leaves nothing to compare, so the description follows the change.
|
|
577
|
+
See [pull request descriptions](../reference/descriptions.md).
|
|
556
578
|
|
|
557
579
|
When a submit supplies no stack overview, the existing overview text is preserved and moves to
|
|
558
580
|
the current head PR if the stack grows. An explicitly supplied overview replaces it. A lone PR has
|
|
@@ -674,7 +696,13 @@ changes that explicit submit boundaries placed in several native GitHub stacks.
|
|
|
674
696
|
not segment the path by GitHub resource or infer an omitted submit boundary.
|
|
675
697
|
|
|
676
698
|
Both report whether an open PR has a merge-queue entry; position and intermediate queue phases
|
|
677
|
-
are not
|
|
699
|
+
are not shown.
|
|
700
|
+
|
|
701
|
+
Both report specific merge warnings alongside reviews and checks, omitting GitHub's generic
|
|
702
|
+
`BLOCKED` label. Blocked PRs receive a batched lookup of applicable rules, review threads, and
|
|
703
|
+
checks; `view --verbose` includes other open PRs. Drafts, queued PRs, and changes with a reported
|
|
704
|
+
problem are excluded. Details are discarded if the PR head or base changes during the lookup.
|
|
705
|
+
GitHub computes merge state lazily, so an unknown state is not reported or polled.
|
|
678
706
|
|
|
679
707
|
Neither command guesses. A change with no saved PR identity is reported as not submitted,
|
|
680
708
|
even if a PR happens to use the branch name that change would generate. A saved PR is always
|
|
@@ -689,10 +717,10 @@ Empty, undescribed, conflicted, and merge changes produce warnings, but do not b
|
|
|
689
717
|
a report incomplete. A merge warning states that only the first-parent path is shown.
|
|
690
718
|
|
|
691
719
|
`view` and `list` share the rule for incomplete reports: an unmerged divergent change, ambiguous
|
|
692
|
-
PR, failed PR lookup, broken saved link, or unobserved saved PR state makes the report
|
|
693
|
-
A per-change lookup failure affects only its row; a failure before rows can be built
|
|
694
|
-
own error code. When several local changes claim one branch, `list` warns and skips
|
|
695
|
-
inspection for that branch. These incomplete reports exit 10.
|
|
720
|
+
PR, failed PR or detail lookup, broken saved link, or unobserved saved PR state makes the report
|
|
721
|
+
incomplete. A per-change lookup failure affects only its row; a failure before rows can be built
|
|
722
|
+
returns its own error code. When several local changes claim one branch, `list` warns and skips
|
|
723
|
+
live inspection for that branch. These incomplete reports exit 10.
|
|
696
724
|
|
|
697
725
|
`view` and `submit` render stack rows through the user's `jj log` formatting. `--json`
|
|
698
726
|
follows [`docs/json-output.schema.json`](../json-output.schema.json) and exposes no cache state,
|
|
@@ -727,6 +755,10 @@ and HTML body of the website's CLI reference page.
|
|
|
727
755
|
|
|
728
756
|
Running the executable without a subcommand is equivalent to `view` without arguments.
|
|
729
757
|
|
|
758
|
+
`--output=jsonl` is a renderer, not a second interface: it writes the same messages, activity
|
|
759
|
+
updates, and `--json` payloads as one JSON object per line on standard output, and command code
|
|
760
|
+
never branches on it.
|
|
761
|
+
|
|
730
762
|
### Exit codes
|
|
731
763
|
|
|
732
764
|
Exit codes are a public interface; their table lives in
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Generated integration testing
|
|
2
|
+
|
|
3
|
+
These constraints supplement the [testing philosophy](testing-philosophy.md):
|
|
4
|
+
|
|
5
|
+
- In `StackMachine`, keep server events and recovery as separate actions. A server merge must
|
|
6
|
+
leave room for local edits before sync; an interrupted submit must leave room for edits or
|
|
7
|
+
remote changes before retry. Combining these actions would hide the inconsistent states the
|
|
8
|
+
harness exists to test.
|
|
9
|
+
- An external stack merge may leave the survivors' rewrite pending, and `server_rewrite`
|
|
10
|
+
completes it later, rooted on trunk's tip at that time as GitHub does, optionally after
|
|
11
|
+
advancing trunk itself. Keep the merge and the rewrite separate actions so local work and
|
|
12
|
+
other server events can happen between them.
|
|
13
|
+
- `interrupt_sync` fails a sync after it has rewritten the local stack and updated the
|
|
14
|
+
surviving PRs but before it cleans up the merged ones, the state a crashed or interrupted sync
|
|
15
|
+
leaves behind. Recovery must come from a later `sync`, `sync --all`, or `cleanup`, so keep the
|
|
16
|
+
interruption separate from those actions.
|
|
17
|
+
- Shared-file edits use single-line replacements, and generated moves preserve the relative order
|
|
18
|
+
of changes that edit the same file. These restrictions let the harness predict conflicts without
|
|
19
|
+
implementing `jj`'s merge algorithm; broadening the edits requires revisiting that assumption.
|
|
20
|
+
- Each independent seeded search (shard) in the property tests has its own Hypothesis example
|
|
21
|
+
database. Sharing a database would spend parallel search time replaying and shrinking the same
|
|
22
|
+
saved failure.
|
|
23
|
+
- The generated search runs through `just property` and CI's smoke job; `just check` runs only
|
|
24
|
+
the fixed scenarios in `tests/property`. The runner ends by listing the rules the sequences
|
|
25
|
+
fired and the rules none reached. Treat an unreached rule as a search problem, not as missing
|
|
26
|
+
coverage: give it a richer starting state or fix its precondition.
|
|
27
|
+
- A rule is eligible only when it has work to do; compute its candidates in a helper that its
|
|
28
|
+
precondition shares. Hypothesis picks uniformly among eligible rules, so a rule that finds
|
|
29
|
+
nothing wastes a step and a model check.
|
|
30
|
+
- Server drift and injected faults are capped per sequence, and some sequences start after an
|
|
31
|
+
external merge of the bottom PR. Each disturbance pushes the state into a stop that later
|
|
32
|
+
commands only confirm, and every recovery rule needs a merged PR first; without both, a short
|
|
33
|
+
walk never reaches recovery.
|
|
34
|
+
- `check_contents` skips a change whose commit and expected contents it already verified. A new
|
|
35
|
+
content check that depends on anything else must extend that key.
|