docs: hxprobe plans, summaries, explanations, usage, and changelog
Plans (docs/plans/): - 2026-07-01-23-47-py-hxprobe-httpx.md — initial httpx probe design - 2026-07-02-09-32 through 14-05 — standalone project, toolchain, usage doc + Makefile, file input (-f), simplification pass, run-summary footer Summaries (docs/summaries/): one per completed feature, recording what was actually built, deviations from the plan, and verification steps Explanations (docs/explanations/): two deep-dives written during review — hxprobe concurrency model and worst-exit-code + render-loop analysis Usage (docs/usage/hxprobe.md): overview with pointer to hxprobe/USAGE.md for the full runnable reference Walkthrough (docs/py-latprobe-walkthrough.md): narrative tour of the latprobe Python package for interview / code-review context CHANGELOG.md: entries for all hxprobe features (toolchain, usage doc, file input, simplification, run-summary footer) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
117
docs/summaries/2026-07-02-09-32-hxprobe-standalone-project.md
Normal file
117
docs/summaries/2026-07-02-09-32-hxprobe-standalone-project.md
Normal file
@@ -0,0 +1,117 @@
|
||||
# Summary: extract `hxprobe` into a standalone top-level project
|
||||
|
||||
Plan: [docs/plans/2026-07-02-09-32-hxprobe-standalone-project.md](../plans/2026-07-02-09-32-hxprobe-standalone-project.md)
|
||||
|
||||
## What was built
|
||||
|
||||
`hxprobe` moved from `python/hxprobe/` to a new top-level `hxprobe/`
|
||||
directory (sibling of `go/` and `python/`), structured as a genuinely
|
||||
independent project: own `pyproject.toml`, own venv (`hxprobe/.venv`), own
|
||||
`tests/` directory. It imports nothing from `python/latprobe` — verified with
|
||||
`grep -rn "latprobe" hxprobe/` returning zero matches in code (a few comments
|
||||
mention Go's `http.DefaultClient` for context, which is fine; no comment
|
||||
references `latprobe` as a concrete path/module anymore either).
|
||||
|
||||
Files:
|
||||
- `hxprobe/pyproject.toml` — own manifest, `httpx[http2]` dependency,
|
||||
`packages = ["hxprobe"]`
|
||||
- `hxprobe/hxprobe/probe.py` — moved from `python/hxprobe/probe.py`, with
|
||||
`Options`, `Phase`, `Result`, `VerboseDetail`, `CertInfo` dataclasses and
|
||||
`_parse_cert`/`_parse_cert_date` helpers now defined locally (copied from
|
||||
`latprobe/probe.py`) instead of imported; all the httpx-instrumentation
|
||||
logic (`_Trace`, `_TimingStream`, `_TimingBackend`, `_TimingTransport`,
|
||||
`measure()`) is unchanged
|
||||
- `hxprobe/hxprobe/aggregate.py`, `duration.py` — verbatim copies of
|
||||
`latprobe`'s; their imports were already package-relative (`from .probe
|
||||
import Result`), so copying required zero edits
|
||||
- `hxprobe/hxprobe/cli.py` — rewritten as a full standalone CLI. Previously a
|
||||
27-line wrapper delegating to `latprobe.cli.run()` via an injected
|
||||
`measure_fn`; now has its own exit codes, argparse, and text/JSON
|
||||
rendering (copied from the shared `latprobe/cli.py`, then stripped of the
|
||||
`measure_fn`/`prog`/`description`/`protocol_flags` parameterization that
|
||||
only existed to let two packages share one `run()`)
|
||||
- `hxprobe/tests/{test_probe,test_cli,test_integration}.py` — moved from
|
||||
`python/tests/test_hx_*.py` / `test_integration_hx.py`, `hx`-prefix
|
||||
dropped, imports repointed from `latprobe.*` to `hxprobe.*`
|
||||
- `python/latprobe/{cli.py,probe.py}` — reverted via `git checkout --` to
|
||||
their exact pre-`hxprobe` committed state (confirmed zero diff afterward)
|
||||
- `Makefile` — `py-deps`/`PY_VENV*`/shared `hx-run`/`hx-test-integration`
|
||||
removed from the Python section; new standalone `hx-deps`/`hx-run`/
|
||||
`hx-test`/`hx-test-integration`/`hx-check`/`hx-clean` targets under
|
||||
`HX_DIR`/`HX_VENV*`; umbrella `test`/`check`/`clean` now run all three
|
||||
(`go-*`/`py-*`/`hx-*`)
|
||||
- `docs/usage/py-hxprobe.md` → `docs/usage/hxprobe.md` (renamed + rewritten
|
||||
for the new structure)
|
||||
- Old `python/hxprobe/`, `python/pyproject.toml`, `python/.venv`,
|
||||
`python/latprobe_python.egg-info/` deleted
|
||||
|
||||
## Key design decisions
|
||||
|
||||
- **Move, don't rewrite, the already-debugged files.** `probe.py` and the
|
||||
three test files carry real bug fixes found during the original
|
||||
implementation (the `mark_dns` present-on-failure bug, verbose detail not
|
||||
populated on the failure path, `Content-Length` needed once the test
|
||||
fixtures switched to HTTP/1.1 keep-alive). Rewriting from scratch would
|
||||
have risked reintroducing them.
|
||||
- **`aggregate.py`/`duration.py` needed zero import changes** — their
|
||||
existing relative imports (`from .probe import ...`) already resolve
|
||||
correctly once copied into a new package with its own `probe.py`. Not
|
||||
every file needed the same treatment as `probe.py`/`cli.py`.
|
||||
- **`cli.py`'s starting point was the *current* shared `latprobe/cli.py`**,
|
||||
not a from-scratch rewrite — it already contained 100% of the needed
|
||||
logic (including the `--no-http2`/`--no-follow-redirects` flags and the
|
||||
verbose Protocol row/JSON keys, both added earlier specifically for
|
||||
hxprobe). The only work was deleting the generalization scaffolding
|
||||
(`measure_fn`, `MeasureFn`, `prog`/`description`/`protocol_flags` params)
|
||||
that existed solely to let two packages share one `run()`.
|
||||
- **Reverting `latprobe` via `git checkout --` rather than hand-editing** —
|
||||
confirmed first via `git log`/`git diff --stat` that `cli.py`/`probe.py`
|
||||
had no changes besides the hxprobe-sharing scaffolding since the last
|
||||
commit, making this a safe, exact, zero-risk revert.
|
||||
- **Comments referencing `latprobe` by file path were reworded**, not just
|
||||
the imports. A comment like "already used by latprobe/probe.py" becomes a
|
||||
dangling reference once this directory is genuinely portable to another
|
||||
repo. Reworded ~5 comments/docstrings to describe the technique generically
|
||||
(e.g., "ports the getaddrinfo → connect split" → "splits DNS and TCP
|
||||
connect into two timed steps") instead of naming the other project.
|
||||
|
||||
## Deviations from the plan
|
||||
|
||||
None of substance. One judgment call not spelled out in the plan: the old
|
||||
`test_cli.py`'s docstring said its tests "focus on what's different... since
|
||||
run() delegates almost entirely to latprobe.cli.run()" — no longer true now
|
||||
that `cli.py` is a full standalone reimplementation. Rewrote that docstring
|
||||
for accuracy rather than leaving a stale claim, without expanding the test
|
||||
suite itself (that would be a larger, separate scope-creep beyond what was
|
||||
asked — see the coverage note below).
|
||||
|
||||
## Notable follow-up worth flagging
|
||||
|
||||
`hxprobe/tests/test_cli.py` has ~11 tests versus `latprobe/tests/test_cli.py`'s
|
||||
~23. That gap was fine when hxprobe's `cli.py` was a thin wrapper around
|
||||
already-tested shared code; it's a real gap now that `cli.py` is an
|
||||
independent ~440-line reimplementation with its own copy of every rendering
|
||||
branch. Existing tests do exercise the core paths (single URL, `--fail`,
|
||||
JSON, DNS/connect failures) so this isn't uncovered, but reaching
|
||||
`latprobe`-level depth (multi-URL separator, sampling aggregate output, JSON
|
||||
error grouping, all-failed multi-header) would be a reasonable next step if
|
||||
full independent confidence in the standalone project matters. Not done here
|
||||
— out of scope for a decoupling/move task.
|
||||
|
||||
## Verification
|
||||
|
||||
- `grep -rn "latprobe" hxprobe/` — zero matches in code; comment mentions
|
||||
reworded to be self-contained
|
||||
- `git diff --stat python/latprobe/` — empty (exact revert to last commit)
|
||||
- `make hx-deps` — creates `hxprobe/.venv`, installs `httpx[http2]` from
|
||||
`hxprobe/pyproject.toml`
|
||||
- `make hx-run ARGS="-v http://github.com"` — same output as before the
|
||||
move (HTTP/2, 1 redirect followed, IP/TLS/cert shown)
|
||||
- `make hx-test` — all hermetic hxprobe tests pass standalone (own venv,
|
||||
own `PYTHONPATH=hxprobe`)
|
||||
- `make hx-test-integration` — live HTTP/2 + redirect tests still pass
|
||||
- `make py-test` — `latprobe`'s own suite passes with zero setup (no
|
||||
`py-deps`/venv needed), confirming the revert didn't leave residue
|
||||
- `make check` (top-level) — Go + latprobe + hxprobe all green in one gate
|
||||
- `python -m latprobe --help` output confirmed unchanged from before the
|
||||
whole hxprobe feature existed (no leftover `--no-http2` etc.)
|
||||
Reference in New Issue
Block a user