Chemenu 2.1.0 - deterministischer Wissenskompiler
CI / verify (push) Failing after 32s
Release / release (push) Successful in 38s

Chemenu kompiliert Rohnotizen zu einem verlinkten, quellengebundenen Wiki:
raw/ -> types/ + tools/ -> kb/ -> reports/. Was mechanisch ist, macht
tools/wikitool; was Urteil braucht, macht ein Agent unter Contracts, deren
Grenzen in Code durchgesetzt sind statt im Prompt.

Dieser Commit ist der Startpunkt der oeffentlichen Historie. Die vorherige
Entwicklung fand in einer privaten Instanz statt und ist nicht Teil dieses
Repositorys; ihre Erzaehlung steht vollstaendig in CHANGES.md, das mit 44
Eintraegen von 0.1.0 bis 2.1.0 erhalten geblieben ist.

Der mitgelieferte Korpus ist ein Testbett und eine Demo: 170 Seiten ueber den
Stack selbst - Gates, Lint, Versionierung, Suche, das Wiki-Muster. Er
dokumentiert das Werkzeug mit den eigenen Mitteln des Werkzeugs.

Lizenz: AGPL-3.0 fuer den Stack (tools/, types/), CC-BY-4.0 fuer die Inhalte.
Die Grenze zwischen beiden ist der Dateiplan, den dist export berechnet -
siehe NOTICE.
This commit is contained in:
2026-09-01 16:24:34 +02:00
commit 18ae28f918
368 changed files with 50628 additions and 0 deletions
@@ -0,0 +1,147 @@
# Conversation Transcript - Two Round-Trip Defects Found by an Ingest Session
> Source: Claude Code session (`claude-opus-5`), llm-wiki-test1 workspace
> Collected: 2026-08-31
> Participant: Torben
> Fidelity: **faithful summary transcript, not a verbatim log.** Command output and measured
> counts quoted below are real. The subagent's findings are **second-hand relative to this
> session** and were independently verified before being acted on - where that verification
> changed or extended the claim, the transcript says so.
> No credentials appeared in the session.
Covers two defects an ingest exposed, both fixed the same day: `cite add` deleting any content
behind the Footnotes block (`1.5.1`, `bb4123b`, issue #17) and a source page's reference arrays
being unreachable while `xref add` wrote a field the schema rejects (`1.6.0`, `ce03749`, issue
#18). Both were `prio/1`. Both had lived under a fully green test suite.
---
## Turn 1 - the ingest reports two tool defects
A subagent ingesting the `touch --set` transcript published successfully (`8524bce`) and then
reported two things it had run into. The assistant did **not** act on the report directly.
`SOUL.md` treats a confidently asserted fact as the cardinal error, and a subagent's finding is
second-hand; both claims were reproduced first.
### Verification of the first claim - and a hold
`split_cite_block()` was read directly. The mechanism was exactly as reported: everything from
the `## Fußnoten` heading to the end of file is taken as the block, only `[^id]:` lines are kept
from it, and every caller reassembles the page as `head + rendered block`.
A scan over the corpus then measured the exposure rather than estimating it: **8 pages carrying
74 lines** in the doomed position, `Detect-Repair Asymmetry` worst at 14.
**The second ingest was held at this point.** It would have called `cite add` on pages in that
list. Continuing would have destroyed content to save a few minutes.
### Verification of the second claim - and a correction of scope
`xref_link_source` was read: it writes only the target pages and never the source page's own
arrays. Confirmed. `types/source.md` declares `page_ref_fields: [entities, concepts]`, so the
`related:` that `xref add` had written was undeclared, and `strip_frontmatter_ref()` swept only
declared fields - so nothing could remove it. One command creating a state another could not
undo.
Both were filed as issues (#17, #18) before any code was touched, per
`instructions/capture-session.md`: what is still open belongs in the tracker, not in a
transcript or in someone's head.
---
## Turn 2 - "Korrigiere zunächst #17"
### The fix, and the option that was rejected
The block now ends at the **next heading** instead of at end of file. Everything after it - and
anything inside it that is not a citation definition - is folded back on to the head.
Two properties turned out to matter more than the repair itself:
- **The page self-heals.** Because the rendered block is always emitted last, the first citation
operation puts a page that had drifted into the broken layout back in order. `xref add` may
keep appending at end of file without doing harm - the contradiction between the two commands
is defused rather than merely avoided.
- **Loose text inside the block is rescued, not rejected.** The issue's own third acceptance
criterion asked for an abort. That was declined with a reason: the same code path runs under
`lint` and `corpus_diff`, where raising would refuse to *read* a page instead of reporting it.
Rescuing is strictly better than aborting and satisfies the intent - nothing is discarded
silently.
Reading the code added a third affected command the issue had not named: **`rename`** uses the
same path and would have deleted the same content. And a second loss path with the same cause -
a `[^id]` referenced only in a section *behind* the block counted as unreferenced, so `cite
sync` would have pruned its definition as an orphan.
### The test was proved red before it was trusted
Rather than asserting that the new test would have caught the defect, the old implementation was
reconstructed and run against it:
```
ALTER Code -> Beziehungen erhalten: False
NEUER Code -> Beziehungen erhalten: True
```
### Corpus repaired and measured
`cite sync --all` normalised eleven pages (the eight at risk plus three needing only a
re-ordering). Afterwards: **0 pages** with content behind the block, and per page an unchanged
count of citation definitions and bullets - checked, not assumed. The line-count asymmetry in
the diff came from `summary:` being re-wrapped on to one line, not from lost content.
---
## Turn 3 - "Mache mit 18 weiter"
Three defects, one cause.
**`xref link-source` writes both directions.** Which field a target lands in follows its
**collection**: `kb/entities/``entities:`, `kb/concepts/``concepts:`. The directory *is*
the field name, so a new collection needs no code change here - it needs a type declaring the
matching field. That was chosen over a type-to-field map precisely because a map is a second
copy of something the type-specs already say.
**`xref add` refuses an undeclared `related:`**, checking both pages before writing either, so a
refusal cannot leave half a link. The message names the fields the type does declare and the
command that fills them.
**`xref remove` sweeps undeclared leftovers**, with the field names taken from the type-specs
rather than a constant. An undeclared field that ends up empty is dropped outright: the key was
never valid for that type, and `related: []` would keep the page failing validation.
### The repair, done with the tool
No `rm --yes`, no hand-edited frontmatter. `xref remove` cleared the leftover, `xref
link-source` recorded both concepts in both directions. `lint` reports no schema error in the
corpus.
The referencing concept page came through the cycle **byte-identical** - `xref remove` cleared
its back-reference bidirectionally and `link-source` restored it exactly. That was the real
proof that the two commands are inverses.
---
## What the session concluded about itself
**The denylist shipped in `1.4.0` that morning was right; its pointer was not.** It refused
page-reference fields with "use `xref add` / `xref remove`" - an unverified claim about another
command's capabilities, and false for exactly the fields a source page has. A refusal that
routes to another command should ship with a test showing that command covers the case.
**Both defects lived under a fully green suite.** 678 tests passed before the `cite add` tests
were written; 67 gate tests passed before the counting change earlier the same day. In each case
no test had ever asserted the wrong behaviour, which is how it survived. The same finding
strengthens the premise of issue #8: a suite verifies what it knows about.
---
## Outcome
| Artifact | Result |
|---|---|
| Stack versions | `1.5.1` (PATCH), `1.6.0` (MINOR) |
| Commits | `bb4123b`, `ce03749` |
| Tests | 689 passing, in the normal and the hardened environment (11 new) |
| Corpus | 8 pages de-risked and normalised; the schema error on `main` repaired |
| Gitea | #17 and #18 closed |