Skip to content

Commit a6d55b3

Browse files
authored
Merge pull request #82 from ChBrain/fix/withheld-audit-footers
fix: withheld audit footers, Norderelbe correction, spotcheck coverage
2 parents 6389dfd + f58ef07 commit a6d55b3

31 files changed

Lines changed: 1019 additions & 492 deletions

.githooks/pre-commit

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,40 @@ def detect_bump_type(current: str, staged: str) -> str:
4848
return "NONE"
4949

5050

51+
UTF8_BOM = b"\xef\xbb\xbf"
52+
53+
54+
def strip_bom_from_staged_files() -> list[str]:
55+
"""Strip UTF-8 BOM from any staged text file that has one.
56+
57+
PowerShell Set-Content writes BOM regardless of .editorconfig. Stripping
58+
at commit time keeps the repository clean without requiring each tool/shell
59+
to be configured correctly.
60+
61+
Returns a list of file paths that were fixed.
62+
"""
63+
staged = run_git("diff", "--cached", "--name-only")
64+
fixed = []
65+
for rel in staged.splitlines():
66+
path = Path(rel)
67+
if not path.exists() or path.suffix not in {".md", ".txt", ".py", ".sh", ".json"}:
68+
continue
69+
raw = path.read_bytes()
70+
if raw.startswith(UTF8_BOM):
71+
path.write_bytes(raw[3:])
72+
subprocess.run(["git", "add", rel], check=False)
73+
fixed.append(rel)
74+
return fixed
75+
76+
5177
def main() -> int:
78+
# Strip BOM from staged files before any other checks.
79+
# Transparent fix for PowerShell Set-Content BOM injection.
80+
fixed = strip_bom_from_staged_files()
81+
if fixed:
82+
for f in fixed:
83+
print(f" (stripped UTF-8 BOM from {f})")
84+
5285
# Guard: prevent direct commits to main branch
5386
current_branch = run_git("rev-parse", "--abbrev-ref", "HEAD")
5487
if current_branch == "main":

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ __pycache__/
22
*.py[cod]
33

44
dist/
5+
audits/

ARCHITECTURE.md

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,27 @@ All filenames use ASCII characters only. Underscores separate words. No hyphens
8888
- `piece_federal-motorway-network.md` ✗ (hyphen not allowed)
8989
- `place_strasse_muenchen.md` ✗ (ü/ö/ä not allowed; use ascii equivalents or spell out)
9090

91-
The deployer (`scripts/deploy.py`) asserts uniqueness of basenames across the entire bundle and resolves all links by basename. Filename validation is enforced by `scripts/validate_general.py`.
91+
The deployer (`scripts/deploy.py`) asserts uniqueness of basenames across the entire bundle and resolves all links by basename.
92+
93+
---
94+
95+
## File Relationships
96+
97+
```mermaid
98+
erDiagram
99+
STATE ||--o{ ROAD : "references (Holds section)"
100+
STATE ||--o{ NODE : "references (Holds section, by state border)"
101+
ROAD ||--o{ NODE : "contains (km chain in Holds)"
102+
NODE }o--|| ROAD : "Owner: Place in road"
103+
NODE }o--|| STATE : "Owner: Place in state"
104+
```
105+
106+
Key constraints:
107+
- A node belongs to exactly one road and exactly one state.
108+
- A road spans 1..n states; a state contains 1..n roads.
109+
- State files list only the nodes within their own borders, not all nodes on a road.
110+
- Folder structure is the authority: `roads/<road>/` owns a node. State membership is declared in the node's `## Owner` block and must match what the state file lists in `## Holds`.
111+
- Sync failures (node listed in wrong state, node missing from state Holds, state backreference in road index pointing to wrong file) are validation errors.
92112

93113
---
94114

