Repository navigation
feat(global-settings): derive the update list from settings.json and verify installed files (v2.7.0) - #804
Merged
Conversation
…verify installed files (v2.7.0) check-settings-version.sh: - The UPDATE REQUIRED notice no longer carries a hand-maintained file list. It fetches the canonical settings.json from the same source as VERSION and emits one command block per hook script it registers, plus settings.json first and VERSION last. The list had fallen behind settings.json twice: v2.4.1 added two hooks it had missed, and block-polling.sh, registered since v2.5.0, was never on it, so following the notice left that guard uninstalled while the version read as current. Hook names are validated before they land in a command; if the canonical settings.json cannot be fetched, the list falls back to the installed one and a warning says so. - When the installed version matches the online one, every registered hook is compared with its canonical copy (sha256, trailing newlines ignored: the printf-based install writes exactly one) and settings.json as parsed JSON without `model` (the VSCode picker writes that key under relock option B; a model choice is a preference, not policy). A missing or changed file produces a FILES OUT OF SYNC notice with the same unlock/contract/relock steps and repair blocks for the affected files only; the phrase is "repair my global settings". A canonical copy that cannot be fetched is reported as not verified, never assumed fine. - The status panel gains a Files line (7/7 verified, or the missing and changed counts). - The GitHub path fetches settings.json and then all hooks in one curl call each; the git-fetch path uses git show. The emitted command shapes are unchanged, so block-write-commands.sh allows them as before. README.md and docs/claude/global-claude-settings.md describe the derived list, the integrity check and the new notice. Tests: new tests/test-check-settings-version.sh runs offline against a file:// origin through the git-fetch path and, via a curl shim in PATH, the GitHub path; wired into hook-tests.yml. Suites: check-settings-version 78/78, polling 29/29. ShellCheck clean at all severities. VERSION 2.6.0 -> 2.7.0. Co-Authored-By: Claude Fable 5.1 <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.
Problem
The
UPDATE REQUIREDnotice thatcheck-settings-version.shemits carried a hand-maintained list of files to install. That list fell behindsettings.jsontwice: v2.4.1 added two hooks it had missed, andblock-polling.sh, registered insettings.jsonsince v2.5.0, was never on it. Anyone who updated through the notice landed asettings.jsonthat wires a hook whose script is absent, and the version check then reported them as up to date: it comparedVERSIONand nothing else.Change
check-settings-version.sh(installed as a hook, hence theVERSIONbump to 2.7.0):settings.jsonfrom the same source it tookVERSIONfrom and emits one command block per hook script it registers, plussettings.jsonfirst andVERSIONlast. A hook that is wired is a hook that gets installed. Hook names are validated before they are placed in a command. If the canonicalsettings.jsoncannot be fetched, the list falls back to the installed one and a warning says so.sha256, trailing newlines ignored because theprintf '%s\n'install writes exactly one).settings.jsonis compared as parsed JSON without themodelkey: the VSCode model picker writes{"model": …}under relock option (B), and a model choice is a preference, not policy. Everything else in that file counts, and the notice names the differing top-level keys.FILES OUT OF SYNC. Same unlock, contract and relock steps as an update, repair blocks for the affected files only,VERSIONleft alone. The phrase isrepair my global settings. A canonical copy that could not be fetched is reported as not verified, never assumed fine.Filesline (7/7 verified ✓, or the missing/changed counts).origin/main:path), soblock-write-commands.shallows them as before. The GitHub path costs two extra fetches per session (settings.json, then all hooks in onecurlcall); the git-fetch path costs none.Docs:
global-settings/README.md(new subsection under Updating) anddocs/claude/global-claude-settings.md(session-start messages, "What check-settings-version.sh does").Tests
New
global-settings/tests/test-check-settings-version.sh, wired intohook-tests.yml. Runs offline: a throwawayfile://origin holding this branch'sglobal-settings/, a clone the hook fetches from, and a fake home. The first part takes the git-fetch path; the second configuressettings-repo-urland puts acurlshim inPATHthat serves the same files, so the GitHub path and its one-call multi-file fetch are covered too. Positive control: an install pinned to v0.0.1 must be reported outdated.Covered: every registered hook appears in the update list and
VERSIONis last; a hook registered only insettings.jsonappears without touching the script (derived, not hardcoded); clean install → up to date, all verified; missing hook, changed hook, changedsettings.json(permissions) and invalid JSON →FILES OUT OF SYNCwith blocks for those files only;model-only change and extra trailing newlines are not drift; an unfetchable canonical copy → "not verified".Results: check-settings-version 78/78, block-polling 29/29, ShellCheck clean at all severities (repo
.shellcheckrc).After merge
Every developer gets the usual
UPDATE REQUIREDfor v2.7.0. From then on, an install with a missing or drifted hook is reported at the next session start instead of passing on the version number.🤖 Generated with Claude Code