jj-stack 0.1.1__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.1 → jj_stack-0.1.2}/.github/workflows/ci.yml +3 -3
- {jj_stack-0.1.1 → jj_stack-0.1.2}/.github/workflows/codeql.yml +2 -2
- {jj_stack-0.1.1 → jj_stack-0.1.2}/.github/workflows/release.yml +30 -4
- {jj_stack-0.1.1 → jj_stack-0.1.2}/AGENTS.md +13 -17
- {jj_stack-0.1.1 → jj_stack-0.1.2}/PKG-INFO +25 -8
- {jj_stack-0.1.1 → jj_stack-0.1.2}/README.md +22 -7
- {jj_stack-0.1.1 → jj_stack-0.1.2}/check.py +10 -2
- {jj_stack-0.1.1 → jj_stack-0.1.2}/docs/README.md +2 -1
- {jj_stack-0.1.1 → jj_stack-0.1.2}/docs/guides/submit-and-update.md +7 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/docs/guides/working-on-github.md +19 -16
- {jj_stack-0.1.1 → jj_stack-0.1.2}/docs/internals/code-reviews.md +2 -2
- {jj_stack-0.1.1 → jj_stack-0.1.2}/docs/internals/design.md +30 -10
- {jj_stack-0.1.1 → jj_stack-0.1.2}/docs/internals/implementation-strategy.md +9 -0
- {jj_stack-0.1.1 → 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.1 → jj_stack-0.1.2}/docs/json-output.schema.json +8 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/docs/quick-start.md +19 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/docs/reference/automation.md +3 -3
- jj_stack-0.1.2/docs/reference/bookmarks-and-selection.md +149 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/docs/reference/commands.md +3 -0
- {jj_stack-0.1.1 → 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.1 → jj_stack-0.1.2}/docs/reference/json-output.md +14 -7
- jj_stack-0.1.2/docs/tool-comparison.md +215 -0
- jj_stack-0.1.2/justfile +60 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/pyproject.toml +5 -3
- jj_stack-0.1.2/release-notes/v0.1.2.md +34 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/skills/jj-stack/SKILL.md +15 -4
- {jj_stack-0.1.1 → jj_stack-0.1.2}/skills/jj-stack/references/recovery.md +13 -9
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/cli.py +8 -4
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/commands/_cleanup_actions.py +18 -21
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/commands/_json_status.py +1 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/commands/checkout.py +25 -23
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/commands/cleanup/command.py +21 -15
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/commands/list_.py +59 -19
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/commands/merge/command.py +10 -3
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/commands/merge/github_stack.py +26 -7
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/commands/merge/models.py +2 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/commands/merge/preconditions.py +17 -22
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/commands/relink.py +47 -26
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/commands/submit/auto_close.py +3 -1
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/commands/submit/command.py +77 -23
- 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.1 → jj_stack-0.1.2}/src/jj_stack/commands/submit/descriptions.py +118 -25
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/commands/submit/github_stack.py +47 -4
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/commands/submit/inputs.py +49 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/commands/submit/models.py +5 -2
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/commands/submit/overview_comments.py +72 -39
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/commands/submit/prs.py +27 -39
- {jj_stack-0.1.1 → 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.1 → jj_stack-0.1.2}/src/jj_stack/commands/sync.py +13 -10
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/commands/sync_apply.py +16 -6
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/commands/unstack.py +6 -6
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/commands/view.py +72 -45
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/completion.py +1 -1
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/console.py +15 -2
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/formatting.py +47 -8
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/github/client.py +337 -133
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/github/resolution.py +0 -6
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/jj/client.py +23 -13
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/models/github.py +37 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/models/tracking.py +4 -19
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/stack/change_status.py +7 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/stack/convergence.py +16 -25
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/stack/convergence_observation.py +2 -10
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/stack/github_stack_safety.py +9 -3
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/stack/global_convergence.py +13 -18
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/stack/pr_branches.py +1 -4
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/stack/pr_facts.py +3 -6
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/stack/repo.py +4 -4
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/stack/selected.py +13 -3
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/stack/selection.py +27 -12
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/stack/status.py +14 -4
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/stack/trunk_evidence.py +11 -15
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/state/migrations.py +15 -1
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/ui.py +23 -1
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/integration/test_jj_stack.py +33 -3
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/integration/test_list_command.py +12 -2
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/integration/test_relink_command.py +19 -11
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/integration/test_submit_command.py +228 -10
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/integration/test_view_command.py +6 -3
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/support/fake_github.py +64 -11
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/support/integration_helpers.py +25 -9
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/support/tracking.py +0 -6
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/unit/test_check_script.py +13 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/unit/test_cleanup.py +8 -5
- {jj_stack-0.1.1 → 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.1 → jj_stack-0.1.2}/tests/unit/test_github_client.py +110 -37
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/unit/test_github_models.py +27 -5
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/unit/test_github_stack_planning.py +35 -3
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/unit/test_in_use_command.py +0 -3
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/unit/test_jj_client.py +9 -3
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/unit/test_pr_branches.py +0 -11
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/unit/test_relink.py +0 -1
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/unit/test_store.py +22 -16
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/unit/test_submit.py +35 -28
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/unit/test_submit_descriptions.py +19 -2
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/unit/test_trunk_evidence.py +4 -19
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/unit/test_ui.py +24 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/unit/test_view.py +54 -48
- {jj_stack-0.1.1 → jj_stack-0.1.2}/uv.lock +23 -21
- jj_stack-0.1.1/docs/gh-stack.md +0 -79
- jj_stack-0.1.1/docs/internals/releasing.md +0 -47
- jj_stack-0.1.1/docs/reference/descriptions.md +0 -59
- {jj_stack-0.1.1 → jj_stack-0.1.2}/.github/SECURITY.md +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/.github/dependabot.yml +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/.github/workflows/block-pr-base-merges.yml +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/.github/workflows/check-jj-release-updates.yml +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/.gitignore +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/CLAUDE.md +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/LICENSE +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/NOTICE +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/complexity-budget.toml +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/docs/AGENTS.md +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/docs/guides/close-or-separate.md +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/docs/guides/continue-a-stack.md +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/docs/guides/merge-and-sync.md +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/docs/guides/multiple-stacks.md +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/docs/guides/review-a-stack.md +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/docs/guides/revise.md +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/docs/internals/AGENTS.md +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/docs/internals/README.md +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/docs/internals/testing-philosophy.md +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/docs/mental-model.md +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/docs/troubleshooting.md +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/evals/jj-stack-skill.md +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/scripts/README.md +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/scripts/describe_with_claude.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/scripts/describe_with_codex.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/scripts/describe_with_editor.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/scripts/describe_with_prompt.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/skills/jj-stack/agents/openai.yaml +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/skills/jj-stack/references/multi-stack.md +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/__init__.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/__main__.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/bootstrap.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/cli_help.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/commands/__init__.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/commands/cleanup/shared.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/commands/cleanup/stale.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/commands/doctor.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/commands/in_use.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/commands/merge/__init__.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/commands/merge/plan.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/commands/merge/render.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/commands/submit/__init__.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/commands/submit/changes.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/concurrency.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/config.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/errors.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/github/__init__.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/github/auth.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/github/error_messages.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/github/overview_comments.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/github/pr_refs.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/github/stack_availability.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/identifiers.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/jj/__init__.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/jj/cli_args.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/jj/colors.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/models/__init__.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/models/git.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/models/stack.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/pr_branch_namespace.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/stack/__init__.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/stack/convergence_models.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/stack/path.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/state/__init__.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/state/operation_lock.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/src/jj_stack/state/store.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/__init__.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/conftest.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/integration/__init__.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/integration/conftest.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/integration/submit_command_helpers.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/integration/test_boundary_conditions.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/integration/test_checkout_command.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/integration/test_cleanup_command.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/integration/test_doctor_command.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/integration/test_merge_command.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/integration/test_sync_command.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/integration/test_unstack_command.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/property/test_submit_property_scenarios.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/run_live_github.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/run_submit_property_scenarios.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/support/__init__.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/support/change_helpers.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/support/contexts.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/support/json_schema.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/support/output_assertions.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/support/pytest_concurrency.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/support/stack_edit_scenarios.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/support/submit_property_harness.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/support/submit_property_scenarios.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/unit/__init__.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/unit/conftest.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/unit/test_bootstrap.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/unit/test_change_status.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/unit/test_change_status_topology.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/unit/test_checkout.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/unit/test_cli.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/unit/test_cli_dispatch.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/unit/test_concurrency.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/unit/test_config.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/unit/test_describe_with_editor_script.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/unit/test_describe_with_prompt_script.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/unit/test_errors.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/unit/test_github_auth.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/unit/test_github_resolution.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/unit/test_list.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/unit/test_live_github_runner.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/unit/test_merge.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/unit/test_operation_lock.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/unit/test_pr_refs.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/unit/test_property_runner.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/unit/test_property_scenarios.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/unit/test_selection.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/unit/test_stack_path.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/unit/test_stack_status.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/unit/test_sync.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/unit/test_unstack.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tests/unit/test_view_entrypoint.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tools/check_complexity.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tools/check_jj_release_updates.py +0 -0
- {jj_stack-0.1.1 → jj_stack-0.1.2}/tools/check_release_artifacts.py +0 -0
- {jj_stack-0.1.1 → 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
|
|
@@ -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@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
|
|
38
38
|
with:
|
|
39
39
|
python-version: "3.14"
|
|
40
40
|
|
|
@@ -50,6 +50,17 @@ jobs:
|
|
|
50
50
|
if: github.event_name == 'push' || inputs.release_tag != ''
|
|
51
51
|
run: git merge-base --is-ancestor HEAD refs/remotes/origin/main
|
|
52
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
|
+
|
|
53
64
|
- name: Install jj
|
|
54
65
|
run: echo "$(tools/install-jj-release.sh "$JJ_VERSION")" >> "$GITHUB_PATH"
|
|
55
66
|
|
|
@@ -83,7 +94,7 @@ jobs:
|
|
|
83
94
|
|
|
84
95
|
steps:
|
|
85
96
|
- name: Set up uv
|
|
86
|
-
uses: astral-sh/setup-uv@
|
|
97
|
+
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
|
|
87
98
|
with:
|
|
88
99
|
python-version: "3.14"
|
|
89
100
|
|
|
@@ -116,7 +127,7 @@ jobs:
|
|
|
116
127
|
|
|
117
128
|
steps:
|
|
118
129
|
- name: Set up uv
|
|
119
|
-
uses: astral-sh/setup-uv@
|
|
130
|
+
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
|
|
120
131
|
with:
|
|
121
132
|
python-version: "3.14"
|
|
122
133
|
|
|
@@ -141,6 +152,11 @@ jobs:
|
|
|
141
152
|
contents: write
|
|
142
153
|
|
|
143
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
|
+
|
|
144
160
|
- name: Download distributions
|
|
145
161
|
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
146
162
|
with:
|
|
@@ -152,12 +168,22 @@ jobs:
|
|
|
152
168
|
GH_TOKEN: ${{ github.token }}
|
|
153
169
|
RELEASE_TAG: ${{ inputs.release_tag || github.ref_name }}
|
|
154
170
|
run: |
|
|
171
|
+
release_notes="release-notes/$RELEASE_TAG.md"
|
|
155
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
|
|
156
182
|
for artifact in dist/*; do
|
|
157
183
|
gh release verify-asset "$RELEASE_TAG" "$artifact" \
|
|
158
184
|
--repo "$GITHUB_REPOSITORY"
|
|
159
185
|
done
|
|
160
186
|
else
|
|
161
187
|
gh release create "$RELEASE_TAG" dist/* --repo "$GITHUB_REPOSITORY" \
|
|
162
|
-
--verify-tag --
|
|
188
|
+
--verify-tag --notes-file "$release_notes" --title "$RELEASE_TAG"
|
|
163
189
|
fi
|
|
@@ -8,10 +8,9 @@
|
|
|
8
8
|
external mutation to the identity and version observed while planning when the platform
|
|
9
9
|
supports a conditional write or lease. Re-observe only when an earlier mutation invalidates a
|
|
10
10
|
precondition or when an observed trigger or platform contract requires it.
|
|
11
|
-
- Apply the cumulative complexity budgets after every code slice.
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
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.
|
|
15
14
|
- If the same subsystem needs a third consecutive hardening change, stop patching it and
|
|
16
15
|
re-derive the design from the core invariants.
|
|
17
16
|
|
|
@@ -20,8 +19,8 @@
|
|
|
20
19
|
- This is a `jj` repo. Do not use `git` to work on the repo itself.
|
|
21
20
|
- Do not use git worktree-based agent isolation in this repo. For isolated parallel work, use
|
|
22
21
|
`jj workspace` instead.
|
|
23
|
-
- Run the CLI locally with `
|
|
24
|
-
|
|
22
|
+
- Run the CLI locally with `just run ...` instead of invoking the module or virtualenv path
|
|
23
|
+
directly.
|
|
25
24
|
- Hard-wrap code and markdown files at 98 columns unless a file uses a different convention.
|
|
26
25
|
|
|
27
26
|
# Commit messages
|
|
@@ -33,7 +32,7 @@
|
|
|
33
32
|
- Hard-wrap commit message bodies at 72 columns.
|
|
34
33
|
- The body should explain the motivation for the change, the intended behavior or design outcome,
|
|
35
34
|
and any important scope or design constraints.
|
|
36
|
-
- 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`.
|
|
37
36
|
- Prefer explaining why the commit exists and what rule or user-visible behavior it is enforcing.
|
|
38
37
|
|
|
39
38
|
# Documentation
|
|
@@ -42,9 +41,10 @@
|
|
|
42
41
|
rules and the public/internal split. Built-in `--help` text is held to the same standard as
|
|
43
42
|
the user docs: assume jj/git familiarity, avoid `jj-stack` internal design jargon.
|
|
44
43
|
- The web version of the user docs normally lives in the sibling jj repository at
|
|
45
|
-
`$(jj root)/../website`. When user-facing docs change here,
|
|
46
|
-
|
|
47
|
-
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.
|
|
48
48
|
- Active internal docs use ordinary technical language too. Introduce a project-specific term
|
|
49
49
|
only when it names a real type, field, or enduring rule, define it at first use, and prefer
|
|
50
50
|
describing concrete inputs and effects.
|
|
@@ -71,13 +71,9 @@
|
|
|
71
71
|
|
|
72
72
|
# Testing
|
|
73
73
|
|
|
74
|
-
- Run
|
|
75
|
-
a test run.
|
|
76
|
-
- Run
|
|
77
|
-
code change.
|
|
78
|
-
- For focused test runs, do not use plain `uv run pytest ...`; it can miss the repo's package
|
|
79
|
-
path in this project layout. First run `uv sync --locked`, then invoke pytest through the repo
|
|
80
|
-
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`.
|
|
81
77
|
- Before adding, modifying, removing, or reviewing tests, fixtures, helpers, or property
|
|
82
78
|
scenarios, read and follow
|
|
83
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
|
|
@@ -61,16 +63,25 @@ python -m pip install jj-stack
|
|
|
61
63
|
To upgrade an installation made with `uv`, rerun its command with `--force`. If the command is
|
|
62
64
|
not on your shell `PATH`, run `uv tool update-shell`.
|
|
63
65
|
|
|
64
|
-
|
|
66
|
+
### Invoke it as `jj stack`
|
|
65
67
|
|
|
66
|
-
|
|
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"]
|
|
68
73
|
```
|
|
69
74
|
|
|
70
|
-
`
|
|
75
|
+
For tab completion of both `jj-stack` and `jj stack`, add the output of `jj-stack completion` to
|
|
76
|
+
your shell startup file:
|
|
71
77
|
|
|
72
|
-
|
|
73
|
-
|
|
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.
|
|
74
85
|
|
|
75
86
|
### Submit your first stack
|
|
76
87
|
|
|
@@ -137,7 +148,7 @@ merge queues, cleanup, and working with multiple stacks.
|
|
|
137
148
|
- [Configuration](https://www.serpentine.com/software/jj-stack/reference/configuration/)
|
|
138
149
|
- [Writing PR descriptions](https://www.serpentine.com/software/jj-stack/reference/descriptions/)
|
|
139
150
|
- [Troubleshooting](https://www.serpentine.com/software/jj-stack/troubleshooting/)
|
|
140
|
-
- [
|
|
151
|
+
- [Tool comparison](https://www.serpentine.com/software/jj-stack/tool-comparison/)
|
|
141
152
|
- [JSON output](https://www.serpentine.com/software/jj-stack/reference/json-output/)
|
|
142
153
|
- [Automation and exit codes](https://www.serpentine.com/software/jj-stack/reference/automation/)
|
|
143
154
|
|
|
@@ -149,6 +160,12 @@ jj-stack <command> --help
|
|
|
149
160
|
jj-stack help --all
|
|
150
161
|
```
|
|
151
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
|
+
|
|
152
169
|
## Coding agent integration
|
|
153
170
|
|
|
154
171
|
Install the bundled skill to teach coding agents to work with local `jj` stacks and refresh their
|
|
@@ -35,16 +35,25 @@ python -m pip install jj-stack
|
|
|
35
35
|
To upgrade an installation made with `uv`, rerun its command with `--force`. If the command is
|
|
36
36
|
not on your shell `PATH`, run `uv tool update-shell`.
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
### Invoke it as `jj stack`
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
|
|
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"]
|
|
42
45
|
```
|
|
43
46
|
|
|
44
|
-
`
|
|
47
|
+
For tab completion of both `jj-stack` and `jj stack`, add the output of `jj-stack completion` to
|
|
48
|
+
your shell startup file:
|
|
45
49
|
|
|
46
|
-
|
|
47
|
-
|
|
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.
|
|
48
57
|
|
|
49
58
|
### Submit your first stack
|
|
50
59
|
|
|
@@ -111,7 +120,7 @@ merge queues, cleanup, and working with multiple stacks.
|
|
|
111
120
|
- [Configuration](https://www.serpentine.com/software/jj-stack/reference/configuration/)
|
|
112
121
|
- [Writing PR descriptions](https://www.serpentine.com/software/jj-stack/reference/descriptions/)
|
|
113
122
|
- [Troubleshooting](https://www.serpentine.com/software/jj-stack/troubleshooting/)
|
|
114
|
-
- [
|
|
123
|
+
- [Tool comparison](https://www.serpentine.com/software/jj-stack/tool-comparison/)
|
|
115
124
|
- [JSON output](https://www.serpentine.com/software/jj-stack/reference/json-output/)
|
|
116
125
|
- [Automation and exit codes](https://www.serpentine.com/software/jj-stack/reference/automation/)
|
|
117
126
|
|
|
@@ -123,6 +132,12 @@ jj-stack <command> --help
|
|
|
123
132
|
jj-stack help --all
|
|
124
133
|
```
|
|
125
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
|
+
|
|
126
141
|
## Coding agent integration
|
|
127
142
|
|
|
128
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
|
)
|
|
@@ -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
|
|
|
@@ -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
|
|
@@ -25,28 +25,31 @@ edits and GitHub's rewritten contents disagree, `sync` stops instead of choosing
|
|
|
25
25
|
## What the next submit replaces
|
|
26
26
|
|
|
27
27
|
`jj-stack submit` makes GitHub's stack match your local stack. It pushes each change in your stack
|
|
28
|
-
to its PR branch, sets each pull request's base from the local parent order,
|
|
29
|
-
|
|
28
|
+
to its PR branch, sets each pull request's base from the local parent order, and updates native
|
|
29
|
+
stack membership.
|
|
30
|
+
|
|
31
|
+
By default, `submit` will generate a pull request description from the `jj` change. On a
|
|
32
|
+
subsequent submit, if the PR description still matches the last automated PR description,
|
|
33
|
+
`submit` will refresh it from the current change description. Otherwise, `submit` will leave it
|
|
34
|
+
untouched.
|
|
35
|
+
|
|
36
|
+
Use `--describe` to replace one body deliberately (or `--describe-with` or `--edit` for titles and
|
|
37
|
+
bodies).
|
|
38
|
+
|
|
30
39
|
`--draft` affects new pull requests. `--draft=all`, `--open`, and the choices made through
|
|
31
40
|
`--edit` can change existing draft states. Labels and reviewer requests that submit applies are
|
|
32
|
-
additive;
|
|
33
|
-
unrelated existing labels and reviewers are not removed.
|
|
34
|
-
|
|
35
|
-
Edits made directly to a pull request title or body are therefore temporary unless you copy them
|
|
36
|
-
back into the change description or pass them again on the next submit.
|
|
41
|
+
additive; unrelated existing labels and reviewers are not removed.
|
|
37
42
|
|
|
38
43
|
## Changes to avoid on GitHub
|
|
39
44
|
|
|
40
|
-
Do not force-push, rename, or delete `jj-stack/` PR branches.
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
unexpected branch move instead causes jj-stack to stop so it does not overwrite someone else's
|
|
44
|
-
work.
|
|
45
|
+
Do not force-push, rename, or delete `jj-stack/` PR branches. If a branch moves unexpectedly,
|
|
46
|
+
jj-stack stops instead of overwriting it. See [troubleshooting](../troubleshooting.md) for the
|
|
47
|
+
recovery steps.
|
|
45
48
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
49
|
+
Do not change pull request bases or GitHub stack membership by hand. `jj-stack submit` derives
|
|
50
|
+
both from the local `jj` history. To keep a different base or order, make that change locally and
|
|
51
|
+
submit again. To leave the pull requests open but remove their GitHub stack grouping, run
|
|
52
|
+
`jj-stack unstack --stack <number>`.
|
|
50
53
|
|
|
51
54
|
For reviewer and repo configuration guidance, see
|
|
52
55
|
[review and operate a stack](review-a-stack.md).
|
|
@@ -54,8 +54,8 @@ wrong PR or ref, guessed linkage, then inconsistencies in reconstructible metada
|
|
|
54
54
|
an elaborate recovery system to protect data that can be observed again.
|
|
55
55
|
|
|
56
56
|
The limits in `complexity-budget.toml` are design constraints. Review changes to the limits,
|
|
57
|
-
governed paths, and test markers as carefully as production code.
|
|
58
|
-
|
|
57
|
+
governed paths, and test markers as carefully as production code. Run `just complexity` locally
|
|
58
|
+
when the pinned `tokei` version is installed; CI invokes the underlying checker.
|
|
59
59
|
Moving the same logic into a helper or neighboring module is not a reduction in complexity.
|
|
60
60
|
|
|
61
61
|
## Review the user experience
|
|
@@ -262,8 +262,9 @@ Three sources answer questions about a tracked PR, each for a different domain:
|
|
|
262
262
|
|
|
263
263
|
1. The **`jj` DAG** determines which local changes exist, how they are related, and what they
|
|
264
264
|
contain.
|
|
265
|
-
2. **GitHub** reports PR existence, lifecycle, reviews, GitHub stack membership,
|
|
266
|
-
results. Whether work actually reached trunk is proven separately by ancestry from
|
|
265
|
+
2. **GitHub** reports PR existence, lifecycle, reviews, check rollups, GitHub stack membership,
|
|
266
|
+
and merge results. Whether work actually reached trunk is proven separately by ancestry from
|
|
267
|
+
it.
|
|
267
268
|
3. **Local tracking** records only the PR identity and submitted baseline of each change. It
|
|
268
269
|
prevents mutation of the wrong PR but cannot make a mutation safe on its own.
|
|
269
270
|
|
|
@@ -305,15 +306,16 @@ These facts are re-derived and never need tool-owned durable state:
|
|
|
305
306
|
|
|
306
307
|
Tracking stores one pair, keyed by full `change_id`:
|
|
307
308
|
|
|
308
|
-
- `PRIdentity`:
|
|
309
|
+
- `PRIdentity`: the PR number and its one canonical head ref
|
|
309
310
|
- `SubmittedBaseline`: the exact `commit_id` last successfully submitted for that identity
|
|
310
311
|
|
|
311
312
|
Both records are created, replaced, and removed together. Partial pairs are invalid.
|
|
313
|
+
The configured GitHub repo is command context, not per-change tracking; `jj-stack` does not carry
|
|
314
|
+
tracking across repos.
|
|
312
315
|
|
|
313
316
|
Two named checks recur throughout the policies:
|
|
314
317
|
|
|
315
|
-
- **identity match**: the live PR's
|
|
316
|
-
`PRIdentity`
|
|
318
|
+
- **identity match**: the live PR's number and head ref equal the saved `PRIdentity`
|
|
317
319
|
- **snapshot match**: an identity match whose live PR head SHA also equals
|
|
318
320
|
`SubmittedBaseline.commit_id`
|
|
319
321
|
|
|
@@ -677,6 +679,10 @@ deletes a branch needed by an active GitHub stack member.
|
|
|
677
679
|
GitHub stacks whose active members are all selected. It may also dissolve one partially selected
|
|
678
680
|
GitHub stack when the selection is a maximal local path and touches no other GitHub stack. A
|
|
679
681
|
non-maximal selection could silently truncate a still-valid stack, so it stops before mutation.
|
|
682
|
+
An unselected active member does not trigger that guard when its observed PR number, branch, and
|
|
683
|
+
head still match the saved PR number, branch, and submitted baseline, and its tracked change has
|
|
684
|
+
no visible off-trunk copy. That change cannot be on an extension of the selected path. Rebuilding
|
|
685
|
+
the grouping leaves the orphaned pull request open and retains its tracking.
|
|
680
686
|
Likewise, a selection that partly overlaps one GitHub stack while including any previously
|
|
681
687
|
submitted PR outside that resource stops; the user submits the source path first, then the
|
|
682
688
|
destination path.
|
|
@@ -696,15 +702,26 @@ they do not block the mutation because they are no longer active.
|
|
|
696
702
|
|
|
697
703
|
### Derived artifacts
|
|
698
704
|
|
|
699
|
-
|
|
700
|
-
|
|
705
|
+
A subsequent submit refreshes a PR description only if it still matches the last automated PR
|
|
706
|
+
description. Otherwise it is preserved; explicitly supplied text still takes effect. PR text is
|
|
707
|
+
not stored locally and never determines topology; see
|
|
708
|
+
[pull request descriptions](../reference/descriptions.md).
|
|
709
|
+
|
|
710
|
+
When a submit supplies no stack overview, the existing overview text is preserved and moves to
|
|
711
|
+
the current head PR if the stack grows. An explicitly supplied overview replaces it. A lone PR has
|
|
712
|
+
no overview comment. New PRs are created in the requested draft state.
|
|
713
|
+
|
|
714
|
+
Submit maintains a per-PR revision-history comment with the most recent versions available from
|
|
715
|
+
GitHub's force-push timeline. The comment is presentation-only and remains after merge and
|
|
716
|
+
cleanup. This makes it easier for a reader to understand how a PR has evolved.
|
|
701
717
|
|
|
702
|
-
The managed overview comment is the first comment whose body contains its marker; its ID is never
|
|
703
|
-
stored. A lone PR has no overview comment. New PRs are created in the requested draft state.
|
|
704
718
|
Existing PRs become draft only with `--draft=all` and become ready only with `--open`; plain
|
|
705
719
|
`submit --draft` never unpublishes an existing PR. With `--edit`, GitHub's current state and those
|
|
706
720
|
command-wide defaults populate one editable draft choice per change. The validated document then
|
|
707
|
-
determines each selected PR's draft state without adding local state.
|
|
721
|
+
determines each selected PR's draft state without adding local state. A newly generated editor
|
|
722
|
+
file remains until the entire submit succeeds. If the command stops, the user can pass that file
|
|
723
|
+
back to `--edit`; the retry re-observes the local stack and GitHub, and accepts the file only when
|
|
724
|
+
it names exactly the currently selected changes. The file carries no submit plan or phase.
|
|
708
725
|
|
|
709
726
|
`--reviewers` and `--team-reviewers` request the named reviewers even when a PR is otherwise
|
|
710
727
|
unchanged and never remove omitted reviewers. `--re-request` acts on an otherwise unchanged PR,
|
|
@@ -713,6 +730,9 @@ adds requests and never cancels a pending one. An explicit `--label` request app
|
|
|
713
730
|
PR is otherwise unchanged; configured labels alone do not turn a no-op submit into a metadata
|
|
714
731
|
update. Labels are also additive; omitted labels are never removed.
|
|
715
732
|
|
|
733
|
+
Default PR bodies derived from change descriptions unfold Markdown soft line breaks into spaces.
|
|
734
|
+
Markdown block boundaries, code, tables, and explicit hard line breaks remain unchanged.
|
|
735
|
+
|
|
716
736
|
### Unstack and cleanup
|
|
717
737
|
|
|
718
738
|
`unstack` removes one exact GitHub stack grouping and leaves every pull request, PR branch,
|
|
@@ -89,6 +89,15 @@ it does not add site navigation or styling. The website invokes that renderer fr
|
|
|
89
89
|
jj-stack checkout whose canonical user guides it snapshots, then owns the generated page's front
|
|
90
90
|
matter, CSS, and publication.
|
|
91
91
|
|
|
92
|
+
## Development workflows
|
|
93
|
+
|
|
94
|
+
The root `justfile` is the contributor entry point for setup, local CLI execution, formatting,
|
|
95
|
+
focused tests, standard checks, complexity checks, generated scenarios, live GitHub qualification,
|
|
96
|
+
website documentation synchronization, and release artifacts. Recipes delegate substantive
|
|
97
|
+
behavior to existing scripts, including the website-owned documentation sync and the check scripts
|
|
98
|
+
shared with CI; they do not reimplement them. The README points contributors to `just` instead of
|
|
99
|
+
duplicating the underlying commands.
|
|
100
|
+
|
|
92
101
|
## Test boundaries
|
|
93
102
|
|
|
94
103
|
The local integration environment uses real `jj` and Git repos with a purpose-built
|
|
@@ -39,10 +39,10 @@ hash-order dependence. Every pytest worker must collect the same cases. If gener
|
|
|
39
39
|
the requested number of unique cases within its attempt limit, it returns the cases found instead
|
|
40
40
|
of looping indefinitely.
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
`just check` runs a small fixed set. Larger deterministic pools are opt-in:
|
|
43
43
|
|
|
44
44
|
```console
|
|
45
|
-
$
|
|
45
|
+
$ just property 500
|
|
46
46
|
```
|
|
47
47
|
|
|
48
48
|
The runner prints a complete reproduction command with the resolved seed, family counts, worker
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Release process
|
|
2
|
+
|
|
3
|
+
A release is built from a `v<version>`-tagged commit on `main`. The tag workflow builds and tests
|
|
4
|
+
both distributions, publishes them to PyPI, and creates the matching GitHub Release. A manual
|
|
5
|
+
workflow run publishes to TestPyPI unless it names an existing release tag to retry.
|
|
6
|
+
|
|
7
|
+
## Write the release notes
|
|
8
|
+
|
|
9
|
+
Create `release-notes/v<version>.md`, using the same version as `pyproject.toml`. This file is the
|
|
10
|
+
source for the GitHub Release body and must be part of the tagged commit. The production workflow
|
|
11
|
+
fails before publishing if the file is absent or empty. On a retry, it also fails if an existing
|
|
12
|
+
GitHub Release does not contain exactly the notes from the tagged commit.
|
|
13
|
+
|
|
14
|
+
Write for someone deciding whether to upgrade, not for someone reconstructing the commit history:
|
|
15
|
+
|
|
16
|
+
- Open with a short summary of the release's user-visible value.
|
|
17
|
+
- Group changes by user impact. Use headings such as `Breaking changes`, `Highlights`, `Fixes`,
|
|
18
|
+
and `Documentation`, but omit empty sections.
|
|
19
|
+
- Put breaking changes first. State who is affected, what happens after upgrading, and the exact
|
|
20
|
+
migration or workaround.
|
|
21
|
+
- Make each bullet describe one observable outcome in plain language. Include commands, version
|
|
22
|
+
requirements, and links to the relevant guide when they help the reader act.
|
|
23
|
+
- Explain important fixes in terms of the symptom that is gone. Do not paste commit subjects,
|
|
24
|
+
internal type names, or an automatically generated pull request list.
|
|
25
|
+
- End with a comparison link from the previous tag to the new tag, labeled `Full changelog`.
|
|
26
|
+
|
|
27
|
+
Keep the notes self-contained even when they link to a pull request or issue. Proofread the
|
|
28
|
+
rendered Markdown and check every command and link before tagging. A release with no breaking
|
|
29
|
+
changes does not need a `Breaking changes` heading.
|
|
30
|
+
|
|
31
|
+
## Qualify the candidate
|
|
32
|
+
|
|
33
|
+
Set the intended version in `pyproject.toml`, finish the release changes and release notes, and
|
|
34
|
+
run the release gates:
|
|
35
|
+
|
|
36
|
+
```console
|
|
37
|
+
just release-check
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
The live test requires a `gh` login that can create and delete a private repo, push to it, and
|
|
41
|
+
manage its pull requests.
|
|
42
|
+
|
|
43
|
+
Check the website snapshot and production build:
|
|
44
|
+
|
|
45
|
+
```console
|
|
46
|
+
just website-check
|
|
47
|
+
cd ../website
|
|
48
|
+
just check
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
If the snapshot is out of date, run `just website` from the jj-stack checkout, review and commit
|
|
52
|
+
the website change, then rerun the checks. Push the release changes to `main` before creating the
|
|
53
|
+
tag. A manual run of the release workflow is the optional TestPyPI smoke test.
|
|
54
|
+
|
|
55
|
+
## Publish the tag
|
|
56
|
+
|
|
57
|
+
Create the version tag and push it explicitly:
|
|
58
|
+
|
|
59
|
+
```console
|
|
60
|
+
jj tag set v0.1.0 -r main
|
|
61
|
+
jj git push --tag v0.1.0
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Use the version from `pyproject.toml` in place of `0.1.0`. After the workflow succeeds, verify the
|
|
65
|
+
GitHub Release contains the authored notes and downloadable distributions. PyPI has no separate
|
|
66
|
+
per-version release-notes field; its project page exposes the GitHub Releases page through the
|
|
67
|
+
standard `Changelog` project link. Verify that link along with the package page, publish the
|
|
68
|
+
already-checked website with `just publish`, and verify the live quick start and install command.
|
|
69
|
+
|
|
70
|
+
Never move or reuse a published version tag. A failed workflow can be rerun against the same tag;
|
|
71
|
+
a source change requires a new version and tag.
|