Turn the README into a landing page, add a browser analyzer prototype - #17
Merged
Conversation
Runs the deterministic analyzer in the visitor's browser through Pyodide, so an exported Impala profile can be diagnosed without leaving the machine. That removes the objection that blocks most first tries: the profile never reaches a server, and DevTools shows it. The analyzer core needed no changes. It imports no third-party package and no networking or process stdlib, so it loads into Pyodide as built; only the CLI wrapper pulls sockets and subprocesses. The page calls analyzer.service.analyze directly with the seven threshold values it reads. Measured against native CPython on synthetic Impala-shaped profiles: 1.9-2.2x slower, linear at roughly 1.1 s per megabyte, with identical output. Full page in headless Chromium boots in ~1.0 s and diagnoses a 103 KiB profile in 126 ms with no external requests. Pyodide is fetched at build time rather than vendored, keeping ~13 MB of binaries out of git while the built site still serves every asset from its own origin. Not deployed and not linked from the README yet; hosting and output language are still open.
The README was 843 lines, and its first Quickstart command pointed at ./exported-impala-profile.txt, a file the reader does not have. The first thing a visitor tried therefore failed, while the path that works in ten seconds -- query-doctor-web --public-demo -- sat on line 597. It now leads. README drops to 196 lines and README.ru.md to 200. The Support Boundary table, the What Is / Is Not lists, the Trino and Spark detail, the direct-Impala history depth note, and the supported deployment shape move to docs/support-boundary.md, with a Russian companion under docs/i18n/ru/. The three entry paths move to docs/first-path.md with their setup options and troubleshooting intact. The Container and Kubernetes section was already duplicated in deploy/kubernetes/README.md, deploy/helm/query-doctor/README.md, and docs/recent-history-store.md, so it collapses to a run command and links. Several tests asserted specific sentences against README.md, which is the mechanism that grew it to 843 lines in the first place. They now assert against the document that carries the claim -- support-boundary for the SSO proxy, Spark, and Trino boundary text, deploy/kubernetes/README.md for the auth front-door smoke -- so the guarantee survives without pinning prose to the landing page. The Trino test keeps a weaker invariant on both READMEs: they must name the engines, say bounded local production support, and link the boundary doc. Also fixes the stale claim that the 0.11.0 image will be published after the release is approved; ghcr.io/alexandrefimov/query-doctor:0.11.0 has been live since 2026-08-10. The package description now leads with what the tool does instead of four qualifiers, and Development Status moves from Alpha to Beta. The version itself stays at 0.11.0: 1.0 touches seven files plus release metadata and belongs to the release checklist, not a metadata edit. Full suite green (4697 passed), docs CI checks green, ruff clean, and the installed README Quickstart smoke passes against the three commands the README now shows.
The analyzer output from render_md is English, so Russian page chrome read badly against it. English is the canonical documentation language here; a Russian layer belongs under docs/i18n/ru/ if it is ever wanted, not as a second page. Also fixes link labels in the Russian support-boundary document, which kept repo-root paths after the text moved into docs/i18n/ru/. Rebuilt and rechecked in headless Chromium: boot 917 ms, 103 KiB sample profile analyzed in 116 ms, 8 requests, no external hosts, no JS errors.
The rename to ./your-profile.txt reached the quickstart smoke and its test but missed installed_user_paths_smoke.py, which asserts the same literal on the summary it gets back. That is what turned the wheel job red. Door 1 in docs/first-path.md still showed the old name too, so the copy-paste command no longer matched the README. The occurrences left alone are deliberate: docs/changelog.md records what the README said at the time, and SELF_TEST_PROFILE_NAME is the self-test's own synthetic fixture, unrelated to README copy. Reproduced the failing job locally against a clean wheel install: installed user paths ok, full suite 4697 passed.
The page called analyzer.service.analyze on the raw text. That skips the CLI's case staging, which is where query-doctor-analyze applies redaction, so users, pools, emails, secrets, local paths, and host identifiers reached the rendered facts. Nothing was transmitted either way, but rendered output is a browser surface and screenshots of it travel, which is exactly the boundary the safety contract draws. The page now calls safety.redaction.redact_profile_text with the CLI defaults before analyzing. It is pure regex over stdlib, so it loads in Pyodide like the rest of the core. Verified on the sample profile: synthetic_user, synthetic_pool, and 15 host references become <user>, <pool>, and host_NN aliases. Costs about 90 ms on a 103 KiB profile; the page still boots in ~1.0 s and diagnoses the sample in 212 ms with no external requests.
25 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two independent pieces of work on one branch; they can be split if you want the
README landing merged first.
README becomes a landing page (
2979d5f). It was 843 lines, and its firstQuickstart command pointed at
./exported-impala-profile.txt, a file the readerdoes not have — so the first thing a visitor tried failed, while the path that
works in ten seconds (
query-doctor-web --public-demo) sat on line 597. Thatpath now leads. README drops to 196 lines,
README.ru.mdto 200. The SupportBoundary table, What Is / Is Not, Trino and Spark detail, direct-Impala history
depth, and supported deployment shape move to
docs/support-boundary.mdwith aRussian companion; the three entry paths move to
docs/first-path.mdwith setupand troubleshooting intact. The Container/Kubernetes section was already
duplicated in
deploy/anddocs/recent-history-store.md, so it collapses to arun command and links.
Eight tests asserted specific sentences against
README.md, which is themechanism that grew it to 843 lines: every claim got pinned to the landing page.
They now assert against the document that carries the claim. Reviewers should
look at the
tests/andscripts/audit_spark_support_boundary.pydiffs first —that is the contract change, not the prose.
Also fixed: the stale claim that the 0.11.0 image will be published after the
release is approved (it has been live since 2026-08-10), and a package
description that led with four qualifiers instead of what the tool does.
Development Status moves Alpha → Beta; the version stays 0.11.0, since 1.0
touches seven files plus release metadata and belongs to the release checklist.
Browser analyzer prototype (
857e783,47263c8) underweb/. A static pagethat runs the deterministic analyzer in the visitor's browser through Pyodide,
so an exported profile can be diagnosed without leaving the machine. The most
common reason an operator cannot try Query Doctor is that the profile must not
go anywhere; here it does not, and DevTools shows it in ten seconds.
The analyzer core needed no changes — it imports no third-party package and no
networking or process stdlib, so it loads into Pyodide as built. Measured
against native CPython on synthetic Impala-shaped profiles: 1.9–2.2× slower,
linear at ~1.1 s per megabyte, identical output. Full page in headless Chromium:
boot 917 ms, 103 KiB profile in 116 ms, no external requests. Pyodide is fetched
at build time rather than vendored, keeping ~13 MB of binaries out of git while
the built site still serves every asset from its own origin.
Not deployed and not linked from the README. Hosting and wheel trimming are
recorded as open decisions in
web/README.md.Type
Safety Checklist
unknown,not_observed, or explicitly unsupported.web/bench/make_profile.pygenerates profiles withexample.invalidhosts andsynthetic_*identifiers.No support claim changes. The moved text is verbatim; 50 of the 52 body lines in
docs/i18n/ru/support-boundary.mdare byte-identical to the already-publicREADME.ru.mdonmain, the other two being relative-link fixes.Validation
check_active_docs,audit_public_docs,audit_public_distribution_boundary,check_markdown_linksscripts/check_staged_public_safety.py --changedover the whole branch diff: OKpython3 scripts/agent_preflight.pyruff check query_doctor scripts tests web/benchgit diff --checkscripts/installed_readme_quickstart_smoke.pyagainst a clean wheel install, exercising the three commands the README now showsquery-doctor-demo-preflight --public-release: READY_WITH_WARNINGSpre-commit run --all-files— not run locally; CI covers itThe preflight gained four warnings on
docs/first-path.mdfor naminganalysis.json,analysis_facts.md,profile.txt, andCM_PASSWORD. That ismoved text, the scan only inspects changed files, and
docs/local-smoke.mdanddocs/credentials.mdalready carry the same tokens onmain.Documentation
docs/changelog.mdis updated.Branch Hygiene
main.main.Assisted-by: Claude Opus 5 via Claude Code