Skip to content

feat(selfhost): warn loudly when the private config mount is empty - #5977

Merged
JSONbored merged 1 commit into
mainfrom
fix/selfhost-config-dir-empty-guardrail
Jul 15, 2026
Merged

feat(selfhost): warn loudly when the private config mount is empty#5977
JSONbored merged 1 commit into
mainfrom
fix/selfhost-config-dir-empty-guardrail

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

Summary

  • LOOPOVER_REPO_CONFIG_DIR silently degrades to "no local config" -> every setting falls back to built-in defaults, with zero error, whenever its host directory is missing, unmounted, or was renamed without updating the bind mount. This bit a live instance: a prior docker-compose.yml directory-convention rename (./gittensory-config -> ./loopover-config) was never migrated on that host, Docker silently created an empty directory at the new path, and every repo's config-driven settings (labels, gate, autonomy, ...) reverted to defaults with no visible symptom until behavior drifted.
  • Adds emptyConfigDirAdvisory + emptyConfigDirAcknowledgedGaugeValue in src/selfhost/health.ts, mirroring the existing sqliteBackupAdvisory/publicOriginReachabilityAdvisory shape exactly: a loud console.warn at boot plus a loopover_config_dir_empty_acknowledged Prometheus gauge, silenced via CONFIG_DIR_EMPTY_ACKNOWLEDGED=true for a genuinely fresh install with no config written yet.
  • Extends the existing selfhost_config_dir boot log line (src/server.ts) with an entryCount, and extends scripts/selfhost-post-update-check.sh -- the script run after every deploy -- with the same empty-mount check, so the very next deploy verification catches this instead of relying on a human noticing a behavior change days later.
  • Regenerates apps/loopover-ui/src/lib/selfhost-env-reference.ts (new CONFIG_DIR_EMPTY_ACKNOWLEDGED env var) and updates the "equivalent manual checks" list in the self-hosting operations docs page to match.

Test plan

  • npm run test:ci (full local gate) green
  • npm audit --audit-level=moderate — 0 vulnerabilities
  • New emptyConfigDirAdvisory/emptyConfigDirAcknowledgedGaugeValue unit tests: 100% line + branch coverage (verified via lcov)
  • New selfhost-post-update-check.sh regression tests (empty mount warns; populated mount is silent) using the script's existing fake-docker-on-PATH test harness
  • npm run selfhost:env-reference regenerated and committed

LOOPOVER_REPO_CONFIG_DIR silently falls back to built-in defaults for
every per-repo and global setting when its host directory is missing
or was renamed without updating the bind mount -- Docker just creates
an empty directory in its place, with no error anywhere. A prior
docker-compose.yml directory-convention rename left unmigrated on a
live instance hit exactly this: every repo's config-driven settings
(labels, gate, autonomy, ...) silently reverted to defaults with no
visible symptom until behavior drifted days later.

