fix: three more #142 command-record mismatches aligned to code (#146)
CI / verify (push) Successful in 1m10s
Release / release (push) Successful in 36s

Files changed:
- CHANGES.md
- VERSION
- kb/CONTRACT.md
- tools/CONTRACT.md
- tools/chemenu/commands/docs_verify.py
- tools/chemenu/commands/git_publish.py
- tools/chemenu/commands/lint.py
- tools/chemenu/commands/xref.py
- tools/chemenu/tests/test_cli.py
This commit is contained in:
torben committed 2026-09-26 18:06:34 +02:00
1 parent 20745399c0
commit 8d5fc6e941
9 files changed
+54 -19

No files matched your search

+19 -1
View File
@@ -59,7 +59,7 @@ concern - readable here, never shipped as something to parse.
--- ---
## 7.1.0-beta.24 - 2026-09-26 - log append: unreadable --body-file is an ERROR line, not a traceback ## 7.1.0-beta.25 - 2026-09-26 - Command records: three more mismatches from #142 aligned to code
**Author:** Torben Nehmer **Author:** Torben Nehmer
@@ -93,6 +93,7 @@ concern - readable here, never shipped as something to parse.
- Command records: NOTES is always a tuple of bullets; every record's examples are tested - Command records: NOTES is always a tuple of bullets; every record's examples are tested
- network: property defined; sync, publish and upstream merge marked networked - network: property defined; sync, publish and upstream merge marked networked
- log append: unreadable --body-file is an ERROR line, not a traceback - log append: unreadable --body-file is an ERROR line, not a traceback
- Command records: three more mismatches from #142 aligned to code
<!-- /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
@@ -389,6 +390,23 @@ through `fail()`, which also gives the budget slot back, before `kb/log.md` is o
stays byte-identical in every failure case, and a parametrised test pins all three. The stays byte-identical in every failure case, and a parametrised test pins all three. The
record's cause now names the cases ("missing, not a readable file, or not valid UTF-8"). record's cause now names the cases ("missing, not a readable file, or not valid UTF-8").
### Command records: three more mismatches from #142 aligned to code
Four more text-vs-code disagreements from #142's collection issue (Gitea #146), decided in the
code's favour and fixed in the text - no behaviour change. `lint`'s quote-limit cap counts
blockquotes, not lines, since #22 changed the unit; `kb/CONTRACT.md`'s Quotation cap section had
kept the old wording and now names the same unit, with the rule that a fenced code block is
masked out first. `docs contract`'s record carried no exit-1 cause at all although
`contract_command` fails when `tools/CONTRACT.md` is missing - the case #143's own follow-up
flagged - so it now names that cause; the merged-stream test that used to exercise the `see:`
fallback through this very gap is updated to check the new hint instead, and the fallback itself
stays covered by its own fixture-based test. `xref add`'s `atomic` property still described the
two-write shape from before the edge became one-sided, though the code and its own NOTES have
long said a source-page edge only ever writes A; it now says so. `publish`'s `atomic` property,
tightened once already in this candidate to "every gate runs before staging", still missed the
one case that breaks it: the rebase-review gate can exit 42 on the single retry of a rejected
push, which happens after the commit already landed.
--- ---
## 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
+1 -1
View File
@@ -1 +1 @@
7.1.0-beta.24 7.1.0-beta.25
+6 -4
View File
@@ -132,10 +132,12 @@ decision record - is the instance's, in
## Quotation cap ## Quotation cap
At most 2 blockquoted lines per page. `wikitool lint` reports overages as advisory, since At most 2 blockquotes per page - a blockquote being a run of consecutive `>` lines, code masked
exceeding the cap can be a legitimate judgment call - but the page should carry the knowledge out first, so a `>` inside a fenced shell transcript is a prompt rather than a quotation.
itself, not delegate it to quotations. The cap is about how much of the page you let quotes `wikitool lint` reports overages as advisory, since exceeding the cap can be a legitimate
carry; it does not apply to text you are citing verbatim from a source. judgment call - but the page should carry the knowledge itself, not delegate it to quotations.
The cap is about how much of the page you let quotes carry, not how long a wrapped quotation
runs; it does not apply to text you are citing verbatim from a source.
The register those lines are written in - what counts as a buzzword, what filler is refused - The register those lines are written in - what counts as a buzzword, what filler is refused -
is the instance's, in [kb/CONVENTIONS.md § Tone](CONVENTIONS.md#tone). is the instance's, in [kb/CONVENTIONS.md § Tone](CONVENTIONS.md#tone).
+9 -4
View File
@@ -125,7 +125,7 @@ instructions verify read idempotent budget:counted exit:0,1
instructions list read idempotent budget:counted exit:0 List the flat instructions with their descriptions. instructions list read idempotent budget:counted exit:0 List the flat instructions with their descriptions.
docs verify read idempotent budget:counted exit:0,1 Check the docs that mirror the code. docs verify read idempotent budget:counted exit:0,1 Check the docs that mirror the code.
docs toc write idempotent budget:counted exit:0 Create, refresh or remove the generated table-of-contents region. docs toc write idempotent budget:counted exit:0 Create, refresh or remove the generated table-of-contents region.
docs contract write idempotent budget:counted exit:0 Regenerate `tools/CONTRACT.md`'s `<!-- wikitool:commands -->` region. docs contract write idempotent budget:counted exit:0,1 Regenerate `tools/CONTRACT.md`'s `<!-- wikitool:commands -->` region.
eval sessions read idempotent budget:exempt exit:0 List the sessions that have a trace under `reports/telemetry/`. eval sessions read idempotent budget:exempt exit:0 List the sessions that have a trace under `reports/telemetry/`.
eval score read idempotent budget:exempt exit:0,1 Score one traced session. eval score read idempotent budget:exempt exit:0,1 Score one traced session.
dist export write idempotent budget:counted exit:0,1 Write a contentless, distributable copy of this repo's machinery. dist export write idempotent budget:counted exit:0,1 Write a contentless, distributable copy of this repo's machinery.
@@ -614,7 +614,7 @@ Declare that A <rel> B.
- effect: write - effect: write
- idempotent: yes - idempotent: yes
- atomic: No - writes A then B, but both edits are idempotent, and both refusals happen before either write - atomic: Yes - a single write to A; B is never touched, and every refusal happens before it
- budget: counted - budget: counted
- network: no - network: no
@@ -1102,7 +1102,7 @@ Run structural lint checks against kb/.
- Advisory only: `see-also` edges whose reverse direction already carries a specific label - never migration-gated. - Advisory only: `see-also` edges whose reverse direction already carries a specific label - never migration-gated.
- Advisory only: a collection past the catalog's per-area shard threshold that has no areas to shard, reported with the split its subtype field would produce, and only when that split puts every resulting area at or under the threshold. - Advisory only: a collection past the catalog's per-area shard threshold that has no areas to shard, reported with the split its subtype field would produce, and only when that split puts every resulting area at or under the threshold.
- Advisory only: source pages sitting in the `unclassified` catalog slot. - Advisory only: source pages sitting in the `unclassified` catalog slot.
- Advisory only: quote-limit overages (>2 blockquoted lines/page). - Advisory only: quote-limit overages (>2 blockquotes/page).
- Prints only the sections that found something and always writes the full report to `reports/Lint Report <date>.md` (or `--markdown`), naming the path. `--full` prints everything; `--json` prints the findings and writes nothing. - Prints only the sections that found something and always writes the full report to `reports/Lint Report <date>.md` (or `--markdown`), naming the path. `--full` prints everything; `--json` prints the findings and writes nothing.
- Exits 0 whatever it finds unless `--fail-on-error` is passed. - Exits 0 whatever it finds unless `--fail-on-error` is passed.
@@ -1662,7 +1662,7 @@ Reconcile with `<remote>/<branch>`, then stage all changes, commit, and push.
- effect: write - effect: write
- idempotent: no - idempotent: no
- atomic: No - sequential git operations, but every gate runs before staging - atomic: No - sequential git operations. Every gate runs before staging, except on the one retry of a rejected push, where the rebase-review gate can exit 42 after the commit: nothing is pushed, and the re-run with `--confirm-rebase` pushes that commit
- budget: counted - budget: counted
- network: yes - network: yes
- gates: mass-update, publish-remote, rebase-review - gates: mass-update, publish-remote, rebase-review
@@ -2249,6 +2249,11 @@ Regenerate `tools/CONTRACT.md`'s `<!-- wikitool:commands -->` region.
**EXIT STATUS** **EXIT STATUS**
- 0 success - 0 success
- 1 `tools/CONTRACT.md` is missing
**ON FAILURE**
- `tools/CONTRACT.md` is missing -> Not transient - restore the file, which carries hand-written prose around the region this command does not generate, then retry
**NEVER** **NEVER**
+5 -1
View File
@@ -1251,7 +1251,11 @@ def toc_command(
"Dry-run by default (says whether the file would change); `--apply` writes.", "Dry-run by default (says whether the file would change); `--apply` writes.",
"`docs verify` checks the result stays current.", "`docs verify` checks the result stays current.",
), ),
failures=(), failures=(cli_contract.Failure(
cause="`tools/CONTRACT.md` is missing",
reaction="Not transient - restore the file, which carries hand-written prose around "
"the region this command does not generate, then retry",
),),
examples=( examples=(
"tools/wikitool docs contract", "tools/wikitool docs contract",
"tools/wikitool docs contract --apply", "tools/wikitool docs contract --apply",
+3 -1
View File
@@ -1088,7 +1088,9 @@ def sync_command(
properties=cli_contract.Properties( properties=cli_contract.Properties(
effect=cli_contract.Effect.WRITE, effect=cli_contract.Effect.WRITE,
idempotent=cli_contract.Idempotent.NO, idempotent=cli_contract.Idempotent.NO,
atomic="No - sequential git operations, but every gate runs before staging", atomic="No - sequential git operations. Every gate runs before staging, except on the "
"one retry of a rejected push, where the rebase-review gate can exit 42 after the "
"commit: nothing is pushed, and the re-run with `--confirm-rebase` pushes that commit",
budget=cli_contract.Budget.COUNTED, budget=cli_contract.Budget.COUNTED,
network=cli_contract.Network.YES, network=cli_contract.Network.YES,
gates=("mass-update", "publish-remote", "rebase-review"), gates=("mass-update", "publish-remote", "rebase-review"),
+1 -1
View File
@@ -75,7 +75,7 @@ __all__ = [
"areas to shard, reported with the split its subtype field would produce, and only " "areas to shard, reported with the split its subtype field would produce, and only "
"when that split puts every resulting area at or under the threshold.", "when that split puts every resulting area at or under the threshold.",
"Advisory only: source pages sitting in the `unclassified` catalog slot.", "Advisory only: source pages sitting in the `unclassified` catalog slot.",
"Advisory only: quote-limit overages (>2 blockquoted lines/page).", "Advisory only: quote-limit overages (>2 blockquotes/page).",
"Prints only the sections that found something and always writes the full report to " "Prints only the sections that found something and always writes the full report to "
"`reports/Lint Report <date>.md` (or `--markdown`), naming the path. `--full` prints " "`reports/Lint Report <date>.md` (or `--markdown`), naming the path. `--full` prints "
"everything; `--json` prints the findings and writes nothing.", "everything; `--json` prints the findings and writes nothing.",
+2 -2
View File
@@ -153,8 +153,8 @@ def _check_authorised(source: Page, target: Page, label: str) -> None:
properties=cli_contract.Properties( properties=cli_contract.Properties(
effect=cli_contract.Effect.WRITE, effect=cli_contract.Effect.WRITE,
idempotent=cli_contract.Idempotent.YES, idempotent=cli_contract.Idempotent.YES,
atomic="No - writes A then B, but both edits are idempotent, and both refusals happen " atomic="Yes - a single write to A; B is never touched, and every refusal happens "
"before either write", "before it",
budget=cli_contract.Budget.COUNTED, budget=cli_contract.Budget.COUNTED,
), ),
notes=( notes=(
+8 -4
View File
@@ -343,9 +343,12 @@ def test_stderr_hint_follows_the_error_line_when_streams_are_merged(tmp_path):
`docs contract` against an empty `CHEMENU_ROOT` fails because `docs contract` against an empty `CHEMENU_ROOT` fails because
`tools/CONTRACT.md` does not exist there - no fixture kb, no write, `tools/CONTRACT.md` does not exist there - no fixture kb, no write,
nothing to clean up. It is also the one real record with no exit-1 cause nothing to clean up. Its record used to carry no exit-1 cause of its own
of its own (Gitea #146), so this doubles as the real-command check for (Gitea #146), so this used to double as the real-command check for the
the `see:` fallback.""" `see:` fallback; the record now names this cause, so the hint is its own
reaction instead - the fallback itself stays covered by
`test_render_failure_hint_falls_back_to_a_bare_pointer` in
`test_cli_contract.py`, against a fixture record."""
tools_dir = Path(__file__).resolve().parents[2] tools_dir = Path(__file__).resolve().parents[2]
env = dict(os.environ) env = dict(os.environ)
env["CHEMENU_ROOT"] = str(tmp_path) env["CHEMENU_ROOT"] = str(tmp_path)
@@ -364,4 +367,5 @@ def test_stderr_hint_follows_the_error_line_when_streams_are_merged(tmp_path):
assert result.returncode == 1 assert result.returncode == 1
lines = result.stdout.splitlines() lines = result.stdout.splitlines()
assert lines[0] == "ERROR tools/CONTRACT.md is missing." assert lines[0] == "ERROR tools/CONTRACT.md is missing."
assert lines[1] == "see: wikitool docs contract -h" hint = cli_contract.render_failure_hint(cli_contract.get("docs contract"))
assert "\n".join(lines[1:]) == hint