jj-stack 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. jj_stack/__init__.py +11 -0
  2. jj_stack/__main__.py +8 -0
  3. jj_stack/bootstrap.py +213 -0
  4. jj_stack/cli.py +1297 -0
  5. jj_stack/cli_help.py +680 -0
  6. jj_stack/commands/__init__.py +1 -0
  7. jj_stack/commands/_cleanup_actions.py +389 -0
  8. jj_stack/commands/_json_status.py +84 -0
  9. jj_stack/commands/checkout.py +668 -0
  10. jj_stack/commands/cleanup/command.py +702 -0
  11. jj_stack/commands/cleanup/shared.py +62 -0
  12. jj_stack/commands/cleanup/stale.py +79 -0
  13. jj_stack/commands/doctor.py +358 -0
  14. jj_stack/commands/in_use.py +31 -0
  15. jj_stack/commands/list_.py +667 -0
  16. jj_stack/commands/merge/__init__.py +1 -0
  17. jj_stack/commands/merge/command.py +385 -0
  18. jj_stack/commands/merge/github_stack.py +333 -0
  19. jj_stack/commands/merge/models.py +97 -0
  20. jj_stack/commands/merge/plan.py +109 -0
  21. jj_stack/commands/merge/preconditions.py +162 -0
  22. jj_stack/commands/merge/render.py +52 -0
  23. jj_stack/commands/relink.py +210 -0
  24. jj_stack/commands/submit/__init__.py +1 -0
  25. jj_stack/commands/submit/auto_close.py +108 -0
  26. jj_stack/commands/submit/changes.py +90 -0
  27. jj_stack/commands/submit/command.py +780 -0
  28. jj_stack/commands/submit/descriptions.py +570 -0
  29. jj_stack/commands/submit/github_stack.py +139 -0
  30. jj_stack/commands/submit/inputs.py +168 -0
  31. jj_stack/commands/submit/models.py +198 -0
  32. jj_stack/commands/submit/overview_comments.py +178 -0
  33. jj_stack/commands/submit/prs.py +461 -0
  34. jj_stack/commands/submit/render.py +129 -0
  35. jj_stack/commands/sync.py +510 -0
  36. jj_stack/commands/sync_apply.py +474 -0
  37. jj_stack/commands/unstack.py +321 -0
  38. jj_stack/commands/view.py +1151 -0
  39. jj_stack/completion.py +484 -0
  40. jj_stack/concurrency.py +93 -0
  41. jj_stack/config.py +170 -0
  42. jj_stack/console.py +708 -0
  43. jj_stack/errors.py +152 -0
  44. jj_stack/formatting.py +95 -0
  45. jj_stack/github/__init__.py +1 -0
  46. jj_stack/github/auth.py +34 -0
  47. jj_stack/github/client.py +1098 -0
  48. jj_stack/github/error_messages.py +89 -0
  49. jj_stack/github/overview_comments.py +35 -0
  50. jj_stack/github/pr_refs.py +70 -0
  51. jj_stack/github/resolution.py +208 -0
  52. jj_stack/github/stack_availability.py +30 -0
  53. jj_stack/identifiers.py +7 -0
  54. jj_stack/jj/__init__.py +1 -0
  55. jj_stack/jj/cli_args.py +23 -0
  56. jj_stack/jj/client.py +1459 -0
  57. jj_stack/jj/colors.py +199 -0
  58. jj_stack/models/__init__.py +1 -0
  59. jj_stack/models/git.py +15 -0
  60. jj_stack/models/github.py +243 -0
  61. jj_stack/models/stack.py +70 -0
  62. jj_stack/models/tracking.py +115 -0
  63. jj_stack/pr_branch_namespace.py +78 -0
  64. jj_stack/stack/__init__.py +1 -0
  65. jj_stack/stack/change_status.py +216 -0
  66. jj_stack/stack/convergence.py +501 -0
  67. jj_stack/stack/convergence_models.py +69 -0
  68. jj_stack/stack/convergence_observation.py +162 -0
  69. jj_stack/stack/github_stack_safety.py +132 -0
  70. jj_stack/stack/global_convergence.py +270 -0
  71. jj_stack/stack/path.py +235 -0
  72. jj_stack/stack/pr_branches.py +126 -0
  73. jj_stack/stack/pr_facts.py +165 -0
  74. jj_stack/stack/repo.py +95 -0
  75. jj_stack/stack/selected.py +358 -0
  76. jj_stack/stack/selection.py +124 -0
  77. jj_stack/stack/status.py +711 -0
  78. jj_stack/stack/trunk_evidence.py +174 -0
  79. jj_stack/state/__init__.py +1 -0
  80. jj_stack/state/operation_lock.py +220 -0
  81. jj_stack/state/store.py +260 -0
  82. jj_stack/ui.py +230 -0
  83. jj_stack-0.1.0.dist-info/METADATA +170 -0
  84. jj_stack-0.1.0.dist-info/RECORD +88 -0
  85. jj_stack-0.1.0.dist-info/WHEEL +4 -0
  86. jj_stack-0.1.0.dist-info/entry_points.txt +2 -0
  87. jj_stack-0.1.0.dist-info/licenses/LICENSE +201 -0
  88. jj_stack-0.1.0.dist-info/licenses/NOTICE +2 -0
