Skip to content

epic: migrate fleet-wide feature-toggle env vars to .loopover.yml config-as-code #6275

Description

@JSONbored

Summary

The self-host config loader treats the global .loopover.yml (at the config-dir root) as a
fallback candidate only — it's consulted purely when a repo has no per-repo config file of its
own. Since every currently-configured repo (loopover, gittensory, metagraphed, awesome-claude)
already has its own per-repo file, the global file is never actually read for any of them today.

Meanwhile, ~25 fleet-wide feature/behavior toggles are controlled exclusively by LOOPOVER_* env
vars in .env (e.g. LOOPOVER_DUPLICATE_WINNER, LOOPOVER_REVIEW_RAG, LOOPOVER_REVIEW_MEMORY,
LOOPOVER_SKIP_AUTOMATION_BOT_PRS, ...), with each per-repo .loopover.yml only able to express
inherit | off | enabled — "inherit" always defers to the env var, never to anything in the global
yml. This violates the config-as-code mandate this project otherwise holds everywhere else: every
review feature should be controllable from .loopover.yml, with env vars reserved for genuine
bootstrap-level config (secrets, DB/connection strings, fleet membership) needed before any config
file can even be located.

What surfaced this

PRs #6248 and #6249 both linked the same issue; #6248 (created first) should have survived as the
duplicate-cluster winner but was auto-closed identically to #6249. Root cause: the duplicate-winner
adjudication feature (#dup-winner) that exists specifically to spare the earliest claimant was off
fleet-wide, controllable only via LOOPOVER_DUPLICATE_WINNER in .env — not from .loopover.yml,
global or per-repo, even though the per-repo schema already exposes a duplicateWinnerMode: inherit | off | enabled field that (today) can only ever narrow the always-off global default, never widen
it via config-as-code.

Plan

Phase 1 (first sub-issue): make the global .loopover.yml a genuine base layer that per-repo
inherit values actually defer to (not just a fallback for repos with no config at all), and migrate
duplicateWinnerMode off LOOPOVER_DUPLICATE_WINNER end to end as the proof case.

Phase 2+: once the base-layer pattern is proven, migrate the remaining feature-toggle env vars
one at a time (each gets its own sub-issue once scoped):

  • LOOPOVER_OPEN_PR_FILE_COLLISION, LOOPOVER_SKIP_AUTOMATION_BOT_PRS
  • LOOPOVER_REVIEW_RAG, LOOPOVER_REVIEW_GROUNDING, LOOPOVER_REVIEW_IMPACT_MAP,
    LOOPOVER_REVIEW_MEMORY, LOOPOVER_REVIEW_SAFETY, LOOPOVER_REVIEW_REPUTATION,
    LOOPOVER_REVIEW_SCREENSHOTS, LOOPOVER_REVIEW_IMPROVEMENT_SIGNAL,
    LOOPOVER_REVIEW_CULTURE_PROFILE, LOOPOVER_REVIEW_DRAFT, LOOPOVER_REVIEW_INLINE_COMMENTS,
    LOOPOVER_REVIEW_FIX_HANDOFF, LOOPOVER_REVIEW_PLANNER, LOOPOVER_REVIEW_OPS,
    LOOPOVER_REVIEW_SELFTUNE, LOOPOVER_REVIEW_CONTINUOUS
  • LOOPOVER_SWEEP_WATCHDOG, LOOPOVER_MAINTAINER_RECAP, LOOPOVER_PUBLIC_STATS,
    LOOPOVER_PR_RECONCILIATION, LOOPOVER_AUTO_FILE_DRIFT_ISSUES,
    LOOPOVER_ENABLE_UNSAFE_CODEX_REVIEWER, LOOPOVER_EXPERIMENTAL_GITTENSOR

Explicitly out of scope — these stay env-var/.env-only, they're genuine bootstrap config, not
review features: secrets/tokens (LOOPOVER_API_TOKEN, LOOPOVER_MCP_TOKEN,
LOOPOVER_CONTRIBUTOR_ISSUE_TOKEN, LOOPOVER_DRIFT_ISSUE_TOKEN), release metadata
(LOOPOVER_VERSION), and fleet membership (LOOPOVER_REVIEW_REPOS — needed before any per-repo
config file could even be located).

Requirements

  • The global .loopover.yml must be loaded as a base layer for EVERY repo, not just repos with no
    per-repo file of their own.
  • Per-repo inherit must resolve against the global yml's own value first, falling back to the env
    var only when the global yml doesn't specify it either — never silently ignoring an explicit global
    yml setting.
  • No behavior change for any repo/setting that doesn't explicitly opt into the new global yml value
    (byte-identical until an operator actually sets something in the global file).

Metadata

Metadata

Assignees

Labels

maintainer-onlyOwner-only work — yields no Gittensor points.

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions