stack-dev/stack-close skill split; publish stack-machinery note; model-selection fix (#47 Block 2)
CI / verify (push) Successful in 58s
Release / release (push) Successful in 38s

Files changed:
- CHANGES.md
- VERSION
- instructions/claude-code-model-selection.md
- instructions/dev/stack-close/SKILL.md
- instructions/dev/stack-dev/SKILL.md
- tools/CONTRACT.md
- tools/chemenu/commands/git_publish.py
- tools/chemenu/tests/test_git_publish.py
This commit is contained in:
2026-09-04 15:30:09 +02:00
parent 87a47cc237
commit d34924d640
8 changed files with 293 additions and 52 deletions
+102
View File
@@ -0,0 +1,102 @@
---
name: stack-close
description: Close out a stack-dev work package after its publish has landed - rewrite the issue body to its final state, check for docs/ staleness, and name which model ran which phase of the session. Use right after a stack-dev session's tools/wikitool publish succeeds, or when resuming a package that was published but never closed.
---
# Stack Close
**Purpose:** Carry out the unchecked closing phase of a stack-development work package, as its
own skill rather than a break `stack-dev` has to remember to ask for mid-flow.
**Trigger:** A `stack-dev` session's `tools/wikitool publish` just succeeded - `stack-dev` ends
there and hands off here rather than continuing into this phase in the same breath. Also: `publish`
printed its stack-machinery note ("this publish touched stack machinery...") and nothing has
closed the work package it belongs to yet; or a package was published in an earlier session and
never went through this skill (the gap this split exists to make impossible to skip past
silently - see [issue-tracking.md](../issue-tracking.md)'s note that a closed body is the version
everyone reads afterwards and nobody revisits).
**This directory is dev-only.** Same boundary as `stack-dev`
([its own note](../stack-dev/SKILL.md) has the full reasoning) - `dist export` prunes
`instructions/dev/` wholesale, so this skill never reaches a distributed instance.
## Why this is a separate skill, not `stack-dev`'s step 6
The two phases around the mechanical middle of a stack-dev session have no mechanical guard at
all - `pytest`, `docs verify` and `instructions verify` cover the code and tests in between, and
nothing covers a changelog entry's accuracy, a `docs/` page's staleness, or an issue body's final
state (see [claude-code-model-selection.md](../../claude-code-model-selection.md)). Asking the
same session to notice it has crossed into that second unchecked stretch - as a prose break inside
`stack-dev`'s own step 6 - failed twice in a row on this stack (Gitea #42, then #30): both times
the session knew the rule and skipped past it anyway, because nothing in the moment forced the
question. Splitting the phase into its own skill does not add a check either - `wikitool` still
does not know this tracker exists and must not learn (see
[issue-tracking.md](../issue-tracking.md) § What no tool checks) - but it removes the thing that
was actually failing: there is no longer a "next step" to skip past, only a skill nobody has
invoked yet. See Gitea #47 for the full incident history and the rejected alternative (a
model-switched subagent - not buildable in Claude Code, where a fork inherits the parent's model
and a fresh subagent starts without the session's context).
## Steps
1. **Offer the model switch back up, once, and keep working either way.**
> Ab hier greift kein maschineller Check mehr - Issue-Body, `docs/`-Veralterung und
> Changelog-Prosa prüft nichts. Wenn du zurück auf Opus willst, ist jetzt der Moment.
**Never block on the answer.** The change is already published; a session that stops here
leaves exactly the state this skill exists to prevent.
2. **Rewrite the issue body to its final state, then close.** The test is what a reader who
opens the closed issue tomorrow would conclude:
- every acceptance criterion ticked, or struck with the reason it was dropped
- proposals that were decided read as decided; a "to decide" section has become the decision
and its reasoning
- nothing left in the present tense about a defect that no longer exists
- what was verified is named - which checks ran, which CI run - not a commit hash alone
Then one short comment naming what changed against the previous state, and nothing else -
[issue-tracking.md](../issue-tracking.md) steps 2-3 and 7 have the full shape; this is that
procedure, run at the point this skill exists to guarantee it actually gets run.
**A closing report in a comment does not satisfy this**, however thorough: it reads as
complete to whoever writes it and leaves a body still phrased as open work. Nothing mechanical
catches it, which is why this is a step - and now a whole skill - rather than a habit. #44 and
#45 both closed exactly this way on the old, single-skill shape, the second an hour after the
rule was first written down.
3. **Check whether a `docs/` page or new human doc went stale.** A `docs/` page carries no
normative sentence, so nothing verifies it by construction (AGENTS.md § File naming) - the
same is true of `README.md`/`INSTALL.md`/`DEVELOPMENT.md` prose and a new instruction's own
wording, which `instructions verify` checks structurally but never for what it claims. If the
change this package shipped moved the reasoning one of these pages documents, update it now;
if none did, say so rather than leaving the question unasked.
4. **Name which model ran which phase - not only this one.** This is the handover in full, not
a note about the tail alone: state the model for the design/version-part/boundary-judgment
phase (`stack-dev` step 3), for the mechanical middle (code, tests, the version bump), and for
this closing phase - all three, even when they are all the same model. A handover that only
flags a cheap-model *closing* phase stays silent exactly when the earlier, equally unchecked
design phase also ran cheap and nobody offered the switch back then either; naming all three
every time is what keeps that omission from being the quiet default.
## Decision points
- **The work package spans several sessions?** Run this skill once, at the point the package is
actually finished and its last publish has landed - not after every individual publish. A
package still open across sessions keeps its body current per
[issue-tracking.md](../issue-tracking.md) step 2 in the meantime; that is maintenance, not
closing.
- **Resuming a package whose publish landed in an earlier, already-ended session?** Run this
skill now, on whatever model the current session is - do not reopen the earlier session to run
it "correctly." The handover in step 4 names the earlier phases from the historical record
(the issue's comments, `CHANGES.md`) rather than from memory.
- **Nothing to close - the session's own exploration, no publish happened?** This skill does not
apply; there is no package to rewrite a body for.
## Scope
Follows a `stack-dev` session's publish. Not for wiki content work - use
`wiki-ingest`/`wiki-query`/`wiki-manage`/`wiki-lint`/`wiki-status` for that, whose own closing
conventions (`kb/log.md`, page provenance) are unrelated to this tracker-body procedure.