Maturity-gated release tooling (./uw dev)#233
Merged
Conversation
Introduce a process and tooling for promoting work from development to main
with confidence: when a feature is announced as released, it has been validated.
main accumulates whatever stable work comes over each quarter; the release notes
(not branch surgery) distinguish validated-and-guaranteed features from those
merely present-but-unguaranteed.
Tooling, grouped under a new ./uw dev namespace (env-aware help hides it on the
stripped-down runtime/default envs; reveal with ./uw --help all):
dev release-check Per-feature validation gate (dry-run)
dev release Orchestrate the quarterly dev->main promotion (RC tag,
validate, scaffold notes, open PR; stops before the
production tag so main's review gate stays intact)
dev branch-hygiene Report/prune branches merged into development
dev feature-audit List feature-branch PR merges available to release
dev format/type-check (moved here from the user-facing surface)
Mechanism:
- docs/release-notes/feature-manifest.yaml declares each shippable feature and
the tests that validate it. "Supported" is tied to the existing tier_a/b
markers by construction; there is no new per-feature marker to maintain.
- scripts/release_gate.py resolves announced = min(claim, tests_result) and
renders the Supported / Preview release-notes sections.
- scripts/check_manifest_coverage.py guards against drift (a tier_a test no
feature references).
Docs: new release-process.md guide; branching-strategy.md and the release-notes
TEMPLATE.md updated. Seed manifest covers units, mesh-smoothing (supported),
the MMPDE mover (preview) and FMG (downgraded until it has a tier_a suite).
Underworld development team with AI support from Claude Code
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a maturity-gated release promotion workflow and associated maintainer tooling under ./uw dev, so quarterly development → main merges can ship stable code while release notes only announce features that are validated by tiered tests.
Changes:
- Introduces
./uw devsubcommands for release orchestration, per-feature release gating, feature auditing, and branch hygiene. - Adds a feature manifest plus Python tooling to run per-feature pytest selections and render Supported/Preview release-notes sections.
- Documents the maturity-gated quarterly promotion process and updates release-note templates/branching guidance.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
uw |
Adds dev namespace, developer help, and release/branch tooling command implementations. |
scripts/release_gate.py |
Implements the per-feature validation gate (manifest-driven pytest selection + reporting/JSON/notes rendering). |
scripts/check_manifest_coverage.py |
Adds a drift check to ensure tier_a tests are referenced by the manifest. |
docs/release-notes/TEMPLATE.md |
Updates the release-notes template with generated Supported/Preview sections. |
docs/release-notes/feature-manifest.yaml |
Seeds the manifest describing features, claims, and validating tests. |
docs/developer/guides/release-process.md |
Documents the maturity-gated release process and new tooling. |
docs/developer/guides/branching-strategy.md |
Documents maturity-gated promotion as part of the branching strategy. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+1726
to
+1732
| git fetch --quiet origin 2>/dev/null || git fetch origin | ||
| local behind=$(git rev-list --count HEAD..origin/development 2>/dev/null || echo 0) | ||
| if [ "$behind" -gt 0 ]; then | ||
| echo -e " ${YELLOW}Local development is $behind commit(s) behind origin. Pull first.${NC}"; exit 1 | ||
| fi | ||
| local ahead=$(git rev-list --count origin/main..origin/development 2>/dev/null || echo 0) | ||
| echo -e " ${GREEN}✓${NC} on development, clean, $ahead commit(s) ahead of main" |
Comment on lines
+1554
to
+1561
| # Head branches of open PRs — never prune these. | ||
| local open_pr_branches="" | ||
| if command -v gh >/dev/null 2>&1; then | ||
| open_pr_branches=$(gh pr list --state open --limit 200 \ | ||
| --json headRefName --jq '.[].headRefName' 2>/dev/null) | ||
| else | ||
| echo -e " ${YELLOW}gh not found — cannot cross-check open PRs; nothing will be pruned.${NC}" | ||
| fi |
Comment on lines
+160
to
+175
| # pytest exit 5 == no tests collected (empty selection under markers) | ||
| if proc.returncode == 5: | ||
| result["note"] = "selection is empty under tier_a/b markers" | ||
| result["tests_maturity"] = "experimental" | ||
| else: | ||
| counts = _parse_junit(junit_path) | ||
| result.update(counts) | ||
| n_real = counts["n_selected"] - counts["n_skipped"] | ||
| if n_real <= 0: | ||
| result["tests_maturity"] = "experimental" | ||
| result["note"] = "all selected tests skipped" | ||
| elif counts["n_failed"] > 0: | ||
| result["tests_maturity"] = "preview" | ||
| result["note"] = f"{counts['n_failed']} test(s) failed" | ||
| else: | ||
| result["tests_maturity"] = "supported" |
Comment on lines
+100
to
+102
| - non-empty selection under `tier_a or tier_b` **and** all pass → `supported` | ||
| - tests ran but some failed, or only unvalidated/`tier_c` tests exist → `preview` | ||
| - no tests at all → `experimental` |
- release preflight: reject local unpushed commits so the RC tag can't point at commits origin/CI haven't seen (was only guarding "behind", not "ahead") - branch-hygiene: only allow --prune when the open-PR cross-check genuinely succeeds; an unauth'd/failed gh query no longer reads as "no open PRs" - release_gate: treat pytest exit 2-4 as an execution error (flagged, never "supported") instead of silently falling through to "experimental/skipped" - coverage + gate globs: expand with recursive=True so ** patterns match - fix ./uw release -> ./uw dev release in comment/usage strings - align release-process.md maturity rules with the implementation (empty tier_a/b selection / only tier_c -> experimental, not preview) Underworld development team with AI support from Claude Code
Member
Author
|
Addressed all 7 Copilot comments in bce2a1d:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this adds
A process and tooling for promoting work from
developmenttomainwith confidence: when a feature is announced as released, it has been validated.mainaccumulates whatever stable work comes over each quarter; the release notes — not branch surgery — distinguish features that are validated-and-guaranteed from those merely present-but-unguaranteed. So the MMPDE mover's code can be onmainwhile the release announces only the validated features as supported.This is usable this cycle for the Q4 (AFY) release.
New
./uw devnamespaceDeveloper/maintenance tools are grouped under
./uw dev <tool>(mirrors./uw worktree). The main./uw --helphides them on the stripped-down runtime/default envs and shows them by default on*-devenvs;./uw --help allreveals them anywhere. Running a dev tool off a dev env prints a soft note but still runs.dev release-checkdev releasedevelopment → mainpromotion: RC tag, full validation + gate, scaffold notes, open the dev→main PR. Stops before the production tag somain's PR + review gate stays intactdev branch-hygienedevelopment(never touches open-PR branches)dev feature-auditdev format/dev type-checkHow the guarantee works
docs/release-notes/feature-manifest.yamldeclares each shippable feature and the tests that validate it. Supported is tied to the existingtier_a/tier_bmarkers by construction — there is no new per-feature marker to maintain.scripts/release_gate.pyresolvesannounced = min(claim, tests_result): an owner can be cautious (claim preview though tests pass), and the gate can downgrade (claim supported but a test fails). It never blocks the merge — only the announcement changes. It also renders the Supported / Preview notes sections.scripts/check_manifest_coverage.pyguards against drift (atier_atest no feature references).Seed manifest (verified against the real suite)
More feature themes (snapshot toolkit, AdvDiff/SL, VEP-faults, solver infra) are candidates to add for Q4 —
dev feature-auditlists the 35 merges to triage.Docs
New
docs/developer/guides/release-process.md;branching-strategy.mdand the release-notesTEMPLATE.mdupdated.Underworld development team with AI support from Claude Code