fix(ci): add PyYAML 6.0.3 cp311 hashes for cloud Python 3.11 - #2657
Conversation
SessionStart pip --require-hashes failed on Melodic cloud VMs because requirements-ci.txt only listed cp314 wheels while the VM ships 3.11. Add the matching cp311 platform set (verified against PyPI), including the Linux x86_64 hash from #2654, and note the coverage in the cloud fleet setup checklist. Co-authored-by: Kyle Sexton <kyle-sexton@users.noreply.github.com>
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
|
Claude finished @kyle-sexton's task in 1m 49s —— View job Security review complete
No security issues found. This PR is a pip hash-pinning fix: it adds cp311 wheel hashes (Linux/macOS/Windows) for Notes from the review:
|
|
Last security-reviewed head: |
|
Claude finished @kyle-sexton's task in 2m 3s —— View job Security review — no findings
Scope reviewed: This PR only adds 8 additional From a supply-chain-security lens (the one angle this kind of change can affect):
No CRITICAL, IMPORTANT, or SUGGESTION findings. |
Rely on #2657's cp311 PyYAML hashes so SessionStart always runs `--require-hashes` without an interpreter-mismatch skip or unpinned ruff fallback. A digest mismatch stays fatal. Co-authored-by: Kyle Sexton <kyle-sexton@users.noreply.github.com>
|
Claude finished @kyle-sexton's task in 3m 37s —— View job Claude Code Review
SummaryScope: adds 8 cp311 sha256 hashes for PyYAML 6.0.3 to Checks performed:
One suggestion posted inline on Limitation: this review lane has no outbound network access, so I could only validate hash format (well-formed, non-duplicate) — not the hash values against PyPI's published digests for the cp311 wheels. The PR description states these were verified against PyPI manually. No correctness or security issues found in the diff itself. |
| --hash=sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e \ | ||
| --hash=sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824 \ | ||
| --hash=sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf \ | ||
| --hash=sha256:8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b |
There was a problem hiding this comment.
Suggestion (maintainability): the 8 new cp311 hashes are structurally well-formed (64-char lowercase hex, no duplicates against each other or the existing cp314 set) and the file's --require-hashes install fails closed if a hash is wrong — so this can't silently install the wrong wheel. But nothing in .github/workflows/ci.yml actually exercises the cp311 branch: hook-exec-form-gate only sets up Python 3.14 (ci.yml#L505), so a typo'd cp311 hash here wouldn't be caught until it breaks cloud SessionStart again — the exact failure mode this PR fixes (#2654). Consider codifying the manual verification command from the PR description (python3.11 -m pip install --dry-run --require-hashes -r .github/requirements-ci.txt) as a cheap CI step (e.g. an extra setup-python@… + dry-run install with python-version: '3.11') so a future re-pin can't regress this silently.
I wasn't able to independently verify the hash values against PyPI (no outbound network access in this review lane) — only their format.
|
Claude has reviewed this PR 1 time. The lane skips further automatic reviews after 5; deleting this comment resets the count. |
…ins (#2655) No linked issue ## Summary Cloud sessions on this repo started with zero plugins loaded and no bootstrap at all: every `/plugin` command unknown, no plugin skill available, an empty `~/.claude/plugins/installed_plugins.json`, and none of the CI-parity tooling `.claude/hooks/session-start.sh` exists to provide. Three independent causes, all fixed here. ## Fix **1. The SessionStart hook was never registered.** `.claude/settings.json` had no `hooks` key. The script has carried a header comment claiming it was registered since it was added in 39fe757, and `docs/CLOUD-SESSIONS.md` documented the registration, but `git log -p --all -- .claude/settings.json` shows the key was never committed — so the bootstrap had never run in a cloud session. Registered with matcher `startup|resume`, pointing at the script via `$CLAUDE_PROJECT_DIR`. **2. Declaring a marketplace is not installing it.** [What runs before you trust a folder](https://code.claude.com/docs/en/permissions#what-runs-before-you-trust-a-folder) groups `extraKnownMarketplaces` entries with content that needs *this exact folder* trusted, while hooks and the `env` block are used whether or not it is. A cloud session on this repo had `hasTrustDialogAccepted` false, an empty plugin registry, and no plugin loaded — while the same settings file's `env` block *had* applied, exactly the split that table predicts. A hook is the durable fix because hooks run untrusted. The hook registers the checkout by absolute path and installs every plugin `enabledPlugins` sets to `true`, computed from the tracked settings file with `jq` so it cannot drift from the catalog. It deliberately never calls `claude plugin marketplace remove` — that subcommand deletes the marketplace's entry from `.claude/settings.json`, so a hook using it to force a re-add would silently mutate tracked repository config. (Observed directly while diagnosing this.) It also repairs same-version commit drift. A directory-source cache is keyed by the semver in `plugin.json` rather than the commit (`docs/MIGRATION-PLAYBOOK.md`, #2061), so a presence check alone would keep serving whichever commit installed first — defeating the reason this repo uses a directory source. The hook compares the `gitCommitSha` recorded at install time against `HEAD` and runs the documented uninstall/install/enable cycle for the plugins whose own directory changed, so an ordinary resume stays cheap. **3. The Python install aborted the bootstrap.** `.github/requirements-ci.txt` was hash-locked against CI's Python 3.14 wheels only; the cloud VM ships 3.11.15 and resolves a different `pyyaml` wheel, so `--require-hashes` refused it and `set -e` aborted before the hygiene binaries and git-history steps ever ran. That surfaced #2654, fixed on `main` by #2657, which added the cp311 hash set. This branch is rebased onto that fix and keeps the install **fail-closed**: SessionStart always runs the hash-locked install and a failure stays fatal. An earlier revision of this branch fell back to a ruff-only install on an interpreter-version mismatch; that was removed, because it both weakened the one control that catches a tampered wheel and — once #2657 landed — would have skipped an install that now succeeds, leaving `pyyaml`/`pytest` permanently absent. `docs/CLOUD-SESSIONS.md` is corrected in the same change: it previously claimed the hook was registered and described the directory source as installing at session start. ## Verification Verified live rather than by inspection — the session restarted mid-change and the newly registered hook fired on its own: ``` SessionStart:resume hook success: session-start: plugins 65 enabled, 26 newly installed, 0 failed session-start: bootstrap complete in /home/user/claude-code-plugins ``` All 65 plugin skill sets became available in-session (`/claude-config:audit`, the command that surfaced this, among them), and `markdown-format` and `hardcoded-path-check` hooks then fired on subsequent edits — confirming plugin hooks load, not just skills. The fail-closed install, checked on a real cloud VM at `8773eae5`: ``` $ python3 -V Python 3.11.15 $ python3 -m pip install --user --only-binary=:all: --require-hashes -r .github/requirements-ci.txt EXIT=0 (2.4s) ``` Full CI-parity inventory now present, all three previously absent or wrong: `ruff` 0.16.2 (CI's exact pin, against the VM image's 0.15.8), `pytest` 9.1.1, `pyyaml` 6.0.3. Other post-run state: - `claude plugin list --json | jq length` → 103 (65 enabled + 38 auto-installed dependencies) - `claude plugin marketplace list --json` → `{"name":"melodic-software","source":"directory","path":"<repo-root>"}` — resolved from the checkout, so a session exercises branch code rather than published `main` - Refresh predicate selects `repo-fleet-hygiene` (10 files changed since the recorded SHA) and skips `session-flow`, `adhd`, `claude-config` (0 changed); an uninstalled id falls through to the install path Gates, all clean: `shellcheck` (with the repo's `check-set-e-suppressed`), `shfmt -d`, `bash -n`, `markdownlint-cli2`, `typos`, `editorconfig-checker`, `check-jsonschema` against the settings schema, and both repo-local hook tests (17/17). Empty-array handling under `set -u` checked against the VM's bash 5.2.21. Not verified: whether a `github`-source marketplace auto-installs at session start without a hook. That is the path consumer repos should use, and it resolves fine here (`claude plugin marketplace add melodic-software/claude-code-plugins` clones through the proxy), but confirming the no-hook auto-install needs a fresh cloud session on a consumer repo. Follow-up, not blocking: the strict path is load-bearing on `requirements-ci.txt` covering whatever `python3` the cloud image ships. If that image moves to a minor with no wheel hashes, session start aborts rather than degrades — worth generating hashes per supported interpreter instead of reactively, as #2654 → #2657 just did. ## Related Refs #2061 (same-version commit drift), #2654 / #2657 (cp311 wheel hashes), and the plugin-enablement setup in `docs/CLOUD-SESSIONS.md` and `docs/CLOUD-FLEET-SETUP.md`. Co-authored-by: Kyle Sexton <kyle-sexton@users.noreply.github.com>
#2668) No linked issue ## Summary Folds the 2026-08-14 live verification of the Melodic cloud environment (#2654) into `docs/CLOUD-FLEET-SETUP.md`, and swaps the guide's embedded environment setup script for a three-line bootstrap that curls the canonical script from the new `cloud-environment` component in standards (melodic-software/standards#388) — so environment behavior changes land by reviewed PR instead of hand-edits to an account-scoped UI field. ## Fix - **Step 1 network access**: the Custom allowlist (default package managers + `dot.net`, `aka.ms`, `builds.dotnet.microsoft.com`, `download.visualstudio.microsoft.com`) is now documented as the requirement, not a fallback — #2654 Blocker 1 reproduced the .NET installer's `403` under Trusted, overturning the 2026-08-13 probe-based optimism. - **Setup script section**: embedded script replaced by the bootstrap + pointers to the standards component and its README; documents the per-step timestamped log (`/var/log/melodic-env-setup.log`), the completion stamp (`/opt/melodic-env-setup.done`, written strictly last), and the cache-rebuild lifecycle (a merged standards change reaches environments only on a forced rebuild or ~7-day expiry). - **Verification checklist**: new item 0 checks the stamp first — a missing stamp is the #2654 Blocker 2 signature (cache build interrupted ~13 s in; PowerShell and the baked-in bootstrap never ran). The .NET item now points at confirming the allowlist rather than "applying the fallback". - **Findings + audit table**: the "bootstrap is unwired" finding is marked resolved — #2631 registered the SessionStart hook and enabled the 65-plugin catalog, #2657 closed the cp311 pyyaml hash gap the hook died on (verified against PyPI's published digests; coverage gap, not tampering). Remaining #2654 actions are environment-side (apply the allowlist, rebuild the cache, re-run the checklist). ## Verification - `markdownlint-cli2 docs/CLOUD-FLEET-SETUP.md` — 0 issues - All referenced anchors (`#step-1--the-shared-environment-claudeai-ui-one-time`, `#verification-checklist`) unchanged and resolvable - Claims cross-checked against the primary sources: #2654 (live run forensics), #2631 / #2657 diffs on `main`, and the component content in melodic-software/standards#388 ## Related - Refs #2654 — the verification report this folds in (left open: the environment-side actions — Custom allowlist + cache rebuild + checklist re-run — are still pending) - Refs #2631, #2657 — the repo-side fixes the Findings section now records - Refs melodic-software/standards#388 — the canonical setup script this guide now bootstraps from - Refs #2613 — the original fleet guide PR this follows up 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01AXaqhrFZeGTzbCJun12Ngx --- _Generated by [Claude Code](https://claude.ai/code/session_01AXaqhrFZeGTzbCJun12Ngx)_ Co-authored-by: Kyle Sexton <kyle-sexton@users.noreply.github.com>
…ste-once rollout kit (#2677) No linked issue ## Summary Cloud sessions could never use this repo's plugins on turn one: the SessionStart hook installs the full catalog, but Claude Code builds its plugin/command registry at process start — before hook effects land — and never re-reads it. This PR records that finding with its evidence and fix, and adds the copy-paste rollout kit for moving the whole fleet (and every account environment) onto the layout that works. ## Fix - `docs/CLOUD-SESSIONS.md`: document the same-session limit observed 2026-08-15 (hook completed `65 enabled, 65 newly installed, 0 failed` with the on-disk registry fully populated, yet the same session resolved no plugin command or skill), plus the confirmation that a stop/resume restarts the process and loads everything; reframe the environment setup-script one-liner from a performance lever to the required pre-launch slot for plugin liveness. - `.claude/hooks/session-start.sh`: state the timing limit in the header — hook-time installs serve the *next* process start, so the environment setup script must run this bootstrap at cache build for a session to start with plugins loaded. - `docs/CLOUD-FLEET-SETUP.md`: refresh the stale "bootstrap is currently unwired" finding (settings.json registers the hook on `main` and it ran), fix the verification step that relied on `/plugin` (unavailable in cloud sessions), and point step 1 at the rollout kit. - `prompts/cloud-bootstrap-rollout.md` (new): the paste-once account environment stub, the prompt for creating the shared `cloud/env-setup.sh` in `melodic-software/standards`, and the per-repo migration prompt that renames `.claude/hooks/session-start.sh` to `.claude/cloud-bootstrap.sh` — one script, two callers (environment setup script pre-launch; SessionStart hook for per-session drift repair) — and settles on one Default environment per account. ## Verification - `markdownlint-cli2`, `typos`, and `editorconfig-checker` pass on all touched files; `shellcheck` and `shfmt -d` pass on the hook (comment-only change). - Empirical basis verified live in the cloud session that produced this PR: installed-on-disk vs empty session registry, a failed mid-session skill probe, and full catalog loading after resume (this repo's own commit-convention hook began enforcing mid-session once loaded). - Official-docs basis: hooks reference documents no same-session pickup; `/plugin` and `--plugin-dir` are unavailable in cloud sessions; the setup script runs after clone and before the session process. ## Related `docs/CLOUD-SESSIONS.md` §"Plugins in sessions on this repo", `docs/CLOUD-FLEET-SETUP.md`, `docs/MIGRATION-PLAYBOOK.md` (same-version commit drift), #2061, #2539, #2657 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_018NhKrvZ4Jz1qK2wWDWXiZd --- _Generated by [Claude Code](https://claude.ai/code/session_018NhKrvZ4Jz1qK2wWDWXiZd)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
Closes #2654
Summary
Cloud Melodic SessionStart failed because
.github/requirements-ci.txthash-locked PyYAML 6.0.3 to cp314 wheels while the VM uses Python 3.11, so pip selected a cp311 manylinux wheel whose hash was missing.Fix
docs/CLOUD-FLEET-SETUP.mdverification checklist item 6.Verification
Related
Refs #2655 — SessionStart registration /
enabledPluginsinstall.Residual host notes
dot.net,aka.ms,builds.dotnet.microsoft.com,download.visualstudio.microsoft.com.