Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 41f5dfe1cd |
+49
@@ -20,6 +20,55 @@ their date-only headings.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 4.1.2 - 2026-09-03 - Issue-Abschluss ist ein Body-Rewrite, nicht nur ein Kommentar
|
||||||
|
|
||||||
|
**Author:** Torben Nehmer
|
||||||
|
|
||||||
|
Aufgefallen beim Schließen von #44: der Abschlussbericht stand als Kommentar da, der Body
|
||||||
|
darunter weiterhin als offene Arbeit — Abschnitt „Zu entscheiden" über eine längst getroffene
|
||||||
|
Entscheidung, ungehakte Checkliste, Präsens über einen Defekt, den es nicht mehr gab.
|
||||||
|
|
||||||
|
Die Regel gab es dafür schon: Schritt 2 von `instructions/dev/issue-tracking.md` sagt, der Body
|
||||||
|
ist die aktuelle Wahrheit und wird umgeschrieben, wenn sich der Stand ändert. Nur ließ die
|
||||||
|
Formulierung offen, *wann* — und Schritt 7 („Close with what actually happened") war vollständig
|
||||||
|
erfüllbar, ohne den Body anzufassen. Ein Abschlussbericht im Kommentar fühlt sich beim Schreiben
|
||||||
|
vollständig an; dass der Body dabei zurückbleibt, merkt erst der nächste Leser.
|
||||||
|
|
||||||
|
**Schritt 2 ist deshalb schärfer geworden: der Body ist das Plan-File dieses Stacks.** Dasselbe,
|
||||||
|
was das Plan-Dokument eines Harness ist, und genauso gepflegt — fortlaufend, sobald etwas darin
|
||||||
|
nicht mehr stimmt, nicht am Ende. Der Maßstab ist der Abbruch, nicht der Meilenstein: eine
|
||||||
|
Session kann jederzeit enden, und was der Body in diesem Moment sagt, ist die vollständige
|
||||||
|
Übergabe. Eine frische Session muss zu **jedem** Zeitpunkt allein aus dem Body weiterarbeiten
|
||||||
|
können, ohne Kommentare rückwärts zu lesen und ohne einen Menschen, der es neu erklärt. Entschieden
|
||||||
|
ersetzt die Frage, erledigt hakt das Kriterium ab, verworfen steht mit Begründung dort, wo das
|
||||||
|
Kriterium stand.
|
||||||
|
|
||||||
|
Schritt 7 ist damit kein Sonderakt mehr, sondern die letzte dieser Aktualisierungen: erst Body
|
||||||
|
auf den Endstand, dann schließen, dann die Changelog-Zeile aus Schritt 3. Wer Schritt 2 befolgt
|
||||||
|
hat, ist fast fertig; wer nicht, zahlt die ganze Schuld im schlechtesten Moment — der
|
||||||
|
geschlossene Body ist die Fassung, die danach alle lesen und niemand mehr aufsucht. #44 steht
|
||||||
|
als Beispiel drin.
|
||||||
|
|
||||||
|
Schritt 3 zieht die Konsequenz: **ein Kommentar pro Session-Umfang, nicht pro Edit.** Ein
|
||||||
|
fortlaufend gepflegter Body mit einem Changelog-Kommentar je Änderung wäre Lärm; triviale Pflege
|
||||||
|
braucht gar keinen. Der `stack-dev`-Skill sagt es beim Aufgreifen mit, weil dort die Entscheidung
|
||||||
|
fällt, ob eine Session den Body überhaupt anfasst.
|
||||||
|
|
||||||
|
**Und die ehrliche Antwort auf die Frage nach dem Tooling: es gibt keins, und es soll keins
|
||||||
|
geben.** `wikitool` kennt diesen Tracker nicht. Es wird an Instanzen ausgeliefert, die unter
|
||||||
|
dieser URL keine Issues haben, während `instructions/dev/` von `dist export` gepruned wird —
|
||||||
|
ein Gitea-Client im ausgelieferten Tool wäre eine Dev-Abhängigkeit, die jede Instanz mitträgt,
|
||||||
|
um ein Board zu prüfen, das keine von ihnen hat. Der Tracker ist ausschließlich über
|
||||||
|
`gitea-mcp` erreichbar, also in einer Session, durch einen Agenten.
|
||||||
|
|
||||||
|
Kein `docs verify` fängt also einen geschlossenen Issue, dessen Body offen klingt, einen Body,
|
||||||
|
der seinen eigenen Kommentaren widerspricht, oder ein fehlendes Pflichtlabel. Das steht jetzt
|
||||||
|
als eigener Abschnitt „What no tool checks" in der Instruktion — nicht als Bedauern, sondern als
|
||||||
|
Begründung dafür, warum die Reihenfolge in Schritt 7 ausgeschrieben ist statt aus Schritt 2
|
||||||
|
erschlossen zu werden.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 4.1.1 - 2026-09-03 - Testisolation: kb_dir repointet config.ROOT, lint löst Kollektionen gegen den übergebenen Baum auf
|
## 4.1.1 - 2026-09-03 - Testisolation: kb_dir repointet config.ROOT, lint löst Kollektionen gegen den übergebenen Baum auf
|
||||||
|
|
||||||
**Author:** Torben Nehmer
|
**Author:** Torben Nehmer
|
||||||
|
|||||||
@@ -28,8 +28,12 @@ issues at that URL, which is exactly why `dist export` excludes
|
|||||||
an assumption nobody has checked, a decision that needs the user.
|
an assumption nobody has checked, a decision that needs the user.
|
||||||
- Picking an issue up: before doing anything else, read the body as the current
|
- Picking an issue up: before doing anything else, read the body as the current
|
||||||
spec, and re-label it if the ground has moved since.
|
spec, and re-label it if the ground has moved since.
|
||||||
|
- **While working on one:** the body is updated as the state moves, not at the
|
||||||
|
end (step 2). A session that is interrupted leaves the body as its handover.
|
||||||
- Prioritising: deciding what to pick up next, or re-labelling after the ground
|
- Prioritising: deciding what to pick up next, or re-labelling after the ground
|
||||||
moved.
|
moved.
|
||||||
|
- Closing one: the body is rewritten to its final state first, and only then
|
||||||
|
closed (step 7).
|
||||||
|
|
||||||
## Steps
|
## Steps
|
||||||
|
|
||||||
@@ -38,23 +42,47 @@ issues at that URL, which is exactly why `dist export` excludes
|
|||||||
specific files or commands involved. An issue that only makes sense to
|
specific files or commands involved. An issue that only makes sense to
|
||||||
whoever wrote it is a note, and notes were the problem.
|
whoever wrote it is a note, and notes were the problem.
|
||||||
|
|
||||||
2. **Treat the body as the current truth, not as a historical first post.**
|
2. **The body is the working state, not a historical first post - keep it
|
||||||
Work on one issue spans several sessions, often weeks apart, and the body is
|
current as you go.** It is this stack's plan file: the same thing a harness's
|
||||||
the only thing that connects them: a session opening the issue must be able
|
own plan document is, and it is maintained the same way. Not written once,
|
||||||
to reconstruct what is decided and what is still open from the body alone,
|
not brought up to date at the end, but **updated whenever something in it
|
||||||
without a human re-explaining it. So when the state changes, **rewrite the
|
stops being true** - a decision made, a criterion met, an approach ruled out,
|
||||||
body** - do not append to a text that has become wrong. An additively grown
|
a new constraint found.
|
||||||
log forces every later reader to reconstruct the current state by filtering
|
|
||||||
the whole history.
|
The test is an abort, not a milestone. A session can end at any moment - an
|
||||||
|
interrupt, a context limit, a crash, a human walking away - and whatever the
|
||||||
|
body says at that instant is the entire handover. So the standard is: **at
|
||||||
|
every point, a fresh session must be able to open the body and pick the work
|
||||||
|
up from there**, without a human re-explaining it and without reading back
|
||||||
|
through the comments. If the body would mislead someone who read it right
|
||||||
|
now, it is already out of date, whether or not the work is finished.
|
||||||
|
|
||||||
|
That means updating *during* the work, not only at its end:
|
||||||
|
|
||||||
|
- a decision gets made → the decision and its reasoning replace the question
|
||||||
|
- an acceptance criterion is done → tick it, in the same session that did it
|
||||||
|
- something turns out differently than the issue assumed → the assumption is
|
||||||
|
corrected where it stands, not contradicted three paragraphs later
|
||||||
|
- work is deferred or dropped → say so, with the reason, where the criterion is
|
||||||
|
|
||||||
|
**Rewrite, never append.** Do not add to a text that has become wrong: an
|
||||||
|
additively grown log forces every later reader to reconstruct the current
|
||||||
|
state by filtering the whole history, which is the exact cost the body exists
|
||||||
|
to remove. Comments carry the history (step 3); the body carries the state.
|
||||||
|
|
||||||
Body rewrites and comments are an LLM session's job. A human normally
|
Body rewrites and comments are an LLM session's job. A human normally
|
||||||
touches only labels and metadata directly.
|
touches only labels and metadata directly.
|
||||||
|
|
||||||
3. **Comment a changelog, never a copy.** Every body rewrite gets one short
|
3. **Comment a changelog, never a copy.** A body rewrite gets one short comment
|
||||||
comment naming only what changed against the previous state - what is new,
|
naming only what changed against the previous state - what is new, what is
|
||||||
what is gone, what was corrected. Do not snapshot the old body into a
|
gone, what was corrected. Do not snapshot the old body into a comment: a full
|
||||||
comment: a full copy per revision forces a human to diff two prose texts,
|
copy per revision forces a human to diff two prose texts, which is not a
|
||||||
which is not a readable history, only another copy.
|
readable history, only another copy.
|
||||||
|
|
||||||
|
One comment per *session's worth* of change, not per edit. Step 2 asks the
|
||||||
|
body to be kept current continuously, and a comment for every tick would bury
|
||||||
|
the board in noise; the changelog line summarises what that session moved.
|
||||||
|
Trivial upkeep - a typo, a tightened sentence - needs no comment at all.
|
||||||
|
|
||||||
```
|
```
|
||||||
**Changelog:** Decision 2 tightened - `kind/` may now change over an
|
**Changelog:** Decision 2 tightened - `kind/` may now change over an
|
||||||
@@ -127,10 +155,46 @@ issues at that URL, which is exactly why `dist export` excludes
|
|||||||
answered can drop a size and move `kind/decision` to `kind/build`. Silent
|
answered can drop a size and move `kind/decision` to `kind/build`. Silent
|
||||||
re-labelling is how a board stops meaning anything.
|
re-labelling is how a board stops meaning anything.
|
||||||
|
|
||||||
7. **Close with what actually happened**, not with a commit hash alone: which
|
7. **Closing is the last body update, not a comment.** If step 2 was followed
|
||||||
proposals were implemented, which were deliberately left out and why, and
|
the body is already nearly there, and closing only settles what the final
|
||||||
what was verified. The issue is the only place that record survives - a
|
run established. If it was not, closing is where the whole debt comes due -
|
||||||
changelog entry says what changed, not what was decided against.
|
and it comes due at the worst moment, because a closed body is the version
|
||||||
|
everyone reads afterwards and nobody revisits.
|
||||||
|
|
||||||
|
Either way the body reaches its final state *before* the issue closes:
|
||||||
|
proposals that were decided read as decided, a "to decide" section has become
|
||||||
|
the decision with its reasoning, acceptance criteria are ticked or struck with
|
||||||
|
a reason, and what was verified is named. Then close, with the one-line
|
||||||
|
changelog comment step 3 asks for.
|
||||||
|
|
||||||
|
Record what actually happened, not a commit hash alone: which proposals were
|
||||||
|
implemented, which were deliberately left out and why, and what was verified.
|
||||||
|
The issue is the only place that record survives - a changelog entry says
|
||||||
|
what changed, not what was decided against.
|
||||||
|
|
||||||
|
**A closing report in a comment does not satisfy this.** It reads as
|
||||||
|
complete to whoever writes it and leaves a body still phrased as open work:
|
||||||
|
unticked boxes, an undecided decision section, present tense about a defect
|
||||||
|
that no longer exists. #44 closed exactly that way, with a thorough comment
|
||||||
|
above a body that still asked for a decision that had already been made and
|
||||||
|
shipped. Nothing mechanical catches it (see below), which is why it is a step
|
||||||
|
rather than a habit.
|
||||||
|
|
||||||
|
## What no tool checks
|
||||||
|
|
||||||
|
`wikitool` does not know this tracker exists, and should not learn. It ships to
|
||||||
|
instances that have no issues at that URL, while this file and the workflow it
|
||||||
|
describes are pruned by `dist export` - a Gitea client inside the shipped tool
|
||||||
|
would be a dev-only dependency carried by every instance, to check a board none
|
||||||
|
of them have. The tracker is reachable only through the `gitea-mcp` server, in a
|
||||||
|
session, by an agent.
|
||||||
|
|
||||||
|
So there is no `docs verify` for the board. Nothing reports a closed issue whose
|
||||||
|
body still reads as open, a body that contradicts its own comments, or an issue
|
||||||
|
missing one of the four mandatory labels. Every one of those is caught by a
|
||||||
|
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.
|
||||||
|
|
||||||
## Decision points
|
## Decision points
|
||||||
|
|
||||||
@@ -144,7 +208,8 @@ issues at that URL, which is exactly why `dist export` excludes
|
|||||||
- **Rewrite the body, or add a comment?** Rewrite whenever a reader of the body
|
- **Rewrite the body, or add a comment?** Rewrite whenever a reader of the body
|
||||||
alone would otherwise be misled - a changed decision, a dropped criterion, a
|
alone would otherwise be misled - a changed decision, a dropped criterion, a
|
||||||
new constraint. A comment carries the changelog line for that rewrite, and
|
new constraint. A comment carries the changelog line for that rewrite, and
|
||||||
nothing else that a future session needs in order to act.
|
nothing else that a future session needs in order to act. Closing an issue is
|
||||||
|
always a rewrite - see step 7.
|
||||||
- **An old issue carries only `prio/` and `size/`?** Complete it to all four
|
- **An old issue carries only `prio/` and `size/`?** Complete it to all four
|
||||||
when you touch it, rather than in a sweep. The board reaches the new scheme
|
when you touch it, rather than in a sweep. The board reaches the new scheme
|
||||||
issue by issue, as each is picked up.
|
issue by issue, as each is picked up.
|
||||||
|
|||||||
@@ -43,9 +43,11 @@ stack development happens in the origin repo instead (see AGENTS.md's routing li
|
|||||||
engineering, memory and deploy-time learning; consult before a design decision in those
|
engineering, memory and deploy-time learning; consult before a design decision in those
|
||||||
areas.
|
areas.
|
||||||
[issue-tracking.md](../issue-tracking.md) - open work lives in Gitea issues, one per work
|
[issue-tracking.md](../issue-tracking.md) - open work lives in Gitea issues, one per work
|
||||||
package, labelled `area/`, `kind/`, `prio/` and `size/`, with the body kept as the current
|
package, labelled `area/`, `kind/`, `prio/` and `size/`. There is no `TODO.md`. **The body
|
||||||
truth rather than as a first post. There is no `TODO.md`. Read it before filing something
|
of the issue you are working on is this session's plan file:** keep it current as the state
|
||||||
for later, before editing an issue, or before deciding what to pick up next.
|
moves, not at the end, so an interrupted session leaves a body the next one can resume from.
|
||||||
|
Read it before filing something for later, before editing or closing an issue, or before
|
||||||
|
deciding what to pick up next.
|
||||||
[testing-conventions.md](../testing-conventions.md) - the suite runs against a deliberately
|
[testing-conventions.md](../testing-conventions.md) - the suite runs against a deliberately
|
||||||
empty machine; what the autouse fixture already neutralizes, and what a test still has to
|
empty machine; what the autouse fixture already neutralizes, and what a test still has to
|
||||||
establish itself. Read it before adding or changing a test.
|
establish itself. Read it before adding or changing a test.
|
||||||
|
|||||||
Reference in New Issue
Block a user