granthi-review v1: estate-wide AI code review service
Webhook-driven central review service for Granthi forges: HMAC-verified push/pull_request webhooks, per-repo serialization with global LLM concurrency 1, shre-router powered rubric review (8 axes, strict JSON, tolerant extractor + retry), commit statuses + PR scorecard comments, sqlite attribution ledger with Co-Authored-By trailer parsing, per-repo HTML history dashboard, nightly per-agent digests, fail-open-with- visibility when the router is unavailable. Posture: BLOCK on confirmed critical/high correctness+security findings; admin merge is the human override. Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
import { DatabaseSync } from 'node:sqlite';
|
||||
import { mkdirSync } from 'node:fs';
|
||||
import { dirname } from 'node:path';
|
||||
|
||||
const DDL = [
|
||||
`CREATE TABLE IF NOT EXISTS reviews (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
repo TEXT NOT NULL,
|
||||
sha TEXT NOT NULL,
|
||||
pr INTEGER,
|
||||
event TEXT NOT NULL,
|
||||
pusher TEXT,
|
||||
authors TEXT,
|
||||
trailers TEXT,
|
||||
axes TEXT,
|
||||
overall INTEGER,
|
||||
grade TEXT,
|
||||
verdict TEXT,
|
||||
findings TEXT,
|
||||
status_state TEXT,
|
||||
error TEXT,
|
||||
diff_bytes INTEGER,
|
||||
truncated INTEGER DEFAULT 0,
|
||||
model TEXT,
|
||||
duration_ms INTEGER,
|
||||
ts TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now'))
|
||||
)`,
|
||||
`CREATE INDEX IF NOT EXISTS idx_reviews_repo_ts ON reviews(repo, ts DESC)`,
|
||||
`CREATE INDEX IF NOT EXISTS idx_reviews_sha ON reviews(sha)`
|
||||
];
|
||||
|
||||
export function openDb(dbPath) {
|
||||
mkdirSync(dirname(dbPath), { recursive: true });
|
||||
const db = new DatabaseSync(dbPath);
|
||||
for (const stmt of DDL) db.prepare(stmt).run();
|
||||
return db;
|
||||
}
|
||||
|
||||
export function insertReview(db, r) {
|
||||
const stmt = db.prepare(`
|
||||
INSERT INTO reviews (repo, sha, pr, event, pusher, authors, trailers, axes,
|
||||
overall, grade, verdict, findings, status_state, error, diff_bytes,
|
||||
truncated, model, duration_ms)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`);
|
||||
const res = stmt.run(
|
||||
r.repo, r.sha, r.pr ?? null, r.event, r.pusher ?? null,
|
||||
JSON.stringify(r.authors ?? []), JSON.stringify(r.trailers ?? []),
|
||||
r.axes ? JSON.stringify(r.axes) : null,
|
||||
r.overall ?? null, r.grade ?? null, r.verdict ?? null,
|
||||
r.findings ? JSON.stringify(r.findings) : null,
|
||||
r.statusState ?? null, r.error ?? null, r.diffBytes ?? null,
|
||||
r.truncated ? 1 : 0, r.model ?? null, r.durationMs ?? null
|
||||
);
|
||||
return res.lastInsertRowid;
|
||||
}
|
||||
|
||||
export function listReviews(db, repo, limit = 50) {
|
||||
return db.prepare(
|
||||
'SELECT * FROM reviews WHERE repo = ? ORDER BY id DESC LIMIT ?'
|
||||
).all(repo, limit);
|
||||
}
|
||||
|
||||
export function allReviews(db, limit = 500) {
|
||||
return db.prepare('SELECT * FROM reviews ORDER BY id DESC LIMIT ?').all(limit);
|
||||
}
|
||||
Reference in New Issue
Block a user