carson 3.24.0 → 3.27.0
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.
- checksums.yaml +4 -4
- data/API.md +26 -8
- data/MANUAL.md +51 -22
- data/README.md +9 -16
- data/RELEASE.md +16 -1
- data/VERSION +1 -1
- data/carson.gemspec +0 -1
- data/hooks/command-guard +60 -16
- data/lib/carson/cli.rb +116 -5
- data/lib/carson/config.rb +3 -8
- data/lib/carson/delivery.rb +17 -9
- data/lib/carson/ledger.rb +242 -222
- data/lib/carson/repository.rb +2 -4
- data/lib/carson/revision.rb +2 -4
- data/lib/carson/runtime/abandon.rb +238 -0
- data/lib/carson/runtime/audit.rb +12 -2
- data/lib/carson/runtime/deliver.rb +162 -15
- data/lib/carson/runtime/govern.rb +48 -21
- data/lib/carson/runtime/housekeep.rb +189 -153
- data/lib/carson/runtime/local/onboard.rb +4 -3
- data/lib/carson/runtime/local/prune.rb +6 -11
- data/lib/carson/runtime/local/sync.rb +9 -0
- data/lib/carson/runtime/local/worktree.rb +166 -0
- data/lib/carson/runtime/recover.rb +418 -0
- data/lib/carson/runtime/setup.rb +11 -7
- data/lib/carson/runtime/status.rb +39 -28
- data/lib/carson/runtime.rb +3 -1
- data/lib/carson/worktree.rb +128 -53
- metadata +4 -22
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e71c18b520bc6869f6f22cff8593d59b7e4d38a58b7c9f7648d75252fdd8691c
|
|
4
|
+
data.tar.gz: 468b1b132620b3844ccd5df01907c149ddce5bf987bf2aa4fee6a17f3301cea7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6a3842a3fdb48ede44c4def41b1533ae43f68b5267a8d1280f1cdf7685b161406f58365002e20b34bb4dfa5a9fc2e788a970cf6c406dd877087844197114148d
|
|
7
|
+
data.tar.gz: 8ee70fb5f5f06bfc417ae39634f9277a07ca5aaa867a57b14960987a12cbe66a44ea193fc167831645025cd573d599f8cf385e8849c2a40d94ff0c6c43eb5967
|
data/API.md
CHANGED
|
@@ -25,13 +25,17 @@ carson <command> [subcommand] [arguments]
|
|
|
25
25
|
| Command | Purpose |
|
|
26
26
|
|---|---|
|
|
27
27
|
| `carson audit` | Evaluate governance status and generate report output. |
|
|
28
|
-
| `carson deliver [--commit MESSAGE]` |
|
|
28
|
+
| `carson deliver [--commit MESSAGE]` | Run Carson-owned branch delivery for the current checkout. Plain `deliver` transports existing commits only; `--commit` creates one all-dirty delivery commit first, then Carson pushes, creates or refreshes the PR, waits for merge readiness, merges when clear, and syncs local `main`. |
|
|
29
|
+
| `carson recover --check NAME [--json]` | Run the exceptional governed recovery path when one governance-owned required check is already red on the default branch. Carson proves the named baseline failure, keeps every other gate intact, merges through the recovery path, and records a machine-readable audit event. |
|
|
29
30
|
| `carson sync` | Fast-forward local `main` from configured remote when tree is clean. |
|
|
30
31
|
| `carson prune` | Remove stale local branches whose upstream refs no longer exist. |
|
|
32
|
+
| `carson housekeep [--json] [--dry-run]` | Attempt to sync the current repo, then reap dead worktrees, reconcile integrated delivery worktree records from the ledger, and prune stale branches. Safe cleanup still runs when sync is blocked. |
|
|
31
33
|
| `carson template check` | Detect drift between managed templates and host `.github/*` files. |
|
|
32
34
|
| `carson template apply` | Write canonical managed template content into host `.github/*` files. |
|
|
33
|
-
| `carson status [--json]` | Show repository delivery state. Default output is Markdown/text; `--json` is the explicit machine contract. |
|
|
35
|
+
| `carson status [--json]` | Show repository delivery state, including the next queued delivery and blocked-delivery summaries. Default output is Markdown/text; `--json` is the explicit machine contract. |
|
|
36
|
+
| `carson abandon <pr_number\|pr_url\|branch> [--json]` | Close abandoned delivery work and clean up its PR, worktree, and branch when safe. |
|
|
34
37
|
| `carson worktree create <name>` | Create an isolated worktree and branch for a new stream of work. |
|
|
38
|
+
| `carson worktree list [--json]` | Show every registered worktree with PR state and Carson's cleanup recommendation. |
|
|
35
39
|
| `carson worktree remove <path_or_name>` | Remove a worktree safely and clean up its branch when allowed. |
|
|
36
40
|
|
|
37
41
|
### Batch commands (Layer 2)
|
|
@@ -46,7 +50,9 @@ All batch commands operate across every governed repository registered in `gover
|
|
|
46
50
|
| `carson prune --all` | Remove stale branches across all governed repos. |
|
|
47
51
|
| `carson status --all [--json]` | Portfolio-wide delivery overview per governed repository. |
|
|
48
52
|
| `carson template check --all` | Read-only template drift detection across all governed repos. |
|
|
49
|
-
| `carson housekeep --all` |
|
|
53
|
+
| `carson housekeep --all [--loop SECONDS]` | Attempt sync, then reap dead worktrees, reconcile integrated delivery worktree records from the ledger, and prune across all governed repos. Safe cleanup still runs when sync is blocked. |
|
|
54
|
+
|
|
55
|
+
`--loop SECONDS` runs the housekeep cycle continuously, sleeping SECONDS between cycles. It requires `--all`, accepts only positive integers, and exits cleanly on `Ctrl-C` with a cycle count summary.
|
|
50
56
|
|
|
51
57
|
### Govern commands
|
|
52
58
|
|
|
@@ -58,6 +64,12 @@ All batch commands operate across every governed repository registered in `gover
|
|
|
58
64
|
|
|
59
65
|
Governed integration is fixed to `squash`. Non-squash `govern.merge.method` values are rejected by config validation.
|
|
60
66
|
|
|
67
|
+
After a live integration attempt, govern reports the actual outcome. Failed merges stay held at gate instead of being reported as integrated.
|
|
68
|
+
|
|
69
|
+
After CI and review pass, Carson still checks GitHub mergeability. Conflicting PRs stay held at gate with an explicit merge-conflict summary, while `BEHIND` PRs remain eligible under Carson's current squash policy.
|
|
70
|
+
|
|
71
|
+
After a successful govern merge, Carson runs the same cleanup path as `housekeep`: sync, reap safe worktrees, then prune.
|
|
72
|
+
|
|
61
73
|
### Review commands
|
|
62
74
|
|
|
63
75
|
| Command | Purpose |
|
|
@@ -79,6 +91,15 @@ Governed integration is fixed to `squash`. Non-squash `govern.merge.method` valu
|
|
|
79
91
|
|
|
80
92
|
Automation and CI integrations should treat exit `2` as an expected policy failure signal.
|
|
81
93
|
|
|
94
|
+
## Governance guard contract
|
|
95
|
+
|
|
96
|
+
In a Carson-governed repository:
|
|
97
|
+
- Raw `git worktree add` and `git worktree remove` are blocked. Use `carson worktree create` and `carson worktree remove`.
|
|
98
|
+
- Raw `git pull --rebase` is blocked. Use `carson sync`.
|
|
99
|
+
- Raw `gh pr create` and `gh pr merge` are blocked. Use `carson deliver`.
|
|
100
|
+
- Bootstrap repair for a baseline-red governance check uses `carson recover --check NAME`, not raw `gh api`.
|
|
101
|
+
- On the governed main working tree, raw `git add` and `git commit` are blocked until a Carson worktree exists for the task.
|
|
102
|
+
|
|
82
103
|
## Repository boundary contract
|
|
83
104
|
|
|
84
105
|
Blocked Carson artefacts in host repositories:
|
|
@@ -107,7 +128,6 @@ Environment overrides:
|
|
|
107
128
|
- `CARSON_REVIEW_SWEEP_STATES`
|
|
108
129
|
- `CARSON_WORKFLOW_STYLE`
|
|
109
130
|
- `CARSON_GOVERN_REPOS`
|
|
110
|
-
- `CARSON_GOVERN_AUTHORITY`
|
|
111
131
|
- `CARSON_GOVERN_AGENT_PROVIDER`
|
|
112
132
|
- `CARSON_GOVERN_CHECK_WAIT`
|
|
113
133
|
|
|
@@ -117,7 +137,6 @@ Environment overrides:
|
|
|
117
137
|
{
|
|
118
138
|
"govern": {
|
|
119
139
|
"repos": ["~/Dev/project-a", "~/Dev/project-b"],
|
|
120
|
-
"authority": "remote",
|
|
121
140
|
"agent": {
|
|
122
141
|
"provider": "auto",
|
|
123
142
|
"codex": {},
|
|
@@ -127,19 +146,18 @@ Environment overrides:
|
|
|
127
146
|
"merge": {
|
|
128
147
|
"method": "squash"
|
|
129
148
|
},
|
|
130
|
-
"state_path": "~/.carson/state.
|
|
149
|
+
"state_path": "~/.carson/state.json"
|
|
131
150
|
}
|
|
132
151
|
}
|
|
133
152
|
```
|
|
134
153
|
|
|
135
154
|
`govern` semantics:
|
|
136
155
|
- `repos`: list of local repo paths to govern (empty = current repo only).
|
|
137
|
-
- `authority`: `"remote"` (default) or `"local"`.
|
|
138
156
|
- `agent.provider`: `"auto"`, `"codex"`, or `"claude"`.
|
|
139
157
|
- `agent.codex` / `agent.claude`: provider-specific options (reserved).
|
|
140
158
|
- `check_wait`: seconds to wait for CI checks before classifying (default: `30`).
|
|
141
159
|
- `merge.method`: `"squash"` only in governed mode.
|
|
142
|
-
- `state_path`:
|
|
160
|
+
- `state_path`: JSON file path for active deliveries and revisions.
|
|
143
161
|
|
|
144
162
|
`template` schema:
|
|
145
163
|
|
data/MANUAL.md
CHANGED
|
@@ -117,8 +117,8 @@ These strategies are the audit lens for Carson. If behaviour departs from them,
|
|
|
117
117
|
### Git Strategist
|
|
118
118
|
|
|
119
119
|
- **Worktree-first discipline** — substantive work happens in worktrees, never on the main working tree. This keeps concurrent agent work isolated and makes cleanup explicit.
|
|
120
|
-
- **Deterministic base selection** — new work starts from
|
|
121
|
-
- **Single landing path
|
|
120
|
+
- **Deterministic base selection** — new work starts from a synced remote baseline, not from whatever branch state happens to be lying around.
|
|
121
|
+
- **Single landing path** — completed work rejoins through remote `main` via PR-based delivery.
|
|
122
122
|
- **Content-aware merge detection** — Carson proves whether a branch's content is already on `main` without relying on commit SHAs, so squash and rebase merges are handled correctly.
|
|
123
123
|
- **Worktree-aware delivery** — Carson lands work without assuming `main` can be checked out in the active worktree, and cleanup is deferred to the correct context.
|
|
124
124
|
- **Exact post-merge guidance** — after a successful landing, Carson tells the caller the next clean-up command instead of leaving the lifecycle half-finished.
|
|
@@ -127,7 +127,8 @@ These strategies are the audit lens for Carson. If behaviour departs from them,
|
|
|
127
127
|
|
|
128
128
|
- **Outsider boundary** — Carson governs repositories without writing Carson-specific config, scripts, or runtime payloads into them.
|
|
129
129
|
- **Command ownership** — in governed repositories, Carson owns worktree and delivery operations so agents do not mix raw git flows with governed ones.
|
|
130
|
-
- **
|
|
130
|
+
- **Main-tree protection** — on the governed main working tree, Carson blocks `git add` and `git commit` until the agent creates a Carson worktree for the task.
|
|
131
|
+
- **Governed delivery** — completed work returns to shared truth through remote `main` via PR-based delivery. Carson owns the landing path.
|
|
131
132
|
- **Active review gating** — when the repo uses PR-based delivery, review findings must be acknowledged before merge. Feedback is never silently buried.
|
|
132
133
|
- **Portfolio triage** — `carson govern` applies the same discipline across multiple repositories: classify, merge, dispatch, or escalate.
|
|
133
134
|
- **Template propagation** — Carson treats canonical policy files as managed infrastructure and keeps them consistent across repos.
|
|
@@ -145,47 +146,76 @@ These strategies are the audit lens for Carson. If behaviour departs from them,
|
|
|
145
146
|
|
|
146
147
|
The core workflow for coding agents using Carson. One command per step, full lifecycle.
|
|
147
148
|
|
|
148
|
-
**1. Create a worktree** — Carson starts new work from
|
|
149
|
+
**1. Create a worktree** — Carson syncs remote `main` and starts new work from that baseline rather than from the caller's current HEAD:
|
|
149
150
|
|
|
150
151
|
```bash
|
|
151
152
|
carson worktree create my-feature
|
|
152
153
|
cd /path/to/.claude/worktrees/my-feature
|
|
153
154
|
```
|
|
154
155
|
|
|
156
|
+
On the governed main working tree, Carson blocks raw `git add` / `git commit` and blocks raw `git worktree add/remove`, raw `git pull --rebase`, and raw `gh pr create/merge`. Use `carson worktree create`, `carson sync`, and `carson deliver` instead.
|
|
157
|
+
|
|
155
158
|
**2. Work** — make changes, test them, and either commit normally or let Carson create the delivery commit.
|
|
156
159
|
|
|
157
|
-
**3. Hand the branch to Carson** — `deliver` is the
|
|
160
|
+
**3. Hand the branch to Carson** — `deliver` is the synchronous happy path. Carson pushes the branch, creates or refreshes the PR, waits for the CI and review signals it can observe, merges when the path is clear, and syncs local `main`. Plain `carson deliver` transports existing commits and blocks if the worktree is dirty. `carson deliver --commit "..."` creates one all-dirty agent-authored commit first, then continues the same delivery flow. Managed template drift is still corrected in a separate Carson-managed commit before push.
|
|
158
161
|
|
|
159
162
|
```bash
|
|
160
163
|
carson deliver
|
|
161
164
|
# or, if the worktree is still dirty:
|
|
162
165
|
carson deliver --commit "fix: describe this delivery"
|
|
163
|
-
# Output:
|
|
164
|
-
# Next: carson status
|
|
166
|
+
# Output: merged into main, or held at gate with the next command
|
|
165
167
|
```
|
|
166
168
|
|
|
167
|
-
**4.
|
|
169
|
+
**4. Inspect or wait when needed** — when `deliver` cannot merge immediately, `status` shows the current branch, the next queued delivery, and any blocked-delivery summaries for the repository. Keep `govern` running when you want unattended portfolio reassessment and revision dispatch across governed repositories:
|
|
168
170
|
|
|
169
171
|
```bash
|
|
170
172
|
carson status
|
|
171
173
|
carson govern --loop 300
|
|
172
174
|
```
|
|
173
175
|
|
|
174
|
-
|
|
176
|
+
### Recover a baseline-red governance check
|
|
177
|
+
|
|
178
|
+
When a governance-owned required check is already red on the default branch, the PR that repairs it can deadlock behind that same gate. Use the explicit recovery path instead of reaching for raw `gh api`:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
carson recover --check "Carson governance"
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Recovery is narrow. Carson proves that the named check is red on the default branch, verifies that the current branch is repairing the governance surface, requires every other required check and the review gate to pass, then records a machine-readable audit event before reporting success.
|
|
185
|
+
|
|
186
|
+
If Carson refuses recovery, the message explains the exact missing proof or remaining gate and tells you what to do next.
|
|
187
|
+
|
|
188
|
+
**5. Clean up landed work** — once the delivery is integrated, use Carson cleanup commands from the main worktree. `worktree list` shows every registered worktree with PR state, absorbed-into-main detection, and Carson's cleanup recommendation:
|
|
175
189
|
|
|
176
190
|
```bash
|
|
177
191
|
cd /path/to/repo
|
|
178
|
-
carson worktree
|
|
179
|
-
carson
|
|
192
|
+
carson worktree list
|
|
193
|
+
carson housekeep
|
|
180
194
|
```
|
|
181
195
|
|
|
196
|
+
`housekeep` still performs safe reaping and branch pruning when `sync` cannot complete. A blocked sync no longer prevents cleanup work that has its own safety evidence.
|
|
197
|
+
|
|
198
|
+
`housekeep` also reconciles integrated delivery worktree records from the ledger. If the recorded worktree is already gone, Carson clears the stale ledger path. If the worktree still points at the integrated head and is safe to remove, Carson reaps it and clears the ledger path in the same pass.
|
|
199
|
+
|
|
200
|
+
When you need to abandon a stale branch or PR instead of landing it:
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
carson abandon 291
|
|
204
|
+
# or:
|
|
205
|
+
carson abandon https://github.com/owner/repo/pull/291
|
|
206
|
+
# or:
|
|
207
|
+
carson abandon feature/stale-work
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
`abandon` closes the PR when it is still open, removes the matching worktree when safe, deletes the local and remote branch refs when allowed, and marks the delivery as failed in Carson's ledger.
|
|
211
|
+
|
|
182
212
|
**Safety guards** — `worktree remove` blocks when:
|
|
183
213
|
- Shell CWD is inside the worktree (prevents session crash).
|
|
184
214
|
- Branch has unpushed commits with content that differs from main (prevents data loss).
|
|
185
215
|
|
|
186
216
|
After squash or rebase merge, the content matches main — removal proceeds without `--force`.
|
|
187
217
|
|
|
188
|
-
**Stale worktree recovery** — if a worktree directory is destroyed externally (for example by a raw GitHub merge/delete flow), `worktree remove` and `prune` handle the stale entry gracefully: they clean up the git registration and delete the branch without error. Use Carson's
|
|
218
|
+
**Stale worktree recovery** — if a worktree directory is destroyed externally (for example by a raw GitHub merge/delete flow), `worktree remove`, `worktree list`, `housekeep`, and `prune` handle the stale entry gracefully: they clean up the git registration and delete the branch without error when Carson has enough evidence. Use Carson's delivery and cleanup commands instead of raw `gh pr merge --delete-branch` so the worktree directory stays intact for orderly cleanup.
|
|
189
219
|
|
|
190
220
|
### Carson vs Claude Code EnterWorktree
|
|
191
221
|
|
|
@@ -264,10 +294,13 @@ carson audit --all # governance audit across all repos
|
|
|
264
294
|
carson prune --all # remove stale branches across all repos
|
|
265
295
|
carson template check --all # detect template drift across all repos
|
|
266
296
|
carson housekeep --all # full maintenance cycle across all repos
|
|
297
|
+
carson housekeep --all --loop 300 # housekeep every 5 minutes
|
|
267
298
|
```
|
|
268
299
|
|
|
269
300
|
`refresh --all` checks each repo for safety before operating: repos with active worktrees or uncommitted changes are skipped with clear reasons. Other batch commands attempt each repo and report failures without stopping.
|
|
270
301
|
|
|
302
|
+
`housekeep --all --loop SECONDS` runs the full housekeep cycle continuously, sleeping SECONDS between passes. It requires `--all`, accepts only positive integers, and exits cleanly on `Ctrl-C` with a cycle count summary.
|
|
303
|
+
|
|
271
304
|
**Periodic maintenance:**
|
|
272
305
|
|
|
273
306
|
```bash
|
|
@@ -292,6 +325,12 @@ Each cycle runs independently: if one cycle fails (network error, GitHub API tim
|
|
|
292
325
|
|
|
293
326
|
`carson govern` dispatches coding agents (Codex or Claude) when an active delivery is blocked by CI, review, or policy feedback. The agent receives the failure context and attempts a revision. If the agent succeeds, the delivery re-enters the governance pipeline. If it fails repeatedly or times out, the delivery is escalated for human attention.
|
|
294
327
|
|
|
328
|
+
After a live merge attempt, govern reports the actual outcome. Failed merges stay held at gate instead of being reported as integrated.
|
|
329
|
+
|
|
330
|
+
After CI and review pass, Carson still checks GitHub mergeability. Conflicting PRs stay held at gate with an explicit merge-conflict summary, while `BEHIND` PRs remain eligible under Carson's current squash policy.
|
|
331
|
+
|
|
332
|
+
After a successful govern merge, Carson runs the same cleanup path as `carson housekeep`: sync, reap safe worktrees, then prune.
|
|
333
|
+
|
|
295
334
|
The agent provider is configurable via `govern.agent.provider` (`auto`, `codex`, or `claude`). In `auto` mode, Carson selects the first available provider.
|
|
296
335
|
|
|
297
336
|
## Governed Integration Policy
|
|
@@ -375,15 +414,6 @@ Whether reviewer findings require acknowledgement.
|
|
|
375
414
|
|
|
376
415
|
Change: `CARSON_REVIEW_DISPOSITION`.
|
|
377
416
|
|
|
378
|
-
#### Delivery authority
|
|
379
|
-
|
|
380
|
-
Where completed work rejoins shared truth.
|
|
381
|
-
|
|
382
|
-
- **`remote`** (default) — the PR lands on remote `main`.
|
|
383
|
-
- **`local`** — Carson integrates through local `main`, then pushes `main` as backup.
|
|
384
|
-
|
|
385
|
-
Change: `govern.authority` in config.
|
|
386
|
-
|
|
387
417
|
#### Output verbosity
|
|
388
418
|
|
|
389
419
|
How much Carson prints.
|
|
@@ -411,7 +441,6 @@ Common environment overrides:
|
|
|
411
441
|
| `CARSON_REVIEW_SWEEP_WINDOW_DAYS` | Lookback window for review sweep. |
|
|
412
442
|
| `CARSON_REVIEW_SWEEP_STATES` | PR states to include in sweep. |
|
|
413
443
|
| `CARSON_REVIEW_BOT_USERNAMES` | Comma-separated bot usernames to ignore in review gate and sweep. |
|
|
414
|
-
| `CARSON_GOVERN_AUTHORITY` | Override delivery authority (`remote` or `local`). |
|
|
415
444
|
| `CARSON_WORKFLOW_STYLE` | Workflow style override (`branch` or `trunk`). |
|
|
416
445
|
| `CARSON_RUBY_INDENTATION` | Ruby indentation policy (`tabs`, `spaces`, or `either`). |
|
|
417
446
|
|
data/README.md
CHANGED
|
@@ -32,20 +32,10 @@ Carson lives on your workstation and in CI, never inside the repositories it gov
|
|
|
32
32
|
|
|
33
33
|
The outsider boundary still matters: Carson governs repositories without becoming a runtime dependency inside them.
|
|
34
34
|
|
|
35
|
-
## Two Authorities
|
|
36
|
-
|
|
37
|
-
Each governed repo chooses one integration authority.
|
|
38
|
-
|
|
39
|
-
**Remote** — remote `main` is the integration authority. Agents still work in local worktrees, but completed work rejoins through remote `main`.
|
|
40
|
-
|
|
41
|
-
**Local** — local `main` is the integration authority. Agents still work in local worktrees, but completed work rejoins through local `main`, then `main` is pushed to the remote as backup.
|
|
42
|
-
|
|
43
|
-
This is about where completed work rejoins shared truth, not about team size. Both authorities use worktrees. The authority changes how work lands, not whether Carson is needed.
|
|
44
|
-
|
|
45
35
|
## Principles
|
|
46
36
|
|
|
47
37
|
- **Worktree-first** — substantive work happens in worktrees, not on `main`.
|
|
48
|
-
- **Carson-owned operations** — Carson owns worktree and delivery operations in governed repositories.
|
|
38
|
+
- **Carson-owned operations** — Carson owns worktree and delivery operations in governed repositories. Raw `git worktree add/remove`, raw `git pull --rebase`, and raw `gh pr create/merge` are blocked, and `git add` / `git commit` are blocked on the main working tree until you create a Carson worktree.
|
|
49
39
|
- **Self-diagnosing output** — every block should say what happened and the exact next command.
|
|
50
40
|
- **Outsider boundary** — Carson governs repositories without becoming a host-repository runtime dependency.
|
|
51
41
|
|
|
@@ -62,13 +52,16 @@ cd your/repo/path/.claude/worktrees/your-worktree
|
|
|
62
52
|
|
|
63
53
|
# work and test, then either commit yourself or let Carson create the delivery commit
|
|
64
54
|
carson deliver --commit "fix: describe this delivery"
|
|
65
|
-
carson status
|
|
66
55
|
|
|
67
|
-
#
|
|
68
|
-
carson
|
|
56
|
+
# inspect cleanup recommendations once the work is landed
|
|
57
|
+
carson worktree list
|
|
69
58
|
```
|
|
70
59
|
|
|
71
|
-
|
|
60
|
+
`carson deliver` owns the normal branch-delivery path: it pushes the branch, creates or refreshes the PR, waits for the review and CI gates Carson can observe, merges when clear, and syncs local `main`. If CI or review is still pending after Carson's configured wait windows, `deliver` returns a gated state instead of merging. Use plain `carson deliver` when the branch is already committed. Use `carson deliver --commit "..."` when the worktree is dirty and Carson should create one all-dirty delivery commit first.
|
|
61
|
+
|
|
62
|
+
When one Carson-governed required check is already red on the default branch and the current PR is the repair, use `carson recover --check "..."`. Recovery is the explicit exceptional path: Carson proves the baseline failure, keeps every other gate intact, records an audit event, and never teaches operators to step outside Carson first.
|
|
63
|
+
|
|
64
|
+
`carson worktree list` is the visibility surface for cleanup: it shows every registered worktree, the branch, PR state, whether the content is already on `main`, and Carson's keep or reap recommendation. When work needs to be abandoned instead of landed, use `carson abandon <pr-number|pr-url|branch>` to close the PR and clean up the branch/worktree safely.
|
|
72
65
|
|
|
73
66
|
## Portfolio Layer
|
|
74
67
|
|
|
@@ -80,7 +73,7 @@ carson refresh --all
|
|
|
80
73
|
carson govern --dry-run
|
|
81
74
|
```
|
|
82
75
|
|
|
83
|
-
`carson govern` is the portfolio layer. It
|
|
76
|
+
`carson govern` is the portfolio layer. It reassesses active deliveries across governed repositories, dispatches revision work for blocked branches, and surfaces what needs human judgement. Governed integration is squash-only and happens one repository at a time.
|
|
84
77
|
|
|
85
78
|
## Where to Read Next
|
|
86
79
|
|
data/RELEASE.md
CHANGED
|
@@ -5,6 +5,21 @@ Release-note scope rule:
|
|
|
5
5
|
- `RELEASE.md` records only version deltas, breaking changes, and migration actions.
|
|
6
6
|
- Operational usage guides live in `MANUAL.md` and `API.md`.
|
|
7
7
|
|
|
8
|
+
## 3.27.0
|
|
9
|
+
|
|
10
|
+
### What changed
|
|
11
|
+
|
|
12
|
+
- **3.25.0 — Value objects simplified** — `Delivery` gains `repo_path`, `key` (composite `repo_path:branch:head`), and an embedded `revisions` array. `revision_count` is now derived from `revisions.length`. `Revision` drops `id` and `delivery_id`. Numeric delivery IDs are removed from the model entirely.
|
|
13
|
+
- **3.25.1 — Config defaults updated** — `govern.state_path` default changed from `~/.carson/state.sqlite3` to `~/.carson/state.json`. Fallback leaf follows suit.
|
|
14
|
+
- **3.26.0 — Ledger rewritten from SQLite to JSON** — The delivery ledger is now a plain JSON file (`~/.carson/state.json`) with file-lock protection and atomic writes. Revisions are embedded in their parent delivery. No migration — a missing `state.json` starts with an empty ledger; legacy `state.sqlite3` files are left untouched.
|
|
15
|
+
- **3.26.1 — Consumers use natural keys** — `govern.rb` and `deliver.rb` reference `delivery.key` instead of `delivery.id`. `revisions_for_delivery` uses the delivery object directly. `revision_count:` arguments removed from `update_delivery` calls (count is derived). Human output shows `Delivery: branch → main` instead of `Delivery #id`.
|
|
16
|
+
- **3.27.0 — sqlite3 dependency removed** — `spec.add_dependency "sqlite3"` removed from `carson.gemspec`. Carson has zero native extension dependencies.
|
|
17
|
+
|
|
18
|
+
### Migration
|
|
19
|
+
|
|
20
|
+
- If you have an existing `~/.carson/state.sqlite3`, Carson will not read it. Active deliveries start fresh. The old file is not deleted.
|
|
21
|
+
- Any automation referencing `govern.state_path` with `.sqlite3` should update to `.json`.
|
|
22
|
+
|
|
8
23
|
## 3.24.0
|
|
9
24
|
|
|
10
25
|
### What changed
|
|
@@ -47,7 +62,7 @@ Release-note scope rule:
|
|
|
47
62
|
|
|
48
63
|
### What changed
|
|
49
64
|
|
|
50
|
-
- **Single-actor branch delivery redesign** — Carson is now the sole actor. Repository and branch state are recorded in a
|
|
65
|
+
- **Single-actor branch delivery redesign** — Carson is now the sole actor. Repository and branch state are recorded in a JSON delivery ledger, `carson deliver` becomes the asynchronous branch handoff, and `carson govern` advances queued deliveries and revision cycles without blocking the caller process.
|
|
51
66
|
- **Status redesigned around deliveries** — `carson status` now reports repository authority, the current branch, active deliveries, and stale-branch counts. `--json` exposes the same delivery-centred model explicitly for software consumers.
|
|
52
67
|
- **Governed integration is squash-only** — Carson now enforces a single governed integration policy. Repository settings must allow squash merge, and Carson rejects governed configs that specify any other merge method.
|
|
53
68
|
- **Setup and help contract simplified** — `carson setup` no longer offers merge-method choice for governed repositories, and `carson deliver --merge` is removed in favour of the single autonomous `carson deliver` path.
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.
|
|
1
|
+
3.27.0
|
data/carson.gemspec
CHANGED
|
@@ -28,7 +28,6 @@ Gem::Specification.new do |spec|
|
|
|
28
28
|
spec.bindir = "exe"
|
|
29
29
|
spec.executables = [ "carson" ]
|
|
30
30
|
spec.require_paths = [ "lib" ]
|
|
31
|
-
spec.add_dependency "sqlite3", ">= 1.3", "< 3"
|
|
32
31
|
spec.files = Dir.glob( "{lib,exe,templates,hooks}/**/*", File::FNM_DOTMATCH ).select { |path| File.file?( path ) } + [
|
|
33
32
|
".github/workflows/carson_policy.yml",
|
|
34
33
|
"README.md",
|
data/hooks/command-guard
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# Carson command guard — Claude Code PreToolUse hook.
|
|
3
3
|
#
|
|
4
|
-
# Blocks raw
|
|
5
|
-
#
|
|
4
|
+
# Blocks raw worktree and delivery commands in Carson-governed repositories,
|
|
5
|
+
# plus `git add` / `git commit` on the main working tree.
|
|
6
|
+
# Agents should use Carson's governed path instead.
|
|
6
7
|
#
|
|
7
8
|
# Claude Code sends JSON on stdin: {"tool_name": "Bash", "tool_input": {"command": "..."}}
|
|
8
9
|
# To block: print reason to stderr, exit 2.
|
|
@@ -22,6 +23,14 @@
|
|
|
22
23
|
# ]
|
|
23
24
|
set -euo pipefail
|
|
24
25
|
|
|
26
|
+
block_command() {
|
|
27
|
+
local summary="$1"
|
|
28
|
+
local recovery="$2"
|
|
29
|
+
echo "$summary" >&2
|
|
30
|
+
echo "$recovery" >&2
|
|
31
|
+
exit 2
|
|
32
|
+
}
|
|
33
|
+
|
|
25
34
|
# Read the tool call JSON from stdin.
|
|
26
35
|
input="$(cat)"
|
|
27
36
|
|
|
@@ -32,14 +41,6 @@ tool_name="$(echo "$input" | jq -r '.tool_name // empty' 2>/dev/null)"
|
|
|
32
41
|
command_text="$(echo "$input" | jq -r '.tool_input.command // empty' 2>/dev/null)"
|
|
33
42
|
[ -n "$command_text" ] || exit 0
|
|
34
43
|
|
|
35
|
-
# Check for gh pr commands that Carson replaces.
|
|
36
|
-
# Match only at command position: start of line, or after a shell operator (&&, ||, ;, |).
|
|
37
|
-
# This avoids false positives from gh pr references inside commit messages or string arguments.
|
|
38
|
-
guarded_pattern='(^|&&|\|\||;|\|)\s*gh\s+pr\s+(create|merge)'
|
|
39
|
-
if ! echo "$command_text" | grep -qE "$guarded_pattern"; then
|
|
40
|
-
exit 0
|
|
41
|
-
fi
|
|
42
|
-
|
|
43
44
|
# Check if the current directory is inside a governed repository.
|
|
44
45
|
config_file="${HOME}/.carson/config.json"
|
|
45
46
|
[ -f "$config_file" ] || exit 0
|
|
@@ -47,12 +48,55 @@ config_file="${HOME}/.carson/config.json"
|
|
|
47
48
|
repo_root="$(git rev-parse --show-toplevel 2>/dev/null || echo "")"
|
|
48
49
|
[ -n "$repo_root" ] || exit 0
|
|
49
50
|
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
current_root="$(cd "$repo_root" && pwd -P)"
|
|
52
|
+
common_dir="$(git rev-parse --path-format=absolute --git-common-dir 2>/dev/null || echo "")"
|
|
53
|
+
if [ -n "$common_dir" ]; then
|
|
54
|
+
governed_root="$(cd "$(dirname "$common_dir")" && pwd -P)"
|
|
55
|
+
else
|
|
56
|
+
governed_root="$current_root"
|
|
57
|
+
fi
|
|
58
|
+
|
|
59
|
+
if ! grep -qF "\"$governed_root\"" "$config_file" 2>/dev/null; then
|
|
52
60
|
exit 0
|
|
53
61
|
fi
|
|
54
62
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
63
|
+
main_branch="$(jq -r '.git.main_branch // "main"' "$config_file" 2>/dev/null || echo "main")"
|
|
64
|
+
[ -n "$main_branch" ] || main_branch="main"
|
|
65
|
+
current_branch="$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "")"
|
|
66
|
+
on_main_worktree=false
|
|
67
|
+
on_main_branch=false
|
|
68
|
+
[ "$current_root" = "$governed_root" ] && on_main_worktree=true
|
|
69
|
+
[ "$current_branch" = "$main_branch" ] && on_main_branch=true
|
|
70
|
+
|
|
71
|
+
# Match only at command position: start of line, or after a shell operator (&&, ||, ;, |).
|
|
72
|
+
# This avoids false positives from mentions inside commit messages or string arguments.
|
|
73
|
+
delivery_pattern='(^|&&|\|\||;|\|)\s*gh\s+pr\s+(create|merge)\b'
|
|
74
|
+
worktree_pattern='(^|&&|\|\||;|\|)\s*git\s+worktree\s+(add|remove)\b'
|
|
75
|
+
pull_rebase_pattern='(^|&&|\|\||;|\|)\s*git\s+pull([^;&|]|\\\|)*--rebase\b'
|
|
76
|
+
main_mutation_pattern='(^|&&|\|\||;|\|)\s*git\s+(add|commit)\b'
|
|
77
|
+
|
|
78
|
+
if grep -qE "$delivery_pattern" <<<"$command_text"; then
|
|
79
|
+
block_command \
|
|
80
|
+
"This repo is Carson-governed — use \`carson deliver\` instead of raw \`gh pr\`." \
|
|
81
|
+
"Use \`carson deliver\` instead — it handles push, PR, and merge with safety guards."
|
|
82
|
+
fi
|
|
83
|
+
|
|
84
|
+
if grep -qE "$worktree_pattern" <<<"$command_text"; then
|
|
85
|
+
block_command \
|
|
86
|
+
"This repo is Carson-governed — use \`carson worktree\` instead of raw \`git worktree\`." \
|
|
87
|
+
"Use \`carson worktree create <name>\` or \`carson worktree remove <name>\` instead."
|
|
88
|
+
fi
|
|
89
|
+
|
|
90
|
+
if grep -qE "$pull_rebase_pattern" <<<"$command_text"; then
|
|
91
|
+
block_command \
|
|
92
|
+
"This repo is Carson-governed — use \`carson sync\` instead of raw \`git pull --rebase\`." \
|
|
93
|
+
"Use \`carson sync\` instead — it owns main-branch alignment in governed repos."
|
|
94
|
+
fi
|
|
95
|
+
|
|
96
|
+
if [ "$on_main_worktree" = true ] && [ "$on_main_branch" = true ] && grep -qE "$main_mutation_pattern" <<<"$command_text"; then
|
|
97
|
+
block_command \
|
|
98
|
+
"Main working tree is read-only in this Carson-governed repo." \
|
|
99
|
+
"Use \`carson worktree create <name>\` first, then run \`git add\` or \`git commit\` inside that worktree."
|
|
100
|
+
fi
|
|
101
|
+
|
|
102
|
+
exit 0
|