arc-prs 0.1.0__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.
@@ -0,0 +1,29 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main, master]
6
+ pull_request:
7
+
8
+ jobs:
9
+ test:
10
+ name: Test (Python ${{ matrix.python-version }})
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ fail-fast: false
14
+ matrix:
15
+ python-version: ["3.11", "3.12", "3.13"]
16
+
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+
20
+ - uses: astral-sh/setup-uv@v5
21
+ with:
22
+ python-version: ${{ matrix.python-version }}
23
+ enable-cache: true
24
+
25
+ - name: Install dependencies
26
+ run: uv sync
27
+
28
+ - name: Run tests
29
+ run: uv run pytest --tb=short -q
@@ -0,0 +1,55 @@
1
+ name: Release
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ inputs:
6
+ version:
7
+ description: "Version to release (e.g. 0.1.0) — must match version in pyproject.toml"
8
+ required: true
9
+
10
+ jobs:
11
+ release:
12
+ name: Build, tag, and publish
13
+ runs-on: ubuntu-latest
14
+ environment: release
15
+ permissions:
16
+ contents: write # create tags and GitHub releases
17
+ id-token: write # PyPI trusted publishing (no API token needed)
18
+
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+
22
+ - uses: astral-sh/setup-uv@v5
23
+ with:
24
+ python-version: "3.11"
25
+
26
+ - name: Validate version matches pyproject.toml
27
+ run: |
28
+ ACTUAL=$(python3 -c "import tomllib; print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")
29
+ if [ "$ACTUAL" != "${{ inputs.version }}" ]; then
30
+ echo "Version mismatch: pyproject.toml has $ACTUAL but release input is ${{ inputs.version }}"
31
+ echo "Bump the version in pyproject.toml via a PR first, then re-run this workflow."
32
+ exit 1
33
+ fi
34
+
35
+ - name: Build
36
+ run: uv build
37
+
38
+ - name: Create git tag
39
+ run: |
40
+ git config user.name "github-actions[bot]"
41
+ git config user.email "github-actions[bot]@users.noreply.github.com"
42
+ git tag -a "v${{ inputs.version }}" -m "Release v${{ inputs.version }}"
43
+ git push origin "v${{ inputs.version }}"
44
+
45
+ - name: Create GitHub Release
46
+ run: |
47
+ gh release create "v${{ inputs.version }}" \
48
+ dist/* \
49
+ --title "v${{ inputs.version }}" \
50
+ --generate-notes
51
+ env:
52
+ GH_TOKEN: ${{ github.token }}
53
+
54
+ - name: Publish to PyPI
55
+ run: uv publish
@@ -0,0 +1,30 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+
7
+ # Distribution / packaging
8
+ *.egg-info/
9
+ dist/
10
+ build/
11
+ *.egg
12
+
13
+ # Virtual environments
14
+ .venv/
15
+ venv/
16
+ env/
17
+
18
+ # Testing
19
+ .pytest_cache/
20
+ .coverage
21
+ htmlcov/
22
+
23
+ # uv lockfile (commit this if you want reproducible installs across machines)
24
+ # uv.lock
25
+
26
+ # arc stack state — per-clone, not shared
27
+ .arc/state.json
28
+
29
+ # Internal design docs — not for public repo
30
+ docs/superpowers/
arc_prs-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,7 @@
1
+ Metadata-Version: 2.4
2
+ Name: arc-prs
3
+ Version: 0.1.0
4
+ Summary: Local CLI for managing stacked pull requests
5
+ Requires-Python: >=3.11
6
+ Requires-Dist: click>=8.1
7
+ Requires-Dist: rich>=13.0
@@ -0,0 +1,252 @@
1
+ # arc
2
+
3
+ Your PR has 47 files changed. Nobody's going to review that.
4
+
5
+ Stacked PRs fix this — break a large change into a chain of small, focused diffs that reviewers can actually follow. The problem is that managing a stack by hand is painful. Every time `main` moves, you cascade rebases through four branches manually. Every merged PR means retargeting the one above it. So you skip the stacking and ship the monster PR anyway.
6
+
7
+ `arc` removes that friction.
8
+
9
+ ```
10
+ $ arc status
11
+
12
+ main
13
+ └── feat/auth PR #42 ✓ 2 commits (rev 3)
14
+ └── feat/api PR #43 ✗ 3 commits (rev 1) ← needs rebase
15
+ └── feat/ui no PR ✓ 1 commit
16
+
17
+ → Run 'arc sync' to rebase feat/api onto feat/auth.
18
+ ```
19
+
20
+ One command keeps the whole stack current. Another opens all the PRs — with a stack map in each description so reviewers can navigate. When a PR merges, `arc land` rebases everything above it and removes it from the stack.
21
+
22
+ ---
23
+
24
+ ## Install
25
+
26
+ ```bash
27
+ pipx install arc-stack
28
+ # or
29
+ uv tool install arc-stack
30
+ ```
31
+
32
+ **Requires:** Python 3.11+, [git](https://git-scm.com), [gh CLI](https://cli.github.com) (authenticated via `gh auth login`)
33
+
34
+ First time on a new machine:
35
+
36
+ ```bash
37
+ arc setup # checks git, gh auth, and configures git rerere
38
+ ```
39
+
40
+ ---
41
+
42
+ ## Building a stack
43
+
44
+ Initialize `arc` in your repo once:
45
+
46
+ ```bash
47
+ arc init --base main --prefix feat
48
+ ```
49
+
50
+ This creates `.arc/state.json` (git-ignored, per-clone) and adds it to `.gitignore`. The `--prefix` is optional — if set, `arc new auth` creates `feat/auth` instead of `auth`.
51
+
52
+ Then build your stack branch by branch as you work:
53
+
54
+ ```bash
55
+ arc new auth
56
+ # write code, run tests
57
+ git add . && git commit -m "Add auth middleware"
58
+
59
+ arc new api
60
+ # write code
61
+ git add . && git commit -m "Add API routes"
62
+
63
+ arc new ui
64
+ git add . && git commit -m "Add frontend"
65
+ ```
66
+
67
+ Each `arc new` creates a branch from your current HEAD and registers it in the stack. `arc status` shows you where you are at any point.
68
+
69
+ ---
70
+
71
+ ## The daily loop
72
+
73
+ When `main` moves or you amend a lower branch, run:
74
+
75
+ ```bash
76
+ arc sync
77
+ ```
78
+
79
+ This fetches the latest from remote and cascades a rebase bottom-up through the stack — `feat/auth` onto `main`, `feat/api` onto `feat/auth`, `feat/ui` onto `feat/api`. If there's a conflict, `arc` aborts the rebase, resets every branch to where it was before, and tells you exactly which files to fix:
80
+
81
+ ```
82
+ Conflict in feat/api. Resolve: src/api.py
83
+ Then run 'arc rebase --continue' or 'arc rebase --abort'.
84
+ ```
85
+
86
+ When the stack is clean, push everything and open PRs:
87
+
88
+ ```bash
89
+ arc push # force-pushes all branches atomically
90
+ arc submit --draft # creates or updates PRs for each branch
91
+ ```
92
+
93
+ Each PR targets the branch below it, not `main` directly. Reviewers see only the diff for that layer. `arc submit` also injects a stack map into every PR description:
94
+
95
+ ```
96
+ ---
97
+ Stack (base: main):
98
+ 1. feat/auth - PR #42 [this PR]
99
+ 2. feat/api - PR #43
100
+ 3. feat/ui - no PR
101
+ ```
102
+
103
+ Reviewers can navigate the whole stack from any PR without hunting for context.
104
+
105
+ When you're ready to open for review, `arc submit --open` marks all drafts as ready at once.
106
+
107
+ ---
108
+
109
+ ## When a PR merges
110
+
111
+ Once `feat/auth` is approved and merged on GitHub:
112
+
113
+ ```bash
114
+ arc land feat/auth
115
+ ```
116
+
117
+ `arc` verifies the PR is merged, detects whether it was a squash-merge or a regular merge, rebases `feat/api` and `feat/ui` onto `main` correctly (using `git rebase --onto` for squash-merges, which would otherwise leave duplicate commits), removes `feat/auth` from the stack, and deletes the local branch.
118
+
119
+ You can land branches in order as they get approved. The rest of the stack stays coherent throughout.
120
+
121
+ ---
122
+
123
+ ## Other useful things
124
+
125
+ **If a lower branch needs changes** after review feedback:
126
+
127
+ ```bash
128
+ arc checkout feat/auth # or: arc checkout 1
129
+ # fix the issue, amend your commit
130
+ arc sync # cascades the change up through api and ui
131
+ arc push && arc submit
132
+ ```
133
+
134
+ `arc checkout 2` navigates to the second branch in the stack. `arc up` / `arc down` / `arc top` / `arc bottom` move you through the stack without remembering branch names.
135
+
136
+ **Remove a branch** from the stack without touching the others:
137
+
138
+ ```bash
139
+ arc drop feat/api -f # restacks feat/ui onto feat/auth
140
+ ```
141
+
142
+ **Keep commit messages useful** after a PR is created:
143
+
144
+ ```bash
145
+ arc amend # appends the PR link and stack position to the HEAD commit message
146
+ ```
147
+
148
+ This means `git log` on the landed commits still traces back to the PR.
149
+
150
+ **Gate submissions on local checks** — configure `.arc/config.json` (committed, shared with your team):
151
+
152
+ ```json
153
+ {
154
+ "hooks": {
155
+ "pre-submit": ["npm run lint", "npm test"]
156
+ }
157
+ }
158
+ ```
159
+
160
+ `arc submit` runs these before touching GitHub. Any non-zero exit aborts. Pass `--skip-hooks` to bypass.
161
+
162
+ **Preview destructive operations** before running them:
163
+
164
+ ```bash
165
+ arc sync -n # shows the rebase plan without executing
166
+ arc push -n # shows which branches would be pushed
167
+ arc land -n # shows which branches would be restacked
168
+ ```
169
+
170
+ ---
171
+
172
+ ## Scripting and agents
173
+
174
+ Every command is non-interactive by default. `--json` sends structured output to stdout; status messages go to stderr. Exit codes carry meaning.
175
+
176
+ ```bash
177
+ # Find branches that need rebasing
178
+ arc status --json | jq '.branches[] | select(.needs_rebase) | .name'
179
+
180
+ # Get all branch names for a script
181
+ arc status --plain
182
+
183
+ # Full dry-run before committing
184
+ arc sync -n && arc push -n && arc submit -n
185
+ ```
186
+
187
+ **`arc status --json` output:**
188
+
189
+ ```json
190
+ {
191
+ "base": "main",
192
+ "prefix": "feat",
193
+ "current_branch": "feat/api",
194
+ "branches": [
195
+ {
196
+ "name": "feat/auth",
197
+ "index": 1,
198
+ "pr_number": 42,
199
+ "pr_url": "https://github.com/owner/repo/pull/42",
200
+ "pr_state": "OPEN",
201
+ "commits": 2,
202
+ "revision": 3,
203
+ "needs_rebase": false,
204
+ "is_current": false,
205
+ "is_merged": false
206
+ }
207
+ ]
208
+ }
209
+ ```
210
+
211
+ **Exit codes:**
212
+
213
+ | Code | Meaning | What to do |
214
+ |------|---------|------------|
215
+ | 0 | Success | — |
216
+ | 1 | Error | Read stderr |
217
+ | 2 | Not in a stack | `arc init` |
218
+ | 3 | Rebase conflict | Resolve, then `arc rebase --continue` or `--abort` |
219
+ | 4 | GitHub API failure | `gh auth status`, retry |
220
+ | 5 | Invalid arguments | Read stderr |
221
+ | 6 | Setup check failed | `arc setup` |
222
+ | 7 | Pre-submit hook failed | Fix the check or `--skip-hooks` |
223
+
224
+ ---
225
+
226
+ ## Reference
227
+
228
+ All commands accept `-q` (`--quiet`) to suppress hints and `-n` (`--dry-run`) where the operation is destructive. `--json` is available on any command that produces data.
229
+
230
+ | Command | What it does |
231
+ |---------|-------------|
232
+ | `arc setup` | Verify environment, configure git |
233
+ | `arc init [--base B] [--prefix P]` | Initialize a stack |
234
+ | `arc new <branch>` | Create branch from HEAD, add to stack |
235
+ | `arc add <branch>` | Adopt an existing local branch |
236
+ | `arc status [--json\|--plain]` | Show the stack |
237
+ | `arc sync` | Fetch + cascade rebase |
238
+ | `arc push` | Force-push all branches, increment revision |
239
+ | `arc submit [--draft\|--open] [--skip-hooks]` | Create or update PRs |
240
+ | `arc land [<branch>] [-f]` | Land a merged PR, restack above |
241
+ | `arc amend` | Append PR link to commit message |
242
+ | `arc drop <branch> [-f]` | Remove branch, restack above |
243
+ | `arc rebase [--upstack\|--downstack\|--continue\|--abort]` | Fine-grained rebase |
244
+ | `arc checkout <name\|index>` | Switch to branch by name or position |
245
+ | `arc up [n]` / `arc down [n]` | Move through the stack |
246
+ | `arc top` / `arc bottom` | Jump to ends of the stack |
247
+
248
+ ---
249
+
250
+ ## License
251
+
252
+ MIT
File without changes