instructions: chains of packages - stack-dev writes ## Kette, stack-close names the next link (#205)
CI / verify (push) Successful in 7m41s
CI / pwsh (push) Successful in 2m23s
Release / release (push) Successful in 36s
Release / wiki-mirror (push) Skipped

Files changed:
- CHANGES.md
- VERSION
- instructions/dev/issue-tracking.md
- instructions/dev/stack-close/SKILL.md
- instructions/dev/stack-dev/SKILL.md
- instructions/dev/stack-mode.md

Co-Authored-By: Claude Code <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SnAJ7Z3CpVD3PRbN73QtU2
This commit is contained in:
torbenandClaude Code committed 2026-10-10 08:49:33 +02:00
1 parent 7cfafd75b2
commit 3c80262a05
6 files changed
+90 -5

No files matched your search

+38 -1
View File
@@ -27,6 +27,7 @@ issues at that URL, which is exactly why `dist export` excludes
- [Steps](#steps)
- [Incoming stubs](#incoming-stubs)
- [Ready to build](#ready-to-build)
- [Chains](#chains)
- [Renames and other decay in the tracker](#renames-and-other-decay-in-the-tracker)
- [Citing an issue in the repo](#citing-an-issue-in-the-repo)
- [What no tool checks](#what-no-tool-checks)
@@ -50,6 +51,8 @@ issues at that URL, which is exactly why `dist export` excludes
ready (§ Ready to build).
- Prioritising: deciding what to pick up next, or re-labelling after the ground
moved.
- A design session yields several packages with an order, or inserts, removes or moves
one in an existing sequence: write or repair the `## Kette` sections (§ Chains).
- Closing one: the body is rewritten to its final state first, and only then
closed (step 7).
- A rename or move ships: sweep the open issues for text that assumed the old
@@ -208,7 +211,7 @@ issues at that URL, which is exactly why `dist export` excludes
| `status/` | Means |
|---|---|
| `status/blocked` | Waiting on another, still-open issue - not workable on its own, whatever its `prio/` says. Name the blocking issue in the body. |
| `status/blocked` | Waiting on another, still-open issue - not workable on its own, whatever its `prio/` says. Name the blocking issue in the body. A place in a chain (§ Chains) is an order, not a block. |
| `status/unconfirmed` | A reported suspicion, not yet checked against actual behaviour. Applies to any `kind/`, not just `kind/defect`. |
| `status/incoming` | A human's stub: a request or a thought, filed at whatever length it arrived, deliberately short of everything step 1 asks for. **Never implemented as it stands** - § Incoming stubs. |
@@ -337,6 +340,40 @@ session fills on its own is the same gap a `status/incoming` stub leaves (§ Inc
only better disguised. The useful side effect of the cut between the two phases is that it
tests this definition - if a cold session cannot build from the body, it was not ready.
## Chains
Packages that are meant to be built one after another lose the thread when each is closed:
which issue comes next is, at best, written in a body nobody reads after closing. A package that
is part of an ordered sequence therefore ends its body with a section of this exact form, as the
**last** section:
```
## Kette
Kette „<name>“
- Vorgänger: #A (or: keiner - erstes Glied)
- Nachfolger: #C (or: keiner - letztes Glied)
```
The heading and the line openings are quoted vocabulary and stay German, like the bodies they
sit in. Three rules keep it cheap and checkable:
- **Neighbours only, never a list of all links.** Inserting, removing or moving a package then
touches the two bodies beside it, not every body in the chain. The whole sequence is
recovered by walking `Nachfolger` links from the first link.
- **The two neighbours point at each other.** If #B names #A as `Vorgänger`, #A names #B as
`Nachfolger`. A one-sided pointer is the defect; `stack-dev` checks every link it touched
before ending its phase.
- **Order is a planning decision, not a dependency.** A real dependency still carries
`status/blocked` (step 5) and names the blocker in the body. A chain position alone never
blocks anything.
`stack-dev` writes the section and keeps the neighbours in step (its steps 3 and 5);
`stack-close` reads it after closing and names the next link (its step 5), and lifts
`status/blocked` from the successor when the closed package was that body's only open blocker,
with the comment step 6 asks for. The successor is *ready* when it carries `kind/build` and
neither `status/incoming` nor `status/unconfirmed`; otherwise the next phase for it is design.
## Renames and other decay in the tracker
A rename is not finished when the tree is green. Renaming a package, a path,
+28
View File
@@ -103,6 +103,31 @@ always will.
4. **Comment, then close.** The closing comment carries the one changelog line
`instructions/dev/issue-tracking.md` step 3 asks for. Then close the issue.
5. **Name the next link of the chain, if there is one.** Read the closed body's `## Kette` section
(`instructions/dev/issue-tracking.md` § Chains) and follow its `Nachfolger` line:
- **Successor open:** if its body names the issue just closed as its only open blocker, take
`status/blocked` off it and say so in a comment there (issue-tracking.md step 6); with
another open blocker the label stays. Then give the line below.
- **Successor already closed:** keep following `Nachfolger` links to the first open link and
name that one.
- **No open link left (`Nachfolger: keiner`, or only closed links):** give the last line below.
- **No `## Kette` section:** give no line, as before.
Close the phase with exactly one of these fixed lines, in the instance's KB language per
`AGENTS.md` § File naming. A link is *ready* when it carries `kind/build` and neither
`status/incoming` nor `status/unconfirmed`:
> #N is closed. Next in the chain "<name>": #M - `/stack-build #M`, here or after `/clear`.
> #N is closed. Next in the chain "<name>": #M - `/stack-dev #M`, here or after `/clear`.
> Chain "<name>" is complete.
The first is for a ready link, the second for one that is not and needs design first. **Do
not run the named skill yourself** - the line only tells the operator what comes next, the
same rule as at every other phase end (`instructions/dev/stack-mode.md` § The three phases).
## Decision points
- **The work package spans several sessions?** Run this skill once, at the point the package is
@@ -112,6 +137,9 @@ always will.
it "correctly."
- **Nothing to close - the session's own exploration, no publish happened?** This skill does not
apply; there is no package to close.
- **The chain section points at a successor that does not point back, or at an issue that does
not exist?** Say so in the closing line's place instead of guessing a successor, and leave the
repair to `/stack-dev` (`issue-tracking.md` § Chains).
## Scope
+10 -1
View File
@@ -41,13 +41,22 @@ are split that way.
asked in the chat and stays a question in the body until it is answered; it is never settled
by a guess.
**A session that yields more than one package with an order gives each of them a
`## Kette` section** (`instructions/dev/issue-tracking.md` § Chains): the chain's name, the
predecessor, the successor, nothing else. When a package is inserted into an existing chain,
taken out of it or moved within it, the neighbours' sections are corrected in the same
session, and the changelog comment names it. The order stays a planning decision; a real
dependency also gets `status/blocked`.
4. **Name the version part.** Apply the drop-in test in `instructions/dev/version-parts.md`
and write the result into the body. Whether a change is a drop-in replacement has no
mechanical guard, so it is decided here, not at the bump. A change that crosses the
compatibility boundary goes to the user with what breaks, what an instance has to do about
it, and the alternatives, before the body can be ready (version-parts.md step 4).
5. **End the phase at a ready body.** Check the body against
5. **End the phase at a ready body.** First, for every package of a chain this session touched,
read both neighbours' `## Kette` sections and confirm that predecessor and successor point at
each other; repair a one-sided pointer before going on. Then check the body against
`instructions/dev/issue-tracking.md` § Ready to build. If it fails, say which point is open
and stay in this phase. If it passes, recommend one of two ways on, and stop:
+2 -2
View File
@@ -33,9 +33,9 @@ so every handover works either in the same session or after a `/clear`.
| Phase | Skill | Invoked by | Ends with (the handover) | What catches a mistake |
|---|---|---|---|---|
| 1 Design/triage | `stack-dev` | the harness on a matching task, or `/stack-dev` | the issue body is **ready** ([issue-tracking.md](issue-tracking.md) § Ready to build) | nothing mechanical |
| 1 Design/triage | `stack-dev` | the harness on a matching task, or `/stack-dev` | the issue body is **ready** ([issue-tracking.md](issue-tracking.md) § Ready to build); writes `## Kette` where an order exists ([§ Chains](issue-tracking.md#chains)) | nothing mechanical |
| 2 Build | `stack-build` | **only** the operator: `/stack-build #N` | a **green CI run** on the published commit, body current | `pytest`, `docs verify`, `instructions verify`, CI |
| 3 Closing | `stack-close` | **only** the operator: `/stack-close` | body in its final state, issue closed | nothing mechanical |
| 3 Closing | `stack-close` | **only** the operator: `/stack-close` | body in its final state, issue closed; names the next link of a chain | nothing mechanical |
`stack-build` and `stack-close` carry `disable-model-invocation: true` in their frontmatter, so in
Claude Code only the operator can start them. That is the point of the split: each phase change is