Repository navigation
Record this host's vLLM receipt with its qualified local models - #131
Merged
seathatflowsinourveins merged 1 commit intoSep 23, 2026
Merged
Conversation
First real use of the qualified_models field (#130): a native_proven host receipt for the vllm component on linux-wsl2-x86_64 (host rtx5090-laptop-20260923, hardware profile this-host-20260923). Live checks on the resident service: health 200, 2048-dimension embeddings, max-model-len 8192. Qualified models: Nemotron-3-Embed-1B-BF16 on vLLM 0.25.0 (the one local embedder for code and memory retrieval; hybrid nDCG@10 +0.078) and Qwen3-8B-AWQ on vLLM 0.29.0 (20/20 tool calls, 4/5 tasks). Regenerated the component matrix and new-host grand list; no platform status changes. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
seathatflowsinourveins
deleted the
claude/host-receipt-local-models-20260923
branch
September 23, 2026 17:23
seathatflowsinourveins
added a commit
that referenced
this pull request
Sep 23, 2026
Hosted macOS run 35894394138 on 51f4145 (3147 tests, failures=2, down from 124 at the start): 1. tests.test_host_receipts.QualifiedModelRecordTests. test_qualified_model_flag_is_recorded_and_validates: the same auto-detected-host.os-vs-declared-platform-id mismatch fixed elsewhere in this file for #131's new class -- --platform-id linux-wsl2-x86_64 with host.os/architecture left on auto-detection, then cmd_validate()'s cross-check. Pinned --os linux --architecture x86_64 in the shared _record() helper (the only other test using it that also calls cmd_validate). Grepped every other record fixture in the file claiming a linux platform: none of the others call cmd_validate, so none needed the same fix. 2. tests.test_offhost_app_state.EvidenceGuards. test_command_timeout_retains_output_and_stops_owned_group: raced a full /usr/bin/python3 interpreter's fork/exec + bootstrap against a 0.1s timeout. macOS process creation (especially on GitHub-hosted runners) is measurably slower than Linux's, so the child was sometimes killed before it printed anything, leaving stdout empty -- this looked like a process-group/kill bug but was a startup-latency race; os.killpg/setsid semantics are POSIX and unaffected. Fixed deterministically, not with a longer sleep: the child is now /bin/sh -c 'printf ...; sleep 3', which has no interpreter to bootstrap and no stdio buffering to flush, so the timeout budget (raised slightly, to .5s, for headroom) is spent almost entirely on the kernel's own fork/exec rather than CPython startup. The behavior under test (partial output retained, process group killed) is unchanged and still asserted on every platform. Co-Authored-By: Claude Sonnet 5 <[email protected]>
seathatflowsinourveins
added a commit
that referenced
this pull request
Sep 23, 2026
…tform-specific tests) (#126) * Fix macOS false-positive repository-escape refusal in safe_file() safe_file(root, relative) compared path.resolve() (fully resolved) against root as given, unresolved. On macOS, TMPDIR sits under a symlinked system directory (/var -> /private/var), so a legitimate root under TMPDIR no longer prefix-matched its own resolved descendant, and safe_file raised "source path escapes the repository" for every caller (catalog_decisions, host_receipts, component_matrix, freshness_propose, lane_packets) even though nothing escaped. Resolve root once at the top of safe_file so both sides of the containment check are canonicalised the same way. The per-component "source symlinks are forbidden" check (which detects a symlink actually placed inside the tree) is untouched and keeps refusing real escapes. Co-Authored-By: Claude Sonnet 5 <[email protected]> * Fix macOS false-positive symlink-ancestor refusals under TMPDIR Several independent safe_path()/safe()/target-symlink checks walked every ancestor of a path (or compared path.resolve() to path.absolute()) looking for an injected symlink. On macOS, TMPDIR resolves through /var -> /private/var (or /tmp -> /private/tmp), so a legitimate path under the system temp directory always contained a "symlink ancestor" and was refused, even with nothing actually escaping. Anchor each check on tempfile.gettempdir(): resolve that one system boundary once, then walk only the components below it (or, for a path outside the temp tree, every component from the filesystem root, exactly as before) looking for an injected symlink. A symlink placed inside the job-owned tree -- an alias pointing back into it, a swapped destination, a tampered receipt.json -- still breaks that walk and is refused; only the tolerated system boundary above it stops causing false positives. Applies to: - alpaca-historical/collect.py and catalyst-dataset/dataset.py (symlink_or_parent_traversal_refused, shared by security-identity, lifecycle-sample and catalyst provenance via the same bridge module) - research-efficiency/experiment.py (symlink refused) - offhost-restore/verify.py (repository target traverses a symlink) - service-reboot/run.py (--work must be a new absolute path) offhost-app-state/run.py's owned_root() takes a different, narrower shape: it requires a path directly under the literal /tmp, so instead of walking ancestors it now resolves both /tmp and the candidate's parent for the containment compare, while path.is_symlink() (not a resolve() comparison on path itself) keeps catching a symlinked leaf; the returned path stays the literal /tmp form the caller passed in. offhost-app-state/run.py and offhost-restore/verify.py are both pinned by frozen_sources sha256 entries in offhost-app-state/plan.json and offhost-restore/hosted-plan.json; both are re-pinned to the new bytes so test_active_recovery_plans.py's dispatch-source guard passes again. Co-Authored-By: Claude Sonnet 5 <[email protected]> * Skip Linux-x86_64-only bootstrap-linux.sh tests on other platforms bootstrap-linux.sh has its own uname-based guard ("This verified asset set targets x86_64 Linux, not Windows/Git Bash or ARM.") and refuses to run at all off Linux x86_64 -- correctly, since it installs x86_64 Linux binaries. On macOS this guard fires before every later check the affected tests exercise (unknown profile, null-hash pin refusal, unpinned-component fail-closed, the ECO_INSTALL_ROOT-resolves-to-HOME refusal, and the missing-tool detection under --skip-system-packages), so those tests saw the platform-guard message instead of the behavior under test. Mark exactly the affected test methods (not their whole classes, which also hold platform-portable tests like --help and missing --profile) with skipUnless(sys.platform.startswith('linux') and platform.machine() == 'x86_64'). bootstrap-macos.sh is the already-covered macOS path; no assertion is deleted or weakened. Co-Authored-By: Claude Sonnet 5 <[email protected]> * Pin host.os/architecture in record fixtures that later cross-check them Four RecorderRoundTripTests fixtures called the record CLI with an explicit --platform-id linux-wsl2-x86_64 but left host.os/architecture on auto-detection, then ran cmd_validate(), which cross-checks a receipt's host.os/architecture against adoption/manifest.json's platform_profiles for the claimed platform_id. On a Linux x86_64 host the auto-detected values happened to match; on macOS (auto-detected os=macos, architecture=arm64) they legitimately do not match linux-wsl2-x86_64's declared linux/x86_64, so validation correctly failed. Pass --os linux --architecture x86_64 explicitly (the CLI already supports overriding auto-detection for exactly this), so the fixture is consistent with its own hardcoded platform_id on every host. This also fixes two platform_profile_map() KeyErrors elsewhere in the suite: that function swallows InvalidDecisionIndex and returns {}, which was the effect of the adjacent safe_file() containment bug now fixed separately -- no schema or assertion changed here. Co-Authored-By: Claude Sonnet 5 <[email protected]> * Compare against resolved paths where the source already canonicalises Three tests compared subprocess/rendered output to a literal, unresolved temp path, while the code under test deliberately resolves that same path before emitting it: - grand-dashboard install.py resolves dagu_bin/dagu_home before writing them into the generated systemd unit (so the unit references a real, unambiguous path); - worker-recovery run.py's exact_read_rule() resolves its workspace argument before embedding it in a generated Bash permission rule (so the rule targets the real path, not a symlink alias of it); - render_config.py's default_project_root() falls back to Path.cwd(), and the getcwd() syscall always returns the fully resolved directory (POSIX, not macOS-specific). On a host where the temp root has a symlinked ancestor (macOS's /tmp -> /private/tmp, /var -> /private/var, or TMPDIR itself symlinked), the resolved output legitimately differs from the tests' hardcoded literal form. Compare against the same .resolve() the source already applies instead of hardcoding the unresolved path; the source's canonicalisation is correct and unchanged. Co-Authored-By: Claude Sonnet 5 <[email protected]> * Re-register changed files in the evidence manifest Re-hash the source, test and plan files touched by the macOS portability fixes (host_receipts.register_file per file, then evidence_manifest.py --write to keep files[] sorted). Co-Authored-By: Claude Sonnet 5 <[email protected]> * Security review round 2: root-owned-only symlink trust, TOCTOU and '..' fixes An independent Opus security review of the round-1 macOS portability fixes found three weakenings, all unreachable through current callers but real: 1. owned_root() (offhost-app-state/run.py) compared path.parent.resolve() to Path('/tmp').resolve(), so /tmp/x -> /tmp made path.parent.resolve() match even though path.parent was NOT literally /tmp -- and /tmp/x could be repointed elsewhere after this check and before the root is actually used (TOCTOU). Fixed: path.parent must literally be /tmp or its resolved form, and path.resolve() must land exactly at <resolved /tmp>/<name>. The same resolve()-vs-literal-/tmp pattern was also live in three other offhost-app-state checks discovered by the round-2 macOS CI run (35890224379): cleanup()'s and password()'s checks always differ once /tmp itself is a symlink, even with nothing wrong, since self.root is already a vetted literal path; fixed by checking only the specific component that could actually be swapped (the leaf, or the intermediate 'private' directory) instead of resolve()-comparing the whole path. validate_source() had the identical bug for an unvetted folder argument; fixed by routing it through the new shared helper (see 3). 2. decode_repository() (offhost-restore/verify.py) lost its '..' refusal when the old target.resolve() != target.absolute() check (which caught '..' incidentally, since resolve() collapses it and absolute() does not) was replaced with the TMPDIR-anchored symlink walk. Restored as an explicit `'..' in target.parts` refusal. 3. The TMPDIR exemption in every one of the six affected checks trusted $TMPDIR unconditionally: everything at or above tempfile.gettempdir() was skipped, so an attacker-controlled symlink set as TMPDIR (or a shared TMPDIR an attacker can plant a link under) was tolerated. Added scripts/path_safety.refuse_untrusted_symlinks(), one shared helper used by alpaca-historical/collect.py, catalyst-dataset/dataset.py, research-efficiency/experiment.py, offhost-restore/verify.py, service-reboot/run.py and offhost-app-state/run.py's validate_source(): it walks every component from the filesystem root (never anchored on $TMPDIR) and tolerates a symlinked ancestor only when it is owned by root and not group/world-writable -- exactly macOS's own /tmp -> /private/tmp, /var -> /private/var, /etc -> /private/etc, never a symlink any unprivileged account (including the one running this process) could have planted or repointed. catalog_decisions.safe_file() does not adopt it: its containment model is a confined, already-resolved root with zero symlink tolerance inside the tree, which this helper's "tolerate a root-owned ancestor" relaxation would only weaken. collect.py's own diff is kept to an import and a one-line call (per compatibility note below); the other five callers follow the same shape. New regression tests (each reproduces the weakening against c1f30cb before passing against this fix): scripts/path_safety's own ownership/mode behavior including the TMPDIR case (tests/test_path_safety.py, with the root-owned/non-writable case simulated via a Path.lstat mock -- Linux does not enforce meaningful symlink permission bits the way macOS does, so a real Linux symlink cannot demonstrate the "tolerated" branch); owned_root's symlinked-parent TOCTOU gap and decode_repository's '..' refusal (tests/test_offhost_app_state.py, tests/test_offhost_restore.py); the same TMPDIR-trust weakening reproduced end-to-end through experiment.safe() and service-reboot's run() (tests/test_research_efficiency.py, tests/test_service_reboot.py). Compatibility: security-identity/ledger.py and quality.py (frozen base-collector.py = collect.py bytes) and research-efficiency/experiment.py (frozen self-comparison) fail-closed re-verification of any identity-readiness private run captured before this change, since the guarded files' bytes changed. This is the correct, deliberate consequence of fixing a real check in a file those runs pin; there is no way to fix the check without changing the file it lives in. Co-Authored-By: Claude Sonnet 5 <[email protected]> * Re-pin frozen_sources hashes after the round-2 security fixes offhost-app-state/run.py, offhost-restore/verify.py and the two test files that gained new regression coverage are all pinned by frozen_sources sha256 entries in these two plans; re-pin them to the fixed bytes so test_active_recovery_plans.py's dispatch-source guard passes again. Co-Authored-By: Claude Sonnet 5 <[email protected]> * Re-register changed files in the evidence manifest (round 2) Re-hash the files touched by the round-2 security fixes (host_receipts .register_file per file, then evidence_manifest.py --write to keep files[] sorted). Co-Authored-By: Claude Sonnet 5 <[email protected]> * Security review round 3, findings A+B: tighten the trusted-link shape Two lows in the round-2 shared helper: A. Once a root-owned link was tolerated, the walk followed it and every component through it, with no check on where in the tree that link sat. A root-owned link deeper in the tree (a hard link to, or a copy of, a relative framework link such as macOS's Versions/Current, planted somewhere under /tmp) could redirect the path. Fixed: a symlink is tolerated only when it sits directly under the filesystem root (candidate.parent == Path(candidate.anchor)) -- exactly macOS's /tmp, /var and /etc; anything else is refused regardless of ownership. B. Checking the *link's own* mode did nothing: a symlink's permission bits are not what gates replacing it, and Linux does not even enforce them (lstat reports 0o777 for every symlink regardless of chmod). What actually controls whether an unprivileged account can repoint or replace the link is whether it can write to the directory the link lives in. Fixed: check that the link's parent directory (which, given A, is always /) is root-owned and not group/world-writable, instead of the link's own stat. New/adjusted tests in tests/test_path_safety.py, each exercising the two conditions independently: a root-owned link (mocked) NOT directly under / is still refused; a link directly under / (mocked, since a real one cannot be planted at the actual filesystem root here) whose parent is mocked writable is refused; the positive case (link directly under /, real /'s own genuinely root-owned/non-writable stat, no mock needed for the parent check) is tolerated. Co-Authored-By: Claude Sonnet 5 <[email protected]> * Fix two more macOS-only failures found by the round-3 hosted run Hosted macOS run 35894394138 on 51f4145 (3147 tests, failures=2, down from 124 at the start): 1. tests.test_host_receipts.QualifiedModelRecordTests. test_qualified_model_flag_is_recorded_and_validates: the same auto-detected-host.os-vs-declared-platform-id mismatch fixed elsewhere in this file for #131's new class -- --platform-id linux-wsl2-x86_64 with host.os/architecture left on auto-detection, then cmd_validate()'s cross-check. Pinned --os linux --architecture x86_64 in the shared _record() helper (the only other test using it that also calls cmd_validate). Grepped every other record fixture in the file claiming a linux platform: none of the others call cmd_validate, so none needed the same fix. 2. tests.test_offhost_app_state.EvidenceGuards. test_command_timeout_retains_output_and_stops_owned_group: raced a full /usr/bin/python3 interpreter's fork/exec + bootstrap against a 0.1s timeout. macOS process creation (especially on GitHub-hosted runners) is measurably slower than Linux's, so the child was sometimes killed before it printed anything, leaving stdout empty -- this looked like a process-group/kill bug but was a startup-latency race; os.killpg/setsid semantics are POSIX and unaffected. Fixed deterministically, not with a longer sleep: the child is now /bin/sh -c 'printf ...; sleep 3', which has no interpreter to bootstrap and no stdio buffering to flush, so the timeout budget (raised slightly, to .5s, for headroom) is spent almost entirely on the kernel's own fork/exec rather than CPython startup. The behavior under test (partial output retained, process group killed) is unchanged and still asserted on every platform. Co-Authored-By: Claude Sonnet 5 <[email protected]> * Pin scripts/path_safety.py in every frozen-source list (finding C) The shared helper added in round 2 was adopted by six checks but never itself pinned anywhere, so a changed helper would silently run different code than reviewed: - offhost-app-state/plan.json and offhost-restore/hosted-plan.json: added to frozen_sources, checked by Trial.verify_frozen() and verify_sources() respectively (run.py:262-ish in each) -- see the companion commit for the re-pinned hashes. - service-reboot/run.py: added to the repository_inputs digest set (a host-side-only dependency of run()'s own check, so tracked alongside source_paths rather than added to it, since source_paths is also copied into the guest payload and path_safety.py has no guest-side role). - research-efficiency/experiment.py: folded 'experiment.py' and 'run_codex.py' plus the new 'path_safety.py' into one RUNTIME_SOURCES mapping, reused by both prepare()'s freeze-time copy and run()'s source-changed-after-freeze comparison, so all three trip the same 'runtime source changed after freeze' check. New tests in tests/test_active_recovery_plans.py confirm the pin is present in both plans and that corrupting the recorded hash (simulating a changed helper, since editing the real checked-in file would not be reverted) trips verify_frozen()/verify_sources() with the expected message. Co-Authored-By: Claude Sonnet 5 <[email protected]> * Re-pin frozen_sources hashes after the round-3 fixes path_safety.py (findings A/B), tests/test_offhost_app_state.py (the timeout-test fix) and scripts/path_safety.py's new pin itself all changed bytes that offhost-app-state/plan.json and offhost-restore/hosted-plan.json pin; re-pin them to the fixed/new bytes so test_active_recovery_plans.py's dispatch-source guard passes again. Co-Authored-By: Claude Sonnet 5 <[email protected]> * Re-register changed files in the evidence manifest (round 3) Re-hash the files touched by the round-3 fixes (host_receipts .register_file per file, then evidence_manifest.py --write to keep files[] sorted). Co-Authored-By: Claude Sonnet 5 <[email protected]> * Make the macOS full test suite a gating step now that it passes on macos-15 Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> --------- Co-authored-by: seathatflowsinourveins <[email protected]> Co-authored-by: Claude Sonnet 5 <[email protected]>
9 of 22 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
First real use of the
qualified_modelsfield added in #130.native_provenhost receipt forvllmonlinux-wsl2-x86_64: hostrtx5090-laptop-20260923, hardware profilethis-host-20260923.max_model_len8192.Checks: validate.py,
host_receipts.py validate,component_matrix.py --check,new_host_grand_list.py --checkandverdict_flip_candidates.pypass. Guarded Gitleaks: no leaks.🤖 Generated with Claude Code