feat!: installation only from a release, into an empty folder; upstream merge/verify and private-instance.md removed, dist adopt, shell-neutral instructions (#153)
CI / verify (push) Successful in 5m19s
CI / pwsh (push) Successful in 1m55s
Release / release (push) Successful in 36s

Files changed:
- .gitea/workflows/ci.yml
- .gitea/workflows/release.yml
- AGENTS.md
- CHANGES.md
- DEVELOPMENT.md
- EVALS.md
- INSTALL.md
- README.md
- VERSION
- docs/ownership-and-templates.md
- instructions/CONTRACT.md
- instructions/bootstrap.md
- instructions/dev/dev-setup.md
- instructions/dev/stack-dev/SKILL.md
- instructions/gates.md
- instructions/ingest-large-tree.md
- instructions/kb-profiles.md
- instructions/mcp-read-server.md
- instructions/migrations/3.0.0-authoring-conventions.md
- instructions/preflight.md
- instructions/private-instance.md
- instructions/session-setup.md
- instructions/setup-instance.md
- instructions/upgrade-instance.md
- tools/CONTRACT.md
- tools/README.md
- tools/chemenu/cli.py
- tools/chemenu/cli_contract.py
- tools/chemenu/commands/dist_cmd.py
- tools/chemenu/commands/docs_verify.py
- tools/chemenu/commands/doctor.py
- tools/chemenu/commands/git_publish.py
- tools/chemenu/commands/upstream_cmd.py
- tools/chemenu/commands/work_cmd.py
- tools/chemenu/config.py
- tools/chemenu/ownership.py
- tools/chemenu/tests/test_cli.py
- tools/chemenu/tests/test_dist_cmd.py
- tools/chemenu/tests/test_instructions_shell.py
- tools/chemenu/tests/test_preflight.py
- tools/chemenu/tests/test_preflight_pwsh.py
- tools/chemenu/tests/test_run_budget.py
- tools/chemenu/tests/test_upstream_cmd.py
- tools/chemenu/toc.py
- tools/preflight.ps1
- tools/preflight.sh
This commit is contained in:
torben committed 2026-10-01 22:12:09 +02:00
1 parent d0f08d1fba
commit a6d07f97c4
46 files changed
+1314 -1936

No files matched your search

+179 -148
View File
@@ -1,15 +1,19 @@
---
type: types/instruction.md
name: setup-instance
description: Turn a fresh distribution (from `dist export`) into a working, self-contained wiki instance - git repo, identity/author, optional remote, bootstrap, first commit.
description: Install a new, self-contained wiki instance from the latest release into an empty folder - preflight asset, git repo, identity/author, optional remote, conventions, personalization, first commit.
---
# Set up a new wiki instance
This instruction takes an empty distribution produced by `tools/wikitool dist export <target>`
and turns it into a working, self-contained wiki instance - with its own git repo, its own
author identity and (optionally) its own remote. At the end the instance is committed, verified
and ready for its first ingest.
This instruction takes an empty folder to a working, self-contained wiki instance, starting from
the latest release - with its own git repo, its own author identity and (optionally) its own
remote. At the end the instance is committed, verified and ready for its first ingest.
The same file is read in two places: as the asset `setup-instance.md` of a release, before
anything is installed, and inside the installed instance as `instructions/setup-instance.md`.
Its links to other instructions resolve only in the second place; step 0 says how to reach the
one it needs before that.
<!-- wikitool:toc -->
## Contents
@@ -21,37 +25,86 @@ and ready for its first ingest.
## When to run
- The user wants to set up a new, empty wiki instance (their own subject, a different person).
- Not for an existing clone of this (source) repo - see [bootstrap.md](bootstrap.md).
- There is no way back: `dist export` deliberately and permanently leaves out
`instructions/dev/` (stack development itself, including the vendored `commonplace/` knowledge
base). Anyone who wants to develop the resulting instance's stack further does that in the
origin repo (or a new dev instance made from it) - not by retrofitting it into this instance.
- The user wants a new wiki instance - their own subject, a different person - in a folder they
name. The folder is empty, or holds nothing but `.git`: an empty clone of the repository the
instance will push to.
- Not for a further checkout of an instance that already exists (a second machine): clone that
instance's repository and follow [bootstrap.md](bootstrap.md).
- Not for working on the stack itself. That happens in a clone of the origin repository; a
release leaves out stack development (`instructions/dev/`) permanently, and nothing in an
instance restores it.
## Steps
1. **Export the distribution**, in the source repo:
0. **Install the release into the folder.** Skip this step when `tools/preflight.sh` already
exists in the folder - then the release is installed and this file is being read from inside
it; continue with step 1.
```bash
tools/wikitool dist export <target>
```
1. **Settle the folder.** It is the one the user named, and every later step runs in it. It
has to be empty or hold only `.git`; on Windows with long paths switched off, its path may
be at most 95 characters (`C:\Chemenu`, for instance). The preflight checks both, so do
not measure anything yourself.
`<target>` must not exist, or must be empty; otherwise the command aborts with `ERROR`. Work
inside `<target>` for every step that follows.
2. **Read `preflight.md` before running anything.** It is an asset of the same release as
this file: in the release description this file came from (the answer of
`.../api/v1/repos/<owner>/<repo>/releases/latest`), the entry under `assets` named
`preflight.md`, at its `browser_download_url`. It says how the preflight is started and
what to do when it stops - and the release's preflight is the next thing to run.
2. **Initialize the git repo:**
3. **Download the preflight for the shell you run in**, from the same release's `assets`,
into the folder - with the shell's own download command, never through a browser, so the
file carries no Mark of the Web. In PowerShell 7:
```powershell
Invoke-WebRequest -Uri <browser_download_url of preflight.ps1> -OutFile preflight.ps1
```
In a POSIX shell (Linux, macOS, Git Bash on Windows):
```bash
curl -fLO <browser_download_url of preflight.sh>
```
4. **Run it, exactly as `preflight.md` step 1 says** - the path is the downloaded file:
```powershell
pwsh -NoProfile -ExecutionPolicy Bypass -File preflight.ps1
```
```bash
sh preflight.sh
```
It downloads the release's tarball, refuses unless its sha256 matches, unpacks it into
this folder, removes the downloaded script and runs the preflight of the installed tree.
Read its exit code as `preflight.md` step 2 says; on exit 42 follow its step 3 - show the
output verbatim and wait. Every later run, including the retry after an exit 42, is the
tree's own `tools/preflight.sh` or `pwsh -NoProfile -ExecutionPolicy Bypass -File
tools/preflight.ps1`.
Continue only after it exits 0. From here on, [preflight.md](preflight.md) and every other
instruction this file links to lie under `instructions/` in the folder.
1. **Initialize the git repo.** If the folder has no `.git` yet:
```bash
git init -b main
```
`-b main` is mandatory: on the actual push, `tools/wikitool publish` checks that the
If it has one - an empty clone - keep it. `git branch --show-current` must print `main`; if
it prints anything else, switch before the first commit:
```bash
git checkout -b main
```
`main` is mandatory: on the actual push, `tools/wikitool publish` checks that the
checked-out branch matches the target branch (default `main`) and refuses otherwise, so that
the wrong branch is never published.
3. **Decision point - identity.** Ask the user for their name and email address; never guess
them, and never quietly carry them over from the source repo (that is a different person and
a different project):
2. **Decision point - identity.** Ask the user for their name and email address; never guess
them, and never quietly carry them over from another repository (that is a different person
and a different project):
```bash
git config user.name "<name>"
@@ -62,18 +115,19 @@ and ready for its first ingest.
resolves `author:` from `$WIKI_AUTHOR` (an override) or else from `git config user.name`, and
aborts with `ERROR` when both are missing - there is no silent placeholder.
4. **Decision point - remote.** Ask the user for a remote URL; a purely local repo is a valid
end state:
3. **Decision point - remote.** An empty clone already has one: show the user `git remote -v`
and confirm that `origin` is where this instance is to be published. Otherwise ask for a
remote URL; a purely local repo is a valid end state:
- Given: `git remote add origin <url>`
- Not given: stay local - then **every** later `tools/wikitool publish` needs a `--no-push`
(which also drops its branch check, see step 2). Without it, `publish` ends with exit 1
(which also drops its branch check, see step 1). Without it, `publish` ends with exit 1
before it commits anything, because there is no remote to publish to.
5. **Decision point - authoring conventions.** The distribution ships no filled-in conventions,
only `kb/CONVENTIONS.md.template` and one `kb/<name>/COLLECTION.md.template` per collection.
Both **bind** once adopted, and both belong to this instance - which is why the stack ships
the template alone. The one decision behind them is: **in which language and in what tone
does this instance write its pages?**
4. **Decision point - authoring conventions.** The release ships no filled-in conventions, only
`kb/CONVENTIONS.md.template` and one `kb/<name>/COLLECTION.md.template` per collection. Both
**bind** once adopted, and both belong to this instance - which is why the stack ships the
template alone. The one decision behind them is: **in which language and in what tone does
this instance write its pages?**
Procedure:
@@ -81,19 +135,17 @@ and ready for its first ingest.
user, because what they say is usable as a starting point regardless of language:
```bash
for template in kb/*/COLLECTION.md.template types/*.template; do
cp "$template" "${template%.template}"
done
tools/wikitool dist adopt
```
The `.template` files stay where they are; they are the source for the next export.
The `.template` files stay where they are; they are what the next `dist upgrade` compares
against.
Under `types/` this covers exactly the type-specs with `root: kb` - `entity`, `concept`,
`source`, `comparison` - along with their `.schema.yaml`. They describe pages *this*
instance writes, so they belong to it: frontmatter, template and language may all be
rewritten. `instruction`, `lint-report`, `type-spec` and `type-guidance` describe stack
artifacts and arrive unchanged - the glob above never matches them because none of them
ships as a `.template` in the first place.
`source`, `comparison`, `project` - along with their `.schema.yaml`. They describe pages
*this* instance writes, so they belong to it: frontmatter, template and language may all
be rewritten. `instruction`, `lint-report`, `type-spec` and `type-guidance` describe stack
artifacts and arrive unchanged - none of them ships as a `.template` in the first place.
A `root: kb` type-spec's generic authoring guidance (when to use the type, when not to)
is not part of this adoption at all: it lives in a sibling `types/<name>.guidance.md`
@@ -102,32 +154,29 @@ and ready for its first ingest.
touched. `types/type-spec.md` § "Anatomy of a type" has the shape.
2. Ask the user for the KB language. `kb/CONVENTIONS.md.template` defaults to **English**;
[kb-profiles.md](kb-profiles.md) additionally holds a complete German profile, whose full
text is the source repo's own `kb/CONVENTIONS.md`. The profile catalogue is a **palette,
not an enum**: what gets adopted is the text *into* the instance file, not a reference to
the catalogue.
[kb-profiles.md](kb-profiles.md) additionally holds a complete German profile. The
profile catalogue is a **palette, not an enum**: what gets adopted is the text *into* the
instance file, not a reference to the catalogue.
3. Copy `kb/CONVENTIONS.md.template` to `kb/CONVENTIONS.md`, fill it in along the chosen
3. Write `kb/CONVENTIONS.md` from `kb/CONVENTIONS.md.template`, filled in along the chosen
profile - language, section names, naming forms, tone, relationship labels, hedging rule -
and remove the sentinel line (`wikitool:template-unfilled`) while doing so. The
placeholders in curly braces **are** the list of questions.
and without the sentinel line (`wikitool:template-unfilled`). The placeholders in curly
braces **are** the list of questions.
4. For a language other than the source repo's: delete `german-terminology.md` or replace it
with your own vocabulary - it is material belonging to the German profile, not to the
stack.
4. For a language other than German: delete `german-terminology.md` or replace it with your
own vocabulary - it is material belonging to the German profile, not to the stack.
5. Ask the user about the subject area and derive a `source_type` proposal from it.
[kb-profiles.md](kb-profiles.md) holds two worked domain profiles as illustration, beside
the value this repo uses itself. The proposal is a **starting point, not a commitment** -
at setup time the operator has zero sources and is guessing a taxonomy before having seen
a single file, which is the worst possible moment to pin an enum down. Carrying out the
proposal means setting the enum in `types/source.schema.yaml` **and** the matching
`layout:` line per value in `types/source.md` in the same edit - one without the other
leaves a value with no target directory. The visible catch-all (`unclassified`) survives
every proposal; it is not a dumping ground but the slot for a source whose category is not
settled yet. Extending the list later, or emptying that slot:
[evolve-subtypes.md](evolve-subtypes.md) - not part of this step, but the way there once
real material exists.
[kb-profiles.md](kb-profiles.md) holds two worked domain profiles as illustration. The
proposal is a **starting point, not a commitment** - at setup time the operator has zero
sources and is guessing a taxonomy before having seen a single file, which is the worst
possible moment to pin an enum down. Carrying out the proposal means setting the enum in
`types/source.schema.yaml` **and** the matching `layout:` line per value in
`types/source.md` in the same edit - one without the other leaves a value with no target
directory. The visible catch-all (`unclassified`) survives every proposal; it is not a
dumping ground but the slot for a source whose category is not settled yet. Extending the
list later, or emptying that slot: [evolve-subtypes.md](evolve-subtypes.md) - not part of
this step, but the way there once real material exists.
**Leave unchanged:** `fidelity` and `authority` on `source` pages. Those are stack
vocabulary, not an instance decision - [kb-profiles.md](kb-profiles.md) says so in the
@@ -139,7 +188,7 @@ and ready for its first ingest.
[migrate-corpus.md](migrate-corpus.md)).
**None of this lives in a stack file.** The compiler reads the section names from
`kb/CONVENTIONS.md`; the four page type-specs have belonged to this instance since step 1. An
`kb/CONVENTIONS.md`; the page type-specs have belonged to this instance since sub-step 1. An
instance in another language simply translates them - that is no longer a local patch to
something shipped, but work on its own files, and an upgrade does not take it away again.
@@ -153,14 +202,14 @@ and ready for its first ingest.
identifiers](../kb/CONTRACT.md#language-and-identifiers)). Titles, wikilink targets, cite ids,
enum values, tags, commands and paths follow no KB language.
`tools/wikitool doctor` checks the result in step 13 (`conventions`): a missing file is a
`tools/wikitool doctor` checks the result in step 12 (`conventions`): a missing file is a
`FAIL`, and so is one carrying the sentinel or lacking a complete `sections:` block.
`docs verify` additionally checks `profile:` and `required_by_stack:` on every
`COLLECTION.md`.
6. **Decision point - personalization.** The distribution ships `USER.md.template` and
5. **Decision point - personalization.** The release ships `USER.md.template` and
`SOUL.md.template`, but no filled-in versions: who operates this instance and how it sounds
is the property of this instance alone and is never carried over from the source repo. Both
is the property of this instance alone and is never carried over from anywhere else. Both
files are read in **every** session from now on, so they come into being here - not later,
when the occasion arises.
@@ -176,7 +225,7 @@ and ready for its first ingest.
better to delete a section than to fill it with something plausible.
4. Write the result as `USER.md` and `SOUL.md` respectively, removing the sentinel line
(`wikitool:template-unfilled`) in the process. The `.template` files stay where they are -
they are the source for the next export, not this step's leftovers.
they are what the next `dist upgrade` compares against, not this step's leftovers.
Two questions the user answers rather than the agent: **the persona name** and **which topics
deliberately stay out** (employer, clients, health - whatever they are). Guessing either
@@ -189,103 +238,86 @@ and ready for its first ingest.
invariant 3. They change no rule from [AGENTS.md](../AGENTS.md), and a user's statement never
travels from them into `kb/` without the normal source/provenance process.
`tools/wikitool doctor` checks the result in step 13 (`personalization`): a missing file is a
`tools/wikitool doctor` checks the result in step 12 (`personalization`): a missing file is a
`FAIL`, and so is one still carrying the sentinel - a renamed template is not a filled-in
one.
7. **Run the preflight** ([preflight.md](preflight.md)). It checks Python, git and ripgrep,
records their paths in `.wikitool-tools.json` and creates `tools/.venv` - no `tools/wikitool`
call works before it has passed:
```bash
tools/preflight.sh
```
From PowerShell 7 on Windows, run the twin instead - same questions, same file:
```powershell
pwsh -NoProfile -ExecutionPolicy Bypass -File tools/preflight.ps1
```
On exit 42, show its output to the user verbatim and wait; run it again once they have
acted. Continue here only after it exits 0.
8. **Publish the skills:**
6. **Publish the skills:**
```bash
tools/wikitool instructions sync
```
9. **Decision point - record the environment.** The distribution ships
`ENVIRONMENT.md.template`: harness, published skills, reachable MCP servers, connectors, git
remotes, where CI runs. Constants a session would otherwise ask about every time.
7. **Decision point - record the environment.** The release ships `ENVIRONMENT.md.template`:
harness, published skills, reachable MCP servers, connectors, git remotes, where CI runs.
Constants a session would otherwise ask about every time.
Unlike step 6, this step is **optional** and not an interview. Whatever can be read off the
Unlike step 5, this step is **optional** and not an interview. Whatever can be read off the
checkout itself (`git remote -v`, the running harness, the skills just published) the agent
fills in; for the rest it asks once and accepts "I don't know" as an answer - an empty
section is deleted, not filled with something plausible. Remove the sentinel line
(`wikitool:template-unfilled`) when writing; the `.template` stays where it is.
If the step is skipped, everything still works: `doctor` reports
`environment: absent (optional)` in step 13, not a `FAIL`. The file is gitignored and enters
`environment: absent (optional)` in step 12, not a `FAIL`. The file is gitignored and enters
no commit - it describes this checkout, not the repo.
10. **Decision point - telemetry.** The default follows the installation path, not this step: an
instance delivered via `dist export` - every instance that arrives here without having taken
route C (a direct clone of the origin repo) - carries a `.wikitool-release.json` and starts
with telemetry **off**; nobody asked for it, and nobody reads `EVALS.md` before the first
file is written anyway. This step only asks whether the operator wants to reverse that.
8. **Decision point - telemetry.** Every instance installed from a release carries a
`.wikitool-release.json` and starts with telemetry **off**; nobody asked for it, and nobody
reads `EVALS.md` before the first file is written anyway. This step only asks whether the
operator wants to reverse that.
Ask the user once: telemetry on? If yes, create `.wikitool-telemetry.json` in the repo root
(per checkout, gitignored, no `.template` - like `.wikitool-remotes.json`):
Ask the user once: telemetry on? If yes, create `.wikitool-telemetry.json` in the repo root
(per checkout, gitignored, no `.template` - like `.wikitool-remotes.json`):
```json
{ "enabled": true }
```
`max_session_bytes` (default 5 MiB) and `keep_sessions` (default 250) are optional in the
same file; most instances need not touch them. If no, do nothing - the default is already
off, and no file is created. `WIKI_TRACE` still overrides in both directions, should a
single session need to differ.
`tools/wikitool doctor` reports the result in step 14 (`telemetry`): on/off, why
(installation form, this file, or `WIKI_TRACE`), and the current volume against both caps -
never a `FAIL`, since both directions are a valid state. More on this:
[EVALS.md](../EVALS.md) § "Whether it runs at all".
11. **Decision point - task tracker.** The instance ships the `project` type and the collection
its type-spec's `base_dir:` names (`kb/gtd/` here), so committed initiatives have a page from
the start. What they do *not* have until this step is the other half of the weekly review:
the tracker that owns the open items, which `tools/wikitool review` joins those pages against
over the project name. No tracker configured is a legitimate end state - the pages work
alone, `review` simply says so and refuses - so ask rather than assume.
Ask the user once: is there a task tracker to connect? If yes, create `.wikitool-tasks.json`
in the repo root (per checkout, no `.template`, **gitignored once it holds a token** - like
`.wikitool-telemetry.json` and `.wikitool-remotes.json`), with the provider's own section and
the three thresholds the review reads as configuration rather than schema. The shape, the
shipped providers, and what Super Productivity in particular needs are in
[INSTALL.md](../INSTALL.md) § Konfiguration; do not restate them here. If no, do nothing - no
file is created, and adding one later needs nothing from this procedure.
`doctor` reports the result in step 14 (`tasks`): absent is `OK`, a malformed file is the one
`FAIL` here (a broken opt-in must not read as "no tracker configured"), and a configured
provider that is simply not running is never a fault.
12. **Scope the session budget** (details: [session-setup.md](session-setup.md)):
```bash
export WIKITOOL_SESSION_ID="wiki-$(date +%s)"
```json
{ "enabled": true }
```
13. **Build the generated indexes** - `dist export` deliberately does not ship them:
`max_session_bytes` (default 5 MiB) and `keep_sessions` (default 250) are optional in the
same file; most instances need not touch them. If no, do nothing - the default is already
off, and no file is created. `WIKI_TRACE` still overrides in both directions, should a
single session need to differ.
`tools/wikitool doctor` reports the result in step 12 (`telemetry`): on/off, why
(installation form, this file, or `WIKI_TRACE`), and the current volume against both caps -
never a `FAIL`, since both directions are a valid state. More on this:
[EVALS.md](../EVALS.md) § "Whether it runs at all".
9. **Decision point - task tracker.** The instance ships the `project` type and the collection
its type-spec's `base_dir:` names (`kb/gtd/` here), so committed initiatives have a page from
the start. What they do *not* have until this step is the other half of the weekly review:
the tracker that owns the open items, which `tools/wikitool review` joins those pages against
over the project name. No tracker configured is a legitimate end state - the pages work
alone, `review` simply says so and refuses - so ask rather than assume.
Ask the user once: is there a task tracker to connect? If yes, create `.wikitool-tasks.json`
in the repo root (per checkout, no `.template`, **gitignored once it holds a token** - like
`.wikitool-telemetry.json` and `.wikitool-remotes.json`), with the provider's own section and
the three thresholds the review reads as configuration rather than schema. The shape, the
shipped providers, and what Super Productivity in particular needs are in
[INSTALL.md](../INSTALL.md) § Konfiguration; do not restate them here. If no, do nothing - no
file is created, and adding one later needs nothing from this procedure.
`doctor` reports the result in step 12 (`tasks`): absent is `OK`, a malformed file is the one
`FAIL` here (a broken opt-in must not read as "no tracker configured"), and a configured
provider that is simply not running is never a fault.
10. **Scope the session budget** with the line for the shell you run in, from
[session-setup.md](session-setup.md) § Steps. Under GitHub Copilot this is what step 12's
`doctor` reads: Copilot sets no session variable of its own, so without the line `doctor`
reports `session-id: WARN` and the budget falls back to the parent process. If your harness
starts a fresh shell for every command, put the line in front of each `tools/wikitool`
call instead, in the same command - [session-setup.md](session-setup.md) says how.
11. **Build the generated indexes** - the release deliberately does not ship them:
```bash
tools/wikitool index rebuild
tools/wikitool sources rebuild-index
```
14. **Verify**, in this order:
12. **Verify**, in this order:
```bash
tools/wikitool doctor
@@ -295,27 +327,26 @@ and ready for its first ingest.
```
`doctor` must run through without a `FAIL` before anything continues - a `WARN` (no remote,
no `WIKITOOL_SESSION_ID`, say) is not a blocker. A `FAIL` names its own fix command; run it
and call `doctor` again.
say) is not a blocker. A `FAIL` names its own fix command; run it and call `doctor` again.
15. **Make the first commit:**
13. **Make the first commit:**
```bash
tools/wikitool publish --message "chore: initial instance setup"
```
The Mass-Update Gate fires here as expected: a fresh distribution consists of far more than
the ten counted files that trip the threshold, so the call ends with exit code 42. Show the
The Mass-Update Gate fires here as expected: a fresh instance consists of far more than the
ten counted files that trip the threshold, so the call ends with exit code 42. Show the
output to the user **in full** and wait; it contains the file list and the exact
`--confirm <token>` line that publishes once they approve. Details on the gate:
[gates.md](gates.md).
A local-only instance (step 4) adds `--no-push` here too. Without it the call ends with exit
A local-only instance (step 3) adds `--no-push` here too. Without it the call ends with exit
1 before the gate, because there is no remote to publish to, and commits nothing.
16. **Restart the agent session.** Harnesses read the skill directories at startup; only
afterwards are `wiki-ingest`, `wiki-query`, `wiki-manage`, `wiki-lint`, `wiki-status` and
`gtd-weekly-review` available.
14. **Restart the agent session in this folder.** Harnesses read `AGENTS.md` and the skill
directories at startup; only afterwards are `wiki-ingest`, `wiki-query`, `wiki-manage`,
`wiki-lint`, `wiki-status` and `gtd-weekly-review` available.
**A step fails and the cause is not obvious?** Do not improvise around it (invariant 7). Offer the
user a bug report - [bug-report.md](bug-report.md) - and run it only if they agree; the collector
@@ -323,10 +354,10 @@ works even when `wikitool` does not start.
## Scope
Applies only to an empty distribution produced by `dist export`. For an existing clone of this
source repo see [bootstrap.md](bootstrap.md) - there the git repo, author and content already
exist, and only the tool environment (step 7) plus the skills (step 8) are missing.
Applies only to an empty folder (or an empty clone) and a release. A further checkout of an
instance that already exists has its git repo, author and content already; it needs only the
preflight and the skills - see [bootstrap.md](bootstrap.md).
One exception: step 6 (personalization) also applies to an existing clone that has no
One exception: the personalization step (5) also applies to an existing checkout that has no
`USER.md`/`SOUL.md` yet - there as a single catch-up step, not as a whole procedure.
`bootstrap.md` points here for it.