@prism-d1/cli 1.1.2 → 1.2.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.
Files changed (160) hide show
  1. package/dist/assets/github-workflows/prism-agent-eval.yml +2 -1
  2. package/dist/assets/github-workflows/prism-eval-gate-kiro.yml +11 -1
  3. package/dist/assets/gitlab-workflows/prism-eval-gate.yml +8 -0
  4. package/dist/assets/infra/lib/constructs/otel-collector-construct.ts +96 -0
  5. package/dist/assets/infra/lib/dashboard-stack.ts +27 -0
  6. package/dist/assets/infra/lib/lambda/otel-receiver.ts +278 -8
  7. package/dist/assets/infra/lib/lambda/pricing/litellm-snapshot.json +3769 -0
  8. package/dist/assets/infra/lib/lambda/pricing/price-source.ts +56 -0
  9. package/dist/assets/infra/lib/lambda/pricing/price-table.ts +240 -0
  10. package/dist/assets/infra/lib/lambda/pricing/prices-key.ts +6 -0
  11. package/dist/assets/infra/lib/lambda/pricing/reprice.ts +108 -0
  12. package/dist/assets/infra/lib/lambda/pricing-refresh.ts +352 -0
  13. package/dist/assets/infra/lib/lambda/velocity-widget.ts +124 -1
  14. package/dist/assets/infra/package.json +4 -1
  15. package/dist/assets/metric-hooks/prepare-commit-msg +3 -1
  16. package/dist/src/codewatch/config.d.ts +17 -0
  17. package/dist/src/codewatch/config.d.ts.map +1 -0
  18. package/dist/src/codewatch/config.js +40 -0
  19. package/dist/src/codewatch/config.js.map +1 -0
  20. package/dist/src/codewatch/gitleaks.d.ts +49 -0
  21. package/dist/src/codewatch/gitleaks.d.ts.map +1 -0
  22. package/dist/src/codewatch/gitleaks.js +160 -0
  23. package/dist/src/codewatch/gitleaks.js.map +1 -0
  24. package/dist/src/codewatch/globalHooks.d.ts +52 -0
  25. package/dist/src/codewatch/globalHooks.d.ts.map +1 -0
  26. package/dist/src/codewatch/globalHooks.js +235 -0
  27. package/dist/src/codewatch/globalHooks.js.map +1 -0
  28. package/dist/src/codewatch/hooks.d.ts +38 -0
  29. package/dist/src/codewatch/hooks.d.ts.map +1 -0
  30. package/dist/src/codewatch/hooks.js +176 -0
  31. package/dist/src/codewatch/hooks.js.map +1 -0
  32. package/dist/src/codewatch/prepush.d.ts +37 -0
  33. package/dist/src/codewatch/prepush.d.ts.map +1 -0
  34. package/dist/src/codewatch/prepush.js +231 -0
  35. package/dist/src/codewatch/prepush.js.map +1 -0
  36. package/dist/src/codewatch/results.d.ts +90 -0
  37. package/dist/src/codewatch/results.d.ts.map +1 -0
  38. package/dist/src/codewatch/results.js +121 -0
  39. package/dist/src/codewatch/results.js.map +1 -0
  40. package/dist/src/codewatch/reviewers/claude.d.ts +9 -0
  41. package/dist/src/codewatch/reviewers/claude.d.ts.map +1 -0
  42. package/dist/src/codewatch/reviewers/claude.js +48 -0
  43. package/dist/src/codewatch/reviewers/claude.js.map +1 -0
  44. package/dist/src/codewatch/reviewers/index.d.ts +39 -0
  45. package/dist/src/codewatch/reviewers/index.d.ts.map +1 -0
  46. package/dist/src/codewatch/reviewers/index.js +97 -0
  47. package/dist/src/codewatch/reviewers/index.js.map +1 -0
  48. package/dist/src/codewatch/reviewers/kiro.d.ts +14 -0
  49. package/dist/src/codewatch/reviewers/kiro.d.ts.map +1 -0
  50. package/dist/src/codewatch/reviewers/kiro.js +32 -0
  51. package/dist/src/codewatch/reviewers/kiro.js.map +1 -0
  52. package/dist/src/codewatch/reviewers/types.d.ts +56 -0
  53. package/dist/src/codewatch/reviewers/types.d.ts.map +1 -0
  54. package/dist/src/codewatch/reviewers/types.js +91 -0
  55. package/dist/src/codewatch/reviewers/types.js.map +1 -0
  56. package/dist/src/codewatch/rules.d.ts +12 -0
  57. package/dist/src/codewatch/rules.d.ts.map +1 -0
  58. package/dist/src/codewatch/rules.js +27 -0
  59. package/dist/src/codewatch/rules.js.map +1 -0
  60. package/dist/src/commands/_top/dashboard.d.ts +17 -0
  61. package/dist/src/commands/_top/dashboard.d.ts.map +1 -0
  62. package/dist/src/commands/_top/dashboard.js +76 -0
  63. package/dist/src/commands/_top/dashboard.js.map +1 -0
  64. package/dist/src/commands/bedrock-protection/scan-account.d.ts.map +1 -1
  65. package/dist/src/commands/bedrock-protection/scan-account.js +2 -1
  66. package/dist/src/commands/bedrock-protection/scan-account.js.map +1 -1
  67. package/dist/src/commands/bedrock-protection/scan-org.d.ts.map +1 -1
  68. package/dist/src/commands/bedrock-protection/scan-org.js +16 -4
  69. package/dist/src/commands/bedrock-protection/scan-org.js.map +1 -1
  70. package/dist/src/commands/bootstrapper/install-eval-harness.d.ts.map +1 -1
  71. package/dist/src/commands/bootstrapper/install-eval-harness.js +15 -48
  72. package/dist/src/commands/bootstrapper/install-eval-harness.js.map +1 -1
  73. package/dist/src/commands/bootstrapper/install-git-hooks.d.ts +13 -0
  74. package/dist/src/commands/bootstrapper/install-git-hooks.d.ts.map +1 -1
  75. package/dist/src/commands/bootstrapper/install-git-hooks.js +28 -147
  76. package/dist/src/commands/bootstrapper/install-git-hooks.js.map +1 -1
  77. package/dist/src/commands/bootstrapper/setup-otel-sync.d.ts.map +1 -1
  78. package/dist/src/commands/bootstrapper/setup-otel-sync.js +5 -39
  79. package/dist/src/commands/bootstrapper/setup-otel-sync.js.map +1 -1
  80. package/dist/src/commands/codewatch/pre-commit.d.ts +7 -0
  81. package/dist/src/commands/codewatch/pre-commit.d.ts.map +1 -0
  82. package/dist/src/commands/codewatch/pre-commit.js +30 -0
  83. package/dist/src/commands/codewatch/pre-commit.js.map +1 -0
  84. package/dist/src/commands/codewatch/pre-push.d.ts +16 -0
  85. package/dist/src/commands/codewatch/pre-push.d.ts.map +1 -0
  86. package/dist/src/commands/codewatch/pre-push.js +32 -0
  87. package/dist/src/commands/codewatch/pre-push.js.map +1 -0
  88. package/dist/src/commands/codewatch/report.d.ts +22 -0
  89. package/dist/src/commands/codewatch/report.d.ts.map +1 -0
  90. package/dist/src/commands/codewatch/report.js +64 -0
  91. package/dist/src/commands/codewatch/report.js.map +1 -0
  92. package/dist/src/commands/enable/codewatch.d.ts +15 -0
  93. package/dist/src/commands/enable/codewatch.d.ts.map +1 -0
  94. package/dist/src/commands/enable/codewatch.js +186 -0
  95. package/dist/src/commands/enable/codewatch.js.map +1 -0
  96. package/dist/src/commands/git/claude-session-context.d.ts.map +1 -1
  97. package/dist/src/commands/git/claude-session-context.js +2 -1
  98. package/dist/src/commands/git/claude-session-context.js.map +1 -1
  99. package/dist/src/commands/git/commit-trailers.js +1 -1
  100. package/dist/src/commands/git/commit-trailers.js.map +1 -1
  101. package/dist/src/commands/workshop/verify-setup.d.ts.map +1 -1
  102. package/dist/src/commands/workshop/verify-setup.js +5 -3
  103. package/dist/src/commands/workshop/verify-setup.js.map +1 -1
  104. package/dist/src/dashboard/codewatch.d.ts +106 -0
  105. package/dist/src/dashboard/codewatch.d.ts.map +1 -0
  106. package/dist/src/dashboard/codewatch.js +119 -0
  107. package/dist/src/dashboard/codewatch.js.map +1 -0
  108. package/dist/src/dashboard/commits.d.ts +96 -0
  109. package/dist/src/dashboard/commits.d.ts.map +1 -0
  110. package/dist/src/dashboard/commits.js +207 -0
  111. package/dist/src/dashboard/commits.js.map +1 -0
  112. package/dist/src/dashboard/page.d.ts +10 -0
  113. package/dist/src/dashboard/page.d.ts.map +1 -0
  114. package/dist/src/dashboard/page.js +315 -0
  115. package/dist/src/dashboard/page.js.map +1 -0
  116. package/dist/src/dashboard/payload.d.ts +111 -0
  117. package/dist/src/dashboard/payload.d.ts.map +1 -0
  118. package/dist/src/dashboard/payload.js +93 -0
  119. package/dist/src/dashboard/payload.js.map +1 -0
  120. package/dist/src/dashboard/report.d.ts +99 -0
  121. package/dist/src/dashboard/report.d.ts.map +1 -0
  122. package/dist/src/dashboard/report.js +300 -0
  123. package/dist/src/dashboard/report.js.map +1 -0
  124. package/dist/src/dashboard/repos.d.ts +58 -0
  125. package/dist/src/dashboard/repos.d.ts.map +1 -0
  126. package/dist/src/dashboard/repos.js +111 -0
  127. package/dist/src/dashboard/repos.js.map +1 -0
  128. package/dist/src/dashboard/server.d.ts +52 -0
  129. package/dist/src/dashboard/server.d.ts.map +1 -0
  130. package/dist/src/dashboard/server.js +163 -0
  131. package/dist/src/dashboard/server.js.map +1 -0
  132. package/dist/src/dashboard/setup.d.ts +52 -0
  133. package/dist/src/dashboard/setup.d.ts.map +1 -0
  134. package/dist/src/dashboard/setup.js +129 -0
  135. package/dist/src/dashboard/setup.js.map +1 -0
  136. package/dist/src/dashboard/usage.d.ts +43 -0
  137. package/dist/src/dashboard/usage.d.ts.map +1 -0
  138. package/dist/src/dashboard/usage.js +88 -0
  139. package/dist/src/dashboard/usage.js.map +1 -0
  140. package/dist/src/index.d.ts +1 -0
  141. package/dist/src/index.d.ts.map +1 -1
  142. package/dist/src/index.js +40 -1
  143. package/dist/src/index.js.map +1 -1
  144. package/dist/src/utils/audit-bedrock.d.ts +1 -0
  145. package/dist/src/utils/audit-bedrock.d.ts.map +1 -1
  146. package/dist/src/utils/audit-bedrock.js +133 -0
  147. package/dist/src/utils/audit-bedrock.js.map +1 -1
  148. package/dist/src/utils/audit-org.d.ts +1 -0
  149. package/dist/src/utils/audit-org.d.ts.map +1 -1
  150. package/dist/src/utils/audit-org.js +155 -0
  151. package/dist/src/utils/audit-org.js.map +1 -1
  152. package/dist/src/utils/otel-sync-schedule.d.ts +22 -0
  153. package/dist/src/utils/otel-sync-schedule.d.ts.map +1 -0
  154. package/dist/src/utils/otel-sync-schedule.js +68 -0
  155. package/dist/src/utils/otel-sync-schedule.js.map +1 -0
  156. package/dist/src/utils/tool-check.d.ts +14 -0
  157. package/dist/src/utils/tool-check.d.ts.map +1 -0
  158. package/dist/src/utils/tool-check.js +42 -0
  159. package/dist/src/utils/tool-check.js.map +1 -0
  160. package/package.json +3 -2
