carson 2.24.0 → 2.25.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/.github/workflows/carson_policy.yml +5 -14
- data/API.md +6 -36
- data/MANUAL.md +10 -38
- data/README.md +9 -22
- data/RELEASE.md +9 -0
- data/SKILL.md +5 -7
- data/VERSION +1 -1
- data/lib/carson/cli.rb +1 -59
- data/lib/carson/config.rb +25 -50
- data/lib/carson/runtime/audit.rb +1 -59
- data/lib/carson/runtime/govern.rb +7 -36
- data/lib/carson/runtime/local/hooks.rb +142 -0
- data/lib/carson/runtime/local/onboard.rb +356 -0
- data/lib/carson/runtime/local/prune.rb +292 -0
- data/lib/carson/runtime/local/sync.rb +93 -0
- data/lib/carson/runtime/local/template.rb +347 -0
- data/lib/carson/runtime/local.rb +6 -1225
- data/lib/carson/runtime/review/gate_support.rb +1 -1
- data/lib/carson/runtime/review/sweep_support.rb +1 -1
- data/lib/carson/runtime/review/utility.rb +2 -2
- data/lib/carson/runtime/setup.rb +8 -2
- data/lib/carson/runtime.rb +0 -1
- data/templates/.github/carson.md +0 -1
- metadata +6 -2
- data/lib/carson/runtime/lint.rb +0 -154
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6046632b555d3558d7b0b8910cbcb50a562d155b92d535f28275eb78cd9f02d9
|
|
4
|
+
data.tar.gz: 8a86dad0adc37689a2dc2185ac428c4710f3aa511b2015455a6eeab9ae7468d6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: aca61a3a47edbbf4a6dea33970b954f5b5116786d3f14713f67e2140ce0d113364f4e5c08181146296cb28858d5023b552102178386e05c6d9120686c79dbcb2
|
|
7
|
+
data.tar.gz: 65fd5eb074422776f240a8161c5bec6d3ea6c8d746e182b9e2f95bf8cbd05131c9a0567af5dc0d9ef3f4e5b9bc1ab71e4c22493d3ef69f9a6e43c9487430fac3
|
|
@@ -12,14 +12,9 @@ on:
|
|
|
12
12
|
description: Exact Carson gem version expected in VERSION
|
|
13
13
|
required: true
|
|
14
14
|
type: string
|
|
15
|
-
rubocop_version:
|
|
16
|
-
description: Exact RuboCop gem version installed before Carson audit.
|
|
17
|
-
required: false
|
|
18
|
-
type: string
|
|
19
|
-
default: "1.81.0"
|
|
20
15
|
secrets:
|
|
21
16
|
CARSON_READ_TOKEN:
|
|
22
|
-
description: Read token for private
|
|
17
|
+
description: Read token for private canonical-template source repository.
|
|
23
18
|
required: false
|
|
24
19
|
|
|
25
20
|
jobs:
|
|
@@ -63,17 +58,13 @@ jobs:
|
|
|
63
58
|
gem build carson.gemspec
|
|
64
59
|
gem install --local "carson-${{ inputs.carson_version }}.gem"
|
|
65
60
|
|
|
66
|
-
- name:
|
|
67
|
-
|
|
61
|
+
- name: Carson refresh
|
|
62
|
+
working-directory: host
|
|
63
|
+
run: carson refresh
|
|
68
64
|
|
|
69
65
|
- name: Carson audit
|
|
70
66
|
working-directory: host
|
|
71
|
-
|
|
72
|
-
CARSON_READ_TOKEN: ${{ secrets.CARSON_READ_TOKEN }}
|
|
73
|
-
run: |
|
|
74
|
-
carson lint policy --source https://github.com/wanghailei/ai.git --ref main --force
|
|
75
|
-
carson prepare
|
|
76
|
-
carson audit
|
|
67
|
+
run: carson audit
|
|
77
68
|
|
|
78
69
|
- name: Carson review gate
|
|
79
70
|
working-directory: host
|
data/API.md
CHANGED
|
@@ -16,9 +16,7 @@ carson <command> [subcommand] [arguments]
|
|
|
16
16
|
| Command | Purpose |
|
|
17
17
|
|---|---|
|
|
18
18
|
| `carson setup` | Interactive quiz to configure remote, main branch, workflow, and merge method. Writes `~/.carson/config.json`. |
|
|
19
|
-
| `carson
|
|
20
|
-
| `carson onboard [repo_path]` | Apply one-command baseline setup for a target git repository. Auto-triggers `setup` on first run. |
|
|
21
|
-
| `carson prepare` | Install or refresh Carson-managed global hooks. |
|
|
19
|
+
| `carson onboard [repo_path]` | Apply one-command baseline setup for a target git repository. Auto-triggers `setup` on first run. Installs or refreshes Carson-managed global hooks. |
|
|
22
20
|
| `carson refresh [repo_path]` | Re-apply hooks, templates, and audit after upgrading Carson. Auto-propagates template updates to the remote via worktree (branch workflow: PR on `carson/template-sync`; trunk workflow: push to main). |
|
|
23
21
|
| `carson offboard [repo_path]` | Remove Carson-managed host artefacts, detach Carson hooks path, and deregister from `govern.repos`. |
|
|
24
22
|
|
|
@@ -37,7 +35,6 @@ carson <command> [subcommand] [arguments]
|
|
|
37
35
|
| Command | Purpose |
|
|
38
36
|
|---|---|
|
|
39
37
|
| `carson govern [--dry-run] [--json] [--loop SECONDS]` | Portfolio-level PR triage: classify, merge, dispatch agents, escalate. |
|
|
40
|
-
| `carson housekeep` | Sync main + prune stale branches (also runs automatically after govern merges). |
|
|
41
38
|
|
|
42
39
|
`--loop SECONDS` runs the govern cycle continuously, sleeping SECONDS between cycles. The loop isolates errors per cycle — a single failing cycle does not stop the daemon. `Ctrl-C` cleanly exits with a cycle count summary. SECONDS must be a positive integer.
|
|
43
40
|
|
|
@@ -55,8 +52,6 @@ carson <command> [subcommand] [arguments]
|
|
|
55
52
|
| Command | Purpose |
|
|
56
53
|
|---|---|
|
|
57
54
|
| `carson version` | Print installed Carson version. |
|
|
58
|
-
| `carson inspect` | Verify Carson-managed hook installation and repository setup. |
|
|
59
|
-
| `carson check` | Report required CI check status for the current branch's open PR. Exits 0 for passing or pending; exits 2 for failing. Never exits 8. |
|
|
60
55
|
|
|
61
56
|
## Exit status contract
|
|
62
57
|
|
|
@@ -90,18 +85,16 @@ Override path:
|
|
|
90
85
|
- `CARSON_CONFIG_FILE=/absolute/path/to/config.json`
|
|
91
86
|
|
|
92
87
|
Environment overrides:
|
|
93
|
-
- `
|
|
88
|
+
- `CARSON_HOOKS_PATH`
|
|
94
89
|
- `CARSON_REVIEW_WAIT_SECONDS`
|
|
95
90
|
- `CARSON_REVIEW_POLL_SECONDS`
|
|
96
91
|
- `CARSON_REVIEW_MAX_POLLS`
|
|
97
|
-
- `
|
|
92
|
+
- `CARSON_REVIEW_DISPOSITION`
|
|
98
93
|
- `CARSON_REVIEW_SWEEP_WINDOW_DAYS`
|
|
99
94
|
- `CARSON_REVIEW_SWEEP_STATES`
|
|
100
95
|
- `CARSON_WORKFLOW_STYLE`
|
|
101
|
-
- `CARSON_RUBY_INDENTATION`
|
|
102
|
-
- `CARSON_LINT_POLICY_SOURCE`
|
|
103
96
|
- `CARSON_GOVERN_REPOS`
|
|
104
|
-
- `
|
|
97
|
+
- `CARSON_GOVERN_AUTO_MERGE`
|
|
105
98
|
- `CARSON_GOVERN_MERGE_METHOD`
|
|
106
99
|
- `CARSON_GOVERN_AGENT_PROVIDER`
|
|
107
100
|
- `CARSON_GOVERN_CHECK_WAIT`
|
|
@@ -118,8 +111,8 @@ Environment overrides:
|
|
|
118
111
|
"claude": {}
|
|
119
112
|
},
|
|
120
113
|
"check_wait": 30,
|
|
114
|
+
"auto_merge": true,
|
|
121
115
|
"merge": {
|
|
122
|
-
"authority": true,
|
|
123
116
|
"method": "squash"
|
|
124
117
|
}
|
|
125
118
|
}
|
|
@@ -131,7 +124,7 @@ Environment overrides:
|
|
|
131
124
|
- `agent.provider`: `"auto"`, `"codex"`, or `"claude"`.
|
|
132
125
|
- `agent.codex` / `agent.claude`: provider-specific options (reserved).
|
|
133
126
|
- `check_wait`: seconds to wait for CI checks before classifying (default: `30`).
|
|
134
|
-
- `
|
|
127
|
+
- `auto_merge`: `true` (default) — Carson may merge autonomously. Set to `false` to require explicit enablement.
|
|
135
128
|
- `merge.method`: `"squash"` (default), `"merge"`, or `"rebase"`.
|
|
136
129
|
|
|
137
130
|
`template` schema:
|
|
@@ -147,29 +140,6 @@ Environment overrides:
|
|
|
147
140
|
`template` semantics:
|
|
148
141
|
- `canonical`: path to a directory of canonical `.github/` files. Carson discovers files in this directory and syncs them to governed repos alongside its own governance files. The directory mirrors `.github/` structure — `workflows/lint.yml` deploys to `.github/workflows/lint.yml`. Default: `nil` (no canonical files).
|
|
149
142
|
|
|
150
|
-
`lint` schema:
|
|
151
|
-
|
|
152
|
-
```json
|
|
153
|
-
{
|
|
154
|
-
"lint": {
|
|
155
|
-
"policy_source": "wanghailei/lint.git"
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
`lint` semantics:
|
|
161
|
-
- `policy_source`: default source for `carson lint policy` when `--source` is not specified.
|
|
162
|
-
|
|
163
|
-
Environment overrides:
|
|
164
|
-
- `CARSON_LINT_POLICY_SOURCE` — overrides `lint.policy_source`.
|
|
165
|
-
|
|
166
|
-
Private-source clone token for `carson lint policy`:
|
|
167
|
-
- `CARSON_READ_TOKEN` (used when `--source` points to a private GitHub repository).
|
|
168
|
-
|
|
169
|
-
Policy layout requirement:
|
|
170
|
-
- Lint config files sit at the root of the source repo and are copied to `<governed-repo>/.github/linters/`.
|
|
171
|
-
- MegaLinter auto-discovers configs in `.github/linters/` during CI.
|
|
172
|
-
|
|
173
143
|
## Output interface
|
|
174
144
|
|
|
175
145
|
Report output directory precedence:
|
data/MANUAL.md
CHANGED
|
@@ -25,26 +25,7 @@ carson version
|
|
|
25
25
|
|
|
26
26
|
## First-Time Setup
|
|
27
27
|
|
|
28
|
-
###
|
|
29
|
-
|
|
30
|
-
Carson distributes lint configuration files from a central policy source — a directory or git repository you control — into each governed repo's `.github/linters/` directory, where MegaLinter auto-discovers them in CI.
|
|
31
|
-
|
|
32
|
-
```bash
|
|
33
|
-
carson lint policy --source /path/to/your-policy-repo
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
After this command, `.github/linters/` contains your lint configs (`.rubocop.yml`, `biome.json`, `ruff.toml`, etc.). MegaLinter uses these in CI. Every governed repository gets the same rules — this is how Carson keeps lint consistent across languages.
|
|
37
|
-
|
|
38
|
-
Carson distributes policy; MegaLinter enforces it. Carson does not run linters itself — that responsibility belongs to MegaLinter in CI and to the developer's own local tooling.
|
|
39
|
-
|
|
40
|
-
Options:
|
|
41
|
-
- `--source <path-or-git-url>` — where to read policy files from (required).
|
|
42
|
-
- `--ref <git-ref>` — branch or tag when `--source` is a git URL.
|
|
43
|
-
- `--force` — overwrite existing `.github/linters/` files.
|
|
44
|
-
|
|
45
|
-
Policy layout: lint config files sit at the root of the source repo (flat layout, no subdirectories required).
|
|
46
|
-
|
|
47
|
-
### Step 2: Onboard a repository
|
|
28
|
+
### Onboard a repository
|
|
48
29
|
|
|
49
30
|
```bash
|
|
50
31
|
carson onboard /path/to/your-repo
|
|
@@ -69,7 +50,7 @@ carson setup
|
|
|
69
50
|
|
|
70
51
|
Re-run the interactive setup quiz to change your remote, main branch, workflow style, or merge method. Choices are saved to `~/.carson/config.json`.
|
|
71
52
|
|
|
72
|
-
###
|
|
53
|
+
### Commit generated files
|
|
73
54
|
|
|
74
55
|
After `onboard`, commit the generated `.github/*` changes in your repository. From this point the repository is governed.
|
|
75
56
|
|
|
@@ -96,7 +77,7 @@ jobs:
|
|
|
96
77
|
|
|
97
78
|
Notes:
|
|
98
79
|
- When upgrading Carson, update both `carson_ref` and `carson_version` together.
|
|
99
|
-
- `CARSON_READ_TOKEN` must have read access to your policy source repository
|
|
80
|
+
- `CARSON_READ_TOKEN` must have read access to your policy source repository.
|
|
100
81
|
- The reusable workflow installs a pinned RuboCop gem before `carson audit`; mirror the same pin in host governance workflows for deterministic checks.
|
|
101
82
|
|
|
102
83
|
### Canonical Templates
|
|
@@ -133,7 +114,6 @@ Carson discovers files in this directory and syncs them to governed repos alongs
|
|
|
133
114
|
|
|
134
115
|
```bash
|
|
135
116
|
carson sync # fast-forward local main
|
|
136
|
-
carson lint policy --source /path/to/your-policy-repo # refresh policy if needed
|
|
137
117
|
carson audit # full governance check
|
|
138
118
|
```
|
|
139
119
|
|
|
@@ -268,16 +248,7 @@ Where Carson installs git hooks.
|
|
|
268
248
|
|
|
269
249
|
- Default: **`~/.carson/hooks/<version>/`**. Outsider principle: hooks live outside your repo, versioned per Carson release, never committed to your repository.
|
|
270
250
|
|
|
271
|
-
Change: `
|
|
272
|
-
|
|
273
|
-
#### Lint policy source
|
|
274
|
-
|
|
275
|
-
Where lint configuration files come from and where they land.
|
|
276
|
-
|
|
277
|
-
- Default source: **`wanghailei/lint.git`**. A central repository containing lint configs for all languages.
|
|
278
|
-
- Target: **`<repo>/.github/linters/`**. MegaLinter auto-discovers configs here in CI.
|
|
279
|
-
|
|
280
|
-
Change: `carson lint policy --source <path-or-git-url>` or `lint.policy_source` in config. After changing policy, run `carson refresh --all` to propagate to all governed repositories.
|
|
251
|
+
Change: `CARSON_HOOKS_PATH`.
|
|
281
252
|
|
|
282
253
|
#### Review disposition
|
|
283
254
|
|
|
@@ -285,7 +256,7 @@ Whether reviewer findings require acknowledgement.
|
|
|
285
256
|
|
|
286
257
|
- Default: **required**. Comments containing risk keywords (`bug`, `security`, `regression`, etc.) must have a `Disposition:` response from the PR author before merge. Prevents feedback from being buried.
|
|
287
258
|
|
|
288
|
-
Change
|
|
259
|
+
Change: `CARSON_REVIEW_DISPOSITION`.
|
|
289
260
|
|
|
290
261
|
#### Merge authority
|
|
291
262
|
|
|
@@ -293,7 +264,7 @@ Whether `carson govern` can merge PRs autonomously.
|
|
|
293
264
|
|
|
294
265
|
- Default: **enabled**. Carson merges PRs that pass all gates (CI green, review clean, audit clean). PRs that need human judgement are escalated, never silently merged.
|
|
295
266
|
|
|
296
|
-
Disable: `govern.
|
|
267
|
+
Disable: `govern.auto_merge: false` in config or `CARSON_GOVERN_AUTO_MERGE=false`.
|
|
297
268
|
|
|
298
269
|
#### Output verbosity
|
|
299
270
|
|
|
@@ -330,14 +301,15 @@ Common environment overrides:
|
|
|
330
301
|
|
|
331
302
|
| Variable | Purpose |
|
|
332
303
|
|---|---|
|
|
333
|
-
| `
|
|
304
|
+
| `CARSON_HOOKS_PATH` | Custom hooks installation directory. |
|
|
334
305
|
| `CARSON_REVIEW_WAIT_SECONDS` | Initial wait before first review poll. |
|
|
335
306
|
| `CARSON_REVIEW_POLL_SECONDS` | Interval between review polls. |
|
|
336
307
|
| `CARSON_REVIEW_MAX_POLLS` | Maximum review poll attempts. |
|
|
337
|
-
| `
|
|
308
|
+
| `CARSON_REVIEW_DISPOSITION` | Required disposition keyword for review comments. |
|
|
338
309
|
| `CARSON_REVIEW_SWEEP_WINDOW_DAYS` | Lookback window for review sweep. |
|
|
339
310
|
| `CARSON_REVIEW_SWEEP_STATES` | PR states to include in sweep. |
|
|
340
311
|
| `CARSON_REVIEW_BOT_USERNAMES` | Comma-separated bot usernames to ignore in review gate and sweep. |
|
|
312
|
+
| `CARSON_GOVERN_AUTO_MERGE` | Enable or disable autonomous PR merging. |
|
|
341
313
|
| `CARSON_WORKFLOW_STYLE` | Workflow style override (`branch` or `trunk`). |
|
|
342
314
|
| `CARSON_RUBY_INDENTATION` | Ruby indentation policy (`tabs`, `spaces`, or `either`). |
|
|
343
315
|
|
|
@@ -350,7 +322,7 @@ For the full configuration schema, see `API.md`.
|
|
|
350
322
|
- Confirm `$(ruby -e 'print Gem.user_dir')/bin` is in `PATH`.
|
|
351
323
|
|
|
352
324
|
**`review gate` fails on actionable comments**
|
|
353
|
-
- Respond with a valid disposition comment using the required
|
|
325
|
+
- Respond with a valid disposition comment using the required disposition keyword.
|
|
354
326
|
- Re-run `carson review gate`.
|
|
355
327
|
|
|
356
328
|
**Template drift blocks**
|
data/README.md
CHANGED
|
@@ -8,7 +8,7 @@ Named after the head of household in Downton Abbey, Carson is your repositories'
|
|
|
8
8
|
|
|
9
9
|
## The Problem to Solve
|
|
10
10
|
|
|
11
|
-
Managing a growing portfolio of repositories is rewarding work — but the operational overhead scales faster than the code itself.
|
|
11
|
+
Managing a growing portfolio of repositories is rewarding work — but the operational overhead scales faster than the code itself. PR templates go stale, reviewer feedback gets quietly buried, and what passes on a developer's laptop fails in CI. When coding agents start producing PRs across multiple projects, the coordination load multiplies: checking results, dispatching fixes, clicking merge, cleaning up branches.
|
|
12
12
|
|
|
13
13
|
Carson exists so you can focus on what matters — building — while governance runs itself.
|
|
14
14
|
|
|
@@ -16,7 +16,7 @@ Carson exists so you can focus on what matters — building — while governance
|
|
|
16
16
|
|
|
17
17
|
Carson is an autonomous governance runtime that lives on your workstation and in CI, never inside the repositories it governs. It operates at two levels:
|
|
18
18
|
|
|
19
|
-
**Per-commit governance** — Carson gates merges on unresolved review comments, synchronises templates, and keeps your local branches clean. Every commit triggers `carson audit` through managed hooks; the same checks run in GitHub Actions.
|
|
19
|
+
**Per-commit governance** — Carson gates merges on unresolved review comments, synchronises templates, and keeps your local branches clean. Every commit triggers `carson audit` through managed hooks; the same checks run in GitHub Actions.
|
|
20
20
|
|
|
21
21
|
**Portfolio-level autonomy** — `carson govern` is a triage loop that scans your registered repositories, classifies every open PR, and acts: merge what's ready, dispatch coding agents (Codex or Claude) to fix what's failing, and escalate what needs human judgement. One command, all your projects, unmanned.
|
|
22
22
|
|
|
@@ -24,7 +24,6 @@ Carson is an autonomous governance runtime that lives on your workstation and in
|
|
|
24
24
|
~/.carson/ ← Carson lives here, never inside your repos
|
|
25
25
|
│
|
|
26
26
|
├─ hooks ──────────────► commit gates (every governed repo)
|
|
27
|
-
├─ lint configs ───────► .github/linters/ (MegaLinter auto-discovers)
|
|
28
27
|
└─ govern ─────────────► PR triage → merge | dispatch agent | escalate
|
|
29
28
|
```
|
|
30
29
|
|
|
@@ -32,25 +31,23 @@ This separation is Carson's defining trait — the **outsider boundary**: no Car
|
|
|
32
31
|
|
|
33
32
|
### The Governance Loop
|
|
34
33
|
|
|
35
|
-
Carson orchestrates a closed governance loop across
|
|
34
|
+
Carson orchestrates a closed governance loop across two layers:
|
|
36
35
|
|
|
37
|
-
1. **
|
|
38
|
-
2. **
|
|
39
|
-
3. **Autonomous triage** — `carson govern` reads CI status (including MegaLinter results), review disposition, and audit health for every open PR. Ready PRs are merged. Failing PRs get a coding agent (Codex or Claude) dispatched to fix them. Stuck PRs are escalated.
|
|
36
|
+
1. **CI enforcement** — Carson's `audit` gates on CI check status reported by GitHub. The actual CI runs are delegated to GitHub Actions.
|
|
37
|
+
2. **Autonomous triage** — `carson govern` reads CI status, review disposition, and audit health for every open PR. Ready PRs are merged. Failing PRs get a coding agent (Codex or Claude) dispatched to fix them. Stuck PRs are escalated.
|
|
40
38
|
|
|
41
|
-
Carson's role is governance orchestration —
|
|
39
|
+
Carson's role is governance orchestration — gating on results and dispatching action. The actual CI runs and code fixes are delegated to specialised tools: GitHub Actions for CI and coding agents for remediation.
|
|
42
40
|
|
|
43
41
|
## Opinions
|
|
44
42
|
|
|
45
43
|
Carson is opinionated about governance. These are non-negotiable principles, not configurable defaults:
|
|
46
44
|
|
|
47
45
|
- **Outsider boundary** — Carson lives outside your repo, never inside. No Carson-owned artefacts in your repository. Offboarding leaves no trace.
|
|
48
|
-
- **Centralised lint** — lint policy distributed from a central source into each repo's `.github/linters/`. One source of truth, zero drift. MegaLinter enforces it in CI.
|
|
49
46
|
- **Active review** — undisposed reviewer findings block merge. Feedback must be acknowledged, not buried.
|
|
50
47
|
- **Self-diagnosing output** — every warning and error names what went wrong, why, and what to do next. If you have to read source code to understand a message, that message is a bug.
|
|
51
48
|
- **Transparent governance** — Carson prepares everything for merge but never oversteps. It does not make decisions for you without telling you.
|
|
52
49
|
|
|
53
|
-
Everything else bends to your preference. Which branch is main, how PRs are merged, which repositories to govern, which coding agent to dispatch
|
|
50
|
+
Everything else bends to your preference. Which branch is main, how PRs are merged, which repositories to govern, which coding agent to dispatch — Carson asks during setup and remembers. Sensible defaults are provided; you only change what matters to you. See `MANUAL.md` for the full list.
|
|
54
51
|
|
|
55
52
|
## Quickstart
|
|
56
53
|
|
|
@@ -75,21 +72,11 @@ After `carson onboard`, your repository has:
|
|
|
75
72
|
|
|
76
73
|
Commit the generated `.github/*` changes, and the repository is governed.
|
|
77
74
|
|
|
78
|
-
**
|
|
79
|
-
|
|
80
|
-
```bash
|
|
81
|
-
# local directory
|
|
82
|
-
carson lint policy --source /path/to/your-policy-dir
|
|
83
|
-
|
|
84
|
-
# remote repository
|
|
85
|
-
carson lint policy --source https://github.com/you/lint-policy.git
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
**Govern your portfolio.** Once repositories are onboarded, `carson govern` is your recurring command. Run it whenever you want Carson to triage open PRs, enforce review policy, dispatch coding agents, and housekeep across all governed repos:
|
|
75
|
+
**Govern your portfolio.** Once repositories are onboarded, `carson govern` is your recurring command. Run it whenever you want Carson to triage open PRs, enforce review policy, and dispatch coding agents across all governed repos:
|
|
89
76
|
|
|
90
77
|
```bash
|
|
91
78
|
carson govern --dry-run # preview what Carson would do, change nothing
|
|
92
|
-
carson govern # triage PRs, merge ready ones, dispatch agents
|
|
79
|
+
carson govern # triage PRs, merge ready ones, dispatch agents
|
|
93
80
|
carson govern --loop 300 # run continuously, cycling every 5 minutes
|
|
94
81
|
```
|
|
95
82
|
|
data/RELEASE.md
CHANGED
|
@@ -5,6 +5,15 @@ 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
|
+
## 2.25.0 — Onboard/Offboard UX Improvements
|
|
9
|
+
|
|
10
|
+
### What changed
|
|
11
|
+
|
|
12
|
+
- **`carson offboard` now asks for TTY confirmation** before removing files. In non-TTY environments (CI, scripts), offboard proceeds without prompting, preserving backwards compatibility.
|
|
13
|
+
- **Offboard prints post-removal guidance** ("commit the removals and push to finalise offboarding") so users know what to do next.
|
|
14
|
+
- **Non-TTY `carson onboard` now shows a govern registration hint** ("to register for portfolio governance: carson onboard in a TTY") instead of silently skipping the prompt.
|
|
15
|
+
- **`carson setup` shows current values** for workflow style and merge method when re-running, and pre-selects the current choice as the default. Previously only canonical template showed its current value.
|
|
16
|
+
|
|
8
17
|
## 2.24.0 — Remove Scope Integrity Guard
|
|
9
18
|
|
|
10
19
|
### What changed
|
data/SKILL.md
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
# Carson Skill
|
|
2
2
|
|
|
3
|
-
You are working in a repository governed by Carson — a deterministic governance runtime. Carson handles git hooks,
|
|
3
|
+
You are working in a repository governed by Carson — a deterministic governance runtime. Carson handles git hooks, PR triage, agent dispatch, merge, and cleanup. You provide the intelligence; Carson provides the infrastructure.
|
|
4
4
|
|
|
5
5
|
## When to use Carson commands
|
|
6
6
|
|
|
7
7
|
| User intent | Command | What happens |
|
|
8
8
|
|---|---|---|
|
|
9
|
-
| "Check if my code is ready" | `carson audit` |
|
|
9
|
+
| "Check if my code is ready" | `carson audit` | Scope, boundary checks. Exit 0 = clean. Exit 2 = policy block. |
|
|
10
10
|
| "Is my PR mergeable?" | `carson review gate` | Polls for unresolved review threads and actionable comments. Blocks until resolved. |
|
|
11
11
|
| "What's happening across my repos?" | `carson govern --dry-run` | Classifies every open PR without taking action. Read the summary. |
|
|
12
12
|
| "Run governance continuously" | `carson govern --loop 300` | Triage-dispatch-merge cycle every 300 seconds. Ctrl-C to stop. |
|
|
13
|
-
| "Merge ready PRs and dispatch fixes" | `carson govern` | Full autonomous cycle: merge, dispatch agents, escalate
|
|
13
|
+
| "Merge ready PRs and dispatch fixes" | `carson govern` | Full autonomous cycle: merge, dispatch agents, escalate. |
|
|
14
14
|
| "Set up Carson for a repo" | `carson onboard /path/to/repo` | Installs hooks, syncs templates, runs first audit. |
|
|
15
15
|
| "Refresh after upgrading Carson" | `carson refresh` | Re-applies hooks and templates for the current version. |
|
|
16
16
|
| "Update my local main" | `carson sync` | Fast-forward local main from remote. Blocks if tree is dirty. |
|
|
@@ -18,13 +18,12 @@ You are working in a repository governed by Carson — a deterministic governanc
|
|
|
18
18
|
| "Check template drift" | `carson template check` then `carson template apply` | Detect and fix .github/* drift. |
|
|
19
19
|
| "Remove Carson from a repo" | `carson offboard /path/to/repo` | Removes hooks and managed files. |
|
|
20
20
|
| "What version?" | `carson version` | Prints installed version with ⧓ badge. |
|
|
21
|
-
| "Verify hook installation" | `carson inspect` | Checks hooks path, file existence, permissions. |
|
|
22
21
|
|
|
23
22
|
## Exit codes
|
|
24
23
|
|
|
25
24
|
- `0` — success, all clear.
|
|
26
25
|
- `1` — runtime or configuration error. Read the error message.
|
|
27
|
-
- `2` — policy block. Something must be fixed before proceeding (
|
|
26
|
+
- `2` — policy block. Something must be fixed before proceeding (unresolved review, boundary breach).
|
|
28
27
|
|
|
29
28
|
When you see exit 2, do NOT bypass it. Read the output, fix the root cause, and re-run.
|
|
30
29
|
|
|
@@ -88,7 +87,7 @@ Run `carson review gate` to see which comments need disposition. Respond to each
|
|
|
88
87
|
This means a commit was made to main that couldn't be pushed (branch protection). Reset: `git checkout main && git reset --hard github/main`.
|
|
89
88
|
|
|
90
89
|
**Hooks out of date after upgrade:**
|
|
91
|
-
Run `carson
|
|
90
|
+
Run `carson refresh` to re-apply hooks and templates for the current version.
|
|
92
91
|
|
|
93
92
|
**Govern merge fails:**
|
|
94
93
|
Check that `govern.merge.method` in config matches what GitHub allows. If the repo enforces linear history, only `rebase` works.
|
|
@@ -98,4 +97,3 @@ Check that `govern.merge.method` in config matches what GitHub allows. If the re
|
|
|
98
97
|
- Carson never lives inside governed repositories. No `.carson.yml`, no `bin/carson`, no `.tools/carson/`.
|
|
99
98
|
- Carson-managed files in repos are limited to `.github/*` templates.
|
|
100
99
|
- Carson's hooks live at `~/.carson/hooks/<version>/`, never in `.git/hooks/`.
|
|
101
|
-
- Lint policy is distributed via `carson lint policy --source <policy-repo>` into each repo's `.github/linters/`.
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.
|
|
1
|
+
2.25.0
|
data/lib/carson/cli.rb
CHANGED
|
@@ -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 [setup|audit|
|
|
56
|
+
opts.banner = "Usage: carson [setup|audit|sync|prune|onboard [repo_path]|refresh [--all|repo_path]|offboard [repo_path]|template check|template apply|review gate|review sweep|govern [--dry-run] [--json] [--loop SECONDS]|version]"
|
|
57
57
|
end
|
|
58
58
|
end
|
|
59
59
|
|
|
@@ -80,8 +80,6 @@ module Carson
|
|
|
80
80
|
parse_refresh_command( argv: argv, parser: parser, err: err )
|
|
81
81
|
when "template"
|
|
82
82
|
parse_template_subcommand( argv: argv, parser: parser, err: err )
|
|
83
|
-
when "lint"
|
|
84
|
-
parse_lint_subcommand( argv: argv, parser: parser, err: err )
|
|
85
83
|
when "review"
|
|
86
84
|
parse_named_subcommand( command: command, usage: "gate|sweep", argv: argv, parser: parser, err: err )
|
|
87
85
|
when "govern"
|
|
@@ -172,48 +170,6 @@ module Carson
|
|
|
172
170
|
{ command: :invalid }
|
|
173
171
|
end
|
|
174
172
|
|
|
175
|
-
def self.parse_lint_subcommand( argv:, parser:, err: )
|
|
176
|
-
action = argv.shift
|
|
177
|
-
unless action == "policy"
|
|
178
|
-
err.puts "#{BADGE} Missing or invalid subcommand for lint. Use: carson lint policy --source <path-or-git-url> [--ref <git-ref>] [--force]"
|
|
179
|
-
err.puts parser
|
|
180
|
-
return { command: :invalid }
|
|
181
|
-
end
|
|
182
|
-
|
|
183
|
-
options = {
|
|
184
|
-
source: nil,
|
|
185
|
-
ref: "main",
|
|
186
|
-
force: false
|
|
187
|
-
}
|
|
188
|
-
lint_parser = OptionParser.new do |opts|
|
|
189
|
-
opts.banner = "Usage: carson lint policy --source <path-or-git-url> [--ref <git-ref>] [--force]"
|
|
190
|
-
opts.on( "--source SOURCE", "Source repository path or git URL that contains CODING/" ) { |value| options[ :source ] = value.to_s.strip }
|
|
191
|
-
opts.on( "--ref REF", "Git ref used when --source is a git URL (default: main)" ) { |value| options[ :ref ] = value.to_s.strip }
|
|
192
|
-
opts.on( "--force", "Overwrite existing files" ) { options[ :force ] = true }
|
|
193
|
-
end
|
|
194
|
-
lint_parser.parse!( argv )
|
|
195
|
-
if options.fetch( :source ).to_s.empty?
|
|
196
|
-
err.puts "#{BADGE} Missing required --source for lint policy."
|
|
197
|
-
err.puts lint_parser
|
|
198
|
-
return { command: :invalid }
|
|
199
|
-
end
|
|
200
|
-
unless argv.empty?
|
|
201
|
-
err.puts "#{BADGE} Unexpected arguments for lint policy: #{argv.join( ' ' )}"
|
|
202
|
-
err.puts lint_parser
|
|
203
|
-
return { command: :invalid }
|
|
204
|
-
end
|
|
205
|
-
{
|
|
206
|
-
command: "lint:setup",
|
|
207
|
-
source: options.fetch( :source ),
|
|
208
|
-
ref: options.fetch( :ref ),
|
|
209
|
-
force: options.fetch( :force )
|
|
210
|
-
}
|
|
211
|
-
rescue OptionParser::ParseError => e
|
|
212
|
-
err.puts "#{BADGE} #{e.message}"
|
|
213
|
-
err.puts lint_parser
|
|
214
|
-
{ command: :invalid }
|
|
215
|
-
end
|
|
216
|
-
|
|
217
173
|
def self.parse_govern_subcommand( argv:, err: )
|
|
218
174
|
options = {
|
|
219
175
|
dry_run: false,
|
|
@@ -260,12 +216,6 @@ module Carson
|
|
|
260
216
|
runtime.sync!
|
|
261
217
|
when "prune"
|
|
262
218
|
runtime.prune!
|
|
263
|
-
when "prepare"
|
|
264
|
-
runtime.prepare!
|
|
265
|
-
when "inspect"
|
|
266
|
-
runtime.inspect!
|
|
267
|
-
when "check"
|
|
268
|
-
runtime.check!
|
|
269
219
|
when "onboard"
|
|
270
220
|
runtime.onboard!
|
|
271
221
|
when "refresh"
|
|
@@ -278,12 +228,6 @@ module Carson
|
|
|
278
228
|
runtime.template_check!
|
|
279
229
|
when "template:apply"
|
|
280
230
|
runtime.template_apply!( push_prep: parsed.fetch( :push_prep, false ) )
|
|
281
|
-
when "lint:setup"
|
|
282
|
-
runtime.lint_setup!(
|
|
283
|
-
source: parsed.fetch( :source ),
|
|
284
|
-
ref: parsed.fetch( :ref ),
|
|
285
|
-
force: parsed.fetch( :force )
|
|
286
|
-
)
|
|
287
231
|
when "review:gate"
|
|
288
232
|
runtime.review_gate!
|
|
289
233
|
when "review:sweep"
|
|
@@ -294,8 +238,6 @@ module Carson
|
|
|
294
238
|
json_output: parsed.fetch( :json, false ),
|
|
295
239
|
loop_seconds: parsed.fetch( :loop_seconds, nil )
|
|
296
240
|
)
|
|
297
|
-
when "housekeep"
|
|
298
|
-
runtime.housekeep!
|
|
299
241
|
else
|
|
300
242
|
runtime.send( :puts_line, "Unknown command: #{command}" )
|
|
301
243
|
Runtime::EXIT_ERROR
|