Diagnose the Alpine trust failure, fix two container-matrix defects - #5
Merged
Conversation
…out, and make check 61 say what failed Three defects, all shipped in v1.61.0, all found by CI on the first commit where the pre-tag red was not masking them. CONTAINER MATRIX, check 63's skip. tests/container-matrix.sh installs bash git jq curl ca-certificates shellcheck and never python3, so check 63 was guaranteed to skip in every image. The skip classifier accepts a reason only if it matches 'plugin manifest|authenticat|claude CLI', so all three lanes failed on the classification -- debian's gate printed VERIFIED and the lane still failed, which is the classifier working. Adding "python3 not on PATH" to that keyword list would have been a lie about what the skip is, and laundering a skip under a credentials explanation is the exact regression tests/container-skip-classify.sh's PROOF 4 was added to stop. Provision the tool instead. CONTAINER MATRIX, the carve-out that could never fire. bin/doctor:1292 prints `DRIFT ✖` as its generic summary whenever the fail count is non-zero. It name-collides with a real drift banner and carries no diagnostic content. The carve-out stripped the allowed finding's own line but not that one, so with "declared release is fetchable" as the SOLE failure the residual was still non-empty and every image reported `doctor exit=1; DRIFT ✖`. The carve-out I shipped yesterday was unreachable by construction. Row 62b proved the list and the doctor branch; nothing proved the filter against real output, which is the third time in this repository that the two halves were each tested and the join was not. Dropping the banner softens nothing -- every individual finding prints its own ✖ -- but the banner was accidentally acting as a guard, so the guard it was standing in for is now explicit: the allowed finding must actually appear in the output, or a doctor that fails while printing no findings would pass. Debian passing while alpine and ubuntu failed was not an OS difference. Debian ran at 10:48 with the tag still on origin; alpine and ubuntu at 10:50 and 10:53, after cleanup-on-failed-gate removed it. A live-network race across a seven-minute matrix, both dash images on opposite sides. CHECK 61 on Alpine. It goes red there and nowhere else, and reported only "vstack trust failed" because the command ran with `>/dev/null 2>&1`. A check that knows something is wrong and has discarded the only sentence saying what. Two reproduction attempts against a byte-identical image could not make it fail, which is precisely when the swallowed stderr is the whole investigation. It now keeps rc and stderr and puts both in the failure body. This commit does not claim to fix that defect; it makes the next red report it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The Alpine stderr, once the check stopped discarding it: `vstack: no vstack repo found (checked $VSTACK_DIR, ~/.vstack, and this script's git root)`, rc=1, all three lanes. Not a portability defect in `vstack trust` and nothing to do with shasum, which was ruled out against a byte-identical image. Check 61 redirects HOME so each lane writes its own trust store instead of the operator's. That also hides ~/.vstack and the global gitconfig. bin/vstack resolves its repo from $VSTACK_DIR, then ~/.vstack, then `git rev-parse --show-toplevel`; under a foreign HOME the first two are gone, and in the Alpine container the third fails as well, because actions/checkout writes its safe.directory exemption into the runner HOME's gitconfig and the override hides it, so git refuses the checkout as dubiously owned. bin/vstack exits before `trust` runs. Proven: the message, the rc, and that it is Alpine-only. Inferred: that the git-root lane lost on dubious ownership specifically -- the message does not say which of the three failed. Naming $VSTACK_DIR settles it either way and is what the error text tells you to do. The check's own environment, not a defect in what it measures. A user does not run vstack under a substituted HOME. What made it expensive is that the invocation threw away stderr, so one platform went red with a sentence that could not distinguish this from a broken hasher. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
Opened to get CI evidence without touching
mainor thev1.61.0tag, which has now been destroyed three times.tests/container-matrix.shnever installspython3. Provisioned it rather than addingpython3 not on PATHto the credential-skip keyword list, which would have been a false label.bin/doctor:1292printsDRIFT ✖as a generic summary for any non-zero fail count, and it survived the filter, so the residual was non-empty even when the allowed finding was the only failure.rcand stderr instead of swallowing them. This PR does not fix that defect. It makes the next red run say what it is.🤖 Generated with Claude Code