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
93 changes: 44 additions & 49 deletions .env.example

Large diffs are not rendered by default.

38 changes: 17 additions & 21 deletions .env.selfhost.example
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,9 @@ GITTENSOR_REGISTRY_URL=https://example.invalid/registry.json
# skip uncommenting these entirely and write the value into secrets/<name>.txt instead (see above).
# GITHUB_WEBHOOK_SECRET= # the sole HMAC key GitHub webhook deliveries are verified against
# LOOPOVER_API_TOKEN= # server-to-server API bearer token — bypasses per-repo write checks
# # (#4774: preferred name; legacy GITTENSORY_API_TOKEN below still works
# # unchanged — dual-read, this new name wins if both are set)
# GITTENSORY_API_TOKEN= # legacy name, still read
# LOOPOVER_MCP_TOKEN= # shared MCP bearer token (#4774: ditto — legacy GITTENSORY_MCP_TOKEN
# # below still works unchanged)
# GITTENSORY_MCP_TOKEN= # legacy name, still read
# GITTENSORY_API_TOKEN= # no longer read (removed by #4777)
# LOOPOVER_MCP_TOKEN= # shared MCP bearer token
# GITTENSORY_MCP_TOKEN= # no longer read (removed by #4777)
# INTERNAL_JOB_TOKEN= # gates internal-only routes

# REQUIRED for the first-run /setup wizard that creates the GitHub App manifest, AND required ongoing:
Expand Down Expand Up @@ -72,18 +69,18 @@ REDIS_URL=redis://redis:6379
# deterministic review are working (see the Quickstart "boot the stack" step)
# =============================================================================
SELFHOST_DEPLOYMENT_MODE=dry-run
GITTENSORY_REVIEW_REPOS=owner/repo
# LOOPOVER_REVIEW_REPOS=owner/repo # #5555 dual-read: preferred name; wins over GITTENSORY_REVIEW_REPOS above when both are set
GITTENSORY_REVIEW_UNIFIED_COMMENT=true
# LOOPOVER_REVIEW_UNIFIED_COMMENT=true # #5555 dual-read: preferred name; wins over GITTENSORY_REVIEW_UNIFIED_COMMENT above when both are set
GITTENSORY_REVIEW_SAFETY=true
# LOOPOVER_REVIEW_SAFETY=true # #5555 dual-read: preferred name; wins over GITTENSORY_REVIEW_SAFETY above when both are set
GITTENSORY_REVIEW_GROUNDING=true
# LOOPOVER_REVIEW_GROUNDING=true # #5555 dual-read: preferred name; wins over GITTENSORY_REVIEW_GROUNDING above when both are set
GITTENSORY_REVIEW_RAG=false
# LOOPOVER_REVIEW_RAG=false # #5555 dual-read: preferred name; wins over GITTENSORY_REVIEW_RAG above when both are set
GITTENSORY_REVIEW_ENRICHMENT=false
# LOOPOVER_REVIEW_ENRICHMENT=false # #5555 dual-read: preferred name; wins over GITTENSORY_REVIEW_ENRICHMENT above when both are set
LOOPOVER_REVIEW_REPOS=owner/repo
# GITTENSORY_REVIEW_REPOS=owner/repo # no longer read (removed by #4777)
LOOPOVER_REVIEW_UNIFIED_COMMENT=true
# GITTENSORY_REVIEW_UNIFIED_COMMENT=true # no longer read (removed by #4777)
LOOPOVER_REVIEW_SAFETY=true
# GITTENSORY_REVIEW_SAFETY=true # no longer read (removed by #4777)
LOOPOVER_REVIEW_GROUNDING=true
# GITTENSORY_REVIEW_GROUNDING=true # no longer read (removed by #4777)
LOOPOVER_REVIEW_RAG=false
# GITTENSORY_REVIEW_RAG=false # no longer read (removed by #4777)
LOOPOVER_REVIEW_ENRICHMENT=false
# GITTENSORY_REVIEW_ENRICHMENT=false # no longer read (removed by #4777)

# =============================================================================
# 4. AI provider — pick ONE block below and uncomment it (deterministic-only review if you skip
Expand All @@ -99,14 +96,13 @@ GITTENSORY_REVIEW_ENRICHMENT=false
# filesystem prompt-influenced reviews can read) -- the explicit opt-in below is required, and you
# must mount your Codex auth at /data/codex (the image exposes it as ~/.codex).
# AI_PROVIDER=codex
# LOOPOVER_ENABLE_UNSAFE_CODEX_REVIEWER=1 # #4774: preferred name; legacy GITTENSORY_ENABLE_UNSAFE_CODEX_REVIEWER=1
# # still works unchanged (dual-read, this new name wins if both are set)
# LOOPOVER_ENABLE_UNSAFE_CODEX_REVIEWER=1 # strict "1"-only opt-in; any other value stays fail-closed

