Audit Scope
A sidebar checklist of the files under review. Point it at a markdown file
listing paths, tick them off as you go, and let it open each one the way that
makes sense for the commits you are reviewing between.
Plain JavaScript, no dependencies, no build step.
Where the data comes from
One markdown file per review, and nothing else. The extension never infers a
scope, never reads a project's own conventions, and holds no state of its own —
the markdown file is the whole input and the whole output.
It is found by glob (auditScope.glob, default **/SCOPE*.md). Several
matching files show as several roots, so one workspace can carry several
reviews at once.
Everything about how a file opens comes from that file's frontmatter:
---
title: Payments review
base: v1.4.0
head: release/1.5
---
## Ledger
- [ ] `src/ledger/posting.go`
- [x] `src/ledger/balance.go` — reviewed, no findings
## API
- [ ] `src/api/handlers.go`
| Key |
Meaning |
Missing? |
title |
Shown as the tree root |
Falls back to the filename |
base |
Left-hand side of the diff |
Files just open — no diffing |
head |
Right-hand side |
base is diffed against the working tree |
repo |
Path to the git repo, relative to the scope file |
The scope file's own repo — usually omit it |
Paths listed in the scope file resolve against the git repository root, not
against the scope file's directory, so the same list works whether the file sits
at the top of the repo or in a subdirectory. That is why repo is almost never
needed: set it only when the scope file lives outside the repository it
describes. A repo that does not point at a git repository falls back to the
scope file's own repo and says so on the root node rather than silently
resolving every path against the wrong place.
base and head take anything git rev-parse accepts — a sha, a tag, a
branch, origin/release-2, a local ref. A value that does not resolve is
reported on the root node rather than failing silently.
Frontmatter is optional at every level. A plain checklist with no ---
block works fine; it simply opens files instead of diffing them. That is also
the graceful path for a list you did not write for this extension — drop the
glob on it and you get a clickable, tickable tree immediately, then add
frontmatter later if you want diffs.
If several scope files in one repo share the same commits, set
auditScope.base / auditScope.head / auditScope.repo in workspace settings
instead of repeating them. Frontmatter always wins over settings, so a scope
file that names its own commits stays portable between machines and people.
Generating the markdown is not this extension's job. If your scope lives
somewhere else — a ticket, a spreadsheet, another document in the repo — write a
small script that emits the markdown and keep it with that project. The
extension reads the result and stays out of it.
What counts as a file
Headings (# … ######) become collapsible groups. Headings with no files
under them are dropped, so prose sections do not clutter the tree.
A list item counts as a file when it holds a backticked path, or a checkbox
followed by a path containing a separator. Bare prose bullets are ignored, as is
anything inside a fenced code block. Text after the path becomes the item's
tooltip. The [ ] marker is optional on input — ticking an item inserts one.
How a file opens
| Situation |
What happens |
No base |
Opens the working-tree file |
base + head, file changed in that range |
Diff, base ↔ head |
base + head, file added in that range |
Opens normally — nothing to compare against |
base + head, file unchanged in that range |
Opens normally. Set auditScope.plainWhenUnchanged: false to get an empty diff instead |
base + head, file deleted at head |
Opens the base version alone |
base, no head |
Diff, base ↔ working tree |
| File not in the working tree |
Falls back to its content at head, or at base |
Both sides of a diff are served read-only out of git, so the commit you review
does not have to be the one you have checked out. Open File (No Diff) in the
context menu always gives you the editable working-tree file.
Diff layout
Diffs open side by side by default. auditScope.diffLayout changes that:
| Value |
|
sideBySide (default) |
Two columns, and stop VS Code collapsing to inline in a narrow editor |
inline |
The single-column inline view |
editorDefault |
Leave diffEditor.* alone and use whatever you already have set |
The right-click menu has Open Diff: Side by Side and Open Diff: Inline,
which override the setting for one file. Unlike a click, they always diff — so
they also work on a file that would otherwise open plainly because it is new or
has no hunks.
VS Code has no per-diff layout option — vscode.diff takes only
TextDocumentShowOptions — so the layout is a global editor setting. Anything
other than editorDefault therefore writes diffEditor.renderSideBySide to
your user settings, and for side-by-side also
diffEditor.useInlineViewWhenSpaceIsLimited. Each key is written only when it
differs from what you have, and skipped entirely if your VS Code build does not
register it. Use editorDefault if you would rather the extension never touched
those settings.
That second key is why a side-by-side diff sometimes "will not stay" side by
side: with it at its default, VS Code collapses to inline whenever the editor is
narrower than diffEditor.renderSideBySideInlineBreakpoint (900px), which is
easy to hit with the sidebar open.
Progress
Ticking a box rewrites the - [ ] marker in the scope file itself, so progress
lives in git and everyone on the review sees it. Every other byte of the file is
left untouched. Set auditScope.persist to workspaceState to keep progress
local to your machine instead.
Ticking a group marks every file under it. The view header shows done/total
and the activity-bar badge shows how many files are left.
Settings
| Setting |
Default |
|
auditScope.glob |
**/SCOPE*.md |
Which files to load |
auditScope.exclude |
**/{node_modules,target,.git}/** |
Paths to skip |
auditScope.base |
"" |
Fallback base for files without frontmatter |
auditScope.head |
"" |
Fallback head for files without frontmatter |
auditScope.repo |
"" |
Fallback repo path for files without frontmatter |
auditScope.diffLayout |
sideBySide |
sideBySide, inline or editorDefault |
auditScope.persist |
scopeFile |
scopeFile or workspaceState |
auditScope.checkForUpdates |
true |
Check GitHub for a newer release at startup |
auditScope.showDiffStat |
true |
Show +added −removed beside each file |
auditScope.plainWhenUnchanged |
true |
Avoid empty diffs for files with no hunks |
Installing
The extension is distributed as a .vsix on the repository's Releases page.
gh release download --repo cre-mer/vscode-audit-scope --pattern '*.vsix' --clobber
code --install-extension audit-scope-*.vsix
After the first install it keeps itself current: shortly after startup it asks
GitHub whether a newer release exists and offers to install it. Audit Scope:
Check for Updates does the same on demand, and auditScope.checkForUpdates
turns the automatic check off.
That check shells out to the gh CLI rather than calling the API directly, so
it works while the repository is private. If gh is missing or logged out the
check stays quiet — it is a convenience, never a dependency.
A .vsix installed by hand is outside any marketplace, so VS Code will not
update it on its own. That is what the built-in check is for. If the
repository is ever made public, publishing to the Marketplace or Open VSX
would replace this with VS Code's native update mechanism.
Running from source
No build step — it is plain JavaScript with no dependencies. Open the folder
and press F5 for an Extension Development Host, or symlink it:
ln -s "$PWD" ~/.vscode-server/extensions/cre-mer.audit-scope-0.1.0
# or, for a local (non-remote) VS Code:
ln -s "$PWD" ~/.vscode/extensions/cre-mer.audit-scope-0.1.0
To build a .vsix yourself:
npx @vscode/vsce package --no-dependencies
Releases
Every push to main cuts one. CI runs the tests, bumps the version, tags it,
packages the .vsix and attaches it to a GitHub Release — which is where the
update check looks.
The bump is a patch by default. Put [minor] or [major] anywhere in the
commit message to bump further.
Tests
npm test # or: node test/parse.test.js && node test/hydrate.test.js
parse.test.js covers the parser, the checkbox rewriter, the open-decision
table and the git helpers. hydrate.test.js drives the tree provider itself
against a stubbed vscode module, covering repo-root resolution, checkbox
event handling and problem reporting.
Both are self-contained: they build throwaway git repositories in a temp
directory, so they depend on no particular project and need no editor.