Skip to content

chore(selfhost): docker-compose.yml PROFILES header is missing ams-observability and backup #5812

Description

@JSONbored

Context

docker-compose.yml's header comment block (lines 6-19) documents the full set of --profile flags an
operator can pass, under the banner "PROFILES — activate optional services by passing --profile <name>
(combine freely)":

--profile postgres, pgbouncer, qdrant, ollama, gpu, visual-review, rees, litestream, caddy,
observability, tailscale, runners

That list is stale. Grepping the file for every profiles: [...] a service actually declares turns up
two profiles that are real, wired, working services but are missing from the header list:

  • ams-observability — used by the ams-reporting-exporter service (docker-compose.yml ~line 850),
    which redacts and exports the AMS (loopover-miner) attempt-log/prediction-ledger SQLite stores for the
    "AMS Attempt Log" / "AMS Prediction Ledger" Grafana datasources
    (grafana/provisioning/datasources/ams-ledgers.yml). This profile is real enough that it's documented
    in .env.example (search LOOPOVER_AMS_REPORTING_EXPORT_INTERVAL_SECONDS), on the website
    (docs.ams-observability-callout.tsx / docs.self-hosting-operations.tsx), and in
    packages/loopover-miner/docs/observability.md — just not in the one place a self-hoster is most
    likely to look first: the compose file's own profile banner.
  • backup — used by both the backup service and the backup-exporter service (~lines 1103, 1150),
    which run scheduled pg_dump/SQLite-online-backup + Qdrant-snapshot backups and expose backup-freshness
    metrics to Prometheus. This profile IS mentioned later in the file's inline comments (e.g. the Grafana
    service's depends_on note) and in apps/loopover-ui/src/routes/docs.self-hosting-operations.tsx, but
    is absent from the top-of-file banner that enumerates "the" profile list.

An operator skimming only the header (the documented entry point — "PROFILES — activate optional services
by passing --profile <name>") has no way to discover either profile exists without reading the entire
~1,170-line file or the separate website docs. This is exactly the kind of drift the repo already guards
against for other doc/runtime pairs (e.g. npm run selfhost:env-reference,
apps/loopover-ui/src/lib/selfhost-docs-audit.ts) — there is currently no automated check that the header
banner's profile list matches the profiles services actually declare.

Requirements

  • Add ams-observability and backup to the docker-compose.yml header's PROFILES comment block, each
    with a one-line description matching the style of the existing entries (see the observability and
    rees lines for tone/length).
  • Add a regression test (e.g. a new test/unit/docker-compose-profiles-header.test.ts, following the
    existing pattern in test/unit/docker-compose-override-example.test.ts / test/unit/miner-docker-compose.test.ts
    for reading/parsing this file) that:
    • Parses every profiles: [...] array declared anywhere in docker-compose.yml.
    • Extracts every --profile <name> token mentioned in the header comment block (lines before the
      services: key).
    • Asserts the two sets are equal, so a future profile addition/removal that forgets to update the
      banner fails CI with a clear message instead of silently drifting again.

Deliverables

  • docker-compose.yml header PROFILES list includes ams-observability and backup, each documented
    in the same style as the existing entries.
  • A new drift-guard test asserting the header's profile list and the file's actual profiles: [...]
    declarations always match.

Test Coverage Requirements

This touches docker-compose.yml (not src/**, so it is outside coverage.include and Codecov's
patch-coverage gate does not apply to the YAML edit itself) plus a new test file under test/unit/**,
which IS measured. The new drift-guard test must cover both branches of the equality assertion (a
passing case against the real file, and at least one deliberately-broken fixture case — e.g. a profile
declared in profiles: but missing from the header, and vice versa — to prove the assertion actually
fails when the lists diverge, not just that it passes today).

Expected Outcome

An operator who reads only docker-compose.yml's header comment sees the complete, accurate list of
every --profile flag the file supports, including ams-observability and backup. A future PR that
adds or renames a profile without updating the header fails CI instead of shipping silent doc drift.

Links & Resources

  • docker-compose.yml (header lines 6-19; ams-reporting-exporter ~line 850; backup/backup-exporter
    ~lines 1103, 1150)
  • .env.example (LOOPOVER_AMS_REPORTING_EXPORT_INTERVAL_SECONDS, LOOPOVER_MINER_CONFIG_DIR)
  • packages/loopover-miner/docs/observability.md
  • apps/loopover-ui/src/routes/docs.self-hosting-operations.tsx
  • Related prior art: test/unit/docker-compose-override-example.test.ts,
    test/unit/miner-docker-compose.test.ts, apps/loopover-ui/src/lib/selfhost-docs-audit.ts (the same
    "doc must match runtime source of truth" pattern applied elsewhere in this repo)

Metadata

Metadata

Assignees

No one assigned

    Labels

    gittensor:bugGittensor-scored bug fix — scores a 0.05x multiplier.help wantedExtra attention is needed

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions