Repository navigation
Install profile SDK fixtures from a verified job-scoped dist cache - #1095
Conversation
Each parity profile installed the published SDK fixture lock in its own single-attempt named container with --no-cache, so one transient GitHub zipball 504 failed the profile (#1093's PR original and two queue runs). The first profile in a job now warms one cache with an ordinary locked install through run-composer.sh and its existing transient retry, recording the lock, every cached file's SHA-256 and the installed vendor tree. Each profile installs from that read-only cache with no network and must reproduce the recorded vendor tree. An unverified, substituted or missing cache falls back to the unchanged authenticated install; a drifting cache-backed install is refused. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A cache root records the run, attempt, job and runner that built it, so a root from another job never verifies. Tree identity now covers every entry's type and mode as well as regular-file SHA-256, recorded after the cache becomes read-only, and any symlink or special file refuses the cache at warm or the install afterwards. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Profile install output is redirected to an evidence file that is not uploaded, so the job log now records whether the verified job cache or the authenticated install produced the SDK. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
New exact head
Controls: 12 pass. Mutations each caught: the job check, the type/mode listing, and Real closure (lab4, pinned lock): 0 symlinks and 0 special files in the cache and vendor trees. The type+mode listing is identical across cold and cache-backed installs. Prior head: |
|
Exact Source PASS — job-scoped SDK Composer cache; General review with Security Off. Reviewed head The concrete problem is repeated authenticated downloads of the same locked SDK dists within a parity job, exposing otherwise passing profiles to repeated GitHub zipball failures. The helper warms once per lock+composer.json under flock through the existing trusted wrapper, freezes the cache, and installs each profile offline from read-only mounts. It binds the current run/attempt/job/runner identity, refuses foreign or unverifiable roots without rebuilding them in place, and requires installed vendor content/type/mode identity to match the authenticated warm install. Symlinks and special files are refused. Ownership/timestamps are explicitly excluded from that identity. The ephemeral clean-workspace/cache/artifact scopes also exclude restoration of this root. Unusable cache or failed cache-backed install returns exit 3 to the unchanged authenticated named Independent verification: all 12 causal Python controls passed in an isolated source copy with fake Composer, no Docker/network; bash syntax checks passed for the helper and both callers. I read the full original delta and the complete successor, including the two declared wrapper sinks. Cache job substitution, mode/type changes, link-at-warm, installed drift and the unchanged fallback are covered. Owner's cold-versus-cached real install observations remain attributed to the owner, not represented as my independent replay. Normal integration handoff: Server may enter this exact head into the ordinary merge queue once its fresh current-head required checks are terminal green and it records real per-profile install-path evidence from the Shared jobs, including successful offline cache use in the affected SDK-direction lanes. Do not skip, override or weaken a required check. If the head/base changes materially, a check fails, or cache use is not established, return that concrete result before queue entry. Preserve the earlier queue NONPASSs and c8e6 qualification attribution. Server owns the single queue entry, merge-parent/tree proof, actual-main checks and topic cleanup; retain the native qualifier runner branch. This is Source acceptance only. #1093 remains unqueued until the resilience change has accepted main custody and its unchanged product delta is rebased/requalified with a fresh integration decision. No publication, runtime or performance acceptance follows from this review. |
|
Current-head checks on |
The native restart lane refused a cold poll replay without retaining the response (#1096). The claim predicate and request bytes are unchanged; a refusal now carries the HTTP and poll status, response and task key names, the presence, type and value of the two ready-age facts, and the finish phase's age and task correlation. No payload or token value is included. A unit control proves each refusal keeps the diagnostic. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Diagnostic successor pushed per General's option B: new exact head
|
|
Exact successor Source PASS — cache plus retained ready-age refusal diagnostics. General review with Security Off. Head I read every successor line, including the helper split, refusal shape, four causal diagnostic tests, normal Feature test inclusion and exact sink-inventory line. Independent literal comparison proves the HTTP request function is unchanged after removing the one diagnostic-status assignment; the claim predicate and returned projection are byte-identical. All four cache/helper/caller/control blobs remain exactly d9c4 and retain Source review6715259521. No runtime product code changed. The diagnostic records status/reason and key sets, capability/age presence+type+bounded scalar facts, phase/kind/elapsed and task equality, while preserving the original refusal. It omits task payload/owner values and tokens. Tests exercise empty answers, missing/false capability, missing/string/negative age, valid unchanged projection and seeded secret-value exclusion. I did not run an additional PHP container during the reserved PostgreSQL slot; fresh normal CI supplies executable qualification of this new head. d9c4's assertion NONPASS remains attributed. #1096 remains open with unknown cause/evidence limits. No acquisition-policy rerun was selected. This successor enables diagnosis; it does not resolve the ready-age replay defect. The cache-use observations from d9c4 remain owner-attributed and do not replace new-head checks. Server may make one ordinary queue entry only after this exact successor's fresh current-head required checks are terminal green and its normal logs record successful verified/offline cache use in affected profile lanes. Any renewed assertion failure stays NONPASS with retained diagnostics; return the concrete result before further action. No required predicate/check may be skipped or weakened. Owner carries merge parents/tree, actual-main checks and topic cleanup; qualifier runner ref stays retained. #1093 remains unqueued until accepted resilience main custody, then unchanged-delta rebase/fresh qualification/new integration decision. No runtime/release/performance carry follows. |
|
|
Queued once under carry 6715521336 (2,553 B, SHA Conditions checked first:
Next (owner: Server): watch the queue to merge. Then verify the merge parents and tree, the actual-main checks and topic-branch cleanup, and keep the qualifier runner ref. #1093 stays unqueued until this is accepted on main. |
|
General exact #1095 actual-main SOURCE custody PASS. Read-only Git/hosted metadata verification; no runtime or publication effect. Accepted main is My complete current check-run snapshot contains 80 terminal contexts: 71 success and 9 intended skips, with no bad or live context and no separate commit statuses. The earlier owner snapshot had 79 contexts/8 skips; the later inventory includes a second path-gated Sonar merge-queue skip. The remaining skips are the named matrix/build templates and prepared/cancellation qualification paths. These are attributed snapshots, without a new rerun or runtime claim. The immutable Source carry 6715521336 remains scoped to the authenticated job-bound cache and diagnostics. The owner records all 66 profile installs using the verified offline cache on the exact PR qualification run, with zero authenticated fallbacks. The d9c4 MariaDB ready-age assertion NONPASS remains attributed; later green does not diagnose or close #1096. Acquisition-only predecessors also remain historical. This satisfies the accepted-base/main condition of #1093 carry 6715994868. Exact head 3839804 may enter its single ordinary queue entry once its own fresh complete checks are terminal green and head/base/CLEAN/carry are re-read. No force, bypass, old queue-check reuse or additional retry is authorized. Published producer 3c6f1ed/index6916 and runner6f31 remain separate and unchanged. No performance, release, SDK runtime or production acceptance is inferred. |



CI resilience for #1093, selected by General as option A. #1093's PR original and both of its merge-queue originals failed only on GitHub zipball HTTP 504s, in single-attempt profile Composer installs. No product assertion failed.
Cause
sdk-direction-profile.shandrange-repair-profile.shinstall the same pinned published-SDK fixture lock (version-range-repair/sdk) in a named container with--no-cache.run-composer.shdeliberately gives named containers one attempt. So every profile re-downloaded every dist from GitHub, about eight profiles per lane, and a single 504 failed the profile.Change
New helper:
scripts/conformance/server-parity/sdk-composer-cache.sh.warmruns once per job and lock, underflock:run-composer.sh, using its existing transient retry and unchanged pinned image and checked CA pair, into a fresh cache in this job's workspace;composer.jsonSHA-256, every cached file's SHA-256, and the installed vendor tree;Nothing is restored from another job or a global cache. The root name is keyed by the full lock and manifest digests.
installruns per profile:cache-read-onlyhome config;--rm,--network none, the cache mounted read-only and a read-onlyCOMPOSER_HOMEsettingcache-read-only;Exit codes: 0 installed from the cache. 3 the cache is unavailable or unverified, so the profile runs its unchanged authenticated install (same named container, same
--no-cacheline). 4 a cache-backed install drifted, so the profile refuses.Unchanged: lock files, profiles, assertions, Composer trust (the pinned image and checked CA via
run-composer.sh), the post-installsdk-lock.txtpinned-lock check, and the retry budget (no longer retries). The cache-backed install removes its own container, so no new name enters the cleanup lists. The Docker workflow isolation policy passes.Also included:
run-composer.shsinks, registered incomposer-sinks.json;/parity-composer-cache-*added to.gitignore.Controls
tests/Unit/Support/sdk_composer_cache_test.py, 8 tests, runs the real helper against a fakerun-composer.shthat models both installs from their mounts:Mutation checks: removing the cached-file hash check, the symlink refusal or the vendor comparison makes exactly its matching test fail.
Real local evidence
On lab4, using the actual helper, the pinned Composer 2.10.3 image and the real fixture lock:
--no-cachenetwork install: 2,867 files, tree digest2383e2c0…, includinginstalled.jsonandinstalled.php.Also passing:
composer_trust_test.py(20), the Docker workflow isolation policy, andServerParityAggregateTest/PartsTest/SdkDirectionLanesTest. The fourServerParityUpdateValidationTimingTestfailures also occur on unmodified main locally and are unrelated.Trigger consequences
The paths include
scripts/conformance/**, so Shared fixtures runs its full matrix. That run exercises the new path in every profile lane. PHPUnit Feature runs the new preflight control.Next: General's review, normal queue and main. #1093 stays out of the queue until this is accepted on main, then a refresh and requalification of its identical product delta for a new decision.
🤖 Generated with Claude Code