ADR-012: CLI owns source mutation; the extension stays read-only
Status: accepted
Deciders: Richard Attermeyer
Date: 2026-08-23
Context and Problem Statement
The supersession lifecycle needs to change source files: archive moves a superseded item’s block to a parallel superseded.adoc page, and remove deletes an orphaned or isolated block.
Two places could own this mutation: the Antora extension (which already parses items during the build) or the CLI (which the author invokes explicitly).
The extension carries a hard requirement that it SHALL NOT modify .adoc source files on disk — its passes operate on in-memory buffers and never write back.
An extension pass that relocates blocks during the build would break that guarantee and surprise authors with silent file changes mid-build.
Decision Drivers
-
Source mutation must be an explicit, author-invoked action, never a build side effect
-
The extension’s read-only guarantee must hold
-
Git history, not the tool, is the safety net for deletion
Considered Options
-
Extension pass that auto-archives superseded items during
contentClassified— rejected: violates the read-only guarantee and mutates files mid-build with no preview -
CLI commands (
archive,remove) that mutate source on explicit invocation — chosen -
No automation, hand-edited moves — rejected: error-prone, with no guard that only superseded items are touched
Decision Outcome
Chosen option: source mutation lives in the CLI only.
archive <ID> and remove <ID> parse the graph, locate the item’s full block (header through the closing delimiter), and mutate the file only after validation — superseded for archive, orphaned or isolated for remove — and, for removal, explicit confirmation.
Block-extent detection refuses ambiguous edits.
The extension remains read-only on source files; every future mutation feature (prune, relink, rename) belongs in the CLI.
Positive Consequences
-
The extension’s read-only guarantee is preserved — builds can never alter source
-
Mutation is intentional and previewable;
removeshows the block and requires confirmation -
Guards make unsafe edits impossible:
archiverejects non-superseded IDs,removerejects non-orphaned/non-isolated IDs