tools: command records, Content migrations group - one line per cause, examples, prohibitions (#142)
Files changed: - CHANGES.md - VERSION - tools/CONTRACT.md - tools/chemenu/commands/migrate_cmd.py
This commit is contained in:
1 parent
71efdbe01b
commit
243db66134
4 files changed
+261
-79
No files matched your search
+11
-1
@@ -59,7 +59,7 @@ concern - readable here, never shipped as something to parse.
|
||||
|
||||
---
|
||||
|
||||
## 7.1.0-beta.17 - 2026-09-26 - Command records, Telemetry group: examples, the missing --fail-on-error exit line
|
||||
## 7.1.0-beta.18 - 2026-09-26 - Command records, Content migrations group: one line per cause, examples, prohibitions
|
||||
|
||||
**Author:** Torben Nehmer
|
||||
|
||||
@@ -86,6 +86,7 @@ concern - readable here, never shipped as something to parse.
|
||||
- Command records, Workshop runs and session budget group: examples, prohibitions
|
||||
- Command records, Types, instructions and docs group: one line per cause, examples, prohibitions
|
||||
- Command records, Telemetry group: examples, the missing --fail-on-error exit line
|
||||
- Command records, Content migrations group: one line per cause, examples, prohibitions
|
||||
<!-- /wikitool:bumps -->
|
||||
|
||||
### CalDAV task-tracker provider (Nextcloud Tasks, iOS Reminders); review reports unknown-value findings instead of skipping them
|
||||
@@ -306,6 +307,15 @@ always done. The reasoning `docs toc`'s record carried about its scope already l
|
||||
has always exited 1 on a failed scorecard, but its record only listed the missing-trace case; it
|
||||
now names both.
|
||||
|
||||
### Command records, Content migrations group: one line per cause, examples, prohibitions
|
||||
|
||||
The five `migrate` commands rewritten the same way; text only. `migrate done` and
|
||||
`migrate baseline` state as NEVER what their prose implied - never force the chain's order,
|
||||
never advance the version with `baseline --force` or by editing `.wikitool-kb.json` - and
|
||||
`migrate verify` separates a bad `--from` revision from the findings it exits 1 on. The reasoning
|
||||
behind counting marker pairs rather than comparing their names, and behind an offered migration
|
||||
ignoring the chain, moved into the `verify` and `done` docstrings.
|
||||
|
||||
---
|
||||
|
||||
## 7.0.0 - 2026-09-22 - Task-Tracker-Anbindung: Vorhaben als Seitenart, Verpflichtungsschicht, Weekly Review als Read-Time-Join
|
||||
|
||||
+100
-13
@@ -2810,13 +2810,23 @@ List every migration document under `instructions/migrations/`.
|
||||
- budget: exempt
|
||||
- network: no
|
||||
|
||||
**EXAMPLES**
|
||||
|
||||
- `tools/wikitool migrate list`
|
||||
|
||||
**EXIT STATUS**
|
||||
|
||||
- 0 success
|
||||
|
||||
**NOTES**
|
||||
|
||||
Oldest target first, with its kind and obligation. Read-only and **exempt from the Iteration Budget Gate**. Never fails.
|
||||
- Lists every migration document under `instructions/migrations/`, oldest target first, with its kind and obligation.
|
||||
- Never fails. Read-only and **exempt from the Iteration Budget Gate**.
|
||||
|
||||
**SEE ALSO**
|
||||
|
||||
- `wikitool migrate status` - which of them this instance still owes
|
||||
- `instructions/migrate-corpus.md` - how a migration is run
|
||||
|
||||
#### `migrate status`
|
||||
|
||||
@@ -2834,18 +2844,35 @@ Show the migrations this instance still owes, in the order they must run.
|
||||
- budget: exempt
|
||||
- network: no
|
||||
|
||||
**EXAMPLES**
|
||||
|
||||
- `tools/wikitool migrate status`
|
||||
- `tools/wikitool migrate status --json`
|
||||
|
||||
**EXIT STATUS**
|
||||
|
||||
- 0 success
|
||||
- 1 `.wikitool-kb.json` is missing (content version undeclared), or `VERSION` is unreadable
|
||||
- 1 `.wikitool-kb.json` is missing - the content version is undeclared
|
||||
- 1 `VERSION` is unreadable
|
||||
|
||||
**ON FAILURE**
|
||||
|
||||
- `.wikitool-kb.json` is missing (content version undeclared), or `VERSION` is unreadable -> For a missing declaration: run `migrate baseline <version>` once, then retry. Safe to retry freely otherwise
|
||||
- `.wikitool-kb.json` is missing - the content version is undeclared -> Run `migrate baseline <version>` once, then retry
|
||||
- `VERSION` is unreadable -> Fix `VERSION`, then retry
|
||||
|
||||
**NOTES**
|
||||
|
||||
Every **required** document whose `migrates_to` lies in `(kb_version, VERSION]`. `offered` documents are listed separately above the chain and never block, never count as owed, and are bounded by the applied ledger rather than by `kb_version` - taking one deliberately does not move the version, so the version cannot say whether it was taken. When a release stamp is present, also reports which shipped files this instance has since edited (from the per-file sha256 in `.wikitool-release.json`), which is what says whether an offer may be copied over or has to be reconciled by hand; without a stamp that question is reported as unanswerable rather than answered. Exits 1 only when `.wikitool-kb.json` is missing - the content's shape is a question the tool refuses to answer by guessing. Read-only and exempt from the budget gate
|
||||
- Shows every **required** migration whose `migrates_to` lies in `(kb_version, VERSION]`, in the order it must run.
|
||||
- `offered` migrations are listed separately above the chain: they never block, never count as owed, and are bounded by the applied ledger rather than by `kb_version` - taking one does not move the version.
|
||||
- With a release stamp present, also reports which shipped files this instance has since edited (from the per-file sha256 in `.wikitool-release.json`) - which says whether an offer may be copied over or has to be reconciled by hand. Without a stamp that question is reported as unanswerable rather than answered.
|
||||
- Exits 1 only when the content version is undeclared (`.wikitool-kb.json` missing) or `VERSION` is unreadable; it never guesses the content's shape.
|
||||
- Read-only, safe to retry freely, and exempt from the Iteration Budget Gate.
|
||||
|
||||
**SEE ALSO**
|
||||
|
||||
- `wikitool migrate done` - records one as applied
|
||||
- `instructions/migrate-corpus.md` - how a migration is run
|
||||
- `instructions/upgrade-instance.md` - where an upgrade checks this
|
||||
|
||||
#### `migrate verify`
|
||||
|
||||
@@ -2863,18 +2890,40 @@ Compare `kb/` against a git revision on the invariants a content migration must
|
||||
- budget: exempt
|
||||
- network: no
|
||||
|
||||
**EXAMPLES**
|
||||
|
||||
- `tools/wikitool migrate verify --from HEAD`
|
||||
- `tools/wikitool migrate verify --from HEAD --path kb/concepts --expect-body-change`
|
||||
|
||||
**EXIT STATUS**
|
||||
|
||||
- 0 success
|
||||
- 1 Only with `--fail-on-error`: an invariant changed. Also exits 1 if `--from` is not a revision in this repository
|
||||
- 1 Only with `--fail-on-error`: an invariant changed
|
||||
- 1 `--from` is not a revision in this repository
|
||||
|
||||
**ON FAILURE**
|
||||
|
||||
- Only with `--fail-on-error`: an invariant changed. Also exits 1 if `--from` is not a revision in this repository -> Exit 1 from `--fail-on-error` means "act on the findings", not "the tool is broken". A finding is never fixed by re-running - it names a page and what changed on it
|
||||
- Only with `--fail-on-error`: an invariant changed -> Act on the findings - exit 1 here means "act on the findings", not "the tool is broken". A finding names a page and what changed on it; it is never fixed by re-running
|
||||
- `--from` is not a revision in this repository -> Fix the revision and retry
|
||||
|
||||
**NEVER**
|
||||
|
||||
- Never re-run to make a finding go away - fix the page it names.
|
||||
|
||||
**NOTES**
|
||||
|
||||
Wikilink and citation **counts** (not sets), footnote definitions, H1, structural frontmatter, and the **count of generated-region marker pairs** - a page that went from one links region to two has the same set of region names and a different count, and a lost marker turns a generated region into prose the next write appends a second one beside. Pages are matched by **title**, not path, so a page `wikitool move` (or `move --reconcile`) relocated compares as itself - reported separately as `moved` - rather than as a removed-and-added pair. Reports added/removed pages without failing on them. `--expect-body-change` additionally flags a page whose body did not change at all. Not migration-specific - worth running after any bulk rewrite, and the one question `lint` cannot answer, since it reads a single revision and so cannot see that something went missing. Read-only and exempt from the budget gate
|
||||
- Compares `kb/` against the revision `--from` on the invariants a content migration must not change: wikilink and citation **counts** (not sets), footnote definitions, H1, structural frontmatter, and the **count of generated-region marker pairs**.
|
||||
- Pages are matched by **title**, not path, so a page `move` (or `move --reconcile`) relocated compares as itself - reported separately as `moved` - rather than as a removed-and-added pair.
|
||||
- Reports added and removed pages without failing on them.
|
||||
- `--expect-body-change` additionally flags a page whose body did not change at all.
|
||||
- Not migration-specific: worth running after any bulk rewrite.
|
||||
- Exits 0 whatever it finds unless `--fail-on-error` is passed.
|
||||
- Read-only and exempt from the Iteration Budget Gate.
|
||||
|
||||
**SEE ALSO**
|
||||
|
||||
- `instructions/migrate-corpus.md` - where a migration runs this
|
||||
- `wikitool lint` - the single-revision checks
|
||||
|
||||
#### `migrate done`
|
||||
|
||||
@@ -2892,18 +2941,39 @@ Record one migration as applied, advancing `kb_version` in `.wikitool-kb.json`.
|
||||
- budget: counted
|
||||
- network: no
|
||||
|
||||
**EXAMPLES**
|
||||
|
||||
- `tools/wikitool migrate done 7.0.0 --pages 42 --dry-run`
|
||||
- `tools/wikitool migrate done 7.0.0 --pages 42`
|
||||
|
||||
**EXIT STATUS**
|
||||
|
||||
- 0 success
|
||||
- 1 Unknown version, no `.wikitool-kb.json`, nothing outstanding, or a *required* version that is not the next link in the chain
|
||||
- 1 Unknown version, no `.wikitool-kb.json`, or nothing outstanding
|
||||
- 1 A *required* version that is not the next link in the chain
|
||||
|
||||
**ON FAILURE**
|
||||
|
||||
- Unknown version, no `.wikitool-kb.json`, nothing outstanding, or a *required* version that is not the next link in the chain -> **Not idempotent** for a required migration: it advances the chain. For "not the next link", run `migrate status` and apply them in the order it prints - never force the order. Recording an `offered` migration *is* idempotent and safe to repeat
|
||||
- Unknown version, no `.wikitool-kb.json`, or nothing outstanding -> Check `migrate status`, fix the argument, then retry once
|
||||
- A *required* version that is not the next link in the chain -> Run `migrate status` and apply the migrations in the order it prints
|
||||
|
||||
**NEVER**
|
||||
|
||||
- Never force the order of required migrations.
|
||||
- Never hand-edit `.wikitool-kb.json` to advance the version.
|
||||
|
||||
**NOTES**
|
||||
|
||||
**Refuses any version that is not the next link in the chain** - skipping one leaves the corpus in a shape no version describes, and an interrupted multi-step upgrade has to be resumable rather than guessable. An `offered` migration is recorded in the applied ledger *without* moving `kb_version` and with no ordering rule applied: it is not a link in the chain, so there is nothing to skip, and requiring the chain first would make an unrelated file upgrade wait on it. Re-recording one already in the ledger is a no-op, not an error
|
||||
- Records one migration as applied, advancing `kb_version` in `.wikitool-kb.json` to its target.
|
||||
- **Refuses any required version that is not the next link in the chain.**
|
||||
- An `offered` migration is recorded in the applied ledger *without* moving `kb_version` and with no ordering rule applied. Re-recording one already in the ledger is a no-op, not an error - idempotent and safe to repeat.
|
||||
- Not idempotent for a required migration: it advances the chain.
|
||||
- `--dry-run` reports without writing.
|
||||
|
||||
**SEE ALSO**
|
||||
|
||||
- `wikitool migrate status` - the order to apply them in
|
||||
- `instructions/migrate-corpus.md` - the migration procedure
|
||||
|
||||
#### `migrate baseline`
|
||||
|
||||
@@ -2921,18 +2991,35 @@ Declare `kb_version` once, for an instance predating `.wikitool-kb.json`.
|
||||
- budget: counted
|
||||
- network: no
|
||||
|
||||
**EXAMPLES**
|
||||
|
||||
- `tools/wikitool migrate baseline 6.2.0`
|
||||
|
||||
**EXIT STATUS**
|
||||
|
||||
- 0 success
|
||||
- 1 Unparseable version, or a declaration already exists and `--force` was not passed
|
||||
- 1 Unparseable version
|
||||
- 1 A declaration already exists and `--force` was not passed
|
||||
|
||||
**ON FAILURE**
|
||||
|
||||
- Unparseable version, or a declaration already exists and `--force` was not passed -> Safe to re-run with the same version. If a declaration exists, it is almost always `migrate done` that was wanted
|
||||
- Unparseable version -> Fix the version and retry
|
||||
- A declaration already exists and `--force` was not passed -> It is almost always `migrate done` that was wanted
|
||||
|
||||
**NEVER**
|
||||
|
||||
- Never use `--force` to advance the version past a migration - that is `migrate done`.
|
||||
|
||||
**NOTES**
|
||||
|
||||
Refuses to overwrite an existing declaration without `--force`: advancing after a migration is `done`, which checks the chain, and this command must not become the quiet way around it
|
||||
- Declares `kb_version` once, for an instance predating `.wikitool-kb.json`.
|
||||
- Refuses to overwrite an existing declaration without `--force`. Advancing the version after a migration is `migrate done`, which checks the chain; this command does not.
|
||||
- Safe to re-run with the same version.
|
||||
|
||||
**SEE ALSO**
|
||||
|
||||
- `wikitool migrate done` - advances the version after a migration
|
||||
- `wikitool migrate status` - what is owed from the declared version
|
||||
|
||||
### Private instances
|
||||
|
||||
|
||||
@@ -59,9 +59,19 @@ def _versions() -> tuple[Version, Optional[Version]]:
|
||||
atomic="Read-only",
|
||||
budget=cli_contract.Budget.EXEMPT,
|
||||
),
|
||||
notes="Oldest target first, with its kind and obligation. Read-only and **exempt from the "
|
||||
"Iteration Budget Gate**. Never fails.",
|
||||
notes=(
|
||||
"Lists every migration document under `instructions/migrations/`, oldest target first, "
|
||||
"with its kind and obligation.",
|
||||
"Never fails. Read-only and **exempt from the Iteration Budget Gate**.",
|
||||
),
|
||||
failures=(),
|
||||
examples=(
|
||||
"tools/wikitool migrate list",
|
||||
),
|
||||
see_also=(
|
||||
"`wikitool migrate status` - which of them this instance still owes",
|
||||
"`instructions/migrate-corpus.md` - how a migration is run",
|
||||
),
|
||||
))
|
||||
@app.command("list")
|
||||
def list_command(
|
||||
@@ -158,23 +168,39 @@ def _report_offers(
|
||||
atomic="Read-only",
|
||||
budget=cli_contract.Budget.EXEMPT,
|
||||
),
|
||||
notes="Every **required** document whose `migrates_to` lies in `(kb_version, VERSION]`. "
|
||||
"`offered` documents are listed separately above the chain and never block, never count as "
|
||||
"owed, and are bounded by the applied ledger rather than by `kb_version` - taking one "
|
||||
"deliberately does not move the version, so the version cannot say whether it was taken. "
|
||||
"When a release stamp is present, also reports which shipped files this instance has since "
|
||||
"edited (from the per-file sha256 in `.wikitool-release.json`), which is what says whether "
|
||||
"an offer may be copied over or has to be reconciled by hand; without a stamp that question "
|
||||
"is reported as unanswerable rather than answered. Exits 1 only when `.wikitool-kb.json` is "
|
||||
"missing - the content's shape is a question the tool refuses to answer by guessing. "
|
||||
"Read-only and exempt from the budget gate",
|
||||
failures=(cli_contract.Failure(
|
||||
label="",
|
||||
cause="`.wikitool-kb.json` is missing (content version undeclared), or `VERSION` is "
|
||||
"unreadable",
|
||||
reaction="For a missing declaration: run `migrate baseline <version>` once, then retry. "
|
||||
"Safe to retry freely otherwise",
|
||||
),),
|
||||
notes=(
|
||||
"Shows every **required** migration whose `migrates_to` lies in "
|
||||
"`(kb_version, VERSION]`, in the order it must run.",
|
||||
"`offered` migrations are listed separately above the chain: they never block, never "
|
||||
"count as owed, and are bounded by the applied ledger rather than by `kb_version` - "
|
||||
"taking one does not move the version.",
|
||||
"With a release stamp present, also reports which shipped files this instance has "
|
||||
"since edited (from the per-file sha256 in `.wikitool-release.json`) - which says "
|
||||
"whether an offer may be copied over or has to be reconciled by hand. Without a stamp "
|
||||
"that question is reported as unanswerable rather than answered.",
|
||||
"Exits 1 only when the content version is undeclared (`.wikitool-kb.json` missing) or "
|
||||
"`VERSION` is unreadable; it never guesses the content's shape.",
|
||||
"Read-only, safe to retry freely, and exempt from the Iteration Budget Gate.",
|
||||
),
|
||||
failures=(
|
||||
cli_contract.Failure(
|
||||
cause="`.wikitool-kb.json` is missing - the content version is undeclared",
|
||||
reaction="Run `migrate baseline <version>` once, then retry",
|
||||
),
|
||||
cli_contract.Failure(
|
||||
cause="`VERSION` is unreadable",
|
||||
reaction="Fix `VERSION`, then retry",
|
||||
),
|
||||
),
|
||||
examples=(
|
||||
"tools/wikitool migrate status",
|
||||
"tools/wikitool migrate status --json",
|
||||
),
|
||||
see_also=(
|
||||
"`wikitool migrate done` - records one as applied",
|
||||
"`instructions/migrate-corpus.md` - how a migration is run",
|
||||
"`instructions/upgrade-instance.md` - where an upgrade checks this",
|
||||
),
|
||||
))
|
||||
@app.command("status")
|
||||
def status_command(
|
||||
@@ -264,21 +290,38 @@ def status_command(
|
||||
atomic="Yes - single file write",
|
||||
budget=cli_contract.Budget.COUNTED,
|
||||
),
|
||||
notes="**Refuses any version that is not the next link in the chain** - skipping one leaves "
|
||||
"the corpus in a shape no version describes, and an interrupted multi-step upgrade has to "
|
||||
"be resumable rather than guessable. An `offered` migration is recorded in the applied "
|
||||
"ledger *without* moving `kb_version` and with no ordering rule applied: it is not a link "
|
||||
"in the chain, so there is nothing to skip, and requiring the chain first would make an "
|
||||
"unrelated file upgrade wait on it. Re-recording one already in the ledger is a no-op, not "
|
||||
"an error",
|
||||
failures=(cli_contract.Failure(
|
||||
label="",
|
||||
cause="Unknown version, no `.wikitool-kb.json`, nothing outstanding, or a *required* "
|
||||
"version that is not the next link in the chain",
|
||||
reaction="**Not idempotent** for a required migration: it advances the chain. For \"not "
|
||||
"the next link\", run `migrate status` and apply them in the order it prints - never "
|
||||
"force the order. Recording an `offered` migration *is* idempotent and safe to repeat",
|
||||
),),
|
||||
notes=(
|
||||
"Records one migration as applied, advancing `kb_version` in `.wikitool-kb.json` to its "
|
||||
"target.",
|
||||
"**Refuses any required version that is not the next link in the chain.**",
|
||||
"An `offered` migration is recorded in the applied ledger *without* moving "
|
||||
"`kb_version` and with no ordering rule applied. Re-recording one already in the ledger "
|
||||
"is a no-op, not an error - idempotent and safe to repeat.",
|
||||
"Not idempotent for a required migration: it advances the chain.",
|
||||
"`--dry-run` reports without writing.",
|
||||
),
|
||||
failures=(
|
||||
cli_contract.Failure(
|
||||
cause="Unknown version, no `.wikitool-kb.json`, or nothing outstanding",
|
||||
reaction="Check `migrate status`, fix the argument, then retry once",
|
||||
),
|
||||
cli_contract.Failure(
|
||||
cause="A *required* version that is not the next link in the chain",
|
||||
reaction="Run `migrate status` and apply the migrations in the order it prints",
|
||||
),
|
||||
),
|
||||
examples=(
|
||||
"tools/wikitool migrate done 7.0.0 --pages 42 --dry-run",
|
||||
"tools/wikitool migrate done 7.0.0 --pages 42",
|
||||
),
|
||||
never=(
|
||||
"Never force the order of required migrations.",
|
||||
"Never hand-edit `.wikitool-kb.json` to advance the version.",
|
||||
),
|
||||
see_also=(
|
||||
"`wikitool migrate status` - the order to apply them in",
|
||||
"`instructions/migrate-corpus.md` - the migration procedure",
|
||||
),
|
||||
))
|
||||
@app.command("done")
|
||||
def done_command(
|
||||
@@ -293,7 +336,9 @@ def done_command(
|
||||
interrupted multi-step upgrade has to be resumable rather than guessable.
|
||||
|
||||
An `offered` migration is recorded but does not move the version, and no
|
||||
ordering rule applies to it - it is not a link in the chain. The record is
|
||||
ordering rule applies to it - it is not a link in the chain, so there is
|
||||
nothing to skip, and requiring the chain first would make an unrelated
|
||||
file upgrade wait on it. The record is
|
||||
the only thing that distinguishes an offer someone took from one they
|
||||
ignored, precisely because the version stays put."""
|
||||
stack, kb_version = _versions()
|
||||
@@ -386,16 +431,32 @@ def done_command(
|
||||
atomic="Yes - single file write",
|
||||
budget=cli_contract.Budget.COUNTED,
|
||||
),
|
||||
notes="Refuses to overwrite an existing declaration without `--force`: advancing after a "
|
||||
"migration is `done`, which checks the chain, and this command must not become the quiet "
|
||||
"way around it",
|
||||
failures=(cli_contract.Failure(
|
||||
label="",
|
||||
cause="Unparseable version, or a declaration already exists and `--force` was not "
|
||||
"passed",
|
||||
reaction="Safe to re-run with the same version. If a declaration exists, it is almost "
|
||||
"always `migrate done` that was wanted",
|
||||
),),
|
||||
notes=(
|
||||
"Declares `kb_version` once, for an instance predating `.wikitool-kb.json`.",
|
||||
"Refuses to overwrite an existing declaration without `--force`. Advancing the version "
|
||||
"after a migration is `migrate done`, which checks the chain; this command does not.",
|
||||
"Safe to re-run with the same version.",
|
||||
),
|
||||
failures=(
|
||||
cli_contract.Failure(
|
||||
cause="Unparseable version",
|
||||
reaction="Fix the version and retry",
|
||||
),
|
||||
cli_contract.Failure(
|
||||
cause="A declaration already exists and `--force` was not passed",
|
||||
reaction="It is almost always `migrate done` that was wanted",
|
||||
),
|
||||
),
|
||||
examples=(
|
||||
"tools/wikitool migrate baseline 6.2.0",
|
||||
),
|
||||
never=(
|
||||
"Never use `--force` to advance the version past a migration - that is `migrate done`.",
|
||||
),
|
||||
see_also=(
|
||||
"`wikitool migrate done` - advances the version after a migration",
|
||||
"`wikitool migrate status` - what is owed from the declared version",
|
||||
),
|
||||
))
|
||||
@app.command("baseline")
|
||||
def baseline_command(
|
||||
@@ -537,25 +598,42 @@ def _shapes_now(wanted: set[str]) -> dict[str, corpus_diff.PageShape]:
|
||||
atomic="Read-only",
|
||||
budget=cli_contract.Budget.EXEMPT,
|
||||
),
|
||||
notes="Wikilink and citation **counts** (not sets), footnote definitions, H1, structural "
|
||||
"frontmatter, and the **count of generated-region marker pairs** - a page that went from "
|
||||
"one links region to two has the same set of region names and a different count, and a "
|
||||
"lost marker turns a generated region into prose the next write appends a second one "
|
||||
"beside. Pages are matched by **title**, not path, so a page `wikitool move` (or "
|
||||
"`move --reconcile`) relocated compares as itself - reported separately as `moved` - rather "
|
||||
"than as a removed-and-added pair. Reports added/removed pages without failing on them. "
|
||||
"`--expect-body-change` additionally flags a page whose body did not change at all. Not "
|
||||
"migration-specific - worth running after any bulk rewrite, and the one question `lint` "
|
||||
"cannot answer, since it reads a single revision and so cannot see that something went "
|
||||
"missing. Read-only and exempt from the budget gate",
|
||||
failures=(cli_contract.Failure(
|
||||
label="",
|
||||
cause="Only with `--fail-on-error`: an invariant changed. Also exits 1 if `--from` is "
|
||||
"not a revision in this repository",
|
||||
reaction="Exit 1 from `--fail-on-error` means \"act on the findings\", not \"the tool is "
|
||||
"broken\". A finding is never fixed by re-running - it names a page and what changed on "
|
||||
"it",
|
||||
),),
|
||||
notes=(
|
||||
"Compares `kb/` against the revision `--from` on the invariants a content migration "
|
||||
"must not change: wikilink and citation **counts** (not sets), footnote definitions, "
|
||||
"H1, structural frontmatter, and the **count of generated-region marker pairs**.",
|
||||
"Pages are matched by **title**, not path, so a page `move` (or `move --reconcile`) "
|
||||
"relocated compares as itself - reported separately as `moved` - rather than as a "
|
||||
"removed-and-added pair.",
|
||||
"Reports added and removed pages without failing on them.",
|
||||
"`--expect-body-change` additionally flags a page whose body did not change at all.",
|
||||
"Not migration-specific: worth running after any bulk rewrite.",
|
||||
"Exits 0 whatever it finds unless `--fail-on-error` is passed.",
|
||||
"Read-only and exempt from the Iteration Budget Gate.",
|
||||
),
|
||||
failures=(
|
||||
cli_contract.Failure(
|
||||
cause="Only with `--fail-on-error`: an invariant changed",
|
||||
reaction="Act on the findings - exit 1 here means \"act on the findings\", not \"the "
|
||||
"tool is broken\". A finding names a page and what changed on it; it is never fixed "
|
||||
"by re-running",
|
||||
),
|
||||
cli_contract.Failure(
|
||||
cause="`--from` is not a revision in this repository",
|
||||
reaction="Fix the revision and retry",
|
||||
),
|
||||
),
|
||||
examples=(
|
||||
"tools/wikitool migrate verify --from HEAD",
|
||||
"tools/wikitool migrate verify --from HEAD --path kb/concepts --expect-body-change",
|
||||
),
|
||||
never=(
|
||||
"Never re-run to make a finding go away - fix the page it names.",
|
||||
),
|
||||
see_also=(
|
||||
"`instructions/migrate-corpus.md` - where a migration runs this",
|
||||
"`wikitool lint` - the single-revision checks",
|
||||
),
|
||||
))
|
||||
@app.command("verify")
|
||||
def verify_command(
|
||||
@@ -575,6 +653,13 @@ def verify_command(
|
||||
must not change: wikilink and citation *counts*, footnote definitions, H1,
|
||||
and structural frontmatter.
|
||||
|
||||
Marker pairs are compared by *count*, not by the set of region names: a
|
||||
page that went from one links region to two has the same set and a
|
||||
different count, and a lost marker turns a generated region into prose
|
||||
the next write appends a second one beside. This is the one question
|
||||
`lint` cannot answer - it reads a single revision, so it cannot see that
|
||||
something went missing.
|
||||
|
||||
Pages are matched by title, not path, so a page that only moved directory
|
||||
(see `wikitool move`) compares as itself rather than as a
|
||||
removed-and-added pair - its path change is reported separately, as
|
||||
|
||||
Reference in new issue
Block a user