docs/ als ausgelieferter Hintergrund-Ort; Decision-Seiten bleiben in kb/, Decay-Skip fuer concept_type: decision (4.3.0, #38)
Files changed: - AGENTS.md - CHANGES.md - VERSION - instructions/kb-profiles.md - kb/CONVENTIONS.md - kb/concepts/COLLECTION.md - tools/CONTRACT.md - tools/chemenu/commands/confidence_decay.py - tools/chemenu/commands/dist_cmd.py - tools/chemenu/tests/test_confidence_decay.py - tools/chemenu/tests/test_dist_cmd.py
This commit is contained in:
@@ -82,6 +82,7 @@ What a file is called says who it is for and how it is loaded. This is a rule, n
|
|||||||
| `instructions/<name>.md` | Agents | By link, or on explicit request |
|
| `instructions/<name>.md` | Agents | By link, or on explicit request |
|
||||||
| `instructions/<name>/SKILL.md` | Agents | By the harness, once published |
|
| `instructions/<name>/SKILL.md` | Agents | By the harness, once published |
|
||||||
| `types/<name>.md` | Agents + validator | Via `tools/wikitool types describe`. Split by `root:`: a page type-spec (`root: kb`) belongs to the instance and ships as `.template`; one describing a stack artifact ships verbatim |
|
| `types/<name>.md` | Agents + validator | Via `tools/wikitool types describe`. Split by `root:`: a page type-spec (`root: kb`) belongs to the instance and ships as `.template`; one describing a stack artifact ships verbatim |
|
||||||
|
| `docs/<name>.md` | Agents and humans | By link, or on explicit request - never automatically, and never as instruction |
|
||||||
| `INDEX.md` | Both | Generated - never hand-edited |
|
| `INDEX.md` | Both | Generated - never hand-edited |
|
||||||
|
|
||||||
A stage may carry both a `README.md` and a `CONTRACT.md`: different readers, different
|
A stage may carry both a `README.md` and a `CONTRACT.md`: different readers, different
|
||||||
@@ -89,6 +90,16 @@ documents. What it may not carry is the same content twice - a README that resta
|
|||||||
contract is a second copy that drifts. `docs verify` enforces the specific case that already
|
contract is a second copy that drifts. `docs verify` enforces the specific case that already
|
||||||
happened once: no README may hold a copy of the `wikitool` command table.
|
happened once: no README may hold a copy of the `wikitool` command table.
|
||||||
|
|
||||||
|
**`docs/` carries no normative sentence.** It holds why the stack is built the way it is -
|
||||||
|
background a session consults in passing, not a rule it must follow. Anything that would bind
|
||||||
|
belongs in a `CONTRACT.md` instead, which is what keeps invariant 8 intact here: `docs/` is
|
||||||
|
never a second place a rule could live, only prose about rules that live elsewhere. That is also
|
||||||
|
why nothing verifies its content - there is no rule in it to check. It has no frontmatter, no type, no index, no lint, no decay, no provenance, and no
|
||||||
|
`COLLECTION.md` - which [kb/CONTRACT.md § Collections](kb/CONTRACT.md#collections) forbids
|
||||||
|
outside `kb/` anyway, but the point holds independently: `docs/` stays a plain directory of
|
||||||
|
prose, invisible to everything `tools/wikitool` does except `dist export`, which copies it
|
||||||
|
verbatim. A fresh instance needs the reasoning as much as this one does.
|
||||||
|
|
||||||
## Personalization
|
## Personalization
|
||||||
|
|
||||||
`USER.md` and `SOUL.md` are read at session start, if the runtime has not already injected
|
`USER.md` and `SOUL.md` are read at session start, if the runtime has not already injected
|
||||||
@@ -145,7 +156,8 @@ input schema + compiler output derived (gitignored)
|
|||||||
work/ tracked scratch, deleted when the run closes
|
work/ tracked scratch, deleted when the run closes
|
||||||
```
|
```
|
||||||
|
|
||||||
Alongside it, not part of it: `instructions/` (what agents are told to do) and this file.
|
Alongside it, not part of it: `instructions/` (what agents are told to do), `docs/` (why the
|
||||||
|
stack is built the way it is - see [File naming](#file-naming)), and this file.
|
||||||
|
|
||||||
**By stage** - read the contract for the stage you are writing in:
|
**By stage** - read the contract for the stage you are writing in:
|
||||||
|
|
||||||
|
|||||||
+51
@@ -20,6 +20,57 @@ their date-only headings.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 4.3.0 - 2026-09-03 - docs/ als ausgelieferter Hintergrund-Ort; Decision-Seiten bleiben in kb/, Decay-Skip fuer concept_type: decision
|
||||||
|
|
||||||
|
**Author:** Torben Nehmer
|
||||||
|
|
||||||
|
Gitea #38: `dist export` lieferte bislang keine einzige `kb/`-Seite aus - eine frische Instanz
|
||||||
|
bekam den Stack, aber keinen Grund für seine Form. Die dokumentierte `adr-NNN-`-Konvention in
|
||||||
|
`kb/concepts/COLLECTION.md` existierte zudem nur auf Papier: keine der sieben
|
||||||
|
`concept_type: decision`-Seiten folgte ihr, und `confidence_decay()` lief bedingungslos über sie
|
||||||
|
- ein Kategorienfehler, weil Zeitablauf eine Entscheidung nicht falscher macht, nur Supersession
|
||||||
|
tut das.
|
||||||
|
|
||||||
|
**Neu:** `docs/` - ein inertes Verzeichnis für Stack-Hintergrund (warum der Stack so gebaut ist,
|
||||||
|
nicht was diese Instanz entschieden hat). Keine Frontmatter, kein Typ, kein Index, kein Lint,
|
||||||
|
keine Decay, keine Provenance, keine `COLLECTION.md`. `dist export` liefert es verbatim aus, wie
|
||||||
|
`instructions/` und `types/`. Befüllung folgt in Gitea #45.
|
||||||
|
|
||||||
|
**Verworfen, nach Prüfung:** ein Umzug der sieben Decision-Seiten nach `decisions/`. Der
|
||||||
|
Subtyp-Floor aus #28 verlangt mindestens eine Seite je deklariertem `concept_type`, und ein
|
||||||
|
Umzug hätte `decision` auf null gebracht; dazu zeigen 89 Wikilinks aus `kb/` sowie
|
||||||
|
tool-eigene Frontmatter-Arrays auf die sieben, und `links.py`/`xref add` kennen kein Ziel
|
||||||
|
außerhalb `kb/`. Die sieben bleiben in `kb/concepts/`, ebenso ein zweiter, separat erwogener
|
||||||
|
Rename (`docs verify` → `parity verify`) - der wäre nur nötig gewesen, wenn ein Befehl auf das
|
||||||
|
Verzeichnis `docs/` wirkt, und keiner tut das.
|
||||||
|
|
||||||
|
**Geändert:**
|
||||||
|
- `confidence_decay()` überspringt `concept_type: decision` strukturell (kategorische Ausnahme,
|
||||||
|
nicht als Brücke gebaut - Begründung im Docstring).
|
||||||
|
- `kb/concepts/COLLECTION.md` § Decisions ersetzt die tote ADR-Vorlage durch die real gelebte
|
||||||
|
Form: eine Entscheidung ist eine gewöhnliche Concept-Seite, organische Prosa, kein
|
||||||
|
`adr-NNN-`-Präfix, `**Status:**` optional, Supersession per `supersedes`-Link.
|
||||||
|
- `kb/CONVENTIONS.md` § Naming und `instructions/kb-profiles.md` (Profil `german`) korrigiert -
|
||||||
|
beide dokumentierten noch die verworfene `adr-NNN-`-Namensregel.
|
||||||
|
- `AGENTS.md` § File naming und § Routing: `docs/`-Zeile, plus die Regel, dass `docs/` keinen
|
||||||
|
normativen Satz trägt (das hält Invariante 8 heil - was binden würde, gehört in einen
|
||||||
|
Contract).
|
||||||
|
- `tools/CONTRACT.md`: Klarstellung, dass `docs verify` Dokumentations-Parität prüft, nicht das
|
||||||
|
`docs/`-Verzeichnis, sowie `docs/` in der `dist export`-Zeile ergänzt.
|
||||||
|
|
||||||
|
Additiv und in beide Richtungen drop-in: eine bestehende Instanz ohne `docs/` exportiert
|
||||||
|
weiterhin identisch (leerer `_copy_tree`-Treffer), eine Instanz mit `docs/` bekommt es ab jetzt
|
||||||
|
mitgeliefert. Kein Feld, kein Kommando ändert sein Verhalten für bestehenden Inhalt.
|
||||||
|
|
||||||
|
**Migration:** none required.
|
||||||
|
|
||||||
|
Berührt: `tools/chemenu/commands/confidence_decay.py`, `tools/chemenu/commands/dist_cmd.py`,
|
||||||
|
`tools/chemenu/tests/test_confidence_decay.py`, `tools/chemenu/tests/test_dist_cmd.py`,
|
||||||
|
`kb/concepts/COLLECTION.md`, `kb/CONVENTIONS.md`, `instructions/kb-profiles.md`, `AGENTS.md`,
|
||||||
|
`tools/CONTRACT.md`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 4.2.0 - 2026-09-03 - Korpus-Kuratierungsrichtlinie: Untergrenzen und Leitplanke für reaktive Fixes
|
## 4.2.0 - 2026-09-03 - Korpus-Kuratierungsrichtlinie: Untergrenzen und Leitplanke für reaktive Fixes
|
||||||
|
|
||||||
**Author:** Torben Nehmer
|
**Author:** Torben Nehmer
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ stack's hardcoded behaviour until the conventions file existed.
|
|||||||
|---|---|
|
|---|---|
|
||||||
| `language:` | `de` |
|
| `language:` | `de` |
|
||||||
| `sections:` | `Beziehungen` / `Siehe auch` / `Fußnoten` |
|
| `sections:` | `Beziehungen` / `Siehe auch` / `Fußnoten` |
|
||||||
| Naming | Human-readable titles with spaces; singular for entities; `adr-NNN-` for decisions; `X vs Y` for comparisons |
|
| Naming | Human-readable titles with spaces; singular for entities; a decision named like any other concept, no `adr-NNN-` prefix; `X vs Y` for comparisons |
|
||||||
| Tone | Wikipedia register, with a German buzzword and filler list |
|
| Tone | Wikipedia register, with a German buzzword and filler list |
|
||||||
| Relationship labels | `hängt ab von` · `verwendet` · `implementiert` · `erweitert` · `ersetzt` · `steht in Konflikt mit` · `benötigt` · `erzeugt` · `konsumiert` · `besitzt` · `pflegt` · `läuft auf` · `verwandt mit` |
|
| Relationship labels | `hängt ab von` · `verwendet` · `implementiert` · `erweitert` · `ersetzt` · `steht in Konflikt mit` · `benötigt` · `erzeugt` · `konsumiert` · `besitzt` · `pflegt` · `läuft auf` · `verwandt mit` |
|
||||||
| Confidence rubric | 0.5 base, +0.2 per supporting source (max +0.6), recency and source-quality bonuses; hedge with "möglicherweise"/"kann" below 0.6, "unsicher"/"unbestätigt" below 0.4 |
|
| Confidence rubric | 0.5 base, +0.2 per supporting source (max +0.6), recency and source-quality bonuses; hedge with "möglicherweise"/"kann" below 0.6, "unsicher"/"unbestätigt" below 0.4 |
|
||||||
|
|||||||
+2
-1
@@ -62,7 +62,8 @@ There is no `## Siehe auch` region any more. It was the reciprocal half of a bid
|
|||||||
- Human-readable titles with spaces: `Hybrid Search.md`, `Gitea Actions.md` - not kebab-case.
|
- Human-readable titles with spaces: `Hybrid Search.md`, `Gitea Actions.md` - not kebab-case.
|
||||||
- Singular for entities: `ha-core.md`, not `ha-cores.md`.
|
- Singular for entities: `ha-core.md`, not `ha-cores.md`.
|
||||||
- Comparison pages read as a comparison: `Go vs Rust.md`.
|
- Comparison pages read as a comparison: `Go vs Rust.md`.
|
||||||
- ADRs are prefixed: `adr-001-use-go-modules.md`.
|
- A decision (`concept_type: decision`) is named like any other concept - no `adr-NNN-` prefix.
|
||||||
|
See [kb/concepts/COLLECTION.md § Decisions](concepts/COLLECTION.md#decisions).
|
||||||
- Prefer readability over convention when the two conflict.
|
- Prefer readability over convention when the two conflict.
|
||||||
|
|
||||||
What to name a thing: projects use their repository or common name; systems a descriptive
|
What to name a thing: projects use their repository or common name; systems a descriptive
|
||||||
|
|||||||
+18
-10
@@ -27,19 +27,27 @@ tone, relationship labels, the confidence rubric. Neither is restated here.
|
|||||||
|
|
||||||
`concept` (`tools/wikitool types describe concept`).
|
`concept` (`tools/wikitool types describe concept`).
|
||||||
|
|
||||||
## Decisions and ADRs
|
## Decisions
|
||||||
|
|
||||||
An architectural decision is a concept page, prefixed as
|
An architectural decision is an ordinary concept page with `concept_type: decision`
|
||||||
[kb/CONVENTIONS.md § Naming](../CONVENTIONS.md#naming) says. It records:
|
(`tools/wikitool types describe concept`) - not a separate format, and not a separate location.
|
||||||
|
There is no `adr-NNN-`-prefixed filename and no dedicated directory: naming follows
|
||||||
|
[kb/CONVENTIONS.md § Naming](../CONVENTIONS.md#naming) like every other concept, and the page
|
||||||
|
lives in `kb/concepts/` like every other concept.
|
||||||
|
|
||||||
- **Context** - what forced a decision.
|
The body is organic prose under this collection's usual sections, not a fixed template. What it
|
||||||
- **Decision** - what was chosen.
|
still has to carry: what was decided, what forced the decision, what it costs (not only what it
|
||||||
- **Consequences** - what this costs, not only what it buys.
|
buys), and a link to every entity the decision affects. A `**Status:**` line is optional - most
|
||||||
- **Status** - proposed / accepted / deprecated / superseded.
|
decision pages in this instance carry none, because the page's own prose already says whether the
|
||||||
- Links to every entity the decision affects.
|
decision stands.
|
||||||
|
|
||||||
A superseded ADR is never deleted or rewritten. The new one declares `supersedes` pointing at
|
A decision superseded by a later one is never deleted or rewritten. The new page declares
|
||||||
it; the old one needs no edge back, because its inbound view renders the replacement.
|
`supersedes` pointing at it; the old one needs no edge back, because its inbound view renders the
|
||||||
|
replacement.
|
||||||
|
|
||||||
|
`concept_type: decision` is also the one subtype [kb/CONTRACT.md](../CONTRACT.md)'s confidence
|
||||||
|
machinery treats differently: `confidence decay` skips it structurally, because elapsed time does
|
||||||
|
not falsify a decision - only a later decision superseding it does.
|
||||||
|
|
||||||
## Authorised labels
|
## Authorised labels
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -68,10 +68,10 @@ tools/wikitool <command> --help
|
|||||||
| `instructions sync [--force]` | Publish every `instructions/<name>/SKILL.md` into `.agents/skills/` and `.claude/skills/` as **copies**, and delete published skills whose source is gone. Both targets are gitignored, so a fresh clone runs this once - see `instructions/bootstrap.md`. Re-running is also how a drifted copy is repaired: the source always wins. `--force` is required only to replace a target directory that is not a published skill at all (no `SKILL.md` in it) |
|
| `instructions sync [--force]` | Publish every `instructions/<name>/SKILL.md` into `.agents/skills/` and `.claude/skills/` as **copies**, and delete published skills whose source is gone. Both targets are gitignored, so a fresh clone runs this once - see `instructions/bootstrap.md`. Re-running is also how a drifted copy is repaired: the source always wins. `--force` is required only to replace a target directory that is not a published skill at all (no `SKILL.md` in it) |
|
||||||
| `instructions verify` | Check the instruction layer: flat instructions validate against `types/instruction.schema.yaml`, each `SKILL.md` carries the frontmatter its harness reads, every published copy is byte-identical to its source, no instruction is left that nothing references, and nothing under `instructions/dev/` is referenced from outside it (a `<!-- dist:strip-start/end -->` block is exempt - see [instructions/CONTRACT.md](../instructions/CONTRACT.md)). Missing *every* copy is reported as "run sync", not as drift - that is a clean checkout |
|
| `instructions verify` | Check the instruction layer: flat instructions validate against `types/instruction.schema.yaml`, each `SKILL.md` carries the frontmatter its harness reads, every published copy is byte-identical to its source, no instruction is left that nothing references, and nothing under `instructions/dev/` is referenced from outside it (a `<!-- dist:strip-start/end -->` block is exempt - see [instructions/CONTRACT.md](../instructions/CONTRACT.md)). Missing *every* copy is reported as "run sync", not as drift - that is a clean checkout |
|
||||||
| `instructions list [--json]` | List the flat instructions with their descriptions. This is how the layer is discovered; `search` deliberately covers `kb/` only |
|
| `instructions list [--json]` | List the flat instructions with their descriptions. This is how the layer is discovered; `search` deliberately covers `kb/` only |
|
||||||
| `docs verify` | Check the docs that mirror the code: every CLI command documented here (and vice versa), every directory under `kb/` has a `COLLECTION.md` and no directory outside it does, every collection declaring `profile:` and a `required_by_stack:` that agrees with the stack's own list, `kb/CONVENTIONS.md` naming all three tool-owned section headings if it exists at all, every stage contract present, no pre-migration `type: entity` blocks left in the contracts, and the `.gitignore` canaries clear in both directions (nothing ignored under `raw/`/`kb/`, everything ignored under `reports/` and the published skill directories) |
|
| `docs verify` | Check the docs that mirror the code: every CLI command documented here (and vice versa), every directory under `kb/` has a `COLLECTION.md` and no directory outside it does, every collection declaring `profile:` and a `required_by_stack:` that agrees with the stack's own list, `kb/CONVENTIONS.md` naming all three tool-owned section headings if it exists at all, every stage contract present, no pre-migration `type: entity` blocks left in the contracts, and the `.gitignore` canaries clear in both directions (nothing ignored under `raw/`/`kb/`, everything ignored under `reports/` and the published skill directories). The name is about documentation parity, not about the `docs/` directory - it neither reads nor requires one, the same way `kb/` predates the collection it now checks |
|
||||||
| `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), `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 |
|
||||||
| `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 |
|
||||||
|
|||||||
@@ -11,6 +11,14 @@ Keeping the undecayed anchor in `confidence_base` is what makes repeated runs
|
|||||||
idempotent - decaying the stored `confidence` in place (the pre-2026-08-13
|
idempotent - decaying the stored `confidence` in place (the pre-2026-08-13
|
||||||
behavior) compounded on every run, because the elapsed-months factor kept
|
behavior) compounded on every run, because the elapsed-months factor kept
|
||||||
growing while the multiplicand had already shrunk.
|
growing while the multiplicand had already shrunk.
|
||||||
|
|
||||||
|
Pages with `concept_type: decision` are skipped structurally, not as an
|
||||||
|
interim measure. The formula models staleness - a claim that nobody has
|
||||||
|
re-checked in a while becomes less trustworthy - and a decision is not a
|
||||||
|
claim about the world that time can falsify. What retires a decision is a
|
||||||
|
later decision superseding it, never elapsed months on its own; that is a
|
||||||
|
category the decay formula does not have a term for, so it does not apply
|
||||||
|
one.
|
||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
@@ -118,6 +126,8 @@ def confidence_decay(
|
|||||||
missing_base = []
|
missing_base = []
|
||||||
|
|
||||||
for title, page in sorted(pages.items()):
|
for title, page in sorted(pages.items()):
|
||||||
|
if page.frontmatter.get("concept_type") == "decision":
|
||||||
|
continue
|
||||||
confidence = page.frontmatter.get("confidence")
|
confidence = page.frontmatter.get("confidence")
|
||||||
if confidence is None:
|
if confidence is None:
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -347,6 +347,12 @@ def build_plan(origin: Optional[Origin] = None) -> dict[str, PlannedFile]:
|
|||||||
for hook_dir in HOOK_DIRS:
|
for hook_dir in HOOK_DIRS:
|
||||||
plan.update(_copy_tree(config.ROOT / hook_dir, hook_dir, frozenset()))
|
plan.update(_copy_tree(config.ROOT / hook_dir, hook_dir, frozenset()))
|
||||||
|
|
||||||
|
# docs/ is stack background - why the stack is built the way it is - and
|
||||||
|
# ships verbatim like instructions/ and types/: it carries no page, no
|
||||||
|
# frontmatter, and (AGENTS.md § File naming) no normative sentence, so
|
||||||
|
# there is nothing instance-owned in it to split off as a .template.
|
||||||
|
plan.update(_copy_tree(config.ROOT / "docs", "docs", frozenset()))
|
||||||
|
|
||||||
# `kb/CONTRACT.md` is stack-owned and ships verbatim; everything beside it
|
# `kb/CONTRACT.md` is stack-owned and ships verbatim; everything beside it
|
||||||
# under `kb/` is the instance's own and ships only as a `.template`. That is
|
# under `kb/` is the instance's own and ships only as a `.template`. That is
|
||||||
# the personalization split (`USER.md`/`SOUL.md`) one directory down, and
|
# the personalization split (`USER.md`/`SOUL.md`) one directory down, and
|
||||||
@@ -492,7 +498,8 @@ def export_command(
|
|||||||
):
|
):
|
||||||
"""Export a contentless, distributable copy of this repo's machinery:
|
"""Export a contentless, distributable copy of this repo's machinery:
|
||||||
AGENTS.md/README.md (dev-instance-only marker blocks removed),
|
AGENTS.md/README.md (dev-instance-only marker blocks removed),
|
||||||
instructions/ (no instructions/dev/), types/, tools/ (no venv/caches),
|
instructions/ (no instructions/dev/), types/, docs/ verbatim,
|
||||||
|
tools/ (no venv/caches),
|
||||||
the .github/hooks/+.vibe session-tracing config plus .claude/settings.json,
|
the .github/hooks/+.vibe session-tracing config plus .claude/settings.json,
|
||||||
kb/CONTRACT.md plus a COLLECTION.md.template per collection and
|
kb/CONTRACT.md plus a COLLECTION.md.template per collection and
|
||||||
kb/CONVENTIONS.md.template (no pages, no areas), empty
|
kb/CONVENTIONS.md.template (no pages, no areas), empty
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import pytest
|
|||||||
from chemenu import config
|
from chemenu import config
|
||||||
from chemenu.commands import confidence_decay
|
from chemenu.commands import confidence_decay
|
||||||
from chemenu.commands.confidence_decay import FLOOR, compute_decay
|
from chemenu.commands.confidence_decay import FLOOR, compute_decay
|
||||||
from chemenu.frontmatter_io import read_page
|
from chemenu.frontmatter_io import read_page, write_page
|
||||||
|
|
||||||
|
|
||||||
def test_no_decay_at_zero_months():
|
def test_no_decay_at_zero_months():
|
||||||
@@ -68,3 +68,22 @@ def test_decay_skips_pages_without_a_base(decay_wiki):
|
|||||||
confidence_decay.confidence_decay(apply=True)
|
confidence_decay.confidence_decay(apply=True)
|
||||||
frontmatter, _ = read_page(decay_wiki / "entities/systems/aurora.md")
|
frontmatter, _ = read_page(decay_wiki / "entities/systems/aurora.md")
|
||||||
assert frontmatter["confidence"] == 0.9
|
assert frontmatter["confidence"] == 0.9
|
||||||
|
|
||||||
|
|
||||||
|
def test_decay_skips_decision_pages(decay_wiki):
|
||||||
|
"""A decision is not falsified by elapsed time, only by a later decision
|
||||||
|
superseding it - `concept_type: decision` is a categorical skip, not
|
||||||
|
something an old `modified` date should ever decay (Gitea #38)."""
|
||||||
|
decision_path = decay_wiki / "concepts" / "some-decision.md"
|
||||||
|
write_page(
|
||||||
|
decision_path,
|
||||||
|
{
|
||||||
|
"type": "types/concept.md", "concept_type": "decision",
|
||||||
|
"tags": [], "created": "2015-01-01", "modified": "2015-01-01",
|
||||||
|
"related": [], "sources": [], "confidence": 0.9, "confidence_base": 0.9,
|
||||||
|
},
|
||||||
|
"\n# some-decision\n",
|
||||||
|
)
|
||||||
|
confidence_decay.confidence_decay(apply=True)
|
||||||
|
frontmatter, _ = read_page(decision_path)
|
||||||
|
assert frontmatter["confidence"] == 0.9
|
||||||
|
|||||||
@@ -135,6 +135,10 @@ def repo(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> Path:
|
|||||||
f"<!-- {config.TEMPLATE_SENTINEL} -->\n# conventions template\n", encoding="utf-8"
|
f"<!-- {config.TEMPLATE_SENTINEL} -->\n# conventions template\n", encoding="utf-8"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
docs_dir = root / "docs"
|
||||||
|
docs_dir.mkdir()
|
||||||
|
(docs_dir / "why-gates-are-code.md").write_text("# Why gates are code\n", encoding="utf-8")
|
||||||
|
|
||||||
for relative in ("raw/CONTRACT.md", "reports/CONTRACT.md", "work/CONTRACT.md"):
|
for relative in ("raw/CONTRACT.md", "reports/CONTRACT.md", "work/CONTRACT.md"):
|
||||||
path = root / relative
|
path = root / relative
|
||||||
path.parent.mkdir(parents=True, exist_ok=True)
|
path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
@@ -156,6 +160,11 @@ def test_plan_never_includes_commonplace(repo):
|
|||||||
assert "commonplace" not in combined
|
assert "commonplace" not in combined
|
||||||
|
|
||||||
|
|
||||||
|
def test_plan_ships_docs_verbatim(repo):
|
||||||
|
plan = dist_cmd.build_plan()
|
||||||
|
assert plan["docs/why-gates-are-code.md"].content == "# Why gates are code\n"
|
||||||
|
|
||||||
|
|
||||||
def test_plan_never_includes_instructions_dev(repo):
|
def test_plan_never_includes_instructions_dev(repo):
|
||||||
"""instructions/dev/ - flat dev-only instructions and the nested skill
|
"""instructions/dev/ - flat dev-only instructions and the nested skill
|
||||||
that switches a session into tool-development mode - is pruned
|
that switches a session into tool-development mode - is pruned
|
||||||
|
|||||||
Reference in New Issue
Block a user