Keeping blocks, regions, and metadata consistent
April 25, 2026 · View on GitHub
Commentray ties three surfaces together. If they drift apart, validation fails, scroll sync misaligns, or commentary points at the wrong lines. This guide is the operational contract: what must match, how to check it, and what to do when it breaks.
The three surfaces (and what each owns)
| Surface | Location | What you must keep aligned |
|---|---|---|
| A. Index | .commentray/metadata/index.json | Per companion file: sourcePath, commentrayPath, and each block’s id, anchor, optional snippet / markerId / verification fields. |
| B. Markdown | .commentray/source/…/*.md (or per-angle paths) | For each block: a line <!-- commentray:block id=<id> --> with the same id as the index, then prose below it. |
| C. Primary file | Repo source (e.g. src/foo.ts) | Depends on anchor type (see below): either line numbers implied by lines:… or explicit region comments for marker:…. |
Rule of thumb: the index block.id and the Markdown marker id must always be identical strings. The anchor in the index describes how to find the span in C; it does not replace B.
Anchor types: maintenance cost vs drift resistance
lines:<start>-<end> (line range)
- Pros: No comments in source; good for generated or policy-locked files.
- Cons: Editing the file moves lines;
anchorand optionalsnippetin the index can become wrong until you update them (or run tooling that refreshes them). - Consistency: After refactors, re-check ranges. Use
commentray validate; fixanchor(and snippet if you use it) so they still describe the intended span.
marker:<id> (named region in source)
- Pros: Tools resolve the span from paired delimiters in the source (
//#region commentray:<id>…//#endregion, orcommentray:start id=<id>/commentray:endwhere regions are not idiomatic). Renumbering lines inside the region does not break the link. - Cons: Markers live in the primary file; reviewers must accept them.
markerIdin the index (when present) must stay consistent withmarker:resolution rules (see anchors.md). - Consistency: Never rename a region id in source without updating
marker:/markerIdand the Markdownid=and indexidto the same new token. Usecommentray convert-source-markersif you change language/comment style.
See Source region delimiters (by editor language) for a table of delimiter shapes by VS Code languageId, and blocks.md — Source markers for the normative narrative.
Single checklist: “is this block still coherent?”
For each block, all of the following must hold:
- Index
blocks[].idequals the Markdown<!-- commentray:block id=… -->id (same string). - Index
entry.sourcePathandentry.commentrayPathmatch the files you think you paired; the JSON object key must equalcommentrayPath. anchorparses (see anchors.md).- If
marker:anchor: source contains a well-formed pair for that id;commentray validatemust not report marker pairing errors for that file. - If
lines:anchor:start–endare within the file and describe the intended lines; update after line insert/delete if the commentary should move with different lines. - Optional
snippet: records trimmed source lines forlines:anchors; update when you intentionally change the anchored span (see blocks.md — “Drift and snippets”).
Commands and when to run them
Run these from the repository root (or ensure commentray resolves paths the same way your workspace does).
| Command | Purpose |
|---|---|
commentray init | Ensures dirs + index.json, creates .commentray.toml if missing, runs migrations/normalization, merges d-led.commentray-vscode into .vscode/extensions.json when that file is valid mergeable JSON, then validate. Safe to repeat. |
commentray validate | Schema, index keys, marker pairing, marker uniqueness across files, marker/source alignment. When a primary file is missing, also prints relocation hints (Git HEAD~1→HEAD renames, marker matches in other indexed files, and a bounded scan of other Git-tracked source files for the same heuristics). Use in CI (exit 1 on errors). |
commentray doctor | validate plus environment hints (e.g. missing .git). |
commentray migrate | Rewrites index.json when schema or snippet normalization changes (also applied automatically on read in many tools). |
commentray sync-moved-paths | After Git renames/moves, rewrites sourcePath / commentrayPath in the index using git diff rename detection. Does not fix anchors inside files—you still need to adjust lines: or regions if logic moved. |
commentray convert-source-markers --file <path> --language <id> | Rewrites source region delimiter style to match a VS Code language id (dry-run first if unsure). |
Editor: “Commentray: Validate workspace metadata” runs the same validation as the CLI and prints issues to the output channel.
Git hook: commentray init scm installs a pre-commit fragment that runs commentray validate when the CLI is on PATH. That catches index/markdown/source mistakes before they land on main.
Workflows after common edits
You moved or renamed a source or commentray file (Git)
commentray sync-moved-paths(optionally--dry-runfirst) to fix index paths.commentray validate— fix any remaining path or anchor issues.
The index still references a primary that no longer exists
Validate reports a missing primary and relocation hints: Git renames in the last commit, marker: / snippet: matches in other indexed files, and (when this is a Git checkout) a bounded scan of other tracked source files. Use those messages to pick the right sourcePath, then run sync-moved-paths if Git renamed the file, or edit index.json when the move was copy-based or outside Git’s rename detection.
You edited line numbers only (lines: anchors)
- Open the source; decide the new first/last line of the documented span.
- Update
anchorinindex.jsonfor that block (andsnippetif you rely on drift tooling). - Optionally adjust the Markdown heading text for humans—it is not authoritative for the span.
commentray validate.
You renamed a marker: id or merged regions
- Update source delimiters, index
anchor/markerId, Markdown markerid=, and indexidso they all use the same new id. commentray convert-source-markersif only the comment syntax changed.commentray validate.
You added a new block
- Add
<!-- commentray:block id=newid -->in the Markdown (new id must satisfy anchors.md id rules). - Append a
blocks[]entry with the sameid, correctanchor, and matchingsourcePath/ file key underbyCommentrayPath. commentray validate.
Using the VS Code command “Add block from selection” creates the marker, index entry, and opens the pair—prefer that for fewer copy-paste mistakes.
You deleted a block
- Remove the Markdown section (including its
<!-- commentray:block … -->line). - Remove the
blocks[]entry (and remove source region markers ifmarker:was used). commentray validate.
Staleness metadata (lastVerifiedCommit / lastVerifiedBlob)
These fields are optional signals for “a human checked this block against Git.” They do not auto-fix anchors. When you complete a review:
- Set
lastVerifiedCommitto the full SHA ofHEAD(or the commit you verified against). - Set
lastVerifiedBlobwhen you want the tool to compare the current blob ofsourcePathatHEAD.
If you do not use them, leave them unset; validation will not treat that as an error.
When metadata feels “not tenable”
If maintaining lines: ranges after every edit is painful:
- Prefer
marker:anchors + regions in source for the hot spots, or - Keep
lines:but runcommentray validatein pre-commit and CI so mistakes are caught immediately, or - Use the VS Code flow to add blocks and validate from the editor.
Commentray does not silently rewrite your primary source to match stale lines: anchors—that is intentional. The tenable path is: pick an anchor strategy that matches your team’s tolerance for source markers vs line churn, then automate validation so inconsistency never accumulates.
Canonical spec links
- blocks.md — block model, Markdown markers, markers, drift, staleness.
- anchors.md —
lines:,marker:,symbol:grammar and validation rules. - storage.md — paths, Angles, where files live.