@@ -0,0 +1,176 @@
1
+ /**
2
+ * Git hook install/uninstall for `prism-cli enable codewatch`.
3
+ *
4
+ * Backup convention matches the old install-git-hooks: a foreign hook at
5
+ * `<hook>` is moved aside to `<hook>.pre-prism`. Unlike the old installer, the
6
+ * PRISM hook then CALLS the backed-up hook first, so installing does not turn
7
+ * off a team's existing hook, and uninstall moves the backup back.
8
+ */
9
+ import { chmodSync, copyFileSync, existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs';
10
+ import { isAbsolute, resolve } from 'node:path';
11
+ import { run } from '../utils/exec.js';
12
+ export const HOOK_MARKER = '# prism-cli enable codewatch';
13
+ /**
14
+ * Markers of earlier hook generations that are still OURS: hook files written
15
+ * before the rename to codewatch carry the old marker and call the removed
16
+ * `prism-cli git pre-commit` / `git pre-push`. Recognising them means install
17
+ * overwrites them in place (rather than backing them up and chaining a hook
18
+ * that can no longer run) and uninstall removes them.
19
+ */
20
+ const OWN_MARKERS = [HOOK_MARKER, '# prism-cli enable security'];
21
+ /** The retired trailer hook is identified the way install-git-hooks identified it. */
22
+ const LEGACY_MARKER = 'AI-Origin';
23
+ export const BACKUP_SUFFIX = '.pre-prism';
24
+ export const MANAGED_HOOKS = ['pre-commit', 'pre-push'];
25
+ /**
26
+ * pre-commit: blocks on a gitleaks finding.
27
+ *
28
+ * Prefers `prism-cli codewatch pre-commit` (writes a result file). Without prism-cli
29
+ * on PATH it still runs gitleaks directly, so the block does not depend on the
30
+ * CLI being installed globally.
31
+ */
32
+ export const PRE_COMMIT_SCRIPT = `#!/bin/sh
33
+ ${HOOK_MARKER} -- pre-commit secret scan (blocks on a finding).
34
+ # Managed file. Remove with: prism-cli enable codewatch --uninstall
35
+ HOOK_DIR=$(dirname "$0")
36
+ if [ -x "$HOOK_DIR/pre-commit${BACKUP_SUFFIX}" ]; then
37
+ "$HOOK_DIR/pre-commit${BACKUP_SUFFIX}" "$@" || exit $?
38
+ fi
39
+ # Probe first: an older prism-cli on PATH has no "codewatch pre-commit" and would
40
+ # fail every commit with "unknown command". Its --help exits 0 with the root help,
41
+ # so the probe checks that the subcommand's own usage line is printed.
42
+ if command -v prism-cli >/dev/null 2>&1 && prism-cli codewatch pre-commit --help 2>/dev/null | grep -q 'codewatch pre-commit'; then
43
+ exec prism-cli codewatch pre-commit
44
+ fi
45
+ if command -v gitleaks >/dev/null 2>&1; then
46
+ set -- protect --staged --redact --no-banner --exit-code=1
47
+ [ -f .gitleaks.toml ] && set -- "$@" --config=.gitleaks.toml
48
+ [ -f .prism/gitleaks-baseline.json ] && set -- "$@" --baseline-path=.prism/gitleaks-baseline.json
49
+ if ! gitleaks "$@"; then
50
+ echo "prism: gitleaks flagged the staged changes; commit blocked." >&2
51
+ echo "prism: fix it, allowlist a false positive in .gitleaks.toml, or bypass once with --no-verify." >&2
52
+ exit 1
53
+ fi
54
+ exit 0
55
+ fi
56
+ echo "prism: neither prism-cli nor gitleaks is on PATH; secret scan skipped." >&2
57
+ exit 0
58
+ `;
59
+ /**
60
+ * pre-push: report-only review. Exits 0 no matter what the review does.
61
+ * stdin (the pushed refs) is buffered so both a chained hook and prism-cli see it.
62
+ */
63
+ export const PRE_PUSH_SCRIPT = `#!/bin/sh
64
+ ${HOOK_MARKER} -- pre-push local eval review (report only, never blocks).
65
+ # Managed file. Remove with: prism-cli enable codewatch --uninstall
66
+ HOOK_DIR=$(dirname "$0")
67
+ PRISM_PUSH_INPUT=$(cat)
68
+ if [ -x "$HOOK_DIR/pre-push${BACKUP_SUFFIX}" ]; then
69
+ printf '%s\\n' "$PRISM_PUSH_INPUT" | "$HOOK_DIR/pre-push${BACKUP_SUFFIX}" "$@" || exit $?
70
+ fi
71
+ if command -v prism-cli >/dev/null 2>&1 && prism-cli codewatch pre-push --help 2>/dev/null | grep -q 'codewatch pre-push'; then
72
+ printf '%s\\n' "$PRISM_PUSH_INPUT" | prism-cli codewatch pre-push --remote "\${1:-}" || true
73
+ else
74
+ echo "prism: prism-cli (with 'codewatch pre-push') is not on PATH; local review skipped (report only)." >&2
75
+ fi
76
+ exit 0
77
+ `;
78
+ export const HOOK_SCRIPTS = {
79
+ 'pre-commit': PRE_COMMIT_SCRIPT,
80
+ 'pre-push': PRE_PUSH_SCRIPT,
81
+ };
82
+ /**
83
+ * Hooks directory as git resolves it: honours core.hooksPath and works in a
84
+ * linked worktree, where `.git` is a file and `.git/hooks` does not exist.
85
+ */
86
+ export function resolveHooksDir(gitRoot) {
87
+ const abs = run('git', ['rev-parse', '--path-format=absolute', '--git-path', 'hooks']);
88
+ if (abs.ok && abs.stdout && isAbsolute(abs.stdout))
89
+ return abs.stdout;
90
+ const rel = run('git', ['rev-parse', '--git-path', 'hooks']);
91
+ return rel.ok && rel.stdout ? resolve(process.cwd(), rel.stdout) : resolve(gitRoot, '.git/hooks');
92
+ }
93
+ function isOurs(path, markers = OWN_MARKERS) {
94
+ try {
95
+ const text = readFileSync(path, 'utf8');
96
+ return markers.some((m) => text.includes(m));
97
+ }
98
+ catch {
99
+ return false;
100
+ }
101
+ }
102
+ export function installHooks(hooksDir) {
103
+ mkdirSync(hooksDir, { recursive: true });
104
+ const changes = [];
105
+ for (const hook of MANAGED_HOOKS) {
106
+ const target = resolve(hooksDir, hook);
107
+ const backup = target + BACKUP_SUFFIX;
108
+ if (existsSync(target) && !isOurs(target)) {
109
+ if (existsSync(backup)) {
110
+ // Never overwrite an earlier backup: that would destroy the original.
111
+ const stamped = `${backup}.${Date.now()}`;
112
+ renameSync(target, stamped);
113
+ changes.push({ hook, action: `existing hook moved to ${stamped} (a ${hook}${BACKUP_SUFFIX} backup already existed)` });
114
+ }
115
+ else {
116
+ renameSync(target, backup);
117
+ changes.push({ hook, action: `existing hook backed up to ${hook}${BACKUP_SUFFIX} and chained` });
118
+ }
119
+ }
120
+ writeFileSync(target, HOOK_SCRIPTS[hook]);
121
+ chmodSync(target, 0o755);
122
+ changes.push({ hook, action: 'installed' });
123
+ }
124
+ return changes;
125
+ }
126
+ export function uninstallHooks(hooksDir) {
127
+ const changes = [];
128
+ for (const hook of MANAGED_HOOKS) {
129
+ const target = resolve(hooksDir, hook);
130
+ const backup = target + BACKUP_SUFFIX;
131
+ if (!existsSync(target) || !isOurs(target)) {
132
+ changes.push({ hook, action: existsSync(target) ? 'left alone (not installed by prism-cli)' : 'not installed' });
133
+ continue;
134
+ }
135
+ rmSync(target, { force: true });
136
+ if (existsSync(backup)) {
137
+ renameSync(backup, target);
138
+ changes.push({ hook, action: `removed; restored previous hook from ${hook}${BACKUP_SUFFIX}` });
139
+ }
140
+ else {
141
+ changes.push({ hook, action: 'removed' });
142
+ }
143
+ }
144
+ return changes;
145
+ }
146
+ /**
147
+ * Removes the retired prepare-commit-msg trailer hook (commit trailers and the
148
+ * token tracker are no longer used) and restores whatever it had backed up.
149
+ * Returns a description, or null when there was nothing to retire.
150
+ */
151
+ export function retireLegacyCommitMsgHook(hooksDir) {
152
+ const target = resolve(hooksDir, 'prepare-commit-msg');
153
+ if (!existsSync(target) || !isOurs(target, [LEGACY_MARKER]))
154
+ return null;
155
+ const backup = target + BACKUP_SUFFIX;
156
+ rmSync(target, { force: true });
157
+ if (existsSync(backup)) {
158
+ copyFileSync(backup, target);
159
+ chmodSync(target, 0o755);
160
+ rmSync(backup, { force: true });
161
+ return 'removed retired prepare-commit-msg trailer hook; restored the hook it had backed up';
162
+ }
163
+ return 'removed retired prepare-commit-msg trailer hook';
164
+ }
165
+ /** Adds `.prism/results/` to .gitignore unless an entry already covers it. */
166
+ export function ensureResultsIgnored(gitRoot) {
167
+ const gi = resolve(gitRoot, '.gitignore');
168
+ const content = existsSync(gi) ? readFileSync(gi, 'utf8') : '';
169
+ const lines = content.split('\n').map((l) => l.trim());
170
+ if (lines.some((l) => ['.prism', '.prism/', '/.prism', '/.prism/', '.prism/results', '.prism/results/', '/.prism/results/'].includes(l)))
171
+ return false;
172
+ const prefix = content && !content.endsWith('\n') ? '\n' : '';
173
+ writeFileSync(gi, `${content}${prefix}# prism-cli local gate results (per developer, not shared)\n.prism/results/\n`);
174
+ return true;
175
+ }
176
+ //# sourceMappingURL=hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../../src/codewatch/hooks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /** Larger diffs are truncated before review; the result notes it. */
2
+ export declare const MAX_DIFF_CHARS = 200000;
3
+ export interface PushRef {
4
+ localRef: string;
5
+ localSha: string;
6
+ remoteRef: string;
7
+ remoteSha: string;
8
+ }
9
+ /** Parses git's pre-push stdin: `<local ref> <local sha> <remote ref> <remote sha>` per line. */
10
+ export declare function parsePushInput(stdin: string): PushRef[];
11
+ /**
12
+ * Base for the review range. The branch's upstream if it has one, else what
13
+ * the remote already has for this ref, else the remote's default branch (a
14
+ * first push of a new branch). The diff is merge-base based (`base...sha`).
15
+ */
16
+ export declare function resolveBase(ref: PushRef, remote: string | null): {
17
+ base: string | null;
18
+ upstream: string | null;
19
+ };
20
+ /**
21
+ * Commits in the range whose tree has no pre-commit secrets result: committed
22
+ * with `--no-verify`, or produced without a commit hook (rebase, cherry-pick,
23
+ * merge). Recorded as `skipped` results; this is a heuristic, and the reason
24
+ * says so.
25
+ */
26
+ export declare function recordUnscannedCommits(repoRoot: string, base: string | null, sha: string, branch: string | null, upstream: string | null): number;
27
+ export interface PrePushOptions {
28
+ repoRoot: string;
29
+ stdin: string;
30
+ remote: string | null;
31
+ /** Injected for tests. */
32
+ pathEnv?: string;
33
+ log?: (line: string) => void;
34
+ }
35
+ /** Entry point for the hook. Always returns 0. */
36
+ export declare function runPrePush(opts: PrePushOptions): number;
37
+ //# sourceMappingURL=prepush.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prepush.d.ts","sourceRoot":"","sources":["../../../src/codewatch/prepush.ts"],"names":[],"mappings":"AAoBA,qEAAqE;AACrE,eAAO,MAAM,cAAc,SAAU,CAAC;AAMtC,MAAM,WAAW,OAAO;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,iGAAiG;AACjG,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,EAAE,CAUvD;AAOD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG;IAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAoBjH;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAiCjJ;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,0BAA0B;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9B;AAkGD,kDAAkD;AAClD,wBAAgB,UAAU,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM,CAmBvD"}
@@ -0,0 +1,231 @@
1
+ /**
2
+ * pre-push local eval gate: REPORT ONLY.
3
+ *
4
+ * Reviews each pushed branch's diff against its upstream with the configured
5
+ * reviewer, writes a result file, prints a short summary, and returns 0 in
6
+ * every case -- reviewer missing, reviewer crashing, unparseable output, or a
7
+ * bug in this file. The push is never blocked by this gate.
8
+ */
9
+ import { spawnSync } from 'node:child_process';
10
+ import { existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
11
+ import { tmpdir } from 'node:os';
12
+ import { join, resolve } from 'node:path';
13
+ import { run } from '../utils/exec.js';
14
+ import { getAssetPath } from '../utils/root.js';
15
+ import { DEFAULT_REVIEW_TIMEOUT_SECONDS, readEvalConfig, REVIEWER_GIT_CONFIG_KEY, RULES_PATH } from './config.js';
16
+ import { safeWrite } from './gitleaks.js';
17
+ import { countBySeverity, makeResult, readResults } from './results.js';
18
+ import { ADAPTERS, detectReviewers, findOnPath, resolveReviewer, runReview, toolVersion } from './reviewers/index.js';
19
+ const ZERO_SHA = /^0+$/;
20
+ /** Larger diffs are truncated before review; the result notes it. */
21
+ export const MAX_DIFF_CHARS = 200_000;
22
+ /** Upper bound on commits checked for a missing pre-commit scan per push. */
23
+ const MAX_SKIP_CHECK_COMMITS = 50;
24
+ /** Lock files are noise to a reviewer and can be megabytes. */
25
+ const DIFF_EXCLUDES = [':(exclude,glob)**/package-lock.json', ':(exclude,glob)**/yarn.lock', ':(exclude,glob)**/pnpm-lock.yaml', ':(exclude,glob)**/poetry.lock', ':(exclude,glob)**/Cargo.lock'];
26
+ /** Parses git's pre-push stdin: `<local ref> <local sha> <remote ref> <remote sha>` per line. */
27
+ export function parsePushInput(stdin) {
28
+ const refs = [];
29
+ for (const line of stdin.split('\n')) {
30
+ const p = line.trim().split(/\s+/);
31
+ if (p.length !== 4)
32
+ continue;
33
+ const [localRef, localSha, remoteRef, remoteSha] = p;
34
+ if (ZERO_SHA.test(localSha))
35
+ continue; // branch deletion: nothing to review
36
+ refs.push({ localRef, localSha, remoteRef, remoteSha });
37
+ }
38
+ return refs;
39
+ }
40
+ function git(args) {
41
+ const r = run('git', args);
42
+ return r.ok ? r.stdout : null;
43
+ }
44
+ /**
45
+ * Base for the review range. The branch's upstream if it has one, else what
46
+ * the remote already has for this ref, else the remote's default branch (a
47
+ * first push of a new branch). The diff is merge-base based (`base...sha`).
48
+ */
49
+ export function resolveBase(ref, remote) {
50
+ const branch = ref.localRef.startsWith('refs/heads/') ? ref.localRef.slice('refs/heads/'.length) : null;
51
+ if (branch) {
52
+ const up = git(['rev-parse', '--abbrev-ref', '--symbolic-full-name', `${branch}@{upstream}`]);
53
+ if (up) {
54
+ const sha = git(['rev-parse', '--verify', '--quiet', `${up}^{commit}`]);
55
+ if (sha)
56
+ return { base: sha, upstream: up };
57
+ }
58
+ }
59
+ if (!ZERO_SHA.test(ref.remoteSha) && git(['cat-file', '-e', `${ref.remoteSha}^{commit}`]) !== null) {
60
+ return { base: ref.remoteSha, upstream: remote ? `${remote}/${ref.remoteRef.replace(/^refs\/heads\//, '')}` : ref.remoteRef };
61
+ }
62
+ if (remote) {
63
+ const head = git(['symbolic-ref', '--quiet', `refs/remotes/${remote}/HEAD`]);
64
+ if (head) {
65
+ const sha = git(['rev-parse', '--verify', '--quiet', head]);
66
+ if (sha)
67
+ return { base: sha, upstream: head.replace(/^refs\/remotes\//, '') };
68
+ }
69
+ }
70
+ return { base: null, upstream: null };
71
+ }
72
+ /**
73
+ * Commits in the range whose tree has no pre-commit secrets result: committed
74
+ * with `--no-verify`, or produced without a commit hook (rebase, cherry-pick,
75
+ * merge). Recorded as `skipped` results; this is a heuristic, and the reason
76
+ * says so.
77
+ */
78
+ export function recordUnscannedCommits(repoRoot, base, sha, branch, upstream) {
79
+ const range = base ? `${base}..${sha}` : sha;
80
+ const list = git(['rev-list', `--max-count=${MAX_SKIP_CHECK_COMMITS}`, range]);
81
+ if (!list)
82
+ return 0;
83
+ const scanned = new Set(readResults(repoRoot)
84
+ .filter((r) => r.kind === 'secrets' && r.hook === 'pre-commit' && r.status !== 'skipped' && r.tree)
85
+ .map((r) => r.tree));
86
+ // Trees committed while gitleaks was missing already have their own skipped
87
+ // record (reason gitleaks-missing); do not report them a second time as --no-verify.
88
+ const knownSkips = new Set(readResults(repoRoot)
89
+ .filter((r) => r.kind === 'secrets' && r.hook === 'pre-commit' && r.status === 'skipped' && r.tree)
90
+ .map((r) => r.tree));
91
+ const already = new Set(readResults(repoRoot).filter((r) => r.kind === 'secrets' && r.status === 'skipped' && r.commit).map((r) => r.commit));
92
+ let n = 0;
93
+ for (const c of list.split('\n').filter(Boolean)) {
94
+ if (already.has(c))
95
+ continue;
96
+ const tree = git(['rev-parse', `${c}^{tree}`]);
97
+ if (!tree || scanned.has(tree) || knownSkips.has(tree))
98
+ continue;
99
+ const now = new Date().toISOString();
100
+ safeWrite(repoRoot, makeResult({
101
+ kind: 'secrets', hook: 'pre-push', status: 'skipped', tool: 'gitleaks', commit: c, tree, branch, upstream, base,
102
+ started_at: now, finished_at: now,
103
+ reason: 'no pre-commit secret scan recorded for this commit (git commit --no-verify, or a rebase/cherry-pick/merge that runs no commit hook)',
104
+ }));
105
+ n++;
106
+ }
107
+ return n;
108
+ }
109
+ /** Reviews one pushed ref. Never throws. */
110
+ function reviewRef(opts, ref, log) {
111
+ const { repoRoot } = opts;
112
+ const started = new Date().toISOString();
113
+ const branch = ref.localRef.startsWith('refs/heads/') ? ref.localRef.slice(11) : ref.localRef;
114
+ const { base, upstream } = resolveBase(ref, opts.remote);
115
+ const unscanned = recordUnscannedCommits(repoRoot, base, ref.localSha, branch, upstream);
116
+ if (unscanned > 0)
117
+ log(`prism: ${unscanned} pushed commit(s) have no pre-commit secret scan (recorded in .prism/results/)`);
118
+ const common = { kind: 'review', hook: 'pre-push', commit: ref.localSha, branch, upstream, base, started_at: started };
119
+ const evalCfg = readEvalConfig(repoRoot);
120
+ const choice = resolveReviewer({
121
+ gitConfigValue: git(['config', '--get', REVIEWER_GIT_CONFIG_KEY]),
122
+ prismConfigValue: evalCfg.reviewer,
123
+ available: detectReviewers(opts.pathEnv),
124
+ });
125
+ if (choice.note)
126
+ log(`prism: ${choice.note}`);
127
+ if (!choice.id) {
128
+ return makeResult({ ...common, tool: 'none', status: 'error', finished_at: new Date().toISOString(), reason: `no reviewer available: ${choice.note}` });
129
+ }
130
+ const adapter = ADAPTERS[choice.id];
131
+ const bin = findOnPath(adapter.binary, opts.pathEnv) || adapter.binary;
132
+ const model = evalCfg.model || null;
133
+ if (!base) {
134
+ return makeResult({ ...common, tool: adapter.id, status: 'skipped', finished_at: new Date().toISOString(), reason: 'no upstream or remote default branch to diff against' });
135
+ }
136
+ // spawnSync rather than run(): run() inherits execFileSync's 1 MB buffer,
137
+ // which a large branch diff exceeds.
138
+ const d = spawnSync('git', ['diff', '--no-color', '--no-ext-diff', `${base}...${ref.localSha}`, '--', '.', ...DIFF_EXCLUDES], { cwd: repoRoot, encoding: 'utf8', maxBuffer: 256 * 1024 * 1024, stdio: ['ignore', 'pipe', 'pipe'] });
139
+ let diff = d.status === 0 ? d.stdout : null;
140
+ if (diff === null) {
141
+ return makeResult({ ...common, tool: adapter.id, status: 'error', finished_at: new Date().toISOString(), reason: 'git diff failed' });
142
+ }
143
+ if (!diff.trim()) {
144
+ return makeResult({ ...common, tool: adapter.id, status: 'skipped', finished_at: new Date().toISOString(), reason: 'no changes against upstream' });
145
+ }
146
+ let truncated = false;
147
+ if (diff.length > MAX_DIFF_CHARS) {
148
+ diff = diff.slice(0, MAX_DIFF_CHARS);
149
+ truncated = true;
150
+ }
151
+ // A repo covered only by the global hooks has no rules file of its own:
152
+ // fall back to the bundled default, the same rules enable codewatch installs.
153
+ let rulesPath = RULES_PATH;
154
+ let rulesText = existsSync(resolve(repoRoot, RULES_PATH)) ? readFileSync(resolve(repoRoot, RULES_PATH), 'utf8') : '';
155
+ if (!rulesText) {
156
+ try {
157
+ rulesPath = getAssetPath(import.meta.url, 'bootstrapper/eval-harness/steering/code-review.md');
158
+ rulesText = readFileSync(rulesPath, 'utf8');
159
+ }
160
+ catch {
161
+ rulesPath = RULES_PATH;
162
+ log(`prism: ${RULES_PATH} not found; reviewing without the shared rules`);
163
+ }
164
+ }
165
+ const tmp = mkdtempSync(join(tmpdir(), 'prism-review-'));
166
+ try {
167
+ const diffPath = join(tmp, 'branch.diff');
168
+ writeFileSync(diffPath, diff, { mode: 0o600 });
169
+ const timeoutS = Number(evalCfg.timeout_seconds) > 0 ? Number(evalCfg.timeout_seconds) : DEFAULT_REVIEW_TIMEOUT_SECONDS;
170
+ log(`prism: reviewing ${branch} against ${upstream} with ${adapter.displayName} (report only, up to ${timeoutS}s)...`);
171
+ const res = runReview(adapter, { repoRoot, rulesPath, rulesText, diffPath, diff, model: model || undefined }, timeoutS * 1000, bin);
172
+ const finished = new Date().toISOString();
173
+ const version = toolVersion(bin);
174
+ if (!res.ok || !res.review) {
175
+ return makeResult({ ...common, tool: adapter.id, tool_version: version, model, status: 'error', finished_at: finished, reason: res.error });
176
+ }
177
+ const r = res.review;
178
+ return makeResult({
179
+ ...common, tool: adapter.id, tool_version: version, model: r.model || model,
180
+ status: r.findings.length ? 'findings' : 'ok', findings: r.findings, summary: r.summary, score: r.score,
181
+ finished_at: finished, reason: truncated ? `diff truncated to ${MAX_DIFF_CHARS} characters` : null,
182
+ });
183
+ }
184
+ finally {
185
+ rmSync(tmp, { recursive: true, force: true });
186
+ }
187
+ }
188
+ function summarize(r, path) {
189
+ const where = path ? ` -> ${path}` : '';
190
+ if (r.status === 'error')
191
+ return `prism: review did not run (${r.reason}). Push continues.${where}`;
192
+ if (r.status === 'skipped')
193
+ return `prism: review skipped (${r.reason}).${where}`;
194
+ const c = countBySeverity(r.findings);
195
+ const top = r.findings
196
+ .filter((f) => f.severity === 'high')
197
+ .slice(0, 3)
198
+ .map((f) => `\n [high/${f.category}] ${f.file}${f.line ? `:${f.line}` : ''} ${f.message.slice(0, 120)}`)
199
+ .join('');
200
+ return `prism: ${r.tool} review: ${r.findings.length} finding(s) (${c.high} high, ${c.medium} medium, ${c.low} low)` +
201
+ `${r.score !== null ? `, score ${r.score}` : ''}. Report only; push continues.${top}${where}`;
202
+ }
203
+ /** Entry point for the hook. Always returns 0. */
204
+ export function runPrePush(opts) {
205
+ const log = opts.log || ((l) => process.stderr.write(l + '\n'));
206
+ try {
207
+ const refs = parsePushInput(opts.stdin);
208
+ if (refs.length === 0)
209
+ return 0;
210
+ for (const ref of refs) {
211
+ let result = null;
212
+ try {
213
+ result = reviewRef(opts, ref, log);
214
+ }
215
+ catch (e) {
216
+ const now = new Date().toISOString();
217
+ result = makeResult({ kind: 'review', hook: 'pre-push', tool: 'none', status: 'error', commit: ref.localSha, started_at: now, finished_at: now, reason: `internal error: ${e?.message || e}` });
218
+ }
219
+ if (result)
220
+ log(summarize(result, safeWrite(opts.repoRoot, result)));
221
+ }
222
+ }
223
+ catch (e) {
224
+ try {
225
+ log(`prism: pre-push review failed (${e?.message || e}). Push continues.`);
226
+ }
227
+ catch { /* ignore */ }
228
+ }
229
+ return 0;
230
+ }
231
+ //# sourceMappingURL=prepush.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prepush.js","sourceRoot":"","sources":["../../../src/codewatch/prepush.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,90 @@
1
+ export declare const RESULT_SCHEMA_VERSION = 1;
2
+ export declare const RESULTS_DIR = ".prism/results";
3
+ /** Pre-commit ran with no gitleaks on PATH: the commit was allowed but not secret-scanned. */
4
+ export declare const REASON_GITLEAKS_MISSING = "gitleaks-missing";
5
+ export type Severity = 'high' | 'medium' | 'low';
6
+ export type FindingCategory = 'quality' | 'security';
7
+ export interface Finding {
8
+ severity: Severity;
9
+ category: FindingCategory;
10
+ /** Rule that fired: a gitleaks RuleID, or the review rule the reviewer named. */
11
+ rule: string;
12
+ file: string;
13
+ line: number | null;
14
+ message: string;
15
+ }
16
+ /** `secrets` = gitleaks; `review` = the reviewer (kiro-cli / Claude Code). */
17
+ export type ResultKind = 'secrets' | 'review';
18
+ export type ResultHook = 'pre-commit' | 'pre-push' | 'ci' | 'manual';
19
+ /**
20
+ * ok ran, nothing found
21
+ * findings ran, found something
22
+ * error could not produce a verdict (tool missing, crashed, unparseable output)
23
+ * skipped did not run: no changes to review, or the hook was bypassed (`--no-verify`)
24
+ */
25
+ export type ResultStatus = 'ok' | 'findings' | 'error' | 'skipped';
26
+ export interface PrismResult {
27
+ schema_version: typeof RESULT_SCHEMA_VERSION;
28
+ kind: ResultKind;
29
+ hook: ResultHook;
30
+ status: ResultStatus;
31
+ /** Tool that produced the verdict: 'gitleaks', 'kiro', 'claude', or 'none'. */
32
+ tool: string;
33
+ tool_version: string | null;
34
+ /** Model the reviewer reported, or the one requested if it reported none. null when unknown. */
35
+ model: string | null;
36
+ /** Commit reviewed. null for pre-commit, where the commit does not exist yet. */
37
+ commit: string | null;
38
+ /**
39
+ * Tree object of the change. For pre-commit this is the staged tree, which
40
+ * equals the tree of the commit that follows -- how a later pre-push links a
41
+ * pushed commit back to its secret scan, and so detects `--no-verify`.
42
+ */
43
+ tree: string | null;
44
+ branch: string | null;
45
+ upstream: string | null;
46
+ /** Base commit of the reviewed range (pre-push). */
47
+ base: string | null;
48
+ started_at: string;
49
+ finished_at: string;
50
+ findings: Finding[];
51
+ summary: string | null;
52
+ score: number | null;
53
+ /**
54
+ * Why the run errored or was skipped. Free text, except these codes, which
55
+ * consumers (the dashboard, CI) match on exactly: see REASON_*.
56
+ */
57
+ reason: string | null;
58
+ }
59
+ export type ResultInit = Omit<PrismResult, 'schema_version' | 'tool_version' | 'model' | 'commit' | 'tree' | 'branch' | 'upstream' | 'base' | 'summary' | 'score' | 'reason' | 'findings'> & Partial<Pick<PrismResult, 'tool_version' | 'model' | 'commit' | 'tree' | 'branch' | 'upstream' | 'base' | 'summary' | 'score' | 'reason' | 'findings'>>;
60
+ export declare function makeResult(init: ResultInit): PrismResult;
61
+ /** `20261104T202000123Z` -- sortable, colon-free. */
62
+ export declare function compactTimestamp(iso: string): string;
63
+ /**
64
+ * `<commit12>-<time>-<hook>-<kind>.json`, or `tree-<tree12>-...` when there is
65
+ * no commit yet (pre-commit).
66
+ */
67
+ export declare function resultFileName(r: PrismResult): string;
68
+ /**
69
+ * Writes a result atomically (temp file + rename), so a dashboard reading the
70
+ * directory never sees a half-written file. Returns the absolute path.
71
+ */
72
+ /**
73
+ * Makes sure `.prism/results/` is ignored in this clone. Under the global
74
+ * hooks a repo may never have had codewatch installed, so it has no .gitignore
75
+ * entry; `.git/info/exclude` is local to the clone and keeps the working tree
76
+ * clean without touching any tracked file. Outside a git repo it does nothing.
77
+ */
78
+ export declare function ensureResultsExcluded(repoRoot: string): boolean;
79
+ export declare function writeResult(repoRoot: string, r: PrismResult): string;
80
+ export interface ResultEntry {
81
+ /** File name without `.json`: the result's stable id (used by report links). */
82
+ id: string;
83
+ result: PrismResult;
84
+ }
85
+ /** Every parseable result with its id. Ids come from the directory listing, never from input. */
86
+ export declare function readResultEntries(repoRoot: string): ResultEntry[];
87
+ /** Reads every parseable result file. Unparseable files are ignored, not fatal. */
88
+ export declare function readResults(repoRoot: string): PrismResult[];
89
+ export declare function countBySeverity(findings: Finding[]): Record<Severity, number>;
90
+ //# sourceMappingURL=results.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"results.d.ts","sourceRoot":"","sources":["../../../src/codewatch/results.ts"],"names":[],"mappings":"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"}