029 — tp maturity code changes level only when the repo is at rest (#181)
Status: in progress
Why
tp maturity code N writes the level and makes the forge agree on
protection and merge style, and nothing else. The level alone picks the
release process (ADR 0006),
so changing it while a release is in flight strands work made under the
old process: dropping to 0 leaves a release branch with stories merged,
open pull requests into it, a .tp-release.yml and fragments that a trunk
release never reads; rising to 1 leaves open story pull requests into
main where a batch expects them into release. Moving in-flight work
from one process to the other is a migration tp does not have, and each
case would need its own. The cheap rule is the one tp release already
lives by: the facts that pick the process change only when nothing is in
flight.
What changes
tp maturity code N, with N different from the declared level: before touching the forge ortask-plus.yml, reads the in-flight state and refuses while any of these holds:releaseexists on the release remote;.tp-release.ymlexists in the checkout; a pull request is open whose head or base isrelease; a pull request is open from astory/<n>-<slug>branch. The error lists every item found and how to clear it (merge or close the pull request, finish the batch withtp releaseon the base branch, delete the file).tp maturity code Nat the declared level: as now — the protection and merge style are still checked and repaired; a repair is not a change of process.-dry-run: the same refusal, under the(dry-run)prefix.- Without a forge API or token (allowed today for
code 0): the remotereleasebranch and.tp-release.ymlare still checked through git; the pull requests are not, and the output says so. tp maturity(show): one more line,at restorin flight: …with the same items, so the refusal can be seen coming.docs/maturity.md: the rule and the table rows below.
Acceptance
code N vs declared |
release on remote |
.tp-release.yml |
Open pull requests | Outcome |
|---|---|---|---|---|
| same | any | any | any | as now: (unchanged); protection and merge style checked and made |
| differs | no | no | none from story/*, none touching release |
as now: forge made to agree, level written |
| differs | yes | — | — | error release exists on origin: finish the batch (tp release on main) or delete it; nothing written, forge untouched |
| differs | no | yes | — | error naming .tp-release.yml; nothing written |
| differs | no | no | #12 story/12-x → release |
error listing #12: merge or close it; nothing written |
| differs | no | no | #13 release → main |
error listing #13: merge it and tag, or close it; nothing written |
| differs | no | no | #14 story/14-y → main |
error listing #14: merge or close it; nothing written |
| differs, several items | yes | yes | #12 | one error listing all three |
differs, -dry-run |
yes | — | — | (dry-run) and the same error; nothing written |
| differs, no API or token | yes | — | not checked | error on release; the output says pull requests were not checked |
| differs, no API or token | no | no | not checked | level written, with a warning that pull requests were not checked |
tp maturity |
Prints |
|---|---|
| nothing in flight | at rest |
release on origin and #12 open |
in flight: release on origin; pull request #12 (story/12-x → release) |
Out of scope
- Migrating in-flight work between processes: closing or retargeting
pull requests, consuming fragments into the CHANGELOG, deleting
release. The refusal names the human steps instead. - Removing the base branch's protection when lowering to 0 (unchanged: the protection is left and reported).
tp release queryreporting the at-rest state: it already reports the position of each in-flight item.
Decisions
None expected. The rule — facts that pick the release process change only at rest — is shared with story 030, which applies it to opening a release branch.
Done when
- tests express the acceptance table and pass
- spec updated (maturity.md)
- ADR written if a fork was resolved (none needed)
- roadmap ticked and stamped; changelog entry
- issue closed with a link to the release