remote info reads every manifest to learn which blobs are referenced. A manifest it could not read was logged and skipped, so that snapshot's blobs were counted as orphaned and the report advised running vaultik prune. The orphan figures are now unknown in that case: the report prints unknown (N manifest(s) could not be read, M manifest(s) under a non-conforming name skipped) and no prune advice, and the --json document gives orphaned_blob_count and orphaned_blob_size as null and lists the remote keys in unreadable_manifests.
Only a listed manifest.json.zst is read. A directory holding only db.zst.age, as a backup interrupted before its manifest upload leaves, keeps the figures known; prune does not treat it as a snapshot either.
Directory names under metadata/ now go through isBlobHash, the check listAllRemoteSnapshotKeys already applies, and a name that fails is skipped with the same warning. A manifest under such a name is not read, so it also leaves the figures unknown; --json counts those manifests in skipped_manifest_count and never gives the names.
Things the diff does not make obvious:
OrphanedBlobCount and OrphanedBlobSize are now pointers so the JSON can carry null; a script reading them has to handle it.
The closing Remote info complete log line carries unreadable_manifests in place of orphaned_blobs, since a nil pointer would print as an address.
Judgement call: the "Referenced by snapshots" figures, and the row of a snapshot whose manifest could not be read (0 blobs), still count only what was read. The issue asks only for the orphan figures.
Model: opus-5-5
Fixes https://git.eeqj.de/sneak/vaultik/issues/228.
`remote info` reads every manifest to learn which blobs are referenced. A manifest it could not read was logged and skipped, so that snapshot's blobs were counted as orphaned and the report advised running `vaultik prune`. The orphan figures are now unknown in that case: the report prints `unknown (N manifest(s) could not be read, M manifest(s) under a non-conforming name skipped)` and no prune advice, and the `--json` document gives `orphaned_blob_count` and `orphaned_blob_size` as `null` and lists the remote keys in `unreadable_manifests`.
Only a listed `manifest.json.zst` is read. A directory holding only `db.zst.age`, as a backup interrupted before its manifest upload leaves, keeps the figures known; `prune` does not treat it as a snapshot either.
Directory names under `metadata/` now go through `isBlobHash`, the check `listAllRemoteSnapshotKeys` already applies, and a name that fails is skipped with the same warning. A manifest under such a name is not read, so it also leaves the figures unknown; `--json` counts those manifests in `skipped_manifest_count` and never gives the names.
Things the diff does not make obvious:
- `OrphanedBlobCount` and `OrphanedBlobSize` are now pointers so the JSON can carry `null`; a script reading them has to handle it.
- The closing `Remote info complete` log line carries `unreadable_manifests` in place of `orphaned_blobs`, since a nil pointer would print as an address.
Judgement call: the "Referenced by snapshots" figures, and the row of a snapshot whose manifest could not be read (0 blobs), still count only what was read. The issue asks only for the orphan figures.
Model: opus-5-5
internal/vaultik/info.go:305: a directory under metadata/ whose name fails the check is dropped before its manifest is read, but it is not counted as unreadable. The orphan figures therefore stay known and the prune advice is still printed, while prune still lists that directory as a snapshot (listUniqueSnapshotIDs, internal/vaultik/prune.go:209). In the scenario of internal/vaultik/prune_manifest_safety_test.go:39 (an undecodable metadata/corruptkey/manifest.json.zst and one blob), remote info now reports the blob as orphaned and advises vaultik prune, which then refuses. That is the defect #228 asks to fix. If the manifest under such a name is readable, remote info calls its blob orphaned (before this change it counted it as referenced) while prune keeps it. Acceptable: a skipped name leaves the orphan figures unknown with no prune advice, the text report and --json give the reason without printing the raw name, and a test covers this case.
TODO.md:25: conflicts with current next (b57ce22), whose new Completed Steps entry for #226 is at the same place. Rebase onto next and keep both entries.
Model: opus-5-5
1. `internal/vaultik/info.go:305`: a directory under `metadata/` whose name fails the check is dropped before its manifest is read, but it is not counted as unreadable. The orphan figures therefore stay known and the prune advice is still printed, while `prune` still lists that directory as a snapshot (`listUniqueSnapshotIDs`, `internal/vaultik/prune.go:209`). In the scenario of `internal/vaultik/prune_manifest_safety_test.go:39` (an undecodable `metadata/corruptkey/manifest.json.zst` and one blob), `remote info` now reports the blob as orphaned and advises `vaultik prune`, which then refuses. That is the defect https://git.eeqj.de/sneak/vaultik/issues/228 asks to fix. If the manifest under such a name is readable, `remote info` calls its blob orphaned (before this change it counted it as referenced) while `prune` keeps it. Acceptable: a skipped name leaves the orphan figures unknown with no prune advice, the text report and `--json` give the reason without printing the raw name, and a test covers this case.
2. `TODO.md:25`: conflicts with current `next` (`b57ce22`), whose new Completed Steps entry for https://git.eeqj.de/sneak/vaultik/issues/226 is at the same place. Rebase onto `next` and keep both entries.
Model: opus-5-5
internal/vaultik/info.go: a name skipped under metadata/ now also leaves the orphan figures unknown with no prune advice. The report line gives both counts (N manifest(s) could not be read, M name(s) under metadata/ skipped), --json adds skipped_metadata_names (a count, never the name), and TestRemoteInfo_SkipsNonConformingMetadataName now adds an unreferenced blob and checks the text and the JSON for this case.
TODO.md: rebased onto next (b57ce22); both Completed Steps entries kept, this one on top.
Model: opus-5-5
Rework delta:
1. `internal/vaultik/info.go`: a name skipped under `metadata/` now also leaves the orphan figures unknown with no prune advice. The report line gives both counts (`N manifest(s) could not be read, M name(s) under metadata/ skipped`), `--json` adds `skipped_metadata_names` (a count, never the name), and `TestRemoteInfo_SkipsNonConformingMetadataName` now adds an unreferenced blob and checks the text and the JSON for this case.
2. `TODO.md`: rebased onto `next` (`b57ce22`); both Completed Steps entries kept, this one on top.
Model: opus-5-5
internal/vaultik/info.go:367: a directory under metadata/ with no manifest.json.zst in it is counted as an unreadable manifest, so the orphan figures become unknown and the prune advice is dropped. A backup interrupted between the database upload and the manifest upload (internal/snapshot/snapshot.go:446-465) leaves such a directory, holding only db.zst.age. remote info then reports "1 manifest(s) could not be read", while prune does not treat that directory as a snapshot (listUniqueSnapshotIDs, internal/vaultik/prune.go:209) and deletes the blobs the report would have listed as orphaned. Before this change, remote info reported the same blobs as prune in this state. A skipped name under metadata/ with no manifest in it (info.go:318) has the same effect. Acceptable: the figures become unknown only for a directory whose manifest.json.zst is listed and cannot be read, or for a skipped name that holds one. A directory without a manifest leaves the figures known, as before, and a test covers a directory holding only db.zst.age.
Model: opus-5-5
1. `internal/vaultik/info.go:367`: a directory under `metadata/` with no `manifest.json.zst` in it is counted as an unreadable manifest, so the orphan figures become unknown and the prune advice is dropped. A backup interrupted between the database upload and the manifest upload (`internal/snapshot/snapshot.go:446-465`) leaves such a directory, holding only `db.zst.age`. `remote info` then reports "1 manifest(s) could not be read", while `prune` does not treat that directory as a snapshot (`listUniqueSnapshotIDs`, `internal/vaultik/prune.go:209`) and deletes the blobs the report would have listed as orphaned. Before this change, `remote info` reported the same blobs as `prune` in this state. A skipped name under `metadata/` with no manifest in it (`info.go:318`) has the same effect. Acceptable: the figures become unknown only for a directory whose `manifest.json.zst` is listed and cannot be read, or for a skipped name that holds one. A directory without a manifest leaves the figures known, as before, and a test covers a directory holding only `db.zst.age`.
Model: opus-5-5
internal/vaultik/info.go: only a listed manifest.json.zst is read now. A directory without one, under a remote key or a skipped name, no longer makes the orphan figures unknown, so they and the prune advice match prune again; a manifest that is listed and unreadable, or sits under a skipped name, still does. Since the count is now of manifests rather than names, the --json field is skipped_manifests and the text says M manifest(s) under a non-conforming name skipped. TestRemoteInfo_DirectoryWithoutManifestLeavesOrphansKnown covers a directory holding only db.zst.age, under a remote key and under a control-character name.
Model: opus-5-5
Rework delta:
1. `internal/vaultik/info.go`: only a listed `manifest.json.zst` is read now. A directory without one, under a remote key or a skipped name, no longer makes the orphan figures unknown, so they and the prune advice match `prune` again; a manifest that is listed and unreadable, or sits under a skipped name, still does. Since the count is now of manifests rather than names, the `--json` field is `skipped_manifests` and the text says `M manifest(s) under a non-conforming name skipped`. `TestRemoteInfo_DirectoryWithoutManifestLeavesOrphansKnown` covers a directory holding only `db.zst.age`, under a remote key and under a control-character name.
Model: opus-5-5
TODO.md:25: conflicts with current next (5d1118d), whose new Completed Steps entry for #229 is at the same place. Rebase onto next and keep both entries.
internal/vaultik/info.go:227: skipped_manifests is a count, but its name matches unreadable_manifests beside it, which is a list of remote keys, and every other count in the same document ends in _count (total_metadata_count, total_blob_count, referenced_blob_count, orphaned_blob_count, blob_count). A script cannot tell from the name which field is a number. Acceptable: skipped_manifest_count (with the Go field named to match), and README.md:399 and the TODO.md entry updated.
internal/vaultik/info.go:261: the progress line still prints Downloading N manifest(s)... with N as the number of directories under metadata/, but only directories whose manifest.json.zst is listed are now downloaded. With a directory holding only db.zst.age (the state TestRemoteInfo_DirectoryWithoutManifestLeavesOrphansKnown sets up) it reports 2 and downloads 1. Acceptable: N is the number of manifests that will be read.
Model: opus-5-5
1. `TODO.md:25`: conflicts with current `next` (`5d1118d`), whose new Completed Steps entry for https://git.eeqj.de/sneak/vaultik/issues/229 is at the same place. Rebase onto `next` and keep both entries.
2. `internal/vaultik/info.go:227`: `skipped_manifests` is a count, but its name matches `unreadable_manifests` beside it, which is a list of remote keys, and every other count in the same document ends in `_count` (`total_metadata_count`, `total_blob_count`, `referenced_blob_count`, `orphaned_blob_count`, `blob_count`). A script cannot tell from the name which field is a number. Acceptable: `skipped_manifest_count` (with the Go field named to match), and `README.md:399` and the `TODO.md` entry updated.
3. `internal/vaultik/info.go:261`: the progress line still prints `Downloading N manifest(s)...` with N as the number of directories under `metadata/`, but only directories whose `manifest.json.zst` is listed are now downloaded. With a directory holding only `db.zst.age` (the state `TestRemoteInfo_DirectoryWithoutManifestLeavesOrphansKnown` sets up) it reports 2 and downloads 1. Acceptable: N is the number of manifests that will be read.
Model: opus-5-5
When a manifest could not be read, remote info skipped it, counted that
snapshot's blobs as orphaned and advised running prune. The orphan
figures are now unknown in that case, with no prune advice; --json gives
them as null and lists the unreadable remote keys in
unreadable_manifests. Only a listed manifest.json.zst is read, so a
directory without one, as an interrupted backup leaves, keeps the
figures known.
Names under metadata/ were used unchecked and printed raw. A name that
is not a remote key is now skipped with a warning. A manifest under it
is not read either, so it also leaves the figures unknown; --json counts
such manifests in skipped_manifest_count.
Model: opus-5-5
TODO.md: rebased onto next (5d1118d); both Completed Steps entries kept, this one on top.
internal/vaultik/info.go: the field is now skipped_manifest_count (Go SkippedManifestCount); README.md and the TODO.md entry match.
internal/vaultik/info.go: the progress line now counts only directories whose manifest.json.zst is listed; TestRemoteInfo_DirectoryWithoutManifestLeavesOrphansKnown checks that it says 1.
Model: opus-5-5
Rework delta:
1. `TODO.md`: rebased onto `next` (`5d1118d`); both Completed Steps entries kept, this one on top.
2. `internal/vaultik/info.go`: the field is now `skipped_manifest_count` (Go `SkippedManifestCount`); `README.md` and the `TODO.md` entry match.
3. `internal/vaultik/info.go`: the progress line now counts only directories whose `manifest.json.zst` is listed; `TestRemoteInfo_DirectoryWithoutManifestLeavesOrphansKnown` checks that it says 1.
Model: opus-5-5
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Fixes #228.
remote inforeads every manifest to learn which blobs are referenced. A manifest it could not read was logged and skipped, so that snapshot's blobs were counted as orphaned and the report advised runningvaultik prune. The orphan figures are now unknown in that case: the report printsunknown (N manifest(s) could not be read, M manifest(s) under a non-conforming name skipped)and no prune advice, and the--jsondocument givesorphaned_blob_countandorphaned_blob_sizeasnulland lists the remote keys inunreadable_manifests.Only a listed
manifest.json.zstis read. A directory holding onlydb.zst.age, as a backup interrupted before its manifest upload leaves, keeps the figures known;prunedoes not treat it as a snapshot either.Directory names under
metadata/now go throughisBlobHash, the checklistAllRemoteSnapshotKeysalready applies, and a name that fails is skipped with the same warning. A manifest under such a name is not read, so it also leaves the figures unknown;--jsoncounts those manifests inskipped_manifest_countand never gives the names.Things the diff does not make obvious:
OrphanedBlobCountandOrphanedBlobSizeare now pointers so the JSON can carrynull; a script reading them has to handle it.Remote info completelog line carriesunreadable_manifestsin place oforphaned_blobs, since a nil pointer would print as an address.Judgement call: the "Referenced by snapshots" figures, and the row of a snapshot whose manifest could not be read (0 blobs), still count only what was read. The issue asks only for the orphan figures.
Model: opus-5-5
internal/vaultik/info.go:305: a directory undermetadata/whose name fails the check is dropped before its manifest is read, but it is not counted as unreadable. The orphan figures therefore stay known and the prune advice is still printed, whileprunestill lists that directory as a snapshot (listUniqueSnapshotIDs,internal/vaultik/prune.go:209). In the scenario ofinternal/vaultik/prune_manifest_safety_test.go:39(an undecodablemetadata/corruptkey/manifest.json.zstand one blob),remote infonow reports the blob as orphaned and advisesvaultik prune, which then refuses. That is the defect #228 asks to fix. If the manifest under such a name is readable,remote infocalls its blob orphaned (before this change it counted it as referenced) whileprunekeeps it. Acceptable: a skipped name leaves the orphan figures unknown with no prune advice, the text report and--jsongive the reason without printing the raw name, and a test covers this case.TODO.md:25: conflicts with currentnext(b57ce22), whose new Completed Steps entry for #226 is at the same place. Rebase ontonextand keep both entries.Model: opus-5-5
c113e120d6to167adf8eb1Rework delta:
internal/vaultik/info.go: a name skipped undermetadata/now also leaves the orphan figures unknown with no prune advice. The report line gives both counts (N manifest(s) could not be read, M name(s) under metadata/ skipped),--jsonaddsskipped_metadata_names(a count, never the name), andTestRemoteInfo_SkipsNonConformingMetadataNamenow adds an unreferenced blob and checks the text and the JSON for this case.TODO.md: rebased ontonext(b57ce22); both Completed Steps entries kept, this one on top.Model: opus-5-5
internal/vaultik/info.go:367: a directory undermetadata/with nomanifest.json.zstin it is counted as an unreadable manifest, so the orphan figures become unknown and the prune advice is dropped. A backup interrupted between the database upload and the manifest upload (internal/snapshot/snapshot.go:446-465) leaves such a directory, holding onlydb.zst.age.remote infothen reports "1 manifest(s) could not be read", whileprunedoes not treat that directory as a snapshot (listUniqueSnapshotIDs,internal/vaultik/prune.go:209) and deletes the blobs the report would have listed as orphaned. Before this change,remote inforeported the same blobs asprunein this state. A skipped name undermetadata/with no manifest in it (info.go:318) has the same effect. Acceptable: the figures become unknown only for a directory whosemanifest.json.zstis listed and cannot be read, or for a skipped name that holds one. A directory without a manifest leaves the figures known, as before, and a test covers a directory holding onlydb.zst.age.Model: opus-5-5
167adf8eb1to55f2cb9cffRework delta:
internal/vaultik/info.go: only a listedmanifest.json.zstis read now. A directory without one, under a remote key or a skipped name, no longer makes the orphan figures unknown, so they and the prune advice matchpruneagain; a manifest that is listed and unreadable, or sits under a skipped name, still does. Since the count is now of manifests rather than names, the--jsonfield isskipped_manifestsand the text saysM manifest(s) under a non-conforming name skipped.TestRemoteInfo_DirectoryWithoutManifestLeavesOrphansKnowncovers a directory holding onlydb.zst.age, under a remote key and under a control-character name.Model: opus-5-5
TODO.md:25: conflicts with currentnext(5d1118d), whose new Completed Steps entry for #229 is at the same place. Rebase ontonextand keep both entries.internal/vaultik/info.go:227:skipped_manifestsis a count, but its name matchesunreadable_manifestsbeside it, which is a list of remote keys, and every other count in the same document ends in_count(total_metadata_count,total_blob_count,referenced_blob_count,orphaned_blob_count,blob_count). A script cannot tell from the name which field is a number. Acceptable:skipped_manifest_count(with the Go field named to match), andREADME.md:399and theTODO.mdentry updated.internal/vaultik/info.go:261: the progress line still printsDownloading N manifest(s)...with N as the number of directories undermetadata/, but only directories whosemanifest.json.zstis listed are now downloaded. With a directory holding onlydb.zst.age(the stateTestRemoteInfo_DirectoryWithoutManifestLeavesOrphansKnownsets up) it reports 2 and downloads 1. Acceptable: N is the number of manifests that will be read.Model: opus-5-5
55f2cb9cfftod19ee34155Rework delta:
TODO.md: rebased ontonext(5d1118d); both Completed Steps entries kept, this one on top.internal/vaultik/info.go: the field is nowskipped_manifest_count(GoSkippedManifestCount);README.mdand theTODO.mdentry match.internal/vaultik/info.go: the progress line now counts only directories whosemanifest.json.zstis listed;TestRemoteInfo_DirectoryWithoutManifestLeavesOrphansKnownchecks that it says 1.Model: opus-5-5
Review passed.
Model: opus-5-5