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
26 changes: 25 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,15 @@ REDIS_URL=redis://redis:6379 # REQUIRED for the self-host review
# LITESTREAM_REGION=us-east-1

# --- Queue worker (#977/#1201) ---
# QUEUE_CONCURRENCY=4 # max concurrent job-processing loops per instance (default 4; set 1 for strict serial processing)
# QUEUE_CONCURRENCY=4 # max concurrent job-processing loops per instance. Default 4; set 1
# # for strict serial processing. 8 is a reasonable starting point for
# # a moderate-load instance (several active repos / a steady
# # contributor-PR stream) on a host with a few spare cores -- review
# # jobs are I/O-bound (GitHub + AI awaits dominate), so raising this
# # mostly buys parallelism, not CPU. Watch gittensory_queue_live_pending
# # / gittensory_queue_oldest_live_pending_age_seconds after raising it;
# # if those stay high, the bottleneck is elsewhere (GitHub rate limit,
# # AI latency, Postgres pool -- see PGPOOL_MAX above), not concurrency.
# QUEUE_BACKGROUND_CONCURRENCY=1 # max low-priority/background jobs allowed to occupy QUEUE_CONCURRENCY slots
# CONTRIBUTOR_EVIDENCE_BATCH_SIZE=150 # logins per build-contributor-evidence job; the scheduled run fans out into
# # per-batch jobs above this so the per-login GitHub reads spread across the
Expand Down Expand Up @@ -285,6 +293,22 @@ REDIS_URL=redis://redis:6379 # REQUIRED for the self-host review
# MAINTENANCE_ADMISSION_MAX_DEFER_AGE_MS=14400000 # trickle ceiling: force-admit a maintenance job that has waited this long (4h)
# MAINTENANCE_ADMISSION_DRAIN_AGE_MS=600000 # drain ceiling: admit a job despite a backed-up lane once it has waited this long (10m); clamped to MAINTENANCE_ADMISSION_MAX_DEFER_AGE_MS

# --- Foreground queue liveness (#selfhost-queue-liveness) ---
# Live contributor-PR-review work (github-webhook, agent-regate-pr, agent-regate-sweep, recapture-preview) must
# always have a BOUNDED runnable trickle. Unlike maintenance jobs (which get an admission trickle floor of their
# own, see above), foreground jobs are never exempted from GitHub rate-limit deferral -- its worst case is
# unbounded (up to ~65 minutes per defer, re-triggered indefinitely under sustained pressure, e.g. right after a
# deploy floods a shared REST budget). This sweep periodically pulls
# back any foreground-priority pending job that has been genuinely waiting (since its own enqueue time, not reset
# by a re-defer) past the ceiling below, regardless of which mechanism deferred it -- mirroring the maintenance
# trickle's own escape hatch. Also runs once at boot, so a restart self-heals inherited over-deferral instead of
# needing manual intervention. All defaults are sane; every value is optional.
# FOREGROUND_LIVENESS_ENABLED=true # set false/0/off to fully disable this sweep
# FOREGROUND_LIVENESS_MAX_DEFER_MS=600000 # trickle ceiling: force-release a foreground job deferred this long (10m)
# FOREGROUND_LIVENESS_CHECK_INTERVAL_MS=60000 # sweep cadence -- deliberately NOT the 1s poll tick, so a job
# # still genuinely rate-limited waits for the next sweep instead
# # of busy-looping (1m)

# --- Caddy HTTPS terminator (#1203; requires --profile caddy) ---
# DOMAIN=gittensory.example.com # fully-qualified domain; Caddy auto-obtains a Let's Encrypt cert

Expand Down
13 changes: 13 additions & 0 deletions .gittensory.yml.example
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,19 @@ gate:
# Default: null (not configured).
checkRunAppSlug: null

# CI check/status context names to treat as REQUIRED when GitHub branch protection returns no
# readable required-status-checks (unconfigured, or a 403 from a token lacking
# administration:read — common for GitHub App installations, especially self-host). Merged with
# any branch-protection required contexts when both are readable; used ALONE when branch
# protection is null/empty. A context listed here that never appears on the commit stays
# pending; a completed red check for a listed context fails the gate; every listed context
# settled clean resolves to a verified "passed" (no completeness warning). List of strings, or
# omit. Default: not configured (keeps today's fold-all fail-closed behavior when branch
# protection is also unreadable). Config-as-code only — no DB column or dashboard toggle.
expectedCiContexts:
- build
- test

