Repository navigation
test(http): pin byte-exact curl transport round-trips - #1019
vernonstinebaker wants to merge 31 commits into
Conversation
Adds integrity coverage for the silent response corruption in nullclaw#1018, where aarch64-linux-android returns scrambled or empty text with exit 0 — nothing fails loudly, so the suite could not catch it. The Android-only half is `ProxyHttpClient.fetchWithCurl` (selected by `fetchWithCurl` at the `comptime builtin.abi == .android` branch); the curl executor under it is shared by every platform, so these assertions run on Linux, macOS and Windows and flag a regression even where the adapter is not selected in production. Existing fixtures used 12-byte bodies against an 8 KiB read buffer, so a truncating reader still passed. Four tests close that: - round-trips 4/8/64 KiB marker payloads across the 8 KiB boundary - preserves a 48 KiB request body (a mangled request reads as scrambled output: the model answers a prompt it never received) - round-trips through `fetchWithCurl`, the Android entry point, which had no body coverage at all - repeats five transfers with distinct payloads to catch state leaking between transfers, the signature of the intermittent failure Payloads use a position-sensitive pattern, so equality detects truncation, duplication and reordering alike. Verified by injecting a simulated truncation: three of the four tests fail loudly and pass again once reverted. Linux 7394/7408, macOS 7391/7400, `zig fmt --check` clean.
The branch replaced the 974-line README with the single line `# Not a skill` and carried a set of unrelated root fixtures (`SKILL.md`, `skill.json`, `history.env`, `config.txt`, `assets/payload.txt`, and fixture directories under `skills/`). None of those paths exist on main, and the names match the `src/skills.zig` workspace-audit test fixtures, so they were written into the working tree by a test run rather than authored here. Restored README to its merge-base content and removed the residue, so the pull request is now only its own work: the byte-exact curl transport round-trips in `src/http_util.zig`. The underlying non-hermeticity is tracked in nullclaw#1029 and addressed in nullclaw#1038. This branch should not be used to validate until those land. Validation: `zig build test --summary all` 13/13 steps, 7391/7400 passed, 9 skipped, 0 failures, 0 leaks; `zig build -Doptimize=ReleaseSmall` and `zig fmt --check src/` clean.
|
This branch was carrying committed test residue and is now What was wrongThe branch replaced the 974-line README with the single line The names are the This is byte-identical to the contamination in #1012, which is how I caught it: both branches had the same What changed
— just the byte-exact curl transport round-trips. Why this happened — correctedAn earlier revision of this comment said the residue was a separate test-hygiene issue tracked in #1029/#1038. That was wrong, and #1038 is unrelated: it touches only The actual cause is #1020. Running the suite with That commit adds #1021 fixes it (it unsets the inherited git environment before running the suite), verified against that exact condition: same worktree, same inherited Validation
|
Extends the same hook that clears GIT_DIR (nullclaw#1020) so it also refuses to let a push through when the test run left untracked files behind. The suite can drop fixtures into the working tree. They are harmless where they sit, but the next `git add -A` commits them silently. That is how nullclaw#1012 and nullclaw#1019 each ended up carrying workspace-audit and skills test fixtures -- `config.txt`, `history.env`, `SKILL.md`, `skill.json`, `assets/payload.txt`, and fixture directories under `skills/` -- along with a one-line `# Not a skill` stub that had replaced the 974-line README. Both branches were single squashed commits, which is the shape that captures whatever happens to be lying around in the tree. Deliberately limited to untracked ("??") entries. Modified tracked files are nearly always work in progress, and blocking on those would make the hook hostile to normal development; the residue problem is specifically about files appearing from nowhere and being swept up by an add-everything commit. The check depends on the `unset` above it: with GIT_DIR still exported from a worktree push, `git status` reports on the wrong repository. Verified by running the hook directly: clean tree passes, an untracked file fails with the offending paths listed, and a modified tracked file still passes.
Adds byte-exact integrity coverage for the HTTP curl transport: large payloads crossing the 8 KiB read buffer, a preserved request body, the Android
fetchWithCurlentry point, and repeated transfers to catch state leaking between calls. These are transport invariants — a truncating or reordering reader still exits 0, so the existing suite could not catch it.Why here
ProxyHttpClient.fetchroutes every Android request throughfetchWithCurl(thecomptime builtin.abi == .androidbranch); other platforms keep usingstd.http. So:The coverage gap
Existing fixtures used 12-byte bodies (
"transport-ok") against an 8 KiB read buffer, so a truncating or reordering reader still passed. Nothing round-tripped throughfetchWithCurlat all — its only tests covered header validation and redirect policy, never a body.The four tests
fetchWithCurlPayloads use a position-sensitive pattern, so
expectEqualSlicesdetects truncation, duplication and reordering.Red proof
I injected a simulated truncation (compared against
payload[0 .. len/2]) rather than trusting that a green test is a useful test:Reverted → green again. The 4th test uses the adapter's writer path, so it asserts independently.
Validation
zig fmt --check src/: cleansrc/http_util.zig+223/-0Note on
--no-verifyThis was pushed with
--no-verifyunder AGENTS.md §8.2, after confirming the same suite green manually on both platforms. Reason: the repo'spre-pushhook cannot pass from a worktree —git pushexportsGIT_DIR, the hook inherits it, and every test that spawnsgit(skills.installSkillFromGit×7,workspace_audit×1, +2) then operates on this repo instead of its temp fixture.Reproduced deterministically: with
GIT_DIRset the suite fails 7380/7400 (10 failed); without it, green. Verified separately that a push from a normal clone exports noGIT_*, while a push from a worktree exportsGIT_DIRandGIT_PREFIX— and worktrees are this repo's documented workflow. That is a pre-existing bug in.githooks/pre-push, not caused by this change; happy to fix it in a separate PR.