carson 3.20.0 → 3.21.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/README.md +11 -3
- data/RELEASE.md +14 -0
- data/VERSION +1 -1
- data/exe/carson +3 -3
- data/hooks/command-guard +56 -0
- data/hooks/pre-push +37 -1
- data/lib/carson/adapters/agent.rb +1 -0
- data/lib/carson/adapters/claude.rb +2 -0
- data/lib/carson/adapters/codex.rb +2 -0
- data/lib/carson/adapters/git.rb +2 -0
- data/lib/carson/adapters/github.rb +2 -0
- data/lib/carson/adapters/prompt.rb +2 -0
- data/lib/carson/cli.rb +415 -414
- data/lib/carson/config.rb +4 -3
- data/lib/carson/runtime/audit.rb +27 -27
- data/lib/carson/runtime/deliver.rb +7 -4
- data/lib/carson/runtime/govern.rb +27 -27
- data/lib/carson/runtime/housekeep.rb +15 -15
- data/lib/carson/runtime/local/hooks.rb +20 -0
- data/lib/carson/runtime/local/onboard.rb +17 -17
- data/lib/carson/runtime/local/prune.rb +13 -13
- data/lib/carson/runtime/local/sync.rb +6 -6
- data/lib/carson/runtime/local/template.rb +26 -25
- data/lib/carson/runtime/local/worktree.rb +26 -26
- data/lib/carson/runtime/local.rb +1 -0
- data/lib/carson/runtime/repos.rb +1 -1
- data/lib/carson/runtime/review/gate_support.rb +2 -2
- data/lib/carson/runtime/review/sweep_support.rb +2 -2
- data/lib/carson/runtime/review.rb +10 -8
- data/lib/carson/runtime/setup.rb +8 -6
- data/lib/carson/runtime/status.rb +20 -20
- data/lib/carson/runtime.rb +39 -25
- data/lib/carson/version.rb +1 -0
- data/lib/carson.rb +1 -0
- data/templates/.github/carson.md +7 -4
- 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: 8274b4268c0fc93eeb9323f2b9fd0d4e042001d1633ccde431afcb7f61448bae
|
|
4
|
+
data.tar.gz: cff9a441857c256c82bf0f395c92a29a2879c5f1da45c4de3ae1232803e0ea5f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 375300bdb2789594fa0a088c3f2d983a31aa492884b7fd399e76f0531885c191b81d855dd35c9d79a488cca6a3fdbdc3da35a9ac24d820901a34558d60bbc4f2
|
|
7
|
+
data.tar.gz: a5f3ddb10f668b7003578c62bdec28b95c0c584cfe5c93da38d50ffc01e4a03f4a91c31053d02a7a97af396baa247917ce3a5edf95608d801c9ce274024cde04
|
data/README.md
CHANGED
|
@@ -6,13 +6,13 @@
|
|
|
6
6
|
|
|
7
7
|
Named after the head of household in Downton Abbey, Carson is your repositories' autonomous governance runtime — you write the code, Carson manages everything else. From commit-time checks through PR triage, agent dispatch, merge, and cleanup, Carson runs the household with discipline and professional standards. Carson itself has no intelligence — it follows a deterministic decision tree. The intelligence comes from the coding agents it dispatches (Codex, Claude) to fix problems.
|
|
8
8
|
|
|
9
|
-
## The Problem
|
|
9
|
+
## The Problem
|
|
10
10
|
|
|
11
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
|
|
|
15
|
-
##
|
|
15
|
+
## What Carson Does
|
|
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
|
|
|
@@ -40,7 +40,7 @@ Carson orchestrates a closed governance loop across two layers:
|
|
|
40
40
|
|
|
41
41
|
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
42
|
|
|
43
|
-
|
|
43
|
+
### Principles
|
|
44
44
|
|
|
45
45
|
Carson is opinionated about governance. These are non-negotiable principles, not configurable defaults:
|
|
46
46
|
|
|
@@ -51,6 +51,14 @@ Carson is opinionated about governance. These are non-negotiable principles, not
|
|
|
51
51
|
|
|
52
52
|
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.
|
|
53
53
|
|
|
54
|
+
## When to Use Carson
|
|
55
|
+
|
|
56
|
+
- **You run coding agents across multiple repositories** and need a single command that triages every open PR, merges what's ready, dispatches agents to fix what's broken, and reports what needs your attention.
|
|
57
|
+
- **Your PR feedback gets buried.** Carson blocks merge until every reviewer comment is explicitly acknowledged — accepted, rejected, or deferred — so nothing is silently ignored.
|
|
58
|
+
- **CI breaks and nobody notices.** `carson audit` runs on every commit via managed hooks, and `carson govern` watches CI status across your portfolio continuously.
|
|
59
|
+
- **You onboard new repositories often** and want consistent hooks, templates, and governance from the first commit without manual setup.
|
|
60
|
+
- **You want agent-safe worktree management.** `carson worktree create` auto-syncs, branches, and isolates; `carson worktree remove` guards against unpushed work and active shells before cleanup.
|
|
61
|
+
|
|
54
62
|
## Quickstart
|
|
55
63
|
|
|
56
64
|
Prerequisites: Ruby `>= 3.4`, `git`, and `gem` in your PATH. `gh` (GitHub CLI) is recommended for full review governance features.
|
data/RELEASE.md
CHANGED
|
@@ -5,6 +5,20 @@ 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.21.0
|
|
9
|
+
|
|
10
|
+
### What changed
|
|
11
|
+
|
|
12
|
+
- **Command guard for governed repositories** — Carson now detects and blocks raw `git push` and `gh pr create/merge` commands in governed repos, redirecting agents to `carson deliver` instead. Three enforcement layers:
|
|
13
|
+
- **Pre-push hook** — blocks raw `git push` in governed repos. Carson sets `CARSON_PUSH=1` internally so its own pushes pass through.
|
|
14
|
+
- **Command guard script** — a Claude Code `PreToolUse` hook that intercepts `gh pr create` and `gh pr merge` Bash commands in governed repos.
|
|
15
|
+
- **Existing pre-push guard** — the main/master branch push block now uses the same `BLOCKED` message format with explicit recovery guidance.
|
|
16
|
+
- **`with_env_var` helper** — new Runtime utility for temporarily setting environment variables with guaranteed cleanup.
|
|
17
|
+
|
|
18
|
+
### UX improvement
|
|
19
|
+
|
|
20
|
+
- Agents that forget to use `carson deliver` are caught at push time or tool-call time with a clear message: what happened, why, and what to use instead. Born from scar: a preflight agent used raw `git push github main` and `gh pr create` in a governed repo, wasting work and requiring manual recovery (2026-03-09).
|
|
21
|
+
|
|
8
22
|
## 3.20.0
|
|
9
23
|
|
|
10
24
|
### What changed
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.
|
|
1
|
+
3.21.0
|
data/exe/carson
CHANGED
|
@@ -5,9 +5,9 @@ $LOAD_PATH.unshift( File.expand_path( "../lib", __dir__ ) )
|
|
|
5
5
|
require "carson"
|
|
6
6
|
|
|
7
7
|
exit Carson::CLI.start(
|
|
8
|
-
|
|
8
|
+
arguments: ARGV.dup,
|
|
9
9
|
repo_root: Dir.pwd,
|
|
10
10
|
tool_root: File.expand_path( "..", __dir__ ),
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
output: $stdout,
|
|
12
|
+
error: $stderr
|
|
13
13
|
)
|
data/hooks/command-guard
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Carson command guard — Claude Code PreToolUse hook.
|
|
3
|
+
#
|
|
4
|
+
# Blocks raw `gh pr create` and `gh pr merge` in Carson-governed repositories.
|
|
5
|
+
# Agents should use `carson deliver` instead.
|
|
6
|
+
#
|
|
7
|
+
# Claude Code sends JSON on stdin: {"tool_name": "Bash", "tool_input": {"command": "..."}}
|
|
8
|
+
# To block: print reason to stderr, exit 2.
|
|
9
|
+
# To allow: exit 0.
|
|
10
|
+
#
|
|
11
|
+
# Registration in ~/.claude/settings.json:
|
|
12
|
+
# "PreToolUse": [
|
|
13
|
+
# {
|
|
14
|
+
# "matcher": "Bash",
|
|
15
|
+
# "hooks": [
|
|
16
|
+
# {
|
|
17
|
+
# "type": "command",
|
|
18
|
+
# "command": "~/.carson/hooks/command-guard"
|
|
19
|
+
# }
|
|
20
|
+
# ]
|
|
21
|
+
# }
|
|
22
|
+
# ]
|
|
23
|
+
set -euo pipefail
|
|
24
|
+
|
|
25
|
+
# Read the tool call JSON from stdin.
|
|
26
|
+
input="$(cat)"
|
|
27
|
+
|
|
28
|
+
# Only inspect Bash tool calls.
|
|
29
|
+
tool_name="$(echo "$input" | jq -r '.tool_name // empty' 2>/dev/null)"
|
|
30
|
+
[ "$tool_name" = "Bash" ] || exit 0
|
|
31
|
+
|
|
32
|
+
command_text="$(echo "$input" | jq -r '.tool_input.command // empty' 2>/dev/null)"
|
|
33
|
+
[ -n "$command_text" ] || exit 0
|
|
34
|
+
|
|
35
|
+
# Check for gh pr commands that Carson replaces.
|
|
36
|
+
guarded_pattern='gh\s+pr\s+(create|merge)'
|
|
37
|
+
if ! echo "$command_text" | grep -qE "$guarded_pattern"; then
|
|
38
|
+
exit 0
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
# Check if the current directory is inside a governed repository.
|
|
42
|
+
config_file="${HOME}/.carson/config.json"
|
|
43
|
+
[ -f "$config_file" ] || exit 0
|
|
44
|
+
|
|
45
|
+
repo_root="$(git rev-parse --show-toplevel 2>/dev/null || echo "")"
|
|
46
|
+
[ -n "$repo_root" ] || exit 0
|
|
47
|
+
|
|
48
|
+
normalised="$(cd "$repo_root" && pwd -P)"
|
|
49
|
+
if ! grep -qF "\"$normalised\"" "$config_file" 2>/dev/null; then
|
|
50
|
+
exit 0
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
# This is a raw gh pr command in a governed repo — block it.
|
|
54
|
+
echo "BLOCKED: raw \`gh pr create/merge\` in a Carson-governed repository." >&2
|
|
55
|
+
echo "Use \`carson deliver\` instead — it handles push, PR, and merge with safety guards." >&2
|
|
56
|
+
exit 2
|
data/hooks/pre-push
CHANGED
|
@@ -1,23 +1,59 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
+
# Carson pre-push hook — enforces push policy in governed repositories.
|
|
3
|
+
#
|
|
4
|
+
# Guards:
|
|
5
|
+
# 1. Blocks direct push to main/master refs.
|
|
6
|
+
# 2. Blocks raw git push in governed repos — agents must use `carson deliver`.
|
|
7
|
+
# Carson sets CARSON_PUSH=1 internally so its own pushes pass through.
|
|
8
|
+
#
|
|
9
|
+
# Bypass (emergency only): git push --no-verify
|
|
2
10
|
set -euo pipefail
|
|
3
11
|
|
|
4
12
|
hooks_dir="$(cd "$(dirname "$0")" && pwd)"
|
|
5
13
|
style="$(cat "$hooks_dir/workflow_style" 2>/dev/null || echo "branch")"
|
|
6
14
|
[ "$style" = "trunk" ] && exit 0
|
|
7
15
|
|
|
16
|
+
# --- Guard 1: block pushes to main/master refs ---
|
|
17
|
+
|
|
8
18
|
remote_name="${1:-unknown}"
|
|
9
19
|
remote_url="${2:-unknown}"
|
|
10
20
|
has_commit_push=false
|
|
11
21
|
while read -r local_ref local_sha remote_ref remote_sha; do
|
|
12
22
|
case "$remote_ref" in
|
|
13
23
|
refs/heads/main|refs/heads/master)
|
|
14
|
-
echo "
|
|
24
|
+
echo "BLOCKED: direct push to ${remote_ref#refs/heads/} is not allowed." >&2
|
|
25
|
+
echo "Use \`carson deliver\` instead — it handles push, PR, and merge with safety guards." >&2
|
|
26
|
+
echo "Bypass (emergency only): git push --no-verify" >&2
|
|
15
27
|
exit 1
|
|
16
28
|
;;
|
|
17
29
|
esac
|
|
18
30
|
[[ "$local_sha" != "0000000000000000000000000000000000000000" ]] && has_commit_push=true
|
|
19
31
|
done
|
|
20
32
|
|
|
33
|
+
# --- Guard 2: block raw git push in governed repos ---
|
|
34
|
+
# Carson sets CARSON_PUSH=1 when pushing internally via `deliver`.
|
|
35
|
+
# If the variable is absent, this is a raw git push from an agent or human.
|
|
36
|
+
|
|
37
|
+
if [[ -z "${CARSON_PUSH:-}" ]]; then
|
|
38
|
+
config_file="${HOME}/.carson/config.json"
|
|
39
|
+
if [[ -f "$config_file" ]]; then
|
|
40
|
+
repo_root="$(git rev-parse --show-toplevel 2>/dev/null || echo "")"
|
|
41
|
+
if [[ -n "$repo_root" ]]; then
|
|
42
|
+
# Check if this repo appears in govern.repos.
|
|
43
|
+
# Uses a simple grep against the JSON — no jq dependency required.
|
|
44
|
+
normalised="$(cd "$repo_root" && pwd -P)"
|
|
45
|
+
if grep -qF "\"$normalised\"" "$config_file" 2>/dev/null; then
|
|
46
|
+
echo "BLOCKED: raw \`git push\` in a Carson-governed repository." >&2
|
|
47
|
+
echo "Use \`carson deliver\` instead — it handles push, PR, and merge with safety guards." >&2
|
|
48
|
+
echo "Bypass (emergency only): git push --no-verify" >&2
|
|
49
|
+
exit 1
|
|
50
|
+
fi
|
|
51
|
+
fi
|
|
52
|
+
fi
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
# --- Template sync on push ---
|
|
56
|
+
|
|
21
57
|
if $has_commit_push; then
|
|
22
58
|
if [[ -n "${CARSON_BIN:-}" ]]; then
|
|
23
59
|
ruby "$CARSON_BIN" template apply --push-prep || exit 1
|
data/lib/carson/adapters/git.rb
CHANGED