docs: ausgelieferte Doku zitiert keine Issue-Nummern mehr, docs verify prueft es (schliesst #77)
CI / verify (push) Successful in 59s
Release / release (push) Successful in 37s

Files changed:
- .gitignore
- CHANGES.md
- EVALS.md
- INSTALL.md
- README.md
- VERSION
- docs/pipeline-rationale.md
- instructions/CONTRACT.md
- instructions/bootstrap.md
- instructions/dev/issue-tracking.md
- instructions/evolve-subtypes.md
- instructions/kb-profiles.md
- instructions/mcp-read-server.md
- instructions/wiki-ingest/SKILL.md
- kb/CONTRACT.md
- kb/concepts/COLLECTION.md
- kb/sources/COLLECTION.md
- raw/CONTRACT.md
- tools/.coveragerc
- tools/CONTRACT.md
- tools/README.md
- tools/chemenu/commands/docs_verify.py
- tools/chemenu/tests/test_docs_verify.py
- types/source.schema.yaml
- types/type-spec.md
This commit is contained in:
2026-09-09 18:52:34 +02:00
parent 5820924ffd
commit a51d7a322f
25 changed files with 388 additions and 68 deletions
+6 -1
View File
@@ -215,7 +215,12 @@ the second. Whether the mechanic bites here is not something this repo can curre
the L2 trajectory scorers read `wikitool` calls, gates and publishes, never an agent's file
reads, and no tool hook is wired on the primary harness at all - so a `head -100` leaves nothing
to score. The other half of the claim, what ended up in the context window, produces no event
anywhere by construction. Gitea #72 records what a test would cost and why it was not bought.
anywhere by construction.
<!-- dist:strip-start -->
Gitea #72 records what such a test would cost and why it was not bought. (Kept behind a strip
marker: the pointer is worth having in the origin repo and resolves nowhere else.)
<!-- dist:strip-end -->
### When a skill carries a copy-in checklist
+1 -1
View File
@@ -30,7 +30,7 @@ they are published: the agent harness will not offer `wiki-ingest`, `wiki-query`
2. **Create the ingest inbox.** `incoming/` (raw/CONTRACT.md "Getting a file in") is gitignored,
so a fresh clone does not have it at all - unlike `raw/` itself, which is committed and
present immediately. It is flat since Gitea #67 (no type subdirectory to create):
present immediately. It is flat - there is no type subdirectory to create:
```bash
mkdir -p incoming
+41
View File
@@ -319,6 +319,37 @@ second pass), and an old body can carry private infrastructure detail into
what is now a public tracker - both found in the same issue, both worth the
same look.
## Citing an issue in the repo
**No file `dist export` ships may cite an issue number.** The board is reachable only from the
origin repo, and this very file - the only one that says where it lives - is pruned along with
the rest of `instructions/dev/`. A "#66" that survives into a distributed instance is therefore
worse than a dead link: the reader cannot resolve it *and* cannot tell that it is unresolvable,
so a rule appears to rest on evidence nobody can produce. `instructions/CONTRACT.md` § "Writing
an instruction" asks the opposite ("self-contained enough for an agent with no prior context"),
and an issue number is the exact counter-example to it.
Which is the same wayfinder/evidence split as in the section below, applied one layer out - but
both halves land in the same place here:
- **A wayfinder** ("see #66 for the reasoning") is resolved: the reasoning goes into the text,
and the number goes.
- **A piece of evidence** ("removed in #66") is dated in words instead - "removed when the
schema default was dropped". The sentence carries itself, and the number stays reachable
through `git blame` -> the commit message, which names the issue anyway.
Where a pointer is genuinely worth having *here* and would leave nothing behind in words, keep
it in a `<!-- dist:strip-start/end -->` block ([instructions/CONTRACT.md](../CONTRACT.md)
§ `instructions/dev/`): visible in this repo, removed on export. Two passages use it today.
`tools/**/*.py` is deliberately outside all of this. A code comment addresses whoever edits that
line, and that only ever happens in the origin repo, because `dist export` prunes the
`stack-dev` skill together with this directory; a distributed `tools/` tree is runtime
machinery, not reading material. The same holds for `.gitignore` and `tools/.coveragerc` -
config, not documentation.
`docs verify` enforces the rule (below).
## What no tool checks
`wikitool` does not know this tracker exists, and should not learn. It ships to
@@ -336,6 +367,16 @@ session following this file, or not at all - which is the argument for the
sequence in step 7 being explicit about the order (body first, then close),
rather than leaving it to be inferred from step 2.
The one rule here that *is* checked is § Citing an issue in the repo, and it is
worth being clear about why that is not a contradiction. `docs verify`'s
`check_no_issue_references` compiles `#\d+` and reads the text
`dist_cmd.build_plan()` would write. It has no client, no URL and no notion of
an issue's state - it cannot tell an open issue from a closed one, or a real
number from an invented one. What it knows is that a shipped document is making
a reference its reader cannot follow, which is a property of the *document*, not
of the board. That is the line: a check may look at what this repo writes about
the tracker; none may look at the tracker.
## Decision points
- **Issue or changelog?** An issue is work that is *not done*. `CHANGES.md` is
+5 -5
View File
@@ -17,7 +17,7 @@ procedure for changing that list once it is running, not for choosing it the fir
The tooling for this loop already exists end to end; this file only names the sequence and the
two rules that keep it from repeating what created `kb/sources/`'s old `notes` catch-all in the
first place (Gitea #66): a schema `default:` that the compiler applied whenever nobody
first place: a schema `default:` that the compiler applied whenever nobody
disagreed, silently turning the least specific value into the collection point for everything
unclear.
@@ -60,10 +60,10 @@ choice of an instance's starting vocabulary - that is
2. **Apply the ≥3-page admission threshold.** A value is admitted *after* it has proven
itself against real material, never in expectation of some. `spec` and `image` are the
cautionary case: both were added to `source_type` ahead of any matching page, both sat at
zero for a year, and both were removed in Gitea #66. A smaller count is only ever an
operator's explicit, named exception (`tracker` at two pages in #66, kept because the
corpus was expected to grow into it from ongoing issue ingests) - never a reason to lower
the threshold itself.
zero for a year, and both were eventually removed again unused. A smaller count is only
ever an operator's explicit, named exception (`tracker` survived that same cleanup at two
pages, kept because the corpus was expected to grow into it from ongoing issue ingests) -
never a reason to lower the threshold itself.
3. Add the enum value in the type-spec's schema (`types/<t>.schema.yaml`) and its `layout:`
entry (`types/<t>.md`) in the same edit - a value with no `layout:` line has nowhere to be
moved to.
+1 -1
View File
@@ -167,7 +167,7 @@ Adopting one means copying the value list into `types/source.schema.yaml`'s enum
value a `layout:` line in `types/source.md` - the same "copy the text in, do not point at this
page" rule as every other profile here. Keep the visible catch-all value (`unclassified` above)
in whatever list is adopted: a subtype field without one silently reintroduces the old
`default:`-driven collection point that Gitea #66 removed the moment nobody names an edge case.
`default:`-driven collection point this stack removed, the moment nobody names an edge case.
Growing the list later, or draining the catch-all, is
[evolve-subtypes.md](evolve-subtypes.md).
+1 -2
View File
@@ -93,8 +93,7 @@ everything an operator needs that is *true of the software* rather than of one i
- **Asked to expose a write tool?** There is none, and the way to add one is not a flag. The
server imports nothing under `chemenu.commands`, so `new`, `touch`, `xref`, `cite`, `publish`
and `migrate` are unreachable from it rather than filtered out of a list. Submitting documents
from outside is a different design with a quarantine in it - Gitea #32 - not a tool added
here.
from outside is a different design, with a quarantine in it - not a tool added here.
- **Asked to rate-limit inside the server?** Rate limiting belongs in the middleware in front of
the process, next to authentication. Not the Iteration Budget Gate: that exists to stop an
agent *session* from iterating unnoticed over the wiki's state, which is why retrieval is
+5 -5
View File
@@ -61,7 +61,7 @@ validator complains - and the ticked list is the only record that they happened.
`incoming/<type>/` habit) is tolerated and ignored - it carries no meaning any more.
**If this refuses because the name is already claimed** (a file stem or a bundle directory
already occupies the name anywhere under `raw/`, Gitea #64/#67), that is not this session's
already occupies the name anywhere under `raw/`), that is not this session's
call to make: whether the incoming file is a later edition of the existing source or a second,
separate one is a judgment about the world, and the command's message names both routes -
`--replaces` and renaming in `incoming/` - without recommending either. Show the message to
@@ -109,7 +109,7 @@ validator complains - and the ticked list is the only record that they happened.
--set entities=A,B,C --set concepts=D,E
```
`source_type` has no default - `new source` refuses without it (Gitea #66). Pick from what
`source_type` has no default - `new source` refuses without it. Pick from what
`tools/wikitool types describe source` lists, based on what the material *is*, not what it is
about: a session transcript is `transcript` regardless of subject, an LLM's own analysis is
`analysis` even when it reads like an article. Genuinely unclear after reading the source?
@@ -118,9 +118,9 @@ validator complains - and the ticked list is the only record that they happened.
it later without moving or renaming the page.
`fidelity` and `authority` have no default either, and `new source` refuses without them the
same way (Gitea #67) - but here there is no catalog slot to fall back on, for the reason step
1 gives. If step 1 already ran `raw accept` without `--page`, its success message printed the
exact `--set fidelity=... --set authority=...` pair to reuse here verbatim; if it did not (the
same way - but here there is no catalog slot to fall back on, for the reason step 1 gives.
If step 1 already ran `raw accept` without `--page`, its success message printed the exact
`--set fidelity=... --set authority=...` pair to reuse here verbatim; if it did not (the
file was already in `raw/`), ask the user, rather than inferring an answer from the file's
content now. Never pass `unknown` here - that value is backfill-only, written only by
`wikitool touch` on a page predating this rule.