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