diff --git a/tools/hunter-local-ingest/.gitignore b/tools/hunter-local-ingest/.gitignore new file mode 100644 index 000000000..40dc63a50 --- /dev/null +++ b/tools/hunter-local-ingest/.gitignore @@ -0,0 +1,6 @@ +runs/ +build/ +*.egg-info/ +__pycache__/ +*.pyc +.venv/ diff --git a/tools/hunter-local-ingest/README.md b/tools/hunter-local-ingest/README.md new file mode 100644 index 000000000..cf2c6b4aa --- /dev/null +++ b/tools/hunter-local-ingest/README.md @@ -0,0 +1,187 @@ +# hunter-local-ingest + +Runs the published HouseScanKit upload lifecycle against one capture-API +endpoint and records what happened. It creates a capture, registers and +uploads files, commits them, finalizes with a packet, follows events to a +terminal status and reads the result, then runs controls that tamper with +uploads, replay a create and read a capture that does not exist. Every check +ends PASS, FAIL, BLOCKED or NOT_RUN and names how it ran. + +The request bodies, response types, retry rules and header handling come from +`ios/HouseScanKit/Sources/HouseScanKit` at alpha `263827ef` +(`Upload/CaptureAPI.swift`, `Upload/CaptureUploader.swift`, +`Upload/ScopedCaptureHTTP.swift`, `CaptureResult/CaptureResult.swift`, +`Processing/FixtureCaptureHTTP.swift`). No backend code, schema or test is +copied here. + +## Install and run + +```bash +python -m venv .venv && .venv/bin/pip install -e '.[dev]' # development +python -m venv .venv && .venv/bin/pip install . # what a user gets + +hunter-gen-plan --seed 1 --out plan.json # or: python fixtures/gen_synthetic_packet.py +hunter-local-ingest --endpoint http://127.0.0.1:8000/v1 --plan-file plan.json \ + --backend-mode REAL_API --backend-ref --out runs --with-faults +hunter-verify-run runs/ # re-check a finished run on its own +hunter-selfcheck # everything above against the in-process fake +pytest -q +``` + +`--restart-argv-json '["cmd", "arg"]'` adds a restart-recovery check: the +harness runs the command without a shell, waits for the endpoint, and reads +the baseline capture again. Without it that check is NOT_RUN. + +Exit codes: 0 every executed check passed; 1 a check failed; 2 usage error; +3 the plan was refused; 4 nothing failed but something was blocked; 5 the +receipts themselves failed (schema, privacy screen, missing file, integrity), +which outranks the others. + +## What a label means + +- `REAL_API`: the client exchanged HTTP with an endpoint the operator declared + real. The harness cannot see whether the backend ran its CPU stages, which + models it used or which ref it is; the summary always records + `real_mirror_cpu: NOT_ESTABLISHED` and `backend_verified: false`. +- `FAKE_HUNTER`: the in-process fake (`fakeapi.py`) or the fault proxy + (`faultproxy.py`). It shows the client reacts to a condition and is never + evidence about a backend. +- `GPU_STUB`: the `objects`, `vlm` and `dense` arms, named and always NOT_RUN. + +BLOCKED means the check got no answer or depends on a step that did not +complete, and NOT_RUN means it was deliberately skipped. Neither counts as a +pass, and the frozen-trace check reports such rows as not comparable rather +than agreeing. A request the client refuses to send (see below) is FAIL. + +## What the client refuses + +Every API request's final URL passes the published scope rule +(`ScopedCaptureHTTP`) before any header, token or connection: same scheme, +host and port as the base, under its path, with no dot segment and no +encoded `/`, `\` or `.`. A server-minted capture id such as `../outside` +therefore becomes a refused request (`auth_destination_refused`), and +nothing is sent. Storage PUTs use their own rule: https, or http to an exact +loopback host, with exactly the signed headers and never `Authorization`. + +Register and commit go in batches of `min(10, upload.maxBatch)`, the +published uploader's limit, in the lifecycle and in the tamper controls +alike. Each commit answer is judged as it arrives, by the scenario's own +rule (the lifecycle needs every path committed; a tamper control needs its +victim kept out and every intact file committed), and the first answer that +breaks it ends the round as FAIL before another batch is sent. When register reports a file already committed (a replayed or resumed +capture), the client neither uploads nor commits it again, and both checks +record that committed-at-register set explicitly. + +Published Swift `Int` fields (event `seq` and `next`, `etaS`, upload limits) +decode as 64-bit integers by value, as Foundation's JSONDecoder does: `5`, +`5.0` and `1e3` are all integers, and a non-integral value such as `5.1` is +refused. The response parser keeps decimal literals exact, so +`4611686018427387905.0` decodes to exactly that integer, never to a rounded +float. A decimal spelling is range-checked through a Double, as Foundation +does, so `9223372036854775807.0` is refused while the integer +`9223372036854775807` is accepted. A value too large for a receipt to hold as +an exact JSON number (2^53 and up) is recorded as `large-int:`, never +clamped and never rejected. `Double` fields accept any JSON number that +converts to a finite double. + +One known compatibility limit: this rule is a deliberately conservative +oracle, not exact Swift Codable parity. Foundation decodes +`1.0000000000000000001` as the Int `1`, because it rounds the literal first; +the harness refuses it, because the value is not an integer. A response the +app would accept can therefore FAIL here in that one kind of case: a +fractional literal that Foundation rounds to an integer. Run locally, +Foundation's JSONDecoder agrees with the harness on 20 of 21 recorded +literals; that is the 21st. + +## The API credential + +`--api-token-env` makes the runner read a bearer token from the +`HUNTER_API_TOKEN` environment variable. Without the flag the variable is not +read. There is no flag that takes the token itself: `--api-token` is refused +in every spelling, without echoing its value, because a command-line value +shows up in process listings and shell history. + +Supply the variable through a secret manager that sets it in the runner's +process environment, not a literal assignment typed into a shell, which +history keeps. The environment is still readable by the same user and by +root; nothing here protects against them. + +The whole token is checked (RFC 6750 b64token, so a trailing newline, a +carriage return, a space or any control character is refused) before any run +directory or request exists. It goes only on API requests to `--endpoint` whose final URL passes +the scope rule, never on a storage PUT and never to the fault proxy. Restart +commands and git run without it in their environment. Receipts record only +the flag name. + +With a token, `--with-faults` does not run the fault round: every fault check +is BLOCKED with the reason `auth_fault_proxy_not_authorized`, and the run +exits 4 unless something failed. The proxy is never given the credential, +and its requests sent without one would only read as endpoint failures. So a +token-protected API gets no fault coverage from this harness; that gap is +open, not passed. Without a token the fault round runs as before. + +## The synthetic plan + +`fixturegen.py` writes seeded noise files, two seeded CSV streams, the +published `CreateRequest`, and a Packet04 packet whose `source.kind` is +`synthetic` with no keyframes. A different seed changes every file's bytes. +The runner's loader (`plan.py`) refuses any plan whose digests do not +recompute from the bytes it read, whose paths are not the generator's, or +whose create body or packet differ from the published shapes. Each control +and fault check uses its own derived packet id carrying this run's id, so +none of them can land on the baseline capture, and a rerun against the same +server opens fresh control captures while the baseline is a true replay. + +## Receipts + +Each run gets a new directory (exclusive `mkdir`, random run id) holding +exactly five files: + +| File | Contents | +| --- | --- | +| `run-manifest.json` | declared backend mode and ref; digest of the package source that ran, plus git HEAD and a digest of the uncommitted diff when run from a checkout; fixture digests; the command with every value rendered by type; runtime; settings | +| `checks.jsonl` | one line per check: id, transport, status, the oracle and expectation (package constants looked up by id), and the observed record | +| `summary.json` | verdict, counts, failed/blocked/not-run ids, digests of the manifest and checks | +| `privacy-screen.json` | the pattern screen's findings over the three files above, run after the summary exists | +| `privacy-chain.jsonl` | a SHA-256 chain over every artifact's final bytes | + +Values reach these files only through typed schemas (`export.py`). A string +must be a published enum word, a package constant, a digest, or a path or +packet id the plan declared. Server identifiers become `id:<12 hex>`, unknown +words `unrecognized:<12 hex>`, and unexpected paths and keys become digests, +so a disagreement stays visible without its content. Homeowner messages, +prompts, signed URLs and raw bodies are never recorded. Recorded commands +keep this program's flags typed (an endpoint as `host:port` only when it is +loopback, paths as ``) and turn every other value into ``, or +`***` after a credential-named flag. A value outside its schema stops the run +with exit 5 before it is written. + +The pattern screen (`sanitize.py`) is the second layer. It cannot recognize a +bare word-shaped secret, which is why the schemas come first. + +What the integrity check proves: the chain, the read-only modes and +`hunter-verify-run` detect an edit made after the run, such as a changed +byte, a broken link, a writable, extra or missing file. They do not stop the +directory's owner from rewriting a file, recomputing the chain and sealing +it again. The chain head is printed when the run ends; recording it +somewhere the run cannot write is the only anchor. A file `hunter-verify-run` +cannot read, decode or parse, or one of the wrong JSON shape, is reported by +file name and category with exit 5; its content is never printed. Screen +findings never delete evidence: failed artifacts survive, sealed, for +inspection. Sealing and a clean screen make receipts tamper-evident, not +publishable — the guarantees above govern when a receipt may leave the +machine. + +## Layout + +| Module | Role | +| --- | --- | +| `netpolicy.py` | the one rule for which hosts are loopback and which URLs may be used | +| `contract.py` | published vocabularies and one strict decoder per response | +| `http_client.py` | the client: transient retries, API-only credential, exact signed PUT headers | +| `scenarios/` | lifecycle, controls, fault round; the only place PASS/FAIL is decided | +| `scenarios/oracles.py` | every check id with its oracle and expectation | +| `traces/` | frozen expectations; v3 is current (v2 plus the committed-at-register branch); v1 and v2 are kept unedited | +| `export.py`, `receipts.py`, `verify.py` | schemas, writing and sealing, independent re-check | +| `fakeapi.py`, `faultproxy.py` | FAKE_HUNTER plumbing with knobs to misbehave | +| `provenance.py` | source digest, git state, runtime | diff --git a/tools/hunter-local-ingest/evidence/1511668/README.md b/tools/hunter-local-ingest/evidence/1511668/README.md new file mode 100644 index 000000000..3a5b21663 --- /dev/null +++ b/tools/hunter-local-ingest/evidence/1511668/README.md @@ -0,0 +1,31 @@ +# Receipts from the installed package at 1511668 + +These seven run directories come from the wheel built out of commit +`1511668e7e1df5d87228862b9d502708a10dee54` +(sha256 `029257adc3597d7f8364531bd86d71d16896fcb7709153ebaf7e255054932121`), +installed non-editable into a scratch venv and run as console scripts from a +directory outside the source tree. The installed package's source digest, +`843fd20eb408e430…`, equals the digest of the committed +`src/hunter_local_ingest` (full values in `index.json`). The plan is +`hunter-gen-plan --seed 1`; the seed reproduces it, so it is not committed. +The older `evidence/23d5fc9/` receipts describe that earlier source and are +unchanged. + +| Run | Endpoint | Exit | Verdict | What it shows | +| --- | --- | --- | --- | --- | +| `selfcheck/` | in-process fake, fault round, no-op restart | 0 | PASS | 26 PASS rows labeled FAKE_HUNTER; GPU arms NOT_RUN | +| `real-api-unreachable/` | declared `REAL_API`, nothing listening | 4 | BLOCKED | 13 BLOCKED rows; an absent backend never passes | +| `mutation-commits-tampered/` | fake that commits tampered bytes | 1 | FAIL | both tamper controls and the trace check fail | +| `canary-responses/` | fake that plants a marker in every response | 0 | PASS | the marker occurs 0 times in the run's files | +| `rerun-committed-capture/` | second run of the same plan on one server | 0 | PASS | the committed baseline is replayed; the rerun's 10 PUTs all belong to fresh control captures | +| `max-batch-2/` | fake that enforces `upload.maxBatch` = 2 | 0 | PASS | lifecycle and tamper controls stay within two files per call | +| `auth-fault-arm-blocked/` | token-protected fake, `--with-faults`, token from `HUNTER_API_TOKEN` | 4 | BLOCKED | authenticated baseline passes; all 12 fault checks BLOCKED with `auth_fault_proxy_not_authorized`; 0 unauthenticated API requests; the synthetic token occurs 0 times in output or receipts | + +None of these runs touched a real backend, a real credential, a GPU or a +phone. The token in the last run was a fresh synthetic value set only in +that subprocess's environment. + +`index.json` lists every artifact's sha256, each chain head, the exit codes +and the result of `hunter-verify-run` on the sealed originals (all OK). Git +checks files out writable, so on these copies `hunter-verify-run` also +reports `not sealed (writable)`; run `chmod -R a-w ` first. diff --git a/tools/hunter-local-ingest/evidence/1511668/auth-fault-arm-blocked/auth-faults-20261012T113539Z-5e25659eb6a8eac5/checks.jsonl b/tools/hunter-local-ingest/evidence/1511668/auth-fault-arm-blocked/auth-faults-20261012T113539Z-5e25659eb6a8eac5/checks.jsonl new file mode 100644 index 000000000..a96fc0ec4 --- /dev/null +++ b/tools/hunter-local-ingest/evidence/1511668/auth-fault-arm-blocked/auth-faults-20261012T113539Z-5e25659eb6a8eac5/checks.jsonl @@ -0,0 +1,29 @@ +{"expected": "an HTTP 2xx answer with status ok", "id": "lifecycle.health", "observed": {"contract": {"status": "ok"}, "http": {"attempts": 1, "body_bytes": 16, "body_sha256": "08e2c358ce13", "elapsed_ms": 0, "fields": ["status"], "http_status": 200, "shape": "object"}, "violations": []}, "oracle": "tools/integration-viewer reads GET /v1/healthz; HouseScanKit never calls it", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:39.720Z"} +{"expected": "2xx, a captureId and a published capture status", "id": "lifecycle.create", "observed": {"contract": {"captureId": "id:fd102437f369", "maxBatch": 50, "status": "uploading"}, "http": {"attempts": 1, "body_bytes": 78, "body_sha256": "8edf48cf4ce9", "elapsed_ms": 0, "fields": ["captureId", "status", "upload"], "http_status": 201, "shape": "object"}, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.create: POST captures with Idempotency-Key=packetId; the answer decodes as CaptureAPI.CreateResponse", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:39.721Z"} +{"expected": "every requested path answered exactly once, no other path, each committed or given a usable PUT target", "id": "lifecycle.register", "observed": {"batches": [{"contract": {"files": [{"path": "synthetic/scan00.bin", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "synthetic/scan01.bin", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "synthetic/scan02.bin", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "streams/arkit_poses.csv.gz", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "streams/imu_raw.csv.gz", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}]}, "http": {"attempts": 1, "body_bytes": 1253, "body_sha256": "352384900fbd", "elapsed_ms": 0, "fields": ["files"], "http_status": 200, "shape": "object"}, "violations": []}], "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.register: the answer decodes as RegisterResponse and is applied by path; a target needs method PUT and a URL that passes uploadURLProblem", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:39.722Z"} +{"expected": "2xx for every file that got a target", "id": "lifecycle.upload", "observed": {"committed_at_register": [], "uploads": [{"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "synthetic/scan00.bin", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "synthetic/scan01.bin", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "synthetic/scan02.bin", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "streams/arkit_poses.csv.gz", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "streams/imu_raw.csv.gz", "shape": "empty"}]}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.put + ScopedCaptureHTTP.upload: exactly the signed headers, never Authorization", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:39.724Z"} +{"expected": "committed equals the uploaded set; notFound and mismatch empty; every declared path committed by register or commit", "id": "lifecycle.commit", "observed": {"batches": [{"contract": {"committed": ["synthetic/scan00.bin", "synthetic/scan01.bin", "synthetic/scan02.bin", "streams/arkit_poses.csv.gz", "streams/imu_raw.csv.gz"], "mismatch": [], "notFound": []}, "http": {"attempts": 1, "body_bytes": 175, "body_sha256": "ab0d647d58c4", "elapsed_ms": 0, "fields": ["committed", "mismatch", "notFound"], "http_status": 200, "shape": "object"}, "violations": []}], "committed_at_register": [], "committed_total": 5, "declared": 5, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.commit: only a commit acknowledges a file; CommitResponse carries committed, notFound and mismatch", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:39.725Z"} +{"expected": "2xx, a runId, a published status, no missing file", "id": "lifecycle.finalize", "observed": {"contract": {"missing": [], "runId": "id:492e113d2d27", "status": "processing"}, "http": {"attempts": 1, "body_bytes": 62, "body_sha256": "425e9d06a56d", "elapsed_ms": 0, "fields": ["missing", "runId", "status"], "http_status": 202, "shape": "object"}, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.finalize: X-Packet-Sha256 and Idempotency-Key=packetId; the answer decodes as FinalizeResponse", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:39.725Z"} +{"expected": "a terminal status within the budget, every answer contract-shaped", "id": "lifecycle.events", "observed": {"answers": 1, "finalize_retries": 0, "last": {"contract": {"events": [{"data": {"runId": "id:492e113d2d27", "runId_matches": true}, "seq": 1, "type": "verdict_ready"}], "next": 1, "status": "complete"}, "http": {"attempts": 1, "body_bytes": 145, "body_sha256": "f7919284ecb6", "elapsed_ms": 0, "fields": ["events", "next", "status"], "http_status": 200, "shape": "object"}, "violations": []}}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.pollEvents: EventsResponse until CaptureAPI.terminalStatuses; next never moves back; a verdict names this run; retry_finalize re-sends the packet", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:39.726Z"} +{"expected": "a decodable result for this run whose status matches the terminal event status", "id": "lifecycle.result", "observed": {"contract": {"criteria": null, "has_preview_url": false, "memberActions": 0, "outcome": {"kind": "eligible", "reasons": 0}, "runId": "id:492e113d2d27", "status": "complete", "viewsNeeded": 0}, "http": {"attempts": 1, "body_bytes": 227, "body_sha256": "1dc1b0ebf7a6", "elapsed_ms": 0, "fields": ["memberActions", "outcome", "runId", "status", "viewsNeeded"], "http_status": 200, "shape": "object"}, "not_ready_reads": 0, "run_matches": true, "status_matches": true, "terminal_status": "complete", "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.fetchResult: the whole body decodes as CaptureResult.Response, its runId is the finalized run, and a null outcome is final only under statusesWithoutOutcome", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:39.726Z"} +{"expected": "both creates 2xx with the same captureId", "id": "control.idempotent-create", "observed": {"first": {"contract": {"captureId": "id:b9d50067aadb", "maxBatch": 50, "status": "uploading"}, "http": {"attempts": 1, "body_bytes": 78, "body_sha256": "ec8a1ff9228b", "elapsed_ms": 0, "fields": ["captureId", "status", "upload"], "http_status": 201, "shape": "object"}, "violations": []}, "same_capture": true, "second": {"contract": {"captureId": "id:b9d50067aadb", "maxBatch": 50, "status": "uploading"}, "http": {"attempts": 1, "body_bytes": 78, "body_sha256": "ec8a1ff9228b", "elapsed_ms": 0, "fields": ["captureId", "status", "upload"], "http_status": 200, "shape": "object"}, "violations": []}}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.start: create is bound to Idempotency-Key=packetId, so a repeated create with the same bytes names the same capture", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:39.728Z"} +{"expected": "intact files committed; the flipped file in mismatch or notFound, or its PUT refused, and never committed", "id": "control.corrupt-upload", "observed": {"batches": [{"contract": {"committed": ["synthetic/scan01.bin", "synthetic/scan02.bin", "streams/arkit_poses.csv.gz", "streams/imu_raw.csv.gz"], "mismatch": ["synthetic/scan00.bin"], "notFound": []}, "http": {"attempts": 1, "body_bytes": 173, "body_sha256": "b6f8e6ec4d66", "elapsed_ms": 0, "fields": ["committed", "mismatch", "notFound"], "http_status": 200, "shape": "object"}, "violations": []}], "intact_committed": true, "intact_reported_negative": false, "tampered": "synthetic/scan00.bin", "tampered_committed": false, "tampered_put_status": 200, "tampered_reported": true, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CommitResponse separates committed from mismatch/notFound; one file's bytes are flipped after its digest was registered", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:39.732Z"} +{"expected": "intact files committed; the truncated file in mismatch or notFound, or its PUT refused, and never committed", "id": "control.truncated-upload", "observed": {"batches": [{"contract": {"committed": ["synthetic/scan01.bin", "synthetic/scan02.bin", "streams/arkit_poses.csv.gz", "streams/imu_raw.csv.gz"], "mismatch": ["synthetic/scan00.bin"], "notFound": []}, "http": {"attempts": 1, "body_bytes": 173, "body_sha256": "b6f8e6ec4d66", "elapsed_ms": 0, "fields": ["committed", "mismatch", "notFound"], "http_status": 200, "shape": "object"}, "violations": []}], "intact_committed": true, "intact_reported_negative": false, "tampered": "synthetic/scan00.bin", "tampered_committed": false, "tampered_put_status": 200, "tampered_reported": true, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CommitResponse separates committed from mismatch/notFound; one file loses its last byte after its digest was registered", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:39.737Z"} +{"expected": "404 with error code capture_not_found for an id the harness invented", "id": "control.wrong-capture", "observed": {"capture": "id:1976512104be", "errors": {"codes": ["capture_not_found"]}, "http": {"attempts": 1, "body_bytes": 43, "body_sha256": "23553eb17fe9", "elapsed_ms": 0, "fields": ["errors"], "http_status": 404, "shape": "object"}}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.captureGone: an unknown capture answers 404 capture_not_found", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:39.737Z"} +{"expected": "an HTTP 2xx answer with status ok", "id": "fault.lifecycle.health", "observed": {"note": "auth_fault_proxy_not_authorized"}, "oracle": "tools/integration-viewer reads GET /v1/healthz; HouseScanKit never calls it", "status": "BLOCKED", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:39.738Z"} +{"expected": "2xx, a captureId and a published capture status", "id": "fault.lifecycle.create", "observed": {"note": "auth_fault_proxy_not_authorized"}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.create: POST captures with Idempotency-Key=packetId; the answer decodes as CaptureAPI.CreateResponse", "status": "BLOCKED", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:39.738Z"} +{"expected": "every requested path answered exactly once, no other path, each committed or given a usable PUT target", "id": "fault.lifecycle.register", "observed": {"note": "auth_fault_proxy_not_authorized"}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.register: the answer decodes as RegisterResponse and is applied by path; a target needs method PUT and a URL that passes uploadURLProblem", "status": "BLOCKED", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:39.738Z"} +{"expected": "2xx for every file that got a target", "id": "fault.lifecycle.upload", "observed": {"note": "auth_fault_proxy_not_authorized"}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.put + ScopedCaptureHTTP.upload: exactly the signed headers, never Authorization", "status": "BLOCKED", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:39.738Z"} +{"expected": "committed equals the uploaded set; notFound and mismatch empty; every declared path committed by register or commit", "id": "fault.lifecycle.commit", "observed": {"note": "auth_fault_proxy_not_authorized"}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.commit: only a commit acknowledges a file; CommitResponse carries committed, notFound and mismatch", "status": "BLOCKED", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:39.738Z"} +{"expected": "2xx, a runId, a published status, no missing file", "id": "fault.lifecycle.finalize", "observed": {"note": "auth_fault_proxy_not_authorized"}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.finalize: X-Packet-Sha256 and Idempotency-Key=packetId; the answer decodes as FinalizeResponse", "status": "BLOCKED", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:39.738Z"} +{"expected": "a terminal status within the budget, every answer contract-shaped", "id": "fault.lifecycle.events", "observed": {"note": "auth_fault_proxy_not_authorized"}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.pollEvents: EventsResponse until CaptureAPI.terminalStatuses; next never moves back; a verdict names this run; retry_finalize re-sends the packet", "status": "BLOCKED", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:39.738Z"} +{"expected": "a decodable result for this run whose status matches the terminal event status", "id": "fault.lifecycle.result", "observed": {"note": "auth_fault_proxy_not_authorized"}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.fetchResult: the whole body decodes as CaptureResult.Response, its runId is the finalized run, and a null outcome is final only under statusesWithoutOutcome", "status": "BLOCKED", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:39.738Z"} +{"expected": "the proxy's single 503 is followed by a second attempt that creates the capture", "id": "fault.retry-transient", "observed": {"note": "auth_fault_proxy_not_authorized"}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.isTransient: a 503 is retried with the same body", "status": "BLOCKED", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:39.738Z"} +{"expected": "exactly one attempt and a reported non-2xx answer", "id": "fault.no-retry-501", "observed": {"note": "auth_fault_proxy_not_authorized"}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.isTransient excludes 501", "status": "BLOCKED", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:39.738Z"} +{"expected": "a transport error category after 1 + max_retries attempts, no capture id taken", "id": "fault.abort", "observed": {"note": "auth_fault_proxy_not_authorized"}, "oracle": "an answer-less connection is a transport failure, retried a bounded number of times", "status": "BLOCKED", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:39.738Z"} +{"expected": "a transport error category, no capture id taken", "id": "fault.truncated-response", "observed": {"note": "auth_fault_proxy_not_authorized"}, "oracle": "a body shorter than its Content-Length is a transport failure, never a parsed answer", "status": "BLOCKED", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:39.738Z"} +{"expected": "every traced check present and PASS with the traced status class and fields, or upload and commit skipped because register reported every declared file committed", "id": "trace.expected-lifecycle-v3", "observed": {"compared": 12, "disagreements": [], "not_comparable": []}, "oracle": "frozen expected trace traces/expected-lifecycle-v3.jsonl, written from the published contract, with a no-request branch for files committed at register", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:39.739Z"} +{"expected": "after a successful restart the capture still reports its terminal status and run", "id": "control.restart-recovery", "observed": {"note": "restart-not-configured"}, "oracle": "operator restart command, then the baseline capture is read again over the published events and result routes", "status": "NOT_RUN", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:39.739Z"} +{"expected": "not run", "id": "gpu-stub.objects", "observed": {"note": "gpu-not-authorized"}, "oracle": "GPU-dependent arms are named and never executed by this harness", "status": "NOT_RUN", "transport": "GPU_STUB", "ts": "2026-10-12T11:35:39.739Z"} +{"expected": "not run", "id": "gpu-stub.vlm", "observed": {"note": "gpu-not-authorized"}, "oracle": "GPU-dependent arms are named and never executed by this harness", "status": "NOT_RUN", "transport": "GPU_STUB", "ts": "2026-10-12T11:35:39.739Z"} +{"expected": "not run", "id": "gpu-stub.dense", "observed": {"note": "gpu-not-authorized"}, "oracle": "GPU-dependent arms are named and never executed by this harness", "status": "NOT_RUN", "transport": "GPU_STUB", "ts": "2026-10-12T11:35:39.739Z"} diff --git a/tools/hunter-local-ingest/evidence/1511668/auth-fault-arm-blocked/auth-faults-20261012T113539Z-5e25659eb6a8eac5/privacy-chain.jsonl b/tools/hunter-local-ingest/evidence/1511668/auth-fault-arm-blocked/auth-faults-20261012T113539Z-5e25659eb6a8eac5/privacy-chain.jsonl new file mode 100644 index 000000000..63677d4b6 --- /dev/null +++ b/tools/hunter-local-ingest/evidence/1511668/auth-fault-arm-blocked/auth-faults-20261012T113539Z-5e25659eb6a8eac5/privacy-chain.jsonl @@ -0,0 +1,4 @@ +{"artifact": "run-manifest.json", "at": "2026-10-12T11:35:39.718Z", "bytes": 3507, "chain_sha256": "dd8da22bc851ee0832f3ebd160c3a53e0e77eeee5bf49e1269753d454bf68943", "sha256": "9c2d312c84c1af433e772745eddf8cdc2ca4c889f909cd9b4d62512ec175e1e8"} +{"artifact": "checks.jsonl", "at": "2026-10-12T11:35:39.740Z", "bytes": 17136, "chain_sha256": "76703e9a2e142c657330790c1c95512394cb62e72216841e5bad8b190bc4c384", "sha256": "7660c20f07a08bcca18c4242af4d0b8b97e480ba30fb2548ca206f21c6e09029"} +{"artifact": "summary.json", "at": "2026-10-12T11:35:39.740Z", "bytes": 1742, "chain_sha256": "88db493eff2582c807bed2c7c70ae1aeb51e10a6f7cf1ae334efb23061826073", "sha256": "d23a921377e8ee7e32665b48bf9009ef403fc8d259aeed776f9dd8632cb5186a"} +{"artifact": "privacy-screen.json", "at": "2026-10-12T11:35:39.747Z", "bytes": 238, "chain_sha256": "7388f9a00373721d6628a30e984b9883bfbb59c5ca9c8258a2e80dabba30a2da", "sha256": "420d4ebb09355316b71b5b54e3207582ec5207704edaa2327037e1051a502f84"} diff --git a/tools/hunter-local-ingest/evidence/1511668/auth-fault-arm-blocked/auth-faults-20261012T113539Z-5e25659eb6a8eac5/privacy-screen.json b/tools/hunter-local-ingest/evidence/1511668/auth-fault-arm-blocked/auth-faults-20261012T113539Z-5e25659eb6a8eac5/privacy-screen.json new file mode 100644 index 000000000..d3c5e59bc --- /dev/null +++ b/tools/hunter-local-ingest/evidence/1511668/auth-fault-arm-blocked/auth-faults-20261012T113539Z-5e25659eb6a8eac5/privacy-screen.json @@ -0,0 +1,12 @@ +{ + "clean": true, + "findings": [], + "finished_utc": "2026-10-12T11:35:39.747Z", + "missing": [], + "schema": "hunter-local-ingest/privacy-screen/2", + "screened": [ + "run-manifest.json", + "checks.jsonl", + "summary.json" + ] +} diff --git a/tools/hunter-local-ingest/evidence/1511668/auth-fault-arm-blocked/auth-faults-20261012T113539Z-5e25659eb6a8eac5/run-manifest.json b/tools/hunter-local-ingest/evidence/1511668/auth-fault-arm-blocked/auth-faults-20261012T113539Z-5e25659eb6a8eac5/run-manifest.json new file mode 100644 index 000000000..05f3055f1 --- /dev/null +++ b/tools/hunter-local-ingest/evidence/1511668/auth-fault-arm-blocked/auth-faults-20261012T113539Z-5e25659eb6a8eac5/run-manifest.json @@ -0,0 +1,111 @@ +{ + "backend": { + "declared_mode": "FAKE_HUNTER", + "declared_ref": null, + "verified": false + }, + "client": { + "declared_ref": null, + "git": null, + "interface": "2.0.0", + "package_version": "0.2.0", + "source_sha256": "843fd20eb408e4308664ec36453b7d887e994c92ad09b0760a897efaa6d0a6d7" + }, + "command": [ + "--endpoint", + "127.0.0.1:58354", + "--plan-file", + "", + "--out", + "", + "--label", + "auth-faults", + "--backend-mode", + "FAKE_HUNTER", + "--with-faults", + "--api-token-env", + "--poll-interval-s", + "0.05", + "--events-wait-s", + "0", + "--retry-backoff-s", + "0.0", + "--result-budget-s", + "30.0" + ], + "created_utc": "2026-10-12T11:35:39.710Z", + "endpoint": "127.0.0.1:58354", + "fixture": { + "create_sha256": "9c2dd5f33bb70b7199e85f165e87602986faa7f6b5beaee6f55db4f1f9edce97", + "files": [ + { + "bytes": 65536, + "contentType": "application/octet-stream", + "path": "synthetic/scan00.bin", + "role": "other", + "sha256": "a1ca0aa5e471b98beddf42738d706871542520398ced6f3ed81008e8c9812d85" + }, + { + "bytes": 65536, + "contentType": "application/octet-stream", + "path": "synthetic/scan01.bin", + "role": "other", + "sha256": "ef4380c88a7e0a2df7506640f6b435b153122e01070d7570870ebd2d3367d4be" + }, + { + "bytes": 65536, + "contentType": "application/octet-stream", + "path": "synthetic/scan02.bin", + "role": "other", + "sha256": "3fda1dfcabd6f77b655435c16a6c7b75d5f2f2b4ef9dccd814fede0f2b69e1f1" + }, + { + "bytes": 9793, + "contentType": "application/gzip", + "path": "streams/arkit_poses.csv.gz", + "role": "stream", + "sha256": "a23bcec6f6829c053e7bc1871999ca7b1a5e88639b5a6cde56afc655d3447388" + }, + { + "bytes": 9443, + "contentType": "application/gzip", + "path": "streams/imu_raw.csv.gz", + "role": "stream", + "sha256": "ae96d9008b71882aeb0dbc1c5463897aa9c316fbda28d5503b4676e0bd85a161" + } + ], + "format_version": 2, + "generator": "gen_synthetic_packet", + "packet_id": "synthetic-000001", + "packet_sha256": "9ab561f503ef3dc0c0e5b007157ab40c803d5b43dc38136285a72ab77acd17d1", + "plan_file_sha256": "eabf28a3f818ee22d38cec91ad6d85af6921f5cb45156378a007475368ab692f", + "plan_sha256": "50f73a67aeb28e5e0c41f40946958a2806024f75ae56dda1384025ccd0a8e4ac", + "seed": 1 + }, + "label": "auth-faults", + "origin_note": "Derived from published client behavior in HouseScanKit upload and result sources at alpha 263827ef. No private source, schema, spec, log or credential material appears in this package or its receipts.", + "restart": { + "argv": [], + "configured": false, + "timeout_s": 120.0 + }, + "run_id": "5e25659eb6a8eac5", + "runtime": { + "cpus": 12, + "implementation": "CPython", + "machine": "arm64", + "python": "3.13.12", + "release": "25.6.0", + "system": "Darwin" + }, + "sanitization": "Every value here passed the typed export schema before it was written: published enum words, package constants, digests, bounded numbers, and the plan's own synthetic paths and packet ids. A pattern screen then ran over the written files.", + "schema": "hunter-local-ingest/run-manifest/2", + "settings": { + "events_wait_s": 0, + "max_retries": 2, + "poll_interval_s": 0.05, + "result_budget_s": 30.0, + "retry_backoff_s": 0.0, + "with_faults": true + } +} diff --git a/tools/hunter-local-ingest/evidence/1511668/auth-fault-arm-blocked/auth-faults-20261012T113539Z-5e25659eb6a8eac5/summary.json b/tools/hunter-local-ingest/evidence/1511668/auth-fault-arm-blocked/auth-faults-20261012T113539Z-5e25659eb6a8eac5/summary.json new file mode 100644 index 000000000..1bb089e23 --- /dev/null +++ b/tools/hunter-local-ingest/evidence/1511668/auth-fault-arm-blocked/auth-faults-20261012T113539Z-5e25659eb6a8eac5/summary.json @@ -0,0 +1,54 @@ +{ + "artifacts": { + "checks.jsonl": "7660c20f07a08bcca18c4242af4d0b8b97e480ba30fb2548ca206f21c6e09029", + "run-manifest.json": "9c2d312c84c1af433e772745eddf8cdc2ca4c889f909cd9b4d62512ec175e1e8" + }, + "blocked": [ + "fault.lifecycle.health", + "fault.lifecycle.create", + "fault.lifecycle.register", + "fault.lifecycle.upload", + "fault.lifecycle.commit", + "fault.lifecycle.finalize", + "fault.lifecycle.events", + "fault.lifecycle.result", + "fault.retry-transient", + "fault.no-retry-501", + "fault.abort", + "fault.truncated-response" + ], + "counts_by_transport": { + "FAKE_HUNTER": { + "BLOCKED": 12, + "NOT_RUN": 1, + "PASS": 13 + }, + "GPU_STUB": { + "NOT_RUN": 3 + } + }, + "failed": [], + "finished_utc": "2026-10-12T11:35:39.740Z", + "lead_questions": [ + "Amendment semantics: does the published contract allow amending a registered capture, and with which route and headers?", + "Local-run auth mode: which credential form does the local backend expect from the published client? The client can send a bearer token on API routes only; no CLI flag supplies one yet.", + "Clock and expiry authority: whose clock governs capture expiry on the local backend?", + "Homeowner text: confirm that receipts may carry outcome kinds and counts but never messages, prompts or reasons." + ], + "mode": { + "backend_verified": false, + "declared_backend": "FAKE_HUNTER", + "gpu_arms": "NOT_RUN", + "real_mirror_cpu": "NOT_ESTABLISHED" + }, + "not_run": [ + "control.restart-recovery", + "gpu-stub.objects", + "gpu-stub.vlm", + "gpu-stub.dense" + ], + "run_id": "5e25659eb6a8eac5", + "schema": "hunter-local-ingest/summary/2", + "total": 29, + "verdict": "BLOCKED" +} diff --git a/tools/hunter-local-ingest/evidence/1511668/canary-responses/canary-20261012T113537Z-14009c69d672a187/checks.jsonl b/tools/hunter-local-ingest/evidence/1511668/canary-responses/canary-20261012T113537Z-14009c69d672a187/checks.jsonl new file mode 100644 index 000000000..a4711a300 --- /dev/null +++ b/tools/hunter-local-ingest/evidence/1511668/canary-responses/canary-20261012T113537Z-14009c69d672a187/checks.jsonl @@ -0,0 +1,17 @@ +{"expected": "an HTTP 2xx answer with status ok", "id": "lifecycle.health", "observed": {"contract": {"status": "ok"}, "http": {"attempts": 1, "body_bytes": 84, "body_sha256": "e7220e7b716f", "elapsed_ms": 0, "fields": ["status"], "http_status": 200, "shape": "object"}, "violations": []}, "oracle": "tools/integration-viewer reads GET /v1/healthz; HouseScanKit never calls it", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:37.593Z"} +{"expected": "2xx, a captureId and a published capture status", "id": "lifecycle.create", "observed": {"contract": {"captureId": "id:cdf2c8ea93b5", "maxBatch": 50, "status": "uploading", "unexpected_keys": {"count": 1, "digest": "unexpected-keys:ec5e373a56fb"}}, "http": {"attempts": 1, "body_bytes": 170, "body_sha256": "04a5017bad26", "elapsed_ms": 0, "fields": ["captureId", "status", "upload"], "http_status": 201, "shape": "object"}, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.create: POST captures with Idempotency-Key=packetId; the answer decodes as CaptureAPI.CreateResponse", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:37.593Z"} +{"expected": "every requested path answered exactly once, no other path, each committed or given a usable PUT target", "id": "lifecycle.register", "observed": {"batches": [{"contract": {"files": [{"path": "synthetic/scan00.bin", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "synthetic/scan01.bin", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "synthetic/scan02.bin", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "streams/arkit_poses.csv.gz", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "streams/imu_raw.csv.gz", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}], "unexpected_keys": {"count": 1, "digest": "unexpected-keys:ec5e373a56fb"}}, "http": {"attempts": 1, "body_bytes": 1321, "body_sha256": "a88c4acf4890", "elapsed_ms": 0, "fields": ["files"], "http_status": 200, "shape": "object"}, "violations": []}], "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.register: the answer decodes as RegisterResponse and is applied by path; a target needs method PUT and a URL that passes uploadURLProblem", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:37.594Z"} +{"expected": "2xx for every file that got a target", "id": "lifecycle.upload", "observed": {"committed_at_register": [], "uploads": [{"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "synthetic/scan00.bin", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "synthetic/scan01.bin", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "synthetic/scan02.bin", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "streams/arkit_poses.csv.gz", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "streams/imu_raw.csv.gz", "shape": "empty"}]}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.put + ScopedCaptureHTTP.upload: exactly the signed headers, never Authorization", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:37.598Z"} +{"expected": "committed equals the uploaded set; notFound and mismatch empty; every declared path committed by register or commit", "id": "lifecycle.commit", "observed": {"batches": [{"contract": {"committed": ["synthetic/scan00.bin", "synthetic/scan01.bin", "synthetic/scan02.bin", "streams/arkit_poses.csv.gz", "streams/imu_raw.csv.gz"], "mismatch": [], "notFound": [], "unexpected_keys": {"count": 1, "digest": "unexpected-keys:ec5e373a56fb"}}, "http": {"attempts": 1, "body_bytes": 243, "body_sha256": "16074b946a85", "elapsed_ms": 0, "fields": ["committed", "mismatch", "notFound"], "http_status": 200, "shape": "object"}, "violations": []}], "committed_at_register": [], "committed_total": 5, "declared": 5, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.commit: only a commit acknowledges a file; CommitResponse carries committed, notFound and mismatch", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:37.598Z"} +{"expected": "2xx, a runId, a published status, no missing file", "id": "lifecycle.finalize", "observed": {"contract": {"missing": [], "runId": "id:3e513f49afe3", "status": "processing", "unexpected_keys": {"count": 1, "digest": "unexpected-keys:ec5e373a56fb"}}, "http": {"attempts": 1, "body_bytes": 154, "body_sha256": "4377bd7e99e1", "elapsed_ms": 0, "fields": ["missing", "runId", "status"], "http_status": 202, "shape": "object"}, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.finalize: X-Packet-Sha256 and Idempotency-Key=packetId; the answer decodes as FinalizeResponse", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:37.599Z"} +{"expected": "a terminal status within the budget, every answer contract-shaped", "id": "lifecycle.events", "observed": {"answers": 1, "finalize_retries": 0, "last": {"contract": {"events": [{"data": {"runId": "id:3e513f49afe3", "runId_matches": true, "stage": "unrecognized:fe938bd70992"}, "seq": 1, "type": "unrecognized:fe938bd70992"}], "next": 1, "status": "complete", "unexpected_keys": {"count": 1, "digest": "unexpected-keys:ec5e373a56fb"}}, "http": {"attempts": 1, "body_bytes": 293, "body_sha256": "5cc9e9d89d41", "elapsed_ms": 0, "fields": ["events", "next", "status"], "http_status": 200, "shape": "object"}, "violations": []}}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.pollEvents: EventsResponse until CaptureAPI.terminalStatuses; next never moves back; a verdict names this run; retry_finalize re-sends the packet", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:37.599Z"} +{"expected": "a decodable result for this run whose status matches the terminal event status", "id": "lifecycle.result", "observed": {"contract": {"criteria": null, "has_preview_url": true, "memberActions": 0, "outcome": {"kind": "eligible", "reasons": 0}, "runId": "id:3e513f49afe3", "status": "complete", "unexpected_keys": {"count": 1, "digest": "unexpected-keys:ec5e373a56fb"}, "viewsNeeded": 0}, "http": {"attempts": 1, "body_bytes": 394, "body_sha256": "c85c1ff05b08", "elapsed_ms": 0, "fields": ["memberActions", "outcome", "previewUrl", "runId", "status", "viewsNeeded"], "http_status": 200, "shape": "object"}, "not_ready_reads": 0, "run_matches": true, "status_matches": true, "terminal_status": "complete", "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.fetchResult: the whole body decodes as CaptureResult.Response, its runId is the finalized run, and a null outcome is final only under statusesWithoutOutcome", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:37.600Z"} +{"expected": "both creates 2xx with the same captureId", "id": "control.idempotent-create", "observed": {"first": {"contract": {"captureId": "id:6bfeb43306c5", "maxBatch": 50, "status": "uploading", "unexpected_keys": {"count": 1, "digest": "unexpected-keys:ec5e373a56fb"}}, "http": {"attempts": 1, "body_bytes": 170, "body_sha256": "0d3221cb4291", "elapsed_ms": 0, "fields": ["captureId", "status", "upload"], "http_status": 201, "shape": "object"}, "violations": []}, "same_capture": true, "second": {"contract": {"captureId": "id:6bfeb43306c5", "maxBatch": 50, "status": "uploading", "unexpected_keys": {"count": 1, "digest": "unexpected-keys:ec5e373a56fb"}}, "http": {"attempts": 1, "body_bytes": 170, "body_sha256": "0d3221cb4291", "elapsed_ms": 0, "fields": ["captureId", "status", "upload"], "http_status": 200, "shape": "object"}, "violations": []}}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.start: create is bound to Idempotency-Key=packetId, so a repeated create with the same bytes names the same capture", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:37.601Z"} +{"expected": "intact files committed; the flipped file in mismatch or notFound, or its PUT refused, and never committed", "id": "control.corrupt-upload", "observed": {"batches": [{"contract": {"committed": ["synthetic/scan01.bin", "synthetic/scan02.bin", "streams/arkit_poses.csv.gz", "streams/imu_raw.csv.gz"], "mismatch": ["synthetic/scan00.bin"], "notFound": [], "unexpected_keys": {"count": 1, "digest": "unexpected-keys:ec5e373a56fb"}}, "http": {"attempts": 1, "body_bytes": 241, "body_sha256": "ed07e93f5a0d", "elapsed_ms": 0, "fields": ["committed", "mismatch", "notFound"], "http_status": 200, "shape": "object"}, "violations": []}], "intact_committed": true, "intact_reported_negative": false, "tampered": "synthetic/scan00.bin", "tampered_committed": false, "tampered_put_status": 200, "tampered_reported": true, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CommitResponse separates committed from mismatch/notFound; one file's bytes are flipped after its digest was registered", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:37.606Z"} +{"expected": "intact files committed; the truncated file in mismatch or notFound, or its PUT refused, and never committed", "id": "control.truncated-upload", "observed": {"batches": [{"contract": {"committed": ["synthetic/scan01.bin", "synthetic/scan02.bin", "streams/arkit_poses.csv.gz", "streams/imu_raw.csv.gz"], "mismatch": ["synthetic/scan00.bin"], "notFound": [], "unexpected_keys": {"count": 1, "digest": "unexpected-keys:ec5e373a56fb"}}, "http": {"attempts": 1, "body_bytes": 241, "body_sha256": "ed07e93f5a0d", "elapsed_ms": 0, "fields": ["committed", "mismatch", "notFound"], "http_status": 200, "shape": "object"}, "violations": []}], "intact_committed": true, "intact_reported_negative": false, "tampered": "synthetic/scan00.bin", "tampered_committed": false, "tampered_put_status": 200, "tampered_reported": true, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CommitResponse separates committed from mismatch/notFound; one file loses its last byte after its digest was registered", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:37.610Z"} +{"expected": "404 with error code capture_not_found for an id the harness invented", "id": "control.wrong-capture", "observed": {"capture": "id:1976512104be", "errors": {"codes": ["capture_not_found"]}, "http": {"attempts": 1, "body_bytes": 170, "body_sha256": "d511c008eca0", "elapsed_ms": 0, "fields": ["errors"], "http_status": 404, "shape": "object"}}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.captureGone: an unknown capture answers 404 capture_not_found", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:37.611Z"} +{"expected": "every traced check present and PASS with the traced status class and fields, or upload and commit skipped because register reported every declared file committed", "id": "trace.expected-lifecycle-v3", "observed": {"compared": 12, "disagreements": [], "not_comparable": []}, "oracle": "frozen expected trace traces/expected-lifecycle-v3.jsonl, written from the published contract, with a no-request branch for files committed at register", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:37.612Z"} +{"expected": "after a successful restart the capture still reports its terminal status and run", "id": "control.restart-recovery", "observed": {"note": "restart-not-configured"}, "oracle": "operator restart command, then the baseline capture is read again over the published events and result routes", "status": "NOT_RUN", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:37.613Z"} +{"expected": "not run", "id": "gpu-stub.objects", "observed": {"note": "gpu-not-authorized"}, "oracle": "GPU-dependent arms are named and never executed by this harness", "status": "NOT_RUN", "transport": "GPU_STUB", "ts": "2026-10-12T11:35:37.613Z"} +{"expected": "not run", "id": "gpu-stub.vlm", "observed": {"note": "gpu-not-authorized"}, "oracle": "GPU-dependent arms are named and never executed by this harness", "status": "NOT_RUN", "transport": "GPU_STUB", "ts": "2026-10-12T11:35:37.613Z"} +{"expected": "not run", "id": "gpu-stub.dense", "observed": {"note": "gpu-not-authorized"}, "oracle": "GPU-dependent arms are named and never executed by this harness", "status": "NOT_RUN", "transport": "GPU_STUB", "ts": "2026-10-12T11:35:37.613Z"} diff --git a/tools/hunter-local-ingest/evidence/1511668/canary-responses/canary-20261012T113537Z-14009c69d672a187/privacy-chain.jsonl b/tools/hunter-local-ingest/evidence/1511668/canary-responses/canary-20261012T113537Z-14009c69d672a187/privacy-chain.jsonl new file mode 100644 index 000000000..20e432d5f --- /dev/null +++ b/tools/hunter-local-ingest/evidence/1511668/canary-responses/canary-20261012T113537Z-14009c69d672a187/privacy-chain.jsonl @@ -0,0 +1,4 @@ +{"artifact": "run-manifest.json", "at": "2026-10-12T11:35:37.590Z", "bytes": 3454, "chain_sha256": "3880c8246b72de171459bd7270945a3ac693ef65d9148ca68fe9ff26ef6e6993", "sha256": "8cc72899b14eedda2045740e443040009197819da7e5c2fffafbddee67edb628"} +{"artifact": "checks.jsonl", "at": "2026-10-12T11:35:37.613Z", "bytes": 13213, "chain_sha256": "e55cb67258416e4bcebc7882fd8c6de55b806cc9e32bd66ddcac9bc2cdd6e421", "sha256": "c9903251775a5737d984650dcc89a292b96036de65b2a846545074b2e0060ad8"} +{"artifact": "summary.json", "at": "2026-10-12T11:35:37.613Z", "bytes": 1366, "chain_sha256": "02cd37e260a3eddc34725aa89e0658528b8df9384b90ff6d6c795dc99c769364", "sha256": "1743da7541bb01a829e6f9be26a4bd6b247e727dfbc20263f667eddadfb546ae"} +{"artifact": "privacy-screen.json", "at": "2026-10-12T11:35:37.619Z", "bytes": 238, "chain_sha256": "6795cd427ccd8c9b2d4f1fd04c0ee5010fcebadfc5e8d1cb352609b7a94e0247", "sha256": "5da5a2e780a8c96f184dc7a477d4eae16b825657e1a2e8fd5f0339525921b182"} diff --git a/tools/hunter-local-ingest/evidence/1511668/canary-responses/canary-20261012T113537Z-14009c69d672a187/privacy-screen.json b/tools/hunter-local-ingest/evidence/1511668/canary-responses/canary-20261012T113537Z-14009c69d672a187/privacy-screen.json new file mode 100644 index 000000000..98d57d3dc --- /dev/null +++ b/tools/hunter-local-ingest/evidence/1511668/canary-responses/canary-20261012T113537Z-14009c69d672a187/privacy-screen.json @@ -0,0 +1,12 @@ +{ + "clean": true, + "findings": [], + "finished_utc": "2026-10-12T11:35:37.618Z", + "missing": [], + "schema": "hunter-local-ingest/privacy-screen/2", + "screened": [ + "run-manifest.json", + "checks.jsonl", + "summary.json" + ] +} diff --git a/tools/hunter-local-ingest/evidence/1511668/canary-responses/canary-20261012T113537Z-14009c69d672a187/run-manifest.json b/tools/hunter-local-ingest/evidence/1511668/canary-responses/canary-20261012T113537Z-14009c69d672a187/run-manifest.json new file mode 100644 index 000000000..909d0c201 --- /dev/null +++ b/tools/hunter-local-ingest/evidence/1511668/canary-responses/canary-20261012T113537Z-14009c69d672a187/run-manifest.json @@ -0,0 +1,109 @@ +{ + "backend": { + "declared_mode": "FAKE_HUNTER", + "declared_ref": null, + "verified": false + }, + "client": { + "declared_ref": null, + "git": null, + "interface": "2.0.0", + "package_version": "0.2.0", + "source_sha256": "843fd20eb408e4308664ec36453b7d887e994c92ad09b0760a897efaa6d0a6d7" + }, + "command": [ + "--endpoint", + "127.0.0.1:58215", + "--plan-file", + "", + "--out", + "", + "--label", + "canary", + "--backend-mode", + "FAKE_HUNTER", + "--poll-interval-s", + "0.05", + "--events-wait-s", + "0", + "--retry-backoff-s", + "0.0", + "--result-budget-s", + "30.0" + ], + "created_utc": "2026-10-12T11:35:37.582Z", + "endpoint": "127.0.0.1:58215", + "fixture": { + "create_sha256": "9c2dd5f33bb70b7199e85f165e87602986faa7f6b5beaee6f55db4f1f9edce97", + "files": [ + { + "bytes": 65536, + "contentType": "application/octet-stream", + "path": "synthetic/scan00.bin", + "role": "other", + "sha256": "a1ca0aa5e471b98beddf42738d706871542520398ced6f3ed81008e8c9812d85" + }, + { + "bytes": 65536, + "contentType": "application/octet-stream", + "path": "synthetic/scan01.bin", + "role": "other", + "sha256": "ef4380c88a7e0a2df7506640f6b435b153122e01070d7570870ebd2d3367d4be" + }, + { + "bytes": 65536, + "contentType": "application/octet-stream", + "path": "synthetic/scan02.bin", + "role": "other", + "sha256": "3fda1dfcabd6f77b655435c16a6c7b75d5f2f2b4ef9dccd814fede0f2b69e1f1" + }, + { + "bytes": 9793, + "contentType": "application/gzip", + "path": "streams/arkit_poses.csv.gz", + "role": "stream", + "sha256": "a23bcec6f6829c053e7bc1871999ca7b1a5e88639b5a6cde56afc655d3447388" + }, + { + "bytes": 9443, + "contentType": "application/gzip", + "path": "streams/imu_raw.csv.gz", + "role": "stream", + "sha256": "ae96d9008b71882aeb0dbc1c5463897aa9c316fbda28d5503b4676e0bd85a161" + } + ], + "format_version": 2, + "generator": "gen_synthetic_packet", + "packet_id": "synthetic-000001", + "packet_sha256": "9ab561f503ef3dc0c0e5b007157ab40c803d5b43dc38136285a72ab77acd17d1", + "plan_file_sha256": "eabf28a3f818ee22d38cec91ad6d85af6921f5cb45156378a007475368ab692f", + "plan_sha256": "50f73a67aeb28e5e0c41f40946958a2806024f75ae56dda1384025ccd0a8e4ac", + "seed": 1 + }, + "label": "canary", + "origin_note": "Derived from published client behavior in HouseScanKit upload and result sources at alpha 263827ef. No private source, schema, spec, log or credential material appears in this package or its receipts.", + "restart": { + "argv": [], + "configured": false, + "timeout_s": 120.0 + }, + "run_id": "14009c69d672a187", + "runtime": { + "cpus": 12, + "implementation": "CPython", + "machine": "arm64", + "python": "3.13.12", + "release": "25.6.0", + "system": "Darwin" + }, + "sanitization": "Every value here passed the typed export schema before it was written: published enum words, package constants, digests, bounded numbers, and the plan's own synthetic paths and packet ids. A pattern screen then ran over the written files.", + "schema": "hunter-local-ingest/run-manifest/2", + "settings": { + "events_wait_s": 0, + "max_retries": 2, + "poll_interval_s": 0.05, + "result_budget_s": 30.0, + "retry_backoff_s": 0.0, + "with_faults": false + } +} diff --git a/tools/hunter-local-ingest/evidence/1511668/canary-responses/canary-20261012T113537Z-14009c69d672a187/summary.json b/tools/hunter-local-ingest/evidence/1511668/canary-responses/canary-20261012T113537Z-14009c69d672a187/summary.json new file mode 100644 index 000000000..23ff8ebca --- /dev/null +++ b/tools/hunter-local-ingest/evidence/1511668/canary-responses/canary-20261012T113537Z-14009c69d672a187/summary.json @@ -0,0 +1,40 @@ +{ + "artifacts": { + "checks.jsonl": "c9903251775a5737d984650dcc89a292b96036de65b2a846545074b2e0060ad8", + "run-manifest.json": "8cc72899b14eedda2045740e443040009197819da7e5c2fffafbddee67edb628" + }, + "blocked": [], + "counts_by_transport": { + "FAKE_HUNTER": { + "NOT_RUN": 1, + "PASS": 13 + }, + "GPU_STUB": { + "NOT_RUN": 3 + } + }, + "failed": [], + "finished_utc": "2026-10-12T11:35:37.613Z", + "lead_questions": [ + "Amendment semantics: does the published contract allow amending a registered capture, and with which route and headers?", + "Local-run auth mode: which credential form does the local backend expect from the published client? The client can send a bearer token on API routes only; no CLI flag supplies one yet.", + "Clock and expiry authority: whose clock governs capture expiry on the local backend?", + "Homeowner text: confirm that receipts may carry outcome kinds and counts but never messages, prompts or reasons." + ], + "mode": { + "backend_verified": false, + "declared_backend": "FAKE_HUNTER", + "gpu_arms": "NOT_RUN", + "real_mirror_cpu": "NOT_ESTABLISHED" + }, + "not_run": [ + "control.restart-recovery", + "gpu-stub.objects", + "gpu-stub.vlm", + "gpu-stub.dense" + ], + "run_id": "14009c69d672a187", + "schema": "hunter-local-ingest/summary/2", + "total": 17, + "verdict": "PASS" +} diff --git a/tools/hunter-local-ingest/evidence/1511668/index.json b/tools/hunter-local-ingest/evidence/1511668/index.json new file mode 100644 index 000000000..faefa357d --- /dev/null +++ b/tools/hunter-local-ingest/evidence/1511668/index.json @@ -0,0 +1,270 @@ +{ + "committed_source_sha256": "843fd20eb408e4308664ec36453b7d887e994c92ad09b0760a897efaa6d0a6d7", + "installed_package_under_venv": true, + "installed_source_sha256": "843fd20eb408e4308664ec36453b7d887e994c92ad09b0760a897efaa6d0a6d7", + "plan_sha256": "eabf28a3f818ee22d38cec91ad6d85af6921f5cb45156378a007475368ab692f", + "runs": { + "auth-fault-arm-blocked": { + "artifacts": { + "checks.jsonl": "7660c20f07a08bcca18c4242af4d0b8b97e480ba30fb2548ca206f21c6e09029", + "privacy-chain.jsonl": "b93ee4518a000574a1f796c44e12f9949814bf6d6d03a979c7ab28973b5999d4", + "privacy-screen.json": "420d4ebb09355316b71b5b54e3207582ec5207704edaa2327037e1051a502f84", + "run-manifest.json": "9c2d312c84c1af433e772745eddf8cdc2ca4c889f909cd9b4d62512ec175e1e8", + "summary.json": "d23a921377e8ee7e32665b48bf9009ef403fc8d259aeed776f9dd8632cb5186a" + }, + "blocked": [ + "fault.lifecycle.health", + "fault.lifecycle.create", + "fault.lifecycle.register", + "fault.lifecycle.upload", + "fault.lifecycle.commit", + "fault.lifecycle.finalize", + "fault.lifecycle.events", + "fault.lifecycle.result", + "fault.retry-transient", + "fault.no-retry-501", + "fault.abort", + "fault.truncated-response" + ], + "chain_head": "7388f9a00373721d6628a30e984b9883bfbb59c5ca9c8258a2e80dabba30a2da", + "counts_by_transport": { + "FAKE_HUNTER": { + "BLOCKED": 12, + "NOT_RUN": 1, + "PASS": 13 + }, + "GPU_STUB": { + "NOT_RUN": 3 + } + }, + "exit_code": 4, + "failed": [], + "not_run": [ + "control.restart-recovery", + "gpu-stub.objects", + "gpu-stub.vlm", + "gpu-stub.dense" + ], + "run_dir": "auth-faults-20261012T113539Z-5e25659eb6a8eac5", + "token_occurrences": 0, + "unauthenticated_api_requests": 0, + "verdict": "BLOCKED", + "verify_exit": 0, + "verify_last_line": "verify: OK" + }, + "canary-responses": { + "artifacts": { + "checks.jsonl": "c9903251775a5737d984650dcc89a292b96036de65b2a846545074b2e0060ad8", + "privacy-chain.jsonl": "941212b4c77d4c380fa32918f0fdbb2327f8e405cf8912b77d6776ffa481e546", + "privacy-screen.json": "5da5a2e780a8c96f184dc7a477d4eae16b825657e1a2e8fd5f0339525921b182", + "run-manifest.json": "8cc72899b14eedda2045740e443040009197819da7e5c2fffafbddee67edb628", + "summary.json": "1743da7541bb01a829e6f9be26a4bd6b247e727dfbc20263f667eddadfb546ae" + }, + "blocked": [], + "canary": "CANARY-evidence-9cd75a1c19a8", + "canary_occurrences": 0, + "chain_head": "6795cd427ccd8c9b2d4f1fd04c0ee5010fcebadfc5e8d1cb352609b7a94e0247", + "counts_by_transport": { + "FAKE_HUNTER": { + "NOT_RUN": 1, + "PASS": 13 + }, + "GPU_STUB": { + "NOT_RUN": 3 + } + }, + "exit_code": 0, + "failed": [], + "not_run": [ + "control.restart-recovery", + "gpu-stub.objects", + "gpu-stub.vlm", + "gpu-stub.dense" + ], + "run_dir": "canary-20261012T113537Z-14009c69d672a187", + "verdict": "PASS", + "verify_exit": 0, + "verify_last_line": "verify: OK" + }, + "max-batch-2": { + "artifacts": { + "checks.jsonl": "23d4330ee3337207cd9f5fc1a1ed71a4ccde8fa7eb09c57a5c5a23366bac9ad8", + "privacy-chain.jsonl": "7f5fae89c769619429af470659fedfbd8a27e93690a612fa1ddc5aac5d01ba33", + "privacy-screen.json": "ecb6f34934d3f420c367baa92835b6375808077c704ae690c577ba124a10f8d2", + "run-manifest.json": "ed4f0b8e57a63a4fa4e92df273d6b26971c652e035a75b089975c47b3daf7bc7", + "summary.json": "c1fee89ba1360b22e4919cde904923500a6eba330380eee3331d611ee8722aa1" + }, + "blocked": [], + "chain_head": "2b58035eac21a2f2b9bf08a7b3c6ced0cd849e5a2035651ad40bb9fd37180e99", + "counts_by_transport": { + "FAKE_HUNTER": { + "NOT_RUN": 1, + "PASS": 13 + }, + "GPU_STUB": { + "NOT_RUN": 3 + } + }, + "exit_code": 0, + "failed": [], + "not_run": [ + "control.restart-recovery", + "gpu-stub.objects", + "gpu-stub.vlm", + "gpu-stub.dense" + ], + "run_dir": "max-batch-2-20261012T113539Z-d5ef95338b5c3a22", + "verdict": "PASS", + "verify_exit": 0, + "verify_last_line": "verify: OK" + }, + "mutation-commits-tampered": { + "artifacts": { + "checks.jsonl": "e4e51f47d421915d07f81a240a187b0ff2f9eb978de64014f0a9b04ff93d5597", + "privacy-chain.jsonl": "daaa56340ca6e41845900cc7879088e682e3179d6e79c778b71b80e2fa0adf9f", + "privacy-screen.json": "0d325f47d2ce67341c707f02e28314dd4287d125550da6baf480ca49465a00c6", + "run-manifest.json": "de02f749138caa6f2498f6ef6ac4d69b3975e14f6db8e486aa8a4017216099b1", + "summary.json": "fb1a5072dba5eef74fd9f418bf7cf49e6e05ceb09e3d705ec1c10288851cfd68" + }, + "blocked": [], + "chain_head": "53f2ebf77525f3c6863afa09456ee5ef6450dde8c0dabaa1a18165f8941653e6", + "counts_by_transport": { + "FAKE_HUNTER": { + "FAIL": 3, + "NOT_RUN": 1, + "PASS": 22 + }, + "GPU_STUB": { + "NOT_RUN": 3 + } + }, + "exit_code": 1, + "failed": [ + "control.corrupt-upload", + "control.truncated-upload", + "trace.expected-lifecycle-v3" + ], + "not_run": [ + "control.restart-recovery", + "gpu-stub.objects", + "gpu-stub.vlm", + "gpu-stub.dense" + ], + "run_dir": "mutation-20261012T113534Z-e31c3fdf39791506", + "verdict": "FAIL", + "verify_exit": 0, + "verify_last_line": "verify: OK" + }, + "real-api-unreachable": { + "artifacts": { + "checks.jsonl": "20be67f9da841af7ec192a43b9f5f8d66d222da374033398dc5ef0e9b81a5b64", + "privacy-chain.jsonl": "4fda9ee8b6733e0b304efc05f9d998a420b2f6a0495ba26bce2bfff7bb8f8eba", + "privacy-screen.json": "dee763035de69a36eadab8be18bacc9a4a5f73be7a64793975a08a25c91a0839", + "run-manifest.json": "f544a0a13099914cd04484060517be26e42146cc17c4f41060a4ebcaaf7d2076", + "summary.json": "525c695fbeb0f8d28323f389891c926957a8defbf6482557cd7455f8a32c9129" + }, + "blocked": [ + "lifecycle.health", + "lifecycle.create", + "lifecycle.register", + "lifecycle.upload", + "lifecycle.commit", + "lifecycle.finalize", + "lifecycle.events", + "lifecycle.result", + "control.idempotent-create", + "control.corrupt-upload", + "control.truncated-upload", + "control.wrong-capture", + "trace.expected-lifecycle-v3" + ], + "chain_head": "3d08a4f54ce935f118171ede03a102c8810f4c6c4fe75a74bda60386ebb3db94", + "counts_by_transport": { + "GPU_STUB": { + "NOT_RUN": 3 + }, + "REAL_API": { + "BLOCKED": 13, + "NOT_RUN": 1 + } + }, + "exit_code": 4, + "failed": [], + "not_run": [ + "control.restart-recovery", + "gpu-stub.objects", + "gpu-stub.vlm", + "gpu-stub.dense" + ], + "run_dir": "real-api-unreachable-20261012T113524Z-f445c56d6cd5b3d3", + "verdict": "BLOCKED", + "verify_exit": 0, + "verify_last_line": "verify: OK" + }, + "rerun-committed-capture": { + "artifacts": { + "checks.jsonl": "775b234bc060147fec93a0db378ef42b8ed6593d616c467952f32665ebafb088", + "privacy-chain.jsonl": "2b73e11d2a7f7d2e9233b9ccd1cd0e7ddd96d160c67c4c6ae84f4123e4b1922b", + "privacy-screen.json": "d09fc155f5bee507550ff9ab1af2119ff8c28c5c42804e38e1c6c7b60c4a9ada", + "run-manifest.json": "9f7c00b7cb44e5e3741d621749aa71c37cfd926da0b57936d58600cbef5e3a4f", + "summary.json": "1edb1aba01f48e49ae99ccf559299b98f863faf6fcfed35200492f5414497d13" + }, + "blocked": [], + "chain_head": "96ff77930cd2e8f9fd521a058b9bbd98e87f77c92b7b99f839412105645b6327", + "counts_by_transport": { + "FAKE_HUNTER": { + "NOT_RUN": 1, + "PASS": 13 + }, + "GPU_STUB": { + "NOT_RUN": 3 + } + }, + "exit_code": 0, + "failed": [], + "first_pass_exit": 0, + "not_run": [ + "control.restart-recovery", + "gpu-stub.objects", + "gpu-stub.vlm", + "gpu-stub.dense" + ], + "rerun_puts": 10, + "run_dir": "rerun-20261012T113538Z-16c9a6f5ca70bb26", + "verdict": "PASS", + "verify_exit": 0, + "verify_last_line": "verify: OK" + }, + "selfcheck": { + "artifacts": { + "checks.jsonl": "af46460e0c8256c151cd0106cb676a29e1a26df4a2b902e7fb7971a3d3b48884", + "privacy-chain.jsonl": "0ee5753e8771af6856e10ce02f700e17fd148f5f858923d5dcbe7d9c501e798e", + "privacy-screen.json": "5d830a9a88ba211e79c36126198f33755e14aafd728983f04f93ae69a6965bc2", + "run-manifest.json": "b9ce795e064561f52586d1469524cf0ec891331f50ddad83a18d59b3854fb80b", + "summary.json": "7989ce84835af32ed6dfbbade954253541df379670c7274ae2b3750a975c6c94" + }, + "blocked": [], + "chain_head": "17726963e7b3241c5779ad91796230590d751b2d1a8f1c889afbe496c1608ff8", + "counts_by_transport": { + "FAKE_HUNTER": { + "PASS": 26 + }, + "GPU_STUB": { + "NOT_RUN": 3 + } + }, + "exit_code": 0, + "failed": [], + "not_run": [ + "gpu-stub.objects", + "gpu-stub.vlm", + "gpu-stub.dense" + ], + "run_dir": "selfcheck-20261012T113520Z-6d9d8505f2ea1312", + "stdout_last": "selfcheck: PASS", + "verdict": "PASS", + "verify_exit": 0, + "verify_last_line": "verify: OK" + } + } +} diff --git a/tools/hunter-local-ingest/evidence/1511668/max-batch-2/max-batch-2-20261012T113539Z-d5ef95338b5c3a22/checks.jsonl b/tools/hunter-local-ingest/evidence/1511668/max-batch-2/max-batch-2-20261012T113539Z-d5ef95338b5c3a22/checks.jsonl new file mode 100644 index 000000000..db32f81ef --- /dev/null +++ b/tools/hunter-local-ingest/evidence/1511668/max-batch-2/max-batch-2-20261012T113539Z-d5ef95338b5c3a22/checks.jsonl @@ -0,0 +1,17 @@ +{"expected": "an HTTP 2xx answer with status ok", "id": "lifecycle.health", "observed": {"contract": {"status": "ok"}, "http": {"attempts": 1, "body_bytes": 16, "body_sha256": "08e2c358ce13", "elapsed_ms": 1, "fields": ["status"], "http_status": 200, "shape": "object"}, "violations": []}, "oracle": "tools/integration-viewer reads GET /v1/healthz; HouseScanKit never calls it", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:39.042Z"} +{"expected": "2xx, a captureId and a published capture status", "id": "lifecycle.create", "observed": {"contract": {"captureId": "id:fd102437f369", "maxBatch": 2, "status": "uploading"}, "http": {"attempts": 1, "body_bytes": 77, "body_sha256": "1c8c152f2eb5", "elapsed_ms": 0, "fields": ["captureId", "status", "upload"], "http_status": 201, "shape": "object"}, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.create: POST captures with Idempotency-Key=packetId; the answer decodes as CaptureAPI.CreateResponse", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:39.043Z"} +{"expected": "every requested path answered exactly once, no other path, each committed or given a usable PUT target", "id": "lifecycle.register", "observed": {"batches": [{"contract": {"files": [{"path": "synthetic/scan00.bin", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "synthetic/scan01.bin", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}]}, "http": {"attempts": 1, "body_bytes": 511, "body_sha256": "3c3a2c9915f5", "elapsed_ms": 0, "fields": ["files"], "http_status": 200, "shape": "object"}, "violations": []}, {"contract": {"files": [{"path": "synthetic/scan02.bin", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "streams/arkit_poses.csv.gz", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}]}, "http": {"attempts": 1, "body_bytes": 509, "body_sha256": "337733d05606", "elapsed_ms": 0, "fields": ["files"], "http_status": 200, "shape": "object"}, "violations": []}, {"contract": {"files": [{"path": "streams/imu_raw.csv.gz", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}]}, "http": {"attempts": 1, "body_bytes": 255, "body_sha256": "30966979a7c4", "elapsed_ms": 0, "fields": ["files"], "http_status": 200, "shape": "object"}, "violations": []}], "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.register: the answer decodes as RegisterResponse and is applied by path; a target needs method PUT and a URL that passes uploadURLProblem", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:39.046Z"} +{"expected": "2xx for every file that got a target", "id": "lifecycle.upload", "observed": {"committed_at_register": [], "uploads": [{"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "synthetic/scan00.bin", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "synthetic/scan01.bin", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "synthetic/scan02.bin", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "streams/arkit_poses.csv.gz", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "streams/imu_raw.csv.gz", "shape": "empty"}]}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.put + ScopedCaptureHTTP.upload: exactly the signed headers, never Authorization", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:39.049Z"} +{"expected": "committed equals the uploaded set; notFound and mismatch empty; every declared path committed by register or commit", "id": "lifecycle.commit", "observed": {"batches": [{"contract": {"committed": ["synthetic/scan00.bin", "synthetic/scan01.bin"], "mismatch": [], "notFound": []}, "http": {"attempts": 1, "body_bytes": 95, "body_sha256": "3007e1924e6c", "elapsed_ms": 0, "fields": ["committed", "mismatch", "notFound"], "http_status": 200, "shape": "object"}, "violations": []}, {"contract": {"committed": ["synthetic/scan02.bin", "streams/arkit_poses.csv.gz"], "mismatch": [], "notFound": []}, "http": {"attempts": 1, "body_bytes": 101, "body_sha256": "70f3ee56be56", "elapsed_ms": 0, "fields": ["committed", "mismatch", "notFound"], "http_status": 200, "shape": "object"}, "violations": []}, {"contract": {"committed": ["streams/imu_raw.csv.gz"], "mismatch": [], "notFound": []}, "http": {"attempts": 1, "body_bytes": 73, "body_sha256": "86b3a2401c09", "elapsed_ms": 0, "fields": ["committed", "mismatch", "notFound"], "http_status": 200, "shape": "object"}, "violations": []}], "committed_at_register": [], "committed_total": 5, "declared": 5, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.commit: only a commit acknowledges a file; CommitResponse carries committed, notFound and mismatch", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:39.051Z"} +{"expected": "2xx, a runId, a published status, no missing file", "id": "lifecycle.finalize", "observed": {"contract": {"missing": [], "runId": "id:492e113d2d27", "status": "processing"}, "http": {"attempts": 1, "body_bytes": 62, "body_sha256": "425e9d06a56d", "elapsed_ms": 0, "fields": ["missing", "runId", "status"], "http_status": 202, "shape": "object"}, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.finalize: X-Packet-Sha256 and Idempotency-Key=packetId; the answer decodes as FinalizeResponse", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:39.051Z"} +{"expected": "a terminal status within the budget, every answer contract-shaped", "id": "lifecycle.events", "observed": {"answers": 1, "finalize_retries": 0, "last": {"contract": {"events": [{"data": {"runId": "id:492e113d2d27", "runId_matches": true}, "seq": 1, "type": "verdict_ready"}], "next": 1, "status": "complete"}, "http": {"attempts": 1, "body_bytes": 145, "body_sha256": "f7919284ecb6", "elapsed_ms": 0, "fields": ["events", "next", "status"], "http_status": 200, "shape": "object"}, "violations": []}}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.pollEvents: EventsResponse until CaptureAPI.terminalStatuses; next never moves back; a verdict names this run; retry_finalize re-sends the packet", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:39.052Z"} +{"expected": "a decodable result for this run whose status matches the terminal event status", "id": "lifecycle.result", "observed": {"contract": {"criteria": null, "has_preview_url": false, "memberActions": 0, "outcome": {"kind": "eligible", "reasons": 0}, "runId": "id:492e113d2d27", "status": "complete", "viewsNeeded": 0}, "http": {"attempts": 1, "body_bytes": 227, "body_sha256": "1dc1b0ebf7a6", "elapsed_ms": 0, "fields": ["memberActions", "outcome", "runId", "status", "viewsNeeded"], "http_status": 200, "shape": "object"}, "not_ready_reads": 0, "run_matches": true, "status_matches": true, "terminal_status": "complete", "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.fetchResult: the whole body decodes as CaptureResult.Response, its runId is the finalized run, and a null outcome is final only under statusesWithoutOutcome", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:39.052Z"} +{"expected": "both creates 2xx with the same captureId", "id": "control.idempotent-create", "observed": {"first": {"contract": {"captureId": "id:b9d50067aadb", "maxBatch": 2, "status": "uploading"}, "http": {"attempts": 1, "body_bytes": 77, "body_sha256": "52186cc73485", "elapsed_ms": 0, "fields": ["captureId", "status", "upload"], "http_status": 201, "shape": "object"}, "violations": []}, "same_capture": true, "second": {"contract": {"captureId": "id:b9d50067aadb", "maxBatch": 2, "status": "uploading"}, "http": {"attempts": 1, "body_bytes": 77, "body_sha256": "52186cc73485", "elapsed_ms": 0, "fields": ["captureId", "status", "upload"], "http_status": 200, "shape": "object"}, "violations": []}}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.start: create is bound to Idempotency-Key=packetId, so a repeated create with the same bytes names the same capture", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:39.053Z"} +{"expected": "intact files committed; the flipped file in mismatch or notFound, or its PUT refused, and never committed", "id": "control.corrupt-upload", "observed": {"batches": [{"contract": {"committed": ["synthetic/scan01.bin"], "mismatch": ["synthetic/scan00.bin"], "notFound": []}, "http": {"attempts": 1, "body_bytes": 93, "body_sha256": "7a48e8706461", "elapsed_ms": 0, "fields": ["committed", "mismatch", "notFound"], "http_status": 200, "shape": "object"}, "violations": []}, {"contract": {"committed": ["synthetic/scan02.bin", "streams/arkit_poses.csv.gz"], "mismatch": [], "notFound": []}, "http": {"attempts": 1, "body_bytes": 101, "body_sha256": "70f3ee56be56", "elapsed_ms": 0, "fields": ["committed", "mismatch", "notFound"], "http_status": 200, "shape": "object"}, "violations": []}, {"contract": {"committed": ["streams/imu_raw.csv.gz"], "mismatch": [], "notFound": []}, "http": {"attempts": 1, "body_bytes": 73, "body_sha256": "86b3a2401c09", "elapsed_ms": 0, "fields": ["committed", "mismatch", "notFound"], "http_status": 200, "shape": "object"}, "violations": []}], "intact_committed": true, "intact_reported_negative": false, "tampered": "synthetic/scan00.bin", "tampered_committed": false, "tampered_put_status": 200, "tampered_reported": true, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CommitResponse separates committed from mismatch/notFound; one file's bytes are flipped after its digest was registered", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:39.060Z"} +{"expected": "intact files committed; the truncated file in mismatch or notFound, or its PUT refused, and never committed", "id": "control.truncated-upload", "observed": {"batches": [{"contract": {"committed": ["synthetic/scan01.bin"], "mismatch": ["synthetic/scan00.bin"], "notFound": []}, "http": {"attempts": 1, "body_bytes": 93, "body_sha256": "7a48e8706461", "elapsed_ms": 0, "fields": ["committed", "mismatch", "notFound"], "http_status": 200, "shape": "object"}, "violations": []}, {"contract": {"committed": ["synthetic/scan02.bin", "streams/arkit_poses.csv.gz"], "mismatch": [], "notFound": []}, "http": {"attempts": 1, "body_bytes": 101, "body_sha256": "70f3ee56be56", "elapsed_ms": 0, "fields": ["committed", "mismatch", "notFound"], "http_status": 200, "shape": "object"}, "violations": []}, {"contract": {"committed": ["streams/imu_raw.csv.gz"], "mismatch": [], "notFound": []}, "http": {"attempts": 1, "body_bytes": 73, "body_sha256": "86b3a2401c09", "elapsed_ms": 0, "fields": ["committed", "mismatch", "notFound"], "http_status": 200, "shape": "object"}, "violations": []}], "intact_committed": true, "intact_reported_negative": false, "tampered": "synthetic/scan00.bin", "tampered_committed": false, "tampered_put_status": 200, "tampered_reported": true, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CommitResponse separates committed from mismatch/notFound; one file loses its last byte after its digest was registered", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:39.067Z"} +{"expected": "404 with error code capture_not_found for an id the harness invented", "id": "control.wrong-capture", "observed": {"capture": "id:1976512104be", "errors": {"codes": ["capture_not_found"]}, "http": {"attempts": 1, "body_bytes": 43, "body_sha256": "23553eb17fe9", "elapsed_ms": 0, "fields": ["errors"], "http_status": 404, "shape": "object"}}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.captureGone: an unknown capture answers 404 capture_not_found", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:39.067Z"} +{"expected": "every traced check present and PASS with the traced status class and fields, or upload and commit skipped because register reported every declared file committed", "id": "trace.expected-lifecycle-v3", "observed": {"compared": 12, "disagreements": [], "not_comparable": []}, "oracle": "frozen expected trace traces/expected-lifecycle-v3.jsonl, written from the published contract, with a no-request branch for files committed at register", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:39.069Z"} +{"expected": "after a successful restart the capture still reports its terminal status and run", "id": "control.restart-recovery", "observed": {"note": "restart-not-configured"}, "oracle": "operator restart command, then the baseline capture is read again over the published events and result routes", "status": "NOT_RUN", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:39.069Z"} +{"expected": "not run", "id": "gpu-stub.objects", "observed": {"note": "gpu-not-authorized"}, "oracle": "GPU-dependent arms are named and never executed by this harness", "status": "NOT_RUN", "transport": "GPU_STUB", "ts": "2026-10-12T11:35:39.069Z"} +{"expected": "not run", "id": "gpu-stub.vlm", "observed": {"note": "gpu-not-authorized"}, "oracle": "GPU-dependent arms are named and never executed by this harness", "status": "NOT_RUN", "transport": "GPU_STUB", "ts": "2026-10-12T11:35:39.069Z"} +{"expected": "not run", "id": "gpu-stub.dense", "observed": {"note": "gpu-not-authorized"}, "oracle": "GPU-dependent arms are named and never executed by this harness", "status": "NOT_RUN", "transport": "GPU_STUB", "ts": "2026-10-12T11:35:39.069Z"} diff --git a/tools/hunter-local-ingest/evidence/1511668/max-batch-2/max-batch-2-20261012T113539Z-d5ef95338b5c3a22/privacy-chain.jsonl b/tools/hunter-local-ingest/evidence/1511668/max-batch-2/max-batch-2-20261012T113539Z-d5ef95338b5c3a22/privacy-chain.jsonl new file mode 100644 index 000000000..d1a6ad762 --- /dev/null +++ b/tools/hunter-local-ingest/evidence/1511668/max-batch-2/max-batch-2-20261012T113539Z-d5ef95338b5c3a22/privacy-chain.jsonl @@ -0,0 +1,4 @@ +{"artifact": "run-manifest.json", "at": "2026-10-12T11:35:39.039Z", "bytes": 3464, "chain_sha256": "5596ad634433483d31ef2f73f5ba642051e127404d5aeb6be77af8972c43e65e", "sha256": "ed4f0b8e57a63a4fa4e92df273d6b26971c652e035a75b089975c47b3daf7bc7"} +{"artifact": "checks.jsonl", "at": "2026-10-12T11:35:39.069Z", "bytes": 14345, "chain_sha256": "d047a2a18f1664a8bf785420a3b09c5ba0867c1c13e8e8795ca7a3382682aeb1", "sha256": "23d4330ee3337207cd9f5fc1a1ed71a4ccde8fa7eb09c57a5c5a23366bac9ad8"} +{"artifact": "summary.json", "at": "2026-10-12T11:35:39.069Z", "bytes": 1366, "chain_sha256": "6680e5ecba165f7eca4434a9014af3585f14a11ab448757e903759579c7029d6", "sha256": "c1fee89ba1360b22e4919cde904923500a6eba330380eee3331d611ee8722aa1"} +{"artifact": "privacy-screen.json", "at": "2026-10-12T11:35:39.075Z", "bytes": 238, "chain_sha256": "2b58035eac21a2f2b9bf08a7b3c6ced0cd849e5a2035651ad40bb9fd37180e99", "sha256": "ecb6f34934d3f420c367baa92835b6375808077c704ae690c577ba124a10f8d2"} diff --git a/tools/hunter-local-ingest/evidence/1511668/max-batch-2/max-batch-2-20261012T113539Z-d5ef95338b5c3a22/privacy-screen.json b/tools/hunter-local-ingest/evidence/1511668/max-batch-2/max-batch-2-20261012T113539Z-d5ef95338b5c3a22/privacy-screen.json new file mode 100644 index 000000000..233e628d7 --- /dev/null +++ b/tools/hunter-local-ingest/evidence/1511668/max-batch-2/max-batch-2-20261012T113539Z-d5ef95338b5c3a22/privacy-screen.json @@ -0,0 +1,12 @@ +{ + "clean": true, + "findings": [], + "finished_utc": "2026-10-12T11:35:39.075Z", + "missing": [], + "schema": "hunter-local-ingest/privacy-screen/2", + "screened": [ + "run-manifest.json", + "checks.jsonl", + "summary.json" + ] +} diff --git a/tools/hunter-local-ingest/evidence/1511668/max-batch-2/max-batch-2-20261012T113539Z-d5ef95338b5c3a22/run-manifest.json b/tools/hunter-local-ingest/evidence/1511668/max-batch-2/max-batch-2-20261012T113539Z-d5ef95338b5c3a22/run-manifest.json new file mode 100644 index 000000000..94b8761b3 --- /dev/null +++ b/tools/hunter-local-ingest/evidence/1511668/max-batch-2/max-batch-2-20261012T113539Z-d5ef95338b5c3a22/run-manifest.json @@ -0,0 +1,109 @@ +{ + "backend": { + "declared_mode": "FAKE_HUNTER", + "declared_ref": null, + "verified": false + }, + "client": { + "declared_ref": null, + "git": null, + "interface": "2.0.0", + "package_version": "0.2.0", + "source_sha256": "843fd20eb408e4308664ec36453b7d887e994c92ad09b0760a897efaa6d0a6d7" + }, + "command": [ + "--endpoint", + "127.0.0.1:58308", + "--plan-file", + "", + "--out", + "", + "--label", + "max-batch-2", + "--backend-mode", + "FAKE_HUNTER", + "--poll-interval-s", + "0.05", + "--events-wait-s", + "0", + "--retry-backoff-s", + "0.0", + "--result-budget-s", + "30.0" + ], + "created_utc": "2026-10-12T11:35:39.031Z", + "endpoint": "127.0.0.1:58308", + "fixture": { + "create_sha256": "9c2dd5f33bb70b7199e85f165e87602986faa7f6b5beaee6f55db4f1f9edce97", + "files": [ + { + "bytes": 65536, + "contentType": "application/octet-stream", + "path": "synthetic/scan00.bin", + "role": "other", + "sha256": "a1ca0aa5e471b98beddf42738d706871542520398ced6f3ed81008e8c9812d85" + }, + { + "bytes": 65536, + "contentType": "application/octet-stream", + "path": "synthetic/scan01.bin", + "role": "other", + "sha256": "ef4380c88a7e0a2df7506640f6b435b153122e01070d7570870ebd2d3367d4be" + }, + { + "bytes": 65536, + "contentType": "application/octet-stream", + "path": "synthetic/scan02.bin", + "role": "other", + "sha256": "3fda1dfcabd6f77b655435c16a6c7b75d5f2f2b4ef9dccd814fede0f2b69e1f1" + }, + { + "bytes": 9793, + "contentType": "application/gzip", + "path": "streams/arkit_poses.csv.gz", + "role": "stream", + "sha256": "a23bcec6f6829c053e7bc1871999ca7b1a5e88639b5a6cde56afc655d3447388" + }, + { + "bytes": 9443, + "contentType": "application/gzip", + "path": "streams/imu_raw.csv.gz", + "role": "stream", + "sha256": "ae96d9008b71882aeb0dbc1c5463897aa9c316fbda28d5503b4676e0bd85a161" + } + ], + "format_version": 2, + "generator": "gen_synthetic_packet", + "packet_id": "synthetic-000001", + "packet_sha256": "9ab561f503ef3dc0c0e5b007157ab40c803d5b43dc38136285a72ab77acd17d1", + "plan_file_sha256": "eabf28a3f818ee22d38cec91ad6d85af6921f5cb45156378a007475368ab692f", + "plan_sha256": "50f73a67aeb28e5e0c41f40946958a2806024f75ae56dda1384025ccd0a8e4ac", + "seed": 1 + }, + "label": "max-batch-2", + "origin_note": "Derived from published client behavior in HouseScanKit upload and result sources at alpha 263827ef. No private source, schema, spec, log or credential material appears in this package or its receipts.", + "restart": { + "argv": [], + "configured": false, + "timeout_s": 120.0 + }, + "run_id": "d5ef95338b5c3a22", + "runtime": { + "cpus": 12, + "implementation": "CPython", + "machine": "arm64", + "python": "3.13.12", + "release": "25.6.0", + "system": "Darwin" + }, + "sanitization": "Every value here passed the typed export schema before it was written: published enum words, package constants, digests, bounded numbers, and the plan's own synthetic paths and packet ids. A pattern screen then ran over the written files.", + "schema": "hunter-local-ingest/run-manifest/2", + "settings": { + "events_wait_s": 0, + "max_retries": 2, + "poll_interval_s": 0.05, + "result_budget_s": 30.0, + "retry_backoff_s": 0.0, + "with_faults": false + } +} diff --git a/tools/hunter-local-ingest/evidence/1511668/max-batch-2/max-batch-2-20261012T113539Z-d5ef95338b5c3a22/summary.json b/tools/hunter-local-ingest/evidence/1511668/max-batch-2/max-batch-2-20261012T113539Z-d5ef95338b5c3a22/summary.json new file mode 100644 index 000000000..b94fc18c4 --- /dev/null +++ b/tools/hunter-local-ingest/evidence/1511668/max-batch-2/max-batch-2-20261012T113539Z-d5ef95338b5c3a22/summary.json @@ -0,0 +1,40 @@ +{ + "artifacts": { + "checks.jsonl": "23d4330ee3337207cd9f5fc1a1ed71a4ccde8fa7eb09c57a5c5a23366bac9ad8", + "run-manifest.json": "ed4f0b8e57a63a4fa4e92df273d6b26971c652e035a75b089975c47b3daf7bc7" + }, + "blocked": [], + "counts_by_transport": { + "FAKE_HUNTER": { + "NOT_RUN": 1, + "PASS": 13 + }, + "GPU_STUB": { + "NOT_RUN": 3 + } + }, + "failed": [], + "finished_utc": "2026-10-12T11:35:39.069Z", + "lead_questions": [ + "Amendment semantics: does the published contract allow amending a registered capture, and with which route and headers?", + "Local-run auth mode: which credential form does the local backend expect from the published client? The client can send a bearer token on API routes only; no CLI flag supplies one yet.", + "Clock and expiry authority: whose clock governs capture expiry on the local backend?", + "Homeowner text: confirm that receipts may carry outcome kinds and counts but never messages, prompts or reasons." + ], + "mode": { + "backend_verified": false, + "declared_backend": "FAKE_HUNTER", + "gpu_arms": "NOT_RUN", + "real_mirror_cpu": "NOT_ESTABLISHED" + }, + "not_run": [ + "control.restart-recovery", + "gpu-stub.objects", + "gpu-stub.vlm", + "gpu-stub.dense" + ], + "run_id": "d5ef95338b5c3a22", + "schema": "hunter-local-ingest/summary/2", + "total": 17, + "verdict": "PASS" +} diff --git a/tools/hunter-local-ingest/evidence/1511668/mutation-commits-tampered/mutation-20261012T113534Z-e31c3fdf39791506/checks.jsonl b/tools/hunter-local-ingest/evidence/1511668/mutation-commits-tampered/mutation-20261012T113534Z-e31c3fdf39791506/checks.jsonl new file mode 100644 index 000000000..4f40c6aaf --- /dev/null +++ b/tools/hunter-local-ingest/evidence/1511668/mutation-commits-tampered/mutation-20261012T113534Z-e31c3fdf39791506/checks.jsonl @@ -0,0 +1,29 @@ +{"expected": "an HTTP 2xx answer with status ok", "id": "lifecycle.health", "observed": {"contract": {"status": "ok"}, "http": {"attempts": 1, "body_bytes": 16, "body_sha256": "08e2c358ce13", "elapsed_ms": 0, "fields": ["status"], "http_status": 200, "shape": "object"}, "violations": []}, "oracle": "tools/integration-viewer reads GET /v1/healthz; HouseScanKit never calls it", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:34.280Z"} +{"expected": "2xx, a captureId and a published capture status", "id": "lifecycle.create", "observed": {"contract": {"captureId": "id:fd102437f369", "maxBatch": 50, "status": "uploading"}, "http": {"attempts": 1, "body_bytes": 78, "body_sha256": "8edf48cf4ce9", "elapsed_ms": 1, "fields": ["captureId", "status", "upload"], "http_status": 201, "shape": "object"}, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.create: POST captures with Idempotency-Key=packetId; the answer decodes as CaptureAPI.CreateResponse", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:34.281Z"} +{"expected": "every requested path answered exactly once, no other path, each committed or given a usable PUT target", "id": "lifecycle.register", "observed": {"batches": [{"contract": {"files": [{"path": "synthetic/scan00.bin", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "synthetic/scan01.bin", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "synthetic/scan02.bin", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "streams/arkit_poses.csv.gz", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "streams/imu_raw.csv.gz", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}]}, "http": {"attempts": 1, "body_bytes": 1253, "body_sha256": "8259e446d97e", "elapsed_ms": 0, "fields": ["files"], "http_status": 200, "shape": "object"}, "violations": []}], "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.register: the answer decodes as RegisterResponse and is applied by path; a target needs method PUT and a URL that passes uploadURLProblem", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:34.283Z"} +{"expected": "2xx for every file that got a target", "id": "lifecycle.upload", "observed": {"committed_at_register": [], "uploads": [{"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "synthetic/scan00.bin", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "synthetic/scan01.bin", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 1, "fields": [], "http_status": 200, "path": "synthetic/scan02.bin", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "streams/arkit_poses.csv.gz", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "streams/imu_raw.csv.gz", "shape": "empty"}]}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.put + ScopedCaptureHTTP.upload: exactly the signed headers, never Authorization", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:34.287Z"} +{"expected": "committed equals the uploaded set; notFound and mismatch empty; every declared path committed by register or commit", "id": "lifecycle.commit", "observed": {"batches": [{"contract": {"committed": ["synthetic/scan00.bin", "synthetic/scan01.bin", "synthetic/scan02.bin", "streams/arkit_poses.csv.gz", "streams/imu_raw.csv.gz"], "mismatch": [], "notFound": []}, "http": {"attempts": 1, "body_bytes": 175, "body_sha256": "ab0d647d58c4", "elapsed_ms": 0, "fields": ["committed", "mismatch", "notFound"], "http_status": 200, "shape": "object"}, "violations": []}], "committed_at_register": [], "committed_total": 5, "declared": 5, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.commit: only a commit acknowledges a file; CommitResponse carries committed, notFound and mismatch", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:34.288Z"} +{"expected": "2xx, a runId, a published status, no missing file", "id": "lifecycle.finalize", "observed": {"contract": {"missing": [], "runId": "id:492e113d2d27", "status": "processing"}, "http": {"attempts": 1, "body_bytes": 62, "body_sha256": "425e9d06a56d", "elapsed_ms": 0, "fields": ["missing", "runId", "status"], "http_status": 202, "shape": "object"}, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.finalize: X-Packet-Sha256 and Idempotency-Key=packetId; the answer decodes as FinalizeResponse", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:34.289Z"} +{"expected": "a terminal status within the budget, every answer contract-shaped", "id": "lifecycle.events", "observed": {"answers": 1, "finalize_retries": 0, "last": {"contract": {"events": [{"data": {"runId": "id:492e113d2d27", "runId_matches": true}, "seq": 1, "type": "verdict_ready"}], "next": 1, "status": "complete"}, "http": {"attempts": 1, "body_bytes": 145, "body_sha256": "f7919284ecb6", "elapsed_ms": 0, "fields": ["events", "next", "status"], "http_status": 200, "shape": "object"}, "violations": []}}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.pollEvents: EventsResponse until CaptureAPI.terminalStatuses; next never moves back; a verdict names this run; retry_finalize re-sends the packet", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:34.289Z"} +{"expected": "a decodable result for this run whose status matches the terminal event status", "id": "lifecycle.result", "observed": {"contract": {"criteria": null, "has_preview_url": false, "memberActions": 0, "outcome": {"kind": "eligible", "reasons": 0}, "runId": "id:492e113d2d27", "status": "complete", "viewsNeeded": 0}, "http": {"attempts": 1, "body_bytes": 227, "body_sha256": "1dc1b0ebf7a6", "elapsed_ms": 0, "fields": ["memberActions", "outcome", "runId", "status", "viewsNeeded"], "http_status": 200, "shape": "object"}, "not_ready_reads": 0, "run_matches": true, "status_matches": true, "terminal_status": "complete", "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.fetchResult: the whole body decodes as CaptureResult.Response, its runId is the finalized run, and a null outcome is final only under statusesWithoutOutcome", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:34.290Z"} +{"expected": "both creates 2xx with the same captureId", "id": "control.idempotent-create", "observed": {"first": {"contract": {"captureId": "id:b9d50067aadb", "maxBatch": 50, "status": "uploading"}, "http": {"attempts": 1, "body_bytes": 78, "body_sha256": "ec8a1ff9228b", "elapsed_ms": 0, "fields": ["captureId", "status", "upload"], "http_status": 201, "shape": "object"}, "violations": []}, "same_capture": true, "second": {"contract": {"captureId": "id:b9d50067aadb", "maxBatch": 50, "status": "uploading"}, "http": {"attempts": 1, "body_bytes": 78, "body_sha256": "ec8a1ff9228b", "elapsed_ms": 0, "fields": ["captureId", "status", "upload"], "http_status": 200, "shape": "object"}, "violations": []}}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.start: create is bound to Idempotency-Key=packetId, so a repeated create with the same bytes names the same capture", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:34.292Z"} +{"expected": "intact files committed; the flipped file in mismatch or notFound, or its PUT refused, and never committed", "id": "control.corrupt-upload", "observed": {"batches": [{"contract": {"committed": ["synthetic/scan00.bin", "synthetic/scan01.bin", "synthetic/scan02.bin", "streams/arkit_poses.csv.gz", "streams/imu_raw.csv.gz"], "mismatch": [], "notFound": []}, "http": {"attempts": 1, "body_bytes": 175, "body_sha256": "ab0d647d58c4", "elapsed_ms": 0, "fields": ["committed", "mismatch", "notFound"], "http_status": 200, "shape": "object"}, "violations": []}], "intact_committed": true, "intact_reported_negative": false, "tampered": "synthetic/scan00.bin", "tampered_committed": true, "tampered_put_status": 200, "tampered_reported": false, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CommitResponse separates committed from mismatch/notFound; one file's bytes are flipped after its digest was registered", "status": "FAIL", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:34.296Z"} +{"expected": "intact files committed; the truncated file in mismatch or notFound, or its PUT refused, and never committed", "id": "control.truncated-upload", "observed": {"batches": [{"contract": {"committed": ["synthetic/scan00.bin", "synthetic/scan01.bin", "synthetic/scan02.bin", "streams/arkit_poses.csv.gz", "streams/imu_raw.csv.gz"], "mismatch": [], "notFound": []}, "http": {"attempts": 1, "body_bytes": 175, "body_sha256": "ab0d647d58c4", "elapsed_ms": 0, "fields": ["committed", "mismatch", "notFound"], "http_status": 200, "shape": "object"}, "violations": []}], "intact_committed": true, "intact_reported_negative": false, "tampered": "synthetic/scan00.bin", "tampered_committed": true, "tampered_put_status": 200, "tampered_reported": false, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CommitResponse separates committed from mismatch/notFound; one file loses its last byte after its digest was registered", "status": "FAIL", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:34.301Z"} +{"expected": "404 with error code capture_not_found for an id the harness invented", "id": "control.wrong-capture", "observed": {"capture": "id:1976512104be", "errors": {"codes": ["capture_not_found"]}, "http": {"attempts": 1, "body_bytes": 43, "body_sha256": "23553eb17fe9", "elapsed_ms": 0, "fields": ["errors"], "http_status": 404, "shape": "object"}}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.captureGone: an unknown capture answers 404 capture_not_found", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:34.301Z"} +{"expected": "an HTTP 2xx answer with status ok", "id": "fault.lifecycle.health", "observed": {"contract": {"status": "ok"}, "http": {"attempts": 1, "body_bytes": 16, "body_sha256": "08e2c358ce13", "elapsed_ms": 0, "fields": ["status"], "http_status": 200, "shape": "object"}, "violations": []}, "oracle": "tools/integration-viewer reads GET /v1/healthz; HouseScanKit never calls it", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:34.304Z"} +{"expected": "2xx, a captureId and a published capture status", "id": "fault.lifecycle.create", "observed": {"contract": {"captureId": "id:d6611115894b", "maxBatch": 50, "status": "uploading"}, "http": {"attempts": 1, "body_bytes": 78, "body_sha256": "1ff5bb037620", "elapsed_ms": 109, "fields": ["captureId", "status", "upload"], "http_status": 201, "shape": "object"}, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.create: POST captures with Idempotency-Key=packetId; the answer decodes as CaptureAPI.CreateResponse", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:34.413Z"} +{"expected": "every requested path answered exactly once, no other path, each committed or given a usable PUT target", "id": "fault.lifecycle.register", "observed": {"batches": [{"contract": {"files": [{"path": "synthetic/scan00.bin", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "synthetic/scan01.bin", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "synthetic/scan02.bin", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "streams/arkit_poses.csv.gz", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "streams/imu_raw.csv.gz", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}]}, "http": {"attempts": 1, "body_bytes": 1253, "body_sha256": "3499d6f20717", "elapsed_ms": 1, "fields": ["files"], "http_status": 200, "shape": "object"}, "violations": []}], "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.register: the answer decodes as RegisterResponse and is applied by path; a target needs method PUT and a URL that passes uploadURLProblem", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:34.415Z"} +{"expected": "2xx for every file that got a target", "id": "fault.lifecycle.upload", "observed": {"committed_at_register": [], "uploads": [{"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "synthetic/scan00.bin", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "synthetic/scan01.bin", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "synthetic/scan02.bin", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "streams/arkit_poses.csv.gz", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "streams/imu_raw.csv.gz", "shape": "empty"}]}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.put + ScopedCaptureHTTP.upload: exactly the signed headers, never Authorization", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:34.418Z"} +{"expected": "committed equals the uploaded set; notFound and mismatch empty; every declared path committed by register or commit", "id": "fault.lifecycle.commit", "observed": {"batches": [{"contract": {"committed": ["synthetic/scan00.bin", "synthetic/scan01.bin", "synthetic/scan02.bin", "streams/arkit_poses.csv.gz", "streams/imu_raw.csv.gz"], "mismatch": [], "notFound": []}, "http": {"attempts": 1, "body_bytes": 175, "body_sha256": "ab0d647d58c4", "elapsed_ms": 0, "fields": ["committed", "mismatch", "notFound"], "http_status": 200, "shape": "object"}, "violations": []}], "committed_at_register": [], "committed_total": 5, "declared": 5, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.commit: only a commit acknowledges a file; CommitResponse carries committed, notFound and mismatch", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:34.419Z"} +{"expected": "2xx, a runId, a published status, no missing file", "id": "fault.lifecycle.finalize", "observed": {"contract": {"missing": [], "runId": "id:636f557a124e", "status": "processing"}, "http": {"attempts": 1, "body_bytes": 62, "body_sha256": "cc5e4603e9bd", "elapsed_ms": 0, "fields": ["missing", "runId", "status"], "http_status": 202, "shape": "object"}, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.finalize: X-Packet-Sha256 and Idempotency-Key=packetId; the answer decodes as FinalizeResponse", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:34.420Z"} +{"expected": "a terminal status within the budget, every answer contract-shaped", "id": "fault.lifecycle.events", "observed": {"answers": 1, "finalize_retries": 0, "last": {"contract": {"events": [{"data": {"runId": "id:636f557a124e", "runId_matches": true}, "seq": 1, "type": "verdict_ready"}], "next": 1, "status": "complete"}, "http": {"attempts": 1, "body_bytes": 145, "body_sha256": "6519430bc83d", "elapsed_ms": 0, "fields": ["events", "next", "status"], "http_status": 200, "shape": "object"}, "violations": []}}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.pollEvents: EventsResponse until CaptureAPI.terminalStatuses; next never moves back; a verdict names this run; retry_finalize re-sends the packet", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:34.421Z"} +{"expected": "a decodable result for this run whose status matches the terminal event status", "id": "fault.lifecycle.result", "observed": {"contract": {"criteria": null, "has_preview_url": false, "memberActions": 0, "outcome": {"kind": "eligible", "reasons": 0}, "runId": "id:636f557a124e", "status": "complete", "viewsNeeded": 0}, "http": {"attempts": 1, "body_bytes": 227, "body_sha256": "f0543371247b", "elapsed_ms": 0, "fields": ["memberActions", "outcome", "runId", "status", "viewsNeeded"], "http_status": 200, "shape": "object"}, "not_ready_reads": 0, "run_matches": true, "status_matches": true, "terminal_status": "complete", "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.fetchResult: the whole body decodes as CaptureResult.Response, its runId is the finalized run, and a null outcome is final only under statusesWithoutOutcome", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:34.422Z"} +{"expected": "the proxy's single 503 is followed by a second attempt that creates the capture", "id": "fault.retry-transient", "observed": {"contract": {"captureId": "id:40a0732506ed", "maxBatch": 50, "status": "uploading"}, "http": {"attempts": 2, "body_bytes": 78, "body_sha256": "2350cd7a9fb2", "elapsed_ms": 2, "fields": ["captureId", "status", "upload"], "http_status": 201, "shape": "object"}, "proxy_hits": 2, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.isTransient: a 503 is retried with the same body", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:35.430Z"} +{"expected": "exactly one attempt and a reported non-2xx answer", "id": "fault.no-retry-501", "observed": {"errors": {"codes": ["harness_fault"]}, "http": {"attempts": 1, "body_bytes": 39, "body_sha256": "be37db4e697d", "elapsed_ms": 0, "fields": ["errors"], "http_status": 501, "shape": "object"}, "proxy_hits": 1}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.isTransient excludes 501", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:35.934Z"} +{"expected": "a transport error category after 1 + max_retries attempts, no capture id taken", "id": "fault.abort", "observed": {"http": {"attempts": 2, "error": "transport:remote-disconnected"}, "proxy_hits": 2}, "oracle": "an answer-less connection is a transport failure, retried a bounded number of times", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:36.439Z"} +{"expected": "a transport error category, no capture id taken", "id": "fault.truncated-response", "observed": {"http": {"attempts": 1, "error": "transport:incomplete-read"}, "proxy_hits": 1}, "oracle": "a body shorter than its Content-Length is a transport failure, never a parsed answer", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:36.943Z"} +{"expected": "every traced check present and PASS with the traced status class and fields, or upload and commit skipped because register reported every declared file committed", "id": "trace.expected-lifecycle-v3", "observed": {"compared": 12, "disagreements": [{"id": "control.corrupt-upload", "kind": "status-fail"}, {"id": "control.truncated-upload", "kind": "status-fail"}], "not_comparable": []}, "oracle": "frozen expected trace traces/expected-lifecycle-v3.jsonl, written from the published contract, with a no-request branch for files committed at register", "status": "FAIL", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:36.946Z"} +{"expected": "after a successful restart the capture still reports its terminal status and run", "id": "control.restart-recovery", "observed": {"note": "restart-not-configured"}, "oracle": "operator restart command, then the baseline capture is read again over the published events and result routes", "status": "NOT_RUN", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:36.946Z"} +{"expected": "not run", "id": "gpu-stub.objects", "observed": {"note": "gpu-not-authorized"}, "oracle": "GPU-dependent arms are named and never executed by this harness", "status": "NOT_RUN", "transport": "GPU_STUB", "ts": "2026-10-12T11:35:36.946Z"} +{"expected": "not run", "id": "gpu-stub.vlm", "observed": {"note": "gpu-not-authorized"}, "oracle": "GPU-dependent arms are named and never executed by this harness", "status": "NOT_RUN", "transport": "GPU_STUB", "ts": "2026-10-12T11:35:36.946Z"} +{"expected": "not run", "id": "gpu-stub.dense", "observed": {"note": "gpu-not-authorized"}, "oracle": "GPU-dependent arms are named and never executed by this harness", "status": "NOT_RUN", "transport": "GPU_STUB", "ts": "2026-10-12T11:35:36.946Z"} diff --git a/tools/hunter-local-ingest/evidence/1511668/mutation-commits-tampered/mutation-20261012T113534Z-e31c3fdf39791506/privacy-chain.jsonl b/tools/hunter-local-ingest/evidence/1511668/mutation-commits-tampered/mutation-20261012T113534Z-e31c3fdf39791506/privacy-chain.jsonl new file mode 100644 index 000000000..799a79e7c --- /dev/null +++ b/tools/hunter-local-ingest/evidence/1511668/mutation-commits-tampered/mutation-20261012T113534Z-e31c3fdf39791506/privacy-chain.jsonl @@ -0,0 +1,4 @@ +{"artifact": "run-manifest.json", "at": "2026-10-12T11:35:34.277Z", "bytes": 3478, "chain_sha256": "f0f5fd9b4cb4f2b1ddc6acb1156cfd9c1b4156906a7415a98ff4c47de48cd517", "sha256": "de02f749138caa6f2498f6ef6ac4d69b3975e14f6db8e486aa8a4017216099b1"} +{"artifact": "checks.jsonl", "at": "2026-10-12T11:35:36.947Z", "bytes": 21616, "chain_sha256": "176d63715f2b5732a16455d8727293bc09ae9a83036173c9963ca11c2e079f52", "sha256": "e4e51f47d421915d07f81a240a187b0ff2f9eb978de64014f0a9b04ff93d5597"} +{"artifact": "summary.json", "at": "2026-10-12T11:35:36.947Z", "bytes": 1482, "chain_sha256": "b355e966f3ac2baaff51e8f7dc98e921bd3d3e3e9f41446cb6c01d9d3209059d", "sha256": "fb1a5072dba5eef74fd9f418bf7cf49e6e05ceb09e3d705ec1c10288851cfd68"} +{"artifact": "privacy-screen.json", "at": "2026-10-12T11:35:36.960Z", "bytes": 238, "chain_sha256": "53f2ebf77525f3c6863afa09456ee5ef6450dde8c0dabaa1a18165f8941653e6", "sha256": "0d325f47d2ce67341c707f02e28314dd4287d125550da6baf480ca49465a00c6"} diff --git a/tools/hunter-local-ingest/evidence/1511668/mutation-commits-tampered/mutation-20261012T113534Z-e31c3fdf39791506/privacy-screen.json b/tools/hunter-local-ingest/evidence/1511668/mutation-commits-tampered/mutation-20261012T113534Z-e31c3fdf39791506/privacy-screen.json new file mode 100644 index 000000000..98f538adc --- /dev/null +++ b/tools/hunter-local-ingest/evidence/1511668/mutation-commits-tampered/mutation-20261012T113534Z-e31c3fdf39791506/privacy-screen.json @@ -0,0 +1,12 @@ +{ + "clean": true, + "findings": [], + "finished_utc": "2026-10-12T11:35:36.960Z", + "missing": [], + "schema": "hunter-local-ingest/privacy-screen/2", + "screened": [ + "run-manifest.json", + "checks.jsonl", + "summary.json" + ] +} diff --git a/tools/hunter-local-ingest/evidence/1511668/mutation-commits-tampered/mutation-20261012T113534Z-e31c3fdf39791506/run-manifest.json b/tools/hunter-local-ingest/evidence/1511668/mutation-commits-tampered/mutation-20261012T113534Z-e31c3fdf39791506/run-manifest.json new file mode 100644 index 000000000..a0cbd9699 --- /dev/null +++ b/tools/hunter-local-ingest/evidence/1511668/mutation-commits-tampered/mutation-20261012T113534Z-e31c3fdf39791506/run-manifest.json @@ -0,0 +1,110 @@ +{ + "backend": { + "declared_mode": "FAKE_HUNTER", + "declared_ref": null, + "verified": false + }, + "client": { + "declared_ref": null, + "git": null, + "interface": "2.0.0", + "package_version": "0.2.0", + "source_sha256": "843fd20eb408e4308664ec36453b7d887e994c92ad09b0760a897efaa6d0a6d7" + }, + "command": [ + "--endpoint", + "127.0.0.1:58147", + "--plan-file", + "", + "--out", + "", + "--label", + "mutation", + "--backend-mode", + "FAKE_HUNTER", + "--with-faults", + "--poll-interval-s", + "0.05", + "--events-wait-s", + "0", + "--retry-backoff-s", + "0.0", + "--result-budget-s", + "30.0" + ], + "created_utc": "2026-10-12T11:35:34.269Z", + "endpoint": "127.0.0.1:58147", + "fixture": { + "create_sha256": "9c2dd5f33bb70b7199e85f165e87602986faa7f6b5beaee6f55db4f1f9edce97", + "files": [ + { + "bytes": 65536, + "contentType": "application/octet-stream", + "path": "synthetic/scan00.bin", + "role": "other", + "sha256": "a1ca0aa5e471b98beddf42738d706871542520398ced6f3ed81008e8c9812d85" + }, + { + "bytes": 65536, + "contentType": "application/octet-stream", + "path": "synthetic/scan01.bin", + "role": "other", + "sha256": "ef4380c88a7e0a2df7506640f6b435b153122e01070d7570870ebd2d3367d4be" + }, + { + "bytes": 65536, + "contentType": "application/octet-stream", + "path": "synthetic/scan02.bin", + "role": "other", + "sha256": "3fda1dfcabd6f77b655435c16a6c7b75d5f2f2b4ef9dccd814fede0f2b69e1f1" + }, + { + "bytes": 9793, + "contentType": "application/gzip", + "path": "streams/arkit_poses.csv.gz", + "role": "stream", + "sha256": "a23bcec6f6829c053e7bc1871999ca7b1a5e88639b5a6cde56afc655d3447388" + }, + { + "bytes": 9443, + "contentType": "application/gzip", + "path": "streams/imu_raw.csv.gz", + "role": "stream", + "sha256": "ae96d9008b71882aeb0dbc1c5463897aa9c316fbda28d5503b4676e0bd85a161" + } + ], + "format_version": 2, + "generator": "gen_synthetic_packet", + "packet_id": "synthetic-000001", + "packet_sha256": "9ab561f503ef3dc0c0e5b007157ab40c803d5b43dc38136285a72ab77acd17d1", + "plan_file_sha256": "eabf28a3f818ee22d38cec91ad6d85af6921f5cb45156378a007475368ab692f", + "plan_sha256": "50f73a67aeb28e5e0c41f40946958a2806024f75ae56dda1384025ccd0a8e4ac", + "seed": 1 + }, + "label": "mutation", + "origin_note": "Derived from published client behavior in HouseScanKit upload and result sources at alpha 263827ef. No private source, schema, spec, log or credential material appears in this package or its receipts.", + "restart": { + "argv": [], + "configured": false, + "timeout_s": 120.0 + }, + "run_id": "e31c3fdf39791506", + "runtime": { + "cpus": 12, + "implementation": "CPython", + "machine": "arm64", + "python": "3.13.12", + "release": "25.6.0", + "system": "Darwin" + }, + "sanitization": "Every value here passed the typed export schema before it was written: published enum words, package constants, digests, bounded numbers, and the plan's own synthetic paths and packet ids. A pattern screen then ran over the written files.", + "schema": "hunter-local-ingest/run-manifest/2", + "settings": { + "events_wait_s": 0, + "max_retries": 2, + "poll_interval_s": 0.05, + "result_budget_s": 30.0, + "retry_backoff_s": 0.0, + "with_faults": true + } +} diff --git a/tools/hunter-local-ingest/evidence/1511668/mutation-commits-tampered/mutation-20261012T113534Z-e31c3fdf39791506/summary.json b/tools/hunter-local-ingest/evidence/1511668/mutation-commits-tampered/mutation-20261012T113534Z-e31c3fdf39791506/summary.json new file mode 100644 index 000000000..d35778cc1 --- /dev/null +++ b/tools/hunter-local-ingest/evidence/1511668/mutation-commits-tampered/mutation-20261012T113534Z-e31c3fdf39791506/summary.json @@ -0,0 +1,45 @@ +{ + "artifacts": { + "checks.jsonl": "e4e51f47d421915d07f81a240a187b0ff2f9eb978de64014f0a9b04ff93d5597", + "run-manifest.json": "de02f749138caa6f2498f6ef6ac4d69b3975e14f6db8e486aa8a4017216099b1" + }, + "blocked": [], + "counts_by_transport": { + "FAKE_HUNTER": { + "FAIL": 3, + "NOT_RUN": 1, + "PASS": 22 + }, + "GPU_STUB": { + "NOT_RUN": 3 + } + }, + "failed": [ + "control.corrupt-upload", + "control.truncated-upload", + "trace.expected-lifecycle-v3" + ], + "finished_utc": "2026-10-12T11:35:36.947Z", + "lead_questions": [ + "Amendment semantics: does the published contract allow amending a registered capture, and with which route and headers?", + "Local-run auth mode: which credential form does the local backend expect from the published client? The client can send a bearer token on API routes only; no CLI flag supplies one yet.", + "Clock and expiry authority: whose clock governs capture expiry on the local backend?", + "Homeowner text: confirm that receipts may carry outcome kinds and counts but never messages, prompts or reasons." + ], + "mode": { + "backend_verified": false, + "declared_backend": "FAKE_HUNTER", + "gpu_arms": "NOT_RUN", + "real_mirror_cpu": "NOT_ESTABLISHED" + }, + "not_run": [ + "control.restart-recovery", + "gpu-stub.objects", + "gpu-stub.vlm", + "gpu-stub.dense" + ], + "run_id": "e31c3fdf39791506", + "schema": "hunter-local-ingest/summary/2", + "total": 29, + "verdict": "FAIL" +} diff --git a/tools/hunter-local-ingest/evidence/1511668/real-api-unreachable/real-api-unreachable-20261012T113524Z-f445c56d6cd5b3d3/checks.jsonl b/tools/hunter-local-ingest/evidence/1511668/real-api-unreachable/real-api-unreachable-20261012T113524Z-f445c56d6cd5b3d3/checks.jsonl new file mode 100644 index 000000000..624516d81 --- /dev/null +++ b/tools/hunter-local-ingest/evidence/1511668/real-api-unreachable/real-api-unreachable-20261012T113524Z-f445c56d6cd5b3d3/checks.jsonl @@ -0,0 +1,17 @@ +{"expected": "an HTTP 2xx answer with status ok", "id": "lifecycle.health", "observed": {"note": "endpoint-unreachable"}, "oracle": "tools/integration-viewer reads GET /v1/healthz; HouseScanKit never calls it", "status": "BLOCKED", "transport": "REAL_API", "ts": "2026-10-12T11:35:34.124Z"} +{"expected": "2xx, a captureId and a published capture status", "id": "lifecycle.create", "observed": {"note": "endpoint-unreachable"}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.create: POST captures with Idempotency-Key=packetId; the answer decodes as CaptureAPI.CreateResponse", "status": "BLOCKED", "transport": "REAL_API", "ts": "2026-10-12T11:35:34.124Z"} +{"expected": "every requested path answered exactly once, no other path, each committed or given a usable PUT target", "id": "lifecycle.register", "observed": {"note": "endpoint-unreachable"}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.register: the answer decodes as RegisterResponse and is applied by path; a target needs method PUT and a URL that passes uploadURLProblem", "status": "BLOCKED", "transport": "REAL_API", "ts": "2026-10-12T11:35:34.124Z"} +{"expected": "2xx for every file that got a target", "id": "lifecycle.upload", "observed": {"note": "endpoint-unreachable"}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.put + ScopedCaptureHTTP.upload: exactly the signed headers, never Authorization", "status": "BLOCKED", "transport": "REAL_API", "ts": "2026-10-12T11:35:34.124Z"} +{"expected": "committed equals the uploaded set; notFound and mismatch empty; every declared path committed by register or commit", "id": "lifecycle.commit", "observed": {"note": "endpoint-unreachable"}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.commit: only a commit acknowledges a file; CommitResponse carries committed, notFound and mismatch", "status": "BLOCKED", "transport": "REAL_API", "ts": "2026-10-12T11:35:34.124Z"} +{"expected": "2xx, a runId, a published status, no missing file", "id": "lifecycle.finalize", "observed": {"note": "endpoint-unreachable"}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.finalize: X-Packet-Sha256 and Idempotency-Key=packetId; the answer decodes as FinalizeResponse", "status": "BLOCKED", "transport": "REAL_API", "ts": "2026-10-12T11:35:34.124Z"} +{"expected": "a terminal status within the budget, every answer contract-shaped", "id": "lifecycle.events", "observed": {"note": "endpoint-unreachable"}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.pollEvents: EventsResponse until CaptureAPI.terminalStatuses; next never moves back; a verdict names this run; retry_finalize re-sends the packet", "status": "BLOCKED", "transport": "REAL_API", "ts": "2026-10-12T11:35:34.124Z"} +{"expected": "a decodable result for this run whose status matches the terminal event status", "id": "lifecycle.result", "observed": {"note": "endpoint-unreachable"}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.fetchResult: the whole body decodes as CaptureResult.Response, its runId is the finalized run, and a null outcome is final only under statusesWithoutOutcome", "status": "BLOCKED", "transport": "REAL_API", "ts": "2026-10-12T11:35:34.124Z"} +{"expected": "both creates 2xx with the same captureId", "id": "control.idempotent-create", "observed": {"note": "endpoint-unreachable"}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.start: create is bound to Idempotency-Key=packetId, so a repeated create with the same bytes names the same capture", "status": "BLOCKED", "transport": "REAL_API", "ts": "2026-10-12T11:35:34.124Z"} +{"expected": "intact files committed; the flipped file in mismatch or notFound, or its PUT refused, and never committed", "id": "control.corrupt-upload", "observed": {"note": "endpoint-unreachable"}, "oracle": "HouseScanKit @ alpha 263827ef CommitResponse separates committed from mismatch/notFound; one file's bytes are flipped after its digest was registered", "status": "BLOCKED", "transport": "REAL_API", "ts": "2026-10-12T11:35:34.124Z"} +{"expected": "intact files committed; the truncated file in mismatch or notFound, or its PUT refused, and never committed", "id": "control.truncated-upload", "observed": {"note": "endpoint-unreachable"}, "oracle": "HouseScanKit @ alpha 263827ef CommitResponse separates committed from mismatch/notFound; one file loses its last byte after its digest was registered", "status": "BLOCKED", "transport": "REAL_API", "ts": "2026-10-12T11:35:34.124Z"} +{"expected": "404 with error code capture_not_found for an id the harness invented", "id": "control.wrong-capture", "observed": {"note": "endpoint-unreachable"}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.captureGone: an unknown capture answers 404 capture_not_found", "status": "BLOCKED", "transport": "REAL_API", "ts": "2026-10-12T11:35:34.124Z"} +{"expected": "every traced check present and PASS with the traced status class and fields, or upload and commit skipped because register reported every declared file committed", "id": "trace.expected-lifecycle-v3", "observed": {"compared": 0, "disagreements": [], "not_comparable": [{"id": "lifecycle.health", "status": "BLOCKED"}, {"id": "lifecycle.create", "status": "BLOCKED"}, {"id": "lifecycle.register", "status": "BLOCKED"}, {"id": "lifecycle.upload", "status": "BLOCKED"}, {"id": "lifecycle.commit", "status": "BLOCKED"}, {"id": "lifecycle.finalize", "status": "BLOCKED"}, {"id": "lifecycle.events", "status": "BLOCKED"}, {"id": "lifecycle.result", "status": "BLOCKED"}, {"id": "control.idempotent-create", "status": "BLOCKED"}, {"id": "control.corrupt-upload", "status": "BLOCKED"}, {"id": "control.truncated-upload", "status": "BLOCKED"}, {"id": "control.wrong-capture", "status": "BLOCKED"}]}, "oracle": "frozen expected trace traces/expected-lifecycle-v3.jsonl, written from the published contract, with a no-request branch for files committed at register", "status": "BLOCKED", "transport": "REAL_API", "ts": "2026-10-12T11:35:34.127Z"} +{"expected": "after a successful restart the capture still reports its terminal status and run", "id": "control.restart-recovery", "observed": {"note": "restart-not-configured"}, "oracle": "operator restart command, then the baseline capture is read again over the published events and result routes", "status": "NOT_RUN", "transport": "REAL_API", "ts": "2026-10-12T11:35:34.127Z"} +{"expected": "not run", "id": "gpu-stub.objects", "observed": {"note": "gpu-not-authorized"}, "oracle": "GPU-dependent arms are named and never executed by this harness", "status": "NOT_RUN", "transport": "GPU_STUB", "ts": "2026-10-12T11:35:34.127Z"} +{"expected": "not run", "id": "gpu-stub.vlm", "observed": {"note": "gpu-not-authorized"}, "oracle": "GPU-dependent arms are named and never executed by this harness", "status": "NOT_RUN", "transport": "GPU_STUB", "ts": "2026-10-12T11:35:34.127Z"} +{"expected": "not run", "id": "gpu-stub.dense", "observed": {"note": "gpu-not-authorized"}, "oracle": "GPU-dependent arms are named and never executed by this harness", "status": "NOT_RUN", "transport": "GPU_STUB", "ts": "2026-10-12T11:35:34.127Z"} diff --git a/tools/hunter-local-ingest/evidence/1511668/real-api-unreachable/real-api-unreachable-20261012T113524Z-f445c56d6cd5b3d3/privacy-chain.jsonl b/tools/hunter-local-ingest/evidence/1511668/real-api-unreachable/real-api-unreachable-20261012T113524Z-f445c56d6cd5b3d3/privacy-chain.jsonl new file mode 100644 index 000000000..ff8ebe7ad --- /dev/null +++ b/tools/hunter-local-ingest/evidence/1511668/real-api-unreachable/real-api-unreachable-20261012T113524Z-f445c56d6cd5b3d3/privacy-chain.jsonl @@ -0,0 +1,4 @@ +{"artifact": "run-manifest.json", "at": "2026-10-12T11:35:24.029Z", "bytes": 3476, "chain_sha256": "596014f9456fa32b4345305701f788518ba4cb211cfd2704d4f6edc8933cc119", "sha256": "f544a0a13099914cd04484060517be26e42146cc17c4f41060a4ebcaaf7d2076"} +{"artifact": "checks.jsonl", "at": "2026-10-12T11:35:34.127Z", "bytes": 7124, "chain_sha256": "7dd86fcad3433c2e4e00b41ae664d155b59184642833faa2542f087899d85aae", "sha256": "20be67f9da841af7ec192a43b9f5f8d66d222da374033398dc5ef0e9b81a5b64"} +{"artifact": "summary.json", "at": "2026-10-12T11:35:34.127Z", "bytes": 1723, "chain_sha256": "b7f11d6747c2991fda749a3c8330464865d5d82cc7f602161af793d894fef66f", "sha256": "525c695fbeb0f8d28323f389891c926957a8defbf6482557cd7455f8a32c9129"} +{"artifact": "privacy-screen.json", "at": "2026-10-12T11:35:34.131Z", "bytes": 238, "chain_sha256": "3d08a4f54ce935f118171ede03a102c8810f4c6c4fe75a74bda60386ebb3db94", "sha256": "dee763035de69a36eadab8be18bacc9a4a5f73be7a64793975a08a25c91a0839"} diff --git a/tools/hunter-local-ingest/evidence/1511668/real-api-unreachable/real-api-unreachable-20261012T113524Z-f445c56d6cd5b3d3/privacy-screen.json b/tools/hunter-local-ingest/evidence/1511668/real-api-unreachable/real-api-unreachable-20261012T113524Z-f445c56d6cd5b3d3/privacy-screen.json new file mode 100644 index 000000000..d29f3f050 --- /dev/null +++ b/tools/hunter-local-ingest/evidence/1511668/real-api-unreachable/real-api-unreachable-20261012T113524Z-f445c56d6cd5b3d3/privacy-screen.json @@ -0,0 +1,12 @@ +{ + "clean": true, + "findings": [], + "finished_utc": "2026-10-12T11:35:34.131Z", + "missing": [], + "schema": "hunter-local-ingest/privacy-screen/2", + "screened": [ + "run-manifest.json", + "checks.jsonl", + "summary.json" + ] +} diff --git a/tools/hunter-local-ingest/evidence/1511668/real-api-unreachable/real-api-unreachable-20261012T113524Z-f445c56d6cd5b3d3/run-manifest.json b/tools/hunter-local-ingest/evidence/1511668/real-api-unreachable/real-api-unreachable-20261012T113524Z-f445c56d6cd5b3d3/run-manifest.json new file mode 100644 index 000000000..9c973a531 --- /dev/null +++ b/tools/hunter-local-ingest/evidence/1511668/real-api-unreachable/real-api-unreachable-20261012T113524Z-f445c56d6cd5b3d3/run-manifest.json @@ -0,0 +1,109 @@ +{ + "backend": { + "declared_mode": "REAL_API", + "declared_ref": null, + "verified": false + }, + "client": { + "declared_ref": null, + "git": null, + "interface": "2.0.0", + "package_version": "0.2.0", + "source_sha256": "843fd20eb408e4308664ec36453b7d887e994c92ad09b0760a897efaa6d0a6d7" + }, + "command": [ + "--endpoint", + "127.0.0.1:58040", + "--plan-file", + "", + "--out", + "", + "--label", + "real-api-unreachable", + "--backend-mode", + "REAL_API", + "--poll-interval-s", + "0.05", + "--events-wait-s", + "0", + "--retry-backoff-s", + "0.0", + "--result-budget-s", + "30.0" + ], + "created_utc": "2026-10-12T11:35:24.020Z", + "endpoint": "127.0.0.1:58040", + "fixture": { + "create_sha256": "9c2dd5f33bb70b7199e85f165e87602986faa7f6b5beaee6f55db4f1f9edce97", + "files": [ + { + "bytes": 65536, + "contentType": "application/octet-stream", + "path": "synthetic/scan00.bin", + "role": "other", + "sha256": "a1ca0aa5e471b98beddf42738d706871542520398ced6f3ed81008e8c9812d85" + }, + { + "bytes": 65536, + "contentType": "application/octet-stream", + "path": "synthetic/scan01.bin", + "role": "other", + "sha256": "ef4380c88a7e0a2df7506640f6b435b153122e01070d7570870ebd2d3367d4be" + }, + { + "bytes": 65536, + "contentType": "application/octet-stream", + "path": "synthetic/scan02.bin", + "role": "other", + "sha256": "3fda1dfcabd6f77b655435c16a6c7b75d5f2f2b4ef9dccd814fede0f2b69e1f1" + }, + { + "bytes": 9793, + "contentType": "application/gzip", + "path": "streams/arkit_poses.csv.gz", + "role": "stream", + "sha256": "a23bcec6f6829c053e7bc1871999ca7b1a5e88639b5a6cde56afc655d3447388" + }, + { + "bytes": 9443, + "contentType": "application/gzip", + "path": "streams/imu_raw.csv.gz", + "role": "stream", + "sha256": "ae96d9008b71882aeb0dbc1c5463897aa9c316fbda28d5503b4676e0bd85a161" + } + ], + "format_version": 2, + "generator": "gen_synthetic_packet", + "packet_id": "synthetic-000001", + "packet_sha256": "9ab561f503ef3dc0c0e5b007157ab40c803d5b43dc38136285a72ab77acd17d1", + "plan_file_sha256": "eabf28a3f818ee22d38cec91ad6d85af6921f5cb45156378a007475368ab692f", + "plan_sha256": "50f73a67aeb28e5e0c41f40946958a2806024f75ae56dda1384025ccd0a8e4ac", + "seed": 1 + }, + "label": "real-api-unreachable", + "origin_note": "Derived from published client behavior in HouseScanKit upload and result sources at alpha 263827ef. No private source, schema, spec, log or credential material appears in this package or its receipts.", + "restart": { + "argv": [], + "configured": false, + "timeout_s": 120.0 + }, + "run_id": "f445c56d6cd5b3d3", + "runtime": { + "cpus": 12, + "implementation": "CPython", + "machine": "arm64", + "python": "3.13.12", + "release": "25.6.0", + "system": "Darwin" + }, + "sanitization": "Every value here passed the typed export schema before it was written: published enum words, package constants, digests, bounded numbers, and the plan's own synthetic paths and packet ids. A pattern screen then ran over the written files.", + "schema": "hunter-local-ingest/run-manifest/2", + "settings": { + "events_wait_s": 0, + "max_retries": 2, + "poll_interval_s": 0.05, + "result_budget_s": 30.0, + "retry_backoff_s": 0.0, + "with_faults": false + } +} diff --git a/tools/hunter-local-ingest/evidence/1511668/real-api-unreachable/real-api-unreachable-20261012T113524Z-f445c56d6cd5b3d3/summary.json b/tools/hunter-local-ingest/evidence/1511668/real-api-unreachable/real-api-unreachable-20261012T113524Z-f445c56d6cd5b3d3/summary.json new file mode 100644 index 000000000..e07b42fbf --- /dev/null +++ b/tools/hunter-local-ingest/evidence/1511668/real-api-unreachable/real-api-unreachable-20261012T113524Z-f445c56d6cd5b3d3/summary.json @@ -0,0 +1,54 @@ +{ + "artifacts": { + "checks.jsonl": "20be67f9da841af7ec192a43b9f5f8d66d222da374033398dc5ef0e9b81a5b64", + "run-manifest.json": "f544a0a13099914cd04484060517be26e42146cc17c4f41060a4ebcaaf7d2076" + }, + "blocked": [ + "lifecycle.health", + "lifecycle.create", + "lifecycle.register", + "lifecycle.upload", + "lifecycle.commit", + "lifecycle.finalize", + "lifecycle.events", + "lifecycle.result", + "control.idempotent-create", + "control.corrupt-upload", + "control.truncated-upload", + "control.wrong-capture", + "trace.expected-lifecycle-v3" + ], + "counts_by_transport": { + "GPU_STUB": { + "NOT_RUN": 3 + }, + "REAL_API": { + "BLOCKED": 13, + "NOT_RUN": 1 + } + }, + "failed": [], + "finished_utc": "2026-10-12T11:35:34.127Z", + "lead_questions": [ + "Amendment semantics: does the published contract allow amending a registered capture, and with which route and headers?", + "Local-run auth mode: which credential form does the local backend expect from the published client? The client can send a bearer token on API routes only; no CLI flag supplies one yet.", + "Clock and expiry authority: whose clock governs capture expiry on the local backend?", + "Homeowner text: confirm that receipts may carry outcome kinds and counts but never messages, prompts or reasons." + ], + "mode": { + "backend_verified": false, + "declared_backend": "REAL_API", + "gpu_arms": "NOT_RUN", + "real_mirror_cpu": "NOT_ESTABLISHED" + }, + "not_run": [ + "control.restart-recovery", + "gpu-stub.objects", + "gpu-stub.vlm", + "gpu-stub.dense" + ], + "run_id": "f445c56d6cd5b3d3", + "schema": "hunter-local-ingest/summary/2", + "total": 17, + "verdict": "BLOCKED" +} diff --git a/tools/hunter-local-ingest/evidence/1511668/rerun-committed-capture/rerun-20261012T113538Z-16c9a6f5ca70bb26/checks.jsonl b/tools/hunter-local-ingest/evidence/1511668/rerun-committed-capture/rerun-20261012T113538Z-16c9a6f5ca70bb26/checks.jsonl new file mode 100644 index 000000000..d562f48d8 --- /dev/null +++ b/tools/hunter-local-ingest/evidence/1511668/rerun-committed-capture/rerun-20261012T113538Z-16c9a6f5ca70bb26/checks.jsonl @@ -0,0 +1,17 @@ +{"expected": "an HTTP 2xx answer with status ok", "id": "lifecycle.health", "observed": {"contract": {"status": "ok"}, "http": {"attempts": 1, "body_bytes": 16, "body_sha256": "08e2c358ce13", "elapsed_ms": 0, "fields": ["status"], "http_status": 200, "shape": "object"}, "violations": []}, "oracle": "tools/integration-viewer reads GET /v1/healthz; HouseScanKit never calls it", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:38.371Z"} +{"expected": "2xx, a captureId and a published capture status", "id": "lifecycle.create", "observed": {"contract": {"captureId": "id:fd102437f369", "maxBatch": 50, "status": "uploading"}, "http": {"attempts": 1, "body_bytes": 78, "body_sha256": "8edf48cf4ce9", "elapsed_ms": 0, "fields": ["captureId", "status", "upload"], "http_status": 200, "shape": "object"}, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.create: POST captures with Idempotency-Key=packetId; the answer decodes as CaptureAPI.CreateResponse", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:38.371Z"} +{"expected": "every requested path answered exactly once, no other path, each committed or given a usable PUT target", "id": "lifecycle.register", "observed": {"batches": [{"contract": {"files": [{"path": "synthetic/scan00.bin", "state": "committed"}, {"path": "synthetic/scan01.bin", "state": "committed"}, {"path": "synthetic/scan02.bin", "state": "committed"}, {"path": "streams/arkit_poses.csv.gz", "state": "committed"}, {"path": "streams/imu_raw.csv.gz", "state": "committed"}]}, "http": {"attempts": 1, "body_bytes": 299, "body_sha256": "c836647d9496", "elapsed_ms": 0, "fields": ["files"], "http_status": 200, "shape": "object"}, "violations": []}], "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.register: the answer decodes as RegisterResponse and is applied by path; a target needs method PUT and a URL that passes uploadURLProblem", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:38.372Z"} +{"expected": "2xx for every file that got a target", "id": "lifecycle.upload", "observed": {"committed_at_register": ["streams/arkit_poses.csv.gz", "streams/imu_raw.csv.gz", "synthetic/scan00.bin", "synthetic/scan01.bin", "synthetic/scan02.bin"], "uploads": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.put + ScopedCaptureHTTP.upload: exactly the signed headers, never Authorization", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:38.372Z"} +{"expected": "committed equals the uploaded set; notFound and mismatch empty; every declared path committed by register or commit", "id": "lifecycle.commit", "observed": {"batches": [], "committed_at_register": ["streams/arkit_poses.csv.gz", "streams/imu_raw.csv.gz", "synthetic/scan00.bin", "synthetic/scan01.bin", "synthetic/scan02.bin"], "committed_total": 5, "declared": 5, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.commit: only a commit acknowledges a file; CommitResponse carries committed, notFound and mismatch", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:38.372Z"} +{"expected": "2xx, a runId, a published status, no missing file", "id": "lifecycle.finalize", "observed": {"contract": {"missing": [], "runId": "id:492e113d2d27", "status": "processing"}, "http": {"attempts": 1, "body_bytes": 62, "body_sha256": "425e9d06a56d", "elapsed_ms": 0, "fields": ["missing", "runId", "status"], "http_status": 202, "shape": "object"}, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.finalize: X-Packet-Sha256 and Idempotency-Key=packetId; the answer decodes as FinalizeResponse", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:38.373Z"} +{"expected": "a terminal status within the budget, every answer contract-shaped", "id": "lifecycle.events", "observed": {"answers": 1, "finalize_retries": 0, "last": {"contract": {"events": [{"data": {"runId": "id:492e113d2d27", "runId_matches": true}, "seq": 1, "type": "verdict_ready"}], "next": 1, "status": "complete"}, "http": {"attempts": 1, "body_bytes": 145, "body_sha256": "f7919284ecb6", "elapsed_ms": 0, "fields": ["events", "next", "status"], "http_status": 200, "shape": "object"}, "violations": []}}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.pollEvents: EventsResponse until CaptureAPI.terminalStatuses; next never moves back; a verdict names this run; retry_finalize re-sends the packet", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:38.373Z"} +{"expected": "a decodable result for this run whose status matches the terminal event status", "id": "lifecycle.result", "observed": {"contract": {"criteria": null, "has_preview_url": false, "memberActions": 0, "outcome": {"kind": "eligible", "reasons": 0}, "runId": "id:492e113d2d27", "status": "complete", "viewsNeeded": 0}, "http": {"attempts": 1, "body_bytes": 227, "body_sha256": "1dc1b0ebf7a6", "elapsed_ms": 0, "fields": ["memberActions", "outcome", "runId", "status", "viewsNeeded"], "http_status": 200, "shape": "object"}, "not_ready_reads": 0, "run_matches": true, "status_matches": true, "terminal_status": "complete", "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.fetchResult: the whole body decodes as CaptureResult.Response, its runId is the finalized run, and a null outcome is final only under statusesWithoutOutcome", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:38.374Z"} +{"expected": "both creates 2xx with the same captureId", "id": "control.idempotent-create", "observed": {"first": {"contract": {"captureId": "id:d6611115894b", "maxBatch": 50, "status": "uploading"}, "http": {"attempts": 1, "body_bytes": 78, "body_sha256": "1ff5bb037620", "elapsed_ms": 0, "fields": ["captureId", "status", "upload"], "http_status": 201, "shape": "object"}, "violations": []}, "same_capture": true, "second": {"contract": {"captureId": "id:d6611115894b", "maxBatch": 50, "status": "uploading"}, "http": {"attempts": 1, "body_bytes": 78, "body_sha256": "1ff5bb037620", "elapsed_ms": 0, "fields": ["captureId", "status", "upload"], "http_status": 200, "shape": "object"}, "violations": []}}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.start: create is bound to Idempotency-Key=packetId, so a repeated create with the same bytes names the same capture", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:38.375Z"} +{"expected": "intact files committed; the flipped file in mismatch or notFound, or its PUT refused, and never committed", "id": "control.corrupt-upload", "observed": {"batches": [{"contract": {"committed": ["synthetic/scan01.bin", "synthetic/scan02.bin", "streams/arkit_poses.csv.gz", "streams/imu_raw.csv.gz"], "mismatch": ["synthetic/scan00.bin"], "notFound": []}, "http": {"attempts": 1, "body_bytes": 173, "body_sha256": "b6f8e6ec4d66", "elapsed_ms": 0, "fields": ["committed", "mismatch", "notFound"], "http_status": 200, "shape": "object"}, "violations": []}], "intact_committed": true, "intact_reported_negative": false, "tampered": "synthetic/scan00.bin", "tampered_committed": false, "tampered_put_status": 200, "tampered_reported": true, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CommitResponse separates committed from mismatch/notFound; one file's bytes are flipped after its digest was registered", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:38.379Z"} +{"expected": "intact files committed; the truncated file in mismatch or notFound, or its PUT refused, and never committed", "id": "control.truncated-upload", "observed": {"batches": [{"contract": {"committed": ["synthetic/scan01.bin", "synthetic/scan02.bin", "streams/arkit_poses.csv.gz", "streams/imu_raw.csv.gz"], "mismatch": ["synthetic/scan00.bin"], "notFound": []}, "http": {"attempts": 1, "body_bytes": 173, "body_sha256": "b6f8e6ec4d66", "elapsed_ms": 0, "fields": ["committed", "mismatch", "notFound"], "http_status": 200, "shape": "object"}, "violations": []}], "intact_committed": true, "intact_reported_negative": false, "tampered": "synthetic/scan00.bin", "tampered_committed": false, "tampered_put_status": 200, "tampered_reported": true, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CommitResponse separates committed from mismatch/notFound; one file loses its last byte after its digest was registered", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:38.384Z"} +{"expected": "404 with error code capture_not_found for an id the harness invented", "id": "control.wrong-capture", "observed": {"capture": "id:1976512104be", "errors": {"codes": ["capture_not_found"]}, "http": {"attempts": 1, "body_bytes": 43, "body_sha256": "23553eb17fe9", "elapsed_ms": 0, "fields": ["errors"], "http_status": 404, "shape": "object"}}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.captureGone: an unknown capture answers 404 capture_not_found", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:38.384Z"} +{"expected": "every traced check present and PASS with the traced status class and fields, or upload and commit skipped because register reported every declared file committed", "id": "trace.expected-lifecycle-v3", "observed": {"compared": 12, "disagreements": [], "not_comparable": []}, "oracle": "frozen expected trace traces/expected-lifecycle-v3.jsonl, written from the published contract, with a no-request branch for files committed at register", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:38.386Z"} +{"expected": "after a successful restart the capture still reports its terminal status and run", "id": "control.restart-recovery", "observed": {"note": "restart-not-configured"}, "oracle": "operator restart command, then the baseline capture is read again over the published events and result routes", "status": "NOT_RUN", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:38.386Z"} +{"expected": "not run", "id": "gpu-stub.objects", "observed": {"note": "gpu-not-authorized"}, "oracle": "GPU-dependent arms are named and never executed by this harness", "status": "NOT_RUN", "transport": "GPU_STUB", "ts": "2026-10-12T11:35:38.386Z"} +{"expected": "not run", "id": "gpu-stub.vlm", "observed": {"note": "gpu-not-authorized"}, "oracle": "GPU-dependent arms are named and never executed by this harness", "status": "NOT_RUN", "transport": "GPU_STUB", "ts": "2026-10-12T11:35:38.386Z"} +{"expected": "not run", "id": "gpu-stub.dense", "observed": {"note": "gpu-not-authorized"}, "oracle": "GPU-dependent arms are named and never executed by this harness", "status": "NOT_RUN", "transport": "GPU_STUB", "ts": "2026-10-12T11:35:38.386Z"} diff --git a/tools/hunter-local-ingest/evidence/1511668/rerun-committed-capture/rerun-20261012T113538Z-16c9a6f5ca70bb26/privacy-chain.jsonl b/tools/hunter-local-ingest/evidence/1511668/rerun-committed-capture/rerun-20261012T113538Z-16c9a6f5ca70bb26/privacy-chain.jsonl new file mode 100644 index 000000000..8661450e5 --- /dev/null +++ b/tools/hunter-local-ingest/evidence/1511668/rerun-committed-capture/rerun-20261012T113538Z-16c9a6f5ca70bb26/privacy-chain.jsonl @@ -0,0 +1,4 @@ +{"artifact": "run-manifest.json", "at": "2026-10-12T11:35:38.368Z", "bytes": 3452, "chain_sha256": "d4e2787197f356cd2fa1424ea910b3e1dd67379a8b9f0bff6b099e30585968cd", "sha256": "9f7c00b7cb44e5e3741d621749aa71c37cfd926da0b57936d58600cbef5e3a4f"} +{"artifact": "checks.jsonl", "at": "2026-10-12T11:35:38.386Z", "bytes": 10718, "chain_sha256": "631481b37d8cd365108cdc3f9f18b910983a7c09f937ba2dd6785ec08c0abaac", "sha256": "775b234bc060147fec93a0db378ef42b8ed6593d616c467952f32665ebafb088"} +{"artifact": "summary.json", "at": "2026-10-12T11:35:38.386Z", "bytes": 1366, "chain_sha256": "d86e549e9401bf61558943024d11445ba2a2bf5f91df5d93679de5e55200f4a6", "sha256": "1edb1aba01f48e49ae99ccf559299b98f863faf6fcfed35200492f5414497d13"} +{"artifact": "privacy-screen.json", "at": "2026-10-12T11:35:38.391Z", "bytes": 238, "chain_sha256": "96ff77930cd2e8f9fd521a058b9bbd98e87f77c92b7b99f839412105645b6327", "sha256": "d09fc155f5bee507550ff9ab1af2119ff8c28c5c42804e38e1c6c7b60c4a9ada"} diff --git a/tools/hunter-local-ingest/evidence/1511668/rerun-committed-capture/rerun-20261012T113538Z-16c9a6f5ca70bb26/privacy-screen.json b/tools/hunter-local-ingest/evidence/1511668/rerun-committed-capture/rerun-20261012T113538Z-16c9a6f5ca70bb26/privacy-screen.json new file mode 100644 index 000000000..4262ac46d --- /dev/null +++ b/tools/hunter-local-ingest/evidence/1511668/rerun-committed-capture/rerun-20261012T113538Z-16c9a6f5ca70bb26/privacy-screen.json @@ -0,0 +1,12 @@ +{ + "clean": true, + "findings": [], + "finished_utc": "2026-10-12T11:35:38.391Z", + "missing": [], + "schema": "hunter-local-ingest/privacy-screen/2", + "screened": [ + "run-manifest.json", + "checks.jsonl", + "summary.json" + ] +} diff --git a/tools/hunter-local-ingest/evidence/1511668/rerun-committed-capture/rerun-20261012T113538Z-16c9a6f5ca70bb26/run-manifest.json b/tools/hunter-local-ingest/evidence/1511668/rerun-committed-capture/rerun-20261012T113538Z-16c9a6f5ca70bb26/run-manifest.json new file mode 100644 index 000000000..2543f8338 --- /dev/null +++ b/tools/hunter-local-ingest/evidence/1511668/rerun-committed-capture/rerun-20261012T113538Z-16c9a6f5ca70bb26/run-manifest.json @@ -0,0 +1,109 @@ +{ + "backend": { + "declared_mode": "FAKE_HUNTER", + "declared_ref": null, + "verified": false + }, + "client": { + "declared_ref": null, + "git": null, + "interface": "2.0.0", + "package_version": "0.2.0", + "source_sha256": "843fd20eb408e4308664ec36453b7d887e994c92ad09b0760a897efaa6d0a6d7" + }, + "command": [ + "--endpoint", + "127.0.0.1:58249", + "--plan-file", + "", + "--out", + "", + "--label", + "rerun", + "--backend-mode", + "FAKE_HUNTER", + "--poll-interval-s", + "0.05", + "--events-wait-s", + "0", + "--retry-backoff-s", + "0.0", + "--result-budget-s", + "30.0" + ], + "created_utc": "2026-10-12T11:35:38.361Z", + "endpoint": "127.0.0.1:58249", + "fixture": { + "create_sha256": "9c2dd5f33bb70b7199e85f165e87602986faa7f6b5beaee6f55db4f1f9edce97", + "files": [ + { + "bytes": 65536, + "contentType": "application/octet-stream", + "path": "synthetic/scan00.bin", + "role": "other", + "sha256": "a1ca0aa5e471b98beddf42738d706871542520398ced6f3ed81008e8c9812d85" + }, + { + "bytes": 65536, + "contentType": "application/octet-stream", + "path": "synthetic/scan01.bin", + "role": "other", + "sha256": "ef4380c88a7e0a2df7506640f6b435b153122e01070d7570870ebd2d3367d4be" + }, + { + "bytes": 65536, + "contentType": "application/octet-stream", + "path": "synthetic/scan02.bin", + "role": "other", + "sha256": "3fda1dfcabd6f77b655435c16a6c7b75d5f2f2b4ef9dccd814fede0f2b69e1f1" + }, + { + "bytes": 9793, + "contentType": "application/gzip", + "path": "streams/arkit_poses.csv.gz", + "role": "stream", + "sha256": "a23bcec6f6829c053e7bc1871999ca7b1a5e88639b5a6cde56afc655d3447388" + }, + { + "bytes": 9443, + "contentType": "application/gzip", + "path": "streams/imu_raw.csv.gz", + "role": "stream", + "sha256": "ae96d9008b71882aeb0dbc1c5463897aa9c316fbda28d5503b4676e0bd85a161" + } + ], + "format_version": 2, + "generator": "gen_synthetic_packet", + "packet_id": "synthetic-000001", + "packet_sha256": "9ab561f503ef3dc0c0e5b007157ab40c803d5b43dc38136285a72ab77acd17d1", + "plan_file_sha256": "eabf28a3f818ee22d38cec91ad6d85af6921f5cb45156378a007475368ab692f", + "plan_sha256": "50f73a67aeb28e5e0c41f40946958a2806024f75ae56dda1384025ccd0a8e4ac", + "seed": 1 + }, + "label": "rerun", + "origin_note": "Derived from published client behavior in HouseScanKit upload and result sources at alpha 263827ef. No private source, schema, spec, log or credential material appears in this package or its receipts.", + "restart": { + "argv": [], + "configured": false, + "timeout_s": 120.0 + }, + "run_id": "16c9a6f5ca70bb26", + "runtime": { + "cpus": 12, + "implementation": "CPython", + "machine": "arm64", + "python": "3.13.12", + "release": "25.6.0", + "system": "Darwin" + }, + "sanitization": "Every value here passed the typed export schema before it was written: published enum words, package constants, digests, bounded numbers, and the plan's own synthetic paths and packet ids. A pattern screen then ran over the written files.", + "schema": "hunter-local-ingest/run-manifest/2", + "settings": { + "events_wait_s": 0, + "max_retries": 2, + "poll_interval_s": 0.05, + "result_budget_s": 30.0, + "retry_backoff_s": 0.0, + "with_faults": false + } +} diff --git a/tools/hunter-local-ingest/evidence/1511668/rerun-committed-capture/rerun-20261012T113538Z-16c9a6f5ca70bb26/summary.json b/tools/hunter-local-ingest/evidence/1511668/rerun-committed-capture/rerun-20261012T113538Z-16c9a6f5ca70bb26/summary.json new file mode 100644 index 000000000..a59119082 --- /dev/null +++ b/tools/hunter-local-ingest/evidence/1511668/rerun-committed-capture/rerun-20261012T113538Z-16c9a6f5ca70bb26/summary.json @@ -0,0 +1,40 @@ +{ + "artifacts": { + "checks.jsonl": "775b234bc060147fec93a0db378ef42b8ed6593d616c467952f32665ebafb088", + "run-manifest.json": "9f7c00b7cb44e5e3741d621749aa71c37cfd926da0b57936d58600cbef5e3a4f" + }, + "blocked": [], + "counts_by_transport": { + "FAKE_HUNTER": { + "NOT_RUN": 1, + "PASS": 13 + }, + "GPU_STUB": { + "NOT_RUN": 3 + } + }, + "failed": [], + "finished_utc": "2026-10-12T11:35:38.386Z", + "lead_questions": [ + "Amendment semantics: does the published contract allow amending a registered capture, and with which route and headers?", + "Local-run auth mode: which credential form does the local backend expect from the published client? The client can send a bearer token on API routes only; no CLI flag supplies one yet.", + "Clock and expiry authority: whose clock governs capture expiry on the local backend?", + "Homeowner text: confirm that receipts may carry outcome kinds and counts but never messages, prompts or reasons." + ], + "mode": { + "backend_verified": false, + "declared_backend": "FAKE_HUNTER", + "gpu_arms": "NOT_RUN", + "real_mirror_cpu": "NOT_ESTABLISHED" + }, + "not_run": [ + "control.restart-recovery", + "gpu-stub.objects", + "gpu-stub.vlm", + "gpu-stub.dense" + ], + "run_id": "16c9a6f5ca70bb26", + "schema": "hunter-local-ingest/summary/2", + "total": 17, + "verdict": "PASS" +} diff --git a/tools/hunter-local-ingest/evidence/1511668/selfcheck/selfcheck-20261012T113520Z-6d9d8505f2ea1312/checks.jsonl b/tools/hunter-local-ingest/evidence/1511668/selfcheck/selfcheck-20261012T113520Z-6d9d8505f2ea1312/checks.jsonl new file mode 100644 index 000000000..456b8cb83 --- /dev/null +++ b/tools/hunter-local-ingest/evidence/1511668/selfcheck/selfcheck-20261012T113520Z-6d9d8505f2ea1312/checks.jsonl @@ -0,0 +1,29 @@ +{"expected": "an HTTP 2xx answer with status ok", "id": "lifecycle.health", "observed": {"contract": {"status": "ok"}, "http": {"attempts": 1, "body_bytes": 16, "body_sha256": "08e2c358ce13", "elapsed_ms": 1, "fields": ["status"], "http_status": 200, "shape": "object"}, "violations": []}, "oracle": "tools/integration-viewer reads GET /v1/healthz; HouseScanKit never calls it", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:20.652Z"} +{"expected": "2xx, a captureId and a published capture status", "id": "lifecycle.create", "observed": {"contract": {"captureId": "id:fd102437f369", "maxBatch": 50, "status": "uploading"}, "http": {"attempts": 1, "body_bytes": 78, "body_sha256": "8edf48cf4ce9", "elapsed_ms": 0, "fields": ["captureId", "status", "upload"], "http_status": 201, "shape": "object"}, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.create: POST captures with Idempotency-Key=packetId; the answer decodes as CaptureAPI.CreateResponse", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:20.653Z"} +{"expected": "every requested path answered exactly once, no other path, each committed or given a usable PUT target", "id": "lifecycle.register", "observed": {"batches": [{"contract": {"files": [{"path": "synthetic/scan00.bin", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "synthetic/scan01.bin", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "synthetic/scan02.bin", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "streams/arkit_poses.csv.gz", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "streams/imu_raw.csv.gz", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}]}, "http": {"attempts": 1, "body_bytes": 1253, "body_sha256": "3491333fa691", "elapsed_ms": 0, "fields": ["files"], "http_status": 200, "shape": "object"}, "violations": []}], "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.register: the answer decodes as RegisterResponse and is applied by path; a target needs method PUT and a URL that passes uploadURLProblem", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:20.654Z"} +{"expected": "2xx for every file that got a target", "id": "lifecycle.upload", "observed": {"committed_at_register": [], "uploads": [{"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 1, "fields": [], "http_status": 200, "path": "synthetic/scan00.bin", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "synthetic/scan01.bin", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "synthetic/scan02.bin", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "streams/arkit_poses.csv.gz", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "streams/imu_raw.csv.gz", "shape": "empty"}]}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.put + ScopedCaptureHTTP.upload: exactly the signed headers, never Authorization", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:20.658Z"} +{"expected": "committed equals the uploaded set; notFound and mismatch empty; every declared path committed by register or commit", "id": "lifecycle.commit", "observed": {"batches": [{"contract": {"committed": ["synthetic/scan00.bin", "synthetic/scan01.bin", "synthetic/scan02.bin", "streams/arkit_poses.csv.gz", "streams/imu_raw.csv.gz"], "mismatch": [], "notFound": []}, "http": {"attempts": 1, "body_bytes": 175, "body_sha256": "ab0d647d58c4", "elapsed_ms": 0, "fields": ["committed", "mismatch", "notFound"], "http_status": 200, "shape": "object"}, "violations": []}], "committed_at_register": [], "committed_total": 5, "declared": 5, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.commit: only a commit acknowledges a file; CommitResponse carries committed, notFound and mismatch", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:20.659Z"} +{"expected": "2xx, a runId, a published status, no missing file", "id": "lifecycle.finalize", "observed": {"contract": {"missing": [], "runId": "id:492e113d2d27", "status": "processing"}, "http": {"attempts": 1, "body_bytes": 62, "body_sha256": "425e9d06a56d", "elapsed_ms": 0, "fields": ["missing", "runId", "status"], "http_status": 202, "shape": "object"}, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.finalize: X-Packet-Sha256 and Idempotency-Key=packetId; the answer decodes as FinalizeResponse", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:20.660Z"} +{"expected": "a terminal status within the budget, every answer contract-shaped", "id": "lifecycle.events", "observed": {"answers": 1, "finalize_retries": 0, "last": {"contract": {"events": [{"data": {"runId": "id:492e113d2d27", "runId_matches": true}, "seq": 1, "type": "verdict_ready"}], "next": 1, "status": "complete"}, "http": {"attempts": 1, "body_bytes": 145, "body_sha256": "f7919284ecb6", "elapsed_ms": 0, "fields": ["events", "next", "status"], "http_status": 200, "shape": "object"}, "violations": []}}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.pollEvents: EventsResponse until CaptureAPI.terminalStatuses; next never moves back; a verdict names this run; retry_finalize re-sends the packet", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:20.660Z"} +{"expected": "a decodable result for this run whose status matches the terminal event status", "id": "lifecycle.result", "observed": {"contract": {"criteria": null, "has_preview_url": false, "memberActions": 0, "outcome": {"kind": "eligible", "reasons": 0}, "runId": "id:492e113d2d27", "status": "complete", "viewsNeeded": 0}, "http": {"attempts": 1, "body_bytes": 227, "body_sha256": "1dc1b0ebf7a6", "elapsed_ms": 0, "fields": ["memberActions", "outcome", "runId", "status", "viewsNeeded"], "http_status": 200, "shape": "object"}, "not_ready_reads": 0, "run_matches": true, "status_matches": true, "terminal_status": "complete", "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.fetchResult: the whole body decodes as CaptureResult.Response, its runId is the finalized run, and a null outcome is final only under statusesWithoutOutcome", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:20.661Z"} +{"expected": "both creates 2xx with the same captureId", "id": "control.idempotent-create", "observed": {"first": {"contract": {"captureId": "id:b9d50067aadb", "maxBatch": 50, "status": "uploading"}, "http": {"attempts": 1, "body_bytes": 78, "body_sha256": "ec8a1ff9228b", "elapsed_ms": 0, "fields": ["captureId", "status", "upload"], "http_status": 201, "shape": "object"}, "violations": []}, "same_capture": true, "second": {"contract": {"captureId": "id:b9d50067aadb", "maxBatch": 50, "status": "uploading"}, "http": {"attempts": 1, "body_bytes": 78, "body_sha256": "ec8a1ff9228b", "elapsed_ms": 0, "fields": ["captureId", "status", "upload"], "http_status": 200, "shape": "object"}, "violations": []}}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.start: create is bound to Idempotency-Key=packetId, so a repeated create with the same bytes names the same capture", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:20.662Z"} +{"expected": "intact files committed; the flipped file in mismatch or notFound, or its PUT refused, and never committed", "id": "control.corrupt-upload", "observed": {"batches": [{"contract": {"committed": ["synthetic/scan01.bin", "synthetic/scan02.bin", "streams/arkit_poses.csv.gz", "streams/imu_raw.csv.gz"], "mismatch": ["synthetic/scan00.bin"], "notFound": []}, "http": {"attempts": 1, "body_bytes": 173, "body_sha256": "b6f8e6ec4d66", "elapsed_ms": 0, "fields": ["committed", "mismatch", "notFound"], "http_status": 200, "shape": "object"}, "violations": []}], "intact_committed": true, "intact_reported_negative": false, "tampered": "synthetic/scan00.bin", "tampered_committed": false, "tampered_put_status": 200, "tampered_reported": true, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CommitResponse separates committed from mismatch/notFound; one file's bytes are flipped after its digest was registered", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:20.667Z"} +{"expected": "intact files committed; the truncated file in mismatch or notFound, or its PUT refused, and never committed", "id": "control.truncated-upload", "observed": {"batches": [{"contract": {"committed": ["synthetic/scan01.bin", "synthetic/scan02.bin", "streams/arkit_poses.csv.gz", "streams/imu_raw.csv.gz"], "mismatch": ["synthetic/scan00.bin"], "notFound": []}, "http": {"attempts": 1, "body_bytes": 173, "body_sha256": "b6f8e6ec4d66", "elapsed_ms": 0, "fields": ["committed", "mismatch", "notFound"], "http_status": 200, "shape": "object"}, "violations": []}], "intact_committed": true, "intact_reported_negative": false, "tampered": "synthetic/scan00.bin", "tampered_committed": false, "tampered_put_status": 200, "tampered_reported": true, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CommitResponse separates committed from mismatch/notFound; one file loses its last byte after its digest was registered", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:20.672Z"} +{"expected": "404 with error code capture_not_found for an id the harness invented", "id": "control.wrong-capture", "observed": {"capture": "id:1976512104be", "errors": {"codes": ["capture_not_found"]}, "http": {"attempts": 1, "body_bytes": 43, "body_sha256": "23553eb17fe9", "elapsed_ms": 0, "fields": ["errors"], "http_status": 404, "shape": "object"}}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.captureGone: an unknown capture answers 404 capture_not_found", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:20.672Z"} +{"expected": "an HTTP 2xx answer with status ok", "id": "fault.lifecycle.health", "observed": {"contract": {"status": "ok"}, "http": {"attempts": 1, "body_bytes": 16, "body_sha256": "08e2c358ce13", "elapsed_ms": 0, "fields": ["status"], "http_status": 200, "shape": "object"}, "violations": []}, "oracle": "tools/integration-viewer reads GET /v1/healthz; HouseScanKit never calls it", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:20.674Z"} +{"expected": "2xx, a captureId and a published capture status", "id": "fault.lifecycle.create", "observed": {"contract": {"captureId": "id:d6611115894b", "maxBatch": 50, "status": "uploading"}, "http": {"attempts": 1, "body_bytes": 78, "body_sha256": "1ff5bb037620", "elapsed_ms": 112, "fields": ["captureId", "status", "upload"], "http_status": 201, "shape": "object"}, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.create: POST captures with Idempotency-Key=packetId; the answer decodes as CaptureAPI.CreateResponse", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:20.787Z"} +{"expected": "every requested path answered exactly once, no other path, each committed or given a usable PUT target", "id": "fault.lifecycle.register", "observed": {"batches": [{"contract": {"files": [{"path": "synthetic/scan00.bin", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "synthetic/scan01.bin", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "synthetic/scan02.bin", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "streams/arkit_poses.csv.gz", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "streams/imu_raw.csv.gz", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}]}, "http": {"attempts": 1, "body_bytes": 1253, "body_sha256": "22c88171812c", "elapsed_ms": 1, "fields": ["files"], "http_status": 200, "shape": "object"}, "violations": []}], "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.register: the answer decodes as RegisterResponse and is applied by path; a target needs method PUT and a URL that passes uploadURLProblem", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:20.789Z"} +{"expected": "2xx for every file that got a target", "id": "fault.lifecycle.upload", "observed": {"committed_at_register": [], "uploads": [{"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 1, "fields": [], "http_status": 200, "path": "synthetic/scan00.bin", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 1, "fields": [], "http_status": 200, "path": "synthetic/scan01.bin", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 1, "fields": [], "http_status": 200, "path": "synthetic/scan02.bin", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "streams/arkit_poses.csv.gz", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "streams/imu_raw.csv.gz", "shape": "empty"}]}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.put + ScopedCaptureHTTP.upload: exactly the signed headers, never Authorization", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:20.795Z"} +{"expected": "committed equals the uploaded set; notFound and mismatch empty; every declared path committed by register or commit", "id": "fault.lifecycle.commit", "observed": {"batches": [{"contract": {"committed": ["synthetic/scan00.bin", "synthetic/scan01.bin", "synthetic/scan02.bin", "streams/arkit_poses.csv.gz", "streams/imu_raw.csv.gz"], "mismatch": [], "notFound": []}, "http": {"attempts": 1, "body_bytes": 175, "body_sha256": "ab0d647d58c4", "elapsed_ms": 2, "fields": ["committed", "mismatch", "notFound"], "http_status": 200, "shape": "object"}, "violations": []}], "committed_at_register": [], "committed_total": 5, "declared": 5, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.commit: only a commit acknowledges a file; CommitResponse carries committed, notFound and mismatch", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:20.797Z"} +{"expected": "2xx, a runId, a published status, no missing file", "id": "fault.lifecycle.finalize", "observed": {"contract": {"missing": [], "runId": "id:636f557a124e", "status": "processing"}, "http": {"attempts": 1, "body_bytes": 62, "body_sha256": "cc5e4603e9bd", "elapsed_ms": 1, "fields": ["missing", "runId", "status"], "http_status": 202, "shape": "object"}, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.finalize: X-Packet-Sha256 and Idempotency-Key=packetId; the answer decodes as FinalizeResponse", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:20.799Z"} +{"expected": "a terminal status within the budget, every answer contract-shaped", "id": "fault.lifecycle.events", "observed": {"answers": 1, "finalize_retries": 0, "last": {"contract": {"events": [{"data": {"runId": "id:636f557a124e", "runId_matches": true}, "seq": 1, "type": "verdict_ready"}], "next": 1, "status": "complete"}, "http": {"attempts": 1, "body_bytes": 145, "body_sha256": "6519430bc83d", "elapsed_ms": 1, "fields": ["events", "next", "status"], "http_status": 200, "shape": "object"}, "violations": []}}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.pollEvents: EventsResponse until CaptureAPI.terminalStatuses; next never moves back; a verdict names this run; retry_finalize re-sends the packet", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:20.801Z"} +{"expected": "a decodable result for this run whose status matches the terminal event status", "id": "fault.lifecycle.result", "observed": {"contract": {"criteria": null, "has_preview_url": false, "memberActions": 0, "outcome": {"kind": "eligible", "reasons": 0}, "runId": "id:636f557a124e", "status": "complete", "viewsNeeded": 0}, "http": {"attempts": 1, "body_bytes": 227, "body_sha256": "f0543371247b", "elapsed_ms": 1, "fields": ["memberActions", "outcome", "runId", "status", "viewsNeeded"], "http_status": 200, "shape": "object"}, "not_ready_reads": 0, "run_matches": true, "status_matches": true, "terminal_status": "complete", "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.fetchResult: the whole body decodes as CaptureResult.Response, its runId is the finalized run, and a null outcome is final only under statusesWithoutOutcome", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:20.802Z"} +{"expected": "the proxy's single 503 is followed by a second attempt that creates the capture", "id": "fault.retry-transient", "observed": {"contract": {"captureId": "id:40a0732506ed", "maxBatch": 50, "status": "uploading"}, "http": {"attempts": 2, "body_bytes": 78, "body_sha256": "2350cd7a9fb2", "elapsed_ms": 2, "fields": ["captureId", "status", "upload"], "http_status": 201, "shape": "object"}, "proxy_hits": 2, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.isTransient: a 503 is retried with the same body", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:21.812Z"} +{"expected": "exactly one attempt and a reported non-2xx answer", "id": "fault.no-retry-501", "observed": {"errors": {"codes": ["harness_fault"]}, "http": {"attempts": 1, "body_bytes": 39, "body_sha256": "be37db4e697d", "elapsed_ms": 1, "fields": ["errors"], "http_status": 501, "shape": "object"}, "proxy_hits": 1}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.isTransient excludes 501", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:22.320Z"} +{"expected": "a transport error category after 1 + max_retries attempts, no capture id taken", "id": "fault.abort", "observed": {"http": {"attempts": 2, "error": "transport:remote-disconnected"}, "proxy_hits": 2}, "oracle": "an answer-less connection is a transport failure, retried a bounded number of times", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:22.827Z"} +{"expected": "a transport error category, no capture id taken", "id": "fault.truncated-response", "observed": {"http": {"attempts": 1, "error": "transport:incomplete-read"}, "proxy_hits": 1}, "oracle": "a body shorter than its Content-Length is a transport failure, never a parsed answer", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:23.335Z"} +{"expected": "every traced check present and PASS with the traced status class and fields, or upload and commit skipped because register reported every declared file committed", "id": "trace.expected-lifecycle-v3", "observed": {"compared": 12, "disagreements": [], "not_comparable": []}, "oracle": "frozen expected trace traces/expected-lifecycle-v3.jsonl, written from the published contract, with a no-request branch for files committed at register", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:23.337Z"} +{"expected": "after a successful restart the capture still reports its terminal status and run", "id": "control.restart-recovery", "observed": {"after_restart": [{"contract": {"events": [{"data": {"runId": "id:492e113d2d27", "runId_matches": true}, "seq": 1, "type": "verdict_ready"}], "next": 1, "status": "complete"}, "http": {"attempts": 1, "body_bytes": 145, "body_sha256": "f7919284ecb6", "elapsed_ms": 1, "fields": ["events", "next", "status"], "http_status": 200, "shape": "object"}, "violations": []}, {"contract": {"criteria": null, "has_preview_url": false, "memberActions": 0, "outcome": {"kind": "eligible", "reasons": 0}, "runId": "id:492e113d2d27", "status": "complete", "viewsNeeded": 0}, "http": {"attempts": 1, "body_bytes": 227, "body_sha256": "1dc1b0ebf7a6", "elapsed_ms": 0, "fields": ["memberActions", "outcome", "runId", "status", "viewsNeeded"], "http_status": 200, "shape": "object"}, "violations": []}], "exit_code": 0, "run_matches": true, "status_matches": true}, "oracle": "operator restart command, then the baseline capture is read again over the published events and result routes", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T11:35:23.362Z"} +{"expected": "not run", "id": "gpu-stub.objects", "observed": {"note": "gpu-not-authorized"}, "oracle": "GPU-dependent arms are named and never executed by this harness", "status": "NOT_RUN", "transport": "GPU_STUB", "ts": "2026-10-12T11:35:23.362Z"} +{"expected": "not run", "id": "gpu-stub.vlm", "observed": {"note": "gpu-not-authorized"}, "oracle": "GPU-dependent arms are named and never executed by this harness", "status": "NOT_RUN", "transport": "GPU_STUB", "ts": "2026-10-12T11:35:23.362Z"} +{"expected": "not run", "id": "gpu-stub.dense", "observed": {"note": "gpu-not-authorized"}, "oracle": "GPU-dependent arms are named and never executed by this harness", "status": "NOT_RUN", "transport": "GPU_STUB", "ts": "2026-10-12T11:35:23.362Z"} diff --git a/tools/hunter-local-ingest/evidence/1511668/selfcheck/selfcheck-20261012T113520Z-6d9d8505f2ea1312/privacy-chain.jsonl b/tools/hunter-local-ingest/evidence/1511668/selfcheck/selfcheck-20261012T113520Z-6d9d8505f2ea1312/privacy-chain.jsonl new file mode 100644 index 000000000..b2046b53b --- /dev/null +++ b/tools/hunter-local-ingest/evidence/1511668/selfcheck/selfcheck-20261012T113520Z-6d9d8505f2ea1312/privacy-chain.jsonl @@ -0,0 +1,4 @@ +{"artifact": "run-manifest.json", "at": "2026-10-12T11:35:20.650Z", "bytes": 3535, "chain_sha256": "1320ed840334feaccd71c662b3cfe058871ed3933d97bdd0dc0fc84c0397ccc5", "sha256": "b9ce795e064561f52586d1469524cf0ec891331f50ddad83a18d59b3854fb80b"} +{"artifact": "checks.jsonl", "at": "2026-10-12T11:35:23.362Z", "bytes": 22307, "chain_sha256": "1ed09611af7e4e43b8c6f31c01c093157eef7f5a36db728da4dcc557a9ee6052", "sha256": "af46460e0c8256c151cd0106cb676a29e1a26df4a2b902e7fb7971a3d3b48884"} +{"artifact": "summary.json", "at": "2026-10-12T11:35:23.363Z", "bytes": 1314, "chain_sha256": "74b1d5d871c13dee34f8531f11333c1ed72bda3ff331e9e862aff86a3714a1c4", "sha256": "7989ce84835af32ed6dfbbade954253541df379670c7274ae2b3750a975c6c94"} +{"artifact": "privacy-screen.json", "at": "2026-10-12T11:35:23.371Z", "bytes": 238, "chain_sha256": "17726963e7b3241c5779ad91796230590d751b2d1a8f1c889afbe496c1608ff8", "sha256": "5d830a9a88ba211e79c36126198f33755e14aafd728983f04f93ae69a6965bc2"} diff --git a/tools/hunter-local-ingest/evidence/1511668/selfcheck/selfcheck-20261012T113520Z-6d9d8505f2ea1312/privacy-screen.json b/tools/hunter-local-ingest/evidence/1511668/selfcheck/selfcheck-20261012T113520Z-6d9d8505f2ea1312/privacy-screen.json new file mode 100644 index 000000000..c628d6fe4 --- /dev/null +++ b/tools/hunter-local-ingest/evidence/1511668/selfcheck/selfcheck-20261012T113520Z-6d9d8505f2ea1312/privacy-screen.json @@ -0,0 +1,12 @@ +{ + "clean": true, + "findings": [], + "finished_utc": "2026-10-12T11:35:23.371Z", + "missing": [], + "schema": "hunter-local-ingest/privacy-screen/2", + "screened": [ + "run-manifest.json", + "checks.jsonl", + "summary.json" + ] +} diff --git a/tools/hunter-local-ingest/evidence/1511668/selfcheck/selfcheck-20261012T113520Z-6d9d8505f2ea1312/run-manifest.json b/tools/hunter-local-ingest/evidence/1511668/selfcheck/selfcheck-20261012T113520Z-6d9d8505f2ea1312/run-manifest.json new file mode 100644 index 000000000..ae111c74b --- /dev/null +++ b/tools/hunter-local-ingest/evidence/1511668/selfcheck/selfcheck-20261012T113520Z-6d9d8505f2ea1312/run-manifest.json @@ -0,0 +1,114 @@ +{ + "backend": { + "declared_mode": "FAKE_HUNTER", + "declared_ref": null, + "verified": false + }, + "client": { + "declared_ref": null, + "git": null, + "interface": "2.0.0", + "package_version": "0.2.0", + "source_sha256": "843fd20eb408e4308664ec36453b7d887e994c92ad09b0760a897efaa6d0a6d7" + }, + "command": [ + "--endpoint", + "127.0.0.1:57967", + "--plan-file", + "", + "--out", + "", + "--label", + "selfcheck", + "--backend-mode", + "FAKE_HUNTER", + "--poll-interval-s", + "0.05", + "--events-wait-s", + "0", + "--retry-backoff-s", + "0.0", + "--with-faults", + "--restart-argv-json", + "" + ], + "created_utc": "2026-10-12T11:35:20.643Z", + "endpoint": "127.0.0.1:57967", + "fixture": { + "create_sha256": "9c2dd5f33bb70b7199e85f165e87602986faa7f6b5beaee6f55db4f1f9edce97", + "files": [ + { + "bytes": 65536, + "contentType": "application/octet-stream", + "path": "synthetic/scan00.bin", + "role": "other", + "sha256": "a1ca0aa5e471b98beddf42738d706871542520398ced6f3ed81008e8c9812d85" + }, + { + "bytes": 65536, + "contentType": "application/octet-stream", + "path": "synthetic/scan01.bin", + "role": "other", + "sha256": "ef4380c88a7e0a2df7506640f6b435b153122e01070d7570870ebd2d3367d4be" + }, + { + "bytes": 65536, + "contentType": "application/octet-stream", + "path": "synthetic/scan02.bin", + "role": "other", + "sha256": "3fda1dfcabd6f77b655435c16a6c7b75d5f2f2b4ef9dccd814fede0f2b69e1f1" + }, + { + "bytes": 9793, + "contentType": "application/gzip", + "path": "streams/arkit_poses.csv.gz", + "role": "stream", + "sha256": "a23bcec6f6829c053e7bc1871999ca7b1a5e88639b5a6cde56afc655d3447388" + }, + { + "bytes": 9443, + "contentType": "application/gzip", + "path": "streams/imu_raw.csv.gz", + "role": "stream", + "sha256": "ae96d9008b71882aeb0dbc1c5463897aa9c316fbda28d5503b4676e0bd85a161" + } + ], + "format_version": 2, + "generator": "gen_synthetic_packet", + "packet_id": "synthetic-000001", + "packet_sha256": "9ab561f503ef3dc0c0e5b007157ab40c803d5b43dc38136285a72ab77acd17d1", + "plan_file_sha256": "eabf28a3f818ee22d38cec91ad6d85af6921f5cb45156378a007475368ab692f", + "plan_sha256": "50f73a67aeb28e5e0c41f40946958a2806024f75ae56dda1384025ccd0a8e4ac", + "seed": 1 + }, + "label": "selfcheck", + "origin_note": "Derived from published client behavior in HouseScanKit upload and result sources at alpha 263827ef. No private source, schema, spec, log or credential material appears in this package or its receipts.", + "restart": { + "argv": [ + "", + "-c", + "" + ], + "configured": true, + "timeout_s": 120.0 + }, + "run_id": "6d9d8505f2ea1312", + "runtime": { + "cpus": 12, + "implementation": "CPython", + "machine": "arm64", + "python": "3.13.12", + "release": "25.6.0", + "system": "Darwin" + }, + "sanitization": "Every value here passed the typed export schema before it was written: published enum words, package constants, digests, bounded numbers, and the plan's own synthetic paths and packet ids. A pattern screen then ran over the written files.", + "schema": "hunter-local-ingest/run-manifest/2", + "settings": { + "events_wait_s": 0, + "max_retries": 2, + "poll_interval_s": 0.05, + "result_budget_s": 1500.0, + "retry_backoff_s": 0.0, + "with_faults": true + } +} diff --git a/tools/hunter-local-ingest/evidence/1511668/selfcheck/selfcheck-20261012T113520Z-6d9d8505f2ea1312/summary.json b/tools/hunter-local-ingest/evidence/1511668/selfcheck/selfcheck-20261012T113520Z-6d9d8505f2ea1312/summary.json new file mode 100644 index 000000000..2ce5ec969 --- /dev/null +++ b/tools/hunter-local-ingest/evidence/1511668/selfcheck/selfcheck-20261012T113520Z-6d9d8505f2ea1312/summary.json @@ -0,0 +1,38 @@ +{ + "artifacts": { + "checks.jsonl": "af46460e0c8256c151cd0106cb676a29e1a26df4a2b902e7fb7971a3d3b48884", + "run-manifest.json": "b9ce795e064561f52586d1469524cf0ec891331f50ddad83a18d59b3854fb80b" + }, + "blocked": [], + "counts_by_transport": { + "FAKE_HUNTER": { + "PASS": 26 + }, + "GPU_STUB": { + "NOT_RUN": 3 + } + }, + "failed": [], + "finished_utc": "2026-10-12T11:35:23.362Z", + "lead_questions": [ + "Amendment semantics: does the published contract allow amending a registered capture, and with which route and headers?", + "Local-run auth mode: which credential form does the local backend expect from the published client? The client can send a bearer token on API routes only; no CLI flag supplies one yet.", + "Clock and expiry authority: whose clock governs capture expiry on the local backend?", + "Homeowner text: confirm that receipts may carry outcome kinds and counts but never messages, prompts or reasons." + ], + "mode": { + "backend_verified": false, + "declared_backend": "FAKE_HUNTER", + "gpu_arms": "NOT_RUN", + "real_mirror_cpu": "NOT_ESTABLISHED" + }, + "not_run": [ + "gpu-stub.objects", + "gpu-stub.vlm", + "gpu-stub.dense" + ], + "run_id": "6d9d8505f2ea1312", + "schema": "hunter-local-ingest/summary/2", + "total": 29, + "verdict": "PASS" +} diff --git a/tools/hunter-local-ingest/evidence/23d5fc9/README.md b/tools/hunter-local-ingest/evidence/23d5fc9/README.md new file mode 100644 index 000000000..6639f73e1 --- /dev/null +++ b/tools/hunter-local-ingest/evidence/23d5fc9/README.md @@ -0,0 +1,25 @@ +# Receipts from the installed package at 23d5fc9 + +These four run directories come from the wheel built out of commit +`23d5fc9f8f47308b4ac69e1c0c85aa12434d111b` +(sha256 `90eeb7e4f89c42459c9bca3118db43e219f3fffccfb6e2ca20d8742811967ed7`), +installed non-editable into a scratch venv and run as console scripts from a +directory outside the source tree. The installed package's source digest, +`a3df65c9ef00ded7ec00a6a43d6d5f08d27154d147ee49af0837cb554cfc54bc`, equals the +digest of the committed `src/hunter_local_ingest`, and each manifest records it +as `client.source_sha256`. The plan is `hunter-gen-plan --seed 1` (plan file +sha256 `eabf28a3…692f`); it is not committed because the seed reproduces it. + +| Run | Endpoint | Exit | Verdict | What it shows | +| --- | --- | --- | --- | --- | +| `selfcheck/` | in-process fake, fault round, no-op restart | 0 | PASS | 26 PASS rows labeled FAKE_HUNTER; GPU arms NOT_RUN | +| `real-api-unreachable/` | declared `REAL_API`, nothing listening | 4 | BLOCKED | an absent backend is 13 BLOCKED rows and a BLOCKED trace check, never a pass | +| `mutation-commits-tampered/` | fake that commits tampered bytes | 1 | FAIL | both tamper controls and the trace check fail; everything else passes | +| `canary-responses/` | fake that plants a marker in every response | 0 | PASS | the marker in `index.json` occurs 0 times in the run's files | + +None of these runs touched a real backend, a GPU or a phone. + +`index.json` lists every artifact's sha256, each chain head, the exit codes, +and the result of `hunter-verify-run` on the sealed originals (all OK). Git +checks files out writable, so on these copies `hunter-verify-run` also reports +`not sealed (writable)`; run `chmod -R a-w ` first to compare the rest. diff --git a/tools/hunter-local-ingest/evidence/23d5fc9/canary-responses/canary-20261012T063545Z-6057c5af4f034318/checks.jsonl b/tools/hunter-local-ingest/evidence/23d5fc9/canary-responses/canary-20261012T063545Z-6057c5af4f034318/checks.jsonl new file mode 100644 index 000000000..5e4eea239 --- /dev/null +++ b/tools/hunter-local-ingest/evidence/23d5fc9/canary-responses/canary-20261012T063545Z-6057c5af4f034318/checks.jsonl @@ -0,0 +1,17 @@ +{"expected": "an HTTP 2xx answer with status ok", "id": "lifecycle.health", "observed": {"contract": {"status": "ok"}, "http": {"attempts": 1, "body_bytes": 84, "body_sha256": "8a50fd3ecfb8", "elapsed_ms": 1, "fields": ["status"], "http_status": 200, "shape": "object"}, "violations": []}, "oracle": "tools/integration-viewer reads GET /v1/healthz; HouseScanKit never calls it", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:45.636Z"} +{"expected": "2xx, a captureId and a published capture status", "id": "lifecycle.create", "observed": {"contract": {"captureId": "id:d4b0af78c405", "maxBatch": 50, "status": "uploading", "unexpected_keys": {"count": 1, "digest": "unexpected-keys:2f8dab7e6e39"}}, "http": {"attempts": 1, "body_bytes": 170, "body_sha256": "2dcd740c3024", "elapsed_ms": 0, "fields": ["captureId", "status", "upload"], "http_status": 201, "shape": "object"}, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.create: POST captures with Idempotency-Key=packetId; the answer decodes as CaptureAPI.CreateResponse", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:45.637Z"} +{"expected": "every requested path answered exactly once, no other path, each committed or given a usable PUT target", "id": "lifecycle.register", "observed": {"batches": [{"contract": {"files": [{"path": "synthetic/scan00.bin", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "synthetic/scan01.bin", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "synthetic/scan02.bin", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "streams/arkit_poses.csv.gz", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "streams/imu_raw.csv.gz", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}], "unexpected_keys": {"count": 1, "digest": "unexpected-keys:2f8dab7e6e39"}}, "http": {"attempts": 1, "body_bytes": 1321, "body_sha256": "dd74d8804888", "elapsed_ms": 0, "fields": ["files"], "http_status": 200, "shape": "object"}, "violations": []}], "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.register: the answer decodes as RegisterResponse and is applied by path; a target needs method PUT and a URL that passes uploadURLProblem", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:45.638Z"} +{"expected": "2xx for every file that got a target", "id": "lifecycle.upload", "observed": {"uploads": [{"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 1, "fields": [], "http_status": 200, "path": "synthetic/scan00.bin", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 1, "fields": [], "http_status": 200, "path": "synthetic/scan01.bin", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "synthetic/scan02.bin", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "streams/arkit_poses.csv.gz", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "streams/imu_raw.csv.gz", "shape": "empty"}]}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.put + ScopedCaptureHTTP.upload: exactly the signed headers, never Authorization", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:45.643Z"} +{"expected": "committed equals the uploaded set; notFound and mismatch empty; every declared path committed by register or commit", "id": "lifecycle.commit", "observed": {"batches": [{"contract": {"committed": ["synthetic/scan00.bin", "synthetic/scan01.bin", "synthetic/scan02.bin", "streams/arkit_poses.csv.gz", "streams/imu_raw.csv.gz"], "mismatch": [], "notFound": [], "unexpected_keys": {"count": 1, "digest": "unexpected-keys:2f8dab7e6e39"}}, "http": {"attempts": 1, "body_bytes": 243, "body_sha256": "3c7491f19e0e", "elapsed_ms": 0, "fields": ["committed", "mismatch", "notFound"], "http_status": 200, "shape": "object"}, "violations": []}], "committed_total": 5, "declared": 5, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.commit: only a commit acknowledges a file; CommitResponse carries committed, notFound and mismatch", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:45.644Z"} +{"expected": "2xx, a runId, a published status, no missing file", "id": "lifecycle.finalize", "observed": {"contract": {"missing": [], "runId": "id:6534ed79f0e0", "status": "processing", "unexpected_keys": {"count": 1, "digest": "unexpected-keys:2f8dab7e6e39"}}, "http": {"attempts": 1, "body_bytes": 154, "body_sha256": "b0bc18c6e426", "elapsed_ms": 0, "fields": ["missing", "runId", "status"], "http_status": 202, "shape": "object"}, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.finalize: X-Packet-Sha256 and Idempotency-Key=packetId; the answer decodes as FinalizeResponse", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:45.645Z"} +{"expected": "a terminal status within the budget, every answer contract-shaped", "id": "lifecycle.events", "observed": {"answers": 1, "finalize_retries": 0, "last": {"contract": {"events": [{"data": {"runId": "id:6534ed79f0e0", "runId_matches": true, "stage": "unrecognized:adb2879dee9c"}, "seq": 1, "type": "unrecognized:adb2879dee9c"}], "next": 1, "status": "complete", "unexpected_keys": {"count": 1, "digest": "unexpected-keys:2f8dab7e6e39"}}, "http": {"attempts": 1, "body_bytes": 293, "body_sha256": "fec5d5924143", "elapsed_ms": 0, "fields": ["events", "next", "status"], "http_status": 200, "shape": "object"}, "violations": []}}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.pollEvents: EventsResponse until CaptureAPI.terminalStatuses; next never moves back; a verdict names this run; retry_finalize re-sends the packet", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:45.645Z"} +{"expected": "a decodable result for this run whose status matches the terminal event status", "id": "lifecycle.result", "observed": {"contract": {"criteria": null, "has_preview_url": true, "memberActions": 0, "outcome": {"kind": "eligible", "reasons": 0}, "runId": "id:6534ed79f0e0", "status": "complete", "unexpected_keys": {"count": 1, "digest": "unexpected-keys:2f8dab7e6e39"}, "viewsNeeded": 0}, "http": {"attempts": 1, "body_bytes": 394, "body_sha256": "641e76ec3436", "elapsed_ms": 0, "fields": ["memberActions", "outcome", "previewUrl", "runId", "status", "viewsNeeded"], "http_status": 200, "shape": "object"}, "not_ready_reads": 0, "run_matches": true, "status_matches": true, "terminal_status": "complete", "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.fetchResult: the whole body decodes as CaptureResult.Response, its runId is the finalized run, and a null outcome is final only under statusesWithoutOutcome", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:45.646Z"} +{"expected": "both creates 2xx with the same captureId", "id": "control.idempotent-create", "observed": {"first": {"contract": {"captureId": "id:349237f58dc7", "maxBatch": 50, "status": "uploading", "unexpected_keys": {"count": 1, "digest": "unexpected-keys:2f8dab7e6e39"}}, "http": {"attempts": 1, "body_bytes": 170, "body_sha256": "8139f362132a", "elapsed_ms": 0, "fields": ["captureId", "status", "upload"], "http_status": 201, "shape": "object"}, "violations": []}, "same_capture": true, "second": {"contract": {"captureId": "id:349237f58dc7", "maxBatch": 50, "status": "uploading", "unexpected_keys": {"count": 1, "digest": "unexpected-keys:2f8dab7e6e39"}}, "http": {"attempts": 1, "body_bytes": 170, "body_sha256": "8139f362132a", "elapsed_ms": 0, "fields": ["captureId", "status", "upload"], "http_status": 200, "shape": "object"}, "violations": []}}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.start: create is bound to Idempotency-Key=packetId, so a repeated create with the same bytes names the same capture", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:45.647Z"} +{"expected": "intact files committed; the flipped file in mismatch or notFound, or its PUT refused, and never committed", "id": "control.corrupt-upload", "observed": {"contract": {"committed": ["synthetic/scan01.bin", "synthetic/scan02.bin", "streams/arkit_poses.csv.gz", "streams/imu_raw.csv.gz"], "mismatch": ["synthetic/scan00.bin"], "notFound": [], "unexpected_keys": {"count": 1, "digest": "unexpected-keys:2f8dab7e6e39"}}, "http": {"attempts": 1, "body_bytes": 241, "body_sha256": "3ec92debc35f", "elapsed_ms": 0, "fields": ["committed", "mismatch", "notFound"], "http_status": 200, "shape": "object"}, "intact_committed": true, "tampered": "synthetic/scan00.bin", "tampered_committed": false, "tampered_put_status": 200, "tampered_reported": true, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CommitResponse separates committed from mismatch/notFound; one file's bytes are flipped after its digest was registered", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:45.652Z"} +{"expected": "intact files committed; the truncated file in mismatch or notFound, or its PUT refused, and never committed", "id": "control.truncated-upload", "observed": {"contract": {"committed": ["synthetic/scan01.bin", "synthetic/scan02.bin", "streams/arkit_poses.csv.gz", "streams/imu_raw.csv.gz"], "mismatch": ["synthetic/scan00.bin"], "notFound": [], "unexpected_keys": {"count": 1, "digest": "unexpected-keys:2f8dab7e6e39"}}, "http": {"attempts": 1, "body_bytes": 241, "body_sha256": "3ec92debc35f", "elapsed_ms": 0, "fields": ["committed", "mismatch", "notFound"], "http_status": 200, "shape": "object"}, "intact_committed": true, "tampered": "synthetic/scan00.bin", "tampered_committed": false, "tampered_put_status": 200, "tampered_reported": true, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CommitResponse separates committed from mismatch/notFound; one file loses its last byte after its digest was registered", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:45.658Z"} +{"expected": "404 with error code capture_not_found for an id the harness invented", "id": "control.wrong-capture", "observed": {"capture": "id:1976512104be", "errors": {"codes": ["capture_not_found"]}, "http": {"attempts": 1, "body_bytes": 170, "body_sha256": "501aabab45d4", "elapsed_ms": 0, "fields": ["errors"], "http_status": 404, "shape": "object"}}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.captureGone: an unknown capture answers 404 capture_not_found", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:45.659Z"} +{"expected": "every traced check present and PASS with the traced status class and fields", "id": "trace.expected-lifecycle-v2", "observed": {"compared": 12, "disagreements": [], "not_comparable": []}, "oracle": "frozen expected trace traces/expected-lifecycle-v2.jsonl, written from the published contract", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:45.660Z"} +{"expected": "after a successful restart the capture still reports its terminal status and run", "id": "control.restart-recovery", "observed": {"note": "restart-not-configured"}, "oracle": "operator restart command, then the baseline capture is read again over the published events and result routes", "status": "NOT_RUN", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:45.660Z"} +{"expected": "not run", "id": "gpu-stub.objects", "observed": {"note": "gpu-not-authorized"}, "oracle": "GPU-dependent arms are named and never executed by this harness", "status": "NOT_RUN", "transport": "GPU_STUB", "ts": "2026-10-12T06:35:45.660Z"} +{"expected": "not run", "id": "gpu-stub.vlm", "observed": {"note": "gpu-not-authorized"}, "oracle": "GPU-dependent arms are named and never executed by this harness", "status": "NOT_RUN", "transport": "GPU_STUB", "ts": "2026-10-12T06:35:45.660Z"} +{"expected": "not run", "id": "gpu-stub.dense", "observed": {"note": "gpu-not-authorized"}, "oracle": "GPU-dependent arms are named and never executed by this harness", "status": "NOT_RUN", "transport": "GPU_STUB", "ts": "2026-10-12T06:35:45.661Z"} diff --git a/tools/hunter-local-ingest/evidence/23d5fc9/canary-responses/canary-20261012T063545Z-6057c5af4f034318/privacy-chain.jsonl b/tools/hunter-local-ingest/evidence/23d5fc9/canary-responses/canary-20261012T063545Z-6057c5af4f034318/privacy-chain.jsonl new file mode 100644 index 000000000..d7b9e0ab2 --- /dev/null +++ b/tools/hunter-local-ingest/evidence/23d5fc9/canary-responses/canary-20261012T063545Z-6057c5af4f034318/privacy-chain.jsonl @@ -0,0 +1,4 @@ +{"artifact": "run-manifest.json", "at": "2026-10-12T06:35:45.633Z", "bytes": 3454, "chain_sha256": "b9cd3a4ef555aaad32baa9b1817bf7647e1da6d9648dae706909505c19d17afc", "sha256": "5a08eacd1a928ebe7c6d30232bef7bbd29148fe61211433661e9888ea77d056e"} +{"artifact": "checks.jsonl", "at": "2026-10-12T06:35:45.661Z", "bytes": 12875, "chain_sha256": "4cec23d81cae93a55e1d1712a987b784d176b6dcab7283080b54560606472e34", "sha256": "1e6431f219597647b4e30c07e1707b93f9db65fe5a14e6f0edf537ad50825a27"} +{"artifact": "summary.json", "at": "2026-10-12T06:35:45.661Z", "bytes": 1366, "chain_sha256": "d6bc7a57f96b5264df8c9ae93401024ba48eced9d80f688dfc15a7f888344695", "sha256": "bc9feea390cb4dfe421fe1f35186254dcbd8079cab146281406dfe5c04b5e572"} +{"artifact": "privacy-screen.json", "at": "2026-10-12T06:35:45.667Z", "bytes": 238, "chain_sha256": "eb0784747aec6ea4982b5602442bbc01c517176e5e3e3ad292dfbf75de7fa8bf", "sha256": "0a5c8284f7f4409a8a92e96d49c546eac39937185b75106224dbae5727b569a6"} diff --git a/tools/hunter-local-ingest/evidence/23d5fc9/canary-responses/canary-20261012T063545Z-6057c5af4f034318/privacy-screen.json b/tools/hunter-local-ingest/evidence/23d5fc9/canary-responses/canary-20261012T063545Z-6057c5af4f034318/privacy-screen.json new file mode 100644 index 000000000..258991295 --- /dev/null +++ b/tools/hunter-local-ingest/evidence/23d5fc9/canary-responses/canary-20261012T063545Z-6057c5af4f034318/privacy-screen.json @@ -0,0 +1,12 @@ +{ + "clean": true, + "findings": [], + "finished_utc": "2026-10-12T06:35:45.666Z", + "missing": [], + "schema": "hunter-local-ingest/privacy-screen/2", + "screened": [ + "run-manifest.json", + "checks.jsonl", + "summary.json" + ] +} diff --git a/tools/hunter-local-ingest/evidence/23d5fc9/canary-responses/canary-20261012T063545Z-6057c5af4f034318/run-manifest.json b/tools/hunter-local-ingest/evidence/23d5fc9/canary-responses/canary-20261012T063545Z-6057c5af4f034318/run-manifest.json new file mode 100644 index 000000000..0ad903f9f --- /dev/null +++ b/tools/hunter-local-ingest/evidence/23d5fc9/canary-responses/canary-20261012T063545Z-6057c5af4f034318/run-manifest.json @@ -0,0 +1,109 @@ +{ + "backend": { + "declared_mode": "FAKE_HUNTER", + "declared_ref": null, + "verified": false + }, + "client": { + "declared_ref": null, + "git": null, + "interface": "2.0.0", + "package_version": "0.2.0", + "source_sha256": "a3df65c9ef00ded7ec00a6a43d6d5f08d27154d147ee49af0837cb554cfc54bc" + }, + "command": [ + "--endpoint", + "127.0.0.1:61710", + "--plan-file", + "", + "--out", + "", + "--label", + "canary", + "--backend-mode", + "FAKE_HUNTER", + "--poll-interval-s", + "0.05", + "--events-wait-s", + "0", + "--retry-backoff-s", + "0.0", + "--result-budget-s", + "30.0" + ], + "created_utc": "2026-10-12T06:35:45.625Z", + "endpoint": "127.0.0.1:61710", + "fixture": { + "create_sha256": "9c2dd5f33bb70b7199e85f165e87602986faa7f6b5beaee6f55db4f1f9edce97", + "files": [ + { + "bytes": 65536, + "contentType": "application/octet-stream", + "path": "synthetic/scan00.bin", + "role": "other", + "sha256": "a1ca0aa5e471b98beddf42738d706871542520398ced6f3ed81008e8c9812d85" + }, + { + "bytes": 65536, + "contentType": "application/octet-stream", + "path": "synthetic/scan01.bin", + "role": "other", + "sha256": "ef4380c88a7e0a2df7506640f6b435b153122e01070d7570870ebd2d3367d4be" + }, + { + "bytes": 65536, + "contentType": "application/octet-stream", + "path": "synthetic/scan02.bin", + "role": "other", + "sha256": "3fda1dfcabd6f77b655435c16a6c7b75d5f2f2b4ef9dccd814fede0f2b69e1f1" + }, + { + "bytes": 9793, + "contentType": "application/gzip", + "path": "streams/arkit_poses.csv.gz", + "role": "stream", + "sha256": "a23bcec6f6829c053e7bc1871999ca7b1a5e88639b5a6cde56afc655d3447388" + }, + { + "bytes": 9443, + "contentType": "application/gzip", + "path": "streams/imu_raw.csv.gz", + "role": "stream", + "sha256": "ae96d9008b71882aeb0dbc1c5463897aa9c316fbda28d5503b4676e0bd85a161" + } + ], + "format_version": 2, + "generator": "gen_synthetic_packet", + "packet_id": "synthetic-000001", + "packet_sha256": "9ab561f503ef3dc0c0e5b007157ab40c803d5b43dc38136285a72ab77acd17d1", + "plan_file_sha256": "eabf28a3f818ee22d38cec91ad6d85af6921f5cb45156378a007475368ab692f", + "plan_sha256": "50f73a67aeb28e5e0c41f40946958a2806024f75ae56dda1384025ccd0a8e4ac", + "seed": 1 + }, + "label": "canary", + "origin_note": "Derived from published client behavior in HouseScanKit upload and result sources at alpha 263827ef. No private source, schema, spec, log or credential material appears in this package or its receipts.", + "restart": { + "argv": [], + "configured": false, + "timeout_s": 120.0 + }, + "run_id": "6057c5af4f034318", + "runtime": { + "cpus": 12, + "implementation": "CPython", + "machine": "arm64", + "python": "3.13.12", + "release": "25.6.0", + "system": "Darwin" + }, + "sanitization": "Every value here passed the typed export schema before it was written: published enum words, package constants, digests, bounded numbers, and the plan's own synthetic paths and packet ids. A pattern screen then ran over the written files.", + "schema": "hunter-local-ingest/run-manifest/2", + "settings": { + "events_wait_s": 0, + "max_retries": 2, + "poll_interval_s": 0.05, + "result_budget_s": 30.0, + "retry_backoff_s": 0.0, + "with_faults": false + } +} diff --git a/tools/hunter-local-ingest/evidence/23d5fc9/canary-responses/canary-20261012T063545Z-6057c5af4f034318/summary.json b/tools/hunter-local-ingest/evidence/23d5fc9/canary-responses/canary-20261012T063545Z-6057c5af4f034318/summary.json new file mode 100644 index 000000000..a2cfccc19 --- /dev/null +++ b/tools/hunter-local-ingest/evidence/23d5fc9/canary-responses/canary-20261012T063545Z-6057c5af4f034318/summary.json @@ -0,0 +1,40 @@ +{ + "artifacts": { + "checks.jsonl": "1e6431f219597647b4e30c07e1707b93f9db65fe5a14e6f0edf537ad50825a27", + "run-manifest.json": "5a08eacd1a928ebe7c6d30232bef7bbd29148fe61211433661e9888ea77d056e" + }, + "blocked": [], + "counts_by_transport": { + "FAKE_HUNTER": { + "NOT_RUN": 1, + "PASS": 13 + }, + "GPU_STUB": { + "NOT_RUN": 3 + } + }, + "failed": [], + "finished_utc": "2026-10-12T06:35:45.661Z", + "lead_questions": [ + "Amendment semantics: does the published contract allow amending a registered capture, and with which route and headers?", + "Local-run auth mode: which credential form does the local backend expect from the published client? The client can send a bearer token on API routes only; no CLI flag supplies one yet.", + "Clock and expiry authority: whose clock governs capture expiry on the local backend?", + "Homeowner text: confirm that receipts may carry outcome kinds and counts but never messages, prompts or reasons." + ], + "mode": { + "backend_verified": false, + "declared_backend": "FAKE_HUNTER", + "gpu_arms": "NOT_RUN", + "real_mirror_cpu": "NOT_ESTABLISHED" + }, + "not_run": [ + "control.restart-recovery", + "gpu-stub.objects", + "gpu-stub.vlm", + "gpu-stub.dense" + ], + "run_id": "6057c5af4f034318", + "schema": "hunter-local-ingest/summary/2", + "total": 17, + "verdict": "PASS" +} diff --git a/tools/hunter-local-ingest/evidence/23d5fc9/index.json b/tools/hunter-local-ingest/evidence/23d5fc9/index.json new file mode 100644 index 000000000..247eda65e --- /dev/null +++ b/tools/hunter-local-ingest/evidence/23d5fc9/index.json @@ -0,0 +1,156 @@ +{ + "committed_source_sha256": "a3df65c9ef00ded7ec00a6a43d6d5f08d27154d147ee49af0837cb554cfc54bc", + "installed_package_under_venv": true, + "installed_source_sha256": "a3df65c9ef00ded7ec00a6a43d6d5f08d27154d147ee49af0837cb554cfc54bc", + "plan_sha256": "eabf28a3f818ee22d38cec91ad6d85af6921f5cb45156378a007475368ab692f", + "runs": { + "canary-responses": { + "artifacts": { + "checks.jsonl": "1e6431f219597647b4e30c07e1707b93f9db65fe5a14e6f0edf537ad50825a27", + "privacy-chain.jsonl": "c444901f140d49f001335a2298d2ec2d3dbe34e9d85a18568ac7621ac02bed2d", + "privacy-screen.json": "0a5c8284f7f4409a8a92e96d49c546eac39937185b75106224dbae5727b569a6", + "run-manifest.json": "5a08eacd1a928ebe7c6d30232bef7bbd29148fe61211433661e9888ea77d056e", + "summary.json": "bc9feea390cb4dfe421fe1f35186254dcbd8079cab146281406dfe5c04b5e572" + }, + "blocked": [], + "canary": "CANARY-evidence-c792c56c7cf1", + "canary_occurrences": 0, + "chain_head": "eb0784747aec6ea4982b5602442bbc01c517176e5e3e3ad292dfbf75de7fa8bf", + "counts_by_transport": { + "FAKE_HUNTER": { + "NOT_RUN": 1, + "PASS": 13 + }, + "GPU_STUB": { + "NOT_RUN": 3 + } + }, + "exit_code": 0, + "failed": [], + "not_run": [ + "control.restart-recovery", + "gpu-stub.objects", + "gpu-stub.vlm", + "gpu-stub.dense" + ], + "run_dir": "canary-20261012T063545Z-6057c5af4f034318", + "verdict": "PASS", + "verify_exit": 0, + "verify_last_line": "verify: OK" + }, + "mutation-commits-tampered": { + "artifacts": { + "checks.jsonl": "d0f2a5f2b85c1a2dddcd406c463af1d9af1bd8b3ba748fed568e00da97267b14", + "privacy-chain.jsonl": "634a21076a15ef42c27f10a9777d1f72438ff388659d3c27f50d79c81ab9f5a9", + "privacy-screen.json": "80cfbeab2565b3ca214ec7cb790734f9b31dede98b1d1a88458b56e79510282a", + "run-manifest.json": "c5304fd90f0710b11a8010f31ef4a44d1d4e959f2ce897796c07605edd041095", + "summary.json": "efa3892645cd476d2a316659e14410acd0b18bb2daf81bbfc4ef905eb2a41c7e" + }, + "blocked": [], + "chain_head": "01c87977bb2841a287db0af6d4afedf1656cfb11ec5031dfa5e994937b6258ab", + "counts_by_transport": { + "FAKE_HUNTER": { + "FAIL": 3, + "NOT_RUN": 1, + "PASS": 22 + }, + "GPU_STUB": { + "NOT_RUN": 3 + } + }, + "exit_code": 1, + "failed": [ + "control.corrupt-upload", + "control.truncated-upload", + "trace.expected-lifecycle-v2" + ], + "not_run": [ + "control.restart-recovery", + "gpu-stub.objects", + "gpu-stub.vlm", + "gpu-stub.dense" + ], + "run_dir": "mutation-20261012T063542Z-8079f0541bad6349", + "verdict": "FAIL", + "verify_exit": 0, + "verify_last_line": "verify: OK" + }, + "real-api-unreachable": { + "artifacts": { + "checks.jsonl": "f312e869a4d928920c8379720a6b55f2b6e7ae1a664bacac893198e0a431f36e", + "privacy-chain.jsonl": "7d14a255d744f1e642ac74f48120d83fc0a8afd0dd63830c3c59365514935fbb", + "privacy-screen.json": "3d27e7b4924bb18891da18e85cd1014c363123f1af9dbfc0a46c02a619a16279", + "run-manifest.json": "a664736c3c8a9732439a0d7cb6d8d16d6255bfb0d6f93fd082147955b8a8e87c", + "summary.json": "a4ddb441b513a0c292aeac860dcfa6319242aa33036974daef88f24a66c068a2" + }, + "blocked": [ + "lifecycle.health", + "lifecycle.create", + "lifecycle.register", + "lifecycle.upload", + "lifecycle.commit", + "lifecycle.finalize", + "lifecycle.events", + "lifecycle.result", + "control.idempotent-create", + "control.corrupt-upload", + "control.truncated-upload", + "control.wrong-capture", + "trace.expected-lifecycle-v2" + ], + "chain_head": "2cd622b2d41fc39946dd979ff3b8636095e968b802c1c2e841c22204c928ce0f", + "counts_by_transport": { + "GPU_STUB": { + "NOT_RUN": 3 + }, + "REAL_API": { + "BLOCKED": 13, + "NOT_RUN": 1 + } + }, + "exit_code": 4, + "failed": [], + "not_run": [ + "control.restart-recovery", + "gpu-stub.objects", + "gpu-stub.vlm", + "gpu-stub.dense" + ], + "run_dir": "real-api-unreachable-20261012T063532Z-76788276ac9cc42a", + "verdict": "BLOCKED", + "verify_exit": 0, + "verify_last_line": "verify: OK" + }, + "selfcheck": { + "artifacts": { + "checks.jsonl": "13646460c99be9aba9b2ad4cd8ed16e2666b0a0553ff9142c2cac66a6aa15880", + "privacy-chain.jsonl": "577c1de283d96cdbc64d158233bfe418fe4ad2b82b796ffb5fc86d9b017018eb", + "privacy-screen.json": "539f956be1187ac5df7a83175bcff0a82128f88f1ffba8c3911edaef4b6f8490", + "run-manifest.json": "38149b47418ff557717f90319f64a392d5344a90c7e085127bf3cb0c3bd00fc5", + "summary.json": "f2e35d9f0a711dfd96e777d089fc19dbee266e8c0d53c46b21fe3c0c304f8ed5" + }, + "blocked": [], + "chain_head": "5ba0524216350e67402232b202308ff2a842911b9f50d76da15388df55eae00c", + "counts_by_transport": { + "FAKE_HUNTER": { + "PASS": 26 + }, + "GPU_STUB": { + "NOT_RUN": 3 + } + }, + "exit_code": 0, + "failed": [], + "not_run": [ + "gpu-stub.objects", + "gpu-stub.vlm", + "gpu-stub.dense" + ], + "run_dir": "selfcheck-20261012T063528Z-b8e3889cea7aa704", + "stdout_last": "selfcheck: PASS", + "verdict": "PASS", + "verify_exit": 0, + "verify_last_line": "verify: OK" + } + } +} diff --git a/tools/hunter-local-ingest/evidence/23d5fc9/mutation-commits-tampered/mutation-20261012T063542Z-8079f0541bad6349/checks.jsonl b/tools/hunter-local-ingest/evidence/23d5fc9/mutation-commits-tampered/mutation-20261012T063542Z-8079f0541bad6349/checks.jsonl new file mode 100644 index 000000000..2f0032bcc --- /dev/null +++ b/tools/hunter-local-ingest/evidence/23d5fc9/mutation-commits-tampered/mutation-20261012T063542Z-8079f0541bad6349/checks.jsonl @@ -0,0 +1,29 @@ +{"expected": "an HTTP 2xx answer with status ok", "id": "lifecycle.health", "observed": {"contract": {"status": "ok"}, "http": {"attempts": 1, "body_bytes": 16, "body_sha256": "08e2c358ce13", "elapsed_ms": 1, "fields": ["status"], "http_status": 200, "shape": "object"}, "violations": []}, "oracle": "tools/integration-viewer reads GET /v1/healthz; HouseScanKit never calls it", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:42.332Z"} +{"expected": "2xx, a captureId and a published capture status", "id": "lifecycle.create", "observed": {"contract": {"captureId": "id:fd102437f369", "maxBatch": 50, "status": "uploading"}, "http": {"attempts": 1, "body_bytes": 78, "body_sha256": "8edf48cf4ce9", "elapsed_ms": 0, "fields": ["captureId", "status", "upload"], "http_status": 201, "shape": "object"}, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.create: POST captures with Idempotency-Key=packetId; the answer decodes as CaptureAPI.CreateResponse", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:42.333Z"} +{"expected": "every requested path answered exactly once, no other path, each committed or given a usable PUT target", "id": "lifecycle.register", "observed": {"batches": [{"contract": {"files": [{"path": "synthetic/scan00.bin", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "synthetic/scan01.bin", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "synthetic/scan02.bin", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "streams/arkit_poses.csv.gz", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "streams/imu_raw.csv.gz", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}]}, "http": {"attempts": 1, "body_bytes": 1253, "body_sha256": "11865e145f78", "elapsed_ms": 0, "fields": ["files"], "http_status": 200, "shape": "object"}, "violations": []}], "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.register: the answer decodes as RegisterResponse and is applied by path; a target needs method PUT and a URL that passes uploadURLProblem", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:42.334Z"} +{"expected": "2xx for every file that got a target", "id": "lifecycle.upload", "observed": {"uploads": [{"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "synthetic/scan00.bin", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "synthetic/scan01.bin", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "synthetic/scan02.bin", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "streams/arkit_poses.csv.gz", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "streams/imu_raw.csv.gz", "shape": "empty"}]}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.put + ScopedCaptureHTTP.upload: exactly the signed headers, never Authorization", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:42.338Z"} +{"expected": "committed equals the uploaded set; notFound and mismatch empty; every declared path committed by register or commit", "id": "lifecycle.commit", "observed": {"batches": [{"contract": {"committed": ["synthetic/scan00.bin", "synthetic/scan01.bin", "synthetic/scan02.bin", "streams/arkit_poses.csv.gz", "streams/imu_raw.csv.gz"], "mismatch": [], "notFound": []}, "http": {"attempts": 1, "body_bytes": 175, "body_sha256": "ab0d647d58c4", "elapsed_ms": 0, "fields": ["committed", "mismatch", "notFound"], "http_status": 200, "shape": "object"}, "violations": []}], "committed_total": 5, "declared": 5, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.commit: only a commit acknowledges a file; CommitResponse carries committed, notFound and mismatch", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:42.339Z"} +{"expected": "2xx, a runId, a published status, no missing file", "id": "lifecycle.finalize", "observed": {"contract": {"missing": [], "runId": "id:492e113d2d27", "status": "processing"}, "http": {"attempts": 1, "body_bytes": 62, "body_sha256": "425e9d06a56d", "elapsed_ms": 0, "fields": ["missing", "runId", "status"], "http_status": 202, "shape": "object"}, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.finalize: X-Packet-Sha256 and Idempotency-Key=packetId; the answer decodes as FinalizeResponse", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:42.339Z"} +{"expected": "a terminal status within the budget, every answer contract-shaped", "id": "lifecycle.events", "observed": {"answers": 1, "finalize_retries": 0, "last": {"contract": {"events": [{"data": {"runId": "id:492e113d2d27", "runId_matches": true}, "seq": 1, "type": "verdict_ready"}], "next": 1, "status": "complete"}, "http": {"attempts": 1, "body_bytes": 145, "body_sha256": "f7919284ecb6", "elapsed_ms": 0, "fields": ["events", "next", "status"], "http_status": 200, "shape": "object"}, "violations": []}}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.pollEvents: EventsResponse until CaptureAPI.terminalStatuses; next never moves back; a verdict names this run; retry_finalize re-sends the packet", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:42.340Z"} +{"expected": "a decodable result for this run whose status matches the terminal event status", "id": "lifecycle.result", "observed": {"contract": {"criteria": null, "has_preview_url": false, "memberActions": 0, "outcome": {"kind": "eligible", "reasons": 0}, "runId": "id:492e113d2d27", "status": "complete", "viewsNeeded": 0}, "http": {"attempts": 1, "body_bytes": 227, "body_sha256": "1dc1b0ebf7a6", "elapsed_ms": 0, "fields": ["memberActions", "outcome", "runId", "status", "viewsNeeded"], "http_status": 200, "shape": "object"}, "not_ready_reads": 0, "run_matches": true, "status_matches": true, "terminal_status": "complete", "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.fetchResult: the whole body decodes as CaptureResult.Response, its runId is the finalized run, and a null outcome is final only under statusesWithoutOutcome", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:42.340Z"} +{"expected": "both creates 2xx with the same captureId", "id": "control.idempotent-create", "observed": {"first": {"contract": {"captureId": "id:b9d50067aadb", "maxBatch": 50, "status": "uploading"}, "http": {"attempts": 1, "body_bytes": 78, "body_sha256": "ec8a1ff9228b", "elapsed_ms": 0, "fields": ["captureId", "status", "upload"], "http_status": 201, "shape": "object"}, "violations": []}, "same_capture": true, "second": {"contract": {"captureId": "id:b9d50067aadb", "maxBatch": 50, "status": "uploading"}, "http": {"attempts": 1, "body_bytes": 78, "body_sha256": "ec8a1ff9228b", "elapsed_ms": 0, "fields": ["captureId", "status", "upload"], "http_status": 200, "shape": "object"}, "violations": []}}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.start: create is bound to Idempotency-Key=packetId, so a repeated create with the same bytes names the same capture", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:42.341Z"} +{"expected": "intact files committed; the flipped file in mismatch or notFound, or its PUT refused, and never committed", "id": "control.corrupt-upload", "observed": {"contract": {"committed": ["synthetic/scan00.bin", "synthetic/scan01.bin", "synthetic/scan02.bin", "streams/arkit_poses.csv.gz", "streams/imu_raw.csv.gz"], "mismatch": [], "notFound": []}, "http": {"attempts": 1, "body_bytes": 175, "body_sha256": "ab0d647d58c4", "elapsed_ms": 0, "fields": ["committed", "mismatch", "notFound"], "http_status": 200, "shape": "object"}, "intact_committed": true, "tampered": "synthetic/scan00.bin", "tampered_committed": true, "tampered_put_status": 200, "tampered_reported": false, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CommitResponse separates committed from mismatch/notFound; one file's bytes are flipped after its digest was registered", "status": "FAIL", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:42.346Z"} +{"expected": "intact files committed; the truncated file in mismatch or notFound, or its PUT refused, and never committed", "id": "control.truncated-upload", "observed": {"contract": {"committed": ["synthetic/scan00.bin", "synthetic/scan01.bin", "synthetic/scan02.bin", "streams/arkit_poses.csv.gz", "streams/imu_raw.csv.gz"], "mismatch": [], "notFound": []}, "http": {"attempts": 1, "body_bytes": 175, "body_sha256": "ab0d647d58c4", "elapsed_ms": 0, "fields": ["committed", "mismatch", "notFound"], "http_status": 200, "shape": "object"}, "intact_committed": true, "tampered": "synthetic/scan00.bin", "tampered_committed": true, "tampered_put_status": 200, "tampered_reported": false, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CommitResponse separates committed from mismatch/notFound; one file loses its last byte after its digest was registered", "status": "FAIL", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:42.350Z"} +{"expected": "404 with error code capture_not_found for an id the harness invented", "id": "control.wrong-capture", "observed": {"capture": "id:1976512104be", "errors": {"codes": ["capture_not_found"]}, "http": {"attempts": 1, "body_bytes": 43, "body_sha256": "23553eb17fe9", "elapsed_ms": 0, "fields": ["errors"], "http_status": 404, "shape": "object"}}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.captureGone: an unknown capture answers 404 capture_not_found", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:42.351Z"} +{"expected": "an HTTP 2xx answer with status ok", "id": "fault.lifecycle.health", "observed": {"contract": {"status": "ok"}, "http": {"attempts": 1, "body_bytes": 16, "body_sha256": "08e2c358ce13", "elapsed_ms": 1, "fields": ["status"], "http_status": 200, "shape": "object"}, "violations": []}, "oracle": "tools/integration-viewer reads GET /v1/healthz; HouseScanKit never calls it", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:42.354Z"} +{"expected": "2xx, a captureId and a published capture status", "id": "fault.lifecycle.create", "observed": {"contract": {"captureId": "id:d6611115894b", "maxBatch": 50, "status": "uploading"}, "http": {"attempts": 1, "body_bytes": 78, "body_sha256": "1ff5bb037620", "elapsed_ms": 111, "fields": ["captureId", "status", "upload"], "http_status": 201, "shape": "object"}, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.create: POST captures with Idempotency-Key=packetId; the answer decodes as CaptureAPI.CreateResponse", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:42.466Z"} +{"expected": "every requested path answered exactly once, no other path, each committed or given a usable PUT target", "id": "fault.lifecycle.register", "observed": {"batches": [{"contract": {"files": [{"path": "synthetic/scan00.bin", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "synthetic/scan01.bin", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "synthetic/scan02.bin", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "streams/arkit_poses.csv.gz", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "streams/imu_raw.csv.gz", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}]}, "http": {"attempts": 1, "body_bytes": 1253, "body_sha256": "35634f5b8c90", "elapsed_ms": 1, "fields": ["files"], "http_status": 200, "shape": "object"}, "violations": []}], "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.register: the answer decodes as RegisterResponse and is applied by path; a target needs method PUT and a URL that passes uploadURLProblem", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:42.468Z"} +{"expected": "2xx for every file that got a target", "id": "fault.lifecycle.upload", "observed": {"uploads": [{"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "synthetic/scan00.bin", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 1, "fields": [], "http_status": 200, "path": "synthetic/scan01.bin", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 1, "fields": [], "http_status": 200, "path": "synthetic/scan02.bin", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "streams/arkit_poses.csv.gz", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "streams/imu_raw.csv.gz", "shape": "empty"}]}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.put + ScopedCaptureHTTP.upload: exactly the signed headers, never Authorization", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:42.473Z"} +{"expected": "committed equals the uploaded set; notFound and mismatch empty; every declared path committed by register or commit", "id": "fault.lifecycle.commit", "observed": {"batches": [{"contract": {"committed": ["synthetic/scan00.bin", "synthetic/scan01.bin", "synthetic/scan02.bin", "streams/arkit_poses.csv.gz", "streams/imu_raw.csv.gz"], "mismatch": [], "notFound": []}, "http": {"attempts": 1, "body_bytes": 175, "body_sha256": "ab0d647d58c4", "elapsed_ms": 1, "fields": ["committed", "mismatch", "notFound"], "http_status": 200, "shape": "object"}, "violations": []}], "committed_total": 5, "declared": 5, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.commit: only a commit acknowledges a file; CommitResponse carries committed, notFound and mismatch", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:42.474Z"} +{"expected": "2xx, a runId, a published status, no missing file", "id": "fault.lifecycle.finalize", "observed": {"contract": {"missing": [], "runId": "id:636f557a124e", "status": "processing"}, "http": {"attempts": 1, "body_bytes": 62, "body_sha256": "cc5e4603e9bd", "elapsed_ms": 0, "fields": ["missing", "runId", "status"], "http_status": 202, "shape": "object"}, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.finalize: X-Packet-Sha256 and Idempotency-Key=packetId; the answer decodes as FinalizeResponse", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:42.475Z"} +{"expected": "a terminal status within the budget, every answer contract-shaped", "id": "fault.lifecycle.events", "observed": {"answers": 1, "finalize_retries": 0, "last": {"contract": {"events": [{"data": {"runId": "id:636f557a124e", "runId_matches": true}, "seq": 1, "type": "verdict_ready"}], "next": 1, "status": "complete"}, "http": {"attempts": 1, "body_bytes": 145, "body_sha256": "6519430bc83d", "elapsed_ms": 1, "fields": ["events", "next", "status"], "http_status": 200, "shape": "object"}, "violations": []}}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.pollEvents: EventsResponse until CaptureAPI.terminalStatuses; next never moves back; a verdict names this run; retry_finalize re-sends the packet", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:42.477Z"} +{"expected": "a decodable result for this run whose status matches the terminal event status", "id": "fault.lifecycle.result", "observed": {"contract": {"criteria": null, "has_preview_url": false, "memberActions": 0, "outcome": {"kind": "eligible", "reasons": 0}, "runId": "id:636f557a124e", "status": "complete", "viewsNeeded": 0}, "http": {"attempts": 1, "body_bytes": 227, "body_sha256": "f0543371247b", "elapsed_ms": 1, "fields": ["memberActions", "outcome", "runId", "status", "viewsNeeded"], "http_status": 200, "shape": "object"}, "not_ready_reads": 0, "run_matches": true, "status_matches": true, "terminal_status": "complete", "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.fetchResult: the whole body decodes as CaptureResult.Response, its runId is the finalized run, and a null outcome is final only under statusesWithoutOutcome", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:42.479Z"} +{"expected": "the proxy's single 503 is followed by a second attempt that creates the capture", "id": "fault.retry-transient", "observed": {"contract": {"captureId": "id:40a0732506ed", "maxBatch": 50, "status": "uploading"}, "http": {"attempts": 2, "body_bytes": 78, "body_sha256": "2350cd7a9fb2", "elapsed_ms": 2, "fields": ["captureId", "status", "upload"], "http_status": 201, "shape": "object"}, "proxy_hits": 2, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.isTransient: a 503 is retried with the same body", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:43.484Z"} +{"expected": "exactly one attempt and a reported non-2xx answer", "id": "fault.no-retry-501", "observed": {"errors": {"codes": ["harness_fault"]}, "http": {"attempts": 1, "body_bytes": 39, "body_sha256": "be37db4e697d", "elapsed_ms": 0, "fields": ["errors"], "http_status": 501, "shape": "object"}, "proxy_hits": 1}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.isTransient excludes 501", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:43.988Z"} +{"expected": "a transport error category after 1 + max_retries attempts, no capture id taken", "id": "fault.abort", "observed": {"http": {"attempts": 2, "error": "transport:remote-disconnected"}, "proxy_hits": 2}, "oracle": "an answer-less connection is a transport failure, retried a bounded number of times", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:44.494Z"} +{"expected": "a transport error category, no capture id taken", "id": "fault.truncated-response", "observed": {"http": {"attempts": 1, "error": "transport:incomplete-read"}, "proxy_hits": 1}, "oracle": "a body shorter than its Content-Length is a transport failure, never a parsed answer", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:44.998Z"} +{"expected": "every traced check present and PASS with the traced status class and fields", "id": "trace.expected-lifecycle-v2", "observed": {"compared": 12, "disagreements": [{"id": "control.corrupt-upload", "kind": "status-fail"}, {"id": "control.truncated-upload", "kind": "status-fail"}], "not_comparable": []}, "oracle": "frozen expected trace traces/expected-lifecycle-v2.jsonl, written from the published contract", "status": "FAIL", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:45.000Z"} +{"expected": "after a successful restart the capture still reports its terminal status and run", "id": "control.restart-recovery", "observed": {"note": "restart-not-configured"}, "oracle": "operator restart command, then the baseline capture is read again over the published events and result routes", "status": "NOT_RUN", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:45.000Z"} +{"expected": "not run", "id": "gpu-stub.objects", "observed": {"note": "gpu-not-authorized"}, "oracle": "GPU-dependent arms are named and never executed by this harness", "status": "NOT_RUN", "transport": "GPU_STUB", "ts": "2026-10-12T06:35:45.000Z"} +{"expected": "not run", "id": "gpu-stub.vlm", "observed": {"note": "gpu-not-authorized"}, "oracle": "GPU-dependent arms are named and never executed by this harness", "status": "NOT_RUN", "transport": "GPU_STUB", "ts": "2026-10-12T06:35:45.000Z"} +{"expected": "not run", "id": "gpu-stub.dense", "observed": {"note": "gpu-not-authorized"}, "oracle": "GPU-dependent arms are named and never executed by this harness", "status": "NOT_RUN", "transport": "GPU_STUB", "ts": "2026-10-12T06:35:45.000Z"} diff --git a/tools/hunter-local-ingest/evidence/23d5fc9/mutation-commits-tampered/mutation-20261012T063542Z-8079f0541bad6349/privacy-chain.jsonl b/tools/hunter-local-ingest/evidence/23d5fc9/mutation-commits-tampered/mutation-20261012T063542Z-8079f0541bad6349/privacy-chain.jsonl new file mode 100644 index 000000000..cbdace50a --- /dev/null +++ b/tools/hunter-local-ingest/evidence/23d5fc9/mutation-commits-tampered/mutation-20261012T063542Z-8079f0541bad6349/privacy-chain.jsonl @@ -0,0 +1,4 @@ +{"artifact": "run-manifest.json", "at": "2026-10-12T06:35:42.329Z", "bytes": 3478, "chain_sha256": "edb26153a74e9f89238d29410c63e19d76f643c43db11b91e3c5dd446c0b98e4", "sha256": "c5304fd90f0710b11a8010f31ef4a44d1d4e959f2ce897796c07605edd041095"} +{"artifact": "checks.jsonl", "at": "2026-10-12T06:35:45.000Z", "bytes": 21220, "chain_sha256": "a9aba53f04529e3beacd690201cb72a46da9b5b577340bbcd5246d8ff27f6451", "sha256": "d0f2a5f2b85c1a2dddcd406c463af1d9af1bd8b3ba748fed568e00da97267b14"} +{"artifact": "summary.json", "at": "2026-10-12T06:35:45.000Z", "bytes": 1482, "chain_sha256": "57577c402ceb7e157fec03bb27c71910d6fe79df0e6c90f1bda77d1e5e62455a", "sha256": "efa3892645cd476d2a316659e14410acd0b18bb2daf81bbfc4ef905eb2a41c7e"} +{"artifact": "privacy-screen.json", "at": "2026-10-12T06:35:45.008Z", "bytes": 238, "chain_sha256": "01c87977bb2841a287db0af6d4afedf1656cfb11ec5031dfa5e994937b6258ab", "sha256": "80cfbeab2565b3ca214ec7cb790734f9b31dede98b1d1a88458b56e79510282a"} diff --git a/tools/hunter-local-ingest/evidence/23d5fc9/mutation-commits-tampered/mutation-20261012T063542Z-8079f0541bad6349/privacy-screen.json b/tools/hunter-local-ingest/evidence/23d5fc9/mutation-commits-tampered/mutation-20261012T063542Z-8079f0541bad6349/privacy-screen.json new file mode 100644 index 000000000..95a55b89a --- /dev/null +++ b/tools/hunter-local-ingest/evidence/23d5fc9/mutation-commits-tampered/mutation-20261012T063542Z-8079f0541bad6349/privacy-screen.json @@ -0,0 +1,12 @@ +{ + "clean": true, + "findings": [], + "finished_utc": "2026-10-12T06:35:45.008Z", + "missing": [], + "schema": "hunter-local-ingest/privacy-screen/2", + "screened": [ + "run-manifest.json", + "checks.jsonl", + "summary.json" + ] +} diff --git a/tools/hunter-local-ingest/evidence/23d5fc9/mutation-commits-tampered/mutation-20261012T063542Z-8079f0541bad6349/run-manifest.json b/tools/hunter-local-ingest/evidence/23d5fc9/mutation-commits-tampered/mutation-20261012T063542Z-8079f0541bad6349/run-manifest.json new file mode 100644 index 000000000..567512938 --- /dev/null +++ b/tools/hunter-local-ingest/evidence/23d5fc9/mutation-commits-tampered/mutation-20261012T063542Z-8079f0541bad6349/run-manifest.json @@ -0,0 +1,110 @@ +{ + "backend": { + "declared_mode": "FAKE_HUNTER", + "declared_ref": null, + "verified": false + }, + "client": { + "declared_ref": null, + "git": null, + "interface": "2.0.0", + "package_version": "0.2.0", + "source_sha256": "a3df65c9ef00ded7ec00a6a43d6d5f08d27154d147ee49af0837cb554cfc54bc" + }, + "command": [ + "--endpoint", + "127.0.0.1:61637", + "--plan-file", + "", + "--out", + "", + "--label", + "mutation", + "--backend-mode", + "FAKE_HUNTER", + "--with-faults", + "--poll-interval-s", + "0.05", + "--events-wait-s", + "0", + "--retry-backoff-s", + "0.0", + "--result-budget-s", + "30.0" + ], + "created_utc": "2026-10-12T06:35:42.321Z", + "endpoint": "127.0.0.1:61637", + "fixture": { + "create_sha256": "9c2dd5f33bb70b7199e85f165e87602986faa7f6b5beaee6f55db4f1f9edce97", + "files": [ + { + "bytes": 65536, + "contentType": "application/octet-stream", + "path": "synthetic/scan00.bin", + "role": "other", + "sha256": "a1ca0aa5e471b98beddf42738d706871542520398ced6f3ed81008e8c9812d85" + }, + { + "bytes": 65536, + "contentType": "application/octet-stream", + "path": "synthetic/scan01.bin", + "role": "other", + "sha256": "ef4380c88a7e0a2df7506640f6b435b153122e01070d7570870ebd2d3367d4be" + }, + { + "bytes": 65536, + "contentType": "application/octet-stream", + "path": "synthetic/scan02.bin", + "role": "other", + "sha256": "3fda1dfcabd6f77b655435c16a6c7b75d5f2f2b4ef9dccd814fede0f2b69e1f1" + }, + { + "bytes": 9793, + "contentType": "application/gzip", + "path": "streams/arkit_poses.csv.gz", + "role": "stream", + "sha256": "a23bcec6f6829c053e7bc1871999ca7b1a5e88639b5a6cde56afc655d3447388" + }, + { + "bytes": 9443, + "contentType": "application/gzip", + "path": "streams/imu_raw.csv.gz", + "role": "stream", + "sha256": "ae96d9008b71882aeb0dbc1c5463897aa9c316fbda28d5503b4676e0bd85a161" + } + ], + "format_version": 2, + "generator": "gen_synthetic_packet", + "packet_id": "synthetic-000001", + "packet_sha256": "9ab561f503ef3dc0c0e5b007157ab40c803d5b43dc38136285a72ab77acd17d1", + "plan_file_sha256": "eabf28a3f818ee22d38cec91ad6d85af6921f5cb45156378a007475368ab692f", + "plan_sha256": "50f73a67aeb28e5e0c41f40946958a2806024f75ae56dda1384025ccd0a8e4ac", + "seed": 1 + }, + "label": "mutation", + "origin_note": "Derived from published client behavior in HouseScanKit upload and result sources at alpha 263827ef. No private source, schema, spec, log or credential material appears in this package or its receipts.", + "restart": { + "argv": [], + "configured": false, + "timeout_s": 120.0 + }, + "run_id": "8079f0541bad6349", + "runtime": { + "cpus": 12, + "implementation": "CPython", + "machine": "arm64", + "python": "3.13.12", + "release": "25.6.0", + "system": "Darwin" + }, + "sanitization": "Every value here passed the typed export schema before it was written: published enum words, package constants, digests, bounded numbers, and the plan's own synthetic paths and packet ids. A pattern screen then ran over the written files.", + "schema": "hunter-local-ingest/run-manifest/2", + "settings": { + "events_wait_s": 0, + "max_retries": 2, + "poll_interval_s": 0.05, + "result_budget_s": 30.0, + "retry_backoff_s": 0.0, + "with_faults": true + } +} diff --git a/tools/hunter-local-ingest/evidence/23d5fc9/mutation-commits-tampered/mutation-20261012T063542Z-8079f0541bad6349/summary.json b/tools/hunter-local-ingest/evidence/23d5fc9/mutation-commits-tampered/mutation-20261012T063542Z-8079f0541bad6349/summary.json new file mode 100644 index 000000000..0e044c8fa --- /dev/null +++ b/tools/hunter-local-ingest/evidence/23d5fc9/mutation-commits-tampered/mutation-20261012T063542Z-8079f0541bad6349/summary.json @@ -0,0 +1,45 @@ +{ + "artifacts": { + "checks.jsonl": "d0f2a5f2b85c1a2dddcd406c463af1d9af1bd8b3ba748fed568e00da97267b14", + "run-manifest.json": "c5304fd90f0710b11a8010f31ef4a44d1d4e959f2ce897796c07605edd041095" + }, + "blocked": [], + "counts_by_transport": { + "FAKE_HUNTER": { + "FAIL": 3, + "NOT_RUN": 1, + "PASS": 22 + }, + "GPU_STUB": { + "NOT_RUN": 3 + } + }, + "failed": [ + "control.corrupt-upload", + "control.truncated-upload", + "trace.expected-lifecycle-v2" + ], + "finished_utc": "2026-10-12T06:35:45.000Z", + "lead_questions": [ + "Amendment semantics: does the published contract allow amending a registered capture, and with which route and headers?", + "Local-run auth mode: which credential form does the local backend expect from the published client? The client can send a bearer token on API routes only; no CLI flag supplies one yet.", + "Clock and expiry authority: whose clock governs capture expiry on the local backend?", + "Homeowner text: confirm that receipts may carry outcome kinds and counts but never messages, prompts or reasons." + ], + "mode": { + "backend_verified": false, + "declared_backend": "FAKE_HUNTER", + "gpu_arms": "NOT_RUN", + "real_mirror_cpu": "NOT_ESTABLISHED" + }, + "not_run": [ + "control.restart-recovery", + "gpu-stub.objects", + "gpu-stub.vlm", + "gpu-stub.dense" + ], + "run_id": "8079f0541bad6349", + "schema": "hunter-local-ingest/summary/2", + "total": 29, + "verdict": "FAIL" +} diff --git a/tools/hunter-local-ingest/evidence/23d5fc9/real-api-unreachable/real-api-unreachable-20261012T063532Z-76788276ac9cc42a/checks.jsonl b/tools/hunter-local-ingest/evidence/23d5fc9/real-api-unreachable/real-api-unreachable-20261012T063532Z-76788276ac9cc42a/checks.jsonl new file mode 100644 index 000000000..a7bbc168d --- /dev/null +++ b/tools/hunter-local-ingest/evidence/23d5fc9/real-api-unreachable/real-api-unreachable-20261012T063532Z-76788276ac9cc42a/checks.jsonl @@ -0,0 +1,17 @@ +{"expected": "an HTTP 2xx answer with status ok", "id": "lifecycle.health", "observed": {"note": "endpoint-unreachable"}, "oracle": "tools/integration-viewer reads GET /v1/healthz; HouseScanKit never calls it", "status": "BLOCKED", "transport": "REAL_API", "ts": "2026-10-12T06:35:42.180Z"} +{"expected": "2xx, a captureId and a published capture status", "id": "lifecycle.create", "observed": {"note": "endpoint-unreachable"}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.create: POST captures with Idempotency-Key=packetId; the answer decodes as CaptureAPI.CreateResponse", "status": "BLOCKED", "transport": "REAL_API", "ts": "2026-10-12T06:35:42.180Z"} +{"expected": "every requested path answered exactly once, no other path, each committed or given a usable PUT target", "id": "lifecycle.register", "observed": {"note": "endpoint-unreachable"}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.register: the answer decodes as RegisterResponse and is applied by path; a target needs method PUT and a URL that passes uploadURLProblem", "status": "BLOCKED", "transport": "REAL_API", "ts": "2026-10-12T06:35:42.180Z"} +{"expected": "2xx for every file that got a target", "id": "lifecycle.upload", "observed": {"note": "endpoint-unreachable"}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.put + ScopedCaptureHTTP.upload: exactly the signed headers, never Authorization", "status": "BLOCKED", "transport": "REAL_API", "ts": "2026-10-12T06:35:42.180Z"} +{"expected": "committed equals the uploaded set; notFound and mismatch empty; every declared path committed by register or commit", "id": "lifecycle.commit", "observed": {"note": "endpoint-unreachable"}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.commit: only a commit acknowledges a file; CommitResponse carries committed, notFound and mismatch", "status": "BLOCKED", "transport": "REAL_API", "ts": "2026-10-12T06:35:42.180Z"} +{"expected": "2xx, a runId, a published status, no missing file", "id": "lifecycle.finalize", "observed": {"note": "endpoint-unreachable"}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.finalize: X-Packet-Sha256 and Idempotency-Key=packetId; the answer decodes as FinalizeResponse", "status": "BLOCKED", "transport": "REAL_API", "ts": "2026-10-12T06:35:42.180Z"} +{"expected": "a terminal status within the budget, every answer contract-shaped", "id": "lifecycle.events", "observed": {"note": "endpoint-unreachable"}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.pollEvents: EventsResponse until CaptureAPI.terminalStatuses; next never moves back; a verdict names this run; retry_finalize re-sends the packet", "status": "BLOCKED", "transport": "REAL_API", "ts": "2026-10-12T06:35:42.180Z"} +{"expected": "a decodable result for this run whose status matches the terminal event status", "id": "lifecycle.result", "observed": {"note": "endpoint-unreachable"}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.fetchResult: the whole body decodes as CaptureResult.Response, its runId is the finalized run, and a null outcome is final only under statusesWithoutOutcome", "status": "BLOCKED", "transport": "REAL_API", "ts": "2026-10-12T06:35:42.180Z"} +{"expected": "both creates 2xx with the same captureId", "id": "control.idempotent-create", "observed": {"note": "endpoint-unreachable"}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.start: create is bound to Idempotency-Key=packetId, so a repeated create with the same bytes names the same capture", "status": "BLOCKED", "transport": "REAL_API", "ts": "2026-10-12T06:35:42.180Z"} +{"expected": "intact files committed; the flipped file in mismatch or notFound, or its PUT refused, and never committed", "id": "control.corrupt-upload", "observed": {"note": "endpoint-unreachable"}, "oracle": "HouseScanKit @ alpha 263827ef CommitResponse separates committed from mismatch/notFound; one file's bytes are flipped after its digest was registered", "status": "BLOCKED", "transport": "REAL_API", "ts": "2026-10-12T06:35:42.180Z"} +{"expected": "intact files committed; the truncated file in mismatch or notFound, or its PUT refused, and never committed", "id": "control.truncated-upload", "observed": {"note": "endpoint-unreachable"}, "oracle": "HouseScanKit @ alpha 263827ef CommitResponse separates committed from mismatch/notFound; one file loses its last byte after its digest was registered", "status": "BLOCKED", "transport": "REAL_API", "ts": "2026-10-12T06:35:42.180Z"} +{"expected": "404 with error code capture_not_found for an id the harness invented", "id": "control.wrong-capture", "observed": {"note": "endpoint-unreachable"}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.captureGone: an unknown capture answers 404 capture_not_found", "status": "BLOCKED", "transport": "REAL_API", "ts": "2026-10-12T06:35:42.180Z"} +{"expected": "every traced check present and PASS with the traced status class and fields", "id": "trace.expected-lifecycle-v2", "observed": {"compared": 0, "disagreements": [], "not_comparable": [{"id": "lifecycle.health", "status": "BLOCKED"}, {"id": "lifecycle.create", "status": "BLOCKED"}, {"id": "lifecycle.register", "status": "BLOCKED"}, {"id": "lifecycle.upload", "status": "BLOCKED"}, {"id": "lifecycle.commit", "status": "BLOCKED"}, {"id": "lifecycle.finalize", "status": "BLOCKED"}, {"id": "lifecycle.events", "status": "BLOCKED"}, {"id": "lifecycle.result", "status": "BLOCKED"}, {"id": "control.idempotent-create", "status": "BLOCKED"}, {"id": "control.corrupt-upload", "status": "BLOCKED"}, {"id": "control.truncated-upload", "status": "BLOCKED"}, {"id": "control.wrong-capture", "status": "BLOCKED"}]}, "oracle": "frozen expected trace traces/expected-lifecycle-v2.jsonl, written from the published contract", "status": "BLOCKED", "transport": "REAL_API", "ts": "2026-10-12T06:35:42.183Z"} +{"expected": "after a successful restart the capture still reports its terminal status and run", "id": "control.restart-recovery", "observed": {"note": "restart-not-configured"}, "oracle": "operator restart command, then the baseline capture is read again over the published events and result routes", "status": "NOT_RUN", "transport": "REAL_API", "ts": "2026-10-12T06:35:42.183Z"} +{"expected": "not run", "id": "gpu-stub.objects", "observed": {"note": "gpu-not-authorized"}, "oracle": "GPU-dependent arms are named and never executed by this harness", "status": "NOT_RUN", "transport": "GPU_STUB", "ts": "2026-10-12T06:35:42.183Z"} +{"expected": "not run", "id": "gpu-stub.vlm", "observed": {"note": "gpu-not-authorized"}, "oracle": "GPU-dependent arms are named and never executed by this harness", "status": "NOT_RUN", "transport": "GPU_STUB", "ts": "2026-10-12T06:35:42.183Z"} +{"expected": "not run", "id": "gpu-stub.dense", "observed": {"note": "gpu-not-authorized"}, "oracle": "GPU-dependent arms are named and never executed by this harness", "status": "NOT_RUN", "transport": "GPU_STUB", "ts": "2026-10-12T06:35:42.183Z"} diff --git a/tools/hunter-local-ingest/evidence/23d5fc9/real-api-unreachable/real-api-unreachable-20261012T063532Z-76788276ac9cc42a/privacy-chain.jsonl b/tools/hunter-local-ingest/evidence/23d5fc9/real-api-unreachable/real-api-unreachable-20261012T063532Z-76788276ac9cc42a/privacy-chain.jsonl new file mode 100644 index 000000000..96e02c7a5 --- /dev/null +++ b/tools/hunter-local-ingest/evidence/23d5fc9/real-api-unreachable/real-api-unreachable-20261012T063532Z-76788276ac9cc42a/privacy-chain.jsonl @@ -0,0 +1,4 @@ +{"artifact": "run-manifest.json", "at": "2026-10-12T06:35:32.105Z", "bytes": 3476, "chain_sha256": "cc91498f8e59f49123bf3ce48b9d93cfcaa9cf7d561a70f2f14b9f3dabcf52e6", "sha256": "a664736c3c8a9732439a0d7cb6d8d16d6255bfb0d6f93fd082147955b8a8e87c"} +{"artifact": "checks.jsonl", "at": "2026-10-12T06:35:42.183Z", "bytes": 6980, "chain_sha256": "99a59ce677f915eb6a0f8538ceddc2fe703cc8c50285a2ef0dd8529414f3cc77", "sha256": "f312e869a4d928920c8379720a6b55f2b6e7ae1a664bacac893198e0a431f36e"} +{"artifact": "summary.json", "at": "2026-10-12T06:35:42.184Z", "bytes": 1723, "chain_sha256": "87d1eec3cb3bb26705576e5654ab388c86053964f2b627866ae2b4238839b86f", "sha256": "a4ddb441b513a0c292aeac860dcfa6319242aa33036974daef88f24a66c068a2"} +{"artifact": "privacy-screen.json", "at": "2026-10-12T06:35:42.188Z", "bytes": 238, "chain_sha256": "2cd622b2d41fc39946dd979ff3b8636095e968b802c1c2e841c22204c928ce0f", "sha256": "3d27e7b4924bb18891da18e85cd1014c363123f1af9dbfc0a46c02a619a16279"} diff --git a/tools/hunter-local-ingest/evidence/23d5fc9/real-api-unreachable/real-api-unreachable-20261012T063532Z-76788276ac9cc42a/privacy-screen.json b/tools/hunter-local-ingest/evidence/23d5fc9/real-api-unreachable/real-api-unreachable-20261012T063532Z-76788276ac9cc42a/privacy-screen.json new file mode 100644 index 000000000..6b8a219ca --- /dev/null +++ b/tools/hunter-local-ingest/evidence/23d5fc9/real-api-unreachable/real-api-unreachable-20261012T063532Z-76788276ac9cc42a/privacy-screen.json @@ -0,0 +1,12 @@ +{ + "clean": true, + "findings": [], + "finished_utc": "2026-10-12T06:35:42.188Z", + "missing": [], + "schema": "hunter-local-ingest/privacy-screen/2", + "screened": [ + "run-manifest.json", + "checks.jsonl", + "summary.json" + ] +} diff --git a/tools/hunter-local-ingest/evidence/23d5fc9/real-api-unreachable/real-api-unreachable-20261012T063532Z-76788276ac9cc42a/run-manifest.json b/tools/hunter-local-ingest/evidence/23d5fc9/real-api-unreachable/real-api-unreachable-20261012T063532Z-76788276ac9cc42a/run-manifest.json new file mode 100644 index 000000000..3491f7e14 --- /dev/null +++ b/tools/hunter-local-ingest/evidence/23d5fc9/real-api-unreachable/real-api-unreachable-20261012T063532Z-76788276ac9cc42a/run-manifest.json @@ -0,0 +1,109 @@ +{ + "backend": { + "declared_mode": "REAL_API", + "declared_ref": null, + "verified": false + }, + "client": { + "declared_ref": null, + "git": null, + "interface": "2.0.0", + "package_version": "0.2.0", + "source_sha256": "a3df65c9ef00ded7ec00a6a43d6d5f08d27154d147ee49af0837cb554cfc54bc" + }, + "command": [ + "--endpoint", + "127.0.0.1:61512", + "--plan-file", + "", + "--out", + "", + "--label", + "real-api-unreachable", + "--backend-mode", + "REAL_API", + "--poll-interval-s", + "0.05", + "--events-wait-s", + "0", + "--retry-backoff-s", + "0.0", + "--result-budget-s", + "30.0" + ], + "created_utc": "2026-10-12T06:35:32.097Z", + "endpoint": "127.0.0.1:61512", + "fixture": { + "create_sha256": "9c2dd5f33bb70b7199e85f165e87602986faa7f6b5beaee6f55db4f1f9edce97", + "files": [ + { + "bytes": 65536, + "contentType": "application/octet-stream", + "path": "synthetic/scan00.bin", + "role": "other", + "sha256": "a1ca0aa5e471b98beddf42738d706871542520398ced6f3ed81008e8c9812d85" + }, + { + "bytes": 65536, + "contentType": "application/octet-stream", + "path": "synthetic/scan01.bin", + "role": "other", + "sha256": "ef4380c88a7e0a2df7506640f6b435b153122e01070d7570870ebd2d3367d4be" + }, + { + "bytes": 65536, + "contentType": "application/octet-stream", + "path": "synthetic/scan02.bin", + "role": "other", + "sha256": "3fda1dfcabd6f77b655435c16a6c7b75d5f2f2b4ef9dccd814fede0f2b69e1f1" + }, + { + "bytes": 9793, + "contentType": "application/gzip", + "path": "streams/arkit_poses.csv.gz", + "role": "stream", + "sha256": "a23bcec6f6829c053e7bc1871999ca7b1a5e88639b5a6cde56afc655d3447388" + }, + { + "bytes": 9443, + "contentType": "application/gzip", + "path": "streams/imu_raw.csv.gz", + "role": "stream", + "sha256": "ae96d9008b71882aeb0dbc1c5463897aa9c316fbda28d5503b4676e0bd85a161" + } + ], + "format_version": 2, + "generator": "gen_synthetic_packet", + "packet_id": "synthetic-000001", + "packet_sha256": "9ab561f503ef3dc0c0e5b007157ab40c803d5b43dc38136285a72ab77acd17d1", + "plan_file_sha256": "eabf28a3f818ee22d38cec91ad6d85af6921f5cb45156378a007475368ab692f", + "plan_sha256": "50f73a67aeb28e5e0c41f40946958a2806024f75ae56dda1384025ccd0a8e4ac", + "seed": 1 + }, + "label": "real-api-unreachable", + "origin_note": "Derived from published client behavior in HouseScanKit upload and result sources at alpha 263827ef. No private source, schema, spec, log or credential material appears in this package or its receipts.", + "restart": { + "argv": [], + "configured": false, + "timeout_s": 120.0 + }, + "run_id": "76788276ac9cc42a", + "runtime": { + "cpus": 12, + "implementation": "CPython", + "machine": "arm64", + "python": "3.13.12", + "release": "25.6.0", + "system": "Darwin" + }, + "sanitization": "Every value here passed the typed export schema before it was written: published enum words, package constants, digests, bounded numbers, and the plan's own synthetic paths and packet ids. A pattern screen then ran over the written files.", + "schema": "hunter-local-ingest/run-manifest/2", + "settings": { + "events_wait_s": 0, + "max_retries": 2, + "poll_interval_s": 0.05, + "result_budget_s": 30.0, + "retry_backoff_s": 0.0, + "with_faults": false + } +} diff --git a/tools/hunter-local-ingest/evidence/23d5fc9/real-api-unreachable/real-api-unreachable-20261012T063532Z-76788276ac9cc42a/summary.json b/tools/hunter-local-ingest/evidence/23d5fc9/real-api-unreachable/real-api-unreachable-20261012T063532Z-76788276ac9cc42a/summary.json new file mode 100644 index 000000000..db92d1fac --- /dev/null +++ b/tools/hunter-local-ingest/evidence/23d5fc9/real-api-unreachable/real-api-unreachable-20261012T063532Z-76788276ac9cc42a/summary.json @@ -0,0 +1,54 @@ +{ + "artifacts": { + "checks.jsonl": "f312e869a4d928920c8379720a6b55f2b6e7ae1a664bacac893198e0a431f36e", + "run-manifest.json": "a664736c3c8a9732439a0d7cb6d8d16d6255bfb0d6f93fd082147955b8a8e87c" + }, + "blocked": [ + "lifecycle.health", + "lifecycle.create", + "lifecycle.register", + "lifecycle.upload", + "lifecycle.commit", + "lifecycle.finalize", + "lifecycle.events", + "lifecycle.result", + "control.idempotent-create", + "control.corrupt-upload", + "control.truncated-upload", + "control.wrong-capture", + "trace.expected-lifecycle-v2" + ], + "counts_by_transport": { + "GPU_STUB": { + "NOT_RUN": 3 + }, + "REAL_API": { + "BLOCKED": 13, + "NOT_RUN": 1 + } + }, + "failed": [], + "finished_utc": "2026-10-12T06:35:42.184Z", + "lead_questions": [ + "Amendment semantics: does the published contract allow amending a registered capture, and with which route and headers?", + "Local-run auth mode: which credential form does the local backend expect from the published client? The client can send a bearer token on API routes only; no CLI flag supplies one yet.", + "Clock and expiry authority: whose clock governs capture expiry on the local backend?", + "Homeowner text: confirm that receipts may carry outcome kinds and counts but never messages, prompts or reasons." + ], + "mode": { + "backend_verified": false, + "declared_backend": "REAL_API", + "gpu_arms": "NOT_RUN", + "real_mirror_cpu": "NOT_ESTABLISHED" + }, + "not_run": [ + "control.restart-recovery", + "gpu-stub.objects", + "gpu-stub.vlm", + "gpu-stub.dense" + ], + "run_id": "76788276ac9cc42a", + "schema": "hunter-local-ingest/summary/2", + "total": 17, + "verdict": "BLOCKED" +} diff --git a/tools/hunter-local-ingest/evidence/23d5fc9/selfcheck/selfcheck-20261012T063528Z-b8e3889cea7aa704/checks.jsonl b/tools/hunter-local-ingest/evidence/23d5fc9/selfcheck/selfcheck-20261012T063528Z-b8e3889cea7aa704/checks.jsonl new file mode 100644 index 000000000..72382f64d --- /dev/null +++ b/tools/hunter-local-ingest/evidence/23d5fc9/selfcheck/selfcheck-20261012T063528Z-b8e3889cea7aa704/checks.jsonl @@ -0,0 +1,29 @@ +{"expected": "an HTTP 2xx answer with status ok", "id": "lifecycle.health", "observed": {"contract": {"status": "ok"}, "http": {"attempts": 1, "body_bytes": 16, "body_sha256": "08e2c358ce13", "elapsed_ms": 1, "fields": ["status"], "http_status": 200, "shape": "object"}, "violations": []}, "oracle": "tools/integration-viewer reads GET /v1/healthz; HouseScanKit never calls it", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:28.766Z"} +{"expected": "2xx, a captureId and a published capture status", "id": "lifecycle.create", "observed": {"contract": {"captureId": "id:fd102437f369", "maxBatch": 50, "status": "uploading"}, "http": {"attempts": 1, "body_bytes": 78, "body_sha256": "8edf48cf4ce9", "elapsed_ms": 0, "fields": ["captureId", "status", "upload"], "http_status": 201, "shape": "object"}, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.create: POST captures with Idempotency-Key=packetId; the answer decodes as CaptureAPI.CreateResponse", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:28.767Z"} +{"expected": "every requested path answered exactly once, no other path, each committed or given a usable PUT target", "id": "lifecycle.register", "observed": {"batches": [{"contract": {"files": [{"path": "synthetic/scan00.bin", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "synthetic/scan01.bin", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "synthetic/scan02.bin", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "streams/arkit_poses.csv.gz", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "streams/imu_raw.csv.gz", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}]}, "http": {"attempts": 1, "body_bytes": 1253, "body_sha256": "2ef03a6d86d2", "elapsed_ms": 0, "fields": ["files"], "http_status": 200, "shape": "object"}, "violations": []}], "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.register: the answer decodes as RegisterResponse and is applied by path; a target needs method PUT and a URL that passes uploadURLProblem", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:28.769Z"} +{"expected": "2xx for every file that got a target", "id": "lifecycle.upload", "observed": {"uploads": [{"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 1, "fields": [], "http_status": 200, "path": "synthetic/scan00.bin", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 1, "fields": [], "http_status": 200, "path": "synthetic/scan01.bin", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 1, "fields": [], "http_status": 200, "path": "synthetic/scan02.bin", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "streams/arkit_poses.csv.gz", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "streams/imu_raw.csv.gz", "shape": "empty"}]}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.put + ScopedCaptureHTTP.upload: exactly the signed headers, never Authorization", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:28.774Z"} +{"expected": "committed equals the uploaded set; notFound and mismatch empty; every declared path committed by register or commit", "id": "lifecycle.commit", "observed": {"batches": [{"contract": {"committed": ["synthetic/scan00.bin", "synthetic/scan01.bin", "synthetic/scan02.bin", "streams/arkit_poses.csv.gz", "streams/imu_raw.csv.gz"], "mismatch": [], "notFound": []}, "http": {"attempts": 1, "body_bytes": 175, "body_sha256": "ab0d647d58c4", "elapsed_ms": 0, "fields": ["committed", "mismatch", "notFound"], "http_status": 200, "shape": "object"}, "violations": []}], "committed_total": 5, "declared": 5, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.commit: only a commit acknowledges a file; CommitResponse carries committed, notFound and mismatch", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:28.775Z"} +{"expected": "2xx, a runId, a published status, no missing file", "id": "lifecycle.finalize", "observed": {"contract": {"missing": [], "runId": "id:492e113d2d27", "status": "processing"}, "http": {"attempts": 1, "body_bytes": 62, "body_sha256": "425e9d06a56d", "elapsed_ms": 0, "fields": ["missing", "runId", "status"], "http_status": 202, "shape": "object"}, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.finalize: X-Packet-Sha256 and Idempotency-Key=packetId; the answer decodes as FinalizeResponse", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:28.775Z"} +{"expected": "a terminal status within the budget, every answer contract-shaped", "id": "lifecycle.events", "observed": {"answers": 1, "finalize_retries": 0, "last": {"contract": {"events": [{"data": {"runId": "id:492e113d2d27", "runId_matches": true}, "seq": 1, "type": "verdict_ready"}], "next": 1, "status": "complete"}, "http": {"attempts": 1, "body_bytes": 145, "body_sha256": "f7919284ecb6", "elapsed_ms": 0, "fields": ["events", "next", "status"], "http_status": 200, "shape": "object"}, "violations": []}}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.pollEvents: EventsResponse until CaptureAPI.terminalStatuses; next never moves back; a verdict names this run; retry_finalize re-sends the packet", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:28.776Z"} +{"expected": "a decodable result for this run whose status matches the terminal event status", "id": "lifecycle.result", "observed": {"contract": {"criteria": null, "has_preview_url": false, "memberActions": 0, "outcome": {"kind": "eligible", "reasons": 0}, "runId": "id:492e113d2d27", "status": "complete", "viewsNeeded": 0}, "http": {"attempts": 1, "body_bytes": 227, "body_sha256": "1dc1b0ebf7a6", "elapsed_ms": 0, "fields": ["memberActions", "outcome", "runId", "status", "viewsNeeded"], "http_status": 200, "shape": "object"}, "not_ready_reads": 0, "run_matches": true, "status_matches": true, "terminal_status": "complete", "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.fetchResult: the whole body decodes as CaptureResult.Response, its runId is the finalized run, and a null outcome is final only under statusesWithoutOutcome", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:28.777Z"} +{"expected": "both creates 2xx with the same captureId", "id": "control.idempotent-create", "observed": {"first": {"contract": {"captureId": "id:b9d50067aadb", "maxBatch": 50, "status": "uploading"}, "http": {"attempts": 1, "body_bytes": 78, "body_sha256": "ec8a1ff9228b", "elapsed_ms": 0, "fields": ["captureId", "status", "upload"], "http_status": 201, "shape": "object"}, "violations": []}, "same_capture": true, "second": {"contract": {"captureId": "id:b9d50067aadb", "maxBatch": 50, "status": "uploading"}, "http": {"attempts": 1, "body_bytes": 78, "body_sha256": "ec8a1ff9228b", "elapsed_ms": 0, "fields": ["captureId", "status", "upload"], "http_status": 200, "shape": "object"}, "violations": []}}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.start: create is bound to Idempotency-Key=packetId, so a repeated create with the same bytes names the same capture", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:28.779Z"} +{"expected": "intact files committed; the flipped file in mismatch or notFound, or its PUT refused, and never committed", "id": "control.corrupt-upload", "observed": {"contract": {"committed": ["synthetic/scan01.bin", "synthetic/scan02.bin", "streams/arkit_poses.csv.gz", "streams/imu_raw.csv.gz"], "mismatch": ["synthetic/scan00.bin"], "notFound": []}, "http": {"attempts": 1, "body_bytes": 173, "body_sha256": "b6f8e6ec4d66", "elapsed_ms": 0, "fields": ["committed", "mismatch", "notFound"], "http_status": 200, "shape": "object"}, "intact_committed": true, "tampered": "synthetic/scan00.bin", "tampered_committed": false, "tampered_put_status": 200, "tampered_reported": true, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CommitResponse separates committed from mismatch/notFound; one file's bytes are flipped after its digest was registered", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:28.785Z"} +{"expected": "intact files committed; the truncated file in mismatch or notFound, or its PUT refused, and never committed", "id": "control.truncated-upload", "observed": {"contract": {"committed": ["synthetic/scan01.bin", "synthetic/scan02.bin", "streams/arkit_poses.csv.gz", "streams/imu_raw.csv.gz"], "mismatch": ["synthetic/scan00.bin"], "notFound": []}, "http": {"attempts": 1, "body_bytes": 173, "body_sha256": "b6f8e6ec4d66", "elapsed_ms": 0, "fields": ["committed", "mismatch", "notFound"], "http_status": 200, "shape": "object"}, "intact_committed": true, "tampered": "synthetic/scan00.bin", "tampered_committed": false, "tampered_put_status": 200, "tampered_reported": true, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CommitResponse separates committed from mismatch/notFound; one file loses its last byte after its digest was registered", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:28.790Z"} +{"expected": "404 with error code capture_not_found for an id the harness invented", "id": "control.wrong-capture", "observed": {"capture": "id:1976512104be", "errors": {"codes": ["capture_not_found"]}, "http": {"attempts": 1, "body_bytes": 43, "body_sha256": "23553eb17fe9", "elapsed_ms": 0, "fields": ["errors"], "http_status": 404, "shape": "object"}}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.captureGone: an unknown capture answers 404 capture_not_found", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:28.790Z"} +{"expected": "an HTTP 2xx answer with status ok", "id": "fault.lifecycle.health", "observed": {"contract": {"status": "ok"}, "http": {"attempts": 1, "body_bytes": 16, "body_sha256": "08e2c358ce13", "elapsed_ms": 0, "fields": ["status"], "http_status": 200, "shape": "object"}, "violations": []}, "oracle": "tools/integration-viewer reads GET /v1/healthz; HouseScanKit never calls it", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:28.793Z"} +{"expected": "2xx, a captureId and a published capture status", "id": "fault.lifecycle.create", "observed": {"contract": {"captureId": "id:d6611115894b", "maxBatch": 50, "status": "uploading"}, "http": {"attempts": 1, "body_bytes": 78, "body_sha256": "1ff5bb037620", "elapsed_ms": 107, "fields": ["captureId", "status", "upload"], "http_status": 201, "shape": "object"}, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.create: POST captures with Idempotency-Key=packetId; the answer decodes as CaptureAPI.CreateResponse", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:28.900Z"} +{"expected": "every requested path answered exactly once, no other path, each committed or given a usable PUT target", "id": "fault.lifecycle.register", "observed": {"batches": [{"contract": {"files": [{"path": "synthetic/scan00.bin", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "synthetic/scan01.bin", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "synthetic/scan02.bin", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "streams/arkit_poses.csv.gz", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "streams/imu_raw.csv.gz", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}]}, "http": {"attempts": 1, "body_bytes": 1253, "body_sha256": "2909c3beba8e", "elapsed_ms": 1, "fields": ["files"], "http_status": 200, "shape": "object"}, "violations": []}], "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.register: the answer decodes as RegisterResponse and is applied by path; a target needs method PUT and a URL that passes uploadURLProblem", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:28.902Z"} +{"expected": "2xx for every file that got a target", "id": "fault.lifecycle.upload", "observed": {"uploads": [{"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "synthetic/scan00.bin", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "synthetic/scan01.bin", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "synthetic/scan02.bin", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "streams/arkit_poses.csv.gz", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "streams/imu_raw.csv.gz", "shape": "empty"}]}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.put + ScopedCaptureHTTP.upload: exactly the signed headers, never Authorization", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:28.905Z"} +{"expected": "committed equals the uploaded set; notFound and mismatch empty; every declared path committed by register or commit", "id": "fault.lifecycle.commit", "observed": {"batches": [{"contract": {"committed": ["synthetic/scan00.bin", "synthetic/scan01.bin", "synthetic/scan02.bin", "streams/arkit_poses.csv.gz", "streams/imu_raw.csv.gz"], "mismatch": [], "notFound": []}, "http": {"attempts": 1, "body_bytes": 175, "body_sha256": "ab0d647d58c4", "elapsed_ms": 1, "fields": ["committed", "mismatch", "notFound"], "http_status": 200, "shape": "object"}, "violations": []}], "committed_total": 5, "declared": 5, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.commit: only a commit acknowledges a file; CommitResponse carries committed, notFound and mismatch", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:28.907Z"} +{"expected": "2xx, a runId, a published status, no missing file", "id": "fault.lifecycle.finalize", "observed": {"contract": {"missing": [], "runId": "id:636f557a124e", "status": "processing"}, "http": {"attempts": 1, "body_bytes": 62, "body_sha256": "cc5e4603e9bd", "elapsed_ms": 1, "fields": ["missing", "runId", "status"], "http_status": 202, "shape": "object"}, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.finalize: X-Packet-Sha256 and Idempotency-Key=packetId; the answer decodes as FinalizeResponse", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:28.908Z"} +{"expected": "a terminal status within the budget, every answer contract-shaped", "id": "fault.lifecycle.events", "observed": {"answers": 1, "finalize_retries": 0, "last": {"contract": {"events": [{"data": {"runId": "id:636f557a124e", "runId_matches": true}, "seq": 1, "type": "verdict_ready"}], "next": 1, "status": "complete"}, "http": {"attempts": 1, "body_bytes": 145, "body_sha256": "6519430bc83d", "elapsed_ms": 0, "fields": ["events", "next", "status"], "http_status": 200, "shape": "object"}, "violations": []}}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.pollEvents: EventsResponse until CaptureAPI.terminalStatuses; next never moves back; a verdict names this run; retry_finalize re-sends the packet", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:28.909Z"} +{"expected": "a decodable result for this run whose status matches the terminal event status", "id": "fault.lifecycle.result", "observed": {"contract": {"criteria": null, "has_preview_url": false, "memberActions": 0, "outcome": {"kind": "eligible", "reasons": 0}, "runId": "id:636f557a124e", "status": "complete", "viewsNeeded": 0}, "http": {"attempts": 1, "body_bytes": 227, "body_sha256": "f0543371247b", "elapsed_ms": 0, "fields": ["memberActions", "outcome", "runId", "status", "viewsNeeded"], "http_status": 200, "shape": "object"}, "not_ready_reads": 0, "run_matches": true, "status_matches": true, "terminal_status": "complete", "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.fetchResult: the whole body decodes as CaptureResult.Response, its runId is the finalized run, and a null outcome is final only under statusesWithoutOutcome", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:28.910Z"} +{"expected": "the proxy's single 503 is followed by a second attempt that creates the capture", "id": "fault.retry-transient", "observed": {"contract": {"captureId": "id:40a0732506ed", "maxBatch": 50, "status": "uploading"}, "http": {"attempts": 2, "body_bytes": 78, "body_sha256": "2350cd7a9fb2", "elapsed_ms": 1, "fields": ["captureId", "status", "upload"], "http_status": 201, "shape": "object"}, "proxy_hits": 2, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.isTransient: a 503 is retried with the same body", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:29.916Z"} +{"expected": "exactly one attempt and a reported non-2xx answer", "id": "fault.no-retry-501", "observed": {"errors": {"codes": ["harness_fault"]}, "http": {"attempts": 1, "body_bytes": 39, "body_sha256": "be37db4e697d", "elapsed_ms": 1, "fields": ["errors"], "http_status": 501, "shape": "object"}, "proxy_hits": 1}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.isTransient excludes 501", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:30.422Z"} +{"expected": "a transport error category after 1 + max_retries attempts, no capture id taken", "id": "fault.abort", "observed": {"http": {"attempts": 2, "error": "transport:remote-disconnected"}, "proxy_hits": 2}, "oracle": "an answer-less connection is a transport failure, retried a bounded number of times", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:30.926Z"} +{"expected": "a transport error category, no capture id taken", "id": "fault.truncated-response", "observed": {"http": {"attempts": 1, "error": "transport:incomplete-read"}, "proxy_hits": 1}, "oracle": "a body shorter than its Content-Length is a transport failure, never a parsed answer", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:31.431Z"} +{"expected": "every traced check present and PASS with the traced status class and fields", "id": "trace.expected-lifecycle-v2", "observed": {"compared": 12, "disagreements": [], "not_comparable": []}, "oracle": "frozen expected trace traces/expected-lifecycle-v2.jsonl, written from the published contract", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:31.433Z"} +{"expected": "after a successful restart the capture still reports its terminal status and run", "id": "control.restart-recovery", "observed": {"after_restart": [{"contract": {"events": [{"data": {"runId": "id:492e113d2d27", "runId_matches": true}, "seq": 1, "type": "verdict_ready"}], "next": 1, "status": "complete"}, "http": {"attempts": 1, "body_bytes": 145, "body_sha256": "f7919284ecb6", "elapsed_ms": 0, "fields": ["events", "next", "status"], "http_status": 200, "shape": "object"}, "violations": []}, {"contract": {"criteria": null, "has_preview_url": false, "memberActions": 0, "outcome": {"kind": "eligible", "reasons": 0}, "runId": "id:492e113d2d27", "status": "complete", "viewsNeeded": 0}, "http": {"attempts": 1, "body_bytes": 227, "body_sha256": "1dc1b0ebf7a6", "elapsed_ms": 0, "fields": ["memberActions", "outcome", "runId", "status", "viewsNeeded"], "http_status": 200, "shape": "object"}, "violations": []}], "exit_code": 0, "run_matches": true, "status_matches": true}, "oracle": "operator restart command, then the baseline capture is read again over the published events and result routes", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T06:35:31.457Z"} +{"expected": "not run", "id": "gpu-stub.objects", "observed": {"note": "gpu-not-authorized"}, "oracle": "GPU-dependent arms are named and never executed by this harness", "status": "NOT_RUN", "transport": "GPU_STUB", "ts": "2026-10-12T06:35:31.457Z"} +{"expected": "not run", "id": "gpu-stub.vlm", "observed": {"note": "gpu-not-authorized"}, "oracle": "GPU-dependent arms are named and never executed by this harness", "status": "NOT_RUN", "transport": "GPU_STUB", "ts": "2026-10-12T06:35:31.457Z"} +{"expected": "not run", "id": "gpu-stub.dense", "observed": {"note": "gpu-not-authorized"}, "oracle": "GPU-dependent arms are named and never executed by this harness", "status": "NOT_RUN", "transport": "GPU_STUB", "ts": "2026-10-12T06:35:31.457Z"} diff --git a/tools/hunter-local-ingest/evidence/23d5fc9/selfcheck/selfcheck-20261012T063528Z-b8e3889cea7aa704/privacy-chain.jsonl b/tools/hunter-local-ingest/evidence/23d5fc9/selfcheck/selfcheck-20261012T063528Z-b8e3889cea7aa704/privacy-chain.jsonl new file mode 100644 index 000000000..6aeda0161 --- /dev/null +++ b/tools/hunter-local-ingest/evidence/23d5fc9/selfcheck/selfcheck-20261012T063528Z-b8e3889cea7aa704/privacy-chain.jsonl @@ -0,0 +1,4 @@ +{"artifact": "run-manifest.json", "at": "2026-10-12T06:35:28.764Z", "bytes": 3535, "chain_sha256": "5552020d7d6f9c4f0e731b548c9ea46e4983a258565561e126299a0f71107ee8", "sha256": "38149b47418ff557717f90319f64a392d5344a90c7e085127bf3cb0c3bd00fc5"} +{"artifact": "checks.jsonl", "at": "2026-10-12T06:35:31.457Z", "bytes": 21911, "chain_sha256": "17ca1a0ecb18ee5bba9f98bf104adbcb91cb3582e6b03cb97dbf6b3005adc852", "sha256": "13646460c99be9aba9b2ad4cd8ed16e2666b0a0553ff9142c2cac66a6aa15880"} +{"artifact": "summary.json", "at": "2026-10-12T06:35:31.457Z", "bytes": 1314, "chain_sha256": "3a65494fee13f51e87778def9ad24556c95988241d20ecc2ce725e3f307de74a", "sha256": "f2e35d9f0a711dfd96e777d089fc19dbee266e8c0d53c46b21fe3c0c304f8ed5"} +{"artifact": "privacy-screen.json", "at": "2026-10-12T06:35:31.466Z", "bytes": 238, "chain_sha256": "5ba0524216350e67402232b202308ff2a842911b9f50d76da15388df55eae00c", "sha256": "539f956be1187ac5df7a83175bcff0a82128f88f1ffba8c3911edaef4b6f8490"} diff --git a/tools/hunter-local-ingest/evidence/23d5fc9/selfcheck/selfcheck-20261012T063528Z-b8e3889cea7aa704/privacy-screen.json b/tools/hunter-local-ingest/evidence/23d5fc9/selfcheck/selfcheck-20261012T063528Z-b8e3889cea7aa704/privacy-screen.json new file mode 100644 index 000000000..b9d064a8d --- /dev/null +++ b/tools/hunter-local-ingest/evidence/23d5fc9/selfcheck/selfcheck-20261012T063528Z-b8e3889cea7aa704/privacy-screen.json @@ -0,0 +1,12 @@ +{ + "clean": true, + "findings": [], + "finished_utc": "2026-10-12T06:35:31.465Z", + "missing": [], + "schema": "hunter-local-ingest/privacy-screen/2", + "screened": [ + "run-manifest.json", + "checks.jsonl", + "summary.json" + ] +} diff --git a/tools/hunter-local-ingest/evidence/23d5fc9/selfcheck/selfcheck-20261012T063528Z-b8e3889cea7aa704/run-manifest.json b/tools/hunter-local-ingest/evidence/23d5fc9/selfcheck/selfcheck-20261012T063528Z-b8e3889cea7aa704/run-manifest.json new file mode 100644 index 000000000..8814ac09d --- /dev/null +++ b/tools/hunter-local-ingest/evidence/23d5fc9/selfcheck/selfcheck-20261012T063528Z-b8e3889cea7aa704/run-manifest.json @@ -0,0 +1,114 @@ +{ + "backend": { + "declared_mode": "FAKE_HUNTER", + "declared_ref": null, + "verified": false + }, + "client": { + "declared_ref": null, + "git": null, + "interface": "2.0.0", + "package_version": "0.2.0", + "source_sha256": "a3df65c9ef00ded7ec00a6a43d6d5f08d27154d147ee49af0837cb554cfc54bc" + }, + "command": [ + "--endpoint", + "127.0.0.1:61431", + "--plan-file", + "", + "--out", + "", + "--label", + "selfcheck", + "--backend-mode", + "FAKE_HUNTER", + "--poll-interval-s", + "0.05", + "--events-wait-s", + "0", + "--retry-backoff-s", + "0.0", + "--with-faults", + "--restart-argv-json", + "" + ], + "created_utc": "2026-10-12T06:35:28.756Z", + "endpoint": "127.0.0.1:61431", + "fixture": { + "create_sha256": "9c2dd5f33bb70b7199e85f165e87602986faa7f6b5beaee6f55db4f1f9edce97", + "files": [ + { + "bytes": 65536, + "contentType": "application/octet-stream", + "path": "synthetic/scan00.bin", + "role": "other", + "sha256": "a1ca0aa5e471b98beddf42738d706871542520398ced6f3ed81008e8c9812d85" + }, + { + "bytes": 65536, + "contentType": "application/octet-stream", + "path": "synthetic/scan01.bin", + "role": "other", + "sha256": "ef4380c88a7e0a2df7506640f6b435b153122e01070d7570870ebd2d3367d4be" + }, + { + "bytes": 65536, + "contentType": "application/octet-stream", + "path": "synthetic/scan02.bin", + "role": "other", + "sha256": "3fda1dfcabd6f77b655435c16a6c7b75d5f2f2b4ef9dccd814fede0f2b69e1f1" + }, + { + "bytes": 9793, + "contentType": "application/gzip", + "path": "streams/arkit_poses.csv.gz", + "role": "stream", + "sha256": "a23bcec6f6829c053e7bc1871999ca7b1a5e88639b5a6cde56afc655d3447388" + }, + { + "bytes": 9443, + "contentType": "application/gzip", + "path": "streams/imu_raw.csv.gz", + "role": "stream", + "sha256": "ae96d9008b71882aeb0dbc1c5463897aa9c316fbda28d5503b4676e0bd85a161" + } + ], + "format_version": 2, + "generator": "gen_synthetic_packet", + "packet_id": "synthetic-000001", + "packet_sha256": "9ab561f503ef3dc0c0e5b007157ab40c803d5b43dc38136285a72ab77acd17d1", + "plan_file_sha256": "eabf28a3f818ee22d38cec91ad6d85af6921f5cb45156378a007475368ab692f", + "plan_sha256": "50f73a67aeb28e5e0c41f40946958a2806024f75ae56dda1384025ccd0a8e4ac", + "seed": 1 + }, + "label": "selfcheck", + "origin_note": "Derived from published client behavior in HouseScanKit upload and result sources at alpha 263827ef. No private source, schema, spec, log or credential material appears in this package or its receipts.", + "restart": { + "argv": [ + "", + "-c", + "" + ], + "configured": true, + "timeout_s": 120.0 + }, + "run_id": "b8e3889cea7aa704", + "runtime": { + "cpus": 12, + "implementation": "CPython", + "machine": "arm64", + "python": "3.13.12", + "release": "25.6.0", + "system": "Darwin" + }, + "sanitization": "Every value here passed the typed export schema before it was written: published enum words, package constants, digests, bounded numbers, and the plan's own synthetic paths and packet ids. A pattern screen then ran over the written files.", + "schema": "hunter-local-ingest/run-manifest/2", + "settings": { + "events_wait_s": 0, + "max_retries": 2, + "poll_interval_s": 0.05, + "result_budget_s": 1500.0, + "retry_backoff_s": 0.0, + "with_faults": true + } +} diff --git a/tools/hunter-local-ingest/evidence/23d5fc9/selfcheck/selfcheck-20261012T063528Z-b8e3889cea7aa704/summary.json b/tools/hunter-local-ingest/evidence/23d5fc9/selfcheck/selfcheck-20261012T063528Z-b8e3889cea7aa704/summary.json new file mode 100644 index 000000000..c87a1e24c --- /dev/null +++ b/tools/hunter-local-ingest/evidence/23d5fc9/selfcheck/selfcheck-20261012T063528Z-b8e3889cea7aa704/summary.json @@ -0,0 +1,38 @@ +{ + "artifacts": { + "checks.jsonl": "13646460c99be9aba9b2ad4cd8ed16e2666b0a0553ff9142c2cac66a6aa15880", + "run-manifest.json": "38149b47418ff557717f90319f64a392d5344a90c7e085127bf3cb0c3bd00fc5" + }, + "blocked": [], + "counts_by_transport": { + "FAKE_HUNTER": { + "PASS": 26 + }, + "GPU_STUB": { + "NOT_RUN": 3 + } + }, + "failed": [], + "finished_utc": "2026-10-12T06:35:31.457Z", + "lead_questions": [ + "Amendment semantics: does the published contract allow amending a registered capture, and with which route and headers?", + "Local-run auth mode: which credential form does the local backend expect from the published client? The client can send a bearer token on API routes only; no CLI flag supplies one yet.", + "Clock and expiry authority: whose clock governs capture expiry on the local backend?", + "Homeowner text: confirm that receipts may carry outcome kinds and counts but never messages, prompts or reasons." + ], + "mode": { + "backend_verified": false, + "declared_backend": "FAKE_HUNTER", + "gpu_arms": "NOT_RUN", + "real_mirror_cpu": "NOT_ESTABLISHED" + }, + "not_run": [ + "gpu-stub.objects", + "gpu-stub.vlm", + "gpu-stub.dense" + ], + "run_id": "b8e3889cea7aa704", + "schema": "hunter-local-ingest/summary/2", + "total": 29, + "verdict": "PASS" +} diff --git a/tools/hunter-local-ingest/evidence/aa10463/README.md b/tools/hunter-local-ingest/evidence/aa10463/README.md new file mode 100644 index 000000000..4d9451af1 --- /dev/null +++ b/tools/hunter-local-ingest/evidence/aa10463/README.md @@ -0,0 +1,20 @@ +# Focused receipts from the installed package at aa10463 + +Three runtime conditions, run with the wheel built out of commit +`aa10463a66bddf1869ec975fc28fdb8991d9a388` +(sha256 `0584da030bd6075ef69b0c884e8478dcd1b8c0779f0e996cdfe91b29d15b3206`), +installed non-editable and run as console scripts outside the source tree. +The installed source digest equals the committed tree's (`index.json`). This +is not the full seven-run campaign: `evidence/1511668/` and `evidence/23d5fc9/` +remain the receipts for their own sources and are unchanged. + +| Run | Exit | What it shows | +| --- | --- | --- | +| `commit-batch-semantic-fail/` | 1 | the first commit batch answers one path notFound; the lifecycle commit FAILs after that one batch, and the run is FAIL, not BLOCKED, although the next commit request gets no answer | +| `bearer-trailing-lf` (no directory) | 2 | a synthetic token ending in a newline is refused with `credential:auth_credential_malformed` before any run directory or request: no directory, 0 requests, the token in no output | +| `decimal-cursor-exact/` | 0 | the server writes an event cursor above 2^53 as a decimal literal; the next poll asks for exactly `after=4611686018427387905`, never the rounded `...904` | + +The token run writes no receipts by design, so `index.json` records its exit +code, request count and output check instead. Fake servers only; no real +backend, credential, GPU or phone. `hunter-verify-run` reported OK on both +sealed originals; on these git copies run `chmod -R a-w ` first. diff --git a/tools/hunter-local-ingest/evidence/aa10463/commit-batch-semantic-fail/batch-fail-20261012T130248Z-191f85151f05e372/checks.jsonl b/tools/hunter-local-ingest/evidence/aa10463/commit-batch-semantic-fail/batch-fail-20261012T130248Z-191f85151f05e372/checks.jsonl new file mode 100644 index 000000000..abc4df40e --- /dev/null +++ b/tools/hunter-local-ingest/evidence/aa10463/commit-batch-semantic-fail/batch-fail-20261012T130248Z-191f85151f05e372/checks.jsonl @@ -0,0 +1,17 @@ +{"expected": "an HTTP 2xx answer with status ok", "id": "lifecycle.health", "observed": {"contract": {"status": "ok"}, "http": {"attempts": 1, "body_bytes": 16, "body_sha256": "08e2c358ce13", "elapsed_ms": 1, "fields": ["status"], "http_status": 200, "shape": "object"}, "violations": []}, "oracle": "tools/integration-viewer reads GET /v1/healthz; HouseScanKit never calls it", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T13:02:48.300Z"} +{"expected": "2xx, a captureId and a published capture status", "id": "lifecycle.create", "observed": {"contract": {"captureId": "id:fd102437f369", "maxBatch": 2, "status": "uploading"}, "http": {"attempts": 1, "body_bytes": 77, "body_sha256": "1c8c152f2eb5", "elapsed_ms": 0, "fields": ["captureId", "status", "upload"], "http_status": 201, "shape": "object"}, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.create: POST captures with Idempotency-Key=packetId; the answer decodes as CaptureAPI.CreateResponse", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T13:02:48.301Z"} +{"expected": "every requested path answered exactly once, no other path, each committed or given a usable PUT target", "id": "lifecycle.register", "observed": {"batches": [{"contract": {"files": [{"path": "synthetic/scan00.bin", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "synthetic/scan01.bin", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}]}, "http": {"attempts": 1, "body_bytes": 511, "body_sha256": "05baa537d3ba", "elapsed_ms": 0, "fields": ["files"], "http_status": 200, "shape": "object"}, "violations": []}, {"contract": {"files": [{"path": "synthetic/scan02.bin", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "streams/arkit_poses.csv.gz", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}]}, "http": {"attempts": 1, "body_bytes": 509, "body_sha256": "c6965a96b072", "elapsed_ms": 0, "fields": ["files"], "http_status": 200, "shape": "object"}, "violations": []}, {"contract": {"files": [{"path": "streams/imu_raw.csv.gz", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}]}, "http": {"attempts": 1, "body_bytes": 255, "body_sha256": "76f6ea59ac49", "elapsed_ms": 0, "fields": ["files"], "http_status": 200, "shape": "object"}, "violations": []}], "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.register: the answer decodes as RegisterResponse and is applied by path; a target needs method PUT and a URL that passes uploadURLProblem", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T13:02:48.304Z"} +{"expected": "2xx for every file that got a target", "id": "lifecycle.upload", "observed": {"committed_at_register": [], "uploads": [{"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 1, "fields": [], "http_status": 200, "path": "synthetic/scan00.bin", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 1, "fields": [], "http_status": 200, "path": "synthetic/scan01.bin", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 1, "fields": [], "http_status": 200, "path": "synthetic/scan02.bin", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "streams/arkit_poses.csv.gz", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "streams/imu_raw.csv.gz", "shape": "empty"}]}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.put + ScopedCaptureHTTP.upload: exactly the signed headers, never Authorization", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T13:02:48.309Z"} +{"expected": "committed equals the uploaded set; notFound and mismatch empty; every declared path committed by register or commit", "id": "lifecycle.commit", "observed": {"batches": [{"contract": {"committed": ["synthetic/scan00.bin"], "mismatch": [], "notFound": ["synthetic/scan01.bin"]}, "http": {"attempts": 1, "body_bytes": 93, "body_sha256": "dc7cdc9835db", "elapsed_ms": 0, "fields": ["committed", "mismatch", "notFound"], "http_status": 200, "shape": "object"}, "violations": []}], "committed_at_register": [], "committed_total": 1, "declared": 5, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.commit: only a commit acknowledges a file; CommitResponse carries committed, notFound and mismatch", "status": "FAIL", "transport": "FAKE_HUNTER", "ts": "2026-10-12T13:02:48.309Z"} +{"expected": "2xx, a runId, a published status, no missing file", "id": "lifecycle.finalize", "observed": {"note": "skipped-after-failed-step"}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.finalize: X-Packet-Sha256 and Idempotency-Key=packetId; the answer decodes as FinalizeResponse", "status": "BLOCKED", "transport": "FAKE_HUNTER", "ts": "2026-10-12T13:02:48.309Z"} +{"expected": "a terminal status within the budget, every answer contract-shaped", "id": "lifecycle.events", "observed": {"note": "skipped-after-failed-step"}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.pollEvents: EventsResponse until CaptureAPI.terminalStatuses; next never moves back; a verdict names this run; retry_finalize re-sends the packet", "status": "BLOCKED", "transport": "FAKE_HUNTER", "ts": "2026-10-12T13:02:48.309Z"} +{"expected": "a decodable result for this run whose status matches the terminal event status", "id": "lifecycle.result", "observed": {"note": "skipped-after-failed-step"}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.fetchResult: the whole body decodes as CaptureResult.Response, its runId is the finalized run, and a null outcome is final only under statusesWithoutOutcome", "status": "BLOCKED", "transport": "FAKE_HUNTER", "ts": "2026-10-12T13:02:48.309Z"} +{"expected": "both creates 2xx with the same captureId", "id": "control.idempotent-create", "observed": {"first": {"contract": {"captureId": "id:a97c96e452e8", "maxBatch": 2, "status": "uploading"}, "http": {"attempts": 1, "body_bytes": 77, "body_sha256": "6a8330d88d7b", "elapsed_ms": 0, "fields": ["captureId", "status", "upload"], "http_status": 201, "shape": "object"}, "violations": []}, "same_capture": true, "second": {"contract": {"captureId": "id:a97c96e452e8", "maxBatch": 2, "status": "uploading"}, "http": {"attempts": 1, "body_bytes": 77, "body_sha256": "6a8330d88d7b", "elapsed_ms": 0, "fields": ["captureId", "status", "upload"], "http_status": 200, "shape": "object"}, "violations": []}}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.start: create is bound to Idempotency-Key=packetId, so a repeated create with the same bytes names the same capture", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T13:02:48.311Z"} +{"expected": "intact files committed; the flipped file in mismatch or notFound, or its PUT refused, and never committed", "id": "control.corrupt-upload", "observed": {"batches": [{"http": {"attempts": 1, "error": "transport:remote-disconnected"}}], "step": "commit"}, "oracle": "HouseScanKit @ alpha 263827ef CommitResponse separates committed from mismatch/notFound; one file's bytes are flipped after its digest was registered", "status": "BLOCKED", "transport": "FAKE_HUNTER", "ts": "2026-10-12T13:02:48.317Z"} +{"expected": "intact files committed; the truncated file in mismatch or notFound, or its PUT refused, and never committed", "id": "control.truncated-upload", "observed": {"batches": [{"http": {"attempts": 1, "error": "transport:remote-disconnected"}}], "step": "commit"}, "oracle": "HouseScanKit @ alpha 263827ef CommitResponse separates committed from mismatch/notFound; one file loses its last byte after its digest was registered", "status": "BLOCKED", "transport": "FAKE_HUNTER", "ts": "2026-10-12T13:02:48.322Z"} +{"expected": "404 with error code capture_not_found for an id the harness invented", "id": "control.wrong-capture", "observed": {"capture": "id:1976512104be", "errors": {"codes": ["capture_not_found"]}, "http": {"attempts": 1, "body_bytes": 43, "body_sha256": "23553eb17fe9", "elapsed_ms": 0, "fields": ["errors"], "http_status": 404, "shape": "object"}}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.captureGone: an unknown capture answers 404 capture_not_found", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T13:02:48.323Z"} +{"expected": "every traced check present and PASS with the traced status class and fields, or upload and commit skipped because register reported every declared file committed", "id": "trace.expected-lifecycle-v3", "observed": {"compared": 7, "disagreements": [{"id": "lifecycle.commit", "kind": "status-fail"}], "not_comparable": [{"id": "lifecycle.finalize", "status": "BLOCKED"}, {"id": "lifecycle.events", "status": "BLOCKED"}, {"id": "lifecycle.result", "status": "BLOCKED"}, {"id": "control.corrupt-upload", "status": "BLOCKED"}, {"id": "control.truncated-upload", "status": "BLOCKED"}]}, "oracle": "frozen expected trace traces/expected-lifecycle-v3.jsonl, written from the published contract, with a no-request branch for files committed at register", "status": "FAIL", "transport": "FAKE_HUNTER", "ts": "2026-10-12T13:02:48.324Z"} +{"expected": "after a successful restart the capture still reports its terminal status and run", "id": "control.restart-recovery", "observed": {"note": "restart-not-configured"}, "oracle": "operator restart command, then the baseline capture is read again over the published events and result routes", "status": "NOT_RUN", "transport": "FAKE_HUNTER", "ts": "2026-10-12T13:02:48.324Z"} +{"expected": "not run", "id": "gpu-stub.objects", "observed": {"note": "gpu-not-authorized"}, "oracle": "GPU-dependent arms are named and never executed by this harness", "status": "NOT_RUN", "transport": "GPU_STUB", "ts": "2026-10-12T13:02:48.324Z"} +{"expected": "not run", "id": "gpu-stub.vlm", "observed": {"note": "gpu-not-authorized"}, "oracle": "GPU-dependent arms are named and never executed by this harness", "status": "NOT_RUN", "transport": "GPU_STUB", "ts": "2026-10-12T13:02:48.324Z"} +{"expected": "not run", "id": "gpu-stub.dense", "observed": {"note": "gpu-not-authorized"}, "oracle": "GPU-dependent arms are named and never executed by this harness", "status": "NOT_RUN", "transport": "GPU_STUB", "ts": "2026-10-12T13:02:48.324Z"} diff --git a/tools/hunter-local-ingest/evidence/aa10463/commit-batch-semantic-fail/batch-fail-20261012T130248Z-191f85151f05e372/privacy-chain.jsonl b/tools/hunter-local-ingest/evidence/aa10463/commit-batch-semantic-fail/batch-fail-20261012T130248Z-191f85151f05e372/privacy-chain.jsonl new file mode 100644 index 000000000..dc1d0eff7 --- /dev/null +++ b/tools/hunter-local-ingest/evidence/aa10463/commit-batch-semantic-fail/batch-fail-20261012T130248Z-191f85151f05e372/privacy-chain.jsonl @@ -0,0 +1,4 @@ +{"artifact": "run-manifest.json", "at": "2026-10-12T13:02:48.296Z", "bytes": 3492, "chain_sha256": "488c09980311247a90ee8850dbb5142e08e4184b150c88fd81a9adb5939fc624", "sha256": "301976851fddada9c169cd88ea031c6adecf132a6a9c27303a0b9ff53762f226"} +{"artifact": "checks.jsonl", "at": "2026-10-12T13:02:48.324Z", "bytes": 10959, "chain_sha256": "db2455181a02d5ac6f2bce1150ab503267f6a299819b3bb5d3c094d3820ba31f", "sha256": "0513a460e14c9ce043d7a08059f916e1c73bdc9a7f391331e0b4800691b15c43"} +{"artifact": "summary.json", "at": "2026-10-12T13:02:48.324Z", "bytes": 1536, "chain_sha256": "72b66477aa4fb11c338231cd3bcdcb7c8954cd336d82d375c3e39f8b8bee3e24", "sha256": "ad930d245a271879630539e1dab938d61ba83db4d137e23db12a4af8da248f81"} +{"artifact": "privacy-screen.json", "at": "2026-10-12T13:02:48.329Z", "bytes": 238, "chain_sha256": "f89e9b6c23963e06d81f29c665be8ba12e9569c7528ae7f79015eebb4e3ddae2", "sha256": "293993f78f077d1ed4bf6cda674f6804029c9a7f81286e9cd8d07ed6adabd4a1"} diff --git a/tools/hunter-local-ingest/evidence/aa10463/commit-batch-semantic-fail/batch-fail-20261012T130248Z-191f85151f05e372/privacy-screen.json b/tools/hunter-local-ingest/evidence/aa10463/commit-batch-semantic-fail/batch-fail-20261012T130248Z-191f85151f05e372/privacy-screen.json new file mode 100644 index 000000000..a0e013624 --- /dev/null +++ b/tools/hunter-local-ingest/evidence/aa10463/commit-batch-semantic-fail/batch-fail-20261012T130248Z-191f85151f05e372/privacy-screen.json @@ -0,0 +1,12 @@ +{ + "clean": true, + "findings": [], + "finished_utc": "2026-10-12T13:02:48.329Z", + "missing": [], + "schema": "hunter-local-ingest/privacy-screen/2", + "screened": [ + "run-manifest.json", + "checks.jsonl", + "summary.json" + ] +} diff --git a/tools/hunter-local-ingest/evidence/aa10463/commit-batch-semantic-fail/batch-fail-20261012T130248Z-191f85151f05e372/run-manifest.json b/tools/hunter-local-ingest/evidence/aa10463/commit-batch-semantic-fail/batch-fail-20261012T130248Z-191f85151f05e372/run-manifest.json new file mode 100644 index 000000000..a47e2f202 --- /dev/null +++ b/tools/hunter-local-ingest/evidence/aa10463/commit-batch-semantic-fail/batch-fail-20261012T130248Z-191f85151f05e372/run-manifest.json @@ -0,0 +1,111 @@ +{ + "backend": { + "declared_mode": "FAKE_HUNTER", + "declared_ref": null, + "verified": false + }, + "client": { + "declared_ref": null, + "git": null, + "interface": "2.0.0", + "package_version": "0.2.0", + "source_sha256": "ddb7f24f4ebcb814564578776393ac88584b393e6e2a35ca5f65b06f97640c28" + }, + "command": [ + "--endpoint", + "127.0.0.1:64096", + "--plan-file", + "", + "--out", + "", + "--label", + "batch-fail", + "--backend-mode", + "FAKE_HUNTER", + "--poll-interval-s", + "0.05", + "--events-wait-s", + "0", + "--retry-backoff-s", + "0.0", + "--result-budget-s", + "30.0", + "--max-retries", + "0" + ], + "created_utc": "2026-10-12T13:02:48.289Z", + "endpoint": "127.0.0.1:64096", + "fixture": { + "create_sha256": "9c2dd5f33bb70b7199e85f165e87602986faa7f6b5beaee6f55db4f1f9edce97", + "files": [ + { + "bytes": 65536, + "contentType": "application/octet-stream", + "path": "synthetic/scan00.bin", + "role": "other", + "sha256": "a1ca0aa5e471b98beddf42738d706871542520398ced6f3ed81008e8c9812d85" + }, + { + "bytes": 65536, + "contentType": "application/octet-stream", + "path": "synthetic/scan01.bin", + "role": "other", + "sha256": "ef4380c88a7e0a2df7506640f6b435b153122e01070d7570870ebd2d3367d4be" + }, + { + "bytes": 65536, + "contentType": "application/octet-stream", + "path": "synthetic/scan02.bin", + "role": "other", + "sha256": "3fda1dfcabd6f77b655435c16a6c7b75d5f2f2b4ef9dccd814fede0f2b69e1f1" + }, + { + "bytes": 9793, + "contentType": "application/gzip", + "path": "streams/arkit_poses.csv.gz", + "role": "stream", + "sha256": "a23bcec6f6829c053e7bc1871999ca7b1a5e88639b5a6cde56afc655d3447388" + }, + { + "bytes": 9443, + "contentType": "application/gzip", + "path": "streams/imu_raw.csv.gz", + "role": "stream", + "sha256": "ae96d9008b71882aeb0dbc1c5463897aa9c316fbda28d5503b4676e0bd85a161" + } + ], + "format_version": 2, + "generator": "gen_synthetic_packet", + "packet_id": "synthetic-000001", + "packet_sha256": "9ab561f503ef3dc0c0e5b007157ab40c803d5b43dc38136285a72ab77acd17d1", + "plan_file_sha256": "eabf28a3f818ee22d38cec91ad6d85af6921f5cb45156378a007475368ab692f", + "plan_sha256": "50f73a67aeb28e5e0c41f40946958a2806024f75ae56dda1384025ccd0a8e4ac", + "seed": 1 + }, + "label": "batch-fail", + "origin_note": "Derived from published client behavior in HouseScanKit upload and result sources at alpha 263827ef. No private source, schema, spec, log or credential material appears in this package or its receipts.", + "restart": { + "argv": [], + "configured": false, + "timeout_s": 120.0 + }, + "run_id": "191f85151f05e372", + "runtime": { + "cpus": 12, + "implementation": "CPython", + "machine": "arm64", + "python": "3.13.12", + "release": "25.6.0", + "system": "Darwin" + }, + "sanitization": "Every value here passed the typed export schema before it was written: published enum words, package constants, digests, bounded numbers, and the plan's own synthetic paths and packet ids. A pattern screen then ran over the written files.", + "schema": "hunter-local-ingest/run-manifest/2", + "settings": { + "events_wait_s": 0, + "max_retries": 0, + "poll_interval_s": 0.05, + "result_budget_s": 30.0, + "retry_backoff_s": 0.0, + "with_faults": false + } +} diff --git a/tools/hunter-local-ingest/evidence/aa10463/commit-batch-semantic-fail/batch-fail-20261012T130248Z-191f85151f05e372/summary.json b/tools/hunter-local-ingest/evidence/aa10463/commit-batch-semantic-fail/batch-fail-20261012T130248Z-191f85151f05e372/summary.json new file mode 100644 index 000000000..bbcfad804 --- /dev/null +++ b/tools/hunter-local-ingest/evidence/aa10463/commit-batch-semantic-fail/batch-fail-20261012T130248Z-191f85151f05e372/summary.json @@ -0,0 +1,51 @@ +{ + "artifacts": { + "checks.jsonl": "0513a460e14c9ce043d7a08059f916e1c73bdc9a7f391331e0b4800691b15c43", + "run-manifest.json": "301976851fddada9c169cd88ea031c6adecf132a6a9c27303a0b9ff53762f226" + }, + "blocked": [ + "lifecycle.finalize", + "lifecycle.events", + "lifecycle.result", + "control.corrupt-upload", + "control.truncated-upload" + ], + "counts_by_transport": { + "FAKE_HUNTER": { + "BLOCKED": 5, + "FAIL": 2, + "NOT_RUN": 1, + "PASS": 6 + }, + "GPU_STUB": { + "NOT_RUN": 3 + } + }, + "failed": [ + "lifecycle.commit", + "trace.expected-lifecycle-v3" + ], + "finished_utc": "2026-10-12T13:02:48.324Z", + "lead_questions": [ + "Amendment semantics: does the published contract allow amending a registered capture, and with which route and headers?", + "--api-token-env opts into HUNTER_API_TOKEN for scoped API routes; token-protected proxy fault coverage remains BLOCKED.", + "Clock and expiry authority: whose clock governs capture expiry on the local backend?", + "Homeowner text: confirm that receipts may carry outcome kinds and counts but never messages, prompts or reasons." + ], + "mode": { + "backend_verified": false, + "declared_backend": "FAKE_HUNTER", + "gpu_arms": "NOT_RUN", + "real_mirror_cpu": "NOT_ESTABLISHED" + }, + "not_run": [ + "control.restart-recovery", + "gpu-stub.objects", + "gpu-stub.vlm", + "gpu-stub.dense" + ], + "run_id": "191f85151f05e372", + "schema": "hunter-local-ingest/summary/2", + "total": 17, + "verdict": "FAIL" +} diff --git a/tools/hunter-local-ingest/evidence/aa10463/decimal-cursor-exact/decimal-cursor-20261012T130249Z-6f398a7fc05434a5/checks.jsonl b/tools/hunter-local-ingest/evidence/aa10463/decimal-cursor-exact/decimal-cursor-20261012T130249Z-6f398a7fc05434a5/checks.jsonl new file mode 100644 index 000000000..38886a246 --- /dev/null +++ b/tools/hunter-local-ingest/evidence/aa10463/decimal-cursor-exact/decimal-cursor-20261012T130249Z-6f398a7fc05434a5/checks.jsonl @@ -0,0 +1,17 @@ +{"expected": "an HTTP 2xx answer with status ok", "id": "lifecycle.health", "observed": {"contract": {"status": "ok"}, "http": {"attempts": 1, "body_bytes": 16, "body_sha256": "08e2c358ce13", "elapsed_ms": 1, "fields": ["status"], "http_status": 200, "shape": "object"}, "violations": []}, "oracle": "tools/integration-viewer reads GET /v1/healthz; HouseScanKit never calls it", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T13:02:49.520Z"} +{"expected": "2xx, a captureId and a published capture status", "id": "lifecycle.create", "observed": {"contract": {"captureId": "id:fd102437f369", "maxBatch": 50, "status": "uploading"}, "http": {"attempts": 1, "body_bytes": 78, "body_sha256": "8edf48cf4ce9", "elapsed_ms": 0, "fields": ["captureId", "status", "upload"], "http_status": 201, "shape": "object"}, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.create: POST captures with Idempotency-Key=packetId; the answer decodes as CaptureAPI.CreateResponse", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T13:02:49.521Z"} +{"expected": "every requested path answered exactly once, no other path, each committed or given a usable PUT target", "id": "lifecycle.register", "observed": {"batches": [{"contract": {"files": [{"path": "synthetic/scan00.bin", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "synthetic/scan01.bin", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "synthetic/scan02.bin", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "streams/arkit_poses.csv.gz", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}, {"path": "streams/imu_raw.csv.gz", "state": "pending", "upload": {"method": "PUT", "signed_content_type": true, "signed_header_count": 1, "signs_auth_header": false, "url_policy": "ok", "url_present": true}}]}, "http": {"attempts": 1, "body_bytes": 1253, "body_sha256": "4420c8994748", "elapsed_ms": 1, "fields": ["files"], "http_status": 200, "shape": "object"}, "violations": []}], "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.register: the answer decodes as RegisterResponse and is applied by path; a target needs method PUT and a URL that passes uploadURLProblem", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T13:02:49.523Z"} +{"expected": "2xx for every file that got a target", "id": "lifecycle.upload", "observed": {"committed_at_register": [], "uploads": [{"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 1, "fields": [], "http_status": 200, "path": "synthetic/scan00.bin", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 1, "fields": [], "http_status": 200, "path": "synthetic/scan01.bin", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 1, "fields": [], "http_status": 200, "path": "synthetic/scan02.bin", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "streams/arkit_poses.csv.gz", "shape": "empty"}, {"attempts": 1, "body_bytes": 0, "body_sha256": null, "elapsed_ms": 0, "fields": [], "http_status": 200, "path": "streams/imu_raw.csv.gz", "shape": "empty"}]}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.put + ScopedCaptureHTTP.upload: exactly the signed headers, never Authorization", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T13:02:49.528Z"} +{"expected": "committed equals the uploaded set; notFound and mismatch empty; every declared path committed by register or commit", "id": "lifecycle.commit", "observed": {"batches": [{"contract": {"committed": ["synthetic/scan00.bin", "synthetic/scan01.bin", "synthetic/scan02.bin", "streams/arkit_poses.csv.gz", "streams/imu_raw.csv.gz"], "mismatch": [], "notFound": []}, "http": {"attempts": 1, "body_bytes": 175, "body_sha256": "ab0d647d58c4", "elapsed_ms": 0, "fields": ["committed", "mismatch", "notFound"], "http_status": 200, "shape": "object"}, "violations": []}], "committed_at_register": [], "committed_total": 5, "declared": 5, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.commit: only a commit acknowledges a file; CommitResponse carries committed, notFound and mismatch", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T13:02:49.529Z"} +{"expected": "2xx, a runId, a published status, no missing file", "id": "lifecycle.finalize", "observed": {"contract": {"missing": [], "runId": "id:492e113d2d27", "status": "processing"}, "http": {"attempts": 1, "body_bytes": 62, "body_sha256": "425e9d06a56d", "elapsed_ms": 0, "fields": ["missing", "runId", "status"], "http_status": 202, "shape": "object"}, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.finalize: X-Packet-Sha256 and Idempotency-Key=packetId; the answer decodes as FinalizeResponse", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T13:02:49.530Z"} +{"expected": "a terminal status within the budget, every answer contract-shaped", "id": "lifecycle.events", "observed": {"answers": 2, "finalize_retries": 1, "last": {"contract": {"events": [{"data": {"runId": "id:cf644efe509d", "runId_matches": true}, "seq": "large-int:6d41a97fe195", "type": "verdict_ready"}], "next": "large-int:6d41a97fe195", "status": "complete"}, "http": {"attempts": 1, "body_bytes": 185, "body_sha256": "387e7adf1285", "elapsed_ms": 0, "fields": ["events", "next", "status"], "http_status": 200, "shape": "object"}, "violations": []}}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.pollEvents: EventsResponse until CaptureAPI.terminalStatuses; next never moves back; a verdict names this run; retry_finalize re-sends the packet", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T13:02:49.534Z"} +{"expected": "a decodable result for this run whose status matches the terminal event status", "id": "lifecycle.result", "observed": {"contract": {"criteria": null, "has_preview_url": false, "memberActions": 0, "outcome": {"kind": "eligible", "reasons": 0}, "runId": "id:cf644efe509d", "status": "complete", "viewsNeeded": 0}, "http": {"attempts": 1, "body_bytes": 227, "body_sha256": "f94cf21efd4a", "elapsed_ms": 0, "fields": ["memberActions", "outcome", "runId", "status", "viewsNeeded"], "http_status": 200, "shape": "object"}, "not_ready_reads": 0, "run_matches": true, "status_matches": true, "terminal_status": "complete", "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.fetchResult: the whole body decodes as CaptureResult.Response, its runId is the finalized run, and a null outcome is final only under statusesWithoutOutcome", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T13:02:49.534Z"} +{"expected": "both creates 2xx with the same captureId", "id": "control.idempotent-create", "observed": {"first": {"contract": {"captureId": "id:dd2bb63acf68", "maxBatch": 50, "status": "uploading"}, "http": {"attempts": 1, "body_bytes": 78, "body_sha256": "4e3aebf20321", "elapsed_ms": 0, "fields": ["captureId", "status", "upload"], "http_status": 201, "shape": "object"}, "violations": []}, "same_capture": true, "second": {"contract": {"captureId": "id:dd2bb63acf68", "maxBatch": 50, "status": "uploading"}, "http": {"attempts": 1, "body_bytes": 78, "body_sha256": "4e3aebf20321", "elapsed_ms": 0, "fields": ["captureId", "status", "upload"], "http_status": 200, "shape": "object"}, "violations": []}}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.start: create is bound to Idempotency-Key=packetId, so a repeated create with the same bytes names the same capture", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T13:02:49.536Z"} +{"expected": "intact files committed; the flipped file in mismatch or notFound, or its PUT refused, and never committed", "id": "control.corrupt-upload", "observed": {"batches": [{"contract": {"committed": ["synthetic/scan01.bin", "synthetic/scan02.bin", "streams/arkit_poses.csv.gz", "streams/imu_raw.csv.gz"], "mismatch": ["synthetic/scan00.bin"], "notFound": []}, "http": {"attempts": 1, "body_bytes": 173, "body_sha256": "b6f8e6ec4d66", "elapsed_ms": 0, "fields": ["committed", "mismatch", "notFound"], "http_status": 200, "shape": "object"}, "violations": []}], "intact_committed": true, "intact_reported_negative": false, "tampered": "synthetic/scan00.bin", "tampered_committed": false, "tampered_put_status": 200, "tampered_reported": true, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CommitResponse separates committed from mismatch/notFound; one file's bytes are flipped after its digest was registered", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T13:02:49.542Z"} +{"expected": "intact files committed; the truncated file in mismatch or notFound, or its PUT refused, and never committed", "id": "control.truncated-upload", "observed": {"batches": [{"contract": {"committed": ["synthetic/scan01.bin", "synthetic/scan02.bin", "streams/arkit_poses.csv.gz", "streams/imu_raw.csv.gz"], "mismatch": ["synthetic/scan00.bin"], "notFound": []}, "http": {"attempts": 1, "body_bytes": 173, "body_sha256": "b6f8e6ec4d66", "elapsed_ms": 0, "fields": ["committed", "mismatch", "notFound"], "http_status": 200, "shape": "object"}, "violations": []}], "intact_committed": true, "intact_reported_negative": false, "tampered": "synthetic/scan00.bin", "tampered_committed": false, "tampered_put_status": 200, "tampered_reported": true, "violations": []}, "oracle": "HouseScanKit @ alpha 263827ef CommitResponse separates committed from mismatch/notFound; one file loses its last byte after its digest was registered", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T13:02:49.547Z"} +{"expected": "404 with error code capture_not_found for an id the harness invented", "id": "control.wrong-capture", "observed": {"capture": "id:1976512104be", "errors": {"codes": ["capture_not_found"]}, "http": {"attempts": 1, "body_bytes": 43, "body_sha256": "23553eb17fe9", "elapsed_ms": 0, "fields": ["errors"], "http_status": 404, "shape": "object"}}, "oracle": "HouseScanKit @ alpha 263827ef CaptureUploader.captureGone: an unknown capture answers 404 capture_not_found", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T13:02:49.547Z"} +{"expected": "every traced check present and PASS with the traced status class and fields, or upload and commit skipped because register reported every declared file committed", "id": "trace.expected-lifecycle-v3", "observed": {"compared": 12, "disagreements": [], "not_comparable": []}, "oracle": "frozen expected trace traces/expected-lifecycle-v3.jsonl, written from the published contract, with a no-request branch for files committed at register", "status": "PASS", "transport": "FAKE_HUNTER", "ts": "2026-10-12T13:02:49.549Z"} +{"expected": "after a successful restart the capture still reports its terminal status and run", "id": "control.restart-recovery", "observed": {"note": "restart-not-configured"}, "oracle": "operator restart command, then the baseline capture is read again over the published events and result routes", "status": "NOT_RUN", "transport": "FAKE_HUNTER", "ts": "2026-10-12T13:02:49.549Z"} +{"expected": "not run", "id": "gpu-stub.objects", "observed": {"note": "gpu-not-authorized"}, "oracle": "GPU-dependent arms are named and never executed by this harness", "status": "NOT_RUN", "transport": "GPU_STUB", "ts": "2026-10-12T13:02:49.549Z"} +{"expected": "not run", "id": "gpu-stub.vlm", "observed": {"note": "gpu-not-authorized"}, "oracle": "GPU-dependent arms are named and never executed by this harness", "status": "NOT_RUN", "transport": "GPU_STUB", "ts": "2026-10-12T13:02:49.549Z"} +{"expected": "not run", "id": "gpu-stub.dense", "observed": {"note": "gpu-not-authorized"}, "oracle": "GPU-dependent arms are named and never executed by this harness", "status": "NOT_RUN", "transport": "GPU_STUB", "ts": "2026-10-12T13:02:49.549Z"} diff --git a/tools/hunter-local-ingest/evidence/aa10463/decimal-cursor-exact/decimal-cursor-20261012T130249Z-6f398a7fc05434a5/privacy-chain.jsonl b/tools/hunter-local-ingest/evidence/aa10463/decimal-cursor-exact/decimal-cursor-20261012T130249Z-6f398a7fc05434a5/privacy-chain.jsonl new file mode 100644 index 000000000..316dfb0ef --- /dev/null +++ b/tools/hunter-local-ingest/evidence/aa10463/decimal-cursor-exact/decimal-cursor-20261012T130249Z-6f398a7fc05434a5/privacy-chain.jsonl @@ -0,0 +1,4 @@ +{"artifact": "run-manifest.json", "at": "2026-10-12T13:02:49.517Z", "bytes": 3500, "chain_sha256": "085ced3b4b53af8cd6489ac18d676aa52a21f1e15c989fce89a9daf25678cb31", "sha256": "7ae7395c2adc4b3b784e499b198a004aa33f8af22a7d4c973a07565c27c9ea80"} +{"artifact": "checks.jsonl", "at": "2026-10-12T13:02:49.549Z", "bytes": 12441, "chain_sha256": "23d959ad1747cc83fbb4b7087cbe64533baa4d4c8e38ae584d0d8dd8d10bacfc", "sha256": "b46988fe2f0b322e05c694d135632be4362ee134777576c65fb3c4ec60862886"} +{"artifact": "summary.json", "at": "2026-10-12T13:02:49.550Z", "bytes": 1301, "chain_sha256": "ad6f2feb2db8a7a23c6b4faa45b0c8e369ed5cb2c34389291604f8362ae974de", "sha256": "c9fd0969f93f1bae0c23f2fa848a6aa406657da67fab73537b994030a4ce2278"} +{"artifact": "privacy-screen.json", "at": "2026-10-12T13:02:49.555Z", "bytes": 238, "chain_sha256": "c96011eb0b78ad34ea1407ddc04476b1bd40cc75a9100e6a55ad7f7e9a26d364", "sha256": "ae14151223d3688ec0370bdee3857ba9f545007ba73255ec40f923e160feca24"} diff --git a/tools/hunter-local-ingest/evidence/aa10463/decimal-cursor-exact/decimal-cursor-20261012T130249Z-6f398a7fc05434a5/privacy-screen.json b/tools/hunter-local-ingest/evidence/aa10463/decimal-cursor-exact/decimal-cursor-20261012T130249Z-6f398a7fc05434a5/privacy-screen.json new file mode 100644 index 000000000..20d1475d2 --- /dev/null +++ b/tools/hunter-local-ingest/evidence/aa10463/decimal-cursor-exact/decimal-cursor-20261012T130249Z-6f398a7fc05434a5/privacy-screen.json @@ -0,0 +1,12 @@ +{ + "clean": true, + "findings": [], + "finished_utc": "2026-10-12T13:02:49.555Z", + "missing": [], + "schema": "hunter-local-ingest/privacy-screen/2", + "screened": [ + "run-manifest.json", + "checks.jsonl", + "summary.json" + ] +} diff --git a/tools/hunter-local-ingest/evidence/aa10463/decimal-cursor-exact/decimal-cursor-20261012T130249Z-6f398a7fc05434a5/run-manifest.json b/tools/hunter-local-ingest/evidence/aa10463/decimal-cursor-exact/decimal-cursor-20261012T130249Z-6f398a7fc05434a5/run-manifest.json new file mode 100644 index 000000000..2a5190b8a --- /dev/null +++ b/tools/hunter-local-ingest/evidence/aa10463/decimal-cursor-exact/decimal-cursor-20261012T130249Z-6f398a7fc05434a5/run-manifest.json @@ -0,0 +1,111 @@ +{ + "backend": { + "declared_mode": "FAKE_HUNTER", + "declared_ref": null, + "verified": false + }, + "client": { + "declared_ref": null, + "git": null, + "interface": "2.0.0", + "package_version": "0.2.0", + "source_sha256": "ddb7f24f4ebcb814564578776393ac88584b393e6e2a35ca5f65b06f97640c28" + }, + "command": [ + "--endpoint", + "127.0.0.1:64135", + "--plan-file", + "", + "--out", + "", + "--label", + "decimal-cursor", + "--backend-mode", + "FAKE_HUNTER", + "--poll-interval-s", + "0.05", + "--events-wait-s", + "0", + "--retry-backoff-s", + "0.0", + "--result-budget-s", + "30.0", + "--max-retries", + "0" + ], + "created_utc": "2026-10-12T13:02:49.508Z", + "endpoint": "127.0.0.1:64135", + "fixture": { + "create_sha256": "9c2dd5f33bb70b7199e85f165e87602986faa7f6b5beaee6f55db4f1f9edce97", + "files": [ + { + "bytes": 65536, + "contentType": "application/octet-stream", + "path": "synthetic/scan00.bin", + "role": "other", + "sha256": "a1ca0aa5e471b98beddf42738d706871542520398ced6f3ed81008e8c9812d85" + }, + { + "bytes": 65536, + "contentType": "application/octet-stream", + "path": "synthetic/scan01.bin", + "role": "other", + "sha256": "ef4380c88a7e0a2df7506640f6b435b153122e01070d7570870ebd2d3367d4be" + }, + { + "bytes": 65536, + "contentType": "application/octet-stream", + "path": "synthetic/scan02.bin", + "role": "other", + "sha256": "3fda1dfcabd6f77b655435c16a6c7b75d5f2f2b4ef9dccd814fede0f2b69e1f1" + }, + { + "bytes": 9793, + "contentType": "application/gzip", + "path": "streams/arkit_poses.csv.gz", + "role": "stream", + "sha256": "a23bcec6f6829c053e7bc1871999ca7b1a5e88639b5a6cde56afc655d3447388" + }, + { + "bytes": 9443, + "contentType": "application/gzip", + "path": "streams/imu_raw.csv.gz", + "role": "stream", + "sha256": "ae96d9008b71882aeb0dbc1c5463897aa9c316fbda28d5503b4676e0bd85a161" + } + ], + "format_version": 2, + "generator": "gen_synthetic_packet", + "packet_id": "synthetic-000001", + "packet_sha256": "9ab561f503ef3dc0c0e5b007157ab40c803d5b43dc38136285a72ab77acd17d1", + "plan_file_sha256": "eabf28a3f818ee22d38cec91ad6d85af6921f5cb45156378a007475368ab692f", + "plan_sha256": "50f73a67aeb28e5e0c41f40946958a2806024f75ae56dda1384025ccd0a8e4ac", + "seed": 1 + }, + "label": "decimal-cursor", + "origin_note": "Derived from published client behavior in HouseScanKit upload and result sources at alpha 263827ef. No private source, schema, spec, log or credential material appears in this package or its receipts.", + "restart": { + "argv": [], + "configured": false, + "timeout_s": 120.0 + }, + "run_id": "6f398a7fc05434a5", + "runtime": { + "cpus": 12, + "implementation": "CPython", + "machine": "arm64", + "python": "3.13.12", + "release": "25.6.0", + "system": "Darwin" + }, + "sanitization": "Every value here passed the typed export schema before it was written: published enum words, package constants, digests, bounded numbers, and the plan's own synthetic paths and packet ids. A pattern screen then ran over the written files.", + "schema": "hunter-local-ingest/run-manifest/2", + "settings": { + "events_wait_s": 0, + "max_retries": 0, + "poll_interval_s": 0.05, + "result_budget_s": 30.0, + "retry_backoff_s": 0.0, + "with_faults": false + } +} diff --git a/tools/hunter-local-ingest/evidence/aa10463/decimal-cursor-exact/decimal-cursor-20261012T130249Z-6f398a7fc05434a5/summary.json b/tools/hunter-local-ingest/evidence/aa10463/decimal-cursor-exact/decimal-cursor-20261012T130249Z-6f398a7fc05434a5/summary.json new file mode 100644 index 000000000..2544fe6fd --- /dev/null +++ b/tools/hunter-local-ingest/evidence/aa10463/decimal-cursor-exact/decimal-cursor-20261012T130249Z-6f398a7fc05434a5/summary.json @@ -0,0 +1,40 @@ +{ + "artifacts": { + "checks.jsonl": "b46988fe2f0b322e05c694d135632be4362ee134777576c65fb3c4ec60862886", + "run-manifest.json": "7ae7395c2adc4b3b784e499b198a004aa33f8af22a7d4c973a07565c27c9ea80" + }, + "blocked": [], + "counts_by_transport": { + "FAKE_HUNTER": { + "NOT_RUN": 1, + "PASS": 13 + }, + "GPU_STUB": { + "NOT_RUN": 3 + } + }, + "failed": [], + "finished_utc": "2026-10-12T13:02:49.549Z", + "lead_questions": [ + "Amendment semantics: does the published contract allow amending a registered capture, and with which route and headers?", + "--api-token-env opts into HUNTER_API_TOKEN for scoped API routes; token-protected proxy fault coverage remains BLOCKED.", + "Clock and expiry authority: whose clock governs capture expiry on the local backend?", + "Homeowner text: confirm that receipts may carry outcome kinds and counts but never messages, prompts or reasons." + ], + "mode": { + "backend_verified": false, + "declared_backend": "FAKE_HUNTER", + "gpu_arms": "NOT_RUN", + "real_mirror_cpu": "NOT_ESTABLISHED" + }, + "not_run": [ + "control.restart-recovery", + "gpu-stub.objects", + "gpu-stub.vlm", + "gpu-stub.dense" + ], + "run_id": "6f398a7fc05434a5", + "schema": "hunter-local-ingest/summary/2", + "total": 17, + "verdict": "PASS" +} diff --git a/tools/hunter-local-ingest/evidence/aa10463/index.json b/tools/hunter-local-ingest/evidence/aa10463/index.json new file mode 100644 index 000000000..c1ac50f46 --- /dev/null +++ b/tools/hunter-local-ingest/evidence/aa10463/index.json @@ -0,0 +1,65 @@ +{ + "committed_source_sha256": "ddb7f24f4ebcb814564578776393ac88584b393e6e2a35ca5f65b06f97640c28", + "installed_source_sha256": "ddb7f24f4ebcb814564578776393ac88584b393e6e2a35ca5f65b06f97640c28", + "plan_sha256": "eabf28a3f818ee22d38cec91ad6d85af6921f5cb45156378a007475368ab692f", + "runs": { + "bearer-trailing-lf": { + "category_reported": true, + "exit_code": 2, + "out_dir_created": false, + "requests_sent": 0, + "token_occurrences_in_output": 0 + }, + "commit-batch-semantic-fail": { + "artifacts": { + "checks.jsonl": "0513a460e14c9ce043d7a08059f916e1c73bdc9a7f391331e0b4800691b15c43", + "privacy-chain.jsonl": "17c7240152810828aee2cb8bfac6c5b19d8367a9a10330fa182ded7bb3b9b780", + "privacy-screen.json": "293993f78f077d1ed4bf6cda674f6804029c9a7f81286e9cd8d07ed6adabd4a1", + "run-manifest.json": "301976851fddada9c169cd88ea031c6adecf132a6a9c27303a0b9ff53762f226", + "summary.json": "ad930d245a271879630539e1dab938d61ba83db4d137e23db12a4af8da248f81" + }, + "blocked": [ + "lifecycle.finalize", + "lifecycle.events", + "lifecycle.result", + "control.corrupt-upload", + "control.truncated-upload" + ], + "chain_head": "f89e9b6c23963e06d81f29c665be8ba12e9569c7528ae7f79015eebb4e3ddae2", + "commit_requests": 3, + "exit_code": 1, + "failed": [ + "lifecycle.commit", + "trace.expected-lifecycle-v3" + ], + "lifecycle_commit": "FAIL", + "lifecycle_commit_batches": 1, + "lifecycle_events": "BLOCKED", + "run_dir": "batch-fail-20261012T130248Z-191f85151f05e372", + "verdict": "FAIL", + "verify_exit": 0, + "verify_last_line": "verify: OK" + }, + "decimal-cursor-exact": { + "artifacts": { + "checks.jsonl": "b46988fe2f0b322e05c694d135632be4362ee134777576c65fb3c4ec60862886", + "privacy-chain.jsonl": "d830753bf8e74b59bd22da10b41495b97c256b47ec98050f64efe97b515c58b6", + "privacy-screen.json": "ae14151223d3688ec0370bdee3857ba9f545007ba73255ec40f923e160feca24", + "run-manifest.json": "7ae7395c2adc4b3b784e499b198a004aa33f8af22a7d4c973a07565c27c9ea80", + "summary.json": "c9fd0969f93f1bae0c23f2fa848a6aa406657da67fab73537b994030a4ce2278" + }, + "blocked": [], + "chain_head": "c96011eb0b78ad34ea1407ddc04476b1bd40cc75a9100e6a55ad7f7e9a26d364", + "exit_code": 0, + "failed": [], + "lifecycle_commit": "PASS", + "lifecycle_events": "PASS", + "polled_exact_cursor": true, + "polled_rounded_cursor": false, + "run_dir": "decimal-cursor-20261012T130249Z-6f398a7fc05434a5", + "verdict": "PASS", + "verify_exit": 0, + "verify_last_line": "verify: OK" + } + } +} diff --git a/tools/hunter-local-ingest/fixtures/gen_synthetic_packet.py b/tools/hunter-local-ingest/fixtures/gen_synthetic_packet.py new file mode 100644 index 000000000..214712a6e --- /dev/null +++ b/tools/hunter-local-ingest/fixtures/gen_synthetic_packet.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python3 +"""Repo entry point for the synthetic plan generator. + +The generator lives in the package (src/hunter_local_ingest/fixturegen.py) +so an installed copy has it too (``hunter-gen-plan``). This wrapper puts +the checkout's src/ on the import path, so it runs without installing. +""" + +import sys +from pathlib import Path + +sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src")) + +from hunter_local_ingest.fixturegen import main # noqa: E402 + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tools/hunter-local-ingest/pyproject.toml b/tools/hunter-local-ingest/pyproject.toml new file mode 100644 index 000000000..458660f6d --- /dev/null +++ b/tools/hunter-local-ingest/pyproject.toml @@ -0,0 +1,37 @@ +[build-system] +requires = ["setuptools>=68"] +build-backend = "setuptools.build_meta" + +[project] +name = "hunter-local-ingest" +version = "0.2.0" +description = "Published-client checks against a local capture API, with labeled fault controls and validated, screened, chained receipts." +requires-python = ">=3.11" + +[project.optional-dependencies] +dev = ["pytest>=8"] + +[project.scripts] +hunter-local-ingest = "hunter_local_ingest.runner:main" +hunter-selfcheck = "hunter_local_ingest.selfcheck:main" +hunter-verify-run = "hunter_local_ingest.verify:main" +hunter-gen-plan = "hunter_local_ingest.fixturegen:main" + +[tool.setuptools.packages.find] +where = ["src"] + +# Frozen expected traces live in src/hunter_local_ingest/traces/ and ship as +# package data; traces.py reads them with importlib.resources, so an +# installed copy finds them without the repo checkout. +[tool.setuptools.package-data] +hunter_local_ingest = ["traces/*.jsonl"] + +[tool.pytest.ini_options] +testpaths = ["tests"] + +[tool.ruff] +line-length = 100 +target-version = "py311" + +[tool.ruff.lint] +select = ["E", "F", "W", "I", "UP", "B"] diff --git a/tools/hunter-local-ingest/src/hunter_local_ingest/__init__.py b/tools/hunter-local-ingest/src/hunter_local_ingest/__init__.py new file mode 100644 index 000000000..0259ecac0 --- /dev/null +++ b/tools/hunter-local-ingest/src/hunter_local_ingest/__init__.py @@ -0,0 +1,30 @@ +"""hunter-local-ingest: published-client checks against a local capture API. + +Drives the published HouseScanKit upload lifecycle against one endpoint, +labels how every check ran, and writes receipts that are validated, +screened, chained and sealed in a fresh directory per run. + +Boundaries: +- The package talks to the capture API over HTTP only. No backend + implementation, schema, spec, internal test, fixture or raw log from any + private repository is vendored here. +- Every check names how it ran (Transport.REAL_API, FAKE_HUNTER or GPU_STUB) + and how it ended (PASS, FAIL, BLOCKED, NOT_RUN). REAL_API records what the + operator declared the endpoint to be; the harness cannot verify it. +""" + +from .adapter import INTERFACE_VERSION, HunterIngestAdapter, StepResult +from .modes import Status, Transport +from .observations import Observation + +__version__ = "0.2.0" + +__all__ = [ + "INTERFACE_VERSION", + "HunterIngestAdapter", + "Observation", + "Status", + "StepResult", + "Transport", + "__version__", +] diff --git a/tools/hunter-local-ingest/src/hunter_local_ingest/adapter.py b/tools/hunter-local-ingest/src/hunter_local_ingest/adapter.py new file mode 100644 index 000000000..ea4fdc79c --- /dev/null +++ b/tools/hunter-local-ingest/src/hunter_local_ingest/adapter.py @@ -0,0 +1,96 @@ +"""The client adapter interface, version 2.0.0. + +2.0.0 changed two signatures from 1.0.0. ``create`` takes the encoded body +bytes, because the published client encodes the create body once and +sends those exact bytes on every retry (CaptureUploader.start). ``upload`` +dropped ``capture_id`` and ``path``, which 1.0.0 accepted and ignored. + +Public client code and public scenarios code against this seam, never +against one backend's implementation. + +Derivation: the published wire behavior in +ios/HouseScanKit/Sources/HouseScanKit/Upload/ (CaptureAPI.swift, +CaptureUploader.swift, ScopedCaptureHTTP.swift) on alpha +263827efaa5d600ecd7ed0443b6e7dd05fbef807. Route paths, bodies, headers and +answer types come from that public source, not from any private repository. + +Published semantics carried over deliberately: +- No redirects: a 3xx is returned as its own reply, never followed. +- HTTP error statuses come back as observations; transport failures and + client-side refusals come back as a StepResult ``error`` category. +- ``Idempotency-Key: `` on create and finalize; + ``X-Packet-Sha256`` on finalize. +- A storage PUT carries exactly the headers the register answer signed. + It never carries the API's credential, and a signed set that holds + ``Authorization`` is refused before anything is sent + (``auth_storage_authorization``). +- A transient answer (no answer, 408, 429, or 5xx other than 501) is + retried with the same body a bounded number of times, as + ``CaptureUploader.isTransient`` defines it. + +New steps arrive as new methods with a bumped INTERFACE_VERSION, never as +edits to existing method signatures. +""" + +from __future__ import annotations + +import dataclasses +import typing + +from .observations import Observation + +INTERFACE_VERSION = "2.0.0" + +# Refusals the client makes without sending anything. +CLIENT_REFUSALS = frozenset( + { + "auth_storage_authorization", + "auth_destination_refused", + "upload_url_invalid", + "upload_url_insecure", + } +) + + +@dataclasses.dataclass(frozen=True) +class StepResult: + """One adapter step: an observation, or an error category with no answer.""" + + step: str + observation: Observation | None = None + error: str | None = None + attempts: int = 1 + + @property + def http_status(self) -> int | None: + return self.observation.http_status if self.observation else None + + @property + def parsed(self) -> object: + return self.observation.parsed if self.observation else None + + def public(self) -> dict: + if self.observation is not None: + return self.observation.public() + return {"error": self.error, "attempts": self.attempts} + + +@typing.runtime_checkable +class HunterIngestAdapter(typing.Protocol): + """One capture's lifecycle against the capture API, over HTTP.""" + + def health(self) -> StepResult: ... + + def create(self, body: bytes, idempotency_key: str) -> StepResult: ... + + def register(self, capture_id: str, files: list[dict]) -> StepResult: ... + + def upload(self, url: str, body: bytes, headers: dict[str, str]) -> StepResult: ... + + def commit(self, capture_id: str, files: list[dict]) -> StepResult: ... + + def finalize(self, capture_id: str, packet: bytes, idempotency_key: str) -> StepResult: ... + + def events(self, capture_id: str, after: int, wait_s: int) -> StepResult: ... + + def result(self, capture_id: str) -> StepResult: ... diff --git a/tools/hunter-local-ingest/src/hunter_local_ingest/contract.py b/tools/hunter-local-ingest/src/hunter_local_ingest/contract.py new file mode 100644 index 000000000..ddb7e214e --- /dev/null +++ b/tools/hunter-local-ingest/src/hunter_local_ingest/contract.py @@ -0,0 +1,893 @@ +"""The published capture-API contract: vocabularies and strict response decoders. + +Source of truth, read-only: ios/HouseScanKit/Sources/HouseScanKit on alpha +263827efaa5d600ecd7ed0443b6e7dd05fbef807 — +Upload/CaptureAPI.swift (request and response types, terminal statuses), +Upload/CaptureUploader.swift (what the client reads and how it reacts), +CaptureResult/CaptureResult.swift (the device result), and +Processing/FixtureCaptureHTTP.swift (the public in-process API the package +tests run against). + +Each decoder returns two things: + +- ``data``: typed values for the scenario's PASS/FAIL decision. Never + serialized. +- ``public``: what a receipt may carry. Published enum words appear as + themselves; any other string becomes ``unrecognized:``. Server + identifiers (captureId, runId) become ``id:``. A path appears only + when the run itself declared it; any other becomes + ``unexpected-path:``. Unknown keys become a count and one digest. + A valid Swift Int too large for a receipt number becomes ``large-int:``. + Homeowner text (messages, prompts, reasons) and URLs are never kept. + +A digest is the first 12 hex characters of SHA-256. It lets a reader see +that two lines carry the same value without the value itself. +""" + +from __future__ import annotations + +import dataclasses +import hashlib +import json +import math +from decimal import Decimal + +from .netpolicy import upload_url_problem + +FORMAT_VERSION = "0.4" + +# CaptureResult.Status: every capture status the app knows. +CAPTURE_STATUSES = frozenset( + { + "uploading", + "awaiting_files", + "processing", + "needs_views", + "complete", + "manual_review", + "failed", + "expired", + } +) +# CaptureAPI.terminalStatuses. +TERMINAL_STATUSES = frozenset({"complete", "manual_review", "failed", "expired", "needs_views"}) +# CaptureAPI.statusesWithoutOutcome. +STATUSES_WITHOUT_OUTCOME = frozenset({"failed", "expired"}) +# CaptureResult.OutcomeKind. +OUTCOME_KINDS = frozenset({"eligible", "needs_more_photos", "not_eligible", "manual_review"}) +# Packet04.Role and Packet04.Tier. +ROLES = frozenset({"keyframe", "depth", "confidence", "features", "still", "stream", "other"}) +TIERS = frozenset({"arkit", "arkit_lidar"}) +# RegisteredFile.state: the client branches only on "committed"; the public +# fixture answers "pending" otherwise. +REGISTER_STATES = frozenset({"pending", "committed"}) +# Event types the client reads (verdict_ready, failed). +EVENT_TYPES = frozenset({"verdict_ready", "failed"}) +# EventData.next directive the client follows. +EVENT_DIRECTIVES = frozenset({"retry_finalize"}) +# Error codes the client branches on, plus ScopedCaptureHTTPError codes. +ERROR_CODES = frozenset( + { + "capture_not_found", + "result_not_ready", + "auth_destination_refused", + "auth_credential_unavailable", + "auth_credential_malformed", + "auth_storage_authorization", + } +) +# Codes this package's own fakes and proxy emit. Prefixed so they can never +# be mistaken for a contract code. +HARNESS_CODES = frozenset( + { + "harness_fault", + "harness_origin_unreachable", + "harness_no_route", + "harness_schema", + "harness_packet_id_mismatch", + "harness_forced_500", + } +) +HEALTH_STATUSES = frozenset({"ok"}) + +# --- violation vocabulary --------------------------------------------------- +# +# A violation names a check and a published field, never a value. Every +# string a decoder can emit is enumerated here so the export validator can +# accept exactly this set. + +_FIELDS = ( + "body", + "status", + "captureId", + "upload", + "finalizeBy", + "files", + "path", + "state", + "headers", + "expiresAt", + "committed", + "notFound", + "mismatch", + "missing", + "runId", + "etaS", + "next", + "events", + "seq", + "type", + "at", + "data", + "viewsNeeded", + "memberActions", + "outcome", + "kind", + "criteria", + "reasons", + "errors", + "code", + "profile", + "message", + "arkitEpoch", + "recommendedPlacement", + "boxArkitWorld", + "prompt", + "referenceCrop", + "previewUrl", + "reviewUrl", +) +_KINDS = ("missing", "type", "enum", "range", "duplicate", "unexpected-path", "not-acknowledged") +VIOLATIONS = frozenset(f"{kind}:{field}" for kind in _KINDS for field in _FIELDS) | frozenset( + { + "shape:not-json", + "shape:not-object", + "shape:empty", + "upload_url_invalid", + "upload_url_insecure", + "upload_method", + "order:next", + "order:seq", + "verdict-for-another-run", + "overlap:commit-categories", + } +) + + +def violation(kind: str, field: str) -> str: + text = f"{kind}:{field}" + if text not in VIOLATIONS: + raise ValueError(f"unregistered violation {text}") + return text + + +# --- public-value helpers ----------------------------------------------------- + + +def digest12(value: str) -> str: + return hashlib.sha256(value.encode("utf-8", "surrogatepass")).hexdigest()[:12] + + +def pub_id(value: object) -> str: + """A server identifier as a digest; a non-string becomes ``unrecognized``.""" + if not isinstance(value, str): + return f"unrecognized:{digest12(type(value).__name__)}" + return f"id:{digest12(value)}" + + +def pub_enum(value: object, vocabulary: frozenset[str]) -> str: + if isinstance(value, str) and value in vocabulary: + return value + return f"unrecognized:{digest12(json.dumps(value, sort_keys=True, default=str))}" + + +def pub_path(value: object, declared: frozenset[str]) -> str: + if isinstance(value, str) and value in declared: + return value + return f"unexpected-path:{digest12(json.dumps(value, default=str))}" + + +def pub_unknown_keys(obj: dict, known: frozenset[str]) -> dict | None: + extra = sorted(str(k) for k in obj if k not in known) + if not extra: + return None + return {"count": len(extra), "digest": f"unexpected-keys:{digest12(chr(0).join(extra))}"} + + +_MAX_INT = 2**53 + + +def is_int(value: object) -> bool: + """An integer a receipt may record as a plain JSON number (below 2**53).""" + return isinstance(value, int) and not isinstance(value, bool) and -_MAX_INT < value < _MAX_INT + + +_INT64_MIN, _INT64_MAX = -(2**63), 2**63 - 1 + + +def swift_int(value: object) -> int | None: + """The exact integer JSONDecoder would decode as a Swift Int, or None. + + Foundation decodes Int from the number's value, not its spelling: 5, + 5.0 and 1e3 all decode (to 5, 5 and 1000), as does + 4611686018427387905.0, exactly. One recorded difference: Foundation + decodes 1.0000000000000000001 as 1 by rounding; the harness refuses it, + because the value is not an integer. ``parse_body`` keeps decimal literals as + exact ``Decimal`` values for this reason; a Python float can stand in + only below 2**53, where it is exact. A bool, a non-integral value (5.1), + NaN, infinity and anything outside 64 bits are refused. + """ + if isinstance(value, bool): + return None + if isinstance(value, int): + exact = value + elif isinstance(value, Decimal): + if not value.is_finite() or value != value.to_integral_value(): + return None + # Recorded Foundation behavior: a decimal or exponent spelling is + # range-checked through a Double, so 9223372036854775807.0 (2**63 as a + # Double) is refused while 4611686018427387905.0 decodes exactly. The + # harness is never more lenient than the app. + if not (_INT64_MIN <= value <= _INT64_MAX) or not (-(2.0**63) <= float(value) < 2.0**63): + return None + exact = int(value) + elif isinstance(value, float): + if not math.isfinite(value) or not value.is_integer() or abs(value) >= 2**53: + return None + exact = int(value) + else: + return None + return exact if _INT64_MIN <= exact <= _INT64_MAX else None + + +def is_swift_int(value: object) -> bool: + return swift_int(value) is not None + + +def pub_int(value: int) -> int | str: + """A decoded Swift Int for a receipt: the number itself while a JSON + reader can hold it exactly, otherwise a digest. Never clamped.""" + return value if is_int(value) else f"large-int:{digest12(str(value))}" + + +@dataclasses.dataclass(frozen=True) +class Decoded: + """A decoded answer. ``ok`` means it has the published shape.""" + + violations: tuple[str, ...] + public: dict + data: dict = dataclasses.field(default_factory=dict, repr=False, compare=False) + + @property + def ok(self) -> bool: + return not self.violations + + +class _Collector: + def __init__(self) -> None: + self.items: list[str] = [] + + def add(self, kind: str, field: str) -> None: + self.raw(violation(kind, field)) + + def raw(self, text: str) -> None: + if text not in VIOLATIONS: + raise ValueError(f"unregistered violation {text}") + if text not in self.items: + self.items.append(text) + + +# Sentinels for bodies that are not a JSON value. +NOT_JSON = object() +EMPTY = object() + + +def parse_body(body: bytes | None) -> object: + """JSON-decode a response body, or return a sentinel for empty / non-JSON.""" + if not body: + return EMPTY + try: + # Decimal literals stay exact (see swift_int); they never leave the + # decoders, whose public views hold only ints, words and digests. + return json.loads(body.decode("utf-8"), parse_float=Decimal) + except (UnicodeDecodeError, json.JSONDecodeError, RecursionError): + return NOT_JSON + + +def body_shape(parsed: object) -> str: + if parsed is EMPTY: + return "empty" + if parsed is NOT_JSON: + return "not-json" + return "object" if isinstance(parsed, dict) else "json-non-object" + + +def _object(parsed: object, out: _Collector) -> dict | None: + if parsed is NOT_JSON: + out.raw("shape:not-json") + return None + if parsed is EMPTY: + out.raw("shape:empty") + return None + if not isinstance(parsed, dict): + out.raw("shape:not-object") + return None + return parsed + + +def _str(obj: dict, key: str, out: _Collector, *, required: bool = True) -> str | None: + if key not in obj or obj[key] is None: + if required: + out.add("missing", key) + return None + value = obj[key] + if not isinstance(value, str): + out.add("type", key) + return None + return value + + +def _str_list(obj: dict, key: str, out: _Collector) -> list[str] | None: + if key not in obj: + out.add("missing", key) + return None + value = obj[key] + if not isinstance(value, list) or not all(isinstance(v, str) for v in value): + out.add("type", key) + return None + return value + + +# --- decoders, one per published response type -------------------------------- + + +def decode_errors(parsed: object) -> Decoded: + """CaptureAPI.ErrorBody: ``{"errors": [{"code": ...}]}``. Messages never kept.""" + out = _Collector() + obj = _object(parsed, out) + codes: list[str] = [] + public: dict = {} + if obj is not None: + errors = obj.get("errors") + if not isinstance(errors, list): + out.add("missing" if "errors" not in obj else "type", "errors") + else: + for item in errors[:20]: + code = item.get("code") if isinstance(item, dict) else None + if not isinstance(code, str): + out.add("type", "code") + continue + codes.append(code) + public["codes"] = [pub_enum(c, ERROR_CODES | HARNESS_CODES) for c in codes] + return Decoded(tuple(out.items), public, {"codes": codes}) + + +def decode_health(parsed: object) -> Decoded: + """GET /healthz as the public integration-viewer client reads it.""" + out = _Collector() + obj = _object(parsed, out) + public: dict = {} + status = None + if obj is not None: + status = _str(obj, "status", out) + if status is not None: + public["status"] = pub_enum(status, HEALTH_STATUSES) + if status not in HEALTH_STATUSES: + out.add("enum", "status") + return Decoded(tuple(out.items), public, {"status": status}) + + +_CREATE_KEYS = frozenset({"captureId", "status", "upload", "finalizeBy"}) +_LIMIT_KEYS = frozenset({"maxSinglePutBytes", "urlTtlS", "maxFiles", "maxBatch"}) + + +def decode_create(parsed: object) -> Decoded: + """CaptureAPI.CreateResponse.""" + out = _Collector() + obj = _object(parsed, out) + public: dict = {} + data: dict = {"captureId": None, "status": None, "maxBatch": None} + if obj is not None: + capture_id = _str(obj, "captureId", out) + if capture_id is not None and not capture_id: + out.add("range", "captureId") + capture_id = None + status = _str(obj, "status", out) + if status is not None and status not in CAPTURE_STATUSES: + out.add("enum", "status") + limits = obj.get("upload") + max_batch = None + if limits is not None: + if not isinstance(limits, dict): + out.add("type", "upload") + else: + for key in _LIMIT_KEYS & limits.keys(): + if limits[key] is None: + continue + exact = swift_int(limits[key]) + if exact is None or exact < 0: + out.add("type", "upload") + batch_value = swift_int(limits.get("maxBatch")) + if batch_value is not None and batch_value > 0: + max_batch = batch_value + extra = pub_unknown_keys(limits, _LIMIT_KEYS) + if extra: + public["upload_unexpected_keys"] = extra + finalize_by = obj.get("finalizeBy") + if finalize_by is not None and not isinstance(finalize_by, str): + out.add("type", "finalizeBy") + public["captureId"] = pub_id(obj.get("captureId")) + if status is not None: + public["status"] = pub_enum(status, CAPTURE_STATUSES) + if max_batch is not None: + public["maxBatch"] = pub_int(max_batch) + extra = pub_unknown_keys(obj, _CREATE_KEYS) + if extra: + public["unexpected_keys"] = extra + data = {"captureId": capture_id, "status": status, "maxBatch": max_batch} + return Decoded(tuple(out.items), public, data) + + +_REGISTERED_KEYS = frozenset({"path", "state", "upload"}) +_TARGET_KEYS = frozenset({"method", "url", "headers", "expiresAt"}) + + +def decode_register(parsed: object, requested: list[str], declared: frozenset[str]) -> Decoded: + """CaptureAPI.RegisterResponse, matched to the request by exact path. + + The client applies an answer only to a path it asked about and takes + an upload target only from ``method == "PUT"`` with a URL that passes + ``uploadURLProblem``. A path answered twice, a path nobody asked + about, or a requested path left out is a violation here; answer order + carries no meaning. + """ + out = _Collector() + obj = _object(parsed, out) + public: dict = {} + targets: dict[str, dict] = {} + committed: list[str] = [] + asked = set(requested) + visible = declared & asked + if obj is not None: + files = obj.get("files") + if not isinstance(files, list): + out.add("missing" if "files" not in obj else "type", "files") + files = [] + seen: set[str] = set() + rows: list[dict] = [] + for entry in files: + if not isinstance(entry, dict): + out.add("type", "files") + continue + path = entry.get("path") + row: dict = {"path": pub_path(path, visible)} + rows.append(row) + if not isinstance(path, str): + out.add("type", "path") + continue + duplicate = path in seen + seen.add(path) + if path not in asked: + out.add("unexpected-path", "files") + elif duplicate: + out.add("duplicate", "files") + state = _str(entry, "state", out) + row["state"] = pub_enum(state, REGISTER_STATES) if state is not None else None + extra = pub_unknown_keys(entry, _REGISTERED_KEYS) + if extra: + row["unexpected_keys"] = extra + if state == "committed": + if path in asked and not duplicate: + committed.append(path) + continue + target = entry.get("upload") + if not isinstance(target, dict): + out.raw("upload_method") + continue + method = target.get("method") + url = target.get("url") + headers = target.get("headers") + if headers is None: + headers = {} + headers_ok = isinstance(headers, dict) and all( + isinstance(k, str) and isinstance(v, str) for k, v in headers.items() + ) + if not headers_ok: + out.add("type", "headers") + expires = target.get("expiresAt") + if expires is not None and not isinstance(expires, str): + out.add("type", "expiresAt") + url_problem = upload_url_problem(url) if isinstance(url, str) else "upload_url_invalid" + upload_row = { + "method": pub_enum(method, frozenset({"PUT"})), + "url_present": isinstance(url, str), + "url_policy": url_problem or "ok", + "signed_header_count": len(headers) if headers_ok else None, + "signs_auth_header": bool( + headers_ok and any(k.lower() == "authorization" for k in headers) + ), + "signed_content_type": bool( + headers_ok and any(k.lower() == "content-type" for k in headers) + ), + } + extra = pub_unknown_keys(target, _TARGET_KEYS) + if extra: + upload_row["unexpected_keys"] = extra + row["upload"] = upload_row + if method != "PUT": + out.raw("upload_method") + elif url_problem: + out.raw(url_problem) + elif headers_ok and path in asked and not duplicate: + targets[path] = {"url": url, "headers": dict(headers)} + for path in requested: + if path not in seen: + out.add("not-acknowledged", "files") + public["files"] = rows[:64] + if len(rows) > 64: + public["files_total"] = len(rows) + extra = pub_unknown_keys(obj, frozenset({"files"})) + if extra: + public["unexpected_keys"] = extra + return Decoded(tuple(out.items), public, {"targets": targets, "committed": committed}) + + +_COMMIT_KEYS = frozenset({"committed", "notFound", "mismatch"}) + + +def decode_commit(parsed: object, requested: list[str], declared: frozenset[str]) -> Decoded: + """CaptureAPI.CommitResponse. All three lists are required by the type.""" + out = _Collector() + obj = _object(parsed, out) + public: dict = {} + data: dict = {"committed": [], "notFound": [], "mismatch": []} + asked = set(requested) + if obj is not None: + for key in ("committed", "notFound", "mismatch"): + values = _str_list(obj, key, out) + if values is None: + continue + if len(set(values)) != len(values): + out.add("duplicate", key) + if any(v not in asked for v in values): + out.add("unexpected-path", key) + data[key] = values + public[key] = [pub_path(v, declared & asked) for v in values[:64]] + # One answer cannot both acknowledge a file and refuse it. + committed, not_found, mismatch = ( + set(data[k]) for k in ("committed", "notFound", "mismatch") + ) + if committed & not_found or committed & mismatch or not_found & mismatch: + out.raw("overlap:commit-categories") + extra = pub_unknown_keys(obj, _COMMIT_KEYS) + if extra: + public["unexpected_keys"] = extra + return Decoded(tuple(out.items), public, data) + + +_FINALIZE_KEYS = frozenset({"status", "missing", "runId", "etaS"}) + + +def decode_finalize(parsed: object, declared: frozenset[str]) -> Decoded: + """CaptureAPI.FinalizeResponse: status, missing and runId are required.""" + out = _Collector() + obj = _object(parsed, out) + public: dict = {} + data: dict = {"status": None, "missing": None, "runId": None} + if obj is not None: + status = _str(obj, "status", out) + if status is not None and status not in CAPTURE_STATUSES: + out.add("enum", "status") + missing = _str_list(obj, "missing", out) + run_id = _str(obj, "runId", out) + if run_id is not None and not run_id: + out.add("range", "runId") + run_id = None + eta_raw = obj.get("etaS") + eta = swift_int(eta_raw) + if eta_raw is not None and not (eta is not None and eta >= 0): + out.add("type", "etaS") + if status is not None: + public["status"] = pub_enum(status, CAPTURE_STATUSES) + if missing is not None: + public["missing"] = [pub_path(p, declared) for p in missing[:64]] + public["runId"] = pub_id(obj.get("runId")) + if eta is not None and eta >= 0: + public["etaS"] = pub_int(eta) + extra = pub_unknown_keys(obj, _FINALIZE_KEYS) + if extra: + public["unexpected_keys"] = extra + data = {"status": status, "missing": missing, "runId": run_id} + return Decoded(tuple(out.items), public, data) + + +_EVENTS_KEYS = frozenset({"status", "next", "events"}) +_EVENT_KEYS = frozenset({"seq", "type", "at", "data"}) +_EVENT_DATA_KEYS = frozenset({"code", "kind", "stage", "status", "runId", "next"}) + + +def decode_events(parsed: object, *, after: int, run_id: str | None) -> Decoded: + """CaptureAPI.EventsResponse, plus the ordering the client relies on. + + ``next`` never moves the cursor back, each event's ``seq`` is past + ``after`` and at most ``next``, and a ``verdict_ready`` naming a run + names this capture's run. + """ + out = _Collector() + obj = _object(parsed, out) + public: dict = {} + data: dict = {"status": None, "next": None, "retry_finalize": False, "events": 0} + if obj is not None: + status = _str(obj, "status", out) + if status is not None and status not in CAPTURE_STATUSES: + out.add("enum", "status") + nxt = swift_int(obj.get("next")) # exact int from here on + if "next" not in obj: + out.add("missing", "next") + nxt = None + elif nxt is None or nxt < 0: + out.add("type", "next") + nxt = None + elif nxt < after: + out.raw("order:next") + events = obj.get("events") + if not isinstance(events, list): + out.add("missing" if "events" not in obj else "type", "events") + events = [] + rows: list[dict] = [] + for event in events: + if not isinstance(event, dict): + out.add("type", "events") + continue + seq = swift_int(event.get("seq")) + etype = event.get("type") + row: dict = {} + if seq is None: + out.add("missing" if "seq" not in event else "type", "seq") + else: + row["seq"] = pub_int(seq) + if seq <= after or (nxt is not None and seq > nxt): + out.raw("order:seq") + if not isinstance(etype, str): + out.add("missing" if "type" not in event else "type", "type") + row["type"] = pub_enum(etype, EVENT_TYPES) + if not isinstance(event.get("at"), str): + out.add("missing" if "at" not in event else "type", "at") + payload = event.get("data") + if payload is not None and not isinstance(payload, dict): + out.add("type", "data") + payload = None + if payload: + for key in _EVENT_DATA_KEYS: + if payload.get(key) is not None and not isinstance(payload[key], str): + out.add("type", "data") + pdata: dict = {} + if "code" in payload: + pdata["code"] = pub_enum(payload["code"], ERROR_CODES | HARNESS_CODES) + if "kind" in payload: + pdata["kind"] = pub_enum(payload["kind"], OUTCOME_KINDS) + if "stage" in payload: + pdata["stage"] = pub_enum(payload["stage"], frozenset()) + if "status" in payload: + pdata["status"] = pub_enum(payload["status"], CAPTURE_STATUSES) + if "runId" in payload: + pdata["runId"] = pub_id(payload["runId"]) + pdata["runId_matches"] = payload["runId"] == run_id + if "next" in payload: + pdata["next"] = pub_enum(payload["next"], EVENT_DIRECTIVES) + extra = pub_unknown_keys(payload, _EVENT_DATA_KEYS) + if extra: + pdata["unexpected_keys"] = extra + row["data"] = pdata + if etype == "verdict_ready" and payload.get("runId") is not None: + if payload.get("runId") != run_id: + out.raw("verdict-for-another-run") + if etype == "failed" and payload.get("next") == "retry_finalize": + data["retry_finalize"] = True + extra = pub_unknown_keys(event, _EVENT_KEYS) + if extra: + row["unexpected_keys"] = extra + rows.append(row) + if status is not None: + public["status"] = pub_enum(status, CAPTURE_STATUSES) + if nxt is not None: + public["next"] = pub_int(nxt) + public["events"] = rows[:50] + if len(rows) > 50: + public["events_total"] = len(rows) + extra = pub_unknown_keys(obj, _EVENTS_KEYS) + if extra: + public["unexpected_keys"] = extra + data.update({"status": status, "next": nxt, "events": len(rows)}) + return Decoded(tuple(out.items), public, data) + + +# CaptureResult.swift, field by field: (kind, required). A kind is "str", +# "num" (Swift Double: a finite JSON number, never a bool), "[str]", "[num]", +# a nested spec dict, or ("list", spec). JSONDecoder rejects a required field +# that is missing or null, accepts a missing or null optional, and rejects +# any present value of the wrong type. Unknown keys are ignored, as in Swift. +_PROMPT = {"title": ("str", True), "body": ("str", True)} +_REFERENCE_CROP = {"image": ("str", True), "boxPx": ("[num]", True)} +_VIEW = { + "id": ("str", True), + "kind": ("str", True), + "criteria": ("[str]", True), + "why": ("str", True), + "promptId": ("str", True), + "prompt": (_PROMPT, True), + "band": ("str", False), + "wallId": ("str", False), + "target": ("str", False), + "referenceCrop": (_REFERENCE_CROP, False), +} +_REASON = { + "criterion": ("str", True), + "text": ("str", True), + "measuredFt": ("num", False), + "plusMinusFt": ("num", False), + "thresholdFt": ("num", False), + "comparison": ("str", False), +} +# BoxArkitWorld's counts are checked only when the app asks for AR, so a +# decode accepts any list of numbers here. +_BOX = {"pose": ("[num]", True), "size": ("[num]", True)} +_PLACEMENT = { + "wallId": ("str", True), + "startSM": ("num", True), + "confidence": ("num", True), + "boxArkitWorld": (_BOX, False), +} +_OUTCOME = { + "kind": ("str", True), + "profile": ("str", True), + "message": ("str", True), + "viewsNeeded": (("list", _VIEW), True), + "reasons": (("list", _REASON), True), + "arkitEpoch": ("str", False), + "recommendedPlacement": (_PLACEMENT, False), +} +_CRITERION = { + "id": ("str", True), + "outcome": ("str", True), + "unsureCause": ("str", False), + "measuredFt": ("num", False), + "plusMinusFt": ("num", False), + "thresholdFt": ("num", False), + "coverage": ("str", False), +} +_RESULT = { + "runId": ("str", False), + "status": ("str", True), + "viewsNeeded": (("list", _VIEW), True), + "memberActions": ("[str]", True), + "outcome": (_OUTCOME, False), + "criteria": (("list", _CRITERION), False), + "previewUrl": ("str", False), + "reviewUrl": ("str", False), +} +_RESULT_KEYS = frozenset(_RESULT) +_OUTCOME_KEYS = frozenset(_OUTCOME) +_FIELD_SET = frozenset(_FIELDS) + + +def _swift_number(value: object) -> bool: + """A JSON number JSONDecoder can decode as a finite Swift Double. + + Any integer or decimal spelling qualifies when it converts to a finite + double: 10000000000000000 and 1e16 alike. A bool, a string, an overflow + to infinity (1e400, a 400-digit integer) and NaN do not. This is about + decoding; the receipt bounds on exported integers (``is_int``) are a + separate rule, and these numbers are never exported. + """ + if isinstance(value, bool): + return False + if isinstance(value, int | Decimal): + try: + return math.isfinite(float(value)) + except OverflowError: + return False + return isinstance(value, float) and math.isfinite(value) + + +def _check_value(value: object, kind, label: str, out: _Collector) -> None: + """Record ``type: