Makefile: add hx-* targets (deps, run, lint, fmt, test, test-integration,
check, clean) that delegate into hxprobe/ via uv; fold hx-test and hx-check
into the umbrella test/check/clean targets; add HX_DIR variable and a note
that hxprobe is intentionally standalone (no cross-imports from python/).
CLAUDE.md: add "Implementation Summaries" convention — after each feature,
save a summary under docs/summaries/ with the same timestamp+slug naming as
plans. Add note about copying plan-mode scratch files into docs/plans/ before
starting implementation.
.gitignore: add *.egg-info/, .pytest_cache/, .ruff_cache/ for the hxprobe
uv+ruff+pytest toolchain.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds the complete Python port of the Go latprobe tool plus diagnostic
verbose output that the Go version does not yet have.
Package (python/latprobe/):
- probe.py: raw-socket HTTP timing with CertInfo/VerboseDetail dataclasses;
TTFB loop accumulates to \r\n\r\n so headers are parseable without changing
t_first_byte semantics; captures resolved IP, TLS version/cipher/bits,
verified cert (via getpeercert()), and all response headers when verbose=True
- aggregate.py: summarize() → per-phase min/avg/max PhaseStats
- cli.py: injectable run(args,stdout,stderr)->int; argparse with injected
streams; ThreadPoolExecutor concurrency across URLs; four text-rendering
branches; JSON output; worst-exit-code accumulation; -v/--verbose flag
appends IP/TLS/cert/header block after every timing table; JSON extended
with "verbose" object (omitted when flag absent)
- duration.py: parse Go-style duration strings (10s, 500ms, 2m, bare seconds)
- Exit codes: 0 ok, 1 usage, 2 dns, 3 connect, 4 timeout, 5 tls, 6 http≥400
Tests:
- test_probe.py: 18 hermetic tests (success, 404, DNS/connect/timeout/scheme
failures, partial-phase invariants, verbose detail fields)
- test_cli.py: 38 hermetic tests (usage errors, single/aggregate/failure text,
worst-code, --fail, JSON schema/ordering/grouping, verbose text and JSON)
- test_integration.py: 45 tests against live internet services (badssl.com for
TLS errors, real cert/IP/header validation in verbose mode)
Makefile: PYTHONPATH fix, fnmatch pattern test_[!i]*.py to exclude
integration tests from py-test, new py-test-integration target
Docs: docs/usage/py-latprobe.md, python/configs/usage-latprobe.md (runnable
reference with captured output), plans for both the package and verbose feature
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Rename python/configs/usage.md → usage-simple.md so both scripts have a
parallel runnable reference file in the same directory
- Add python/configs/usage-phases.md: runnable sh commands + real expected
output for phases.py against every error-path config, including a note on
the key difference from simple.py (HTTP 4xx exits 0 in phases.py vs 1 in
simple.py because phases.py completes at the network level)
- Update doc cross-links in docs/usage/py-simple.md and py-phases.md
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Hand-drives raw sockets to time each HTTP phase individually — DNS
(getaddrinfo), TCP connect, TLS handshake (ssl.wrap_socket, https only),
TTFB (sendall → first recv), Transfer (first byte → EOF), Total.
Partial phases are preserved on failure (same invariant as Go's probe.go).
Error classification mirrors Go's priority: dns → timeout → tls → connect.
Output format matches Go's single-sample text layout.
Input: bare URL args or plain-text config file (same format as simple.py).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- python/configs/: 7 purpose-built config files, one per error class:
all-ok.txt, dns-failure.txt, connection-refused.txt, timeout.txt,
tls-errors.txt (badssl.com), http-errors.txt (real 404 paths on stable
hosts), mixed.txt (one of each, no timeout)
- python/configs/usage.md: runnable sh commands + expected output per config,
plus quick-sweep and full-sweep loops; commands written for running from
the python/ directory
- docs/custom-usage-examples.md: example 11 added (all failure classes at once)
- docs/usage/py-simple.md: added pointer to python/configs/ and corrected
limitation note (4xx/5xx are FAIL, not OK)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- python/simple.py: reads a plain-text site list (one URL/line, # comments),
issues a GET per site, prints aligned OK/FAIL + elapsed ms, exits 0/1
- Config format forward-compatible with future key=value annotations
- HTTPError caught separately from URLError so HTTP status code appears in
the FAIL message (e.g. "HTTP Error 404: Not Found")
- python/sites.txt: committed example config
- Makefile: PYTHON/PY_DIR/SITES vars; py-simple-run, py-phases-run, py-run,
py-test, py-check, py-clean targets; umbrella test/check/clean include Python
- docs/plans/2026-07-01-10-39-py-simple.md: design plan
- docs/usage/py-simple.md: flags, format, examples, limitations
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Probe multiple URLs in parallel with a bounded worker pool; the N samples
of each URL remain sequential to preserve accurate min/avg/max statistics.
Default auto-concurrency is min(numURLs, 8); -c 1 restores serial mode.
Output is always buffered and printed in original input order. Verified
clean with go test -race.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Examples 1-3: clean global sweep (single, 10 samples, JSON).
Examples 4-8: one failure type each (DNS, refused, timeout, HTTP, TLS).
Example 9: full matrix, all 5 failure types in one run.
Example 10: quick smoke test (-n 1, JSON, --timeout 2s, all types).
Includes runtime estimates and jq filter snippets.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Namespaced go-* targets (build, run, test, test-verbose, check, cover,
fmt, vet, tidy, install, lint, clean) plus umbrella targets that delegate
to them. help is the default. py-* targets will slot in during the Python
port. Updates .gitignore with coverage artifacts.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Extract run(args, stdout, stderr) int from main() for in-process
testability. Fix TLS failure classification (tlsErr now captured from
TLSHandshakeDone hook). Add run_test.go with 14 table-driven in-process
tests and cli_test.go with TestMain + 3 subprocess smoke tests. All
servers use httptest; .invalid TLD for deterministic DNS failures.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Classify network failures (dns/connect/timeout/tls) with distinct exit
codes 2-5. Add --timeout (default 10s) via context.WithTimeout. Add
--fail for exit 6 on HTTP status >= 400. Preserve partial phase timing
up to the failure point. -n sampling continues on network failures,
aggregating successes and reporting fail counts. JSON extended with
succeeded/failed/errors fields.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add --json flag that emits all results as a JSON array. Schema always
uses min/avg/max per phase (consistent regardless of -n); phases absent
from the request are omitted from the phases object. Output is buffered
until all URLs complete, then printed as one pretty-printed array.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add probe.Summarize to aggregate N Results into per-phase min/avg/max
stats. Wire up -n/--count flag in main to repeat each URL N times and
display an aligned three-column table. Single-sample output (n=1) is
unchanged. URLs are grouped with a blank line between them.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Instruments HTTP requests with net/http/httptrace.ClientTrace to capture
timestamps for DNS, TCP connect, TLS handshake, TTFB, and body transfer.
TLS row is omitted automatically for plain http:// URLs. Output is an
aligned text table with a separator before the Total row.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
probe.Measure performs an HTTP GET and records total elapsed time from
request start to body fully read. main.go prints URL, status code, and
total for each positional URL argument, exiting 1 on any failure.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sets up project structure, working conventions (CLAUDE.md), README with
the full assignment and roadmap, seeded CHANGELOG, and a buildable Go
scaffold (Step 0) with flag parsing and stub probe types.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>