@bookedsolid/rea 0.17.0 → 0.19.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 +10 -2
- package/agents/codex-adversarial.md +7 -2
- package/commands/codex-review.md +8 -4
- package/dist/cli/init.js +17 -0
- package/dist/cli/upgrade.js +16 -1
- package/dist/hooks/push-gate/codex-runner.js +18 -7
- package/dist/hooks/push-gate/index.js +80 -1
- package/dist/hooks/push-gate/policy.d.ts +17 -0
- package/dist/hooks/push-gate/policy.js +13 -0
- package/dist/hooks/push-gate/verdict-cache.d.ts +98 -0
- package/dist/hooks/push-gate/verdict-cache.js +190 -0
- package/dist/policy/loader.d.ts +21 -4
- package/dist/policy/loader.js +17 -4
- package/dist/policy/profiles.d.ts +34 -0
- package/dist/policy/profiles.js +15 -0
- package/dist/policy/types.d.ts +11 -0
- package/hooks/_lib/cmd-segments.sh +144 -20
- package/hooks/_lib/policy-read.sh +91 -3
- package/hooks/_lib/protected-paths.sh +78 -7
- package/hooks/attribution-advisory.sh +28 -3
- package/hooks/security-disclosure-gate.sh +17 -0
- package/package.json +1 -1
- package/profiles/bst-internal.yaml +8 -0
- package/scripts/postinstall.mjs +39 -1
|
@@ -58,13 +58,24 @@ fi
|
|
|
58
58
|
source "$(dirname "$0")/_lib/cmd-segments.sh"
|
|
59
59
|
|
|
60
60
|
# ── 6. Check if this is a relevant command ────────────────────────────────────
|
|
61
|
+
# 0.18.0 helix-020 / discord-ops Round 10 #2 fix (G4.A): use
|
|
62
|
+
# `any_segment_starts_with`, not `any_segment_matches`. The pre-fix
|
|
63
|
+
# matcher used the unanchored form, so a segment like
|
|
64
|
+
# gh pr edit --body "tracked: gh pr create earlier in the run"
|
|
65
|
+
# triggered IS_RELEVANT=1 because the substring `gh pr create` was
|
|
66
|
+
# anywhere in the segment. The downstream attribution check then
|
|
67
|
+
# scanned the body for the markdown-link / Co-Authored-By patterns,
|
|
68
|
+
# and ANY mention of those terms in the body's prose got blocked
|
|
69
|
+
# even though the actual command was a `gh pr edit` whose intent had
|
|
70
|
+
# nothing to do with structural attribution. The same anchoring fix
|
|
71
|
+
# `dangerous-bash-interceptor.sh` got in 0.16.3 F5 finally lands here.
|
|
61
72
|
IS_RELEVANT=0
|
|
62
73
|
|
|
63
|
-
if
|
|
74
|
+
if any_segment_starts_with "$CMD" 'gh[[:space:]]+pr[[:space:]]+(create|edit)'; then
|
|
64
75
|
IS_RELEVANT=1
|
|
65
76
|
fi
|
|
66
77
|
|
|
67
|
-
if
|
|
78
|
+
if any_segment_starts_with "$CMD" 'git[[:space:]]+commit'; then
|
|
68
79
|
IS_RELEVANT=1
|
|
69
80
|
fi
|
|
70
81
|
|
|
@@ -77,7 +88,21 @@ fi
|
|
|
77
88
|
FOUND=0
|
|
78
89
|
|
|
79
90
|
# Co-Authored-By with noreply@ email
|
|
80
|
-
|
|
91
|
+
# 0.18.0 helix-020 / discord-ops Round 10 #3 fix (G4.B): exclude
|
|
92
|
+
# GitHub's legitimate `<user>@users.noreply.github.com` collaborator
|
|
93
|
+
# footers from the noreply match. Pre-fix the regex `Co-Authored-By:.*noreply@`
|
|
94
|
+
# matched both AI-tool noreply addresses (anthropic.com, openai.com,
|
|
95
|
+
# github-copilot, etc.) AND GitHub's per-user noreply form, blocking
|
|
96
|
+
# legitimate human collaborator credits. The new regex requires
|
|
97
|
+
# `noreply@` to be followed by something that ISN'T `users.noreply.github.com`
|
|
98
|
+
# — covered via a negative-lookahead simulation: match `noreply@` then
|
|
99
|
+
# either end-of-line, whitespace, `>`, or a domain that does NOT begin
|
|
100
|
+
# with `users.noreply.github.com`. Posix ERE has no lookarounds, so we
|
|
101
|
+
# enumerate the allowed-prefix shapes explicitly. The "AI names" branch
|
|
102
|
+
# below catches Co-Authored-By with named tools regardless of the email
|
|
103
|
+
# domain, so dropping `users.noreply.github.com` from the noreply
|
|
104
|
+
# pattern only relaxes the check for human collaborators — never for AI.
|
|
105
|
+
if any_segment_matches "$CMD" 'Co-Authored-By:.*noreply@(anthropic\.com|openai\.com|github-copilot|github\.com|claude\.ai|chatgpt\.com|googlemail\.com|google\.com|cursor\.com|codeium\.com|tabnine\.com|amazon\.com|amazonaws\.com|amazon-q\.amazonaws\.com|cody\.dev|sourcegraph\.com)'; then
|
|
81
106
|
FOUND=1
|
|
82
107
|
fi
|
|
83
108
|
|
|
@@ -171,6 +171,23 @@ _extract_body_file_paths() {
|
|
|
171
171
|
while (i <= n) {
|
|
172
172
|
ch = substr(line, i, 1)
|
|
173
173
|
if (mode == 0) {
|
|
174
|
+
# 0.18.0 helix-020 G3.B fix: in plain (unquoted) mode,
|
|
175
|
+
# `\X` (any character X) is the POSIX shell escape for
|
|
176
|
+
# the literal character X — most commonly a space in
|
|
177
|
+
# paths like `path\ with\ spaces.md`. Pre-fix the
|
|
178
|
+
# tokenizer treated the `\` as an ordinary character and
|
|
179
|
+
# truncated at the following space, dropping the rest of
|
|
180
|
+
# the path. We now consume the backslash and emit the
|
|
181
|
+
# following byte as a literal part of the current token.
|
|
182
|
+
# `\<eol>` (line-continuation) is left intact — emit the
|
|
183
|
+
# `\` and let the splitter flow into the next record on
|
|
184
|
+
# the assumption that the caller already joined the line.
|
|
185
|
+
if (ch == "\\" && i < n) {
|
|
186
|
+
nxt = substr(line, i + 1, 1)
|
|
187
|
+
tok = tok nxt
|
|
188
|
+
i += 2
|
|
189
|
+
continue
|
|
190
|
+
}
|
|
174
191
|
if (ch == " " || ch == "\t") {
|
|
175
192
|
if (tok != "") { emit_token(tok); tok = "" }
|
|
176
193
|
i++; continue
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bookedsolid/rea",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.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)",
|
|
@@ -28,3 +28,11 @@ context_protection:
|
|
|
28
28
|
- pnpm run test
|
|
29
29
|
- pnpm run lint
|
|
30
30
|
max_bash_output_lines: 100
|
|
31
|
+
# 0.18.1+ helixir #9: enable audit log rotation by default for
|
|
32
|
+
# bst-internal. Long sessions accumulate 100s of push_gate.reviewed
|
|
33
|
+
# entries; without rotation the audit file grows unbounded. The empty
|
|
34
|
+
# `rotation: {}` block opts in to the documented defaults — 50 MiB
|
|
35
|
+
# OR 30 days, whichever arrives first. Rotation marker preserves the
|
|
36
|
+
# hash chain across the boundary.
|
|
37
|
+
audit:
|
|
38
|
+
rotation: {}
|
package/scripts/postinstall.mjs
CHANGED
|
@@ -116,13 +116,51 @@ try {
|
|
|
116
116
|
|
|
117
117
|
if (manifestVersion === installedVersion) process.exit(0);
|
|
118
118
|
|
|
119
|
-
//
|
|
119
|
+
// 0.18.1+ helixir #3: opt-in auto-upgrade. Pre-fix the drift was
|
|
120
|
+
// detected and a "run rea upgrade" nudge printed, but consumers had
|
|
121
|
+
// to run the upgrade by hand on every install. With
|
|
122
|
+
// `REA_AUTO_UPGRADE=1` (or `--yes` semantics inferred from a
|
|
123
|
+
// package.json field), the postinstall runs `rea upgrade --yes`
|
|
124
|
+
// for them. Defaults to PRINT-ONLY for back-compat — silent
|
|
125
|
+
// mutation of the consumer's `.claude/` / `.husky/` on every
|
|
126
|
+
// install would surprise existing users.
|
|
127
|
+
const autoUpgrade =
|
|
128
|
+
process.env.REA_AUTO_UPGRADE === '1' ||
|
|
129
|
+
process.env.REA_AUTO_UPGRADE === 'true';
|
|
130
|
+
|
|
131
|
+
if (autoUpgrade) {
|
|
132
|
+
// Best-effort: invoke `rea upgrade --yes`. Failures fall through to
|
|
133
|
+
// the print path so the consumer still sees the drift advisory.
|
|
134
|
+
try {
|
|
135
|
+
const reaCli = path.join(consumerRoot, 'node_modules', '.bin', 'rea');
|
|
136
|
+
if (fs.existsSync(reaCli)) {
|
|
137
|
+
const { spawnSync } = await import('node:child_process');
|
|
138
|
+
const res = spawnSync(reaCli, ['upgrade', '--yes'], {
|
|
139
|
+
cwd: consumerRoot,
|
|
140
|
+
stdio: 'inherit',
|
|
141
|
+
env: process.env,
|
|
142
|
+
});
|
|
143
|
+
if (res.status === 0) {
|
|
144
|
+
NOTE([
|
|
145
|
+
`@bookedsolid/rea: auto-upgraded from v${manifestVersion} to v${installedVersion}.`,
|
|
146
|
+
`(REA_AUTO_UPGRADE=1; set REA_AUTO_UPGRADE=0 to opt out.)`,
|
|
147
|
+
]);
|
|
148
|
+
process.exit(0);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
} catch {
|
|
152
|
+
// Fall through to the manual-nudge path below.
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Package-manager-agnostic nudge. Any of `npx rea upgrade`,
|
|
120
157
|
// `pnpm exec rea upgrade`, or `yarn rea upgrade` works; recommending `npx`
|
|
121
158
|
// covers the widest audience without privileging pnpm in error output.
|
|
122
159
|
NOTE([
|
|
123
160
|
`@bookedsolid/rea v${installedVersion} installed; manifest at v${manifestVersion}.`,
|
|
124
161
|
`Run \`npx rea upgrade\` to sync .claude/, .husky/, and managed fragments.`,
|
|
125
162
|
`(Or \`npx rea doctor --drift\` to preview without changes.)`,
|
|
163
|
+
`(Set \`REA_AUTO_UPGRADE=1\` to auto-run upgrade on future installs.)`,
|
|
126
164
|
]);
|
|
127
165
|
} catch {
|
|
128
166
|
// Any uncaught failure → silent success. Never break the consumer's install.
|