feat: page titles must be valid, unique file names on Windows and macOS - new/rename/move refuse, lint reports Unportable Titles, new never overwrites (#155)
CI / verify (push) Successful in 1m37s
Release / release (push) Successful in 37s

Files changed:
- CHANGES.md
- README.md
- VERSION
- instructions/page-lifecycle.md
- instructions/wiki-lint/SKILL.md
- kb/CONTRACT.md
- kb/CONVENTIONS.md
- kb/CONVENTIONS.md.template
- tools/CONTRACT.md
- tools/chemenu/commands/_util.py
- tools/chemenu/commands/lint.py
- tools/chemenu/commands/new_page.py
- tools/chemenu/commands/page_ops.py
- tools/chemenu/lint_core.py
- tools/chemenu/tests/test_lint.py
- tools/chemenu/tests/test_new_page.py
- tools/chemenu/tests/test_page_ops.py
- tools/chemenu/tests/test_titles.py
- tools/chemenu/titles.py
This commit is contained in:
torben committed 2026-09-30 06:29:28 +02:00
1 parent 94deccb18d
commit 8be5e6e5f3
19 files changed
+654 -33

No files matched your search

+18
View File
@@ -120,6 +120,24 @@ Which *form* those titles take - spaces or kebab-case, singular or plural, what
decision record - is the instance's, in
[kb/CONVENTIONS.md § Naming](CONVENTIONS.md#naming).
**A title is also a file name, so it must be one on every platform** - Windows and macOS as
well as Linux, checked wherever the command runs: a corpus written on Linux is checked out on
the others, and a title that Linux accepts and Windows refuses breaks every clone there. The full
title counts, after any `title_prefix`. A title must not:
- be empty, or end with a dot or a space
- contain `<` `>` `:` `"` `/` `\` `|` `?` `*` or a control character
- start, before its first dot and regardless of case, with a Windows device name (`CON`, `PRN`,
`AUX`, `NUL`, `COM0`-`COM9`, `LPT0`-`LPT9`, and the superscript forms `COM¹`-`COM³`,
`LPT¹`-`LPT³`) or with a name the stack itself keeps beside a page (`INDEX`, `COLLECTION`)
- collide with another page once both are normalized to NFC and compared by `casefold` - NTFS and
APFS fold case, and APFS folds NFC and NFD as well
`wikitool new` and `wikitool rename` refuse such a title (`new` for every type, whatever root it
writes to; `rename` only for `--to`, so a page that already breaks the rule can always be renamed
away from it), and never write over an existing file. `wikitool lint` reports existing pages that
break the rule as Unportable Titles, a hard error at every `kb_version`.
## Every page should
- [ ] Carry a clear, descriptive title and a summary near the top
+3 -2
View File
@@ -96,8 +96,9 @@ What to name a thing: projects use their repository or common name; systems a de
name; tools the tool's own name; technologies their standard spelling and capitalization;
people a full name or common handle.
The one naming fact that is *not* a choice, and therefore lives in the contract: the filename
stem is the page title, and `[[wikilinks]]` must match it exactly.
The naming facts that are *not* a choice, and therefore live in the contract: the filename
stem is the page title, `[[wikilinks]]` must match it exactly, and the title must be a valid,
unique file name on every platform (`kb/CONTRACT.md` § Titles are identifiers).
## Tone
+3 -2
View File
@@ -81,8 +81,9 @@ them - they are rebuilt from frontmatter on every write. Any *other* heading is
- {The ADR prefix, if this instance files decisions as pages.}
- {What to name a thing: projects, systems, tools, technologies, people.}
The one naming fact that is *not* a choice, and therefore lives in the contract: the filename
stem is the page title, and `[[wikilinks]]` must match it exactly.
The naming facts that are *not* a choice, and therefore live in the contract: the filename
stem is the page title, `[[wikilinks]]` must match it exactly, and the title must be a valid,
unique file name on every platform (`kb/CONTRACT.md` § Titles are identifiers).
## Tone