You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Part of #6275. Four sibling fleet-wide background jobs already got a full top-level self-repo .loopover.yml override under this same epic — a present manifest block on the loopover self-repo's
own manifest (resolveLoopOverSelfRepoFullName) wins outright over the env var, exactly like OpsManifestOverride/resolveOpsManifestOverride in src/review/ops-wire.ts:
Two more background jobs of the identical shape — same "iterate the acting-autonomy repo set on a cron
tick" design, same doc-commented sibling relationship to each other and to ops — never got this:
Both already have a per-repo FORCE-OFF-ONLY override (review.sweepWatchdog/review.prReconciliation: false, also added under #6275) that lets one already-watched repo exclude itself from the scan. That part
is intentionally asymmetric and is NOT what this issue is about (see Boundaries below). What's missing is
the top-level flag — today isSweepWatchdogEnabled/isPrReconciliationEnabled read only env, with
no way to flip the whole job on or off from .loopover.yml the way ops/draftFlow/publicStats/ upstreamDriftIssues already can.
Requirements
Add SweepWatchdogManifestOverride/resolveSweepWatchdogManifestOverride to sweep-watchdog.ts and PrReconciliationManifestOverride/resolvePrReconciliationManifestOverride to pr-reconciliation.ts,
each mirroring OpsManifestOverride/resolveOpsManifestOverride (ops-wire.ts) exactly: a { present: boolean; enabled: boolean } shape, read off the loopover self-repo's manifest via loadRepoFocusManifest(env, resolveLoopOverSelfRepoFullName(env)), a short in-isolate TTL cache (mirror
the existing 60s OPS_MANIFEST_OVERRIDE_CACHE_TTL_MS pattern), and fail-safe-to-{present:false} on a
manifest load error (never let a config-read blip silently enable or disable the job).
Update isSweepWatchdogEnabled/isPrReconciliationEnabled to accept the optional manifest override
parameter and check it first (if (manifestOverride?.present) return manifestOverride.enabled;),
falling through to the existing env-var check only when no override is present — same signature shape as isOpsEnabled(env, manifestOverride?).
Add new top-level manifest keys sweepWatchdog: and prReconciliation: to the shared engine package
(packages/loopover-engine/src/focus-manifest.ts — FocusManifestSweepWatchdogConfig/ FocusManifestPrReconciliationConfig, parse functions, *ConfigToJson serializers, EMPTY_*_CONFIG
defaults), mirroring FocusManifestOpsConfig/parseOpsConfig/opsConfigToJson exactly. These are new
top-level keys, NOT a rename or reuse of the existing review.sweepWatchdog/review.prReconciliation
per-repo boolean fields — those stay exactly as-is (per-repo force-off), this is an unrelated sibling
namespace, same relationship ops: (top-level) already has to any per-repo review.* keys.
Re-export the new types/functions from src/signals/focus-manifest.ts (the app-local shim file), the
same re-export list opsConfigToJson/FocusManifestOpsConfig already appear in.
Update every caller of isSweepWatchdogEnabled/isPrReconciliationEnabled to pass the resolved override
(mirror how ops-wire.ts's own callers — the cron dispatch and any manual-trigger route — already pass resolveOpsManifestOverride's result through).
Document sweepWatchdog:/prReconciliation: in .loopover.yml.example next to ops:/draftFlow:/ publicStats:/upstreamDriftIssues:.
No behavior change for any deployment that doesn't add these blocks to the loopover self-repo's .loopover.yml — byte-identical until an operator opts in.
Boundaries — what NOT to touch
Do not change watchedRepos()'s per-repo scan-set selection in either file, and do not fold the
per-repo review.sweepWatchdog/review.prReconciliation: false override onto feature-activation.ts's resolver. Investigate + design config-as-code for ops / sweep_watchdog / pr_reconciliation #4106 (closed, NOT_PLANNED) already investigated exactly that move
for these two jobs (plus ops) and rejected it: the per-repo scan-set axis already runs through settings.autonomy/isAgentConfigured, and letting a repo-writable, lower-trust .loopover.yml widen
its own inclusion would spend the operator's shared GitHub API budget on the repo's own say-so — a worse
trust boundary than today's operator-only allowlist. This issue is scoped ONLY to the top-level,
operator-writable-only (loopover self-repo) fleet-wide switch — it does not reopen Investigate + design config-as-code for ops / sweep_watchdog / pr_reconciliation #4106's question.
Do not add a true/force-on value to the existing per-repo review.sweepWatchdog/ review.prReconciliation keys. They stay force-off-only, unchanged.
Deliverables
SweepWatchdogManifestOverride + resolveSweepWatchdogManifestOverride in sweep-watchdog.ts
PrReconciliationManifestOverride + resolvePrReconciliationManifestOverride in pr-reconciliation.ts
sweepWatchdog:/prReconciliation: top-level manifest config types + parse/serialize functions in packages/loopover-engine/src/focus-manifest.ts, re-exported from src/signals/focus-manifest.ts
Call sites updated to resolve and pass the override through
.loopover.yml.example documents the two new blocks
Test Coverage Requirements
100% branch coverage on both new resolver functions (present+enabled true/false, absent, manifest-load
error → fail-safe), plus the manifest parse/serialize round-trip for both new config types. src/** and packages/loopover-engine/src/** are both Codecov-measured (this repo mirrors engine-package coverage per
its own root vitest suite) — aim for 99%+ patch on every changed line and branch, including a regression
test asserting a present-but-enabled:false manifest block turns the job off even when the env var is "true", and vice versa.
Expected Outcome
An operator can turn LOOPOVER_SWEEP_WATCHDOG and LOOPOVER_PR_RECONCILIATION on or off fleet-wide from
the loopover self-repo's .loopover.yml alone, matching ops/draftFlow/publicStats/ upstreamDriftIssues's already-shipped precedent, with the env var remaining as the fallback default when
no override block is present.
Links & Resources
Pattern to mirror exactly: OpsManifestOverride/resolveOpsManifestOverride/isOpsEnabled in src/review/ops-wire.ts, and its manifest-type sibling in packages/loopover-engine/src/focus-manifest.ts
(FocusManifestOpsConfig, parseOpsConfig, opsConfigToJson, EMPTY_OPS_CONFIG).
Context
Part of #6275. Four sibling fleet-wide background jobs already got a full top-level self-repo
.loopover.ymloverride under this same epic — a present manifest block on the loopover self-repo'sown manifest (
resolveLoopOverSelfRepoFullName) wins outright over the env var, exactly likeOpsManifestOverride/resolveOpsManifestOverrideinsrc/review/ops-wire.ts:LOOPOVER_REVIEW_OPS→ops:block (ops-wire.ts)LOOPOVER_REVIEW_DRAFT→draftFlow:block (src/services/draft.ts)LOOPOVER_PUBLIC_STATS→publicStats:block (src/review/public-stats.ts)LOOPOVER_AUTO_FILE_DRIFT_ISSUES→upstreamDriftIssues:block (src/upstream/ruleset.ts)Two more background jobs of the identical shape — same "iterate the acting-autonomy repo set on a cron
tick" design, same doc-commented sibling relationship to each other and to
ops— never got this:LOOPOVER_SWEEP_WATCHDOG—isSweepWatchdogEnabled(env),src/review/sweep-watchdog.tsLOOPOVER_PR_RECONCILIATION—isPrReconciliationEnabled(env),src/review/pr-reconciliation.tsBoth already have a per-repo FORCE-OFF-ONLY override (
review.sweepWatchdog/review.prReconciliation: false, also added under #6275) that lets one already-watched repo exclude itself from the scan. That partis intentionally asymmetric and is NOT what this issue is about (see Boundaries below). What's missing is
the top-level flag — today
isSweepWatchdogEnabled/isPrReconciliationEnabledread onlyenv, withno way to flip the whole job on or off from
.loopover.ymlthe wayops/draftFlow/publicStats/upstreamDriftIssuesalready can.Requirements
SweepWatchdogManifestOverride/resolveSweepWatchdogManifestOverridetosweep-watchdog.tsandPrReconciliationManifestOverride/resolvePrReconciliationManifestOverridetopr-reconciliation.ts,each mirroring
OpsManifestOverride/resolveOpsManifestOverride(ops-wire.ts) exactly: a{ present: boolean; enabled: boolean }shape, read off the loopover self-repo's manifest vialoadRepoFocusManifest(env, resolveLoopOverSelfRepoFullName(env)), a short in-isolate TTL cache (mirrorthe existing 60s
OPS_MANIFEST_OVERRIDE_CACHE_TTL_MSpattern), and fail-safe-to-{present:false}on amanifest load error (never let a config-read blip silently enable or disable the job).
isSweepWatchdogEnabled/isPrReconciliationEnabledto accept the optional manifest overrideparameter and check it first (
if (manifestOverride?.present) return manifestOverride.enabled;),falling through to the existing env-var check only when no override is present — same signature shape as
isOpsEnabled(env, manifestOverride?).sweepWatchdog:andprReconciliation:to the shared engine package(
packages/loopover-engine/src/focus-manifest.ts—FocusManifestSweepWatchdogConfig/FocusManifestPrReconciliationConfig, parse functions,*ConfigToJsonserializers,EMPTY_*_CONFIGdefaults), mirroring
FocusManifestOpsConfig/parseOpsConfig/opsConfigToJsonexactly. These are newtop-level keys, NOT a rename or reuse of the existing
review.sweepWatchdog/review.prReconciliationper-repo boolean fields — those stay exactly as-is (per-repo force-off), this is an unrelated sibling
namespace, same relationship
ops:(top-level) already has to any per-reporeview.*keys.src/signals/focus-manifest.ts(the app-local shim file), thesame re-export list
opsConfigToJson/FocusManifestOpsConfigalready appear in.isSweepWatchdogEnabled/isPrReconciliationEnabledto pass the resolved override(mirror how
ops-wire.ts's own callers — the cron dispatch and any manual-trigger route — already passresolveOpsManifestOverride's result through).sweepWatchdog:/prReconciliation:in.loopover.yml.examplenext toops:/draftFlow:/publicStats:/upstreamDriftIssues:..loopover.yml— byte-identical until an operator opts in.Boundaries — what NOT to touch
watchedRepos()'s per-repo scan-set selection in either file, and do not fold theper-repo
review.sweepWatchdog/review.prReconciliation: falseoverride ontofeature-activation.ts's resolver. Investigate + design config-as-code for ops / sweep_watchdog / pr_reconciliation #4106 (closed,NOT_PLANNED) already investigated exactly that movefor these two jobs (plus
ops) and rejected it: the per-repo scan-set axis already runs throughsettings.autonomy/isAgentConfigured, and letting a repo-writable, lower-trust.loopover.ymlwidenits own inclusion would spend the operator's shared GitHub API budget on the repo's own say-so — a worse
trust boundary than today's operator-only allowlist. This issue is scoped ONLY to the top-level,
operator-writable-only (loopover self-repo) fleet-wide switch — it does not reopen Investigate + design config-as-code for ops / sweep_watchdog / pr_reconciliation #4106's question.
true/force-on value to the existing per-reporeview.sweepWatchdog/review.prReconciliationkeys. They stay force-off-only, unchanged.Deliverables
SweepWatchdogManifestOverride+resolveSweepWatchdogManifestOverrideinsweep-watchdog.tsPrReconciliationManifestOverride+resolvePrReconciliationManifestOverrideinpr-reconciliation.tssweepWatchdog:/prReconciliation:top-level manifest config types + parse/serialize functions inpackages/loopover-engine/src/focus-manifest.ts, re-exported fromsrc/signals/focus-manifest.ts.loopover.yml.exampledocuments the two new blocksTest Coverage Requirements
100% branch coverage on both new resolver functions (present+enabled true/false, absent, manifest-load
error → fail-safe), plus the manifest parse/serialize round-trip for both new config types.
src/**andpackages/loopover-engine/src/**are both Codecov-measured (this repo mirrors engine-package coverage perits own root vitest suite) — aim for 99%+ patch on every changed line and branch, including a regression
test asserting a present-but-
enabled:falsemanifest block turns the job off even when the env var is"true", and vice versa.Expected Outcome
An operator can turn
LOOPOVER_SWEEP_WATCHDOGandLOOPOVER_PR_RECONCILIATIONon or off fleet-wide fromthe loopover self-repo's
.loopover.ymlalone, matchingops/draftFlow/publicStats/upstreamDriftIssues's already-shipped precedent, with the env var remaining as the fallback default whenno override block is present.
Links & Resources
OpsManifestOverride/resolveOpsManifestOverride/isOpsEnabledinsrc/review/ops-wire.ts, and its manifest-type sibling inpackages/loopover-engine/src/focus-manifest.ts(
FocusManifestOpsConfig,parseOpsConfig,opsConfigToJson,EMPTY_OPS_CONFIG).NOT_PLANNED— per-repo scan-set axis for these same twojobs, a different question than this issue).