feat: docs reference generates a human command reference under docs/reference/ from the command records, one page per group plus exit codes and gates; toc never lands inside another generated region (#188)
CI / verify (push) Successful in 6m11s
CI / pwsh (push) Successful in 2m0s
Release / release (push) Successful in 35s

Files changed:
- CHANGES.md
- README.md
- VERSION
- docs/reference/README.md
- docs/reference/commands/README.md
- docs/reference/commands/catalog-and-log.md
- docs/reference/commands/content-migrations.md
- docs/reference/commands/distribution-and-versioning.md
- docs/reference/commands/finding-and-checking.md
- docs/reference/commands/git.md
- docs/reference/commands/guideline-export.md
- docs/reference/commands/instance-health.md
- docs/reference/commands/links-and-citations.md
- docs/reference/commands/pages.md
- docs/reference/commands/provenance.md
- docs/reference/commands/raw-material-and-uploads.md
- docs/reference/commands/telemetry.md
- docs/reference/commands/types-instructions-and-docs.md
- docs/reference/commands/workshop-runs-and-session-budget.md
- docs/reference/exit-codes.md
- instructions/dev/doc-pull-through.md
- tools/CONTRACT.md
- tools/README.md
- tools/chemenu/cli.py
- tools/chemenu/cli_contract.py
- tools/chemenu/commands/docs_verify.py
- tools/chemenu/reference_doc.py
- tools/chemenu/tests/test_reference_doc.py
- tools/chemenu/toc.py

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SnAJ7Z3CpVD3PRbN73QtU2
This commit is contained in:
torbenandClaude Opus 5.5 committed 2026-10-06 21:29:01 +02:00
1 parent 01c888d3cd
commit 53383e7e9b
29 files changed
+5079 -29

No files matched your search

+532
View File
@@ -0,0 +1,532 @@
# Pages
Creating, updating, renaming, moving and removing wiki pages, and filing and closing items in the task tracker.
<!-- wikitool:toc -->
## Contents
- [`new`](#new)
- [`task new`](#task-new)
- [`task list`](#task-list)
- [`task close`](#task-close)
- [`touch`](#touch)
- [`rename`](#rename)
- [`rm`](#rm)
- [`move`](#move)
<!-- /wikitool:toc -->
<!-- wikitool:reference-commands -->
## `new`
Scaffold a new wiki page of any type.
**Synopsis**
- `wikitool new <type-name> --name "<Name>" [--type <path>] [--set field=value ...]` - Any type; its type-spec decides fields, directory, title prefix and template.
- `wikitool new entity --name "<Name>" --set entity_type=<t> [--set tags=a,b] [--set related=X,Y] [--set sources="Source - Z"] [--set provenance=sourced|general|mixed]` - Writes `kb/entities/<subdir>/<Name>.md` - `<subdir>` from `entity_type` via the type-spec's `layout:`
- `wikitool new concept --name "<Name>" --set concept_type=<t> ...` - Writes `kb/concepts/<subdir>/<Name>.md` - `<subdir>` from `concept_type` via the type-spec's `layout:`
- `wikitool new source --name "<Name>" --set source_type=<t> --set raw_files=raw/notes/x.md,raw/notes/y.md --set fidelity=<f> --set authority=<a> [--set source_url=<URL>] [--set entities=A,B] [--set concepts=C,D]` - Writes `kb/sources/<subdir>/Source - <Name>.md` (prefix added automatically; `<subdir>` from `source_type` via the type-spec's `layout:`) with a `raw_files:` list; rejects paths that don't exist
- `wikitool new comparison --name "X vs Y" --set entities=X,Y` - Writes `kb/comparisons/X vs Y.md`
- `wikitool new project --name "<Name>" --set responsibility=<bereich> [--resume]` - Writes `kb/gtd/<bereich>/<Name>.md` and, with a task tracker configured, a same-named tracker project
**Options**
```text
Arguments:
type_name Type name, e.g. entity|concept|source|comparison (see `wikitool
types list`) [required]
Options:
--name <str> Page title (a type's title_prefix is added automatically)
[required]
--type <str> Override the type-spec path (defaults to the one named by
TYPE_NAME)
--set <str> Frontmatter field, repeatable: --set entity_type=tool --set
tags=a,b. Array values split on commas (escape a literal one as
\,); repeating --set for an array field appends instead of
replacing
--resume `project` only: confirm a human has completed the manual tracker
step an earlier HumanInterventionRequired refusal asked for, so
this run continues to page creation instead of refusing the now-
existing tracker project as a collision.
-h, --help Show this message and exit.
```
**Examples**
```bash
tools/wikitool new entity --name "Docker" --set entity_type=tool --set tags=containers
tools/wikitool new source --name "Docker Cheatsheet" --set raw_files=raw/2026/09/docker-cheatsheet.md --set fidelity=verbatim --set authority=reporting
tools/wikitool new project --name "Homelab migration" --set responsibility=infrastruktur --resume # re-run after exit 42, once the user created the tracker project
```
**Behaviour**
- A title becomes a file name, so it must be valid and unique on Windows and macOS as well as Linux, whichever platform runs the command and whichever root the type writes to. The rule is `kb/CONTRACT.md` § Titles are identifiers; it is checked on the full title, after `title_prefix`.
- The target's path below the instance root may be at most 160 characters, counted in UTF-16 code units the way Windows counts MAX_PATH, so a Windows checkout without long paths keeps working. A longer one is refused, for every root, naming the length and how much shorter it has to get.
- `new` never overwrites: a file already at the target - or one a case-insensitive file system would treat as the same file - is refused for every root, `instructions/` included.
- The type-spec drives everything: fields, directory (`base_dir`/`layout`), title prefix, and template. `types list`/`types describe` show what a type requires.
- The body skeleton is `types/<type>.<value>.md` when that file exists, `<value>` being the page's subtype field value (e.g. `types/entity.person.md` for `entity_type=person`) - it replaces the type-spec's `## Template` block whole. Without such a file, and for a type with no subtype field, the `## Template` block is used as before.
- A schema `default:` is materialized only for a field the schema also lists in `required:`.
- `--set` is repeatable, and comma-separated values fill array fields. An element that itself contains a comma is written `\,`, or passed as its own repeated `--set` for that field - repeating an array field appends.
- A capture field the type-spec requires (a source's `fidelity`/`authority`) must be passed with `--set`; `new` never guesses it and refuses `unknown` for it.
- Produces structurally correct frontmatter and a body skeleton only - the prose (Description, Summary, judgment calls about relationships) is written afterwards.
- `new project`: with `.wikitool-tasks.json` configuring a task tracker, also makes sure a same-named tracker project exists - one name, one identity. No tracker configured is a legitimate, explicitly announced state: page only.
- `new project`: tracker before page. The tracker side is settled first, so a failure past that point leaves a tracker project with no page - a state `review`'s check 3 reports - never a page with no tracker project.
- `new project`: a name already taken, case-insensitively, in `kb/` or the tracker is refused outright, naming where it was found, and creates nothing. For `caldav` the tracker check covers every list in the account, not only the ones counted as projects.
- `new project`: a provider whose configured access path has no write path (Super Productivity's `access: "snapshot"`) refuses entirely with exit 1, naming the `access: "api"` instance to use instead - neither the tracker project nor the page is created, and `--resume` behaves the same.
- `new project`: a provider that could write but has no project-creation call of its own (Super Productivity's `access: "api"` - `GET /projects` exists, `POST /projects` does not) prints instructions for a human and exits 42, creating nothing. That is not one of the named gates, but the same exit code and the same handling. `caldav` never does this: `MKCALENDAR` creates the list, so a valid, non-colliding name always creates it.
- `--resume` is how a later run tells the command a human has done what that message asked: it re-verifies through the tracker's read path before continuing to page creation, rather than trusting the claim, and exits 42 again if the tracker still does not have the project. `--resume` on any other type is refused.
**Properties**
- Changes files: yes
- Idempotent: no
- Atomic: `new <type>`: Yes - single file write. `new project`: **No** for the tracker-configured case - a tracker-project write (or its human-clearance request) happens before the kb/ page write, so a failure between the two leaves a tracker project with no page (a state `review`'s check 3 already reports), never a page with no tracker project. Still a single file write when no tracker is configured
- Counts toward the session call budget: yes
- Can reach the network: no
- Gates: human-intervention-required (`new project` only) - see [exit codes and gates](../exit-codes.md)
**Exit codes**
- `0` - success
- `1` - A page with this title already exists, the type is unknown, or a `--set` value is invalid
- `1` - The title is not a valid file name (forbidden character, control character, reserved name such as `CON` or `Index`, trailing dot or space, empty), collides with another page by case or Unicode normalization, the target file already exists, or the target path is over the 160-character path budget
- `1` - A `raw_files` path does not exist
- `1` - A capture field the type-spec requires is missing, or set to `unknown`
- `1` - `--resume` with a type other than `project`
- `1` - new project: The name is already taken in the tracker (case-insensitively; for `caldav` against every list in the account)
- `1` - new project: The configured access path has no write path (Super Productivity's `access: "snapshot"`)
- `1` - new project: The page write failed after the tracker project was confirmed to exist
- `42` - new project: The provider cannot create the project itself (Super Productivity's `access: "api"`); the output says what a human has to create
**See also**
- `wikitool types describe <type>` - what a type requires and where it lands
- `wikitool touch` - changes a page's own frontmatter afterwards
- `wikitool task new` - a tracker item without a page
- `docs/explanation/knowledge-and-commitment.md` - why a project is a page and a tracker project
## `task new`
Create one open item in the configured task tracker - never a kb/ page.
**Synopsis**
- `wikitool task new --title "<Title>" (--project "<Name>" | --inbox) [--waiting [--follow-up-at YYYY-MM-DD]] [--notes "..."]`
**Options**
```text
--title <str> The item's title. Stored verbatim, never parsed.
[required]
--project <str> An existing tracker project's name (matched case-
insensitively). This command never searches or guesses
one and never creates one - use `wikitool new project`
first if it does not exist yet. Exactly one of
--project/--inbox is required.
--inbox File into the tracker's own inbox instead of a project -
the deliberately chosen exit when no project fits, never
a stand-in for an omitted --project. An item filed here
is invisible to `wikitool review`, since every check
there is reached through a project name and the inbox
has none.
--waiting Tag the item WAITING - the review's check 2 reads this.
--follow-up-at <str> YYYY-MM-DD. Only meaningful together with --waiting - it
is never a due date and is refused without --waiting.
--notes <str> A freetext backref, e.g. to the kb/ source page this
item came from. Stored verbatim, never parsed.
-h, --help Show this message and exit.
```
**Examples**
```bash
tools/wikitool task new --title "Renew the TLS certificate" --project "Homelab migration"
tools/wikitool task new --title "Quote from the electrician" --project "Homelab migration" --waiting --follow-up-at 2026-10-05
tools/wikitool task new --title "Read the qmd README" --inbox --notes "from [[Source - qmd - GitHub Repository]]"
```
**Behaviour**
- Creates one open item in the configured task tracker; never touches `kb/`.
- Exactly one of `--project` or `--inbox` is required; an omitted `--project` refuses rather than silently falling into the inbox.
- `--project` names an existing tracker project, matched case-insensitively - never created, and never searched or guessed.
- `--inbox` files into the tracker's own inbox. An item filed there never appears in `review`, since every one of its checks reaches items through a project name.
- `--waiting` sets the WAITING status `review`'s waiting-overdue check reads. `--follow-up-at` is refused without `--waiting` - it is never a due date on its own.
- `--notes` carries a freetext backref (e.g. to the `kb/` source page the item came from), stored verbatim, never parsed.
- The tracker configuration is read from `.wikitool-tasks.json`, or from the file `WIKITOOL_TASKS_CONFIG` names when that variable is set (so one checkout can be run against several trackers in turn). A set variable that names no file is an error, never "no tracker configured".
- No `.wikitool-tasks.json` fails immediately with a "no tracker configured" message.
- A provider whose configured access path has no write path (Super Productivity's `access: "snapshot"`) refuses entirely with exit 1, naming the `access: "api"` instance to use instead.
- **Never exits 42.** A `--project` matching no tracker project, or `--waiting` against a provider that cannot represent it right now (Super Productivity: the `waiting` tag does not exist yet, and its API cannot create tags), are ordinary exit-1 refusals that create nothing.
- Not idempotent: every successful run creates another item.
**Properties**
- Changes files: yes
- Idempotent: no
- Atomic: Yes - a single API call, made only once every precondition (the project's own id, the WAITING tag's own id) is confirmed to exist, so a missing one never leaves a half-written item behind
- Counts toward the session call budget: yes
- Can reach the network: yes
**Exit codes**
- `0` - success
- `1` - No `.wikitool-tasks.json` - no tracker configured
- `1` - `WIKITOOL_TASKS_CONFIG` names a file that does not exist or is broken
- `1` - Neither or both of `--project`/`--inbox`, or a `--follow-up-at` without `--waiting` or not `YYYY-MM-DD`
- `1` - A `--project` name matching no tracker project
- `1` - `--waiting` against a provider with no way to represent it right now (Super Productivity: the `waiting` tag does not exist)
- `1` - A read-only access path (Super Productivity's `access: "snapshot"`)
**See also**
- `wikitool task list` - a project's open items and their ids
- `wikitool task close` - marks an item done
- `wikitool new project` - a project page and its tracker project
- `docs/explanation/knowledge-and-commitment.md` - why commitments live in the tracker, not in `kb/`
## `task list`
List a project's open items - id, title, and whether each carries the WAITING status.
**Synopsis**
- `wikitool task list --project "<Name>"`
**Options**
```text
--project <str> An existing tracker project's name (matched case-
insensitively). [required]
-h, --help Show this message and exit.
```
**Examples**
```bash
tools/wikitool task list --project "Homelab migration"
```
**Behaviour**
- Lists one tracker project's open items: id, title, and whether each carries the WAITING status.
- The id source `task close` and `review`'s `waiting_overdue`/`someday_stale` findings need, without running `review` first.
- Works on every access path a provider offers, read-only ones included.
- A `--project` matching no tracker project prints "No open items": the tracker read does not distinguish an empty project from an unknown one.
- Read-only.
**Properties**
- Changes files: no
- Idempotent: yes
- Atomic: Yes - read-only, nothing to leave half-written
- Counts toward the session call budget: yes
- Can reach the network: yes
**Exit codes**
- `0` - success
- `0` - A `--project` matching no tracker project - prints "No open items", not an error
- `1` - No `.wikitool-tasks.json` - no tracker configured
- `1` - `WIKITOOL_TASKS_CONFIG` names a file that does not exist or is broken
**See also**
- `wikitool task close` - closes an item by the id listed here
- `wikitool review` - the findings that name items
## `task close`
Mark one tracker item done - never delete it.
**Synopsis**
- `wikitool task close --id <item-id>`
**Options**
```text
--id <str> The tracker's own item id, e.g. from `task list` or `wikitool
review`'s waiting_overdue/someday_stale findings - never a title.
[required]
-h, --help Show this message and exit.
```
**Examples**
```bash
tools/wikitool task close --id <item-id>
```
**Behaviour**
- Marks one tracker item done. It never deletes or moves an item - the only closing write this stack makes.
- `--id` is the provider's own item id, from `task list` or a `review` finding - never a title.
- The tracker configuration is read from `.wikitool-tasks.json`, or from the file `WIKITOOL_TASKS_CONFIG` names when that variable is set (so one checkout can be run against several trackers in turn). A set variable that names no file is an error, never "no tracker configured".
- No `.wikitool-tasks.json` fails with a "no tracker configured" message.
- A provider whose configured access path has no write path (Super Productivity's `access: "snapshot"`) refuses entirely with exit 1, naming the `access: "api"` instance to use instead.
- **Never exits 42.**
**Properties**
- Changes files: yes
- Idempotent: yes
- Atomic: Yes - a single API call; an unknown id is rejected by the provider itself (Super Productivity: `404 TASK_NOT_FOUND`) before anything is written
- Counts toward the session call budget: yes
- Can reach the network: yes
**Exit codes**
- `0` - success
- `1` - No `.wikitool-tasks.json` - no tracker configured
- `1` - `WIKITOOL_TASKS_CONFIG` names a file that does not exist or is broken
- `1` - An `--id` matching no tracker item right now
- `1` - A read-only access path (Super Productivity's `access: "snapshot"`)
**See also**
- `wikitool task list` - where the id comes from
- `wikitool review` - findings that carry item ids
## `touch`
Bump a page's `modified:` date and optionally rewrite its other frontmatter fields.
**Synopsis**
- `wikitool touch --page "<Title>" [--summary "..."] [--provenance <v>] [--date YYYY-MM-DD] [--set field=value ...] [--add field=value ...] [--remove field=value ...] [--no-date] [--dry-run]`
**Options**
```text
--page <str> Exact page title, e.g. 'Docker Cheatsheet' [required]
--summary <str> Replace the page's 1-line summary
--provenance <str> Replace the page's provenance marker
(sourced|general|mixed)
--date <str> Date to record (YYYY-MM-DD). `modified:` defaults to
today; a source's `date:` is its publication date and
changes only when given here.
--set <str> Replace a frontmatter field, repeatable: --set tags=a,b.
Array values split on commas (escape a literal one as \,);
repeating --set for one array field appends within this
call. Page-reference fields belong to `xref`, not here
--add <str> Append elements to an array field without naming the whole
list: --add tags=x. Elements already present are left
alone
--remove <str> Drop elements from an array field: --remove tags=x.
Removing an absent element succeeds and says so
--no-date Only change the given fields; leave the modified/date
field alone
--dry-run Preview the new frontmatter instead of writing
-h, --help Show this message and exit.
```
**Examples**
```bash
tools/wikitool touch --page "Docker" --summary "Container runtime and image format"
tools/wikitool touch --page "Docker" --add tags=containers --no-date
tools/wikitool touch --page "Source - Docker Cheatsheet" --date 2026-09-01 --dry-run
```
**Behaviour**
- Bumps `modified:` to today and optionally rewrites any other field the page's type declares.
- `--summary`/`--provenance` are shorthands; `--set` reaches every other field and **replaces** its value, while `--add`/`--remove` change single elements of an array field (removing an absent element succeeds and says so).
- Repeating `--set` for one array field appends *within the call*, and `\,` is a literal comma.
- Refused, naming the command that owns them instead: `type:` (the page-lifecycle procedure) and the page-ref arrays `related:`/`sources:`/`entities:`/`concepts:` (`xref`). Everything else the schema declares is settable, and an unknown field is refused with the list of fields the page actually has.
- Schema-validates the fields it writes; `raw_files:` entries must exist on disk.
- A source page declares `date:` instead of `modified:`: the *publication* date of the raw material. It is never bumped to today and changes only when `--date` names a value explicitly.
- `--no-date` changes only the given fields and leaves the date alone; `--dry-run` previews the new frontmatter without writing.
- Safe to re-run as-is: `--set` and `--add` are idempotent, and `--remove` of an already-absent element succeeds while reporting it.
**Properties**
- Changes files: yes
- Idempotent: yes
- Atomic: Yes - single file write, and every refusal happens before it
- Counts toward the session call budget: yes
- Can reach the network: no
**Exit codes**
- `0` - success
- `1` - Page not found
- `1` - An invalid value for a field it writes, or a `raw_files:` path that doesn't exist
- `1` - A field owned by another command (`type:`, a page-ref array) or absent from the type's schema
- `1` - `--add`/`--remove` on a non-array field
**See also**
- `wikitool xref add` / `wikitool xref remove` - the page-ref arrays
- `instructions/page-lifecycle.md` - changing a page's `type:`
## `rename`
Rename a page, or repoint references that name a page that never existed.
**Synopsis**
- `wikitool rename --from "<Old>" --to "<New>" [--dry-run]`
**Options**
```text
--from <str> Current page title, exactly as it appears [required]
--to <str> New page title [required]
--dry-run List what would change instead of writing
-h, --help Show this message and exit.
```
**Examples**
```bash
tools/wikitool rename --from "act_runner" --to "Act Runner" --dry-run
tools/wikitool rename --from "Docker Engine" --to "Docker"
```
**Behaviour**
- Renames a page and repoints every reference to it: body `[[wikilinks]]` (aliases and anchors preserved), a `[^cite-id]` whose id was derived from the old title (refreshed to match the new one, both in its Footnotes definition and every reference to it), the page's own H1, and every page-ref frontmatter array declared by the type's `page_ref_fields:`.
- If `--from` is *not* a page but is referenced, it instead repoints those references onto the existing `--to` page and moves nothing - the fix for a reference spelled `act_runner` when the page is `Act Runner`.
- Each page's rewrite is idempotent, so a re-run as-is is safe. If a write fails midway, nothing is renamed on disk and the error lists what was updated.
- `--dry-run` lists every page it would change; run it first to see the blast radius.
- Only `--to` is checked against the title rule and the path budget (160 UTF-16 code units for the whole path below the instance root). A page whose current title breaks either (`lint`'s Unportable Titles and Long Paths) can always be renamed away from it, and a title that differs from the page's own only by case (`Foo` to `FOO`) is allowed.
**Properties**
- Changes files: yes
- Idempotent: yes
- Atomic: No - one write per referencing page, then the file move
- Counts toward the session call budget: yes
- Can reach the network: no
**Exit codes**
- `0` - success
- `1` - `--from` equals `--to`
- `1` - Neither `--from` nor `--to` is a page
- `1` - The `--to` title is already taken - also by a page that differs only in case or Unicode normalization, or by a file in the page's directory - or is not a valid file name, or would put the page's path over the path budget (see `kb/CONTRACT.md` § Titles are identifiers)
- `1` - A page write failed partway; nothing was renamed on disk
**See also**
- `instructions/page-lifecycle.md` - renaming, moving and deleting a page
- `wikitool move` - changes a page's directory, not its title
- `wikitool rm` - deletes a page
## `rm`
Delete a page and mechanically de-link it from the rest of the wiki.
**Synopsis**
- `wikitool rm --page "<Title>" [--yes] [--dry-run]`
**Options**
```text
--page <str> Exact title of the page to delete [required]
-y, --yes Confirm deletion of a page that other pages still reference.
Only pass this after a human has reviewed the inbound list -
never set it automatically.
--dry-run List what would change instead of writing
-h, --help Show this message and exit.
```
**Examples**
```bash
tools/wikitool rm --page "Old Draft" --dry-run
tools/wikitool rm --page "Old Draft" --yes # after the user approved the inbound list
```
**Behaviour**
- Deletes a page and de-links it from the rest of the wiki: strips page-ref array entries and bare `- [[Title]]` / `- **label:** [[Title]]` bullets pointing at it.
- Leaves prose references and inline citations in place and reports them afterwards; those are an editorial fix, not a reason to retry.
- Refuses without `--yes` while other pages still reference it, listing them.
- If a de-link write fails midway, the page is not deleted, so nothing is orphaned and a re-run is safe.
- `--dry-run` lists what would change, without writing.
- Not idempotent: once the page is gone, a second run finds nothing to delete.
**Properties**
- Changes files: yes
- Idempotent: no
- Atomic: No - one write per referencing page, then the delete
- Counts toward the session call budget: yes
- Can reach the network: no
**Exit codes**
- `0` - success
- `1` - Page not found
- `1` - Other pages still reference it and `--yes` was not passed
- `1` - A de-link write failed partway; the page was not deleted
**See also**
- `instructions/page-lifecycle.md` - when a page is deleted rather than renamed
- `wikitool rename` - repoints references instead of removing them
## `move`
Move a page (or every misplaced page) to the directory its type-spec computes.
**Synopsis**
- `wikitool move --page "<Title>"`
- `wikitool move --reconcile [--dry-run]`
**Options**
```text
--page <str> Exact title of the page to move to its computed location
--reconcile Move every page under kb/ that is not at its computed location
--dry-run List what would move without writing
-h, --help Show this message and exit.
```
**Examples**
```bash
tools/wikitool move --page "Docker"
tools/wikitool move --reconcile --dry-run
tools/wikitool move --reconcile
```
**Behaviour**
- Moves a page to the directory its type-spec computes for its current frontmatter (`base_dir` + `layout`, the same rule `new` places a page by) - never to a hand-chosen destination; there is no `--to <dir>`.
- A destination whose path would be over the path budget (160 UTF-16 code units below the instance root) is refused, and `--reconcile` skips such a page and names it, as it does for an occupied destination - `wikitool rename` the page to a shorter title.
- `--reconcile` applies it corpus-wide: every misplaced page moves in one call, and a second run reports nothing left to do. It fixes `lint`'s `Misplaced Pages` (advisory) and `Nested Pages` (hard) findings.
- Neither mode touches a body or a frontmatter field, and the page's title - its only identity in the wiki - never changes; only the file moves.
- A directory a move empties is removed with it, so a page nested below its area leaves no leftover directory behind.
- A page already at its computed location is reported and left alone, and `--reconcile` only re-moves what is still misplaced, so a re-run is safe.
- `--dry-run` (with `--reconcile`) lists the moves; run it first to see the blast radius.
- Run `wikitool index rebuild` afterwards.
**Properties**
- Changes files: yes
- Idempotent: yes
- Atomic: `--page`: yes, a single file move. `--reconcile`: no - one file move per page, each idempotent
- Counts toward the session call budget: yes
- Can reach the network: no
**Exit codes**
- `0` - success
- `1` - Neither or both of `--page`/`--reconcile` given
- `1` - The named page is not found, or has no `type:` to compute a placement from
- `1` - The destination already holds an entry with the same name, or one that differs only in case or Unicode normalization (a pre-existing duplicate-stem collision), or its path would be over the path budget - refused rather than silently skipped
- `1` - `--reconcile` failed partway
**See also**
- `wikitool lint` - reports Misplaced and Nested Pages
- `wikitool index rebuild` - run after moving
- `instructions/page-lifecycle.md` - moving, renaming and deleting a page
<!-- /wikitool:reference-commands -->