Skip to content

feat(doctor): recompute a store version against the pack's file-manifest.csv - #139

Merged
arcaven merged 2 commits into
mainfrom
build/sideshow/xorml-doctor-manifest
Sep 30, 2026
Merged

arcaven merged 2 commits into
mainfrom
build/sideshow/xorml-doctor-manifest

Conversation

@arcaven

@arcaven arcaven commented Sep 30, 2026

Copy link
Copy Markdown
Member

sideshow doctor could 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

  • New layer-1 check store-file-manifest (internal/doctor/file_manifest.go). For each installed version it reads the root file-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.
  • No manifest: unavailable, naming a rebuild after sideshow-packs#40, never ok. A manifest that does not parse fails.
  • Install needs no change: it copies the whole source tree, so the in-pack manifest already lands in the store.

acceptance, red then green

  • Red: TestStoreFileManifest fails on main with no store-file-manifest finding.
  • Green: it passes with the ok, differs, missing, unlisted and no-manifest cases, each mutation undone back to ok. TestStoreFileManifestUnparsable covers a manifest that does not parse, and fails when the parse guard is removed.
  • End to end, in a temporary SIDESHOW_HOME and CLAUDE_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:
    • clean install: [ok] store-file-manifest: bmad 6.12.0: 2023 files match file-manifest.csv;
    • mobz8's case, install --from a copy with one edited SKILL.md and no manifest: [fail] ... 1 differ (first: .claude/skills/bmad-agent-architect/SKILL.md), while store-freeze still reports ok;
    • published bmad-v6.12.0-r2: [unavailable] ... ships no file-manifest.csv.

gates: gofumpt clean, go vet, golangci-lint 0 issues, go test ./... -race all 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):

  • The in-store manifest is only as trustworthy as the install source. sideshow does not see the release signature or install.meta until install fetches and verifies signed tarballs (aae-orc-wk92). An overwrite from a tree that ships its own consistent manifest is not detected by this check.
  • Refusing an overwrite at install time is mobz8's own fix and is not in this PR.

Opportunities (outside this PR):

  • The existing store-content-census fails 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

…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

@arcavenai arcavenai left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 sideshow at 5b69efb and ran doctor with 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.
  • 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, via sha256File) 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 vet is 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 -iwF per 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.

@arcaven
arcaven marked this pull request as ready for review September 30, 2026 13:51
@arcaven
arcaven merged commit 1b5d716 into main Sep 30, 2026
10 checks passed
@arcaven
arcaven deleted the build/sideshow/xorml-doctor-manifest branch September 30, 2026 13:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type.feature Net-new capability

Projects

None yet

Development

Successfully merging this pull request may close these issues.

doctor: recompute an installed store version against the pack's file-manifest.csv

2 participants