@bookedsolid/rea 0.11.0 → 0.13.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.
- package/.husky/commit-msg +32 -0
- package/.husky/pre-push +88 -13
- package/README.md +914 -550
- package/dist/cli/doctor.d.ts +12 -0
- package/dist/cli/doctor.js +152 -1
- package/dist/cli/hook.d.ts +7 -0
- package/dist/cli/hook.js +12 -1
- package/dist/cli/install/commit-msg.d.ts +34 -0
- package/dist/cli/install/commit-msg.js +60 -0
- package/dist/cli/install/pre-push.d.ts +32 -10
- package/dist/cli/install/pre-push.js +106 -27
- package/dist/hooks/push-gate/base.d.ts +48 -1
- package/dist/hooks/push-gate/base.js +121 -0
- package/dist/hooks/push-gate/codex-runner.d.ts +8 -0
- package/dist/hooks/push-gate/codex-runner.js +13 -0
- package/dist/hooks/push-gate/index.d.ts +8 -0
- package/dist/hooks/push-gate/index.js +162 -22
- package/dist/hooks/push-gate/policy.d.ts +39 -4
- package/dist/hooks/push-gate/policy.js +29 -4
- package/dist/policy/loader.d.ts +19 -0
- package/dist/policy/loader.js +11 -0
- package/dist/policy/types.d.ts +72 -2
- package/package.json +1 -1
- package/scripts/tarball-smoke.sh +7 -2
package/dist/policy/loader.d.ts
CHANGED
|
@@ -34,14 +34,29 @@ declare const PolicySchema: z.ZodObject<{
|
|
|
34
34
|
codex_required: z.ZodOptional<z.ZodBoolean>;
|
|
35
35
|
concerns_blocks: z.ZodOptional<z.ZodBoolean>;
|
|
36
36
|
timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
37
|
+
last_n_commits: z.ZodOptional<z.ZodNumber>;
|
|
38
|
+
/**
|
|
39
|
+
* Auto-narrow threshold (J / 0.13.0). When the resolved diff base is more
|
|
40
|
+
* than N commits away from HEAD, the gate auto-scopes to
|
|
41
|
+
* `last_n_commits` (or the 0.13 fallback default of 10) and emits a
|
|
42
|
+
* stderr warning. Default 30 when unset; explicit 0 disables auto-narrow
|
|
43
|
+
* entirely. Suppressed when the operator pinned `--last-n-commits`,
|
|
44
|
+
* `--base`, or `policy.review.last_n_commits` (those are explicit
|
|
45
|
+
* intent and auto-narrow stays out of the way).
|
|
46
|
+
*/
|
|
47
|
+
auto_narrow_threshold: z.ZodOptional<z.ZodNumber>;
|
|
37
48
|
}, "strict", z.ZodTypeAny, {
|
|
38
49
|
codex_required?: boolean | undefined;
|
|
39
50
|
concerns_blocks?: boolean | undefined;
|
|
40
51
|
timeout_ms?: number | undefined;
|
|
52
|
+
last_n_commits?: number | undefined;
|
|
53
|
+
auto_narrow_threshold?: number | undefined;
|
|
41
54
|
}, {
|
|
42
55
|
codex_required?: boolean | undefined;
|
|
43
56
|
concerns_blocks?: boolean | undefined;
|
|
44
57
|
timeout_ms?: number | undefined;
|
|
58
|
+
last_n_commits?: number | undefined;
|
|
59
|
+
auto_narrow_threshold?: number | undefined;
|
|
45
60
|
}>>;
|
|
46
61
|
redact: z.ZodOptional<z.ZodObject<{
|
|
47
62
|
match_timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
@@ -135,6 +150,8 @@ declare const PolicySchema: z.ZodObject<{
|
|
|
135
150
|
codex_required?: boolean | undefined;
|
|
136
151
|
concerns_blocks?: boolean | undefined;
|
|
137
152
|
timeout_ms?: number | undefined;
|
|
153
|
+
last_n_commits?: number | undefined;
|
|
154
|
+
auto_narrow_threshold?: number | undefined;
|
|
138
155
|
} | undefined;
|
|
139
156
|
redact?: {
|
|
140
157
|
match_timeout_ms?: number | undefined;
|
|
@@ -178,6 +195,8 @@ declare const PolicySchema: z.ZodObject<{
|
|
|
178
195
|
codex_required?: boolean | undefined;
|
|
179
196
|
concerns_blocks?: boolean | undefined;
|
|
180
197
|
timeout_ms?: number | undefined;
|
|
198
|
+
last_n_commits?: number | undefined;
|
|
199
|
+
auto_narrow_threshold?: number | undefined;
|
|
181
200
|
} | undefined;
|
|
182
201
|
redact?: {
|
|
183
202
|
match_timeout_ms?: number | undefined;
|
package/dist/policy/loader.js
CHANGED
|
@@ -27,6 +27,17 @@ const ReviewPolicySchema = z
|
|
|
27
27
|
codex_required: z.boolean().optional(),
|
|
28
28
|
concerns_blocks: z.boolean().optional(),
|
|
29
29
|
timeout_ms: z.number().int().positive().optional(),
|
|
30
|
+
last_n_commits: z.number().int().positive().optional(),
|
|
31
|
+
/**
|
|
32
|
+
* Auto-narrow threshold (J / 0.13.0). When the resolved diff base is more
|
|
33
|
+
* than N commits away from HEAD, the gate auto-scopes to
|
|
34
|
+
* `last_n_commits` (or the 0.13 fallback default of 10) and emits a
|
|
35
|
+
* stderr warning. Default 30 when unset; explicit 0 disables auto-narrow
|
|
36
|
+
* entirely. Suppressed when the operator pinned `--last-n-commits`,
|
|
37
|
+
* `--base`, or `policy.review.last_n_commits` (those are explicit
|
|
38
|
+
* intent and auto-narrow stays out of the way).
|
|
39
|
+
*/
|
|
40
|
+
auto_narrow_threshold: z.number().int().nonnegative().optional(),
|
|
30
41
|
})
|
|
31
42
|
.strict();
|
|
32
43
|
/**
|
package/dist/policy/types.d.ts
CHANGED
|
@@ -54,12 +54,82 @@ export interface ReviewPolicy {
|
|
|
54
54
|
/**
|
|
55
55
|
* Hard cap on the `codex exec review` subprocess in milliseconds. Exceeding
|
|
56
56
|
* this kills the subprocess and the gate returns exit 2 with a timeout
|
|
57
|
-
* error (audited). Default when unset is
|
|
58
|
-
*
|
|
57
|
+
* error (audited). Default when unset is 1_800_000 (30 minutes) as of
|
|
58
|
+
* 0.12.0 — raised from 10 minutes after the helixir migration session
|
|
59
|
+
* 2026-04-26 showed realistic feature-branch diffs routinely exceeded
|
|
60
|
+
* the previous default. Operators with explicit `timeout_ms:` in
|
|
61
|
+
* `.rea/policy.yaml` are unaffected.
|
|
59
62
|
*
|
|
60
63
|
* Positive integer only. The loader rejects zero/negative values.
|
|
61
64
|
*/
|
|
62
65
|
timeout_ms?: number;
|
|
66
|
+
/**
|
|
67
|
+
* When set, `rea hook push-gate` resolves the diff base to `HEAD~N`
|
|
68
|
+
* instead of the upstream → origin/HEAD ladder. Useful when a feature
|
|
69
|
+
* branch accumulates many commits and the full origin/main diff
|
|
70
|
+
* overwhelms the reviewer (the helixir 2026-04-26 case: 50+ commits
|
|
71
|
+
* relative to origin/main produced non-deterministic Codex verdicts and
|
|
72
|
+
* 10-minute timeouts).
|
|
73
|
+
*
|
|
74
|
+
* Precedence: explicit `--base <ref>` flag wins; then `--last-n-commits N`
|
|
75
|
+
* flag; then this policy key; then refspec-aware base resolution; then
|
|
76
|
+
* the upstream-ladder fallback. When `--base` AND
|
|
77
|
+
* `--last-n-commits`/`policy.last_n_commits` are both set, `--base`
|
|
78
|
+
* wins and a stderr warning is emitted.
|
|
79
|
+
*
|
|
80
|
+
* Resolution: `git rev-parse HEAD~N`. When `HEAD~N` is unreachable
|
|
81
|
+
* the resolver consults `git rev-parse --is-shallow-repository` to
|
|
82
|
+
* pick the right clamp:
|
|
83
|
+
*
|
|
84
|
+
* - FULL clone, branch shorter than N: clamps to the empty-tree
|
|
85
|
+
* sentinel so the root commit's changes are included
|
|
86
|
+
* (`git diff base..HEAD` excludes `base`, so diffing against
|
|
87
|
+
* `HEAD~K` would silently drop the root commit). Reports
|
|
88
|
+
* `last_n_commits: K+1` — every commit on the branch reviewed.
|
|
89
|
+
*
|
|
90
|
+
* - SHALLOW clone: clamps to `HEAD~K` (the deepest LOCALLY
|
|
91
|
+
* resolvable ancestor) since older history exists on the remote
|
|
92
|
+
* but isn't fetched. Using empty-tree here would balloon the
|
|
93
|
+
* review to every tracked file in the checkout. Reports
|
|
94
|
+
* `last_n_commits: K`. The K-th commit's content is excluded —
|
|
95
|
+
* accepted as the cost of the shallow clone.
|
|
96
|
+
*
|
|
97
|
+
* A stderr warning surfaces the requested-vs-clamped numbers in
|
|
98
|
+
* both cases. Audit metadata records `base_source: 'last-n-commits'`,
|
|
99
|
+
* `last_n_commits: <count actually reviewed>`, and
|
|
100
|
+
* `last_n_commits_requested: N` (only present when clamped).
|
|
101
|
+
*
|
|
102
|
+
* Positive integer. The loader rejects zero/negative values.
|
|
103
|
+
*/
|
|
104
|
+
last_n_commits?: number;
|
|
105
|
+
/**
|
|
106
|
+
* Auto-narrow threshold (J / 0.13.0). When the resolved diff base is more
|
|
107
|
+
* than N commits behind HEAD, the gate automatically scopes the review to
|
|
108
|
+
* the last 10 commits (or `last_n_commits` if pinned) and emits a stderr
|
|
109
|
+
* warning explaining the auto-narrow + how to override.
|
|
110
|
+
*
|
|
111
|
+
* Default `30` when unset. Explicit `0` disables auto-narrow entirely.
|
|
112
|
+
*
|
|
113
|
+
* Auto-narrow is SUPPRESSED when the operator already expressed explicit
|
|
114
|
+
* intent — any of these prevents auto-narrow from firing:
|
|
115
|
+
*
|
|
116
|
+
* - `--last-n-commits N` flag (the operator picked an exact window)
|
|
117
|
+
* - `--base <ref>` flag (the operator picked an exact base)
|
|
118
|
+
* - `policy.review.last_n_commits` (persistent narrow-window config)
|
|
119
|
+
*
|
|
120
|
+
* Audit metadata records `auto_narrowed: true|false` and
|
|
121
|
+
* `original_commit_count: N` on every reviewed event so operators can
|
|
122
|
+
* grep their audit log for narrowed reviews.
|
|
123
|
+
*
|
|
124
|
+
* Background: large feature branches (50+ commits relative to origin/main)
|
|
125
|
+
* routinely produced non-deterministic Codex verdicts, 10-minute timeouts,
|
|
126
|
+
* and the "thrashing" reported in helixir migration 2026-04-26. The 0.12.0
|
|
127
|
+
* `last_n_commits` knob fixed it for operators who knew to set it; J makes
|
|
128
|
+
* the protective default automatic.
|
|
129
|
+
*
|
|
130
|
+
* Non-negative integer. The loader rejects negative values.
|
|
131
|
+
*/
|
|
132
|
+
auto_narrow_threshold?: number;
|
|
63
133
|
}
|
|
64
134
|
/**
|
|
65
135
|
* User-supplied redaction pattern entry. Each pattern has a stable `name` used
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bookedsolid/rea",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Agentic governance layer for Claude Code — policy enforcement, hook-based safety gates, audit logging, and Codex-integrated adversarial review for AI-assisted projects",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Booked Solid Technology <oss@bookedsolid.tech> (https://bookedsolid.tech)",
|
package/scripts/tarball-smoke.sh
CHANGED
|
@@ -74,8 +74,13 @@ echo "[smoke] → $VERSION_OUT"
|
|
|
74
74
|
echo "[smoke] rea --help"
|
|
75
75
|
./node_modules/.bin/rea --help >/dev/null
|
|
76
76
|
|
|
77
|
-
echo "[smoke] rea init --yes --profile open-source"
|
|
78
|
-
|
|
77
|
+
echo "[smoke] rea init --yes --profile open-source-no-codex"
|
|
78
|
+
# 0.12.0+: doctor hard-fails when policy.review.codex_required: true and codex
|
|
79
|
+
# is not on PATH (fix C of the helixir migration unblocker — see PR #85). CI
|
|
80
|
+
# does not provision the codex CLI, so the smoke uses the -no-codex profile
|
|
81
|
+
# variant which defaults codex_required: false. The new doctor probe is
|
|
82
|
+
# covered by unit tests in src/cli/doctor.test.ts.
|
|
83
|
+
./node_modules/.bin/rea init --yes --profile open-source-no-codex
|
|
79
84
|
|
|
80
85
|
# Verify the installed layout matches what init claims it wrote.
|
|
81
86
|
for expected in .rea/policy.yaml .rea/registry.yaml .claude/settings.json CLAUDE.md .rea/install-manifest.json; do
|