# Quality and observability The qualities the system is held to — fidelity, correctness, availability, speed, accessibility — how each is measured, where it is gated, how production is watched, and what is not yet wired. - Page: - Updated: 2026-10-26 - Verified against: `05086f5` on 2026-09-27 - From the Sri Guru Granth Sahib Ji — Knowledge Base wiki. Sri Guru Granth Sahib Ji is quoted verbatim, cited by Ang, and never altered. --- Every quality this system promises is backed by something that runs: a CI check, a deploy gate, or a scheduled probe that opens an issue. This page lists them, in order of what matters most: the text first, then correct answers, then being up, then being fast and usable. It ends with what is **not** yet checked automatically. ```mermaid flowchart TB accTitle: Quality is checked before merge, during deploy, and continuously in production accDescr: Before a change merges, the required checks run the unit tests, the scripture integrity check, the golden contract against the local server, and the browser tests. During a deploy, the workflow waits for the API to report the exact commit with every health check true, replays the golden contract and the smoke tests, and rolls production back automatically if the public smoke test fails. In production, scheduled workflows probe uptime every 15 minutes, compare served scripture with the pinned database every six hours, and check the wiki; each opens or updates one GitHub issue when it fails. pr[Before merge:
unit tests, integrity,
golden contract, e2e] pr --> dep[During deploy:
commit identity,
contract, smoke,
auto-rollback] dep --> run[In production:
uptime every 15 min,
data canary every 6 h,
wiki watch] run -->|a failure| issue[One GitHub issue
per watcher,
updated until green] ``` ## The qualities, and what enforces them | Quality | The promise | Measured by | Enforced where | |---|---|---|---| | **Fidelity** | Served scripture is byte-identical to the pinned, proven database | `integrity` (row count, Ang range, `quick_check`, the pin agrees with the contract); the data canary | required check on every PR; every six hours in production | | **Correctness** | Every route answers exactly as recorded | the golden contract: 311 records replayed over HTTP, plus the Roman-fold and scoring vectors | `python` check, the API image, staging and production deploys | | **Search quality** | Casual and misspelt quotations still find the line | the casual-quote and round-trip harnesses (reported; neither has a pass threshold) | `python` check ([harnesses](https://docs.gurbanisoul.com/search/harnesses-and-golden-vectors/)) | | **Availability** | The site and API answer, with every health check true | `uptime.yml`, `/api/health`, `/readyz` | every 15 minutes | | **Recoverability** | A bad deploy never stays live | the public smoke test after promotion | automatic `vercel rollback` ([rollback](https://docs.gurbanisoul.com/process/runbooks/rollback/)) | | **Speed** | p95 per context within 10% of the recorded baseline | `tools/perf_baseline.py --compare` | a manual release step (not in CI) | | **Accessibility** | No serious or critical WCAG issues | axe in Playwright; Lighthouse accessibility = 1 on the wiki | `e2e` and the wiki's `docs` job | ## Health, readiness and identity - **`/api/health`** is the integrity probe. It reports `version`, `db_version`, `commit` and a set of checks, and `ok` is false if any check fails: 60,658 lines, 1,430 Angs, full-text search answering, the Mool Mantar verbatim at Ang 1, at least 560 occurrences of Ik Onkar, a live verification returning an exact match, and the Japji bani mapping. It is never cached. - **`/readyz`** answers per service: the contexts it serves, any declared table missing from its slice, its version and commit. A function whose slice is incomplete refuses to load, and a split-mode server refuses to start. - **`/healthz`** is liveness only. - **Identity.** Deploys are verified by the **commit** the running API reports, not by the version: `wait_for_deploy.py` polls `/api/health` until `commit` equals the deployed SHA and every check is true ([ADR-0009](https://docs.gurbanisoul.com/adr/0009-production-verification/)). - **Tracing a request.** Every response carries `X-Request-Id` (reused from the platform's id when present) and `X-Service`, the context that answered. The same id is in the access log and in `/api/v1` error bodies. ## Watching production | Watcher | When (UTC) | Checks | On failure | |---|---|---|---| | `uptime` | every 15 minutes | `/api/health` all-true; `/`, `/privacy` and `/support` carry their expected text; the wiki and its `/api` rewrite | opens or updates one issue per probe; never redeploys | | `data-canary` | every 6 hours | 500 sampled lines and 12 Angs (always 1, 712 and 1430) from the production site and the Render standby, byte for byte against the pinned database; then the golden contract | one issue, to be treated as P1 | | `docs-watch` | every 6 hours | the production wiki: the deployed commit, the smoke checks, the live Playwright suite | one issue, closed when green | | `deploy-docs` (nightly) | 16:17 daily | the full wiki build and checks on `integration` | one issue, labelled `documentation` | | `docs-links`, `docs-pins`, `docs-freshness` | weekly | external links, sibling-doc pins, pages due for re-verification | an issue or a pin-bump PR | Deploy-time failures open their own issues too: a failed production API verification, and a web rollback after a failed smoke test. ## Logs The API writes one JSON line per request to standard error, which the host collects: `{"m": method, "p": path, "s": status, "ms": duration, "id": request_id}`. The query string, IP address and user agent are never logged, and a test enforces it. An unexpected error adds its traceback. `SGGS_ACCESS_LOG=0` turns request logging off. There is no tracing SDK or error service. ## Speed - **Caching.** Responses that depend only on the immutable database (`ang`, `shabad`, `lines`, `bani`, `banis`, `word`, `analytics/*`, `themes/*`, `timing/*`, `forms`, `neighbors`, `related`, `line_concepts`) are sent `public, max-age=300, s-maxage=3600` with an ETag and answer `If-None-Match` with 304. `health`, `meta`, `random`, `search` and `verify` are `no-store`. Each deploy purges the CDN ([versioning and caching](https://docs.gurbanisoul.com/api/versioning-and-caching/)). - **In the process.** One read-only SQLite connection per thread (memory-mapped, 32 MB page cache); `/api/meta` and `/api/timing/clock` are built once and kept. - **Baseline.** [`docs/perf/baseline-2026-09.json`](https://github.com/Algorythmos-AI/sggs-platform/blob/integration/docs/perf/baseline-2026-09.json) records p50 and p95 per route and per context (60 requests per route, 2 in flight, after one warm-up request), measured against the Render API from Sydney before the move to functions. Context p95 ranged from 365 ms (verify) to 568 ms (reader). Functions scale to zero, and the first request after idle pays a cold start of about a second, which the budget excludes ([ADR-0011](https://docs.gurbanisoul.com/adr/0011-api-as-functions-in-the-web-project/)). ## Not yet wired - **No performance gate in CI.** `perf_baseline.py --compare` is a manual release step; there is no load or soak test ([CI gates](https://docs.gurbanisoul.com/process/ci-gates/)). - **Two search harnesses do not gate.** The round-trip harness runs with `|| true`; the chaos harness is not run by any workflow. - **Some probes still point at the Render standby.** The canary's contract replay, the production API verification step and `make verify-prod` default to `sggs-knowledge-base.onrender.com`, while production's `/api` is served by the Vercel functions. The canary's byte comparison does cover the production site. - **The website has no Lighthouse run and no page budget** beyond the repository gates' weight limits for the Gurbani Soul pages; the wiki has both. - **`api-image` and `deps` are not required checks**, and `playwright` is required only by the deploy workflows, which wait for it.