@@ -149,15 +169,6 @@ Subsection order follows the road's direction from its starting terminus (first
149169
* [km 348.0]: [Neubrandenburg-Ost](place_a20_39_neubrandenburg_ost.md)
150170
```
151171

152-
**Validation (STRICT):** `scripts/validate_roads.py` enforces:
153-
- Road index files have `Owner: - Project: Autobahn` only (no other items)
154-
- Multi-state roads have subsections by state
155-
- Each subsection has state name header and backreference
156-
- State backreferences are valid (files exist)
157-
- Kilometre sequences within states are strictly ascending
158-
- No cross-state entry mixing (all entries for one state must be in its subsection)
159-
- Entry format matches: `* [km X.X]: [Name](place_file.md)`
160-
161172
---
162173

163174
### Exit
@@ -330,10 +341,27 @@ The single author-facing rule: **every file basename in the world is unique**.
330341

331342
---
332343

344+
## States
345+
346+
The 16 federal state files live in `states/place_<state>.md`. Each state file is a Place that aggregates roads and their nodes.
347+
348+
**Owner** carries only `- Project: Autobahn`.
349+
350+
**Shown** is the state as experienced from the motorway network - landscape, approach, what the road reveals about the territory.
351+
352+
**Holds** is the road list. For each road the state contains, there is a subsection headed by the road link. Under each road, the state lists only the nodes within its own borders in kilometre order. Nodes in other states on the same road are not listed.
353+
354+
**Offers** is what the state's network makes available - connections, destinations, facts about density and coverage.
355+
356+
**Withheld** is what the motorway passes through but does not show - geography, cities, landmarks unreachable without leaving the road.
357+
358+
**Naming:** `states/place_<bundesland>.md` using the full lowercase German state name in ASCII (e.g. `place_schleswig_holstein.md`, `place_mecklenburg_vorpommern.md`).
359+
360+
---
361+
333362
## To document
334363

335364
- **Geographic coordinates** - each place node to carry latitude, longitude, and altitude (from OSM or BASt sources). Enables geographic validation: compass directions verified against bearing, distances against geodetic calculations, elevation changes detected. Lookup table vs. per-file embedding still open. Proposed: validate directions against bearing; validate distances against haversine; detect anomalies (altitude spikes, direction contradictions). Requires authoritative source identification and accuracy tolerance definition.
336-
- **State files** - the 16 federal state files in `states/`, their structure, subtitle tagline pattern, and how they aggregate roads and nodes. Needs its own `## State` chapter and `validate_states.py` script.
337365
- **Naming conventions in use** - CONVERTED: German infixes replaced with English (`_bruecke_``_bridge_`, `_raststaette_``_service_`). Road-tied stops (service/rest/roadhouse) now require road prefix: `place_{road}_service_*`, `place_{road}_rest_*`, `place_{road}_roadhouse_*`; optional exit numbers if official AS-number exists. ✅ Migration complete. Tunnel naming still pending.
338366
- **Navigation links placement** - FIXED: neighbour links (distance + direction markers) moved from `## Shown` to `## Holds` across 51 files (A1, A7, A20, A23, A24, A25, A210, A215). Validator `validate_navigation_links.py` enforces rule; all 187 files pass.
339367
- **Engine files** - `instructions.md`, `stack.md`, and the pieces in `engine/` (kilometerstein, driver seat, infotainment, etc.)

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ The world holds it. It does not resolve.
7575

7676
## How this is built
7777

78-
Authored by Kai Schlüter (ChBrain) with AI-assisted drafting. The per-file workflow is: a model proposes several drafts, the facts are checked against authoritative sources, then the final voice is rewritten by hand. The aim is to use facts (not copyrightable) carried in the author's own expression.
78+
Authored by Kai Schlüter (ChBrain) with AI-assisted drafting. The per-file workflow is: a model proposes several drafts, the facts are checked against authoritative sources, then the final voice is rewritten. The aim is to use facts (not copyrightable) carried in the author's own expression.
7979

8080
This is not an academic paper - the source list in [REFERENCES.md](REFERENCES.md) names the sources used most often, not all of them. If you spot a passage that closely paraphrases a specific source, or a factual error, please open an issue and link the source.
8181

REFERENCES.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Authored by Kai Schlüter (ChBrain) with AI-assisted drafting. The per-file work
1010

1111
The intent is to use facts (which are not copyrightable) carried in the author's own expression. Occasional close-paraphrase or factual drift may slip through; if you spot it, please open an issue and link the source.
1212

13-
`scripts/spotcheck_withheld.py` is a sampling helper for periodic review: it picks N random in-scope Withheld blocks (deterministic per seed) and prints them as a markdown brief with audit instructions. The audit itself is performed by whichever LLM session runs the script - no API key required.
13+
`scripts/validate_withheld.py` is a sampling helper for periodic review: it picks N random in-scope Withheld blocks (deterministic per seed) and prints them as a markdown brief with audit instructions. The audit itself is performed by whichever LLM session runs the script - no API key required.
1414

1515
---
1616

0 commit comments

Comments
 (0)