# Plan: hxprobe-specific usage doc (case-by-case) + hxprobe-specific Makefile ## Context `hxprobe` is a fully standalone project (own `pyproject.toml`, `uv.lock`, `README.md` — see `docs/summaries/2026-07-02-09-32-hxprobe-standalone-project.md` and `...-toolchain-modernization.md`). Two gaps remain versus the other Python implementations and versus hxprobe's own "could be `cp -r`'d to its own repo" design goal: 1. **Docs**: `latprobe`/`phases.py`/`simple.py` each have two usage docs — the CLAUDE.md-mandated `docs/usage/py-.md` (what/flags/one example) _and_ a much richer `python/configs/usage-.md` "Runnable Usage Reference" walking through a full set of concrete cases with real captured output (confirmed by reading `python/configs/usage-latprobe.md`, 313 lines: basic, verbose × 4 variants, sampling, multi-URL, `--fail`, JSON × 2, timeout, exit-codes table, Makefile shortcuts). `hxprobe` only has the first kind. User confirmed: add the second kind, placed _inside_ `hxprobe/` itself (not under `python/configs/`, since hxprobe no longer lives there) so the doc travels with the project if extracted. 2. **Makefile**: hxprobe currently has no `Makefile` of its own — the only way to run/test/lint it is through the parent repo's root `Makefile`. Extracted to its own repo, there'd be no `make` interface left. User confirmed: add `hxprobe/Makefile`, fully independent from the root Makefile's existing `hx-*` targets (no delegation either direction — both keep their own complete logic, at the cost of some duplication). Confirmed: neither `latprobe` nor `hxprobe` accept a config file (both take URLs as positional CLI args — only `simple.py`/`phases.py` read the `python/configs/*.txt` files), so no `.txt`-config-file equivalent is needed for hxprobe; this is a docs+Makefile-only task. ## Changes **`hxprobe/USAGE.md`** (new) — modeled directly on `python/configs/usage-latprobe.md`'s structure and tone (concrete `sh` command blocks immediately followed by real captured output, real IPs/certs/ timings, brief explanatory notes, `---` section separators). Cases, in order: 1. Basic — single URL 2. Verbose — HTTPS site (shows `Protocol: HTTP/2`, TLS, cert) 3. Verbose — plain HTTP (no TLS block) 4. Verbose — redirect followed by default (`http://github.com` → 200, `Protocol: HTTP/2 (1 redirect)`) — **hxprobe-specific**, latprobe has no equivalent 5. `--no-follow-redirects` — same URL, raw `301` instead — **hxprobe-specific** 6. `--no-http2` — forces `Protocol: HTTP/1.1` — **hxprobe-specific** 7. Verbose — TLS failure (expired cert, badssl.com) 8. Verbose — DNS failure (empty verbose block, suppressed) 9. Sampling (`-n`) — min/avg/max table, plus verbose+sampling 10. Multiple URLs (parallel probing) 11. `--fail` flag — exit 6 on HTTP 4xx 12. JSON output 13. JSON + verbose (includes `http_version`/`redirect_count` keys) 14. Timeout 15. Exit codes table (same 0–6 scheme as `latprobe`/Go) 16. Makefile shortcuts — both the new `hxprobe/Makefile` (`make run`, `make test`, etc., run from inside `hxprobe/`) and the parent repo's root shortcuts (`make hx-run`, run from the repo root) Cases 1, 2, 3, 4, 5, 6, 8, 11 can reuse real output already captured earlier in this session (still accurate — no code changed since). Cases 7, 9, 10, 12, 13, 14 need fresh live runs during implementation to get real numbers (same standard the other `usage-*.md` docs hold themselves to — no fabricated timings). **`docs/usage/hxprobe.md`** (edit) — add a one-line pointer near the top: "For a full case-by-case runnable reference, see `hxprobe/USAGE.md`." No other changes; it stays the CLAUDE.md-mandated summary doc. **`hxprobe/Makefile`** (new) — fully self-sufficient, same auto-generated `## comment` help style as the root Makefile, short target names (no `hx-` prefix needed since it's already scoped by being inside `hxprobe/`): ```makefile PYTHON ?= python3.14 ARGS ?= .DEFAULT_GOAL := help help # auto-generated from ## comments, same style as root Makefile deps # uv sync run # uv run python -m hxprobe $(ARGS) (deps: deps) lint # uv run ruff check . (deps: deps) fmt # uv run ruff format . (deps: deps) test # uv run pytest tests -m "not integration" -v $(ARGS) (deps: deps) test-integration # uv run pytest tests -m integration -v $(ARGS) (deps: deps) check # lint + test clean # remove __pycache__/*.pyc/*.egg-info/.pytest_cache/.ruff_cache ``` No changes to the root `Makefile` — its existing `hx-*` targets are left exactly as-is per the "keep both independent" decision. **Docs housekeeping** (per CLAUDE.md convention): save this plan to `docs/plans/-hxprobe-usage-doc-and-makefile.md`, write a summary to `docs/summaries/-hxprobe-usage-doc-and-makefile.md` after implementation, and append a `CHANGELOG.md` entry. ## Verification 1. `cd hxprobe && make help` — lists all targets with descriptions, works with zero dependency on the parent repo's Makefile. 2. `cd hxprobe && make run ARGS="-v https://example.com"` — same output as `make hx-run ARGS="-v https://example.com"` from the repo root (proves the two Makefiles agree, without one calling the other). 3. `cd hxprobe && make check` — lint + hermetic tests pass (28 tests). 4. `cd hxprobe && make test-integration` — 9 live tests pass. 5. Re-run every command block in `hxprobe/USAGE.md` and confirm the captured output matches what's printed in the doc (structure must be stable even if exact millisecond timings drift). 6. Confirm the root `Makefile`'s `hx-*` targets are byte-for-byte unchanged (`git diff Makefile` shows no `hx-*` section changes from this task).