Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions src/review/ops.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
// Operational endpoints (the ops capability — reviewbot→gittensory convergence, ADDITIVE, NATIVE port of
// Operational endpoints (the ops capability — reviewbot→loopover convergence, ADDITIVE, NATIVE port of
// reviewbot src/core/ops.ts). Bearer-protected per agent. Surfaces enough to answer "is this agent
// behaving?": health snapshot (status/verdict breakdown, manual-rate, stuck/failed/DLQ targets, reversals),
// confidence-vs-outcome calibration + a recommended floor, and the decision trail for one target.
//
// SELF-CONTAINED: every type + helper this module needs is defined HERE. No imports from reviewbot. The
// logic is byte-faithful to the reviewbot source; the only deltas are mechanical guards for gittensory's
// logic is byte-faithful to the reviewbot source; the only deltas are mechanical guards for loopover's
// stricter tsconfig + an INJECTED-DEPS seam for the runtime-gate-specific pieces.
//
// STORAGE: gittensory has no platform/access adapter — `Env` is a global ambient interface with `DB`.
// STORAGE: loopover has no platform/access adapter — `Env` is a global ambient interface with `DB`.
//
// SCOPE (deferred): reviewbot's ops.ts ALSO exposes the auto-tune override handlers
// (handleApplyRecommendation / handleClearOverride / handleOverrideAudit). Those are HEAVILY entangled with
// reviewbot's runtime override store (src/core/tunables.ts — a 257-line shadow-soak/sanitize/tighten-only
// engine) and are intentionally NOT ported here — porting them would drag the auto-tune engine into the
// gittensory tree. Likewise handleInternalStatus's account-wide AI-error count is the runtime AI-health
// loopover tree. Likewise handleInternalStatus's account-wide AI-error count is the runtime AI-health
// pacer (src/core/ai-health.ts) and is taken as an INJECTED dep (default 0). What IS ported is the clean,
// D1-only / pure surface: computeAgentHealth, computeCalibration, the bearer gate, and the status / decision
// / calibration read endpoints.
Expand Down Expand Up @@ -126,7 +126,7 @@ export interface OpsAgentConfig {

// ── Inlined helpers (byte-faithful from reviewbot src/core/{crypto,util,db}.ts) ──────────────────

/** Storage seam: gittensory's `Env` is a global ambient interface with `DB`. */
/** Storage seam: loopover's `Env` is a global ambient interface with `DB`. */
function storage(env: Env): D1Database {
return env.DB;
}
Expand Down
6 changes: 3 additions & 3 deletions src/review/outcomes-wire.ts
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ export async function recordPrOutcome(

// ── 2) reversals — a human undid a bot action ────────────────────────────────────────────────────────────────

/** Was the last GITTENSORY action on this PR a CLOSE? Reads the agent-action audit ledger (audit_events,
/** Was the last LOOPOVER action on this PR a CLOSE? Reads the agent-action audit ledger (audit_events,
* eventType `agent.action.<class>`, written by buildAgentActionAudit) — the most-recent SUCCESSFUL action for
* this target. A reopen of a bot-CLOSED PR is the high-value "human disagreed with the close" reversal signal.
* Fail-safe: a read error → false (record nothing rather than a false reversal). */
Expand Down Expand Up @@ -419,7 +419,7 @@ async function wasMergeRecorded(env: Env, targetId: string): Promise<boolean> {
}

/**
* Record a REVERSAL — a human overriding a gittensory auto-action — into the eval/audit stores (the
* Record a REVERSAL — a human overriding a loopover auto-action — into the eval/audit stores (the
* ground-truth accuracy signal). Mirrors reviewbot recordReversalSignals (runtime.ts ~157/274):
* • REOPEN of a bot-CLOSED PR by a CONTRIBUTOR → `reversal_reopened` (the high-value case). Reopens by the
* repo OWNER (administrative re-queue) or by a BOT are NOT contributor disputes and are skipped, so the
Expand Down Expand Up @@ -507,7 +507,7 @@ const BREAKER_EVAL_WINDOW_DAYS = 90;

/**
* One precision-circuit-breaker tick, run on the scheduled (selftune) cron. Reads the gate-eval confusion
* matrix over gittensory's OWN recorded pr_outcome/gate_decision rows -- SCOPED to `source: 'gittensory-native'`
* matrix over loopover's OWN recorded pr_outcome/gate_decision rows -- SCOPED to `source: 'gittensory-native'`
* (#autoclear-deadlock / stale-source): review_audit can also carry historical `gate_decision` rows from the
* pre-convergence reviewbot engine (source='reviewbot'), which stopped running once a repo converged and so
* never grows. Reading across ALL sources (the pre-fix behavior) let a permanently-frozen legacy prediction set
Expand Down
10 changes: 5 additions & 5 deletions src/review/parity-wire.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,13 @@ export const LOOPOVER_NATIVE_SOURCE = "gittensory-native";
const PARITY_WINDOW_DAYS = 90;

/**
* PURE: map a gittensory gate-check conclusion to the parity-comparable {@link GateAction}, or `null` when the
* PURE: map a loopover gate-check conclusion to the parity-comparable {@link GateAction}, or `null` when the
* conclusion carries no comparable terminal decision.
*
* The gittensory gate is a CHECK that passes or blocks a merge — it NEVER auto-closes a PR. So the honest,
* The loopover gate is a CHECK that passes or blocks a merge — it NEVER auto-closes a PR. So the honest,
* safe mapping is:
* • 'success' → 'merge' — the gate would ALLOW the merge.
* • 'failure' | 'action_required' → 'hold' — the gate BLOCKS the merge (holds it for a human); gittensory
* • 'failure' | 'action_required' → 'hold' — the gate BLOCKS the merge (holds it for a human); loopover
* does not close, so this is 'hold', not 'close'. This also
* keeps the parity SAFETY metric honest: a shadow 'hold' is
* never the dangerous "shadow merges where authoritative
Expand Down Expand Up @@ -189,7 +189,7 @@ export interface ParityReadinessRow extends GateParityRow {
}

export interface ParityReadinessReport {
/** The authoritative writer (default 'reviewbot') and the shadow writer ('gittensory') being compared. */
/** The authoritative writer (default 'reviewbot') and the shadow writer ('loopover') being compared. */
authoritative: string;
shadow: string;
/** Whether enough paired evidence exists anywhere to read parity meaningfully (>= MIN_PARITY_SAMPLE). */
Expand All @@ -215,7 +215,7 @@ export async function computeParityReadiness(
days: opts.days ?? PARITY_WINDOW_DAYS,
nowMs: opts.nowMs ?? Date.now(),
// The shadow source MUST match what recordNativeGateDecision stamps ('gittensory-native'); computeGateParity
// defaults `shadow` to 'gittensory', so pass it explicitly or the self-join would find no shadow rows. The
// defaults `shadow` to 'loopover', so pass it explicitly or the self-join would find no shadow rows. The
// authoritative side stays the default 'reviewbot' (the deploy-time dual-run writer).
shadow: LOOPOVER_NATIVE_SOURCE,
...(opts.project ? { project: opts.project } : {}),
Expand Down
16 changes: 8 additions & 8 deletions src/review/parity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,24 @@
// GROUND TRUTH (the PR's real `pr_outcome` — merged vs closed). The human's normal
// merge/close IS the answer key, so accuracy is measurable with zero manual labeling.
// computeGateParity — compares TWO systems (an authoritative writer vs a shadow writer) against EACH
// OTHER on the SAME PR at the SAME COMMIT, to prove the gittensory-app gate matches
// OTHER on the SAME PR at the SAME COMMIT, to prove the loopover-app gate matches
// reviewbot's before a per-repo cutover. isParityCutoverReady is the hard gate.
//
// SELF-CONTAINED NATIVE PORT (reviewbot→gittensory convergence): every type + helper this module needs is
// SELF-CONTAINED NATIVE PORT (reviewbot→loopover convergence): every type + helper this module needs is
// defined HERE. No imports from reviewbot — the reviewbot `storage(env)` adapter is inlined as `env.DB`, and
// `Env` is gittensory's global ambient interface (referenced directly). The FOLD logic + SQL are byte-faithful
// to the reviewbot source (src/core/eval.ts); the only deltas are mechanical guards for gittensory's stricter
// `Env` is loopover's global ambient interface (referenced directly). The FOLD logic + SQL are byte-faithful
// to the reviewbot source (src/core/eval.ts); the only deltas are mechanical guards for loopover's stricter
// tsconfig (noUncheckedIndexedAccess / exactOptionalPropertyTypes), which don't change behavior.
//
// ⚠ LIVE-USE PREREQUISITE (OUT OF SCOPE here): using this live requires gittensory's gate-decision audit rows
// ⚠ LIVE-USE PREREQUISITE (OUT OF SCOPE here): using this live requires loopover's gate-decision audit rows
// to carry a `source` (which writer) + `head_sha` (which commit) column — computeGateParity self-joins on
// (project, target_id, head_sha) per source, and computeGateEval can scope predictions by source. Those
// columns land in a LATER D1 migration. This port is the PURE functions + their tests; the reads degrade
// fail-safe (empty report) against any schema that doesn't yet have them.

// ── Inlined minimal deps (no reviewbot imports) ─────────────────────────────────────────────────────────

/** The D1 binding this module reads. `Env` is gittensory's global ambient interface (env.DB: D1Database); it is
/** The D1 binding this module reads. `Env` is loopover's global ambient interface (env.DB: D1Database); it is
* referenced directly. The reviewbot `storage(env)` adapter maps to `env.DB` here. */
function storage(env: Env): D1Database {
return env.DB;
Expand Down Expand Up @@ -174,13 +174,13 @@ export async function computeGateEval(env: Env, opts: { days: number; nowMs: num
}

// ── Cross-system gate-decision PARITY (#preconv-parity) ───────────────────────────────────────────────
// Phase-2 of the gittensory convergence proves the gittensory-app's gate decisions MATCH reviewbot's on
// Phase-2 of the loopover convergence proves the loopover-app's gate decisions MATCH reviewbot's on
// the SAME PR at the SAME COMMIT before a per-repo cutover. computeGateEval scores ONE system vs the
// realized human outcome (accuracy); this compares TWO systems against EACH OTHER. The two never live in
// the same gate_decision row — they're distinct `source` writers in the SAME review_audit store — so we
// join the latest gate_decision per (project, target_id, head_sha) for the authoritative source vs a
// shadow source. The head_sha is in the join key precisely so reviewbot@shaA is never compared to
// gittensory@shaB (a different commit = a different decision; comparing across commits is meaningless).
// loopover@shaB (a different commit = a different decision; comparing across commits is meaningless).

/** The canonical gate actions a decision can take. Anything else (or a missing head_sha) is excluded from
* the parity pairing — only a clean merge/close/hold on a known commit is comparable. */
Expand Down
2 changes: 1 addition & 1 deletion src/review/pr-reconciliation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export function isPrReconciliationEnabled(env: { LOOPOVER_PR_RECONCILIATION?: st
}

/** The same acting-autonomy repo set fanOutAgentRegateSweepJobs sweeps (mirrors sweep-watchdog.ts's own copy of
* this selection) — this reconciliation only makes sense for repos gittensory is actually reviewing. */
* this selection) — this reconciliation only makes sense for repos loopover is actually reviewing. */
async function watchedRepos(env: Env): Promise<Array<{ fullName: string; installationId?: number }>> {
const repositoriesByKey = new Map((await listRepositories(env)).map((repo) => [repo.fullName.toLowerCase(), repo]));
const byKey = new Map<string, { fullName: string; installationId?: number }>();
Expand Down
2 changes: 1 addition & 1 deletion src/review/prompt-injection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// we both flag it (a strong negative signal) and redact the literal manipulation so it can't be obeyed
// verbatim.
//
// SELF-CONTAINED NATIVE PORT (reviewbot→gittensory convergence): every type + pattern this module needs
// SELF-CONTAINED NATIVE PORT (reviewbot→loopover convergence): every type + pattern this module needs
// is defined HERE. No imports from reviewbot. The logic is byte-faithful to the reviewbot source
// (src/core/prompt-injection.ts); there are no stricter-tsconfig deltas — the module is already total.

Expand Down
12 changes: 6 additions & 6 deletions src/review/public-stats.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// Public "proof of power" stats (#1059) — a small, public-safe aggregate of what gittensory's REVIEW SYSTEM has
// Public "proof of power" stats (#1059) — a small, public-safe aggregate of what loopover's REVIEW SYSTEM has
// done, powering the above-the-fold homepage counter. Flag-gated by LOOPOVER_PUBLIC_STATS (default OFF): when
// off the public endpoint 404s, so the deploy is byte-identical to today until the flag is deliberately set.
//
// REALTIME: queries the live ledger directly (no rollup/cron) so a new review shows up within the 60s HTTP cache
// window. "reviewed" = a distinct PR for which the review system published a public review surface (audit_events
// `github_app.pr_public_surface_published`, scoped to the repos it handles: gittensory, awesome-claude,
// `github_app.pr_public_surface_published`, scoped to the repos it handles: loopover, awesome-claude,
// metagraphed); each PR's terminal DISPOSITION is read from the pull_requests cache. (The legacy review_targets
// ledger this used to read was orphaned by the convergence cutover — nothing writes it anymore.)
//
Expand All @@ -23,7 +23,7 @@
// PRIVACY: counts only — no PR content, authors, scores, or reward internals. Safe to serve publicly.
//
// GLOBAL: the homepage total folds in every REGISTERED Orb installation's outcomes (getOrbGlobalStats) on top of
// the own-ledger side, so the counter reflects the whole fleet, not just gittensory's own repos. The own-ledger
// the own-ledger side, so the counter reflects the whole fleet, not just loopover's own repos. The own-ledger
// side (audit_events) is a FROZEN snapshot as of the self-host cutover -- it stops growing the day each repo's
// live processing moved off this worker, and can never grow again now that the old App has been fully deleted --
// while orb_pr_outcomes keeps growing in realtime for any repo with the central Orb App installed (including
Expand All @@ -50,7 +50,7 @@ export function isPublicStatsEnabled(env: {
return /^(1|true|yes|on)$/i.test(env.LOOPOVER_PUBLIC_STATS ?? "");
}

/** Storage seam: gittensory's `Env` is a global ambient interface with `DB` (mirrors src/review/stats.ts). */
/** Storage seam: loopover's `Env` is a global ambient interface with `DB` (mirrors src/review/stats.ts). */
function storage(env: Env): D1Database {
return env.DB;
}
Expand All @@ -71,7 +71,7 @@ export async function safeAll<T>(
}
}

/** reviewed = the PRs gittensory actually reviewed (excludes ignored drafts/bots + errors). */
/** reviewed = the PRs loopover actually reviewed (excludes ignored drafts/bots + errors). */
function reviewedOf(d: {
merged: number;
closed: number;
Expand Down Expand Up @@ -105,7 +105,7 @@ function accuracyPct(
/** The own-ledger side of public stats is intentionally constrained to an explicit allowlist (privacy: publish
* only what's deliberately opted in). Deliberately reads LOOPOVER_PUBLIC_STATS_REPOS, NOT
* LOOPOVER_REVIEW_REPOS (the live per-PR-feature cutover allowlist) -- the two once held the same value, but
* diverged once gittensory/awesome-claude/metagraphed moved their LIVE processing to self-host: the cutover
* diverged once loopover/awesome-claude/metagraphed moved their LIVE processing to self-host: the cutover
* allowlist correctly went empty, while the historical rows this worker already wrote for them remain real and
* safe to publish. Empty allowlist => the own-ledger side reports zero (still fails safe), but does NOT
* suppress the separately-gated Orb cross-fleet aggregate (see getPublicStats below). */
Expand Down
4 changes: 2 additions & 2 deletions src/review/rag-index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Convergence (RAG / codebase index — Layer C, flag LOOPOVER_REVIEW_RAG): the INDEX-POPULATION driver. This is
// the population half (rag-wire.ts wires RETRIEVAL only):
// it fetches a repo's CODE tree, chunks + embeds it, and upserts vectors+text into the `gittensory-review-rag`
// it fetches a repo's CODE tree, chunks + embeds it, and upserts vectors+text into the `loopover-review-rag`
// Vectorize index + the `repo_chunks` table (migration 0051) — so retrieval has a warm index to read from instead
// of always seeing a cold namespace and returning "".
//
Expand Down Expand Up @@ -56,7 +56,7 @@ type TreeEntry = { path: string; size?: number | undefined; sha?: string | undef
* AHEAD of filePriority's code/doc split. On a repo whose file count exceeds MAX_CHUNKS_PER_REPO,
* `indexRepo`'s per-file loop stops once the cap is hit — with only `filePriority` (code=0, doc=1)
* as the sort key, a manifest file ties every other source file at priority 0 and then loses on the
* alphabetical tiebreaker, so it can be starved out entirely by volume (verified in prod: gittensory's
* alphabetical tiebreaker, so it can be starved out entirely by volume (verified in prod: loopover's
* own package.json never got indexed). These files are already indexable code (JSON/TOML/YAML all
* match CODE_EXT_RE in `./rag`) — this only reorders them, it does not change what's included.
* Reuses the same "manifest-like filename" classifiers signals/path-matchers.ts already exports for
Expand Down
4 changes: 2 additions & 2 deletions src/review/rag-wire.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ const MAX_QUERY_DIFF_CHARS = 4000;
const RAG_TOP_K = 12;
/** Relevance floor for the cosine matches — drops low-relevance "neighbours" that are noise, not real context
* (bge-m3 scores relevant code ~0.5-0.7 and clear noise <0.35; 0.4 is a conservative floor). Matches reviewbot's
* core config (`rag: { minScore: 0.4 }`); gittensory previously used 0 (off), which kept that noise as
* core config (`rag: { minScore: 0.4 }`); loopover previously used 0 (off), which kept that noise as
* "relevant code" and itself drove false positives. (#GAP-2) */
const RAG_MIN_SCORE = 0.4;
/** Rerank the cosine top-K by exact-term overlap before injecting, to demote vector-accident matches (high
* cosine, no real term overlap). Matches reviewbot's core config (`rag: { reranker: "bm25" }`); gittensory
* cosine, no real term overlap). Matches reviewbot's core config (`rag: { reranker: "bm25" }`); loopover
* previously left this off. (#283 / #GAP-2) */
const RAG_RERANKER = "bm25" as const;

Expand Down
Loading