feat(doctor): recompute a store version against the pack's file-manifest.csv - #139
Merged
Merged
Conversation
…est.csv Packs built after sideshow-packs#40 carry a per-file manifest at their root, and install already copies it into the store. The new layer-1 check store-file-manifest recomputes every installed version against it and fails on content that differs, listed files that are missing, and files present but not listed. A version without the manifest reports unavailable, not ok. Refs: aae-orc-xorml, aae-orc-mobz8 Closes #138
Refs: aae-orc-xorml
arcavenai
approved these changes
Sep 30, 2026
arcavenai
left a comment
Member
There was a problem hiding this comment.
APPROVE at 5b69efb. Merge recommended.
Checked, one command each:
- Red: fresh main c33fdd2 with this PR's file_manifest_test.go checked out gives TestStoreFileManifest and TestStoreFileManifestUnparsable both FAIL, with "want one store-file-manifest finding, got []". Green at 5b69efb: both pass. The tests cover ok, differs, missing, unlisted, no-manifest (unavailable) and unparsable, and restore ok after each failure case.
- End to end: I built
sideshowat 5b69efb and randoctorwith HOME and SIDESHOW_HOME in a temp dir, over a store version I built (2 files plus a pipeline-shaped file-manifest.csv):- clean:
[ok] store-file-manifest: alpha 1.0.0: 2 files match file-manifest.csv, exit 0; - one byte changed, same size:
[fail] ... 1 differ (first: agents/a.md), exit 2, so the sha256 path runs and not only the size check; - an extra file plus a removed listed file:
1 differ; 1 missing (first: pack.yaml); 1 unlisted (first: extra.md), exit 2; - the manifest removed:
[unavailable] ... ships no file-manifest.csv, exit 0.
store-freeze reported only its warn on every run, never a manifest verdict, which fits the edited-copy case the body describes.
- clean:
- doctor stays read-only. A snapshot of the whole temp tree (path, mtime, size and mode of every entry, plus sha256 of every file) is identical before and after a doctor run. The new code opens files read-only (
os.Open, viasha256File) and walks with WalkDir, with no create, rename, chmod or remove. A snapshot of the real ~/.claude/settings.json and ~/.local/share/sideshow showed nothing newer after the test runs. - Install is unchanged: the diff is three files, all under internal/doctor, and layer1.go only registers the check.
- The limit is stated honestly in the body: the in-store manifest is only as trustworthy as its source until wk92 anchors it. An in-place edit of both a file and the manifest passes, as expected.
- The full suite has 15 packages ok and no failures.
go vetis clean, gofumpt lists nothing, and golangci-lint reports 0 issues. CI at 5b69efb is green. Both commits are signed. merge-tree against fresh main c33fdd2 is clean. The redaction scan (grep -iwFper token, with a positive control) and the em-dash scan are clean.
Non-blocking:
- Symlinks are skipped (
d.Type().IsRegular()). A listed path replaced by a symlink shows as missing, which is right. An unlisted symlink added to the store is not reported. The pipeline manifest lists regular files only, so this is consistent, but one line in the check's comment would stop a reader assuming full coverage. - A duplicate relpath in the manifest silently keeps the last entry. A parse error on duplicates would be stricter and cheap.
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.
sideshow doctorcould not tell when an installed store version stopped matching what the pack shipped: an in-place overwrite (aae-orc-mobz8) still read as healthy. Packs built after sideshow-packs#40 carry a per-file manifest at their root, and this check recomputes the store against it.item: aae-orc-xorml, half 2 (consumer). Half 1 is sideshow-packs#40.
changes
store-file-manifest(internal/doctor/file_manifest.go). For each installed version it reads the rootfile-manifest.csv(sha256,size,relpath, no header) and reports content that differs, listed files that are missing, and regular files present but not listed. The manifest itself is excluded.unavailable, naming a rebuild after sideshow-packs#40, never ok. A manifest that does not parse fails.acceptance, red then green
TestStoreFileManifestfails on main with nostore-file-manifestfinding.TestStoreFileManifestUnparsablecovers a manifest that does not parse, and fails when the parse guard is removed.SIDESHOW_HOMEandCLAUDE_CONFIG_DIR, with a bmad 6.12.0 pack built from build(deps): bump the actions group across 1 directory with 2 updates #40's branch:[ok] store-file-manifest: bmad 6.12.0: 2023 files match file-manifest.csv;install --froma copy with one edited SKILL.md and no manifest:[fail] ... 1 differ (first: .claude/skills/bmad-agent-architect/SKILL.md), whilestore-freezestill reports ok;[unavailable] ... ships no file-manifest.csv.gates: gofumpt clean,
go vet, golangci-lint 0 issues,go test ./... -raceall packages pass.blast radius: doctor output only; one new layer-1 finding per installed version. Unavailable never gates, and the new check fails only on a real mismatch. Existing packs report unavailable until reinstalled from a newer release.
limits (not decided here):
Opportunities (outside this PR):
store-content-censusfails on a clean install of the published r2:9 of 74 census entries differ from the store tree (first: bmb/config.yaml, bmm/config.yaml, cis/config.yaml). This looks like the build's identity neutralization editing config files after bmad records them in its own census.Closes #138
Refs: aae-orc-xorml, aae-orc-mobz8, ArcavenAE/sideshow-packs#40