docs: dist upgrade - Stamp-Semantik nach --keep-local, drei Eigentumsklassen in docs/ (#7)
Files changed: - CHANGES.md - VERSION - docs/ownership-and-templates.md - tools/CONTRACT.md
This commit is contained in:
+25
-1
@@ -35,7 +35,7 @@ dev-checkout concern - readable here, never shipped as something to parse.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 4.5.0-beta.4 - 2026-09-04 - dist upgrade: apply a stack update, not just detect one (#7)
|
## 4.5.0-beta.5 - 2026-09-04 - dist upgrade: Stamp-Semantik nach --keep-local benannt, docs/ownership-and-templates.md auf drei Eigentumsklassen nachgezogen
|
||||||
|
|
||||||
**Author:** Torben Nehmer
|
**Author:** Torben Nehmer
|
||||||
|
|
||||||
@@ -45,6 +45,7 @@ dev-checkout concern - readable here, never shipped as something to parse.
|
|||||||
- upstream merge: combined-commit regression test (edit+add+delete+contract+template+contract-delete in one commit)
|
- upstream merge: combined-commit regression test (edit+add+delete+contract+template+contract-delete in one commit)
|
||||||
- upstream merge: keep gitignored local data under a content stage, refuse a merge git never opened, report what actually changed
|
- upstream merge: keep gitignored local data under a content stage, refuse a merge git never opened, report what actually changed
|
||||||
- dist upgrade: apply a stack update, not just detect one (#7)
|
- dist upgrade: apply a stack update, not just detect one (#7)
|
||||||
|
- dist upgrade: Stamp-Semantik nach --keep-local benannt, docs/ownership-and-templates.md auf drei Eigentumsklassen nachgezogen
|
||||||
<!-- /wikitool:bumps -->
|
<!-- /wikitool:bumps -->
|
||||||
|
|
||||||
Die Prosa zu 4.4.0 - Changelog-Eintrag, `docs/version-model.md`, `instructions/dev/version-parts.md`,
|
Die Prosa zu 4.4.0 - Changelog-Eintrag, `docs/version-model.md`, `instructions/dev/version-parts.md`,
|
||||||
@@ -208,6 +209,29 @@ Collection-Templates umgeht, deren Namen eine fremde Instanz gar nicht hat - es
|
|||||||
`upstream merge` und schreibt sie, was ein eigenes Issue gegen den Export wäre, keins gegen das
|
`upstream merge` und schreibt sie, was ein eigenes Issue gegen den Export wäre, keins gegen das
|
||||||
Upgrade.
|
Upgrade.
|
||||||
|
|
||||||
|
**Sechster Bump: die ungeprüfte Phase nachgeholt.** Der Abschluss des vorigen Bumps lief auf
|
||||||
|
Sonnet, und `stack-dev` Schritt 6 verlangt dort genau zwei Dinge, die kein Check erzwingt:
|
||||||
|
Issue-Body und `docs/`-Veralterung. Der Body war gemacht, die `docs/`-Prüfung nicht - sie wurde
|
||||||
|
benannt statt durchgeführt. Nachgeholt auf Opus, mit einem Fund.
|
||||||
|
|
||||||
|
`docs/ownership-and-templates.md` § „The consequence in practice" beschrieb ein Upgrade als
|
||||||
|
Zweiteilung: verbatim überschreiben, `.template`-gestützte Dateien liegen lassen - und begründete
|
||||||
|
den ersten Teil damit, dass verbatim ausgelieferte Dateien „safe to replace wholesale" seien,
|
||||||
|
weil sie „never instance-specific to begin with" waren. Genau diese Annahme trifft `dist upgrade`
|
||||||
|
nicht: eine Instanz *kann* eine verbatim ausgelieferte Datei angefasst haben, und die sha256 je
|
||||||
|
Datei existiert, um das zu erkennen, statt es vorauszusetzen. Dazu fehlte die dritte Klasse ganz -
|
||||||
|
die einmalig gesäten, danach instanzeigenen Pfade (`.wikitool-kb.json`, `CHANGES.md`,
|
||||||
|
`kb/log.md`, `raw/*/.gitkeep`), die im Stamp stehen wie jede andere Datei und deshalb aktiv
|
||||||
|
ausgeschlossen werden müssen. Die Seite nennt jetzt drei Klassen und die engere praktische Regel:
|
||||||
|
überschreibe die verbatim ausgelieferten Dateien, *die diese Instanz nicht angefasst hat*.
|
||||||
|
|
||||||
|
Dazu eine Präzisierung in `tools/CONTRACT.md`, die vorher nirgends stand: nach `--keep-local`
|
||||||
|
wird der neue Stamp trotzdem vollständig geschrieben, trägt also die Release-Summe auch für
|
||||||
|
Dateien, die bewusst *nicht* geschrieben wurden. Der Stamp ist die Vergleichsbasis für den
|
||||||
|
nächsten Lauf, kein wörtliches Inventar der Platte - und genau das hält eine übersprungene Datei
|
||||||
|
bei jedem weiteren Lauf als abweichend gemeldet, statt sie nach einmaligem Überspringen still als
|
||||||
|
aktuell zu führen.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 4.4.0 - 2026-09-03 - Versionskandidat statt Bump-pro-Release: VERSION traegt -beta.N, version release fixiert
|
## 4.4.0 - 2026-09-03 - Versionskandidat statt Bump-pro-Release: VERSION traegt -beta.N, version release fixiert
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ Chemenu ships two kinds of files side by side, and at a glance they look the sam
|
|||||||
plain markdown, both sit in the repo root or under `kb/`, both get read at session start. But a
|
plain markdown, both sit in the repo root or under `kb/`, both get read at session start. But a
|
||||||
stack upgrade treats them completely differently. Some - [AGENTS.md](../AGENTS.md),
|
stack upgrade treats them completely differently. Some - [AGENTS.md](../AGENTS.md),
|
||||||
[kb/CONTRACT.md](../kb/CONTRACT.md), the per-stage contracts - are identical in every instance
|
[kb/CONTRACT.md](../kb/CONTRACT.md), the per-stage contracts - are identical in every instance
|
||||||
that runs this stack and can simply be overwritten by the next release. Others - `USER.md`,
|
that runs this stack and are the next release's to replace (with one caveat about local edits,
|
||||||
|
below). Others - `USER.md`,
|
||||||
`SOUL.md`, `kb/CONVENTIONS.md`, `ENVIRONMENT.md` - describe one particular instance, and
|
`SOUL.md`, `kb/CONVENTIONS.md`, `ENVIRONMENT.md` - describe one particular instance, and
|
||||||
overwriting them would silently erase a choice someone made on purpose.
|
overwriting them would silently erase a choice someone made on purpose.
|
||||||
|
|
||||||
@@ -82,9 +83,33 @@ state rather than a sign setup was skipped.
|
|||||||
|
|
||||||
## The consequence in practice
|
## The consequence in practice
|
||||||
|
|
||||||
Running a stack upgrade against an existing instance boils down to: overwrite the verbatim
|
An upgrade sorts every shipped path into three categories, not two - and the third one only
|
||||||
files, leave the `.template`-sourced files alone. The verbatim files are safe to replace
|
becomes visible once an upgrade is a command rather than a hand-run copy:
|
||||||
wholesale because they were never instance-specific to begin with - identical content going
|
|
||||||
back in changes nothing an instance actually decided. The template-sourced files were filled in
|
- **Verbatim files** - `AGENTS.md`, `kb/CONTRACT.md`, the per-stage contracts, everything under
|
||||||
once, by a person, for a reason, and nothing about a newer release of the stack's mechanics
|
`tools/`, `types/` and `instructions/` - are the release's to replace.
|
||||||
gives it standing to override that.
|
- **`.template`-sourced files** - `USER.md`, `SOUL.md`, `kb/CONVENTIONS.md`, each
|
||||||
|
`kb/<name>/COLLECTION.md`, `ENVIRONMENT.md`, the `root: kb` type-specs - are never written by
|
||||||
|
an upgrade at all. The distribution ships only the `.template` beside them, so the filled file
|
||||||
|
is out of reach by construction rather than by a rule someone has to remember.
|
||||||
|
- **Seeded-once files** - `.wikitool-kb.json`, `CHANGES.md`, `kb/log.md`, `raw/*/.gitkeep` - are
|
||||||
|
written into a *new* instance by `dist export` and belong to the instance from then on. They
|
||||||
|
are the awkward category: they sit in the release stamp's file list like any other shipped
|
||||||
|
file, so an upgrade has to exclude them deliberately (`chemenu.ownership.is_export_stub` and
|
||||||
|
`is_upgrade_preserved`). An upgrade that re-seeded them would reset the record of which
|
||||||
|
migrations ran, or erase the changelog the instance wrote for itself.
|
||||||
|
|
||||||
|
The first category carries a caveat that the word "verbatim" hides. It says who *decides* the
|
||||||
|
content, not that overwriting is always safe: an instance can still have edited a verbatim file
|
||||||
|
- a patched `tools/`, a locally adjusted instruction - and an upgrade assuming otherwise would
|
||||||
|
destroy that silently. Avoiding that assumption is the whole reason `dist export` records a
|
||||||
|
sha256 per shipped file in `.wikitool-release.json`. `wikitool dist upgrade` compares every
|
||||||
|
candidate path against the digest recorded when it was installed, overwrites only what still
|
||||||
|
matches, and refuses rather than overwrite what does not.
|
||||||
|
|
||||||
|
So the practical rule is narrower than "overwrite the verbatim files, leave the rest alone":
|
||||||
|
overwrite the verbatim files *this instance has not touched*, never write the other two
|
||||||
|
categories, and make a locally changed file a decision someone takes deliberately instead of
|
||||||
|
one an upgrade takes for them. The template-sourced files were filled in once, by a person, for
|
||||||
|
a reason, and nothing about a newer release of the stack's mechanics gives it standing to
|
||||||
|
override that.
|
||||||
|
|||||||
+1
-1
@@ -72,7 +72,7 @@ tools/wikitool <command> --help
|
|||||||
| `eval sessions [--json]` | List the sessions that have a trace under `reports/telemetry/`, most recent first. Read-only and exempt from the Iteration Budget Gate |
|
| `eval sessions [--json]` | List the sessions that have a trace under `reports/telemetry/`, most recent first. Read-only and exempt from the Iteration Budget Gate |
|
||||||
| `eval score [--session <id>] [--json] [--markdown out.md] [--save] [--fail-on-error]` | Score one traced session: structural state from `lint`'s own checks (L1) plus trajectory rules over the trace (L2) - was a refused call repeated unchanged, was a gate flag passed without that gate having refused anything, did a publish of `kb/` pages go unlogged. Defaults to the current session. `--save` writes `reports/evals/<date>/<session>.{json,md}`. Read-only over `kb/` and exempt from the budget; see [../EVALS.md](../EVALS.md) |
|
| `eval score [--session <id>] [--json] [--markdown out.md] [--save] [--fail-on-error]` | Score one traced session: structural state from `lint`'s own checks (L1) plus trajectory rules over the trace (L2) - was a refused call repeated unchanged, was a gate flag passed without that gate having refused anything, did a publish of `kb/` pages go unlogged. Defaults to the current session. `--save` writes `reports/evals/<date>/<session>.{json,md}`. Read-only over `kb/` and exempt from the budget; see [../EVALS.md](../EVALS.md) |
|
||||||
| `dist export <target> [--dry-run] [--source-repo U] [--source-commit SHA] [--release-url U] [--update-url U]` | Write a contentless, distributable copy of this repo's machinery into an empty `<target>` directory: `AGENTS.md`/`README.md`/`EVALS.md` with any `<!-- dist:strip-start -->...<!-- dist:strip-end -->` region removed, `instructions/` (minus `instructions/dev/`), `types/` (the `root: kb` page type-specs and their schemas re-keyed as `.template`, the stack's own verbatim), `docs/` verbatim, `tools/` (no venv/caches), the `.github/hooks/`+`.vibe/` session-tracing config plus `.claude/settings.json`, `kb/CONTRACT.md` (no pages, no areas), empty `raw/{articles,documents,notes,assets}/`, `VERSION`, `USER.md.template`/`SOUL.md.template` plus `kb/CONVENTIONS.md.template` and each collection's contract re-keyed as `kb/<name>/COLLECTION.md.template` (the templates ship; the filled `USER.md`/`SOUL.md`/`kb/CONVENTIONS.md`/`kb/<name>/COLLECTION.md`/`types/<page-type>.md` never do - all of them bind their instance and none are the stack's to decide, and `find_leaks` refuses a plan carrying one), and a generated `.wikitool-release.json` stamp (version, export date, origin, and a sha256 per exported file - the base a later upgrade would compare against). The four origin options only fill stamp fields: `export` never calls git and cannot discover them. Refuses a non-empty target, and a tree with no `VERSION`. See `instructions/setup-instance.md`. One-way: there is no command that reconstructs a distributed instance into a dev instance - work on the stack in the origin repo (or a new dev instance exported from it) instead |
|
| `dist export <target> [--dry-run] [--source-repo U] [--source-commit SHA] [--release-url U] [--update-url U]` | Write a contentless, distributable copy of this repo's machinery into an empty `<target>` directory: `AGENTS.md`/`README.md`/`EVALS.md` with any `<!-- dist:strip-start -->...<!-- dist:strip-end -->` region removed, `instructions/` (minus `instructions/dev/`), `types/` (the `root: kb` page type-specs and their schemas re-keyed as `.template`, the stack's own verbatim), `docs/` verbatim, `tools/` (no venv/caches), the `.github/hooks/`+`.vibe/` session-tracing config plus `.claude/settings.json`, `kb/CONTRACT.md` (no pages, no areas), empty `raw/{articles,documents,notes,assets}/`, `VERSION`, `USER.md.template`/`SOUL.md.template` plus `kb/CONVENTIONS.md.template` and each collection's contract re-keyed as `kb/<name>/COLLECTION.md.template` (the templates ship; the filled `USER.md`/`SOUL.md`/`kb/CONVENTIONS.md`/`kb/<name>/COLLECTION.md`/`types/<page-type>.md` never do - all of them bind their instance and none are the stack's to decide, and `find_leaks` refuses a plan carrying one), and a generated `.wikitool-release.json` stamp (version, export date, origin, and a sha256 per exported file - the base a later upgrade would compare against). The four origin options only fill stamp fields: `export` never calls git and cannot discover them. Refuses a non-empty target, and a tree with no `VERSION`. See `instructions/setup-instance.md`. One-way: there is no command that reconstructs a distributed instance into a dev instance - work on the stack in the origin repo (or a new dev instance exported from it) instead |
|
||||||
| `dist upgrade <source> [--dry-run] [--keep-local] [--prune] [--pre]` | Apply a stack update `dist export` produced - the write half of `version check`. Never downloads anything: `<source>` is an already-fetched export directory or `.tar.gz` release archive (verified against a sibling `.sha256` if one is present; WARNs, does not block, if it is absent), which must unpack to exactly one top-level directory - the shape `.gitea/workflows/release.yml` packs. The write set is exactly the *new* `.wikitool-release.json`'s `files` block, minus what an export re-seeds from a blank template every time (`kb/log.md`, `raw/*/.gitkeep` - `chemenu.ownership.is_export_stub`) or seeds once and the instance owns from then on (`.wikitool-kb.json`, `CHANGES.md` - `chemenu.ownership.is_upgrade_preserved`), plus the stamp itself, always rewritten. Every candidate path is classified against the *local* `.wikitool-release.json`'s recorded digest for it: unchanged is overwritten silently, absent from the old stamp is created, and locally modified or locally deleted is **never** silently overwritten - the run aborts with the full list unless `--keep-local` says to proceed and leave every one of them untouched. A path in the old stamp but not the new one is reported as no longer part of the release and left alone unless `--prune` is passed, which removes it only if it is still unchanged since installation. Reports the migration chain the new machinery would owe (`chemenu.kb_state.chain` over the *new* tree's `instructions/migrations/`, read via a `directory` argument to `load_migrations`) but never runs any of it - there is no `migrate run`. Refuses before touching the source at all when: `VERSION` or `.wikitool-release.json` (with a `files` block) is missing locally, `.wikitool-kb.json` is missing, a migration is already outstanding against the *installed* machinery, or the working tree is dirty (not being a git repository at all is a WARN, not a refusal). Refuses after reading the source when: it carries no `VERSION`/`.wikitool-release.json`/`files` block, its version is older than or equal to the installed one (equal is a no-op success), or it is a pre-release (`-beta.N`) without `--pre`. Reports, but does not block on, a crossed compatibility boundary. Never touches git - no commit, no push (invariant 5). See Gitea #7 and `INSTALL.md` § "Eine Instanz aktualisieren" |
|
| `dist upgrade <source> [--dry-run] [--keep-local] [--prune] [--pre]` | Apply a stack update `dist export` produced - the write half of `version check`. Never downloads anything: `<source>` is an already-fetched export directory or `.tar.gz` release archive (verified against a sibling `.sha256` if one is present; WARNs, does not block, if it is absent), which must unpack to exactly one top-level directory - the shape `.gitea/workflows/release.yml` packs. The write set is exactly the *new* `.wikitool-release.json`'s `files` block, minus what an export re-seeds from a blank template every time (`kb/log.md`, `raw/*/.gitkeep` - `chemenu.ownership.is_export_stub`) or seeds once and the instance owns from then on (`.wikitool-kb.json`, `CHANGES.md` - `chemenu.ownership.is_upgrade_preserved`), plus the stamp itself, always rewritten. Every candidate path is classified against the *local* `.wikitool-release.json`'s recorded digest for it: unchanged is overwritten silently, absent from the old stamp is created, and locally modified or locally deleted is **never** silently overwritten - the run aborts with the full list unless `--keep-local` says to proceed and leave every one of them untouched. After a `--keep-local` run the new stamp is still written whole, so it records the release's digest for files that were deliberately *not* written: the stamp is the baseline for the next comparison, not a literal inventory of what is on disk. That is what keeps a skipped file diverging - and therefore reported - on every later run, rather than quietly reading as current once it has been skipped once. A path in the old stamp but not the new one is reported as no longer part of the release and left alone unless `--prune` is passed, which removes it only if it is still unchanged since installation. Reports the migration chain the new machinery would owe (`chemenu.kb_state.chain` over the *new* tree's `instructions/migrations/`, read via a `directory` argument to `load_migrations`) but never runs any of it - there is no `migrate run`. Refuses before touching the source at all when: `VERSION` or `.wikitool-release.json` (with a `files` block) is missing locally, `.wikitool-kb.json` is missing, a migration is already outstanding against the *installed* machinery, or the working tree is dirty (not being a git repository at all is a WARN, not a refusal). Refuses after reading the source when: it carries no `VERSION`/`.wikitool-release.json`/`files` block, its version is older than or equal to the installed one (equal is a no-op success), or it is a pre-release (`-beta.N`) without `--pre`. Reports, but does not block on, a crossed compatibility boundary. Never touches git - no commit, no push (invariant 5). See Gitea #7 and `INSTALL.md` § "Eine Instanz aktualisieren" |
|
||||||
| `version show [--json]` | Print this instance's stack version and where it came from (development tree, or a distribution with its export date and origin). Bare `wikitool version` is an alias for this. Read-only, offline, and **exempt from the Iteration Budget Gate** |
|
| `version show [--json]` | Print this instance's stack version and where it came from (development tree, or a distribution with its export date and origin). Bare `wikitool version` is an alias for this. Read-only, offline, and **exempt from the Iteration Budget Gate** |
|
||||||
| `version check [--url U] [--timeout S] [--json]` | Ask the origin's release feed whether a newer stack exists, and whether the step crosses a compatibility boundary (`state: current\|update\|migration\|ahead`). **The only command in `wikitool` that makes a network call** - never reached implicitly from another command, needs no key, times out, and reports an unreachable feed as an error rather than as "up to date". The feed is `$WIKITOOL_UPDATE_URL`, else the release stamp's, else the built-in origin; `$WIKITOOL_UPDATE_TOKEN` is only needed if that feed is not readable anonymously. Read-only and exempt from the budget gate |
|
| `version check [--url U] [--timeout S] [--json]` | Ask the origin's release feed whether a newer stack exists, and whether the step crosses a compatibility boundary (`state: current\|update\|migration\|ahead`). **The only command in `wikitool` that makes a network call** - never reached implicitly from another command, needs no key, times out, and reports an unreachable feed as an error rather than as "up to date". The feed is `$WIKITOOL_UPDATE_URL`, else the release stamp's, else the built-in origin; `$WIKITOOL_UPDATE_TOKEN` is only needed if that feed is not readable anonymously. Read-only and exempt from the budget gate |
|
||||||
| `version notes [--version X.Y.Z]` | Print one version's `CHANGES.md` entry, for use as release notes (default: this tree's `VERSION`). Read-only and exempt from the budget gate |
|
| `version notes [--version X.Y.Z]` | Print one version's `CHANGES.md` entry, for use as release notes (default: this tree's `VERSION`). Read-only and exempt from the budget gate |
|
||||||
|
|||||||
Reference in New Issue
Block a user