Repository navigation
Report index gaps instead of writing them (#15) - #16
Merged
Merged
Conversation
A vault that writes its own `index.md` files — its own headings, its own order, its own groupings — can't use index generation, because generation writes a shape the vault didn't choose. The closing comment on #8 asked for the maintenance half instead: flag a folder with no `index.md`, and flag the entries a listing is missing, "doesn't matter where in file". That last clause is the requirement. A note counts as listed if the index links at it anywhere, under any heading, in any order — so the check had to be the reading `mergeIndex` already does to decide what to append, not a second one that would drift from it. `mergeIndex` now returns that reading alongside the merged text, and `unlistedEntries` stops one step short of the append. Both findings are warnings. §8 makes an index optional and §11 forbids failing a bundle for a missing one, so this says a vault's own convention has slipped, not that the bundle is non-conformant. Off by default. Building a folder's listing and writing it are now separate steps, so the report can ask what a folder's entries are without the generator's side effect of filling in a subfolder's missing index on the way past. The report pane's "Open note →" now appears only when the path resolves to a file. It was always shown and silently did nothing otherwise, which a finding that names the `index.md` a folder hasn't got would hit every time. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The report pane labelled each finding with the file name alone. Two notes named the same in different folders were one row repeated, and an index finding — which names `index.md` — said nothing at all about which folder it meant, so the gap report added in this branch was unreadable exactly where it mattered. The path is split so the folder part carries the shrink factor: at a narrow pane width the folders ellipsize and the file name the row ends in stays legible. The `aria-label` already carried the full path and is unchanged.
The report pane had two ways of wasting a reader's attention. Every row carried its full vault-relative path, so a folder with a dozen findings spent most of a sidebar's width writing its own name a dozen times. And opening a note re-validated it -- that has always happened -- but sent the verdict to the status bar alone, a count with the detail in a tooltip, while the pane went on showing whatever the last vault scan had found, every row collapsed. The note in front of you was the one thing the pane wouldn't tell you about. Rows are now grouped under a header naming the folder once, and the note in the editor gets a section of its own at the top, listed open. Grouping: results are bucketed by their folder, error-bearing folders sort first and then alphabetically, and rows sort the same way inside each group. Groups start expanded -- a header is there to say where a finding lives, not to hide it -- and collapse per folder, with their collapsed state pruned against the folders of the current results the way per-file expansion already was. The full path stays on each row's aria-label, so it never has to be reconstructed from what happens to be rendered above it. Active note: the plugin holds the active note's findings in a field of its own and pushes them to the pane on file-open, on the live check after a save, when a pane is opened later, and at the end of a scan -- that last one because a Fix all would otherwise leave the section contradicting the list below it. They are kept out of the scan results on purpose: those count the vault, and one note's verdict arriving between scans would have the summary chips describing a vault nobody scanned. Opening something that isn't a markdown note clears the section rather than leaving a stale verdict standing. renderBody() is split into summary / active / list, which also moves the two empty-state early returns down into the list -- before, "no scan yet" would have suppressed the active section, which is exactly the case where it earns its place.
`Report index gaps` finds a gap by walking the folder tree, and only `scanVault` walks it. `validateActive` runs `validateContent` alone, so opening a folder's `index.md` dropped the very findings the scan files against that path: the pane's Active note section and the status bar both called the file clean while its own row in the list below carried the warnings. Switching tabs away and back was enough to make the pane contradict itself about one file. Adds `indexGapsForActive`, which runs the same folder pass for the one folder an open `index.md` describes. It is guarded on `folderIsIndexable`, the predicate the scan's walk prunes by. Both halves of that predicate are prefix-closed, so a folder passing implies every ancestor passes, and checking the file's own folder is exactly equivalent to re-deriving the walk — an index under an excluded folder, or under the config dir, picks up nothing merely by being open. The merge lands before `updateStatus`, so the status bar counts the gaps too, and `openReport` reads the same list, so `Validate active note` does as well. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Merged
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.
Closes #15. Follow-up to the closing comment on #8.
The ask
A vault that hand-writes its
index.mdfiles can't use index generation, because generation writes a shape the vault didn't choose. The reporter of #8 said so on the way out, and asked for the maintenance half instead:What this adds
A Report index gaps setting, off by default. On, a vault scan warns:
index.mdat all, andIt writes nothing. Both are warnings, never errors — §8 makes an index optional and §11 forbids failing a bundle for a missing one, so this reports that a vault's own convention has slipped, not that the bundle is non-conformant. Findings are filed against the index's own path, since that is the file to edit, and it reads as "this should be here" in the case where it isn't.
"Doesn't matter where in file" is the whole requirement, so the check is the reading
mergeIndexalready does to decide what to append — an entry counts under whatever heading, in whatever order, in whatever grouping its author invented. Rather than write a second implementation that would drift from the first,mergeIndexnow returns that reading alongside the merged text andunlistedEntriesstops one step short of the append. Building a folder's listing and writing it are likewise now separate steps, so the report can ask what a folder's entries are without the generator's side effect of filling in a subfolder's missing index on the way past.Also: the report pane's Open note → now appears only when the path resolves to a file. It was always shown and silently did nothing otherwise — which a finding that names the
index.mda folder hasn't got would hit every time.Verification
npx tsc --noEmitandnpm run buildare clean. Behaviour was checked with two throwaway harnesses (not committed — this repo has no test framework), 21 assertions, all passing.Against a hand-authored index in the reporter's own shape — one H1 naming the directory, prose, H3 groupings the plugin would never generate, a numbered list, a wikilink, a bare subdirectory link, and nothing in the plugin's order:
deep/) still counts as listedAnd over a stubbed vault walked through the plugin's own folder logic: excluded folders are skipped and the root is included; a folder with no index reports one warning filed at the index it hasn't got; a root index that never names
raft.mdreports exactly that; every finding is a warning citing §8; and nothing is written — noindex.mdis created, and the existing one stays byte-identical.Deliberately out of scope: the reporter also attached their own
index.md/log.mdcontracts. Their log rules are already largely enforced (validateLogcovers no-frontmatter, ISO date headings, newest-first). Their index structural rules — exactly one H1 naming the directory, H3 subgrouping, a description trailer on every link — are vault conventions rather than OKF, so they aren't checks to impose by default.The changelog entry sits under
## [Unreleased]; this is a new capability, so it's a minor bump when you want to cut one.🤖 Generated with Claude Code