Point-of-use enforcement needs hands, not advice: - `destroy-vault.py` — moves the pages on a kill list to `.AGENTTRASH/` and then deletes every reference to them from the survivors, including the whole line when the dead link was the line's only content. Stems are seeded from the trash so the pass is re-runnable; `pathlib.Path.stem` is NOT used to compare link targets, because it strips the real suffix off names like `sd.cpp`. - `axe-measurements.py` — deletes bench/throughput ledger sections and rate rows, blanks any table cell that reports a rate, and folds Eras older than the current one into a single row that says the numbers were destroyed and that rollback is a commit. Never touches a shape number or a Law/Wire/Rollback section. - `repair-damage.py` — fixes the two artifacts those passes can leave (a list marker that lost its space, a table separator left without its header). - `restore-punctuation.py` — restores a line whose only difference from HEAD is stripped trailing punctuation. Written after `repair-damage.py`'s first version matched every wrapped prose line ending in a comma and deleted 660 of them: the rule is now `… see .` only, and the incident is recorded in its docstring. - `gen-vault-index.py` — never walks into `.AGENTTRASH/`, and sweeps rows whose page cell is empty (a description left nameless by a destruction). Full suite: 451 tests pass.
57 lines
2.2 KiB
Python
Executable File
57 lines
2.2 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Repair the two artifacts the destruction passes introduced.
|
|
|
|
1. The link stripper could eat the space after a `- ` marker (`-`X``) and leave a
|
|
dangling `see .` where a wikilink used to be.
|
|
2. The Eras collapse could swallow a table's HEADER row (it looked like just
|
|
another non-current row), leaving a separator with no header above it.
|
|
|
|
Usage: repair-damage.py [--apply]
|
|
"""
|
|
import pathlib
|
|
import re
|
|
import sys
|
|
|
|
VAULT = pathlib.Path("serverAppConfigs-docs")
|
|
ERAS_HEADER = "| Window | Payload | Runtime | Shape | Replaced because | Rollback |"
|
|
|
|
|
|
def main(argv):
|
|
apply = "--apply" in argv
|
|
marker = dangling = header = 0
|
|
for p in sorted(VAULT.rglob("*.md")):
|
|
s = str(p)
|
|
if ".AGENTTRASH" in s or ".obsidian" in s:
|
|
continue
|
|
lines = p.read_text(errors="replace").split("\n")
|
|
out = []
|
|
# Only a pointer whose target was deleted reads as `… see .` — never touch
|
|
# a line merely because it wraps on a comma. (An earlier version of this
|
|
# rule stripped the trailing comma off 660 wrapped prose lines, which
|
|
# `scripts/restore-punctuation.py` then had to undo from HEAD.)
|
|
for line in lines:
|
|
new = line
|
|
if re.match(r"^(\s*)[-*](?![-* ])[$`[(*_]", new):
|
|
new = re.sub(r"^(\s*)[-*]", r"\1- ", new)
|
|
marker += 1
|
|
if re.search(r"\s(?:see|also|details in|via|per)\s*\.?\s*$", new):
|
|
new = re.sub(r"\s(?:see|also|details in|via|per)\s*\.?\s*$", "", new)
|
|
dangling += 1
|
|
out.append(new)
|
|
# A separator row whose line above is not a header gets its header back.
|
|
fixed = []
|
|
for i, line in enumerate(out):
|
|
if re.match(r"^\|-+", line.strip()) and (not fixed or not fixed[-1].strip().startswith("|")):
|
|
fixed.append(ERAS_HEADER)
|
|
header += 1
|
|
fixed.append(line)
|
|
if apply and "".join(fixed) != "".join(lines):
|
|
p.write_text("\n".join(fixed))
|
|
print(f"{'APPLIED' if apply else 'dry run'}: marker spacing {marker}, "
|
|
f"dangling pointers {dangling}, restored table headers {header}")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main(sys.argv))
|