You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(clade): name every code, and stop the TSV reader eating empty fields (#50)
Two problems, both in how a `CLADE.a2ml` gets written. The second one
**defeats my own merged #48** — details below.
## 1. A code cannot express a wrong belief, so it cannot be checked for
one
CLADE-003 checks the code is one of the 12. It **cannot check the author
meant that clade** — every code is valid whatever you thought it stood
for. So these passed every gate:
| repo | wrote | believing | `pt`/`gv` actually mean |
|---|---|---|---|
| paint-type | `primary = "pt"` | "**P**ain**T**-type" | Protocols &
Interop (it is an image editor → `ap`) |
| gossamer | `primary = "gv"` | "**G**raphical/**V**isual" | Governance
& Standards (there is no graphical clade → `dx`) |
**The two letters abbreviate the CLADE's name. They never abbreviate the
REPO's name.** It is a closed taxonomy of categories, not an
abbreviation scheme — but nothing said so at the point of authoring, and
nothing could catch it.
### Fix: write the name beside the code, and check the pair
```toml
[clade]
primary = "ap"
primary-name = "Applications"
```
CLADE-006 (BLOCK, pre-commit) rejects any pair disagreeing with
`verisim/seed/clades.a2ml`. **The redundancy is the point** — the *pair*
can express the wrong belief, so the pair can be rejected. Verified on
all 10 cases, including both real historical errors:
```
ap|Applications PASS
dx|Developer Ecosystem PASS
gv|Governance & Standards PASS (ampersand survives)
pt|PainT-type FAIL <- the actual paint-type error
gv|Graphical/Visual FAIL <- the actual gossamer error
pt|Applications FAIL valid code, wrong name
ap|Protocols & Interop FAIL valid name, wrong code
zz|Applications FAIL invalid code
ap|<missing> FAIL cannot omit the name
UNASSIGNED|UNASSIGNED FAIL template default fails loudly
```
`clades.a2ml` and the spec now state the rule and name both real errors,
so the next author reads *why* before choosing. `deploy-clade-a2ml.sh`
emits `primary-name` and refuses to write an identity it cannot name.
## 2. The TSV reader collapsed empty fields — 153 files already
corrupted
**Tab is IFS whitespace**, so `IFS=$'\t' read` treats a run of tabs as
**one** delimiter: empty fields vanish and everything after shifts left.
**316 of 319** seed entries have an empty `parent` — this was the normal
case, not an edge case:
```
proven <tab> fv <tab> [] <tab> standalone <tab><tab> Formally verified… <tab> hyperpolymath
^^ empty parent collapses
-> parent="Formally verified…" description="hyperpolymath" owner=""
```
**The damage is real and committed — 153 CLADE.a2ml files** carry
`rationale = ""` with the repo's *description* sitting in `parent`:
```
panic-attack parent = "Security scanning tool — static analysis…"
flat-mate parent = "Flat/apartment sharing management…"
rpa-elysium parent = "Robotic Process Automation framework…"
live-files parent = "Live file synchronisation tool…"
```
### This defeated #48, and #48's own test could not see it
The `owner` support I added in #48 **never worked here**: `$7` was
always empty, so `owner` always fell back to `hyperpolymath` and an
explicit `owner = "metadatastician"` was ignored. #48's byte-identical
regression test passed because `export-json.sh` uses `awk -F'\t'`, which
does **not** collapse — the two derivation sites disagreed and only the
tested one was correct. My apologies: I shipped that.
### Fix
Translate tabs to US (`0x1f`) before reading. It is not IFS whitespace
so runs are not collapsed, it cannot occur in the data (0 occurrences in
`repos.a2ml`), and it is exactly what the ASCII unit separator is for.
The parser's TSV contract is unchanged.
## Verification
Scratch tree, end to end:
```
proven (empty parent — the 316-entry case)
rationale = "Formally verified safety library — Idris2 dependent types…" (was "")
parent = "" (was the description)
uuid = ffa8e1f5-… (unchanged, matches registry)
cadastra (owner = "metadatastician" in seed)
uuid = da97ea76-1715-5331-963b-27f011b10d22 <- correct; #48 works for the first time
primary-owner = "metadatastician"
```
Also: `repos.json` regenerates **byte-identical** (no uuid moves), both
a2ml files still parse as **TOML** (the dogfood gate uses `tomllib`),
and the spec renders under asciidoctor.
## Not in this PR
Repairing the **153 already-corrupted files** is a separate,
owner-facing job — this only stops the script producing more. Related:
#49.
Draft: this changes the clade contract for every repo, so it is yours to
review.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
0 commit comments