# --- Both, synthesized into one decision --------------------------------------
# AI_PROVIDER=claude-code,codex
# AI_COMBINE=synthesis
# CLAUDE_CODE_OAUTH_TOKEN=
# LOOPOVER_ENABLE_UNSAFE_CODEX_REVIEWER=1 # #4774: same dual-read as above
# LOOPOVER_ENABLE_UNSAFE_CODEX_REVIEWER=1

# =============================================================================
# 5. Telemetry — informational only, no action needed
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/release-selfhost.yml
Original file line number Diff line number Diff line change
Expand Up @@ -246,11 +246,11 @@ jobs:
push: true
# Visual-capture convergence (#3607/#4111): every official image ships puppeteer-core so a
# self-hoster can turn on before/after screenshot capture with just BROWSER_WS_ENDPOINT +
# GITTENSORY_REVIEW_SCREENSHOTS=true at runtime -- no custom image build required. Inert either
# LOOPOVER_REVIEW_SCREENSHOTS=true at runtime -- no custom image build required. Inert either
# way until those runtime flags are set (Dockerfile's INSTALL_VISUAL_REVIEW only controls
# whether the dependency is installed, never whether the feature runs).
build-args: |
GITTENSORY_VERSION=${{ steps.version.outputs.release }}
LOOPOVER_VERSION=${{ steps.version.outputs.release }}
INSTALL_VISUAL_REVIEW=true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
Expand Down
6 changes: 3 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# Cloudflare Worker (wrangler) deploy is unaffected. SECRETS ARE NEVER BAKED: supply them at run time via
# the .env file or mounted *_FILE secrets (see docker-compose.yml + .env.example).

ARG GITTENSORY_VERSION=
ARG LOOPOVER_VERSION=