Adds emptyConfigDirAdvisory (mirrors sqliteBackupAdvisory /
publicOriginReachabilityAdvisory's existing shape): a loud boot-time
warning plus a loopover_config_dir_empty_acknowledged gauge, silenced
via CONFIG_DIR_EMPTY_ACKNOWLEDGED=true for a legitimately fresh
install. Also extends selfhost-post-update-check.sh -- the script run
after every deploy -- with the same check, so the very next deploy
verification catches this instead of relying on someone noticing a
behavior change.
@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@codecov

codecov Bot commented Jul 15, 2026

Copy link
Copy Markdown

Bundle Report

Changes will increase total bundle size by 163 bytes (0.01%) ⬆️. This is within the configured threshold ✅

Detailed changes
Bundle name Size Change
loopover-ui 3.04MB 163 bytes (0.01%) ⬆️

Affected Assets, Files, and Routes:

view changes for bundle: loopover-ui

Assets Changed:

Asset Name Size Change Total Size Change (%)
assets/tanstack-vendor-Dif8XsKC.js (New) 718.45kB 718.45kB 100.0% 🚀
assets/maintainer-panel-BcBZ8WTF.js (New) 75.5kB 75.5kB 100.0% 🚀
assets/ui-vendor-BF-usqSI.js (New) 65.83kB 65.83kB 100.0% 🚀
assets/owner-panel-DAlrt7dy.js (New) 58.6kB 58.6kB 100.0% 🚀
assets/docs.self-hosting-configuration-9w86G5ho.js (New) 48.42kB 48.42kB 100.0% 🚀
assets/app.analytics-COy3Yi0N.js (New) 36.26kB 36.26kB 100.0% 🚀
assets/docs.self-hosting-release-checklist-CldY9wI3.js (New) 34.54kB 34.54kB 100.0% 🚀
assets/docs.tuning-DdIN6e3y.js (New) 34.22kB 34.22kB 100.0% 🚀
assets/routes-BJwJklsB.js (New) 34.04kB 34.04kB 100.0% 🚀
assets/app.runs-Bv9tWrc7.js (New) 27.11kB 27.11kB 100.0% 🚀
assets/app-C42RuZQX.js (New) 25.83kB 25.83kB 100.0% 🚀
assets/app.operator-BExGCT-l.js (New) 24.59kB 24.59kB 100.0% 🚀
assets/docs.self-hosting-security-B-B7r6up.js (New) 21.3kB 21.3kB 100.0% 🚀
assets/docs.github-app-Cy35zbjL.js (New) 19.49kB 19.49kB 100.0% 🚀
assets/miner-panel-DQeaeQK9.js (New) 19.23kB 19.23kB 100.0% 🚀
assets/docs.self-hosting-troubleshooting-DYQgdzMS.js (New) 18.47kB 18.47kB 100.0% 🚀
assets/api._op-Bzfk7GNE.js (New) 17.89kB 17.89kB 100.0% 🚀
assets/docs.self-hosting-github-app-BPX8b46f.js (New) 17.32kB 17.32kB 100.0% 🚀
assets/docs.how-reviews-work-Bj-aCJSR.js (New) 16.95kB 16.95kB 100.0% 🚀
assets/app.index-B-ot0DsP.js (New) 16.19kB 16.19kB 100.0% 🚀
assets/docs.maintainer-self-hosting-Dqd5auL3.js (New) 15.99kB 15.99kB 100.0% 🚀
assets/playground-panel-CrC5KAdf.js (New) 14.43kB 14.43kB 100.0% 🚀
assets/docs.self-hosting-quickstart-Eyzjr-V-.js (New) 14.15kB 14.15kB 100.0% 🚀
assets/docs.self-hosting-docs-audit-9BZBUNc4.js (New) 12.14kB 12.14kB 100.0% 🚀
assets/docs.maintainer-install-trust-BfPIuSLw.js (New) 10.51kB 10.51kB 100.0% 🚀
assets/docs.self-hosting-backup-scaling-a6wvgn3A.js (New) 10.06kB 10.06kB 100.0% 🚀
assets/docs.beta-onboarding-CxZQq8tv.js (New) 9.95kB 9.95kB 100.0% 🚀
assets/app.audit-BZJQeTN2.js (New) 9.35kB 9.35kB 100.0% 🚀
assets/extension-D93JJIFW.js (New) 9.21kB 9.21kB 100.0% 🚀
assets/docs.self-hosting-rees-Xqz_r14l.js (New) 8.95kB 8.95kB 100.0% 🚀
assets/docs.self-hosting-ai-providers-BlUlZgQM.js (New) 8.92kB 8.92kB 100.0% 🚀
assets/app.config-generator-16pmC5yL.js (New) 8.13kB 8.13kB 100.0% 🚀
assets/maintainers-CkJBgbSn.js (New) 8.06kB 8.06kB 100.0% 🚀
assets/miners-CUypq11g.js (New) 7.88kB 7.88kB 100.0% 🚀
assets/agents-1dxq_v25.js (New) 7.76kB 7.76kB 100.0% 🚀
assets/docs.privacy-security-BUTYpqDf.js (New) 7.21kB 7.21kB 100.0% 🚀
assets/docs.owner-checklist-B8hy9fxU.js (New) 7.0kB 7.0kB 100.0% 🚀
assets/commands-panel-DZGoQ6s6.js (New) 6.65kB 6.65kB 100.0% 🚀
assets/docs.self-hosting-releases-DU5s0Bhm.js (New) 6.62kB 6.62kB 100.0% 🚀
assets/roadmap-rBUC4frG.js (New) 6.33kB 6.33kB 100.0% 🚀
assets/docs.self-hosting-rees-analyzers-Bd631kXv.js (New) 6.05kB 6.05kB 100.0% 🚀
assets/digest-panel-ihKQVxLL.js (New) 6.04kB 6.04kB 100.0% 🚀
assets/docs.loopover-commands-Dba6jQG0.js (New) 5.18kB 5.18kB 100.0% 🚀
assets/docs.scoreability-BmKQSiUd.js (New) 5.05kB 5.05kB 100.0% 🚀
assets/docs.troubleshooting-DG8Nk2--.js (New) 4.91kB 4.91kB 100.0% 🚀
assets/repos._owner._repo.quality-D-v6e9kf.js (New) 4.87kB 4.87kB 100.0% 🚀
assets/api.index-3GKiIzPP.js (New) 4.78kB 4.78kB 100.0% 🚀
assets/docs.index-CkAdqis6.js (New) 4.68kB 4.68kB 100.0% 🚀
assets/changelog-BLhdsOST.js (New) 4.67kB 4.67kB 100.0% 🚀
assets/docs.maintainer-workflow-B8aDO4lC.js (New) 4.36kB 4.36kB 100.0% 🚀
assets/docs.self-hosting-rag-C2GVenu0.js (New) 4.35kB 4.35kB 100.0% 🚀
assets/control-primitives-BvQ7XYPd.js (New) 3.75kB 3.75kB 100.0% 🚀
assets/docs.ai-summaries-BTNf3XNU.js (New) 3.04kB 3.04kB 100.0% 🚀
assets/docs.branch-analysis-D91CTjdB.js (New) 2.91kB 2.91kB 100.0% 🚀
assets/docs.mcp-clients-D2pACjRS.js (New) 2.9kB 2.9kB 100.0% 🚀
assets/api-C0gmcORb.js (New) 2.73kB 2.73kB 100.0% 🚀
assets/docs-DPIUaI8g.js (New) 2.67kB 2.67kB 100.0% 🚀
assets/docs.quickstart-BOgrZFcl.js (New) 2.1kB 2.1kB 100.0% 🚀
assets/alert-dialog-eGvvefUK.js (New) 2.07kB 2.07kB 100.0% 🚀
assets/docs.upstream-drift-3TjedH52.js (New) 2.04kB 2.04kB 100.0% 🚀
assets/button-UOQnhyYn.js (New) 1.74kB 1.74kB 100.0% 🚀
assets/app.workbench-D1Sldna1.js (New) 1.63kB 1.63kB 100.0% 🚀
assets/tooltip-BbTfeqY5.js (New) 1.45kB 1.45kB 100.0% 🚀
assets/session-BxQU1jzG.js (New) 1.44kB 1.44kB 100.0% 🚀
assets/tabs-DzrbttIm.js (New) 1.39kB 1.39kB 100.0% 🚀
assets/trend-chart-G1l8Vs2i.js (New) 1.22kB 1.22kB 100.0% 🚀
assets/app.repos-ZpqmYp8w.js (New) 1.07kB 1.07kB 100.0% 🚀
assets/switch-9Blna0--.js (New) 982 bytes 982 bytes 100.0% 🚀
assets/analytics-card-shell-Dn6SC1uI.js (New) 972 bytes 972 bytes 100.0% 🚀
assets/use-api-resource-BF9LO61y.js (New) 934 bytes 934 bytes 100.0% 🚀
assets/input-BK0DPyzZ.js (New) 796 bytes 796 bytes 100.0% 🚀
assets/refresh-meta-BsVJIChW.js (New) 796 bytes 796 bytes 100.0% 🚀
assets/file-cog-CIFPeuXq.js (New) 758 bytes 758 bytes 100.0% 🚀
assets/app.maintainer-B3NgOmzL.js (New) 501 bytes 501 bytes 100.0% 🚀
assets/sparkles-xHCPDtps.js (New) 494 bytes 494 bytes 100.0% 🚀
assets/app.owner-DWi4pDK8.js (New) 473 bytes 473 bytes 100.0% 🚀
assets/app.commands-eTbNciWs.js (New) 454 bytes 454 bytes 100.0% 🚀
assets/reveal-CUGo_wiF.js (New) 442 bytes 442 bytes 100.0% 🚀
assets/app.playground-DBI5WbDx.js (New) 441 bytes 441 bytes 100.0% 🚀
assets/index-BzhXLtpe.js (New) 438 bytes 438 bytes 100.0% 🚀
assets/eye-off-D8Rnge7Y.js (New) 430 bytes 430 bytes 100.0% 🚀
assets/app.digest-BQWvCYM7.js (New) 429 bytes 429 bytes 100.0% 🚀
assets/app.miner-CgTNq_4L.js (New) 421 bytes 421 bytes 100.0% 🚀
assets/key-round-BiI7fpvr.js (New) 355 bytes 355 bytes 100.0% 🚀
assets/bot-Cx94FS-b.js (New) 328 bytes 328 bytes 100.0% 🚀
assets/trash-2-C218Pwvw.js (New) 328 bytes 328 bytes 100.0% 🚀
assets/save-FykLfS3u.js (New) 327 bytes 327 bytes 100.0% 🚀
assets/git-pull-request-arrow-CCUspvSv.js (New) 321 bytes 321 bytes 100.0% 🚀
assets/shield-check-C79agp9f.js (New) 320 bytes 320 bytes 100.0% 🚀
assets/wrench-DXD88PDo.js (New) 303 bytes 303 bytes 100.0% 🚀
assets/bell-Dhr5idbi.js (New) 290 bytes 290 bytes 100.0% 🚀
assets/list-checks-DUNlurVD.js (New) 279 bytes 279 bytes 100.0% 🚀
assets/shield-D7DVOAka.js (New) 272 bytes 272 bytes 100.0% 🚀
assets/workflow-BvCgcpba.js (New) 265 bytes 265 bytes 100.0% 🚀
assets/chart-column-D7gHM-F0.js (New) 251 bytes 251 bytes 100.0% 🚀
assets/compass-BvKaWIeM.js (New) 251 bytes 251 bytes 100.0% 🚀
assets/skeleton-oSijkFy5.js (New) 241 bytes 241 bytes 100.0% 🚀
assets/history-DlURcTFS.js (New) 237 bytes 237 bytes 100.0% 🚀
assets/activity-C4uWexvl.js (New) 234 bytes 234 bytes 100.0% 🚀
assets/message-square-asBzEXDL.js (New) 233 bytes 233 bytes 100.0% 🚀
assets/download-BskLXpBs.js (New) 232 bytes 232 bytes 100.0% 🚀
assets/chevron-right-CU7WbaZp.js (New) 207 bytes 207 bytes 100.0% 🚀
assets/lock-DWhUezzb.js (New) 206 bytes 206 bytes 100.0% 🚀
assets/rotate-cw-REpNRjY7.js (New) 201 bytes 201 bytes 100.0% 🚀
assets/play-CrWDrTJp.js (New) 190 bytes 190 bytes 100.0% 🚀
assets/circle-check-ND1Mnxid.js (New) 178 bytes 178 bytes 100.0% 🚀
assets/search-BxzAbrUF.js (New) 174 bytes 174 bytes 100.0% 🚀
assets/circle-BO1hJ_ci.js (New) 130 bytes 130 bytes 100.0% 🚀
assets/tanstack-vendor-B83QpdiJ.js (Deleted) -718.34kB 0 bytes -100.0% 🗑️
assets/maintainer-panel-BqkBAFCk.js (Deleted) -75.5kB 0 bytes -100.0% 🗑️
assets/ui-vendor-Clmy7-t8.js (Deleted) -65.83kB 0 bytes -100.0% 🗑️
assets/owner-panel-C3UlnENQ.js (Deleted) -58.6kB 0 bytes -100.0% 🗑️
assets/docs.self-hosting-configuration-DJ66FDU7.js (Deleted) -48.37kB 0 bytes -100.0% 🗑️
assets/app.analytics-uqaHyAdT.js (Deleted) -36.26kB 0 bytes -100.0% 🗑️
assets/docs.self-hosting-release-checklist-ChRAo-Q-.js (Deleted) -34.54kB 0 bytes -100.0% 🗑️
assets/docs.tuning-8ihvWHbS.js (Deleted) -34.22kB 0 bytes -100.0% 🗑️
assets/routes-CRCsDBUz.js (Deleted) -34.04kB 0 bytes -100.0% 🗑️
assets/app.runs-BPsjVe0Q.js (Deleted) -27.11kB 0 bytes -100.0% 🗑️
assets/app-rrn8zHMf.js (Deleted) -25.83kB 0 bytes -100.0% 🗑️
assets/app.operator-BjeAj_ZV.js (Deleted) -24.59kB 0 bytes -100.0% 🗑️
assets/docs.self-hosting-security-CqUzlFMg.js (Deleted) -21.3kB 0 bytes -100.0% 🗑️
assets/docs.github-app-CEtLj_Hj.js (Deleted) -19.49kB 0 bytes -100.0% 🗑️
assets/miner-panel-DYoLgoHu.js (Deleted) -19.23kB 0 bytes -100.0% 🗑️
assets/docs.self-hosting-troubleshooting-vxBkmAa-.js (Deleted) -18.47kB 0 bytes -100.0% 🗑️
assets/api._op-CH251qxP.js (Deleted) -17.89kB 0 bytes -100.0% 🗑️
assets/docs.self-hosting-github-app-DZQQK4Yl.js (Deleted) -17.32kB 0 bytes -100.0% 🗑️
assets/docs.how-reviews-work-EUVuMEUP.js (Deleted) -16.95kB 0 bytes -100.0% 🗑️
assets/app.index-DhBmCPGJ.js (Deleted) -16.19kB 0 bytes -100.0% 🗑️
assets/docs.maintainer-self-hosting-CKmOjnvo.js (Deleted) -15.99kB 0 bytes -100.0% 🗑️
assets/playground-panel-DB6EAmsM.js (Deleted) -14.43kB 0 bytes -100.0% 🗑️
assets/docs.self-hosting-quickstart-DLHB53Qw.js (Deleted) -14.15kB 0 bytes -100.0% 🗑️
assets/docs.self-hosting-docs-audit-CrFtkcEo.js (Deleted) -12.14kB 0 bytes -100.0% 🗑️
assets/docs.maintainer-install-trust-BdR3u72X.js (Deleted) -10.51kB 0 bytes -100.0% 🗑️
assets/docs.self-hosting-backup-scaling-C8Faheg2.js (Deleted) -10.06kB 0 bytes -100.0% 🗑️
assets/docs.beta-onboarding-BNtn_cQH.js (Deleted) -9.95kB 0 bytes -100.0% 🗑️
assets/app.audit-BU661x-v.js (Deleted) -9.35kB 0 bytes -100.0% 🗑️
assets/extension-DqRdYVaL.js (Deleted) -9.21kB 0 bytes -100.0% 🗑️
assets/docs.self-hosting-rees-CqwUFuc_.js (Deleted) -8.95kB 0 bytes -100.0% 🗑️
assets/docs.self-hosting-ai-providers-BcLK-8hZ.js (Deleted) -8.92kB 0 bytes -100.0% 🗑️
assets/app.config-generator-DhIgMIud.js (Deleted) -8.13kB 0 bytes -100.0% 🗑️
assets/maintainers-CQoY3VFD.js (Deleted) -8.06kB 0 bytes -100.0% 🗑️
assets/miners-BtijoBHo.js (Deleted) -7.88kB 0 bytes -100.0% 🗑️
assets/agents-C4bfwi8R.js (Deleted) -7.76kB 0 bytes -100.0% 🗑️
assets/docs.privacy-security-B7ktSqsJ.js (Deleted) -7.21kB 0 bytes -100.0% 🗑️
assets/docs.owner-checklist-B_q8eOyf.js (Deleted) -7.0kB 0 bytes -100.0% 🗑️
assets/commands-panel-Bt42stae.js (Deleted) -6.65kB 0 bytes -100.0% 🗑️
assets/docs.self-hosting-releases-DDx6fd9o.js (Deleted) -6.62kB 0 bytes -100.0% 🗑️
assets/roadmap-NPPVl4xc.js (Deleted) -6.33kB 0 bytes -100.0% 🗑️
assets/docs.self-hosting-rees-analyzers-cdnA_Asf.js (Deleted) -6.05kB 0 bytes -100.0% 🗑️
assets/digest-panel-DD7k9-pE.js (Deleted) -6.04kB 0 bytes -100.0% 🗑️
assets/docs.loopover-commands-BkEoezrO.js (Deleted) -5.18kB 0 bytes -100.0% 🗑️
assets/docs.scoreability-Cy16uQP6.js (Deleted) -5.05kB 0 bytes -100.0% 🗑️
assets/docs.troubleshooting-CVAETSbc.js (Deleted) -4.91kB 0 bytes -100.0% 🗑️
assets/repos._owner._repo.quality-CQAw5Dyh.js (Deleted) -4.87kB 0 bytes -100.0% 🗑️
assets/api.index-BbrzA0HH.js (Deleted) -4.78kB 0 bytes -100.0% 🗑️
assets/docs.index-BfgF3i2K.js (Deleted) -4.68kB 0 bytes -100.0% 🗑️
assets/changelog-0xV0YnAq.js (Deleted) -4.67kB 0 bytes -100.0% 🗑️
assets/docs.maintainer-workflow-Z1NTyTt2.js (Deleted) -4.36kB 0 bytes -100.0% 🗑️
assets/docs.self-hosting-rag-DUSmlh6A.js (Deleted) -4.35kB 0 bytes -100.0% 🗑️
assets/control-primitives-MY6j18Gw.js (Deleted) -3.75kB 0 bytes -100.0% 🗑️
assets/docs.ai-summaries-B4ea_UBl.js (Deleted) -3.04kB 0 bytes -100.0% 🗑️
assets/docs.branch-analysis-B-2fy8vf.js (Deleted) -2.91kB 0 bytes -100.0% 🗑️
assets/docs.mcp-clients-Ba3Fa9wv.js (Deleted) -2.9kB 0 bytes -100.0% 🗑️
assets/api-46hPwYNX.js (Deleted) -2.73kB 0 bytes -100.0% 🗑️
assets/docs-CoMsZ6B3.js (Deleted) -2.67kB 0 bytes -100.0% 🗑️
assets/docs.quickstart-DGhPxrXG.js (Deleted) -2.1kB 0 bytes -100.0% 🗑️
assets/alert-dialog-BUdakRbk.js (Deleted) -2.07kB 0 bytes -100.0% 🗑️
assets/docs.upstream-drift-BrvadXpc.js (Deleted) -2.04kB 0 bytes -100.0% 🗑️
assets/button-kJgA4vf6.js (Deleted) -1.74kB 0 bytes -100.0% 🗑️
assets/app.workbench-DfZKMZpb.js (Deleted) -1.63kB 0 bytes -100.0% 🗑️
assets/tooltip-CFeitjff.js (Deleted) -1.45kB 0 bytes -100.0% 🗑️
assets/session-CNTrXujU.js (Deleted) -1.44kB 0 bytes -100.0% 🗑️
assets/tabs-CL3LtPgE.js (Deleted) -1.39kB 0 bytes -100.0% 🗑️
assets/trend-chart-BUUFGHG1.js (Deleted) -1.22kB 0 bytes -100.0% 🗑️
assets/app.repos-DGO1ll41.js (Deleted) -1.07kB 0 bytes -100.0% 🗑️
assets/switch-Dc_vPTOd.js (Deleted) -982 bytes 0 bytes -100.0% 🗑️
assets/analytics-card-shell-BX6E5hJV.js (Deleted) -972 bytes 0 bytes -100.0% 🗑️
assets/use-api-resource-DIKkkmX5.js (Deleted) -934 bytes 0 bytes -100.0% 🗑️
assets/input-B3qL5nI0.js (Deleted) -796 bytes 0 bytes -100.0% 🗑️
assets/refresh-meta-B_3-jx9V.js (Deleted) -796 bytes 0 bytes -100.0% 🗑️
assets/file-cog-BxkQWG7H.js (Deleted) -758 bytes 0 bytes -100.0% 🗑️
assets/app.maintainer-BKRLHh7Q.js (Deleted) -501 bytes 0 bytes -100.0% 🗑️
assets/sparkles-DcPvc_um.js (Deleted) -494 bytes 0 bytes -100.0% 🗑️
assets/app.owner-CLp89A5t.js (Deleted) -473 bytes 0 bytes -100.0% 🗑️
assets/app.commands-CdUzNyGX.js (Deleted) -454 bytes 0 bytes -100.0% 🗑️
assets/reveal-WIZ9nlR4.js (Deleted) -442 bytes 0 bytes -100.0% 🗑️
assets/app.playground-sQ9pE7I-.js (Deleted) -441 bytes 0 bytes -100.0% 🗑️
assets/index-BqzHZ56t.js (Deleted) -438 bytes 0 bytes -100.0% 🗑️
assets/eye-off-BVpnhwl6.js (Deleted) -430 bytes 0 bytes -100.0% 🗑️
assets/app.digest-CgOJQJLn.js (Deleted) -429 bytes 0 bytes -100.0% 🗑️
assets/app.miner-B4EUV-r8.js (Deleted) -421 bytes 0 bytes -100.0% 🗑️
assets/key-round-Dn1Pq-lP.js (Deleted) -355 bytes 0 bytes -100.0% 🗑️
assets/bot-D0iUIl_C.js (Deleted) -328 bytes 0 bytes -100.0% 🗑️
assets/trash-2-BVhgUDiU.js (Deleted) -328 bytes 0 bytes -100.0% 🗑️
assets/save-C9hWvom4.js (Deleted) -327 bytes 0 bytes -100.0% 🗑️
assets/git-pull-request-arrow-BL6HVoYj.js (Deleted) -321 bytes 0 bytes -100.0% 🗑️
assets/shield-check-BR1ZWQIw.js (Deleted) -320 bytes 0 bytes -100.0% 🗑️
assets/wrench-D09wq3zv.js (Deleted) -303 bytes 0 bytes -100.0% 🗑️
assets/bell-Dd3AJV3m.js (Deleted) -290 bytes 0 bytes -100.0% 🗑️
assets/list-checks-BZYPtkMi.js (Deleted) -279 bytes 0 bytes -100.0% 🗑️
assets/shield-BfsWVOAZ.js (Deleted) -272 bytes 0 bytes -100.0% 🗑️
assets/workflow-DpP3e5F6.js (Deleted) -265 bytes 0 bytes -100.0% 🗑️
assets/chart-column-fmlep58J.js (Deleted) -251 bytes 0 bytes -100.0% 🗑️
assets/compass-BNuvYpam.js (Deleted) -251 bytes 0 bytes -100.0% 🗑️
assets/skeleton-DC7qKnHl.js (Deleted) -241 bytes 0 bytes -100.0% 🗑️
assets/history-DlS6luMt.js (Deleted) -237 bytes 0 bytes -100.0% 🗑️
assets/activity-C9HJkj6V.js (Deleted) -234 bytes 0 bytes -100.0% 🗑️
assets/message-square-B9tvAU8g.js (Deleted) -233 bytes 0 bytes -100.0% 🗑️
assets/download-D1HyQQzg.js (Deleted) -232 bytes 0 bytes -100.0% 🗑️
assets/chevron-right-BKWeqZCD.js (Deleted) -207 bytes 0 bytes -100.0% 🗑️
assets/lock-7YY7VRFi.js (Deleted) -206 bytes 0 bytes -100.0% 🗑️
assets/rotate-cw-B3CeZKoT.js (Deleted) -201 bytes 0 bytes -100.0% 🗑️
assets/play-Dca2LmKk.js (Deleted) -190 bytes 0 bytes -100.0% 🗑️
assets/circle-check-wTEf-dU-.js (Deleted) -178 bytes 0 bytes -100.0% 🗑️
assets/search-CTJoxJpf.js (Deleted) -174 bytes 0 bytes -100.0% 🗑️
assets/circle-DnNJ9S84.js (Deleted) -130 bytes 0 bytes -100.0% 🗑️

@codecov

codecov Bot commented Jul 15, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.16%. Comparing base (7e36a60) to head (6b97ffe).
⚠️ Report is 13 commits behind head on main.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #5977   +/-   ##
=======================================
  Coverage   95.16%   95.16%           
=======================================
  Files         589      589           
  Lines       46776    46779    +3     
  Branches    14934    14936    +2     
=======================================
+ Hits        44514    44517    +3     
  Misses       1511     1511           
  Partials      751      751           
Flag Coverage Δ
shard-1 43.90% <0.00%> (-0.01%) ⬇️
shard-2 36.19% <0.00%> (-0.01%) ⬇️
shard-3 31.96% <0.00%> (-0.01%) ⬇️
shard-4 31.96% <100.00%> (+<0.01%) ⬆️
shard-5 32.50% <0.00%> (-0.01%) ⬇️
shard-6 44.70% <0.00%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/selfhost/health.ts 100.00% <100.00%> (ø)
src/selfhost/metrics.ts 100.00% <ø> (ø)

@loopover-orb loopover-orb Bot added the gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier. label Jul 15, 2026
@loopover-orb

loopover-orb Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Warning

🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨

⏸️ LoopOver review result - manual review recommended

Review updated: 2026-07-15 05:29:11 UTC

8 files · 1 AI reviewer · 2 blockers · readiness 93/100 · CI green · clean

⏸️ Suggested Action - Manual Review

Review summary
Adds a boot-time advisory + Prometheus gauge (src/selfhost/health.ts) that fires when LOOPOVER_REPO_CONFIG_DIR is set but the mounted directory has zero top-level entries, wires it into src/server.ts's boot log and a new gauge, extends the post-update-check script and the self-hosting docs' manual-check list with an equivalent empty-mount check, and regenerates the env-reference table for the new CONFIG_DIR_EMPTY_ACKNOWLEDGED opt-out. The advisory/gauge logic (emptyConfigDirAdvisory / emptyConfigDirAcknowledgedGaugeValue) is a straightforward, correctly-guarded mirror of the existing sqliteBackupAdvisory/publicOriginReachabilityAdvisory pattern, safeReaddirCount fails closed to 0 rather than crashing boot, and the shell check in selfhost-post-update-check.sh is non-fatal and numerically validated before acting on its output. Tests cover all four boolean combinations of configured/entryCount/acknowledged for both functions and both branches (empty vs populated) of the shell script via its existing fake-docker harness.

Nits — 5 non-blocking
  • src/server.ts: `configDirOpts.entryCount` is computed once but then re-gated a second time by `repoConfigDir ?` in the log line (`entryCount: repoConfigDir ? configDirOpts.entryCount : null`) — since `safeReaddirCount` already returns 0 for an unset dir, this could just be `configDirOpts.entryCount` directly (safe to simplify, not a defect).
  • scripts/selfhost-post-update-check.sh: the `docker exec ... 2>/dev/null || true` swallows any exec failure (e.g. container not running that command, permission error) into the `[[ ... ]] && ... -eq 0` check silently failing to match the numeric regex, so a genuine problem running the check fails open (no warning) rather than being surfaced — acceptable for a non-fatal advisory but worth a one-line comment noting the fail-open behavior is intentional.
  • apps/loopover-ui/.../docs.self-hosting-operations.tsx: the added `docker exec ... ls -A ...` line duplicates the shell check now also embedded in selfhost-post-update-check.sh — if the script's logic (e.g. default path) ever changes, this doc snippet could drift out of sync since nothing enforces parity between the two.
  • Consider having the docs snippet at docs.self-hosting-operations.tsx:1145 just tell operators to run selfhost-post-update-check.sh (which now already performs this check) instead of duplicating the raw `docker exec` command, to avoid the two falling out of sync.
  • In src/server.ts, drop the redundant `repoConfigDir ?` re-check on `entryCount` in the JSON log line since `configDirOpts.entryCount` is already 0 for an unset dir.

Concerns raised — review before merging

  • No linked issue detected — If this PR is intended to solve an issue, link it explicitly in the PR body.
  • Maintainer requires a linked issue — Link the relevant issue (for example Closes #123) before opening the PR.
📋 Copy for AI agents — paste into your coding agent
Fix the following blocker(s) from this PR review:

1. No linked issue detected — If this PR is intended to solve an issue, link it explicitly in the PR body.

2. Maintainer requires a linked issue — Link the relevant issue (for example `Closes #123`) before opening the PR.
Signal Result Evidence
Code review ❌ 2 blockers 1 reviewer
Linked issue ⚠️ Missing No linked issue or no-issue rationale found.
Related work ✅ No active overlap found No same-issue or scoped active PR overlap found.
Change scope ✅ 20/20 Low review scope from cached public metadata (no linked issue context).
Validation posture ✅ 25/25 PR body includes validation/test evidence.
Contributor workload ✅ 10/10 Author activity: 43 registered-repo PR(s), 35 merged, 401 issue(s).
Contributor context ✅ Confirmed Gittensor contributor JSONbored; Gittensor profile; 43 PR(s), 401 issue(s).
Gate result ❌ Blocking Repo-configured hard blocker found.
Improvement ✅ Minor risk: clean · value: minor · LLM: moderate
Review context
  • Author: JSONbored
  • Role context: owner (maintainer lane)
  • Public audience mode: oss maintainer
  • Lane context: Repository is configured for direct PR review.
  • Public profile languages: not available
  • Official Gittensor activity: 43 PR(s), 401 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Start here: Treat this as maintainer-lane context rather than normal contributor-lane activity.
  • Then work through the remaining 2 steps in the Signals table above.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Change scope = cached public metadata such as size labels, draft state, and review-burden hints.
  • Validation posture = whether the PR provides enough public validation/test evidence for maintainer review.
  • Contributor workload = public contributor activity and cleanup pressure, not a repo-wide quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.
🧪 Chat with LoopOver

Ask LoopOver a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.

  • @loopover ask &lt;question&gt; answers contribution-quality Q&A with source citations and freshness.
  • @loopover chat &lt;question&gt; answers in natural prose from cached decision-pack facts via local inference (maintainer/collaborator; read-only).
  • A plain-language @loopover mention with a real question is routed to the closest matching read-only command automatically — no exact syntax required.

Full command reference: https://gittensory.aethereal.dev/docs/loopover-commands

🧪 Experimental — new and may change.

🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed


💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →.

Checked by LoopOver, a quiet PR intelligence layer for OSS maintainers.

  • Re-run LoopOver review

@loopover-orb loopover-orb Bot added the manual-review Gittensor contributor context label Jul 15, 2026
@JSONbored
JSONbored merged commit a8d168d into main Jul 15, 2026
20 checks passed
@JSONbored
JSONbored deleted the fix/selfhost-config-dir-empty-guardrail branch July 15, 2026 05:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier. manual-review Gittensor contributor context

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant