feat: Link-Taxonomie u5 - Restkanten gelabelt, migrate done 4.0.0, Workshop geschlossen
CI / verify (push) Successful in 51s
CI / verify (push) Successful in 51s
Files changed: - .wikitool-kb.json - kb/entities/technologies/Arch Linux.md - kb/entities/technologies/Disk Encryption.md - kb/entities/technologies/Wine-Staging.md - kb/entities/tools/AUR.md - kb/entities/tools/GPG.md - kb/entities/tools/Lutris.md - kb/entities/tools/NotebookLM.md - kb/entities/tools/Obsidian.md - kb/entities/tools/OpenAI Codex.md - kb/entities/tools/OpenCode.md - kb/entities/tools/Pi.md - kb/entities/tools/Proton.md - kb/entities/tools/Steam.md - kb/entities/tools/Wine.md - kb/entities/tools/gdeploy.md - kb/entities/tools/makepkg.md - kb/entities/tools/pascalandy schema.md - kb/log.md - work/link-taxonomy-migration/README.md - work/link-taxonomy-migration/glossary.md - work/link-taxonomy-migration/plan.md
This commit is contained in:
@@ -1,106 +0,0 @@
|
||||
# Workshop: link-taxonomy-migration
|
||||
|
||||
- **Run key:** `link-taxonomy-migration` (this directory's name - there is no other identifier)
|
||||
- **Input:** none - this run is not an ingest
|
||||
- **Started:** 2026-09-02
|
||||
- **Session id form:** `WIKITOOL_SESSION_ID="link-taxonomy-migration/u<N>"`, one per unit
|
||||
- **Issue:** Gitea #40, sections *Label werden Enum* and *Toolgeführte Blöcke*
|
||||
|
||||
## Goal
|
||||
|
||||
Move every relationship in `kb/` from free-text German prose in a body bullet to a machine
|
||||
value in `related:`, and every tool-owned body region from heading-matching to a marker pair.
|
||||
Afterwards the compiler contains no heading text and no relationship label, and `lint` can
|
||||
enforce the vocabulary because there is one.
|
||||
|
||||
## Why this is `assisted` and not `mechanical`
|
||||
|
||||
Measured on 2026-09-02, against the corpus rather than against the documentation:
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Pages | 180 |
|
||||
| Distinct relationship labels in body bullets | **152** |
|
||||
| Labelled bullets | 337 |
|
||||
| Labels occurring exactly once | 102 |
|
||||
| Top 20 labels cover | 167 of 337 |
|
||||
| Bare `- [[X]]` bullets under `## Siehe auch` | 555 |
|
||||
| ...of those, provably redundant (a labelled edge already exists) | 353 |
|
||||
| ...of those, the only connection between the two pages | **202**, across 63 target pages |
|
||||
|
||||
`kb/CONVENTIONS.md` documents thirteen labels. Nothing ever checked that, and the corpus does
|
||||
not follow it - so there is no mapping table to apply, and roughly 539 edges need a judgment
|
||||
call each. A large minority are reverse directions (`Verwendet von` 20x, `implementiert durch`,
|
||||
`Ersetzt durch`), which under authored directional edges are exactly the edges that stop being
|
||||
stored and start being rendered.
|
||||
|
||||
Rejected alternative, recorded so it is not re-proposed: map the top 20 mechanically and set
|
||||
everything else to `see-also`. That would start the new taxonomy with ~370 of ~539 edges on its
|
||||
weakest label - the `verwandt mit` sediment this whole change exists to end, re-created as the
|
||||
documented initial state.
|
||||
|
||||
## Closes when
|
||||
|
||||
Every unit in `plan.md` is published, and:
|
||||
|
||||
- `wikitool lint` reports zero unlabelled edges and zero labels outside the authorising
|
||||
collection's `outbound:` block
|
||||
- `wikitool migrate verify --from <pre-migration rev>` reports no wikilink or citation count
|
||||
change, and no unbalanced marker
|
||||
- `wikitool migrate done 4.0.0 --pages <N>` has run
|
||||
|
||||
## Checklist
|
||||
|
||||
- [x] u0 mechanism - taxonomy, `links.py`, `blocks.py`, `xref` rewrite, lint checks,
|
||||
`links show` for the inbound view, deletion of the matching layer. No page touched.
|
||||
- [x] u1 `kb/entities/` (systems, tools, technologies) - 57 pages, 199 edges, run as five
|
||||
sub-sessions (`u1`, `u1-technologies`, `u1-technologies-2`, `u1-tools-1`, `u1-tools-2`,
|
||||
`u1-close`) against one 60-call-per-session ceiling; published together as commit
|
||||
`b137359`. Deferred cross-collection edges recorded in `glossary.md` for u2/u3.
|
||||
- [x] u2 `kb/entities/` (projects, people) + `kb/comparisons/` - 16 pages, ~45 edges, single
|
||||
session (`link-taxonomy-migration/u2`, closed as `u2-close`). Discovered comparisons pages
|
||||
carry no `related:` field at all (only `entities:`, unlabelled by the type spec); labelled
|
||||
the prose by hand instead. Confirmed taxonomy gap for person-authored/extended
|
||||
relationships, resolved as `see-also` throughout - see `glossary.md`.
|
||||
- [x] u3 `kb/concepts/` - 80 pages, ~250 edges, run as seven sub-sessions (`u3`, `u3-b2`..`u3-b7`,
|
||||
close `u3-close`) against the 60-call ceiling, including one gate-forced pause mid-batch
|
||||
resumed with explicit user approval. Two self-caught defects: 14 pages left unlabelled
|
||||
after a wrong "already covered elsewhere" call (fixed via `lint --full`'s unlabelled-edges
|
||||
report), and one real content loss - a cited, substantive `Verwandte Concepts` line deleted
|
||||
alongside a bare wikilink during prose cleanup, caught by `migrate verify`'s `cite-refs`
|
||||
diff and restored. Published as commit `a35c94e`. See `glossary.md` for the
|
||||
add-is-safe/remove-is-risky mechanism note this unit established.
|
||||
- [x] u4 `kb/sources/` - zero page edits needed. `types/source.md` declares no `related:` field
|
||||
(only `entities:`/`concepts:`, same structural gap as comparisons), and all 27 source pages
|
||||
already had those fields correctly populated via `xref link-source` at ingest time - there
|
||||
was never an unlabelled edge here to fix. `migrate verify --from 177c7e9 --path kb/sources`:
|
||||
0 findings. No commit, no session id spent beyond the check itself. See `glossary.md`.
|
||||
- [ ] u5 close-out - `migrate done`, version bump, `CHANGES.md`, workshop close
|
||||
|
||||
## Measured after u0
|
||||
|
||||
`lint` against the corpus, with the machinery in place and no page touched:
|
||||
|
||||
| Finding | Count |
|
||||
|---|---|
|
||||
| `unlabelled_edges` | **480** - every `related:` entry, since none carries a label yet |
|
||||
| `unauthorised_labels` | 0 - nothing declares a label at all, so nothing can be unauthorised |
|
||||
| `malformed_edges` | 0 |
|
||||
| `unbalanced_markers` | 0 |
|
||||
| `orphan_pages` | 1 (`GRUB`, pre-existing) |
|
||||
| `broken_links`, `dangling_frontmatter_refs`, `schema_validation_errors` | 0 |
|
||||
|
||||
480 is the number u1-u4 have to bring to zero. It is larger than the 337 labelled body bullets
|
||||
because `related:` also holds entries whose bullet was lost or never written - which is itself a
|
||||
finding: the frontmatter and the body had already drifted apart under the old model, and nothing
|
||||
could see it while the label lived only in the prose.
|
||||
|
||||
## Open decisions
|
||||
|
||||
- **Settled 2026-09-02:** edges are directional; the reverse edge is authored only when it is a
|
||||
primary statement on its own page. The inbound view is rendered, not stored.
|
||||
- **Settled 2026-09-02:** the 353 provably-redundant `## Siehe auch` edges are dropped
|
||||
mechanically. The 202 that are the only connection get a real label each, or are dropped with
|
||||
a reason - never converted to `see-also` in bulk.
|
||||
- **Settled 2026-09-02:** labels are not localized. `- **depends-on:** [[Hermes]]` is what a
|
||||
German page carries.
|
||||
@@ -1,114 +0,0 @@
|
||||
# Glossary: link-taxonomy-migration
|
||||
|
||||
Vocabulary decided while processing one page, carried forward so u3 (concepts) and u2
|
||||
(projects/people/comparisons) do not re-decide it. Add to this file before dispatching the next
|
||||
unit or sub-session.
|
||||
|
||||
## Mechanism correction, discovered in u3 (concepts): `xref add` is always safe
|
||||
|
||||
`xref add --a A --b B --rel X` **only ever touches page A** - it upserts (idempotent by target),
|
||||
so calling it on a pair that already has an unlabelled or even a differently-labelled entry just
|
||||
relabels it in place. `xref remove` is the only bidirectional, destructive call (strips the pair
|
||||
from **both** pages' `related:` and matching body lines). u1 already learned to sequence removes
|
||||
before adds per pair; u3 goes further and mostly **stops calling `xref remove` at all** for
|
||||
drift-only entries. Standing policy for the rest of this migration: when a frontmatter `related:`
|
||||
entry does not deserve its most literal label, relabel it with the best authorised fit - `see-also`
|
||||
if truly nothing fits - via `xref add`, rather than removing it. Only remove when the entry is a
|
||||
misplaced mention with nothing worth keeping on either side, and only after confirming (grep) that
|
||||
the target page carries no reciprocal reference that a bidirectional strip would destroy. This
|
||||
avoided several near-misses in u3 (`CPPC`/`amd-pstate` already carried `amd-pstate implements
|
||||
CPPC` from u1 - removing would have destroyed it; relabelled as `CPPC mechanism amd-pstate`
|
||||
instead).
|
||||
|
||||
## Unit sizing correction (2026-09-02)
|
||||
|
||||
u1 as written in `plan.md` (`kb/entities/systems, tools, technologies`, estimated ~45 pages) is
|
||||
actually **57 pages carrying 199 `related:` entries** (systems 6/19, technologies 20/69,
|
||||
tools 31/111). At one `wikitool` call per edge (no bulk mode exists for `xref add`/`xref
|
||||
remove`), that is far past the 60-call session ceiling. Decided with the user: run u1 as planned
|
||||
in scope (all three areas, one eventual publish), but as **per-area sub-sessions**, each under
|
||||
its own `WIKITOOL_SESSION_ID`, holding `index rebuild`/`lint`/`log append`/`publish` until every
|
||||
area is done:
|
||||
|
||||
- `link-taxonomy-migration/u1` - systems (done, see below)
|
||||
- `link-taxonomy-migration/u1-technologies` - technologies
|
||||
- `link-taxonomy-migration/u1-tools` - tools
|
||||
|
||||
## Recurring pattern: reverse-reading edge, correct statement already elsewhere
|
||||
|
||||
Several old bullets read true only backwards, and the *correct* forward statement already exists
|
||||
(as still-unmigrated prose) on the other page - sometimes in a collection this unit does not
|
||||
touch. Rule applied: drop the backward one from the current page's `related:` (via `xref
|
||||
remove`, so it stops showing as an unlabelled edge) and note the correct edge here for whichever
|
||||
unit owns the other page. Never invert the label to fake the direction.
|
||||
|
||||
Deferred edges for later units, discovered while processing systems:
|
||||
|
||||
- **u3 (concepts):** `Denylist over Allowlist` invokes-or-operates-on `AGENTS.md` (its own body
|
||||
already says "beruft sich auf: AGENTS.md" - pick the label when concepts' outbound set is in
|
||||
front of you).
|
||||
- **u3 (concepts):** `LLM Wiki Pattern` derived-from-or-abstracted-from `Memex` (Memex's old
|
||||
"Geistiger Vorgänger von" bullet reads backwards from Memex's side).
|
||||
- **u2 (people):** `Vannevar Bush` owns `Memex` (Memex's "Erfunden von" bullet is `owns`'s
|
||||
unlabelled inverse; `owns` has no catalogue inverse, so it must be authored from Bush's page).
|
||||
- **u2 (people):** `E3DC GmbH` owns `E3DC` (same reasoning: `owns` has no inverse to assert from
|
||||
the owned entity's side).
|
||||
- **u2 (projects):** no action needed on `ha-core`/`hacs-e3dc` - E3DC's page independently
|
||||
asserts `required-by` (a real pair with a genuine inverse), which already covers the
|
||||
relationship without needing anything written on the project pages.
|
||||
|
||||
## Label choices worth reusing
|
||||
|
||||
- A file that is normative *because* a tool enforces it (`AGENTS.md` vs. `wikitool`) is
|
||||
`depends-on`, not `implements`/`mechanism` - those realization labels are entities-to-concepts
|
||||
only, and these pages are both entities.
|
||||
- An optional dependency that the source tolerates the absence of (`CLAUDE.md`'s `@ENVIRONMENT.md`
|
||||
import) is `uses`, not `depends-on` - the catalogue's own test ("does removing the target break
|
||||
this thing?") answers no.
|
||||
- A root file that another root file's own prose defines the rules for (`AGENTS.md` defines what
|
||||
`ENVIRONMENT.md` is and is allowed to contain) is `owns` from the defining page, not asserted
|
||||
back from the defined one (no inverse exists).
|
||||
- A hardware/software pairing where the dependent side is a specific integration package, not the
|
||||
general platform (E3DC vs. `ha-core`/`hacs-e3dc` vs. Home Assistant broadly): assert
|
||||
`required-by` from the depended-upon entity's page, and do not manufacture an edge to the broad
|
||||
platform if no specific claim holds there.
|
||||
- A device supporting a communication standard: `implements` reads fine even outside pure
|
||||
software (E3DC implements Modbus).
|
||||
- Two entities in the same wiki cited as parallel real-world examples of the same concept, with
|
||||
no sharper label fitting: `see-also` is correct and not a cop-out (Memex/Tolkien Gateway).
|
||||
- **Taxonomy gap, confirmed while processing u2 (people):** there is no "created by" / "authored"
|
||||
/ "extends the work of" label for a person-entity pointing at another entity or at a concept.
|
||||
`owns` covers a person being *accountable for* an entity going forward (used for `Vannevar
|
||||
Bush owns Memex`, `Rohit Gupta owns Agent Memory`, `E3DC GmbH owns E3DC`), but a one-time
|
||||
historical act of creating/originating a *concept* (Karpathy authoring the LLM Wiki Pattern,
|
||||
Bush originating Memex-the-idea) or of one person's work building on another's (Gupta extending
|
||||
Karpathy) has nothing in Realization or Lineage that is authorised for a person: those
|
||||
registers are concept-to-concept or concept-to-entity, never entity-to-entity or
|
||||
entity-to-concept for authorship. Resolved as `see-also` in every such case on Karpathy's,
|
||||
Gupta's and Bush's own pages, checked against every register first - not a stretch, a genuine
|
||||
gap. Worth proposing a label (`originates`/`authored-by`?) if this recurs in u3/u4.
|
||||
- **`kb/sources/` pages carry no `related:` field either, same as comparisons.**
|
||||
`types/source.md` declares only `page_ref_fields: [entities, concepts]` - `xref add` refuses
|
||||
there with the identical "type does not declare a related: field" error. Unlike comparisons,
|
||||
though, there is nothing left to migrate by hand: every one of the 27 source pages already had
|
||||
`entities:`/`concepts:` correctly populated via `xref link-source` at ingest time, and their
|
||||
prose "Verwandte Entities"/"Verwandte Concepts" sections already just mirror those fields -
|
||||
there was never a labelled-vs-unlabelled distinction to fix here. `migrate verify --from
|
||||
177c7e9 --path kb/sources` returns 0 findings against baseline. u4 closes with zero page edits.
|
||||
- **comparisons pages carry no `related:` field at all.** `types/comparison.md` declares only
|
||||
`entities` (`page_ref_fields: [entities]`) - unlabelled by the schema, like `sources:`. `xref
|
||||
add`/`xref remove` refuse on this type ("type does not declare a related: field"). The
|
||||
`compares-with` label from `kb/comparisons/COLLECTION.md`'s `outbound:` block is documentational
|
||||
only for this type: it is written into the `## Beziehungen` prose by hand (there is no marker
|
||||
region either), never into machine data. Confirmed on `amd-pstate vs acpi-cpufreq.md`.
|
||||
- A dependent-side project whose own page only names the platform vaguely ("Kernintegrationsbibliothek
|
||||
für E3DC-Systeme") while a specific downstream package (a HACS component, an automation
|
||||
blueprint) explicitly wraps it: assert `required-by` from the depended-upon project's page for
|
||||
each specific downstream package, mirroring `depends-on` asserted on each dependent's own page -
|
||||
the same genuine two-sided pair as `E3DC`/`ha-core` from u1, one level up the stack
|
||||
(`ha-core`/`hacs-e3dc`, `ha-core`/`hacs-integration-blueprint`).
|
||||
- An external, out-of-wiki reference project cited only as "look how someone else solved this" (a
|
||||
GitHub repo mentioned as a structural analogue, no functional dependency): `see-also` asserted
|
||||
from the external project's own page toward the project it inspired, not the reverse - matches
|
||||
"reads correctly from the source page" even though nothing here is a stretch, just weak by
|
||||
nature (`wiki-skills`, `wiki-skills-vanillaflava`, `llm-wiki-skills` -> `Chemenu`).
|
||||
@@ -1,48 +0,0 @@
|
||||
# Plan: link-taxonomy-migration
|
||||
|
||||
One unit is one session id and one `publish`, sized against the 60-call iteration budget.
|
||||
Per-page cost here is roughly `1 touch` + the edges on it; the corpus-wide commands
|
||||
(`index rebuild`, `sources rebuild-index`, `log append`, `publish` twice for the gate) are
|
||||
per unit, not per page. That puts the ceiling near 45 pages and the target at 40.
|
||||
|
||||
| # | Unit | Pages | Job | Done when |
|
||||
|---|------|------:|-----|-----------|
|
||||
| u0 | mechanism | 0 | Taxonomy catalogue, `links.py`, `blocks.py`, `outbound:` in every `COLLECTION.md`, `xref` rewritten to one directional edge, lint checks, `links show` for the inbound view, `migrate verify` marker invariant, deletion of `sections.py` and the matching layer | Suite green; `lint` reports the corpus's unlabelled edges as findings rather than crashing |
|
||||
| u1 | `kb/entities/systems`, `tools`, `technologies` | ~45 | Label every edge, drop redundant see-also, wrap markers | `migrate verify --path kb/entities --fail-on-error` clean |
|
||||
| u2 | `kb/entities/projects`, `people`, `kb/comparisons` | ~40 | as u1 | as u1 |
|
||||
| u3 | `kb/concepts` | ~45 | as u1 | `migrate verify --path kb/concepts --fail-on-error` clean |
|
||||
| u4 | `kb/sources` | ~50 | as u1, plus `entities:`/`concepts:` on source pages | `migrate verify --path kb/sources --fail-on-error` clean |
|
||||
| u5 | close-out | 0 | `migrate done 4.0.0`, `version bump --major`, `CHANGES.md` body, promote nothing, close workshop | `docs verify` + `lint --fail-on-error` green, workshop deleted |
|
||||
|
||||
Unit boundaries are written down here *before* the run so that publishing several units
|
||||
together stays a planned batch rather than a way around a Mass-Update Gate refusal - see
|
||||
`instructions/gates.md`.
|
||||
|
||||
## Per-page procedure
|
||||
|
||||
1. Read the page's `## Beziehungen` and `## Siehe auch` blocks.
|
||||
2. For each labelled bullet: say the sentence `[this page] <label> [target]`. Pick the catalogue
|
||||
label that makes it true. If it only reads true backwards, the edge belongs on the other
|
||||
page - move it, do not invert the label into something the catalogue does not have.
|
||||
3. For each bare `## Siehe auch` bullet: drop it if a labelled edge already connects the pair
|
||||
(the tooling lists these). Otherwise decide - a real label, or dropped with the reason
|
||||
recorded in the unit's notes.
|
||||
4. Write the edges with `xref add --rel`, never by hand.
|
||||
5. The body blocks are then *generated*: no hand-editing inside a marker pair.
|
||||
|
||||
## Vocabulary carried between units
|
||||
|
||||
`glossary.md` in this directory. A mapping decided in u1 and re-decided in u3 is the failure the
|
||||
file exists to prevent - add to it **before** dispatching the next unit.
|
||||
|
||||
## Deliberately excluded from this run
|
||||
|
||||
- **Commonplace's articulation test and the `connect` report workflow.** They change how ingest
|
||||
proposes links, not how links are stored. Separate question, separate issue.
|
||||
- **Promoting the lint checks to hard errors.** During this run an unlabelled edge is a finding,
|
||||
because that is precisely the migration window `.wikitool-kb.json` exists to represent. The
|
||||
promotion is a later version's change, once the corpus can pass it.
|
||||
- **`sources:` and `[^cite-id]`.** The provenance path is unlabelled by construction and is not
|
||||
part of the link taxonomy.
|
||||
- **Any change to page prose.** This run restates relationships in a new form; it learns
|
||||
nothing new, and a body edit outside a marker pair is out of scope.
|
||||
Reference in New Issue
Block a user