# Composite merge-readiness gate (no min score).
# off | advisory | block. Default: off.
mergeReadiness: off
Expand Down
6 changes: 6 additions & 0 deletions apps/gittensory-ui/public/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -9058,6 +9058,12 @@
"claCheckRunAppSlug": {
"type": "string",
"nullable": true
},
"expectedCiContexts": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
Expand Down
113 changes: 59 additions & 54 deletions apps/gittensory-ui/src/lib/selfhost-env-reference.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,43 +7,43 @@ export type SelfHostEnvReferenceRow = {
export const SELFHOST_ENV_REFERENCE_ROWS: SelfHostEnvReferenceRow[] = [
{
name: "AI_COMBINE",
firstReference: "src/selfhost/ai.ts:930",
firstReference: "src/selfhost/ai.ts:936",
},
{
name: "AI_EMBED_API_KEY",
firstReference: "src/server.ts:423",
firstReference: "src/server.ts:425",
},
{
name: "AI_EMBED_BASE_URL",
firstReference: "src/server.ts:420",
firstReference: "src/server.ts:422",
},
{
name: "AI_EMBED_MODEL",
firstReference: "src/selfhost/ai.ts:826",
firstReference: "src/selfhost/ai.ts:832",
},
{
name: "AI_ON_MERGE",
firstReference: "src/selfhost/ai.ts:932",
firstReference: "src/selfhost/ai.ts:938",
},
{
name: "AI_PROVIDER",
firstReference: "src/selfhost/ai-config.ts:43",
},
{
name: "ANTHROPIC_AI_BASE_URL",
firstReference: "src/selfhost/ai.ts:830",
firstReference: "src/selfhost/ai.ts:836",
},
{
name: "ANTHROPIC_AI_MODEL",
firstReference: "src/selfhost/ai.ts:57",
},
{
name: "ANTHROPIC_API_KEY",
firstReference: "src/selfhost/ai.ts:829",
firstReference: "src/selfhost/ai.ts:835",
},
{
name: "BACKUP_ACKNOWLEDGED",
firstReference: "src/server.ts:362",
firstReference: "src/server.ts:364",
},
{
name: "BROWSER_WS_ENDPOINT",
Expand Down Expand Up @@ -79,11 +79,11 @@ export const SELFHOST_ENV_REFERENCE_ROWS: SelfHostEnvReferenceRow[] = [
},
{
name: "CRON_INTERVAL_MS",
firstReference: "src/server.ts:872",
firstReference: "src/server.ts:885",
},
{
name: "DATABASE_PATH",
firstReference: "src/server.ts:245",
firstReference: "src/server.ts:247",
},
{
name: "DATABASE_URL",
Expand All @@ -97,6 +97,10 @@ export const SELFHOST_ENV_REFERENCE_ROWS: SelfHostEnvReferenceRow[] = [
name: "DISCORD_WEBHOOK_URL",
firstReference: "src/selfhost/discord-notify.ts:40",
},
{
name: "FOREGROUND_LIVENESS_ENABLED",
firstReference: "src/selfhost/foreground-liveness.ts:34",
},
{
name: "GITHUB_APP_ID",
firstReference: "src/selfhost/orb-collector.ts:59",
Expand All @@ -107,11 +111,11 @@ export const SELFHOST_ENV_REFERENCE_ROWS: SelfHostEnvReferenceRow[] = [
},
{
name: "GITHUB_CACHE_TTL_SECONDS",
firstReference: "src/server.ts:491",
firstReference: "src/server.ts:493",
},
{
name: "GITTENSORY_REPO_CONFIG_DIR",
firstReference: "src/server.ts:279",
firstReference: "src/server.ts:281",
},
{
name: "GITTENSORY_VERSION",
Expand All @@ -123,11 +127,11 @@ export const SELFHOST_ENV_REFERENCE_ROWS: SelfHostEnvReferenceRow[] = [
},
{
name: "MAINTENANCE_ADMISSION_ENABLED",
firstReference: "src/selfhost/maintenance-admission.ts:99",
firstReference: "src/selfhost/maintenance-admission.ts:111",
},
{
name: "MIGRATIONS_DIR",
firstReference: "src/server.ts:375",
firstReference: "src/server.ts:377",
},
{
name: "OBSERVABILITY_SMOKE_POLL_MS",
Expand All @@ -139,35 +143,35 @@ export const SELFHOST_ENV_REFERENCE_ROWS: SelfHostEnvReferenceRow[] = [
},
{
name: "OLLAMA_AI_API_KEY",
firstReference: "src/selfhost/ai.ts:823",
firstReference: "src/selfhost/ai.ts:829",
},
{
name: "OLLAMA_AI_BASE_URL",
firstReference: "src/selfhost/ai.ts:819",
firstReference: "src/selfhost/ai.ts:825",
},
{
name: "OLLAMA_AI_MODEL",
firstReference: "src/selfhost/ai.ts:61",
},
{
name: "OPENAI_AI_BASE_URL",
firstReference: "src/selfhost/ai.ts:821",
firstReference: "src/selfhost/ai.ts:827",
},
{
name: "OPENAI_AI_MODEL",
firstReference: "src/selfhost/ai.ts:62",
},
{
name: "OPENAI_API_KEY",
firstReference: "src/selfhost/ai.ts:823",
firstReference: "src/selfhost/ai.ts:829",
},
{
name: "OPENAI_COMPATIBLE_AI_API_KEY",
firstReference: "src/selfhost/ai.ts:823",
firstReference: "src/selfhost/ai.ts:829",
},
{
name: "OPENAI_COMPATIBLE_AI_BASE_URL",
firstReference: "src/selfhost/ai.ts:822",
firstReference: "src/selfhost/ai.ts:828",
},
{
name: "OPENAI_COMPATIBLE_AI_MODEL",
Expand All @@ -187,7 +191,7 @@ export const SELFHOST_ENV_REFERENCE_ROWS: SelfHostEnvReferenceRow[] = [
},
{
name: "ORB_BROKER_URL",
firstReference: "src/server.ts:921",
firstReference: "src/server.ts:934",
},
{
name: "ORB_COLLECTOR_TOKEN",
Expand All @@ -203,7 +207,7 @@ export const SELFHOST_ENV_REFERENCE_ROWS: SelfHostEnvReferenceRow[] = [
},
{
name: "ORB_RELAY_MODE",
firstReference: "src/server.ts:923",
firstReference: "src/server.ts:936",
},
{
name: "OTEL_EXPORTER_OTLP_ENDPOINT",
Expand Down Expand Up @@ -235,11 +239,11 @@ export const SELFHOST_ENV_REFERENCE_ROWS: SelfHostEnvReferenceRow[] = [
},
{
name: "PGVECTOR_ENABLED",
firstReference: "src/server.ts:225",
firstReference: "src/server.ts:227",
},
{
name: "PORT",
firstReference: "src/server.ts:671",
firstReference: "src/server.ts:684",
},
{
name: "PUBLIC_API_ORIGIN",
Expand All @@ -255,7 +259,7 @@ export const SELFHOST_ENV_REFERENCE_ROWS: SelfHostEnvReferenceRow[] = [
},
{
name: "QDRANT_URL",
firstReference: "src/server.ts:510",
firstReference: "src/server.ts:512",
},
{
name: "QUEUE_BACKGROUND_CONCURRENCY",
Expand All @@ -267,7 +271,7 @@ export const SELFHOST_ENV_REFERENCE_ROWS: SelfHostEnvReferenceRow[] = [
},
{
name: "REVIEW_AUDIT_DIR",
firstReference: "src/server.ts:555",
firstReference: "src/server.ts:557",
},
{
name: "SELFHOST_BUNDLE_ALL",
Expand Down Expand Up @@ -303,23 +307,23 @@ export const SELFHOST_ENV_REFERENCE_ROWS: SelfHostEnvReferenceRow[] = [
},
{
name: "SETUP_OUTPUT_PATH",
firstReference: "src/server.ts:788",
firstReference: "src/server.ts:801",
},
];

export const SELFHOST_ENV_REFERENCE_MARKDOWN = [
"| Name | First reference |",
"| --- | --- |",
"| `AI_COMBINE` | `src/selfhost/ai.ts:930` |",
"| `AI_EMBED_API_KEY` | `src/server.ts:423` |",
"| `AI_EMBED_BASE_URL` | `src/server.ts:420` |",
"| `AI_EMBED_MODEL` | `src/selfhost/ai.ts:826` |",
"| `AI_ON_MERGE` | `src/selfhost/ai.ts:932` |",
"| `AI_COMBINE` | `src/selfhost/ai.ts:936` |",
"| `AI_EMBED_API_KEY` | `src/server.ts:425` |",
"| `AI_EMBED_BASE_URL` | `src/server.ts:422` |",
"| `AI_EMBED_MODEL` | `src/selfhost/ai.ts:832` |",
"| `AI_ON_MERGE` | `src/selfhost/ai.ts:938` |",
"| `AI_PROVIDER` | `src/selfhost/ai-config.ts:43` |",
"| `ANTHROPIC_AI_BASE_URL` | `src/selfhost/ai.ts:830` |",
"| `ANTHROPIC_AI_BASE_URL` | `src/selfhost/ai.ts:836` |",
"| `ANTHROPIC_AI_MODEL` | `src/selfhost/ai.ts:57` |",
"| `ANTHROPIC_API_KEY` | `src/selfhost/ai.ts:829` |",
"| `BACKUP_ACKNOWLEDGED` | `src/server.ts:362` |",
"| `ANTHROPIC_API_KEY` | `src/selfhost/ai.ts:835` |",
"| `BACKUP_ACKNOWLEDGED` | `src/server.ts:364` |",
"| `BROWSER_WS_ENDPOINT` | `src/selfhost/stubs/puppeteer.ts:11` |",
"| `CLAUDE_AI_EFFORT` | `src/selfhost/ai.ts:108` |",
"| `CLAUDE_AI_MODEL` | `src/selfhost/ai.ts:49` |",
Expand All @@ -328,54 +332,55 @@ export const SELFHOST_ENV_REFERENCE_MARKDOWN = [
"| `CODEX_AI_MODEL` | `src/selfhost/ai.ts:53` |",
"| `CODEX_AI_TIMEOUT_MS` | `src/selfhost/ai.ts:112` |",
"| `CODEX_HOME` | `src/selfhost/ai.ts:274` |",
"| `CRON_INTERVAL_MS` | `src/server.ts:872` |",
"| `DATABASE_PATH` | `src/server.ts:245` |",
"| `CRON_INTERVAL_MS` | `src/server.ts:885` |",
"| `DATABASE_PATH` | `src/server.ts:247` |",
"| `DATABASE_URL` | `src/selfhost/preflight.ts:201` |",
"| `DISCORD_REPO_WEBHOOKS` | `src/selfhost/discord-notify.ts:31` |",
"| `DISCORD_WEBHOOK_URL` | `src/selfhost/discord-notify.ts:40` |",
"| `FOREGROUND_LIVENESS_ENABLED` | `src/selfhost/foreground-liveness.ts:34` |",
"| `GITHUB_APP_ID` | `src/selfhost/orb-collector.ts:59` |",
"| `GITHUB_APP_PRIVATE_KEY` | `src/selfhost/orb-collector.ts:166` |",
"| `GITHUB_CACHE_TTL_SECONDS` | `src/server.ts:491` |",
"| `GITTENSORY_REPO_CONFIG_DIR` | `src/server.ts:279` |",
"| `GITHUB_CACHE_TTL_SECONDS` | `src/server.ts:493` |",
"| `GITTENSORY_REPO_CONFIG_DIR` | `src/server.ts:281` |",
"| `GITTENSORY_VERSION` | `src/selfhost/health.ts:29` |",
"| `HOME` | `src/selfhost/ai.ts:274` |",
"| `MAINTENANCE_ADMISSION_ENABLED` | `src/selfhost/maintenance-admission.ts:99` |",
"| `MIGRATIONS_DIR` | `src/server.ts:375` |",
"| `MAINTENANCE_ADMISSION_ENABLED` | `src/selfhost/maintenance-admission.ts:111` |",
"| `MIGRATIONS_DIR` | `src/server.ts:377` |",
"| `OBSERVABILITY_SMOKE_POLL_MS` | `scripts/smoke-observability-traces.mjs:8` |",
"| `OBSERVABILITY_SMOKE_TIMEOUT_MS` | `scripts/smoke-observability-traces.mjs:6` |",
"| `OLLAMA_AI_API_KEY` | `src/selfhost/ai.ts:823` |",
"| `OLLAMA_AI_BASE_URL` | `src/selfhost/ai.ts:819` |",
"| `OLLAMA_AI_API_KEY` | `src/selfhost/ai.ts:829` |",
"| `OLLAMA_AI_BASE_URL` | `src/selfhost/ai.ts:825` |",
"| `OLLAMA_AI_MODEL` | `src/selfhost/ai.ts:61` |",
"| `OPENAI_AI_BASE_URL` | `src/selfhost/ai.ts:821` |",
"| `OPENAI_AI_BASE_URL` | `src/selfhost/ai.ts:827` |",
"| `OPENAI_AI_MODEL` | `src/selfhost/ai.ts:62` |",
"| `OPENAI_API_KEY` | `src/selfhost/ai.ts:823` |",
"| `OPENAI_COMPATIBLE_AI_API_KEY` | `src/selfhost/ai.ts:823` |",
"| `OPENAI_COMPATIBLE_AI_BASE_URL` | `src/selfhost/ai.ts:822` |",
"| `OPENAI_API_KEY` | `src/selfhost/ai.ts:829` |",
"| `OPENAI_COMPATIBLE_AI_API_KEY` | `src/selfhost/ai.ts:829` |",
"| `OPENAI_COMPATIBLE_AI_BASE_URL` | `src/selfhost/ai.ts:828` |",
"| `OPENAI_COMPATIBLE_AI_MODEL` | `src/selfhost/ai.ts:63` |",
"| `ORB_AIR_GAP` | `src/selfhost/orb-collector.ts:161` |",
"| `ORB_ANONYMIZE` | `src/selfhost/orb-collector.ts:174` |",
"| `ORB_APP_ID` | `src/selfhost/orb-collector.ts:59` |",
"| `ORB_BROKER_URL` | `src/server.ts:921` |",
"| `ORB_BROKER_URL` | `src/server.ts:934` |",
"| `ORB_COLLECTOR_TOKEN` | `src/selfhost/orb-collector.ts:205` |",
"| `ORB_COLLECTOR_URL` | `src/selfhost/orb-collector.ts:172` |",
"| `ORB_ENROLLMENT_SECRET` | `src/selfhost/orb-collector.ts:165` |",
"| `ORB_RELAY_MODE` | `src/server.ts:923` |",
"| `ORB_RELAY_MODE` | `src/server.ts:936` |",
"| `OTEL_EXPORTER_OTLP_ENDPOINT` | `src/selfhost/otel.ts:47` |",
"| `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` | `src/selfhost/otel.ts:45` |",
"| `OTEL_SERVICE_ENVIRONMENT` | `src/selfhost/otel.ts:60` |",
"| `OTEL_SERVICE_NAME` | `src/selfhost/otel.ts:59` |",
"| `OTEL_TRACES_EXPORTER` | `src/selfhost/otel.ts:40` |",
"| `OTEL_TRACES_SAMPLER` | `src/selfhost/otel.ts:74` |",
"| `OTEL_TRACES_SAMPLER_ARG` | `src/selfhost/otel.ts:76` |",
"| `PGVECTOR_ENABLED` | `src/server.ts:225` |",
"| `PORT` | `src/server.ts:671` |",
"| `PGVECTOR_ENABLED` | `src/server.ts:227` |",
"| `PORT` | `src/server.ts:684` |",
"| `PUBLIC_API_ORIGIN` | `src/selfhost/preflight.ts:192` |",
"| `QDRANT_API_KEY` | `src/selfhost/qdrant-vectorize.ts:50` |",
"| `QDRANT_DIM` | `src/selfhost/qdrant-vectorize.ts:71` |",
"| `QDRANT_URL` | `src/server.ts:510` |",
"| `QDRANT_URL` | `src/server.ts:512` |",
"| `QUEUE_BACKGROUND_CONCURRENCY` | `src/selfhost/queue-common.ts:102` |",
"| `REDIS_URL` | `src/selfhost/preflight.ts:144` |",
"| `REVIEW_AUDIT_DIR` | `src/server.ts:555` |",
"| `REVIEW_AUDIT_DIR` | `src/server.ts:557` |",
"| `SELFHOST_BUNDLE_ALL` | `scripts/build-selfhost.mjs:13` |",
"| `SELFHOST_SERVICE` | `scripts/smoke-observability-traces.mjs:5` |",
"| `SELFHOST_SETUP_TOKEN` | `src/selfhost/preflight.ts:186` |",
Expand All @@ -384,5 +389,5 @@ export const SELFHOST_ENV_REFERENCE_MARKDOWN = [
"| `SENTRY_RELEASE` | `src/selfhost/otel.ts:62` |",
"| `SENTRY_SERVER_NAME` | `src/selfhost/sentry.ts:383` |",
"| `SENTRY_TRACES_SAMPLE_RATE` | `src/selfhost/sentry.ts:171` |",
"| `SETUP_OUTPUT_PATH` | `src/server.ts:788` |",
"| `SETUP_OUTPUT_PATH` | `src/server.ts:801` |",
].join("\n");
Loading
Loading