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:
torben committed 2026-09-04 15:30:09 +02:00
1 parent 87a47cc237
commit d34924d640
8 files changed
+293 -52

No files matched your search

+37
View File
@@ -423,6 +423,41 @@ def counted_files_of(
return [change for change in changes if not is_exempt(change.path, prefixes)]
# The same scope `version-parts.md` names for the stack version itself -
# "tools/, types/, instructions/, AGENTS.md and the contracts" - reused here
# to decide whether a publish's changeset falls under it. Not a copy of that
# rule: version-parts.md states the scope in prose for a human choosing a
# version part, this instantiates the same boundary in code for a different
# question (does this publish deserve the closing-phase reminder below).
STACK_MACHINERY_PREFIXES = ("tools/", "types/", "instructions/")
STACK_MACHINERY_NAMES = ("AGENTS.md",)
STACK_MACHINERY_NOTE = (
"Note: this publish touched stack machinery. What a stack-dev session "
"does next - closing prose, a changelog entry's accuracy, whether a "
"docs/ page went stale - is not covered by docs verify, instructions "
"verify, or pytest. No tool checks it; a session has to."
)
def touches_stack_machinery(changed_files: list[str]) -> bool:
"""Whether `changed_files` includes a path under `version-parts.md`'s
scope for the stack version - `tools/`, `types/`, `instructions/`,
`AGENTS.md`, or any `<stage>/CONTRACT.md`. A publish in this class is,
by construction of the `stack-dev`/`stack-close` split, always followed
by the unchecked closing phase - `STACK_MACHINERY_NOTE` times a reminder
to land exactly there, for any session, not only one that read the
skill that names it."""
for path in changed_files:
if path in STACK_MACHINERY_NAMES:
return True
if path.endswith("CONTRACT.md"):
return True
if path.startswith(STACK_MACHINERY_PREFIXES):
return True
return False
YES_REMOVED_MESSAGE = (
"--yes no longer exists. The Mass-Update Gate is cleared with `--confirm <token>`, and the "
"token comes from the gate's own refusal output - run this command without it first to see "
@@ -1138,3 +1173,5 @@ def publish_command(
},
)
success(f"Published changes to {remote}/{branch}." if push else "Committed changes (not pushed).")
if touches_stack_machinery(changed_files):
typer.echo(STACK_MACHINERY_NOTE)