carson 3.13.2 → 3.14.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/MANUAL.md +37 -0
- data/README.md +2 -0
- data/RELEASE.md +10 -0
- data/VERSION +1 -1
- data/lib/carson/cli.rb +15 -2
- data/lib/carson/runtime/local/onboard.rb +1 -5
- data/lib/carson/runtime/local/worktree.rb +3 -2
- data/lib/carson/runtime/repos.rb +29 -0
- data/lib/carson/runtime/setup.rb +4 -12
- data/lib/carson/runtime.rb +1 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a6187204d01b1fc7f62657f451451a0124e039b265d83379ce8c23e9ba62a346
|
|
4
|
+
data.tar.gz: d5b11033558afc8847386858bc62d9ba19816636dece60dfe4a5f1708528a50f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 005575df223f30f900794447f012d29bfa3c6a939433870da80dd54cdbcb43dd9099413357a049232ffdcd7d7c502996e3d4279a40f310fde576fe991c8659a0
|
|
7
|
+
data.tar.gz: 9c4c5023488bce12162fbcb0c4746db515c72e2b28618ca35682a3076ec2b3c1c67513af7712cb4238dc76a2fd389f9abf75385baf6d63ea10970be960d949e9
|
data/MANUAL.md
CHANGED
|
@@ -142,6 +142,36 @@ carson prune
|
|
|
142
142
|
|
|
143
143
|
After squash or rebase merge, the content matches main — removal proceeds without `--force`.
|
|
144
144
|
|
|
145
|
+
### Carson vs Claude Code EnterWorktree
|
|
146
|
+
|
|
147
|
+
Claude Code has a built-in `EnterWorktree` tool. Both create a git worktree under `.claude/worktrees/` with a new branch — but they solve different problems and have different trade-offs.
|
|
148
|
+
|
|
149
|
+
**What Carson adds over EnterWorktree:**
|
|
150
|
+
|
|
151
|
+
| Concern | EnterWorktree | Carson |
|
|
152
|
+
|---|---|---|
|
|
153
|
+
| Auto-sync main before branching | No — branches from current HEAD, which may be stale | Yes — `git pull --ff-only` before branch creation |
|
|
154
|
+
| CWD guard on removal | No | Yes — blocks if shell is inside the worktree |
|
|
155
|
+
| Unpushed-commits guard | No | Yes — blocks if work hasn't been pushed |
|
|
156
|
+
| Content-aware squash/rebase detection | No | Yes — compares tree content, not SHAs |
|
|
157
|
+
| Branch cleanup (local + remote) | No | Yes — one command removes worktree, local branch, and remote branch |
|
|
158
|
+
| `.git/info/exclude` management | No | Yes — prevents `.claude/` appearing as untracked |
|
|
159
|
+
| Recovery-aware errors | No | Yes — every error includes a concrete recovery command |
|
|
160
|
+
| `--json` output | No | Yes — machine-readable for agent consumption |
|
|
161
|
+
|
|
162
|
+
**What EnterWorktree does that Carson does not:**
|
|
163
|
+
|
|
164
|
+
- **Automatic session CWD switch.** After creating the worktree, Claude Code moves the agent's working directory into it — no manual `cd` required. This is genuine friction that Carson should learn from.
|
|
165
|
+
|
|
166
|
+
**What EnterWorktree gets wrong:**
|
|
167
|
+
|
|
168
|
+
- **Session-exit cleanup prompt.** On session exit, Claude Code asks the user whether to keep or remove each worktree. In an agent workflow this is pure friction — the user cannot verify the state of bot-created worktrees and is forced to choose "keep" every time. Carson's approach is better: deferred deletion by default, with safety guards when you do choose to clean up.
|
|
169
|
+
- **Random names.** Without a name argument, EnterWorktree generates a random string. `git branch` output becomes unreadable. Carson requires a meaningful name that doubles as the branch name.
|
|
170
|
+
|
|
171
|
+
**Relationship — complementary, not competing:**
|
|
172
|
+
|
|
173
|
+
The two tools serve different layers. EnterWorktree owns the session (CWD switch); Carson owns the git lifecycle (sync, safety, cleanup). The ideal integration is Claude Code's `WorktreeCreate`/`WorktreeRemove` hook mechanism — Carson registers as the hook handler, so `EnterWorktree` delegates creation to `carson worktree create` and gets both Carson's safety and Claude Code's automatic CWD switch.
|
|
174
|
+
|
|
145
175
|
## Daily Operations
|
|
146
176
|
|
|
147
177
|
**Start of work:**
|
|
@@ -170,6 +200,13 @@ carson template apply
|
|
|
170
200
|
carson review gate
|
|
171
201
|
```
|
|
172
202
|
|
|
203
|
+
**Portfolio overview:**
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
carson repos # list all governed repositories
|
|
207
|
+
carson repos --json # machine-readable output
|
|
208
|
+
```
|
|
209
|
+
|
|
173
210
|
**Periodic maintenance:**
|
|
174
211
|
|
|
175
212
|
```bash
|
data/README.md
CHANGED
|
@@ -29,6 +29,8 @@ Carson is an autonomous governance runtime that lives on your workstation and in
|
|
|
29
29
|
|
|
30
30
|
This separation is Carson's defining trait — the **outsider boundary**: no Carson scripts, config files, or governance payloads are ever placed inside a governed repository.
|
|
31
31
|
|
|
32
|
+
**Agent workspace management** — `carson worktree create` and `carson worktree remove` give coding agents safe, isolated workspaces. Unlike Claude Code's built-in `EnterWorktree`, Carson auto-syncs main before branching, guards against removing worktrees with unpushed work or an active shell inside, detects squash/rebase merges so removal doesn't falsely block, and cleans up the local and remote branch in one step. The two tools are complementary — see `MANUAL.md § Carson vs Claude Code EnterWorktree` for the full comparison.
|
|
33
|
+
|
|
32
34
|
### The Governance Loop
|
|
33
35
|
|
|
34
36
|
Carson orchestrates a closed governance loop across two layers:
|
data/RELEASE.md
CHANGED
|
@@ -5,6 +5,16 @@ 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.14.0
|
|
9
|
+
|
|
10
|
+
### What changed
|
|
11
|
+
|
|
12
|
+
- **`carson repos` command** — lists all governed repositories from Carson's global config. Shows which repos Carson is serving at a glance. Supports `--json` for machine-readable output. Portfolio-level command — works from any directory.
|
|
13
|
+
|
|
14
|
+
### UX improvement
|
|
15
|
+
|
|
16
|
+
- Bots and humans can now verify which repos Carson oversees with a single command instead of reading raw config JSON.
|
|
17
|
+
|
|
8
18
|
## 3.13.2
|
|
9
19
|
|
|
10
20
|
### What changed
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.
|
|
1
|
+
3.14.0
|
data/lib/carson/cli.rb
CHANGED
|
@@ -12,7 +12,7 @@ module Carson
|
|
|
12
12
|
return Runtime::EXIT_OK
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
-
if %w[refresh:all prune:all].include?( command )
|
|
15
|
+
if %w[repos refresh:all prune:all].include?( command )
|
|
16
16
|
verbose = parsed.fetch( :verbose, false )
|
|
17
17
|
runtime = Runtime.new( repo_root: repo_root, tool_root: tool_root, out: out, err: err, verbose: verbose )
|
|
18
18
|
return dispatch( parsed: parsed, runtime: runtime )
|
|
@@ -53,7 +53,7 @@ module Carson
|
|
|
53
53
|
|
|
54
54
|
def self.build_parser
|
|
55
55
|
OptionParser.new do |opts|
|
|
56
|
-
opts.banner = "Usage: carson [status [--json]|setup|audit [--json]|sync [--json]|deliver [--merge] [--json] [--title T] [--body-file F]|prune [--all] [--json]|worktree [--json] create|remove <name>|onboard|refresh [--all]|offboard|template check|apply|review gate|sweep|govern [--dry-run] [--json] [--loop SECONDS]|version]"
|
|
56
|
+
opts.banner = "Usage: carson [status [--json]|setup|audit [--json]|sync [--json]|deliver [--merge] [--json] [--title T] [--body-file F]|prune [--all] [--json]|worktree [--json] create|remove <name>|repos [--json]|onboard|refresh [--all]|offboard|template check|apply|review gate|sweep|govern [--dry-run] [--json] [--loop SECONDS]|version]"
|
|
57
57
|
end
|
|
58
58
|
end
|
|
59
59
|
|
|
@@ -86,6 +86,8 @@ module Carson
|
|
|
86
86
|
parse_prune_command( argv: argv, parser: parser, err: err )
|
|
87
87
|
when "worktree"
|
|
88
88
|
parse_worktree_subcommand( argv: argv, parser: parser, err: err )
|
|
89
|
+
when "repos"
|
|
90
|
+
parse_repos_command( argv: argv, err: err )
|
|
89
91
|
when "review"
|
|
90
92
|
parse_named_subcommand( command: command, usage: "gate|sweep", argv: argv, parser: parser, err: err )
|
|
91
93
|
when "audit"
|
|
@@ -299,6 +301,15 @@ module Carson
|
|
|
299
301
|
{ command: :invalid }
|
|
300
302
|
end
|
|
301
303
|
|
|
304
|
+
def self.parse_repos_command( argv:, err: )
|
|
305
|
+
json_flag = argv.delete( "--json" ) ? true : false
|
|
306
|
+
unless argv.empty?
|
|
307
|
+
err.puts "#{BADGE} Unexpected arguments for repos: #{argv.join( ' ' )}"
|
|
308
|
+
return { command: :invalid }
|
|
309
|
+
end
|
|
310
|
+
{ command: "repos", json: json_flag }
|
|
311
|
+
end
|
|
312
|
+
|
|
302
313
|
def self.parse_govern_subcommand( argv:, err: )
|
|
303
314
|
options = {
|
|
304
315
|
dry_run: false,
|
|
@@ -376,6 +387,8 @@ module Carson
|
|
|
376
387
|
runtime.review_gate!
|
|
377
388
|
when "review:sweep"
|
|
378
389
|
runtime.review_sweep!
|
|
390
|
+
when "repos"
|
|
391
|
+
runtime.repos!( json_output: parsed.fetch( :json, false ) )
|
|
379
392
|
when "govern"
|
|
380
393
|
runtime.govern!(
|
|
381
394
|
dry_run: parsed.fetch( :dry_run, false ),
|
|
@@ -229,11 +229,7 @@ module Carson
|
|
|
229
229
|
puts_line ""
|
|
230
230
|
puts_line "Carson at your service."
|
|
231
231
|
|
|
232
|
-
|
|
233
|
-
prompt_govern_registration!
|
|
234
|
-
else
|
|
235
|
-
puts_line "To register for portfolio governance: carson onboard (in a TTY)"
|
|
236
|
-
end
|
|
232
|
+
auto_register_govern!
|
|
237
233
|
|
|
238
234
|
puts_line ""
|
|
239
235
|
puts_line "Your repository is set up. Carson has placed files in your"
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Safe worktree lifecycle management for coding agents.
|
|
2
|
-
# Two operations: create and remove.
|
|
3
|
-
# CWD-inside-worktree and unpushed
|
|
2
|
+
# Two operations: create and remove. Create auto-syncs main before branching.
|
|
3
|
+
# Remove is safe by default — guards against CWD-inside-worktree and unpushed
|
|
4
|
+
# commits. Content-aware: allows removal after squash/rebase merge without --force.
|
|
4
5
|
# Supports --json for machine-readable structured output with recovery commands.
|
|
5
6
|
module Carson
|
|
6
7
|
class Runtime
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Lists governed repositories from Carson's global config.
|
|
2
|
+
# Portfolio-level query — not scoped to any single repository.
|
|
3
|
+
require "json"
|
|
4
|
+
|
|
5
|
+
module Carson
|
|
6
|
+
class Runtime
|
|
7
|
+
module Repos
|
|
8
|
+
def repos!( json_output: false )
|
|
9
|
+
repos = config.govern_repos
|
|
10
|
+
|
|
11
|
+
if json_output
|
|
12
|
+
out.puts JSON.pretty_generate( { command: "repos", repos: repos } )
|
|
13
|
+
else
|
|
14
|
+
if repos.empty?
|
|
15
|
+
puts_line "No governed repositories."
|
|
16
|
+
puts_line " Run carson onboard in a repo to register it."
|
|
17
|
+
else
|
|
18
|
+
puts_line "Governed repositories (#{repos.length}):"
|
|
19
|
+
repos.each { |path| puts_line " #{path}" }
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
EXIT_OK
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
include Repos
|
|
28
|
+
end
|
|
29
|
+
end
|
data/lib/carson/runtime/setup.rb
CHANGED
|
@@ -368,24 +368,16 @@ module Carson
|
|
|
368
368
|
!path.empty? && File.file?( path )
|
|
369
369
|
end
|
|
370
370
|
|
|
371
|
-
#
|
|
372
|
-
def
|
|
371
|
+
# Automatically registers the repo for portfolio governance during onboard.
|
|
372
|
+
def auto_register_govern!
|
|
373
373
|
expanded = File.expand_path( repo_root )
|
|
374
374
|
if config.govern_repos.include?( expanded )
|
|
375
375
|
puts_verbose "govern_registration: already registered #{expanded}"
|
|
376
376
|
return
|
|
377
377
|
end
|
|
378
378
|
|
|
379
|
-
|
|
380
|
-
puts_line "
|
|
381
|
-
puts_line " Register this repo so carson refresh --all and carson govern include it?"
|
|
382
|
-
accepted = prompt_yes_no( default: true )
|
|
383
|
-
if accepted
|
|
384
|
-
append_govern_repo!( repo_path: expanded )
|
|
385
|
-
puts_line "Registered. Run carson refresh --all to keep all repos in sync."
|
|
386
|
-
else
|
|
387
|
-
puts_line "Skipped. Run carson onboard here again to register later."
|
|
388
|
-
end
|
|
379
|
+
append_govern_repo!( repo_path: expanded )
|
|
380
|
+
puts_line "Registered for portfolio governance."
|
|
389
381
|
end
|
|
390
382
|
|
|
391
383
|
# Reusable Y/n prompt following existing prompt_choice conventions.
|
data/lib/carson/runtime.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: carson
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.14.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Hailei Wang
|
|
@@ -61,6 +61,7 @@ files:
|
|
|
61
61
|
- lib/carson/runtime/local/sync.rb
|
|
62
62
|
- lib/carson/runtime/local/template.rb
|
|
63
63
|
- lib/carson/runtime/local/worktree.rb
|
|
64
|
+
- lib/carson/runtime/repos.rb
|
|
64
65
|
- lib/carson/runtime/review.rb
|
|
65
66
|
- lib/carson/runtime/review/data_access.rb
|
|
66
67
|
- lib/carson/runtime/review/gate_support.rb
|