feat: INSTALL.md is the English installation tutorial; new tutorial docs/tutorials/first-source-to-first-answer.md with a shipped sample source; README.md links it as its first-ingestion step (#191)
CI / verify (push) Successful in 6m14s
CI / pwsh (push) Successful in 2m2s
Release / release (push) Successful in 34s

Files changed:
- CHANGES.md
- INSTALL.md
- README.md
- VERSION
- docs/reference/commands/types-instructions-and-docs.md
- docs/tutorials/README.md
- docs/tutorials/first-source-to-first-answer.md
- docs/tutorials/sample-source.md
- instructions/dev/doc-pull-through.md
- tools/CONTRACT.md
- tools/chemenu/commands/docs_verify.py
- tools/chemenu/install_doc.py
- tools/chemenu/tests/test_install_doc.py

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SnAJ7Z3CpVD3PRbN73QtU2
This commit is contained in:
torbenandClaude Opus 5.5 committed 2026-10-07 06:38:40 +02:00
1 parent f9056c04f7
commit fe1de63e0f
13 files changed
+403 -190

No files matched your search

+6 -1
View File
@@ -14,7 +14,7 @@ place only: `instructions/dev/version-parts.md` § The candidate model.
--- ---
## 9.0.0-beta.6 - 2026-10-06 - docs/: how-to guides, configuration reference and two explanation pages carved out of README.md, INSTALL.md, INSTALL-MCP.md and EVALS.md; the last two retired ## 9.0.0-beta.7 - 2026-10-07 - INSTALL.md is an English installation tutorial; new tutorial from a first source to a first answer with a shipped sample; README.md a landing page
**Author:** Torben Nehmer **Author:** Torben Nehmer
@@ -31,6 +31,7 @@ place only: `instructions/dev/version-parts.md` § The candidate model.
- docs reference: human command reference under docs/reference/, generated from the command records - docs reference: human command reference under docs/reference/, generated from the command records
- docs reference: skill catalogue and page types under docs/reference/, generated from the shipped defaults in the origin repo only - docs reference: skill catalogue and page types under docs/reference/, generated from the shipped defaults in the origin repo only
- docs/: how-to guides, configuration reference and two explanation pages carved out of README.md, INSTALL.md, INSTALL-MCP.md and EVALS.md; the last two retired - docs/: how-to guides, configuration reference and two explanation pages carved out of README.md, INSTALL.md, INSTALL-MCP.md and EVALS.md; the last two retired
- INSTALL.md is an English installation tutorial; new tutorial from a first source to a first answer with a shipped sample; README.md a landing page
**Low impact** **Low impact**
- version bump: Abschlussmeldung nennt Stichpunkt oder Themenabsatz statt pauschal Prosa - version bump: Abschlussmeldung nennt Stichpunkt oder Themenabsatz statt pauschal Prosa
@@ -38,6 +39,10 @@ place only: `instructions/dev/version-parts.md` § The candidate model.
- tools/README.md module tree names reference_doc.py and the fourth view cli_contract renders - tools/README.md module tree names reference_doc.py and the fourth view cli_contract renders
<!-- /wikitool:bumps --> <!-- /wikitool:bumps -->
### Tutorials: installation in English, and a first source to a first answer (#191)
`INSTALL.md` stays at the root and is now the English installation tutorial, the first one `docs/tutorials/README.md` lists; its generated prerequisites lists and `setup-question` markers are unchanged, and `docs verify`'s finding for a missing question names the English section "What the agent asks you". The new `docs/tutorials/first-source-to-first-answer.md` walks a fresh instance through one ingest and two questions, one the wiki answers with citations and one it has no source for, using `docs/tutorials/sample-source.md`, a short made-up note that ships with every instance. `README.md`'s "Your first ingestion" is a link to it, which finishes `README.md` as a landing page.
### The root documents split into `docs/` pages (#190) ### The root documents split into `docs/` pages (#190)
The task and explanation parts of `README.md`, `INSTALL.md`, `INSTALL-MCP.md` and `EVALS.md` are now single English pages: eleven how-to guides under `docs/how-to/` (ingest, capture, guideline export, query, maintenance, weekly review, Obsidian, updating an instance, troubleshooting, the MCP read server, tracing and scoring sessions), a hand-written `docs/reference/configuration.md`, and `docs/explanation/architecture.md` and `telemetry-and-evaluation.md`. A guide says what to prepare, what to tell the agent and where it stops; it links an agent's procedure instead of retelling it. `INSTALL-MCP.md` and `EVALS.md` are gone from the root and from `dist export`, so an upgrade removes them as retired; `README.md` is a landing page, and `INSTALL.md` keeps only the installation itself. Pointers in messages and command records, among them `version check`'s, name the new pages. The task and explanation parts of `README.md`, `INSTALL.md`, `INSTALL-MCP.md` and `EVALS.md` are now single English pages: eleven how-to guides under `docs/how-to/` (ingest, capture, guideline export, query, maintenance, weekly review, Obsidian, updating an instance, troubleshooting, the MCP read server, tracing and scoring sessions), a hand-written `docs/reference/configuration.md`, and `docs/explanation/architecture.md` and `telemetry-and-evaluation.md`. A guide says what to prepare, what to tell the agent and where it stops; it links an agent's procedure instead of retelling it. `INSTALL-MCP.md` and `EVALS.md` are gone from the root and from `dist export`, so an upgrade removes them as retired; `README.md` is a landing page, and `INSTALL.md` keeps only the installation itself. Pointers in messages and command records, among them `version check`'s, name the new pages.
+136 -136
View File
@@ -1,27 +1,27 @@
# Installation # Install a Chemenu instance
Dieses Dokument richtet sich an Menschen. Es gibt genau einen Weg zu einer Chemenu-Instanz: Ein This tutorial takes you from an empty folder to a running Chemenu instance. There is exactly one
Agent installiert das **neueste Release** in ein leeres Verzeichnis, das du vorgibst. Die way to get one: an agent installs the **latest release** into an empty folder you choose. The
Schritte führt der Agent aus, nach `instructions/setup-instance.md` aus demselben Release. Hier agent runs the steps, following `instructions/setup-instance.md` from that same release. This
steht, was du vorher bereitstellst, welchen Satz du ihm gibst, was er dich fragt und was zu tun page covers what you prepare beforehand, the sentence you give the agent, what it asks you, and
ist, wenn er anhält. Die vollständige Kommandoreferenz steht in what to do when it stops. The full command reference is in
[tools/CONTRACT.md](tools/CONTRACT.md). [tools/CONTRACT.md](tools/CONTRACT.md).
Den optionalen **MCP-Leseserver** richtet The optional **MCP read server** is set up separately, once the instance runs:
[docs/how-to/set-up-the-mcp-server.md](docs/how-to/set-up-the-mcp-server.md) ein: derselbe [docs/how-to/set-up-the-mcp-server.md](docs/how-to/set-up-the-mcp-server.md). It serves the same
Korpus, lesend, für einen Konsumenten, der kein Terminal auf dieser Maschine ist. corpus, read-only, to a consumer that is not a terminal on this machine.
<!-- dist:strip-start --> <!-- dist:strip-start -->
Wer am Stack selbst arbeiten will, klont dieses Repo. Das ist eine Entwicklungsumgebung mit To work on the stack itself, clone this repository instead. That is a development checkout with a
Demo-Korpus und keine Instanz; sie steht in [docs/dev/development.md](docs/dev/development.md). demo corpus, not an instance; it is described in [docs/dev/development.md](docs/dev/development.md).
<!-- dist:strip-end --> <!-- dist:strip-end -->
## Was vorher da sein muss ## What you need first
Diese Programme prüft der Preflight, bevor irgendein `wikitool`-Befehl läuft. Installieren musst The preflight checks these programs before any `wikitool` command runs. You install them
du sie selbst - der Agent tut es nie, auch nicht mit deiner Zustimmung. Wo eines fehlt, nennt yourself - the agent never does, not even with your permission. Where one is missing, the
der Preflight den Installationsbefehl für dein System. Die Liste wird aus preflight names the install command for your system. The list is generated from
`tools/prerequisites.txt` erzeugt, derselben Datei, die der Preflight liest: `tools/prerequisites.txt`, the same file the preflight reads:
<!-- wikitool:prerequisites --> <!-- wikitool:prerequisites -->
- **Python** ≥ 3.11 - **Python** ≥ 3.11
@@ -29,166 +29,166 @@ der Preflight den Installationsbefehl für dein System. Die Liste wird aus
- **ripgrep (rg)** - **ripgrep (rg)**
<!-- /wikitool:prerequisites --> <!-- /wikitool:prerequisites -->
Dazu: You also need:
- **Ein Agent-Harness**: Claude Code, GitHub Copilot (in VS Code oder als CLI), Codex CLI oder - **An agent harness**: Claude Code, GitHub Copilot (in VS Code or as a CLI), Codex CLI or
Mistral Vibe. Mistral Vibe.
- **Ein leeres Verzeichnis**, in dem die Instanz liegen soll, und dein Harness darin geöffnet. - **An empty folder** for the instance, with your harness opened in it. Empty means nothing but a
Leer heißt: nichts außer einem `.git`. Ein frisch geklontes, leeres Repo für deine Instanz ist `.git`. A freshly cloned, empty repository for your instance is exactly right: if your
also genau richtig - liegt dein Repo `torben/nathan` etwa in `~/src/nathan`, installierst du repository `torben/nathan` lives in `~/src/nathan`, install there, and the agent keeps its
dorthin, und der Agent übernimmt dessen `origin` als Ziel für `publish`. `origin` as the target for `publish`.
Unter Windows zusätzlich, ebenfalls vom Preflight geprüft: On Windows, additionally, also checked by the preflight:
<!-- wikitool:prerequisites-windows --> <!-- wikitool:prerequisites-windows -->
- **PowerShell 7 (pwsh)** ≥ 7 - **PowerShell 7 (pwsh)** ≥ 7
<!-- /wikitool:prerequisites-windows --> <!-- /wikitool:prerequisites-windows -->
Und außerdem: And on Windows also:
- **PowerShell 7 als Standardterminal in VS Code.** Windows PowerShell 5.1 reicht nicht, und WSL - **PowerShell 7 as the default terminal in VS Code.** Windows PowerShell 5.1 is not enough, and
ist nicht vorgesehen. WSL is not supported.
- **Execution Policy `RemoteSigned`** - auf vielen Rechnern ab Werk gesetzt - **Execution policy `RemoteSigned`** - the factory setting on many machines
(`Get-ExecutionPolicy -List` zeigt es). (`Get-ExecutionPolicy -List` shows it).
- **Git for Windows.** Es bringt Git Bash mit, in dem Claude Code seine Befehle ausführt. - **Git for Windows.** It brings Git Bash, which Claude Code runs its commands in.
- **Ein Installationsverzeichnis mit höchstens 95 Zeichen**, zum Beispiel `C:\Chemenu`. Windows - **An installation folder of at most 95 characters**, for example `C:\Chemenu`. Without long
erlaubt ohne eingeschaltete lange Pfade nur 259 Zeichen je Pfad, und die Dateien des Wikis paths switched on, Windows allows only 259 characters per path, and the wiki's files need the
brauchen den Rest. Wer Administratorrechte hat, kann stattdessen lange Pfade einschalten rest. If you have administrator rights you can switch long paths on instead
(`LongPathsEnabled`); verlangt wird das nicht. (`LongPathsEnabled`); that is not required.
## Der Satz für den Agenten ## The sentence for the agent
Öffne das leere Verzeichnis in deinem Harness und gib dem Agenten diesen Satz: Open the empty folder in your harness and give the agent this sentence:
> Richte in diesem Verzeichnis eine neue Chemenu-Instanz ein. Hol dazu das neueste Release von > Set up a new Chemenu instance in this folder. Fetch the latest release from
> `https://gitea.nehmer.net/api/v1/repos/torben/chemenu/releases/latest` und folge dessen Asset > `https://gitea.nehmer.net/api/v1/repos/torben/chemenu/releases/latest` and follow its asset
> `setup-instance.md`. Lies vor dem Start des Preflights das Asset `preflight.md` aus demselben > `setup-instance.md`. Before you start the preflight, read the asset `preflight.md` from the same
> Release. > release.
Damit liest der Agent die Beschreibung des neuesten Releases und daraus die beiden Anleitungen. With that, the agent reads the description of the latest release, and from it the two
Dann lädt er das passende Preflight-Skript (`preflight.ps1` für PowerShell, `preflight.sh` für instructions. It then downloads the matching preflight script (`preflight.ps1` for PowerShell,
eine POSIX-Shell) mit einem Befehl seiner Shell ins Verzeichnis - nicht über den Browser, damit `preflight.sh` for a POSIX shell) into the folder with a command of its shell - not through the
Windows die Datei nicht als „aus dem Internet“ markiert - und startet es. Das Skript lädt den browser, so that Windows does not mark the file as "from the internet" - and runs it. The script
Tarball desselben Releases, prüft dessen sha256, entpackt ihn in das Verzeichnis, löscht sich downloads the tarball of the same release, checks its sha256, unpacks it into the folder, deletes
selbst und prüft dann im entpackten Baum, ob alles da ist. itself, and then checks in the unpacked tree that everything is in place.
Die Liste aller Releases: <https://gitea.nehmer.net/torben/chemenu/releases>. Das Repo ist All releases are listed at <https://gitea.nehmer.net/torben/chemenu/releases>. The repository is
öffentlich; der Download braucht weder Konto noch Token. public; the download needs neither an account nor a token.
## Was der Agent dich fragt ## What the agent asks you
Raten darf der Agent keine dieser Antworten, und keine übernimmt er aus einem anderen Repo: The agent may guess none of these answers, and it carries none of them over from another
repository:
- <!-- setup-question: identity --> **Autor-Identität** - Name und E-Mail für `git config`. Das ist - <!-- setup-question: identity --> **Author identity** - name and email for `git config`. This is
zugleich der Autorname jeder künftig angelegten Wiki-Seite (`$WIKI_AUTHOR` überschreibt ihn bei also the author name of every wiki page created from now on (`$WIKI_AUTHOR` overrides it when
Bedarf). needed).
- <!-- setup-question: remote --> **Remote** - bei einem leeren Klon nur die Bestätigung, dass - <!-- setup-question: remote --> **Remote** - for an empty clone, only the confirmation that
`origin` stimmt; sonst eine URL, wenn du auf einen Server pushen willst. Ohne Remote bleibt die `origin` is right; otherwise a URL, if you want to push to a server. Without a remote the
Instanz lokal, und jedes `publish` läuft mit `--no-push`. instance stays local, and every `publish` runs with `--no-push`.
- <!-- setup-question: kb-language --> **Sprache und Ton der Seiten** - sie landen in - <!-- setup-question: kb-language --> **Language and tone of the pages** - they go into
`kb/CONVENTIONS.md`, dazu je Collection `kb/<name>/COLLECTION.md`. Fertige Profile, darunter ein `kb/CONVENTIONS.md`, plus `kb/<name>/COLLECTION.md` per collection. Ready-made profiles,
vollständiges deutsches, hält `instructions/kb-profiles.md` bereit. Entscheide das **vor dem including a complete German one, are in `instructions/kb-profiles.md`. Decide this **before the
ersten Ingest**: Danach ist ein Wechsel der Abschnittsnamen eine Migration jeder bestehenden first ingest**: afterwards, changing the section names is a migration of every existing page.
Seite. Titel, Wikilink-Ziele, Zitat-IDs, Schema-Werte, Tags, Befehle und Pfade folgen keiner Titles, wikilink targets, citation ids, schema values, tags, commands and paths follow no
Sprache - `Act Runner` heißt in jeder Instanz `Act Runner`. language - `Act Runner` is called `Act Runner` in every instance.
- <!-- setup-question: domain --> **Anwendungsgebiet** - woraus dieses Wiki seine Quellen zieht. - <!-- setup-question: domain --> **Subject area** - where this wiki draws its sources from. From
Daraus schlägt der Agent eine `source_type`-Liste vor (bei einem Verein etwa Satzung, Protokoll, it the agent proposes a `source_type` list (for a sports club, say: statutes, minutes, match
Spielbericht). Das ist ein Startpunkt, keine Festlegung: Später wird sie an echtem Bestand report). That is a starting point, not a commitment: it gets corrected against real material
korrigiert (`instructions/evolve-subtypes.md`). later (`instructions/evolve-subtypes.md`).
- <!-- setup-question: personalization --> **Personalisierung** - wer diese Instanz bedient - <!-- setup-question: personalization --> **Personalization** - who operates this instance
(`USER.md`) und wie sie klingt (`SOUL.md`). Der Agent interviewt dich entlang der Vorlagen und (`USER.md`) and how it sounds (`SOUL.md`). The agent interviews you along the templates and
schreibt deine Antworten wörtlich mit. Zwei Fragen beantwortest nur du: den **Namen der Persona** writes your answers down verbatim. Two questions only you answer: the **name of the persona**
und die **Themen, die bewusst draußen bleiben**. and the **topics that deliberately stay out**.
- <!-- setup-question: environment --> **Umgebung** (optional) - Harness, MCP-Server, Remotes, - <!-- setup-question: environment --> **Environment** (optional) - harness, MCP servers, remotes,
damit spätere Sitzungen nicht erneut fragen. „Weiß ich nicht“ ist eine gültige Antwort. so that later sessions don't ask again. "I don't know" is a valid answer.
- <!-- setup-question: telemetry --> **Telemetrie** - standardmäßig aus; der Agent fragt nur, ob du - <!-- setup-question: telemetry --> **Telemetry** - off by default; the agent only asks whether
sie einschalten willst. you want to switch it on.
- <!-- setup-question: task-tracker --> **Aufgaben-Tracker** (optional) - siehe - <!-- setup-question: task-tracker --> **Task tracker** (optional) - see
[docs/reference/configuration.md](docs/reference/configuration.md#task-tracker). [docs/reference/configuration.md](docs/reference/configuration.md#task-tracker).
Am Ende legt der Agent den ersten Commit an. Dabei hält das Mass-Update-Gate an (Exit 42), weil At the end the agent makes the first commit. The Mass-Update Gate stops it there (exit 42),
eine neue Instanz aus weit mehr als zehn Dateien besteht. Das ist erwartet: Der Agent zeigt dir because a new instance consists of far more than ten files. That is expected: the agent shows you
die Dateiliste und die `--confirm`-Zeile, und erst nach deiner Freigabe wird veröffentlicht. the file list and the `--confirm` line, and nothing is published until you approve. Afterwards,
Danach startest du die Agent-Sitzung im selben Verzeichnis neu, damit sie die Skills lädt. restart the agent session in the same folder so that it loads the skills.
## Wenn der Agent anhält ## When the agent stops
Der Preflight hält mit **Exit 42** an, wenn du etwas tun musst. Seine Ausgabe nennt in einem The preflight stops with **exit 42** when you have to do something. Its output names, in a
nummerierten Block, was fehlt, warum, den Befehl, der es behebt, und wie es weitergeht. Der numbered block, what is missing, why, the command that fixes it, and how to continue. The agent
Agent zeigt dir diesen Block unverändert, setzt eine Übersetzung höchstens darunter und wartet. shows you this block unchanged, adds a translation below it at most, and waits. Tell it when you
Sag ihm Bescheid, wenn du fertig bist; dann prüft er erneut. Ausweichen oder selbst installieren are done; then it checks again. It may not work around the stop or install anything itself.
darf er nicht.
**Beim Herunterladen und Entpacken** (das Skript aus dem Release, bevor es einen Baum gibt): **While downloading and unpacking** (the script from the release, before there is a tree):
- **Werkzeuge zum Laden oder Entpacken fehlen** (Exit 42). Unter Linux und macOS braucht das - **Tools for downloading or unpacking are missing** (exit 42). On Linux and macOS the script
Skript `curl`, `tar` und `sha256sum` (oder `shasum`), unter Windows nur das `tar.exe` aus needs `curl`, `tar` and `sha256sum` (or `shasum`); on Windows only the `tar.exe` that comes
Windows 10/11. Installiere, was die Ausgabe nennt; unter Windows liefert Git for Windows alles with Windows 10/11. Install what the output names; on Windows, Git for Windows brings
für Git Bash mit. everything for Git Bash.
- **Das Verzeichnis ist zu lang** (Exit 42, nur Windows ohne lange Pfade). Nimm ein kürzeres, - **The folder path is too long** (exit 42, only on Windows without long paths). Take a shorter
etwa `C:\Chemenu`, öffne es im Harness und gib den Satz dort noch einmal. one, such as `C:\Chemenu`, open it in the harness and give the sentence there again.
- **Das Verzeichnis ist nicht leer** (Exit 1). Es darf nichts enthalten außer dem Skript und - **The folder is not empty** (exit 1). It may hold nothing but the script and a `.git`. Clean it
einem `.git`. Räume es selbst auf oder nimm ein anderes - der Agent löscht dort nichts. up yourself or take another one - the agent deletes nothing there.
- **Download fehlgeschlagen oder Prüfsumme falsch** (Exit 1). Es wurde nichts entpackt. Prüf die - **Download failed or checksum wrong** (exit 1). Nothing was unpacked. Check the internet
Internetverbindung und lass es erneut versuchen; einen anderen Download-Weg sucht der Agent connection and let it try again; the agent does not look for another way to download. Without a
nicht. Ohne direkten Download kannst du Tarball und `.sha256` von der Release-Seite selbst direct download you can put the tarball and its `.sha256` from the release page side by side
nebeneinander ablegen; der Agent startet das Skript dann mit `--archive <tarball>`. yourself; the agent then runs the script with `--archive <tarball>`.
**Im entpackten Baum** (jeder weitere Lauf ist `tools/preflight.sh` bzw. unter PowerShell **In the unpacked tree** (every further run is `tools/preflight.sh`, or under PowerShell
`pwsh -NoProfile -ExecutionPolicy Bypass -File tools/preflight.ps1`): `pwsh -NoProfile -ExecutionPolicy Bypass -File tools/preflight.ps1`):
- **Ein Werkzeug fehlt** - Python, git, ripgrep, unter Windows auch PowerShell 7. Die Ausgabe - **A tool is missing** - Python, git, ripgrep, on Windows also PowerShell 7. The output names
nennt den Installationsbefehl für dein System. Ist es schon installiert, nur woanders, nenn dem the install command for your system. If it is installed, just somewhere else, tell the agent the
Agenten den Pfad; er reicht ihn mit `--set <werkzeug>=<pfad>` weiter. path; it passes it on with `--set <tool>=<path>`.
- **Eine Version ist zu alt** - zum Beispiel Python unter 3.11. Neuere Version installieren oder - **A version is too old** - Python below 3.11, for example. Install a newer version or name its
deren Pfad nennen. path.
- **Ein genannter Pfad funktioniert nicht** - der Pfad muss auf das Programm selbst zeigen, nicht - **A path you named does not work** - the path must point at the program itself, not at its
auf seinen Ordner. folder.
- **Die Python-Umgebung (`tools/.venv`) oder ihre Bibliotheken ließen sich nicht einrichten.** Die - **The Python environment (`tools/.venv`) or its libraries could not be set up.** The output
Ausgabe zeigt, was Python oder pip gemeldet haben. Meist blockiert ein Proxy oder ein shows what Python or pip reported. Usually a proxy or a security program blocks the download;
Sicherheitsprogramm den Download; das klärt, wer deinen Rechner betreut. whoever looks after your machine can sort that out.
- **Skripte tragen die Markierung „aus dem Internet“** (nur Windows). Das passiert, wenn das - **Scripts carry the "from the internet" mark** (only on Windows). That happens when the release
Release im Browser geladen und im Explorer entpackt wurde. Einmal im Verzeichnis, in was downloaded in the browser and unpacked in Explorer. Once, in the folder, in PowerShell 7:
PowerShell 7: `Get-ChildItem -Recurse -File | Unblock-File`. `doctor` zeigt den Stand unter `Get-ChildItem -Recurse -File | Unblock-File`. `doctor` shows the state under `script-marks`.
`script-marks`. - **The execution policy forbids scripts** (`Restricted` or `AllSigned`, only on Windows). The
- **Die Execution Policy verbietet Skripte** (`Restricted` oder `AllSigned`, nur Windows). Die output names the one line for a PowerShell 7 window
Ausgabe nennt die eine Zeile für ein PowerShell-7-Fenster (`Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned`). If a group policy sets
(`Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned`). Setzt eine it, only your IT department can help - or you work from Git Bash with `tools/wikitool`. `doctor`
Gruppenrichtlinie sie, hilft nur die IT - oder du arbeitest aus Git Bash mit `tools/wikitool`. shows the state under `execution-policy`.
`doctor` zeigt den Stand unter `execution-policy`. - **The installation folder path is too long** (only on Windows without long paths). The instance
- **Das Installationsverzeichnis ist zu lang** (nur Windows ohne lange Pfade). Die Instanz muss has to move to a shorter folder, such as `C:\Chemenu`.
in ein kürzeres Verzeichnis umziehen, etwa `C:\Chemenu`.
Hält der Agent an einer anderen Stelle an und ist die Ursache nicht offensichtlich, bietet er dir If the agent stops anywhere else and the cause is not obvious, it offers you a bug report - see
einen Fehlerbericht an - siehe
[docs/how-to/troubleshoot.md](docs/how-to/troubleshoot.md). [docs/how-to/troubleshoot.md](docs/how-to/troubleshoot.md).
## Verifikation ## Check the instance
```bash ```bash
tools/wikitool doctor tools/wikitool doctor
``` ```
Prüft in einem Aufruf: Abhängigkeiten, Autor-Auflösung, Git-Identität/Branch/Remote, This checks in one call: dependencies, author resolution, git identity/branch/remote, published
publizierte Skills, Struktur (Collection-Contracts, generierte Dateien), Personalization skills, structure (collection contracts, generated files), personalization (`USER.md`/`SOUL.md`
(`USER.md`/`SOUL.md` vorhanden **und** ausgefüllt), die optionale Umgebungsnotiz present **and** filled in), the optional environment note (`ENVIRONMENT.md`), the task tracker
(`ENVIRONMENT.md`), den Aufgaben-Tracker (`.wikitool-tasks.json` - fehlt sie, ist das `OK`; ist (`.wikitool-tasks.json` - if it is missing, that is `OK`; if a provider is configured, also
ein Provider konfiguriert, zusätzlich ob sein Lesepfad bereitsteht und seine API gerade whether its read path is ready and its API is answering right now, neither ever a `FAIL`) and the
antwortet, beides nie ein `FAIL`) und die Session-ID. session id. `OK`/`WARN` are harmless (a missing remote, for example, is a valid end state); only a
`OK`/`WARN` sind unbedenklich (ein fehlender Remote z. B. ist ein gültiger Endzustand); nur ein `FAIL` ends with exit 1, and every line names its own fix command.
`FAIL` bricht mit exit 1 ab, und jede Zeile nennt ihr eigenes Fix-Kommando.
Danach zusätzlich: Then also:
```bash ```bash
tools/wikitool docs verify tools/wikitool docs verify
tools/wikitool instructions verify tools/wikitool instructions verify
``` ```
## Danach ## Next steps
- **Aktualisieren** auf ein neueres Release: [docs/how-to/update-an-instance.md](docs/how-to/update-an-instance.md). - **Your first source and your first answer:**
- **Konfiguration** - Umgebungsvariablen und die Dateien pro Checkout: [docs/tutorials/first-source-to-first-answer.md](docs/tutorials/first-source-to-first-answer.md)
walks you through both in the instance you just set up.
- **Updating** to a newer release: [docs/how-to/update-an-instance.md](docs/how-to/update-an-instance.md).
- **Configuration** - environment variables and the files per checkout:
[docs/reference/configuration.md](docs/reference/configuration.md). [docs/reference/configuration.md](docs/reference/configuration.md).
- **Wenn etwas nicht geht:** [docs/how-to/troubleshoot.md](docs/how-to/troubleshoot.md). - **When something does not work:** [docs/how-to/troubleshoot.md](docs/how-to/troubleshoot.md).
- **Mit dem Wiki arbeiten:** [docs/how-to/](docs/how-to/README.md). - **Working with the wiki:** [docs/how-to/](docs/how-to/README.md).
+3 -21
View File
@@ -45,7 +45,7 @@ Two starting points, depending on what you're doing:
The human documentation lives under `docs/`, sorted by what you want from it: The human documentation lives under `docs/`, sorted by what you want from it:
- [docs/tutorials/](docs/tutorials/README.md) - learning: a guided first walk through an - [docs/tutorials/](docs/tutorials/README.md) - learning: a guided first walk through an
instance. Installation is still [INSTALL.md](INSTALL.md). instance, starting with the installation in [INSTALL.md](INSTALL.md).
- [docs/how-to/](docs/how-to/README.md) - doing: one task per page, for the operator of an - [docs/how-to/](docs/how-to/README.md) - doing: one task per page, for the operator of an
instance. instance.
- [docs/reference/](docs/reference/README.md) - looking up: commands, exit codes, skills, page - [docs/reference/](docs/reference/README.md) - looking up: commands, exit codes, skills, page
@@ -61,26 +61,8 @@ How the parts fit together is [docs/explanation/architecture.md](docs/explanatio
## Your first ingestion ## Your first ingestion
### First Steps Once the instance runs, [From your first source to your first answer](docs/tutorials/first-source-to-first-answer.md)
takes a sample document that ships with it through an ingest and a cited answer, step by step.
1. Read `AGENTS.md` - the control plane (invariants, routing, gates) - then the stage contract
for whichever of `raw/`, `types/` or `kb/` you are working in, and, inside `kb/`, the
`COLLECTION.md` of the collection you are writing to
2. Add your first source to `incoming/`
3. Run: `Ingest <your-file>`
4. Review the created pages
5. Ask your first query
### Example First Ingestion
```bash
# Add a source
cp ~/Downloads/my-notes.md incoming/my-notes.md
# Tell the LLM to process it
# (in your LLM agent)
Ingest incoming/my-notes.md
```
## Changelog ## Changelog
+1 -1
View File
@@ -1 +1 @@
9.0.0-beta.6 9.0.0-beta.7
@@ -400,7 +400,7 @@ tools/wikitool docs prerequisites --apply
**Behaviour** **Behaviour**
- Rewrites each `<!-- wikitool:prerequisites -->` region in `INSTALL.md` (tools every platform needs) and `<!-- wikitool:prerequisites-<platform> -->` region (tools only that platform needs) from the manifest: one list item per tool, its label and minimum version. The manifest's reason field stays out - it is English prose, and the region sits in a document that need not be. - Rewrites each `<!-- wikitool:prerequisites -->` region in `INSTALL.md` (tools every platform needs) and `<!-- wikitool:prerequisites-<platform> -->` region (tools only that platform needs) from the manifest: one list item per tool, its label and minimum version. The manifest's reason field stays out - it explains a tool to whoever reads the preflight's own output, while the region only says what to install.
- Never places a region: where a list belongs in the human guide is that guide's own decision. A region the manifest calls for but the file lacks is an error naming the marker pair to add. - Never places a region: where a list belongs in the human guide is that guide's own decision. A region the manifest calls for but the file lacks is an error naming the marker pair to add.
- Dry-run by default (says whether the file would change); `--apply` writes. - Dry-run by default (says whether the file would change); `--apply` writes.
- `docs verify` checks the result stays current. - `docs verify` checks the result stays current.
+7 -2
View File
@@ -4,5 +4,10 @@ Learning-oriented pages: a guided first walk through an instance, start to finis
who has not used one before. A tutorial shows one path that works; it does not list options or who has not used one before. A tutorial shows one path that works; it does not list options or
explain why. explain why.
Nothing is here yet. The installation tutorial is still [INSTALL.md](../../INSTALL.md) at the Take them in this order:
repository root, which stays there; a walk from the first source to the first answer is planned.
1. [Install a Chemenu instance](../../INSTALL.md) - from an empty folder to a running instance.
It stays at the repository root, where someone who has nothing else yet finds it first.
2. [From your first source to your first answer](first-source-to-first-answer.md) - ingest a
sample document, look at the pages it became, and ask the wiki a question about it.
[sample-source.md](sample-source.md) is the document it uses.
@@ -0,0 +1,157 @@
# From your first source to your first answer
In this tutorial you put one document into a fresh instance, let the agent turn it into wiki
pages, look at what it wrote, and then ask the wiki a question and follow the answer back to the
document. It takes about a quarter of an hour. You need nothing but the instance and your harness:
the document is a sample that ships with the instance.
You start from an instance that [INSTALL.md](../../INSTALL.md) has just set up, with the agent
session restarted afterwards so that it has loaded its skills. Ask the agent `Which skills do you
have?` if you are unsure - `wiki-ingest` and `wiki-query` should be among them.
<!-- wikitool:toc -->
## Contents
- [1. Put the sample source into `incoming/`](#1-put-the-sample-source-into-incoming)
- [2. Ask the agent to ingest it](#2-ask-the-agent-to-ingest-it)
- [3. Tell the agent what matters](#3-tell-the-agent-what-matters)
- [4. Answer the two capture questions](#4-answer-the-two-capture-questions)
- [5. Let the agent publish](#5-let-the-agent-publish)
- [6. Look at what it wrote](#6-look-at-what-it-wrote)
- [7. Ask a question](#7-ask-a-question)
- [8. Optional: browse it in Obsidian](#8-optional-browse-it-in-obsidian)
- [What next](#what-next)
<!-- /wikitool:toc -->
## 1. Put the sample source into `incoming/`
`incoming/` is where everything you want in the wiki waits until it is ingested. Copy the sample
there - copy, not move, so the tutorial page keeps its sample:
```bash
cp docs/tutorials/sample-source.md incoming/home-lab-backups.md
```
On Windows in PowerShell 7:
```powershell
Copy-Item docs/tutorials/sample-source.md incoming/home-lab-backups.md
```
Open [the sample](sample-source.md) and read it once. It is a page of notes about the backups of a
small home file server called Atlas: which tool makes them (restic), where they go, and why there
are two targets (the 3-2-1 backup rule). Knowing what it says will let you check the agent's work.
## 2. Ask the agent to ingest it
In the agent session, say:
```text
Ingest
```
A bare `Ingest` takes the oldest entry waiting in `incoming/` - here, the only one. The agent
reads the whole file before it writes anything.
## 3. Tell the agent what matters
The agent comes back with the key takeaways of the document and a few questions: which points
matter most, which things should get a page of their own, and whether the document carries
something you have to *do*. Answer in your own words, for example:
```text
Atlas, restic and the 3-2-1 rule are what matter. Nothing to do from this one.
```
The pages it writes next follow your answer, so this is the moment to steer. The agent may well
notice that the notes leave something untested and offer to track it as a task; "nothing to do"
declines that.
Often the same message already asks the two questions of the next step. Then answer them in the
same reply.
## 4. Answer the two capture questions
Before the file leaves `incoming/`, the agent asks two things about the capture itself:
- **`fidelity`** - how faithful is this file to the original? The sample is the notes exactly as
written, so the answer is `verbatim`.
- **`authority`** - what may the material claim about its subject? The notes describe how a setup
works; they do not set a standard anyone else has to follow. The answer is `reporting`.
```text
verbatim, reporting
```
The agent never guesses these two. Only you know them, and only now: once the file is in the wiki,
nobody can tell any more where it came from. [raw/CONTRACT.md](../../raw/CONTRACT.md#capture-fields-fidelity-and-authority)
lists every value, for the sources you add later.
## 5. Let the agent publish
The agent now moves the file into `raw/`, writes the pages, and publishes everything as one
commit. For a source this small that goes straight through; the agent tells you what it committed.
If your instance has no remote, the commit stays on your machine.
A larger source - ten or more new or changed pages and files, not counting the generated indexes
and log - stops at the Mass-Update Gate instead: you see the list of files and a line ending in
`--confirm <token>`, and nothing is committed until you tell the agent to go ahead.
## 6. Look at what it wrote
Ask the agent where the pages are, or look yourself. You will find:
- **The file itself under `raw/`**, in a folder for the current year and month. It is never edited
again.
- **A source page under `kb/sources/`**, summarising the notes. Its frontmatter carries your two
answers, `fidelity: verbatim` and `authority: reporting`, and `raw_files:` points at the file in
`raw/`.
- **Entity and concept pages** for what you said matters - Atlas, restic, the 3-2-1 backup rule,
in the language and naming your instance chose at setup. Each one links back to the source page,
and each claim taken from the notes carries a footnote citing it.
- **A new entry at the end of `kb/log.md`**, recording the ingest.
The exact set of pages depends on your answer in step 3, and on the agent: two runs of this
tutorial do not produce word-for-word the same wiki. What is always the same is that every page is
tied back to the file in `raw/`.
## 7. Ask a question
Start a new agent session, so that the answer can only come from the wiki and not from what the
agent remembers of the ingest, and ask:
```text
How are the backups of Atlas protected against a fire in the house?
```
The answer names the storage box outside the house as the copy that survives, and the 3-2-1 rule
as the reason it exists. It cites the pages it came from and the source behind them. Open one of
the cited pages and follow its footnote: it leads to the source page, and that one to the file in
`raw/` - the notes you copied in step 1.
Now ask something the notes do not answer:
```text
How long does a full restore of Atlas take?
```
The notes say only that one has never been tried. The agent tells you that the wiki has no source
for this, rather than estimating one. That is the rule behind every answer: no claim without a
source.
## 8. Optional: browse it in Obsidian
Open the instance's root folder as a vault in [Obsidian](https://obsidian.md). The graph view shows
the pages you just made and the links between them. Read there as much as you like, but change
pages through the agent: [Browse the wiki in Obsidian](../how-to/browse-with-obsidian.md) explains
why.
## What next
You have taken one source all the way from a file to a cited answer. From here on, the how-to
guides cover the everyday tasks:
- [Ingest a source](../how-to/ingest-a-source.md) - your own files, folders and web pages
- [Query the wiki](../how-to/query-the-wiki.md) - and search it yourself
- [Maintain the wiki](../how-to/maintain-the-wiki.md) - the lint the agent suggests every ten
sources
+48
View File
@@ -0,0 +1,48 @@
# Home lab backups - how they work now
Notes written after reworking the backups in September 2026. This file is the sample source for
the tutorial "From your first source to your first answer"; the machine and its setup are made
up for it.
## The machine
**Atlas** is the small file server in the hall cupboard: a fanless mini PC with two 4 TB disks
in a mirror, running Debian 13. It holds the family photo archive, scanned documents and the
configuration of every other machine in the house. Everything else on the network is replaceable;
what is on Atlas is not.
## The tool
Backups are made with **restic**, an open-source backup program. restic splits files into chunks,
stores each chunk only once and encrypts everything before it leaves the machine, so the backup
target never sees a file name or a byte of content in the clear. A restic *repository* is the
storage location it writes to; a *snapshot* is one backup run.
restic was chosen over plain `rsync` for two reasons: deduplication keeps the daily runs small,
and encryption makes it safe to put a copy on storage someone else operates.
## How it is set up
Atlas runs restic every night at 02:30 from a systemd timer. Each run writes one snapshot to two
repositories:
- a USB disk that stays plugged into Atlas, for fast restores;
- a rented storage box at a hosting provider, reached over SFTP, as the copy outside the house.
Snapshots are thinned out by `restic forget` after each run: the last 7 daily, 5 weekly and
12 monthly snapshots are kept.
## Why two targets
The setup follows the **3-2-1 backup rule**: keep three copies of the data, on two different
kinds of storage, with one copy off site. Here the three copies are the mirror on Atlas itself,
the USB disk, and the storage box. A fire or a burglary takes the first two; the storage box is
what is left.
The mirror alone does not count as a backup. It protects against a dead disk, but a deleted or
encrypted file is deleted or encrypted on both disks at once.
## What is still open
The restore has been tried once, for a single folder, from the USB disk. It worked and took
under a minute. A full restore from the storage box has not been tried.
+1 -1
View File
@@ -41,7 +41,7 @@ touched; a row that does not apply needs no action.
| A task-tracker adapter (`tools/chemenu/tasks/`), its recorded fixtures, or the live suite | [instructions/dev/tracker-testing.md](tracker-testing.md), and `MANIFEST.json` beside the fixtures when they were re-recorded | | A task-tracker adapter (`tools/chemenu/tasks/`), its recorded fixtures, or the live suite | [instructions/dev/tracker-testing.md](tracker-testing.md), and `MANIFEST.json` beside the fixtures when they were re-recorded |
| A skill's own step sequence or catalogue | The skill's `SKILL.md` source under `instructions/<name>/` or `instructions/dev/<name>/`; for a shipped skill (not under `instructions/dev/`) whose name or `description` changed, or one added or removed, `wikitool docs reference --apply` for the skill catalogue `docs/reference/skills.md` | | A skill's own step sequence or catalogue | The skill's `SKILL.md` source under `instructions/<name>/` or `instructions/dev/<name>/`; for a shipped skill (not under `instructions/dev/`) whose name or `description` changed, or one added or removed, `wikitool docs reference --apply` for the skill catalogue `docs/reference/skills.md` |
| A per-checkout configuration file an instance owns (`.wikitool-tasks.json`, `.wikitool-telemetry.json`, `.wikitool-remotes.json`, `.wikitool-upload.json`) | [docs/reference/configuration.md](../../docs/reference/configuration.md), where an operator looks the shape up - written by hand, since nothing generates it; the [setup-instance.md](../setup-instance.md) decision point that offers it during setup; and `doctor`'s own row in [tools/CONTRACT.md](../../tools/CONTRACT.md), since `doctor` is what reports the file's state | | A per-checkout configuration file an instance owns (`.wikitool-tasks.json`, `.wikitool-telemetry.json`, `.wikitool-remotes.json`, `.wikitool-upload.json`) | [docs/reference/configuration.md](../../docs/reference/configuration.md), where an operator looks the shape up - written by hand, since nothing generates it; the [setup-instance.md](../setup-instance.md) decision point that offers it during setup; and `doctor`'s own row in [tools/CONTRACT.md](../../tools/CONTRACT.md), since `doctor` is what reports the file's state |
| An installation instruction - [preflight.md](../preflight.md), [setup-instance.md](../setup-instance.md), [bootstrap.md](../bootstrap.md), [upgrade-instance.md](../upgrade-instance.md) - or `tools/prerequisites.txt` | [INSTALL.md](../../INSTALL.md), the human guide to the same procedure - for `upgrade-instance.md`, [docs/how-to/update-an-instance.md](../../docs/how-to/update-an-instance.md) instead. Read it against the instruction: what to prepare, the sentence for the agent, what the agent asks, where it stops and why. `docs verify` checks only the two enumerable overlaps - the prerequisites lists, which `wikitool docs prerequisites --apply` regenerates from the manifest, and the setup questions: a question the agent asks the user carries `<!-- setup-question: <key> -->` where it is asked in `setup-instance.md`, and `INSTALL.md` § "Was der Agent dich fragt" names it with the same marker. Every other sentence is this session's to compare. `INSTALL.md` does not retell the steps, so a change to their order or wording alone moves nothing there | | An installation instruction - [preflight.md](../preflight.md), [setup-instance.md](../setup-instance.md), [bootstrap.md](../bootstrap.md), [upgrade-instance.md](../upgrade-instance.md) - or `tools/prerequisites.txt` | [INSTALL.md](../../INSTALL.md), the human guide to the same procedure - for `upgrade-instance.md`, [docs/how-to/update-an-instance.md](../../docs/how-to/update-an-instance.md) instead. Read it against the instruction: what to prepare, the sentence for the agent, what the agent asks, where it stops and why. `docs verify` checks only the two enumerable overlaps - the prerequisites lists, which `wikitool docs prerequisites --apply` regenerates from the manifest, and the setup questions: a question the agent asks the user carries `<!-- setup-question: <key> -->` where it is asked in `setup-instance.md`, and `INSTALL.md` § "What the agent asks you" names it with the same marker. Every other sentence is this session's to compare. `INSTALL.md` does not retell the steps, so a change to their order or wording alone moves nothing there |
| [dev-setup.md](dev-setup.md), the release workflow (`version bump`/`version release`/`publish`/CI), or another developer-facing process | [docs/dev/development.md](../../docs/dev/development.md), read against it the same way - nothing checks this pair at all. A page under `docs/dev/` is never shipped, so it may link into `instructions/dev/` and cite issue numbers | | [dev-setup.md](dev-setup.md), the release workflow (`version bump`/`version release`/`publish`/CI), or another developer-facing process | [docs/dev/development.md](../../docs/dev/development.md), read against it the same way - nothing checks this pair at all. A page under `docs/dev/` is never shipped, so it may link into `instructions/dev/` and cite issue numbers |
| A new page type the stack requires, or a new collection | Its type-spec and `COLLECTION.md` (both as the `.template` an instance adopts), the collection table in [kb/CONTRACT.md](../../kb/CONTRACT.md), and **both adoption paths**: [setup-instance.md](../setup-instance.md) for a fresh instance and [upgrade-instance.md](../upgrade-instance.md) for an existing one, where an unadopted template is what `docs verify` refuses. A new or changed `root: kb` type-spec or its schema - description, `layout:`, subtype enum, required fields - also needs `wikitool docs reference --apply` for `docs/reference/page-types.md` | | A new page type the stack requires, or a new collection | Its type-spec and `COLLECTION.md` (both as the `.template` an instance adopts), the collection table in [kb/CONTRACT.md](../../kb/CONTRACT.md), and **both adoption paths**: [setup-instance.md](../setup-instance.md) for a fresh instance and [upgrade-instance.md](../upgrade-instance.md) for an existing one, where an unadopted template is what `docs verify` refuses. A new or changed `root: kb` type-spec or its schema - description, `layout:`, subtype enum, required fields - also needs `wikitool docs reference --apply` for `docs/reference/page-types.md` |
+1 -1
View File
@@ -2651,7 +2651,7 @@ Regenerate `INSTALL.md`'s prerequisites lists from `tools/prerequisites.txt`.
**NOTES** **NOTES**
- Rewrites each `<!-- wikitool:prerequisites -->` region in `INSTALL.md` (tools every platform needs) and `<!-- wikitool:prerequisites-<platform> -->` region (tools only that platform needs) from the manifest: one list item per tool, its label and minimum version. The manifest's reason field stays out - it is English prose, and the region sits in a document that need not be. - Rewrites each `<!-- wikitool:prerequisites -->` region in `INSTALL.md` (tools every platform needs) and `<!-- wikitool:prerequisites-<platform> -->` region (tools only that platform needs) from the manifest: one list item per tool, its label and minimum version. The manifest's reason field stays out - it explains a tool to whoever reads the preflight's own output, while the region only says what to install.
- Never places a region: where a list belongs in the human guide is that guide's own decision. A region the manifest calls for but the file lacks is an error naming the marker pair to add. - Never places a region: where a list belongs in the human guide is that guide's own decision. A region the manifest calls for but the file lacks is an error naming the marker pair to add.
- Dry-run by default (says whether the file would change); `--apply` writes. - Dry-run by default (says whether the file would change); `--apply` writes.
- `docs verify` checks the result stays current. - `docs verify` checks the result stays current.
+2 -2
View File
@@ -1555,8 +1555,8 @@ def toc_command(
"Rewrites each `<!-- wikitool:prerequisites -->` region in `INSTALL.md` (tools every " "Rewrites each `<!-- wikitool:prerequisites -->` region in `INSTALL.md` (tools every "
"platform needs) and `<!-- wikitool:prerequisites-<platform> -->` region (tools only that " "platform needs) and `<!-- wikitool:prerequisites-<platform> -->` region (tools only that "
"platform needs) from the manifest: one list item per tool, its label and minimum " "platform needs) from the manifest: one list item per tool, its label and minimum "
"version. The manifest's reason field stays out - it is English prose, and the region " "version. The manifest's reason field stays out - it explains a tool to whoever reads "
"sits in a document that need not be.", "the preflight's own output, while the region only says what to install.",
"Never places a region: where a list belongs in the human guide is that guide's own " "Never places a region: where a list belongs in the human guide is that guide's own "
"decision. A region the manifest calls for but the file lacks is an error naming the " "decision. A region the manifest calls for but the file lacks is an error naming the "
"marker pair to add.", "marker pair to add.",
+26 -19
View File
@@ -1,28 +1,31 @@
"""The two places `INSTALL.md` overlaps the installation instructions, held to them. """The two places `INSTALL.md` overlaps the installation instructions, held to them.
`INSTALL.md` is written for a human and in the instance's KB language; `INSTALL.md` is written for a human, `instructions/setup-instance.md` for an
`instructions/setup-instance.md` is written for an agent and in English. A agent; both in English (`AGENTS.md` § File naming). A single file serving
single file serving both was rejected: an agent reads every sentence as an both was rejected: an agent reads every sentence as an instruction, and the
instruction, and the human needs preparation and decisions where the agent human needs preparation and decisions where the agent needs steps and exit
needs steps and exit codes. So the human document does not retell the codes. So the human document does not retell the procedure, and what it still
procedure, and what it still shares with the instructions is two enumerable shares with the instructions is two enumerable lists - both checked here, so
lists - both checked here, so neither can drift silently: neither can drift silently:
1. **What the machine needs.** `tools/prerequisites.txt` is the one list; the 1. **What the machine needs.** `tools/prerequisites.txt` is the one list; the
preflight and `doctor` read it. `INSTALL.md` carries it as a generated preflight and `doctor` read it. `INSTALL.md` carries it as a generated
region per platform value (`<!-- wikitool:prerequisites -->` for `all`, region per platform value (`<!-- wikitool:prerequisites -->` for `all`,
`<!-- wikitool:prerequisites-<platform> -->` otherwise), rendered from the `<!-- wikitool:prerequisites-<platform> -->` otherwise), rendered from the
label and minimum version only. The manifest's `why` field stays out: it is label and minimum version only. The manifest's `why` field stays out: it
English prose, and the region sits in a document that is not. A region is explains a tool to whoever reads the preflight's own output, while the
never placed by the tool - where it goes is the human document's own region only says what to install. A region is never placed by the tool -
decision - so a missing one is reported, not appended. where it goes is the human document's own decision - so a missing one is
reported, not appended.
2. **What the agent asks the user.** Every place `setup-instance.md` puts a 2. **What the agent asks the user.** Every place `setup-instance.md` puts a
question to the user carries `<!-- setup-question: <key> -->`, and the question to the user carries `<!-- setup-question: <key> -->`, and the
bullet in `INSTALL.md` that tells the human about it carries the same bullet in `INSTALL.md` § "What the agent asks you" that tells the human
marker. The two key sets must be equal: a question the human guide does not about it carries the same marker. The two key sets must be equal: a
mention catches them unprepared, and one it mentions that is no longer asked question the human guide does not mention catches them unprepared, and one
is a claim about a procedure that no longer exists. The key is the shared it mentions that is no longer asked is a claim about a procedure that no
identifier precisely because the surrounding prose is in two languages. longer exists. The key is the shared identifier because the two texts word
the same question for different readers, and neither wording is stable
enough to match on.
Everything else in `INSTALL.md` is prose no check reads; Everything else in `INSTALL.md` is prose no check reads;
`instructions/dev/doc-pull-through.md` names it as session work. `instructions/dev/doc-pull-through.md` names it as session work.
@@ -37,6 +40,10 @@ from chemenu import blocks, config, prerequisites
INSTALL_DOC = "INSTALL.md" INSTALL_DOC = "INSTALL.md"
SETUP_INSTRUCTION = "instructions/setup-instance.md" SETUP_INSTRUCTION = "instructions/setup-instance.md"
# The heading in INSTALL.md whose bullets carry the setup-question markers -
# named in check_setup_questions' finding, and held to the real file by a test.
QUESTIONS_SECTION = "What the agent asks you"
REGION_PREFIX = "prerequisites" REGION_PREFIX = "prerequisites"
QUESTION_RE = re.compile(r"<!-- setup-question: ([a-z][a-z0-9-]*) -->") QUESTION_RE = re.compile(r"<!-- setup-question: ([a-z][a-z0-9-]*) -->")
@@ -101,7 +108,7 @@ def refresh(text: str, manifest: prerequisites.Manifest) -> tuple[str, list[str]
A region the manifest no longer has a platform for is left alone and A region the manifest no longer has a platform for is left alone and
reported by `check_prerequisite_regions`, not deleted here: the prose reported by `check_prerequisite_regions`, not deleted here: the prose
introducing it ("Unter Windows zusätzlich:") would otherwise be left introducing it ("On Windows, additionally ...") would otherwise be left
standing over nothing. standing over nothing.
""" """
missing = [] missing = []
@@ -166,8 +173,8 @@ def check_setup_questions() -> list[str]:
named = question_keys(install.read_text(encoding="utf-8")) named = question_keys(install.read_text(encoding="utf-8"))
issues = [ issues = [
f"{SETUP_INSTRUCTION} asks the user `{key}`, but {INSTALL_DOC} § \"Was der Agent dich " f"{SETUP_INSTRUCTION} asks the user `{key}`, but {INSTALL_DOC} § \"{QUESTIONS_SECTION}\" "
f"fragt\" does not name it - add a bullet carrying `<!-- setup-question: {key} -->`" f"does not name it - add a bullet carrying `<!-- setup-question: {key} -->`"
for key in sorted(asked - named) for key in sorted(asked - named)
] ]
issues += [ issues += [
+14 -5
View File
@@ -16,22 +16,22 @@ MANIFEST = prerequisites.Manifest(
CURRENT = """# Installation CURRENT = """# Installation
Vorher: You need:
<!-- wikitool:prerequisites --> <!-- wikitool:prerequisites -->
- **Python** ≥ 3.11 - **Python** ≥ 3.11
- **Git** - **Git**
<!-- /wikitool:prerequisites --> <!-- /wikitool:prerequisites -->
Unter Windows zusätzlich: On Windows, additionally:
<!-- wikitool:prerequisites-windows --> <!-- wikitool:prerequisites-windows -->
- **PowerShell 7 (pwsh)** ≥ 7 - **PowerShell 7 (pwsh)** ≥ 7
<!-- /wikitool:prerequisites-windows --> <!-- /wikitool:prerequisites-windows -->
## Was der Agent dich fragt ## What the agent asks you
- <!-- setup-question: identity --> **Autor-Identität** - Name und E-Mail. - <!-- setup-question: identity --> **Author identity** - name and email.
""" """
SETUP = """# Set up SETUP = """# Set up
@@ -57,6 +57,14 @@ def test_this_repos_install_doc_names_every_setup_question():
assert install_doc.check_setup_questions() == [] assert install_doc.check_setup_questions() == []
def test_this_repos_install_doc_has_the_section_the_finding_names():
"""A missing question is reported as missing from a named section; that
name is a constant, and a renamed heading would leave the finding pointing
at nothing."""
text = install_doc.install_doc_path().read_text(encoding="utf-8")
assert f"\n## {install_doc.QUESTIONS_SECTION}\n" in text
def test_this_repos_setup_instruction_marks_its_questions(): def test_this_repos_setup_instruction_marks_its_questions():
"""The check compares two sets; an instruction that lost every marker would """The check compares two sets; an instruction that lost every marker would
compare empty against empty and pass. Guard the real file's own count.""" compare empty against empty and pass. Guard the real file's own count."""
@@ -133,10 +141,11 @@ def test_a_question_the_install_doc_does_not_name_fails(tmp_path, monkeypatch):
issues = install_doc.check_setup_questions() issues = install_doc.check_setup_questions()
assert len(issues) == 1 assert len(issues) == 1
assert "`remote`" in issues[0] and "does not name it" in issues[0] assert "`remote`" in issues[0] and "does not name it" in issues[0]
assert f'§ "{install_doc.QUESTIONS_SECTION}"' in issues[0]
def test_a_question_no_longer_asked_fails(tmp_path, monkeypatch): def test_a_question_no_longer_asked_fails(tmp_path, monkeypatch):
install = CURRENT + "- <!-- setup-question: telemetry --> **Telemetrie**\n" install = CURRENT + "- <!-- setup-question: telemetry --> **Telemetry**\n"
_tree(tmp_path, monkeypatch, install=install) _tree(tmp_path, monkeypatch, install=install)
issues = install_doc.check_setup_questions() issues = install_doc.check_setup_questions()
assert len(issues) == 1 assert len(issues) == 1