# --- build: install deps + bundle the Node entry --------------------------------------------------------
# ECR Public Gallery mirrors Docker Official Images with no rate limits and no auth.
Expand All @@ -28,14 +28,14 @@ RUN node scripts/validate-selfhost-sourcemap.mjs
# --- runtime base: slim, non-root -----------------------------------------------------------------------
FROM public.ecr.aws/docker/library/node:24-slim AS runtime-base
WORKDIR /app
ARG GITTENSORY_VERSION=
ARG LOOPOVER_VERSION=
ENV NODE_ENV=production \
PLATFORM=self-hosted \
PORT=8787 \
DATABASE_PATH=/data/gittensory.sqlite \
MIGRATIONS_DIR=/app/migrations \
NPM_CONFIG_PREFIX=/home/node/.npm-global \
GITTENSORY_VERSION=${GITTENSORY_VERSION}
LOOPOVER_VERSION=${LOOPOVER_VERSION}
# Bake the Claude Code / Codex CLIs by default so the self-host image is ready for subscription reviewers (#979).
# No credentials are baked — operators mint CLAUDE_CODE_OAUTH_TOKEN (`claude setup-token`) / codex auth at run time
# and pass/mount them via env/volumes. Minimal custom builds can opt out with `--build-arg INSTALL_AI_CLIS=false`.
Expand Down
2 changes: 1 addition & 1 deletion apps/gittensory-ui/src/lib/selfhost-docs-audit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ export const SELFHOST_SOURCE_OF_TRUTH_ROWS: readonly SelfHostSourceOfTruthRow[]
topic: "AI providers and unsafe Codex opt-in",
runtimeSources: ["src/selfhost/ai-config.ts", "src/selfhost/ai.ts"],
docsPath: "/docs/self-hosting-ai-providers",
notes: "Codex PR review is fail-closed unless GITTENSORY_ENABLE_UNSAFE_CODEX_REVIEWER=1.",
notes: "Codex PR review is fail-closed unless LOOPOVER_ENABLE_UNSAFE_CODEX_REVIEWER=1.",
},
{
topic: "REES sidecar (compose profile)",
Expand Down
20 changes: 0 additions & 20 deletions apps/gittensory-ui/src/lib/selfhost-env-reference.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,22 +189,6 @@ export const SELFHOST_ENV_REFERENCE_ROWS: SelfHostEnvReferenceRow[] = [
name: "GITHUB_INSTALLATION_CONCURRENCY_LIMIT",
firstReference: "src/selfhost/installation-concurrency-admission.ts",
},
{
name: "GITTENSORY_ENABLE_PAGERDUTY",
firstReference: "src/services/notify-pagerduty.ts",
},
{
name: "GITTENSORY_ENABLE_UNSAFE_CODEX_REVIEWER",
firstReference: "src/selfhost/ai.ts",
},
{
name: "GITTENSORY_REPO_CONFIG_DIR",
firstReference: "src/server.ts",
},
{
name: "GITTENSORY_VERSION",
firstReference: "src/selfhost/otel.ts",
},
{
name: "HOME",
firstReference: "src/selfhost/ai.ts",
Expand Down Expand Up @@ -548,10 +532,6 @@ export const SELFHOST_ENV_REFERENCE_MARKDOWN = [
"| `GITHUB_INSTALLATION_CONCURRENCY_DEFER_MS` | `src/selfhost/installation-concurrency-admission.ts` |",
"| `GITHUB_INSTALLATION_CONCURRENCY_ENABLED` | `src/selfhost/installation-concurrency-admission.ts` |",
"| `GITHUB_INSTALLATION_CONCURRENCY_LIMIT` | `src/selfhost/installation-concurrency-admission.ts` |",
"| `GITTENSORY_ENABLE_PAGERDUTY` | `src/services/notify-pagerduty.ts` |",
"| `GITTENSORY_ENABLE_UNSAFE_CODEX_REVIEWER` | `src/selfhost/ai.ts` |",
"| `GITTENSORY_REPO_CONFIG_DIR` | `src/server.ts` |",
"| `GITTENSORY_VERSION` | `src/selfhost/otel.ts` |",
"| `HOME` | `src/selfhost/ai.ts` |",
"| `LOOPOVER_ENABLE_PAGERDUTY` | `src/services/notify-pagerduty.ts` |",
"| `LOOPOVER_ENABLE_UNSAFE_CODEX_REVIEWER` | `src/selfhost/ai.ts` |",
Expand Down
42 changes: 21 additions & 21 deletions apps/gittensory-ui/src/routes/docs.github-app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -265,83 +265,83 @@ review:
</p>

<h2>
Review capability flags (<code>GITTENSORY_REVIEW_*</code>)
Review capability flags (<code>LOOPOVER_REVIEW_*</code>)
</h2>
<p>
Beyond per-repo settings, operators turn whole review <em>capabilities</em> on or off with
the <code>GITTENSORY_REVIEW_*</code> worker environment variables. Every flag defaults to{" "}
the <code>LOOPOVER_REVIEW_*</code> worker environment variables. Every flag defaults to{" "}
<strong>OFF</strong>: when a flag is off its code path is inert and the review behaves
exactly as if the feature did not exist. "Truthy" is one of <code>1</code>,{" "}
<code>true</code>, <code>yes</code>, or <code>on</code>. You roll capabilities forward — and
back — one flag, and one repo, at a time.
</p>
<Callout variant="safety">
Per-PR features require <strong>two</strong> conditions: the capability flag is on{" "}
<em>and</em> the repo is listed in <code>GITTENSORY_REVIEW_REPOS</code>. With an empty repo
<em>and</em> the repo is listed in <code>LOOPOVER_REVIEW_REPOS</code>. With an empty repo
allowlist every per-PR feature stays dormant for everyone, no matter the global flags.
</Callout>
<ul>
<li>
<code>GITTENSORY_REVIEW_REPOS</code> — per-repo cutover allowlist. Comma-separated{" "}
<code>LOOPOVER_REVIEW_REPOS</code> — per-repo cutover allowlist. Comma-separated{" "}
<code>owner/repo</code> names that may run the per-PR features. Add repos one at a time to
roll forward; remove to roll back.
</li>
<li>
<code>GITTENSORY_REVIEW_SAFETY</code> — safety scan: defangs untrusted PR title/body/diff
<code>LOOPOVER_REVIEW_SAFETY</code> — safety scan: defangs untrusted PR title/body/diff
(prompt-injection neutralization) before the reviewer sees it, and surfaces a{" "}
<code>secret_leak</code> blocker for leaked secrets in the diff. Per-PR.
</li>
<li>
<code>GITTENSORY_REVIEW_GROUNDING</code> — grounds the AI reviewer with the PR's finished
CI status and the full post-change content of the changed files, so the model verifies its
<code>LOOPOVER_REVIEW_GROUNDING</code> — grounds the AI reviewer with the PR's finished CI
status and the full post-change content of the changed files, so the model verifies its
claims against reality. Per-PR.
</li>
<li>
<code>GITTENSORY_REVIEW_RAG</code> — retrieval-augmented context: appends semantically
<code>LOOPOVER_REVIEW_RAG</code> — retrieval-augmented context: appends semantically
related code/docs from the codebase vector index to the reviewer prompt. Per-PR; inert
until a <code>VECTORIZE</code> index exists for the repo.
</li>
<li>
<code>GITTENSORY_REVIEW_REPUTATION</code> — submitter-reputation spend control: downgrades
a new / burst / low-reputation submitter to a deterministic-only review. Internal-only,
<code>LOOPOVER_REVIEW_REPUTATION</code> — submitter-reputation spend control: downgrades a
new / burst / low-reputation submitter to a deterministic-only review. Internal-only,
never surfaced publicly. Per-PR.
</li>
<li>
<code>GITTENSORY_REVIEW_UNIFIED_COMMENT</code> — renders the public PR comment as one
<code>LOOPOVER_REVIEW_UNIFIED_COMMENT</code> — renders the public PR comment as one
in-place unified comment instead of the legacy multi-panel comment. Per-PR; flag-off keeps
the legacy comment byte-identical.
</li>
<li>
<code>GITTENSORY_REVIEW_OPS</code> — read-only observability: a cron anomaly scan over
your own review-outcome data plus a bearer-gated stats aggregate. Global (not scoped by
the repo allowlist).
<code>LOOPOVER_REVIEW_OPS</code> — read-only observability: a cron anomaly scan over your
own review-outcome data plus a bearer-gated stats aggregate. Global (not scoped by the
repo allowlist).
</li>
<li>
<code>GITTENSORY_REVIEW_SELFTUNE</code> — self-improvement loop that computes tuning
<code>LOOPOVER_REVIEW_SELFTUNE</code> — self-improvement loop that computes tuning
recommendations from review outcomes, shadow-soaks any strictly-tightening recommendation,
and can <em>only ever tighten</em> the gate. Global.
</li>
<li>
<code>GITTENSORY_REVIEW_CONTENT_LANE</code> — routes content repos (curated lists,
<code>LOOPOVER_REVIEW_CONTENT_LANE</code> — routes content repos (curated lists,
registries) through the dedicated content lane instead of the code gate. Global.
</li>
<li>
<code>GITTENSORY_REVIEW_DRAFT</code> — public draft-submission flow (contributor draft →
<code>LOOPOVER_REVIEW_DRAFT</code> — public draft-submission flow (contributor draft →
GitHub OAuth → fork PR). Global; also needs the draft secrets set.
</li>
</ul>
<p>
A safe rollout for a per-PR feature is two flips: set the capability flag truthy, then add
the repo to <code>GITTENSORY_REVIEW_REPOS</code>. Because both must hold, a capability can
the repo to <code>LOOPOVER_REVIEW_REPOS</code>. Because both must hold, a capability can
stay globally enabled while remaining dormant everywhere except the repos you have
explicitly added.
</p>
<CodeBlock
lang="bash"
code={`# Roll grounding + the unified comment onto one repo:
GITTENSORY_REVIEW_GROUNDING="true"
GITTENSORY_REVIEW_UNIFIED_COMMENT="true"
GITTENSORY_REVIEW_REPOS="JSONbored/gittensory"`}
LOOPOVER_REVIEW_GROUNDING="true"
LOOPOVER_REVIEW_UNIFIED_COMMENT="true"
LOOPOVER_REVIEW_REPOS="JSONbored/gittensory"`}
/>

<h2>Dogfood mode</h2>
Expand Down
13 changes: 6 additions & 7 deletions apps/gittensory-ui/src/routes/docs.how-reviews-work.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -219,17 +219,17 @@ function HowReviewsWork() {
changing <em>who</em> can be blocked.
</p>
<Callout variant="note" title="Grounding makes the AI check reality">
The <code>GITTENSORY_REVIEW_GROUNDING</code> flag grounds the reviewer prompt with the PR's
The <code>LOOPOVER_REVIEW_GROUNDING</code> flag grounds the reviewer prompt with the PR's
finished CI status and the full post-change content of the changed files — so the model
verifies its claims instead of predicting CI or flagging a symbol defined just outside the
diff hunk. <code>GITTENSORY_REVIEW_RAG</code> adds semantically related existing code and
docs as extra context. Both are additive and opt-in.
diff hunk. <code>LOOPOVER_REVIEW_RAG</code> adds semantically related existing code and docs
as extra context. Both are additive and opt-in.
</Callout>

<h2>3. The unified review comment</h2>
<p>
The result is rendered as <strong>one in-place comment</strong> on the PR — updated in place
on each push rather than stacked — when <code>GITTENSORY_REVIEW_UNIFIED_COMMENT</code> is on
on each push rather than stacked — when <code>LOOPOVER_REVIEW_UNIFIED_COMMENT</code> is on
for the repo. It has three parts, top to bottom:
</p>
<ul>
Expand Down Expand Up @@ -260,15 +260,14 @@ function HowReviewsWork() {
<Callout variant="safety">
Public-facing comments are sanitized before they leave the worker. Private scoring, reward,
and reputation language never appears in the PR thread — and reputation-based spend control
(<code>GITTENSORY_REVIEW_REPUTATION</code>) is never surfaced in any comment, label, or
check.
(<code>LOOPOVER_REVIEW_REPUTATION</code>) is never surfaced in any comment, label, or check.
</Callout>

<h2>4. The signals behind a verdict</h2>
<p>Each row in the signal table comes from a named finding. The common ones you will see:</p>
<ul>
<li>
<code>secret_leak</code> — the safety scan (<code>GITTENSORY_REVIEW_SAFETY</code>) found a
<code>secret_leak</code> — the safety scan (<code>LOOPOVER_REVIEW_SAFETY</code>) found a
leaked secret in the diff. The same scan also defangs untrusted PR text before the AI
reviewer reads it.
</li>
Expand Down
10 changes: 5 additions & 5 deletions apps/gittensory-ui/src/routes/docs.maintainer-self-hosting.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ function MaintainerSelfHosting() {
{
title: "Private policy",
description:
"A mounted GITTENSORY_REPO_CONFIG_DIR lets maintainers keep review thresholds, autonomy, and notes out of public repos.",
"A mounted LOOPOVER_REPO_CONFIG_DIR lets maintainers keep review thresholds, autonomy, and notes out of public repos.",
},
{
title: "Optional intelligence",
Expand Down Expand Up @@ -212,7 +212,7 @@ function MaintainerSelfHosting() {
<ol>
<li>
<code>cp .env.selfhost.example .env</code> — conservative defaults (<code>dry-run</code>,
small <code>GITTENSORY_REVIEW_REPOS</code>).
small <code>LOOPOVER_REVIEW_REPOS</code>).
</li>
<li>
Pull or build the image (<code>INSTALL_AI_CLIS=true</code> by default;{" "}
Expand All @@ -229,7 +229,7 @@ function MaintainerSelfHosting() {
files deep-merge on top).
</li>
<li>
Add each pilot repo to <code>GITTENSORY_REVIEW_REPOS</code>, watch a PR in{" "}
Add each pilot repo to <code>LOOPOVER_REVIEW_REPOS</code>, watch a PR in{" "}
<code>dry-run</code>, then enable advisory gate mode from the control panel or{" "}
<code>POST /v1/repos/:owner/:repo/activation</code>.
</li>
Expand All @@ -245,7 +245,7 @@ function MaintainerSelfHosting() {
{
title: "Single-command repo onboarding",
description:
"Today: edit .env allowlist, copy YAML templates, sign into the panel, click activate. Proposed: one CLI/API command that adds owner/repo to GITTENSORY_REVIEW_REPOS, seeds gittensory-config/owner__repo/.loopover.yml from global.gittensory.yml, and POSTs activation — idempotent, dry-run aware.",
"Today: edit .env allowlist, copy YAML templates, sign into the panel, click activate. Proposed: one CLI/API command that adds owner/repo to LOOPOVER_REVIEW_REPOS, seeds gittensory-config/owner__repo/.loopover.yml from global.gittensory.yml, and POSTs activation — idempotent, dry-run aware.",
},
{
title: "Centralized private default only",
Expand All @@ -260,7 +260,7 @@ function MaintainerSelfHosting() {
{
title: "Clearer activation vocabulary",
description:
"Docs now separate GITTENSORY_REVIEW_REPOS (feature allowlist), gate activation (check + rules), and is_registered (Gittensor registry). Proposed: surface all three in the control-panel repo workspace with plain labels instead of making operators infer from logs.",
"Docs now separate LOOPOVER_REVIEW_REPOS (feature allowlist), gate activation (check + rules), and is_registered (Gittensor registry). Proposed: surface all three in the control-panel repo workspace with plain labels instead of making operators infer from logs.",
},
]}
/>
Expand Down
Loading
Loading