jj_stack/ui.py ADDED
@@ -0,0 +1,230 @@
1
+ """Semantic message fragments shared across layers."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Callable, Iterable
6
+ from dataclasses import dataclass
7
+ from string.templatelib import Interpolation, Template, convert
8
+ from typing import Literal
9
+
10
+
11
+ @dataclass(frozen=True, slots=True)
12
+ class SemanticText:
13
+ """A short semantic text fragment that should preserve its semantic labels."""
14
+
15
+ text: str
16
+ labels: tuple[str, ...]
17
+
18
+ def __str__(self) -> str:
19
+ return self.text
20
+
21
+
22
+ StatusValue = Literal["ok", "warn", "fail", "fixed", "skip"]
23
+ type Message = str | Template | SemanticText | tuple[Message, ...]
24
+
25
+
26
+ @dataclass(frozen=True, slots=True)
27
+ class StatusBadge:
28
+ """A semantic status indicator rendered by the console layer."""
29
+
30
+ value: StatusValue
31
+
32
+
33
+ @dataclass(frozen=True, slots=True)
34
+ class PrefixedLine:
35
+ """A hanging-indent line with semantic prefix and body content."""
36
+
37
+ prefix: Message
38
+ body: Message | StatusBadge
39
+ message_labels: tuple[str, ...] | None = None
40
+ prefix_labels: tuple[str, ...] | None = None
41
+
42
+
43
+ type TableCell = Message | StatusBadge | PrefixedLine
44
+
45
+
46
+ @dataclass(frozen=True, slots=True)
47
+ class TableColumn:
48
+ """A presentation-layer table column description."""
49
+
50
+ header: str
51
+ no_wrap: bool = False
52
+ width: int | None = None
53
+
54
+
55
+ @dataclass(frozen=True, slots=True)
56
+ class DataTable:
57
+ """A lightweight table model rendered by the console layer."""
58
+
59
+ columns: tuple[TableColumn, ...]
60
+ rows: tuple[tuple[TableCell, ...], ...]
61
+ box: str = "simple"
62
+ expand: bool = False
63
+ header_style: str | None = "bold"
64
+ pad_edge: bool = False
65
+ padding: int | tuple[int, int] | tuple[int, int, int, int] = (0, 0)
66
+ show_edge: bool = False
67
+ show_header: bool = True
68
+
69
+
70
+ type Renderable = TableCell | DataTable
71
+
72
+
73
+ def semantic_text(text: str, *labels: str) -> SemanticText:
74
+ """Wrap text with semantic labels for later rendering."""
75
+
76
+ return SemanticText(text=text, labels=labels)
77
+
78
+
79
+ def bookmark(name: str) -> SemanticText:
80
+ """Wrap bookmark-like names, including Git remotes, for semantic rendering."""
81
+
82
+ label = "remote_bookmarks" if "@" in name else "local_bookmarks"
83
+ return semantic_text(name, label)
84
+
85
+
86
+ def change_id(name: str) -> SemanticText:
87
+ """Wrap a change ID for semantic rendering, shortening it for display."""
88
+
89
+ return semantic_text(name[:8], "change_id")
90
+
91
+
92
+ def commit_id(name: str) -> SemanticText:
93
+ """Wrap a commit ID for semantic rendering, shortening it for display."""
94
+
95
+ return semantic_text(name[:8], "commit_id")
96
+
97
+
98
+ def revset(text: str) -> SemanticText:
99
+ """Wrap jj revset syntax for semantic rendering."""
100
+
101
+ return semantic_text(text, "revset")
102
+
103
+
104
+ def metavar(text: str) -> SemanticText:
105
+ """Wrap a command-line metavariable."""
106
+
107
+ return semantic_text(text, "metavar")
108
+
109
+
110
+ def code(text: str) -> SemanticText:
111
+ """Wrap a code-like token for semantic rendering."""
112
+
113
+ return semantic_text(text, "code")
114
+
115
+
116
+ def cmd(text: str) -> SemanticText:
117
+ """Wrap a command-line snippet for semantic rendering.
118
+
119
+ This can be used for commands, options, or arguments.
120
+ """
121
+
122
+ return semantic_text(text, "command", "hint")
123
+
124
+
125
+ def option(text: str) -> SemanticText:
126
+ """Wrap one command-line option."""
127
+
128
+ return semantic_text(text, "option", "command", "hint")
129
+
130
+
131
+ def status(value: StatusValue) -> StatusBadge:
132
+ """Wrap a status indicator for semantic rendering."""
133
+
134
+ return StatusBadge(value=value)
135
+
136
+
137
+ def join[T](
138
+ render_item: Callable[[T], Message],
139
+ items: Iterable[T],
140
+ ) -> tuple[Message, ...]:
141
+ """Render and comma-join items."""
142
+
143
+ parts: list[Message] = []
144
+ for index, item in enumerate(items):
145
+ if index:
146
+ parts.append(", ")
147
+ parts.append(render_item(item))
148
+ return tuple(parts)
149
+
150
+
151
+ def prefixed_line(
152
+ prefix: Message,
153
+ body: Message | StatusBadge,
154
+ *,
155
+ message_labels: tuple[str, ...] | None = None,
156
+ prefix_labels: tuple[str, ...] | None = None,
157
+ ) -> PrefixedLine:
158
+ """Build a hanging-indent line without choosing a concrete renderer."""
159
+
160
+ return PrefixedLine(
161
+ prefix=prefix,
162
+ body=body,
163
+ message_labels=message_labels,
164
+ prefix_labels=prefix_labels,
165
+ )
166
+
167
+
168
+ def plain_text(content: Message) -> str:
169
+ """Render semantic template content into plain text."""
170
+
171
+ parts: list[str] = []
172
+ _append_plain_text(parts, content)
173
+ return "".join(parts)
174
+
175
+
176
+ def _append_plain_text(parts: list[str], content: Message) -> None:
177
+ if isinstance(content, tuple):
178
+ for item in content:
179
+ _append_plain_text(parts, item)
180
+ return
181
+ if isinstance(content, Template):
182
+ for part in content:
183
+ if isinstance(part, str):
184
+ parts.append(part)
185
+ else:
186
+ _append_plain_text(parts, resolve_interpolation(part))
187
+ return
188
+ if isinstance(content, SemanticText):
189
+ parts.append(content.text)
190
+ return
191
+ parts.append(str(content))
192
+
193
+
194
+ def resolve_interpolation(interpolation: Interpolation) -> Message:
195
+ value = interpolation.value
196
+ if isinstance(value, SemanticText):
197
+ if interpolation.conversion is not None:
198
+ converted = convert(value.text, interpolation.conversion)
199
+ return (
200
+ format(converted, interpolation.format_spec)
201
+ if interpolation.format_spec
202
+ else converted
203
+ )
204
+ if interpolation.format_spec:
205
+ return SemanticText(
206
+ text=format(value.text, interpolation.format_spec),
207
+ labels=value.labels,
208
+ )
209
+ return value
210
+ if isinstance(value, Template):
211
+ if interpolation.conversion is not None or interpolation.format_spec:
212
+ plain = plain_text(value)
213
+ converted = convert(plain, interpolation.conversion)
214
+ if interpolation.format_spec:
215
+ return format(converted, interpolation.format_spec)
216
+ return converted
217
+ return value
218
+ if isinstance(value, tuple):
219
+ if interpolation.conversion is not None or interpolation.format_spec:
220
+ plain = plain_text(value)
221
+ converted = convert(plain, interpolation.conversion)
222
+ if interpolation.format_spec:
223
+ return format(converted, interpolation.format_spec)
224
+ return converted
225
+ return value
226
+
227
+ converted = convert(value, interpolation.conversion)
228
+ if interpolation.format_spec:
229
+ return format(converted, interpolation.format_spec)
230
+ return str(converted)
@@ -0,0 +1,170 @@
1
+ Metadata-Version: 2.5
2
+ Name: jj-stack
3
+ Version: 0.1.0
4
+ Summary: Stacked GitHub pull requests for Jujutsu
5
+ Project-URL: Homepage, https://www.serpentine.com/software/jj-stack/
6
+ Project-URL: Documentation, https://www.serpentine.com/software/jj-stack/
7
+ Project-URL: Repository, https://github.com/bos/jj-stack
8
+ Project-URL: Issues, https://github.com/bos/jj-stack/issues
9
+ License-Expression: Apache-2.0
10
+ License-File: LICENSE
11
+ License-File: NOTICE
12
+ Keywords: github,jj,jujutsu,pull-requests,stacked-pull-requests
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Environment :: Console
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: License :: OSI Approved :: Apache Software License
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.14
19
+ Classifier: Topic :: Software Development :: Version Control
20
+ Classifier: Topic :: Software Development :: Version Control :: Git
21
+ Requires-Python: >=3.14
22
+ Requires-Dist: httpxyz<0.32,>=0.31.0
23
+ Requires-Dist: pydantic<3,>=2.13.3
24
+ Requires-Dist: rich<16,>=15.0.0
25
+ Description-Content-Type: text/markdown
26
+
27
+ # jj-stack: manage stacked GitHub PRs with jj
28
+
29
+ `jj-stack` turns a linear series of local `jj` changes into a stack of GitHub pull requests.
30
+ Rewrite, split, squash, or reorder the changes with `jj`, then let `jj-stack` update the
31
+ matching PRs.
32
+
33
+ ## Quick start
34
+
35
+ ### Requirements
36
+
37
+ - Python 3.14 or newer
38
+ - `uv`
39
+ - `jj` 0.44.0 or newer
40
+ - GitHub authentication
41
+
42
+ ### Install
43
+
44
+ Install `jj-stack` from PyPI:
45
+
46
+ ```bash
47
+ uv tool install jj-stack
48
+ ```
49
+
50
+ To upgrade, rerun that command with `--force`. If the command is not on your shell `PATH`, run
51
+ `uv tool update-shell`.
52
+
53
+ For tab completion, add the output of `jj-stack completion` to your shell startup file:
54
+
55
+ ```bash
56
+ eval "$(jj-stack completion zsh)"
57
+ ```
58
+
59
+ `bash` and `fish` work the same way.
60
+
61
+ To invoke it as `jj stack` and complete that alias too, see
62
+ [Configuration](https://www.serpentine.com/software/jj-stack/reference/configuration/).
63
+
64
+ ### Submit your first stack
65
+
66
+ Start with a linear series of local `jj` changes on top of `trunk()`. In a new repo, check
67
+ the setup and apply the safe local fixes:
68
+
69
+ ```bash
70
+ jj-stack doctor --fix
71
+ ```
72
+
73
+ Inspect the stack that ends at your working copy:
74
+
75
+ ```bash
76
+ jj-stack
77
+ ```
78
+
79
+ Create one GitHub PR per local change:
80
+
81
+ ```bash
82
+ jj-stack submit
83
+ ```
84
+
85
+ Revise the changes locally with `jj` and rerun `jj-stack submit` whenever the stack is ready to
86
+ refresh. Use `jj-stack list` to see every tracked stack in the repo.
87
+
88
+ ## Mental model
89
+
90
+ The local `jj` DAG determines which changes form a stack and their order. On GitHub, each change
91
+ gets a stable PR branch and a PR; every PR targets the PR branch below it, except the
92
+ bottom PR, which targets trunk by default:
93
+
94
+ ```text
95
+ jj-stack/add-ui-... -> PR #3 (base: jj-stack/add-api-...)
96
+ jj-stack/add-api-... -> PR #2 (base: jj-stack/refactor-model-...)
97
+ jj-stack/refactor-model-... -> PR #1 (base: main)
98
+ main -> trunk
99
+ ```
100
+
101
+ The PR branches normally stay out of your local bookmark view. When you rewrite a change,
102
+ `jj-stack` updates that change's existing PR branch and PR, along with the PR branches and PRs for
103
+ dependent changes.
104
+
105
+ ## Everyday workflow
106
+
107
+ 1. Write code as a series of local `jj` changes.
108
+ 2. Run `jj-stack submit`.
109
+ 3. Revise, add, remove, or reorder the changes locally as reviews come in.
110
+ 4. Run `jj-stack submit` again to refresh GitHub.
111
+ 5. Run `jj-stack merge` when the changes at the bottom are ready.
112
+ 6. After a queued or externally initiated merge finishes, run
113
+ `jj-stack sync <head-change-id>`.
114
+
115
+ `view`, `submit`, `merge`, and `sync` accept a change ID when you need to select a stack other
116
+ than the one ending at the working copy.
117
+
118
+ See the [user guide](https://www.serpentine.com/software/jj-stack/) for drafts, descriptions,
119
+ merge queues, cleanup, and working with multiple stacks.
120
+
121
+ ## Learn more
122
+
123
+ - [Mental model](https://www.serpentine.com/software/jj-stack/mental-model/)
124
+ - [Quick start](https://www.serpentine.com/software/jj-stack/quick-start/)
125
+ - [Everyday workflows](https://www.serpentine.com/software/jj-stack/guides/submit-and-update/)
126
+ - [Configuration](https://www.serpentine.com/software/jj-stack/reference/configuration/)
127
+ - [Writing PR descriptions](https://www.serpentine.com/software/jj-stack/reference/descriptions/)
128
+ - [Troubleshooting](https://www.serpentine.com/software/jj-stack/troubleshooting/)
129
+ - [`jj-stack` and `gh stack`](https://www.serpentine.com/software/jj-stack/gh-stack/)
130
+ - [JSON output](https://www.serpentine.com/software/jj-stack/reference/json-output/)
131
+ - [Automation and exit codes](https://www.serpentine.com/software/jj-stack/reference/automation/)
132
+
133
+ The built-in help is the canonical flag reference:
134
+
135
+ ```bash
136
+ jj-stack --help
137
+ jj-stack <command> --help
138
+ jj-stack help --all
139
+ ```
140
+
141
+ ## Coding agent integration
142
+
143
+ Install the bundled skill to teach coding agents to work with local `jj` stacks and refresh their
144
+ GitHub PRs safely:
145
+
146
+ ```bash
147
+ gh skill install bos/jj-stack jj-stack
148
+ ```
149
+
150
+ See the [skill source](https://github.com/bos/jj-stack/blob/main/skills/jj-stack/SKILL.md). In
151
+ my evaluations with Codex and Claude Code, agents with the `jj-stack` skill succeeded in 11/12
152
+ scenarios versus 6/12 without it, with one critical error versus four, using 60% fewer failed
153
+ command attempts and 18% fewer tool calls. (The critical error was due to Claude Haiku
154
+ understanding a rule and ignoring it. I haven't figured out how to get smaller Claude models to
155
+ behave better, and I don't personally use them.)
156
+
157
+ ## Performance
158
+
159
+ Although `jj-stack` is written in Python, this does not significantly affect its speed.
160
+ The real determinants of its performance are the GitHub API and the `jj` command.
161
+
162
+ The GitHub API is *slow*; a single roundtrip takes many hundreds of milliseconds. `jj-stack`
163
+ reduces its impact with:
164
+
165
+ - GraphQL batch requests where possible
166
+ - concurrent use of the GitHub REST API
167
+ - periodic audits that its queries are minimal in extent
168
+
169
+ In pursuit of good performance, `jj-stack` also batches calls to `jj` and minimizes the amount
170
+ of work those calls must do.
@@ -0,0 +1,88 @@
1
+ jj_stack/__init__.py,sha256=xOj0QztgnLYl1oYIcmniN9_TAJ3HyzDVt-Uh-6p9gjQ,273
2
+ jj_stack/__main__.py,sha256=DEO1C6HgNEWuIgPZByIoPR8yQ90HHdEo869dPvTK13A,175
3
+ jj_stack/bootstrap.py,sha256=GY9D8TOu4jvGNEZdbpNykPOdrIFFgaHO0itlYyYoGho,7050
4
+ jj_stack/cli.py,sha256=1m6412HdrQCisL1wY2XPAdMuOe-CtM106w1YkvXUvx0,42227
5
+ jj_stack/cli_help.py,sha256=HUIPBDEq4NmQ23Kw1gkrYswDD0SBMKTUfQXL-OUnAV0,23519
6
+ jj_stack/completion.py,sha256=CeEacS1xJURqvsYyfICCdupDx0eFsiIjC6B2ruqwiHs,16224
7
+ jj_stack/concurrency.py,sha256=HNQ164WFtBWNvRc0HQWiOCZQh2TuJ-StLiI_xSdw3CA,2932
8
+ jj_stack/config.py,sha256=Y3efFsSSD7_IsHXC6ToSIFu6tHkpw5yAF8G1aM_252A,5653
9
+ jj_stack/console.py,sha256=eUQxWaj8YItAZnDKEvvto4Nha4Ya9ukfE8eBBwihkmE,22158
10
+ jj_stack/errors.py,sha256=Sv5UOpwYA_AtC_PPrGyYWYYA-hTrUjQVOu4bBBqAzOI,4340
11
+ jj_stack/formatting.py,sha256=EKjpdB1NZpUHisvQvZ40XX4-0hImKfkfzZZAuc27JZA,2582
12
+ jj_stack/identifiers.py,sha256=NoELDuHtwv0-7oqGUThhSfWfrz_WpbXSJfdmBpljJ5o,187
13
+ jj_stack/pr_branch_namespace.py,sha256=ShPXnWyK43N2d8v88-6a192aIUbppeq6FHJGnokrSF0,2548
14
+ jj_stack/ui.py,sha256=DDSEqkXorLiENp6z5QG0smFdX2nbLQEbatEjt_F57f4,6538
15
+ jj_stack/commands/__init__.py,sha256=QAweKA6qt-08PEvBiZ6DirzntN3ScfoEzbuyzbdS_Mo,46
16
+ jj_stack/commands/_cleanup_actions.py,sha256=FG00gbVY9WZGY_FwPuPaErNCDeB_YDH-I65FxNeOq2s,12789
17
+ jj_stack/commands/_json_status.py,sha256=-VErmTJR0LKMGNWzwJx1ihR1oK1Q8sd0eFd-JYTRULA,2442
18
+ jj_stack/commands/checkout.py,sha256=CB7kcEgP8eUDGQUzsfgH0GZpb_YaWbGqzToWC8jrW4Y,24315
19
+ jj_stack/commands/doctor.py,sha256=JMp6dvzKxCs-IP-DHu37t-wuV9YMHxcAs-wdbUPFM8c,11747
20
+ jj_stack/commands/in_use.py,sha256=7HcXwL5XVdHwxIAhbyp0KcFfwep2GFikNp5NhfRa5LE,1150
21
+ jj_stack/commands/list_.py,sha256=F5FhSDYtd5t9hDFoo5guUJkB5qnhmLWl4DvE-J8L3iA,21609
22
+ jj_stack/commands/relink.py,sha256=L_D3dG-yC33v6i5qjVPKKCgLGapvq4IlaqEJ7bhjKgY,7070
23
+ jj_stack/commands/sync.py,sha256=6NkCww3hMjq6TUiHBr0pLRZ-rt86qCUMC0Gt7wP2A48,20620
24
+ jj_stack/commands/sync_apply.py,sha256=hqXcoiU2ySSA8YxpPoQcG4lGF-wBj97hzmNOd-oXPp4,16700
25
+ jj_stack/commands/unstack.py,sha256=7eegRmybr2RhKnLNx4fsZ2orKbBeYP5Dh3ig-Q5Qhz0,10267
26
+ jj_stack/commands/view.py,sha256=Xr4CvNk_v4lHO63z7cjwSn_14Ji_HgqUFxLBIeVg2A8,37865
27
+ jj_stack/commands/cleanup/command.py,sha256=Juv8nECxjdjDLdmEC2bAPP0lOrlczEzWRJApKVLiUTU,23592
28
+ jj_stack/commands/cleanup/shared.py,sha256=u3ckXkoWN9fv_OLpP7kfAczuBPHFwUBG1Mz2ocdfYh0,1768
29
+ jj_stack/commands/cleanup/stale.py,sha256=T7svin7aMD3p-Gk__QqvVdvLWfpctTGfYVmlProfyIY,2677
30
+ jj_stack/commands/merge/__init__.py,sha256=8cE_1kLL6LcIELntAgqMNx6iF3rqeSf_YuWlvbtb-CY,44
31
+ jj_stack/commands/merge/command.py,sha256=Ocx-KS_tgrZazEEMqSmMG9wBRbb6pPPwIB_GYCTpsBw,13844
32
+ jj_stack/commands/merge/github_stack.py,sha256=2zL9XBs5LV0mjkJ6WiwsshaS2QFsgS0Z5XLQs9-4q2s,11656
33
+ jj_stack/commands/merge/models.py,sha256=fAxDnmCA4D40GY0qYnlGQAo7yRnAhlQW2fOFKF1FNQ8,2507
34
+ jj_stack/commands/merge/plan.py,sha256=UF1KuZ4wU8fwgVNgy0sLa7SVdE81-tDerSo0dyIFrko,3456
35
+ jj_stack/commands/merge/preconditions.py,sha256=X2oY3ESH0uE7gUrV2orpUUygOgqrh18XmhR5JL__PB4,6375
36
+ jj_stack/commands/merge/render.py,sha256=QWvIzOcEISfNmDStzs_isldZ3OFJwBDiXoPvHtNHvHg,1838
37
+ jj_stack/commands/submit/__init__.py,sha256=gqdUEEZBkAyp926OnuvZysHeM5kBCuwtQafpUb8nan8,45
38
+ jj_stack/commands/submit/auto_close.py,sha256=GIX1Bhajj09S-s_NjEECLtCwYcrbiilYdJX0MNqelzE,3422
39
+ jj_stack/commands/submit/changes.py,sha256=ovAOxvBpVYa_-Mt8Kc29633DIZ3dW4K3jO5bc1suFao,3745
40
+ jj_stack/commands/submit/command.py,sha256=8xNeqMnN26YHoyg3pFVi3G10KjYYUotHkpUU9f0mwBc,28712
41
+ jj_stack/commands/submit/descriptions.py,sha256=MIK9W0hIctijK0lHnTlg6aI-iGqHrSXR8xYYySNAPWM,19946
42
+ jj_stack/commands/submit/github_stack.py,sha256=kSoWem8c5CBNyXsu8MhaDaN7pxn5RIlchENoYk8z3dw,5456
43
+ jj_stack/commands/submit/inputs.py,sha256=vmxrtjcWxHnl6Z-5mEo1iiq7eel8RZU9DfR_piSRht8,5801
44
+ jj_stack/commands/submit/models.py,sha256=EjF7eNN0rhunBjl2hvanftY6Ilwsda_bjEC39mfDp50,5669
45
+ jj_stack/commands/submit/overview_comments.py,sha256=Neie5Kp1CLCIYvfyTucW77iAXkScdgcWTNbzWfv9IOE,5751
46
+ jj_stack/commands/submit/prs.py,sha256=3USaQLXOhvIpsByR67ROuz1pnYp0-n_uSKnsX6BQxb8,16099
47
+ jj_stack/commands/submit/render.py,sha256=9UdWcksfx5FlkHhHlo_Fy_00dz6NryZGgmEaH4xvyck,3899
48
+ jj_stack/github/__init__.py,sha256=wLJPTInhzISydB4lQ-cWXOhx6nEeXBqn2jaEgKQKmrY,34
49
+ jj_stack/github/auth.py,sha256=UTyldI9Dlyx4rVksv9x_aw27h50VvFuvWoBZaFKrVH0,790
50
+ jj_stack/github/client.py,sha256=7AHkjhgW0Waf9w1AsEY-M7PUs2AohJ8gkHYvZouw9Po,34761
51
+ jj_stack/github/error_messages.py,sha256=v0Prwh9DXER_vftBHYhvDeu6uf9GODB3_TmLlXtQh08,2912
52
+ jj_stack/github/overview_comments.py,sha256=gV85sYRzMFnZ8-ePGaPkuNScFw-OgitbtbTMU-X35eU,1031
53
+ jj_stack/github/pr_refs.py,sha256=b3X5W7CbShe2Om2_HEPpFlpHVAGGdMcDctg1n6Jt_90,1923
54
+ jj_stack/github/resolution.py,sha256=eb6AC4qOovSNLyTbDf-Y1-SmXgLCfozh3Ux67u7ROnI,7213
55
+ jj_stack/github/stack_availability.py,sha256=B1XAwmYniU37zRGaw6fxDMb808Q_GJMfurv-27yEt5s,883
56
+ jj_stack/jj/__init__.py,sha256=3Q1JPAUWM_WNSVTYSSVdTQeZ9ajoKYHxyDoeoyGYNJs,45
57
+ jj_stack/jj/cli_args.py,sha256=Wnp-r29ZuA9_sCstwiCJG9ejxiM6MCY4SaknpDgOYLM,794
58
+ jj_stack/jj/client.py,sha256=rvZUdT0Tn0fW7NZnJcFG4e2b8O1Z9k_XsSDxLKjbb2I,53443
59
+ jj_stack/jj/colors.py,sha256=0mB6YmrQMyeSrMErIFc7bz-1VSRzuOggXLRCJEc6ToU,6570
60
+ jj_stack/models/__init__.py,sha256=OOw4B0fALOH6NqMpFWP-Yx2ZZYp3lN3-TbyLbICwKCo,56
61
+ jj_stack/models/git.py,sha256=L-HoS_s4uxL9Z-0gXmDOSCz4Z2j32BfI1EtmXEq1GkM,294
62
+ jj_stack/models/github.py,sha256=5BstIzymtRzsQORdT0ZNnNdFqEGRcA8NE5V8Pj_y_pM,7258
63
+ jj_stack/models/stack.py,sha256=ro5eVHaC3bIi65Qk5zXLXc1FcloHRXBkETJbYZh1Dk4,2203
64
+ jj_stack/models/tracking.py,sha256=lQzt0EgveBfRGS5tMpmOIiXjfwUbxI-PdD7iCCJYCiw,3601
65
+ jj_stack/stack/__init__.py,sha256=Rw0c_kAYZvVBubOIozFLcyh0Ef84qY_IouL3gXpnHrw,48
66
+ jj_stack/stack/change_status.py,sha256=DAaxaYumviki7ZYx9PAY8HJ82gZTgd9-xE55E-dWb6I,6461
67
+ jj_stack/stack/convergence.py,sha256=Ocf5lFPnIlGYUInlOdXo8lqe6xeEVHCMgMgctOZhJJ4,19542
68
+ jj_stack/stack/convergence_models.py,sha256=GsChOEWmoYV5RmUzrBzI3HxBcw82MX3MVwvJzCfc-Qo,1624
69
+ jj_stack/stack/convergence_observation.py,sha256=ul_RO6germ4qY6CYxDURJ8kRLVn0Ofi3ULln4fnXAbY,5322
70
+ jj_stack/stack/github_stack_safety.py,sha256=xMsD4ymdXZZUcJDnlHTd5e_1UTsHWvHfGJ_fdGX2xLE,5561
71
+ jj_stack/stack/global_convergence.py,sha256=drVstw0hTH234FCAXWw74r_Gbq5Em5cfyPxmXFIKgWA,8477
72
+ jj_stack/stack/path.py,sha256=TpjfV2v49-YEFW5AfZuTnPVY7R1QGo0U5fKoUGBfdj4,8145
73
+ jj_stack/stack/pr_branches.py,sha256=NCEyjWhpx6YUlAqCukzkZywDFY098P_8KE62c4eaihg,4229
74
+ jj_stack/stack/pr_facts.py,sha256=efbUaHQIluKpKAfttCzcgdtdBkO4Kc0iQ2Nty7j4MLM,6059
75
+ jj_stack/stack/repo.py,sha256=iY_TuaKcTm71rxyAgeUAQgDRZlJ2FSz9Poir1hNXObs,3699
76
+ jj_stack/stack/selected.py,sha256=n53M8o4HwF9qliBd92NgVoU0n_CLn8gvSMJjmu-bCrc,11741
77
+ jj_stack/stack/selection.py,sha256=XxHnw1VFPPXzr-iNZGJgWtLRdG1L1a_QAoCz_7OmXSE,3784
78
+ jj_stack/stack/status.py,sha256=bf_y_a4a5nJLB93tJwx_B7MoCUjQHHdj9fmFA_y9zTk,23199
79
+ jj_stack/stack/trunk_evidence.py,sha256=o9agVfp2ZS9BW2abgtOTb-Hk6ETL5gzIXcNQC929UBc,6003
80
+ jj_stack/state/__init__.py,sha256=_DS82nymsX27tydWjlq0Pge_QUTqF29tlhAxwH-18Vs,38
81
+ jj_stack/state/operation_lock.py,sha256=j4dp19q9z6aTYCRVUuEIhzVJiAznIXTNBNcq5CJVbas,6180
82
+ jj_stack/state/store.py,sha256=WzVQKaN8K74_FMbw9w6Hfi4GznNvoEZIKbwvXGWpLzI,9259
83
+ jj_stack-0.1.0.dist-info/METADATA,sha256=dcszfiLdcvNGjkpmW4o_Rr_gdhgmF2ceD6-3dSHxASo,6052
84
+ jj_stack-0.1.0.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
85
+ jj_stack-0.1.0.dist-info/entry_points.txt,sha256=bl_q9c4duNoHqZM-mtN-3ln-W5E7rD6-b_MUMSgVst0,47
86
+ jj_stack-0.1.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
87
+ jj_stack-0.1.0.dist-info/licenses/NOTICE,sha256=getthGQb0vFKoS8T4m7GGkTcHhztrzjT71PusRrVjBc,41
88
+ jj_stack-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.32.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ jj-stack = jj_stack.cli:main