Skip to content

ci: define and enforce prerelease payload identity - #179

Merged
NikolayS merged 6 commits into
mainfrom
agent/wave1-stamp
Jul 28, 2026
Merged

ci: define and enforce prerelease payload identity#179
NikolayS merged 6 commits into
mainfrom
agent/wave1-stamp

Conversation

@NikolayS

@NikolayS NikolayS commented Jul 27, 2026

Copy link
Copy Markdown
Owner

Summary

  • retains pg_ash's established two-part vMAJOR.MINOR release scheme and the existing vX.Y-alphaN, vX.Y-betaN, and vX.Y-rcN prerelease shapes;
  • enforces exact tag-minus-v identity against all three ash.config.version stamp sites;
  • keeps the mandatory pre-tag CI dispatch and the v* tag-push backstop;
  • validates every released/development migration edge before applying post-prerelease development installers across full-upgrade, re-apply, and pinned public-wrapper paths;
  • documents and verifies the cumulative 2.0-beta1 → final 2.0 upgrade path.

Refs #146.

This PR deliberately does not perform the final 2.0 release stamp: it does not change released SQL, promote devel/sql/, create v2.0, or publish a release. When that release-stamp PR is made, the tag must be exactly v2.0 and every payload stamp must be exactly 2.0.

Policy

Stage Git tag Payload stamp
Alpha vX.Y-alphaN X.Y-alphaN
Beta vX.Y-betaN X.Y-betaN
Release candidate vX.Y-rcN X.Y-rcN
Final vX.Y X.Y

Prerelease tags and their payloads are immutable releases. If SQL changes after a prerelease, the changed payload is staged under devel/sql/ and receives a new identity in the next release-stamp PR. All release identity surfaces must agree; only the Git tag has the leading v.

This preserves the scheme used by the existing tags. The version-schema line in CLAUDE.md remains unchanged: vMAJOR.MINOR. The cumulative 2.0 migration remains sql/migrations/ash-1.5-to-2.0.sql; no beta-specific bridge is introduced, and its checked-in copy becomes final and immutable at v2.0.

Enforcement and CI

devel/scripts/check_release_stamp.py:

  • accepts only vX.Y, vX.Y-alphaN, vX.Y-betaN, or vX.Y-rcN, without leading zeroes or hardcoded release numbers;
  • compares tag-minus-v with shipped sql/ash-install.sql, so a development overlay cannot mask the released payload;
  • requires exactly one shared identity in the config column default, singleton update, and altered default.

.github/workflows/test.yml keeps both release gates:

  • workflow_dispatch.release_tag runs the identity check before a tag is created;
  • every pushed v* tag runs the same check as a backstop.

devel/scripts/ash_sql_chain.py now validates that every released/development migration edge is reachable from a released installer and that each requested start reaches the graph head before emitting any SQL. Its pinned-upgrade-chain emits the public compatibility wrapper first, continues through connected migrations, and appends a lone post-prerelease devel/sql/ash-install.sql only when no connected development migration already owns that overlay. Both pinned v1.5 gates use that composed path, as do the existing full-upgrade and re-apply paths.

RED

After changing the tests to the owner-selected two-part contract, the old three-part implementation failed as expected:

test_existing_prerelease_payload_tag_passes (__main__.ReleaseStampTest.test_existing_prerelease_payload_tag_passes) ... FAIL
test_inconsistent_payload_stamps_are_rejected (__main__.ReleaseStampTest.test_inconsistent_payload_stamps_are_rejected) ... ok
test_matching_final_stamp_passes (__main__.ReleaseStampTest.test_matching_final_stamp_passes) ... FAIL
test_matching_nonstandard_tag_is_rejected (__main__.ReleaseStampTest.test_matching_nonstandard_tag_is_rejected) ... ok
test_matching_prerelease_stamps_pass (__main__.ReleaseStampTest.test_matching_prerelease_stamps_pass) ...
  test_matching_prerelease_stamps_pass (__main__.ReleaseStampTest.test_matching_prerelease_stamps_pass) (stage='alpha') ... FAIL
  test_matching_prerelease_stamps_pass (__main__.ReleaseStampTest.test_matching_prerelease_stamps_pass) (stage='beta') ... FAIL
  test_matching_prerelease_stamps_pass (__main__.ReleaseStampTest.test_matching_prerelease_stamps_pass) (stage='rc') ... FAIL
test_mismatched_tag_rejects_payload (__main__.ReleaseStampTest.test_mismatched_tag_rejects_payload) ... ok
test_numeric_identifiers_reject_leading_zeroes (__main__.ReleaseStampTest.test_numeric_identifiers_reject_leading_zeroes) ... ok
test_tag_requires_v_prefix (__main__.ReleaseStampTest.test_tag_requires_v_prefix) ... ok
test_three_part_tag_is_rejected (__main__.ReleaseStampTest.test_three_part_tag_is_rejected) ... FAIL
test_connected_development_migration_owns_the_overlay (__main__.SQLChainOverlayTest.test_connected_development_migration_owns_the_overlay) ... ok
test_prerelease_development_installer_extends_upgrade_paths (__main__.SQLChainOverlayTest.test_prerelease_development_installer_extends_upgrade_paths) ... ok

======================================================================
FAIL: test_existing_prerelease_payload_tag_passes (__main__.ReleaseStampTest.test_existing_prerelease_payload_tag_passes)
----------------------------------------------------------------------
AssertionError: 1 != 0 : release stamp mismatch: release tag 'v2.0-beta1' must use vX.Y.Z or vX.Y.Z-{dev,alpha,beta,rc}.N

======================================================================
FAIL: test_matching_final_stamp_passes (__main__.ReleaseStampTest.test_matching_final_stamp_passes)
----------------------------------------------------------------------
AssertionError: 1 != 0 : release stamp mismatch: release tag 'v2.0' must use vX.Y.Z or vX.Y.Z-{dev,alpha,beta,rc}.N

======================================================================
FAIL: test_matching_prerelease_stamps_pass (__main__.ReleaseStampTest.test_matching_prerelease_stamps_pass) (stage='alpha')
----------------------------------------------------------------------
AssertionError: 1 != 0 : release stamp mismatch: release tag 'v2.0-alpha1' must use vX.Y.Z or vX.Y.Z-{dev,alpha,beta,rc}.N

======================================================================
FAIL: test_matching_prerelease_stamps_pass (__main__.ReleaseStampTest.test_matching_prerelease_stamps_pass) (stage='beta')
----------------------------------------------------------------------
AssertionError: 1 != 0 : release stamp mismatch: release tag 'v2.0-beta1' must use vX.Y.Z or vX.Y.Z-{dev,alpha,beta,rc}.N

======================================================================
FAIL: test_matching_prerelease_stamps_pass (__main__.ReleaseStampTest.test_matching_prerelease_stamps_pass) (stage='rc')
----------------------------------------------------------------------
AssertionError: 1 != 0 : release stamp mismatch: release tag 'v2.0-rc1' must use vX.Y.Z or vX.Y.Z-{dev,alpha,beta,rc}.N

======================================================================
FAIL: test_three_part_tag_is_rejected (__main__.ReleaseStampTest.test_three_part_tag_is_rejected)
----------------------------------------------------------------------
AssertionError: 0 == 0

----------------------------------------------------------------------
Ran 11 tests in 0.550s

FAILED (failures=6)

GREEN

test_existing_prerelease_payload_tag_passes (__main__.ReleaseStampTest.test_existing_prerelease_payload_tag_passes) ... ok
test_inconsistent_payload_stamps_are_rejected (__main__.ReleaseStampTest.test_inconsistent_payload_stamps_are_rejected) ... ok
test_matching_final_stamp_passes (__main__.ReleaseStampTest.test_matching_final_stamp_passes) ... ok
test_matching_nonstandard_tag_is_rejected (__main__.ReleaseStampTest.test_matching_nonstandard_tag_is_rejected) ... ok
test_matching_prerelease_stamps_pass (__main__.ReleaseStampTest.test_matching_prerelease_stamps_pass) ... ok
test_mismatched_tag_rejects_payload (__main__.ReleaseStampTest.test_mismatched_tag_rejects_payload) ... ok
test_numeric_identifiers_reject_leading_zeroes (__main__.ReleaseStampTest.test_numeric_identifiers_reject_leading_zeroes) ... ok
test_tag_requires_v_prefix (__main__.ReleaseStampTest.test_tag_requires_v_prefix) ... ok
test_three_part_tag_is_rejected (__main__.ReleaseStampTest.test_three_part_tag_is_rejected) ... ok
test_connected_development_migration_owns_the_overlay (__main__.SQLChainOverlayTest.test_connected_development_migration_owns_the_overlay) ... ok
test_prerelease_development_installer_extends_upgrade_paths (__main__.SQLChainOverlayTest.test_prerelease_development_installer_extends_upgrade_paths) ... ok

----------------------------------------------------------------------
Ran 11 tests in 0.570s

OK

Blocking review follow-up (TASK2)

The overlay guarantee is now explicit and enforced: before any SQL is emitted, every released/development migration edge must be reachable from a released installer, and the requested start must reach the graph head. The pinned v1.5 behavioral and schema-equivalence gates use a helper-generated chain that executes the public `sql/ash-1.5-to-2.0.sql` wrapper and then the candidate overlay.

Finding 1 — pinned v1.5 gates include the overlay

RED, with a temporary `devel/sql/ash-install.sql` stamped `2.0`:

```text
test_pinned_v15_gate_matches_fresh_candidate ... FAIL
fresh_version=2.0
pinned_v1_5_version=2.0-beta1

AssertionError: fresh path '2.0' != pinned v1.5 path '2.0-beta1'
```

GREEN, using the helper-generated pinned public-wrapper chain:

```text
test_pinned_v15_gate_matches_fresh_candidate ... ok
fresh_version=2.0
pinned_v1_5_version=2.0

Pinned v1.5 path and fresh path converge at '2.0'
```

The exact pinned behavioral gate and the schema-equivalence gate also passed on PostgreSQL 17.9 with that staged candidate, including state/reader-grant preservation and wrapper-chain re-application.

Finding 2 — disconnected graphs fail before emission

RED, for released `1.0→1.1` plus detached `1.2→1.3` and a development installer:

```text
test_disconnected_released_chain_is_rejected ... FAIL
emitted chain:
\i sql/ash-1.0.sql
\i sql/migrations/ash-1.0-to-1.1.sql
\i devel/sql/ash-install.sql

AssertionError: SystemExit not raised
```

GREEN, for the same graph:

```text
test_disconnected_released_chain_is_rejected ... ok
SystemExit: disconnected released upgrade chain from 1.0: stopped at 1.1, expected to reach 1.3
emitted chain:
```

The focused suite now passes 14 tests: the 11 original tests, the two blocking-finding regressions, and an additional detached-edge-below-head hardening case.

Verified 2.0-beta12.0 upgrade

The rehearsal used the exact tagged beta installer and a temporary final candidate archived from the final rebased PR head. Only the installer header and its three payload stamp literals were changed to 2.0; the canonical cumulative migration remained byte-identical. The temporary stamp was not committed.

Pinned inputs
  origin/main: 0e3aa578925889c4e71e9c8781b5c807bf0ed2f2
  candidate HEAD: 22fe149dc5e95c02fb31a4de34e76a9491ead368
  v2.0-beta1 commit: 9a18ca0705c5c97c2ce2eb8db6647784a4db9fdd
  origin/main ancestor of candidate: yes
Payload hashes (sha256)
  tagged archive ash-install.sql: d8d2b744756e80df55a30db275fdf3d5b4ab63cfc438f065be7a523e3dc800ab
  git show v2.0-beta1:sql/ash-install.sql: d8d2b744756e80df55a30db275fdf3d5b4ab63cfc438f065be7a523e3dc800ab
  checkout canonical migration: d667c27d538310049c270887934d251e55c5848866d7e3cea4bebebcd49590ed
  final candidate canonical migration: d667c27d538310049c270887934d251e55c5848866d7e3cea4bebebcd49590ed
  byte-identity checks: tagged installer exact; canonical migration unchanged
Only final-candidate changes
--- candidate/sql/ash-install.sql
+++ final/sql/ash-install.sql
@@ -1,6 +1,6 @@
 /*
  * pg_ash: Active Session History for Postgres
- * Version: 2.0 beta 1
+ * Version: 2.0
  * Fresh install: \i sql/ash-install.sql
  * Upgrade from 1.0: \i sql/migrations/ash-1.0-to-1.1.sql, then \i sql/migrations/ash-1.1-to-1.2.sql, then \i sql/migrations/ash-1.2-to-1.3.sql, then \i sql/migrations/ash-1.3-to-1.4.sql, then \i sql/migrations/ash-1.4-to-1.5.sql, then \i sql/migrations/ash-1.5-to-2.0.sql
  * Upgrade from 1.1: \i sql/migrations/ash-1.1-to-1.2.sql, then \i sql/migrations/ash-1.2-to-1.3.sql, then \i sql/migrations/ash-1.3-to-1.4.sql, then \i sql/migrations/ash-1.4-to-1.5.sql, then \i sql/migrations/ash-1.5-to-2.0.sql
@@ -255,7 +255,7 @@
   include_bg_workers         bool not null default false,
   debug_logging              bool not null default false,
   encoding_version           smallint not null default 1,
-  version                    text not null default '2.0-beta1',
+  version                    text not null default '2.0',
   rotated_at                 timestamptz not null default clock_timestamp(),
   installed_at               timestamptz not null default clock_timestamp(),
   rollup_1m_retention_days   smallint not null default 30
@@ -335,8 +335,8 @@
  * fresh 2.0 install and an upgrade chain landing on 2.0 (the CI
  * schema-equivalence check).
  */
-update ash.config set version = '2.0-beta1' where singleton;
-alter table ash.config alter column version set default '2.0-beta1';
+update ash.config set version = '2.0' where singleton;
+alter table ash.config alter column version set default '2.0';
 
 /*
  * Wait event dictionary.
Changed-file check: only sql/ash-install.sql (4 additions, 4 deletions)
Dedicated database: ash_pr179_upgrade_1272039
Tagged v2.0-beta1 install: ok
                                                           server_version                                                            | pg_cron_installed
-------------------------------------------------------------------------------------------------------------------------------------+-------------------
 PostgreSQL 17.9 (Ubuntu 17.9-1.pgdg24.04+1) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 13.3.0-6ubuntu2~24.04.1) 13.3.0, 64-bit | f
(1 row)

UPDATE 1
 config_version | missed_samples |  version_default
----------------+----------------+-------------------
 2.0-beta1      |             42 | '2.0-beta1'::text
(1 row)

      metric       |            value
-------------------+-----------------------------
 version           | 2.0-beta1
 pg_cron_available | no (use external scheduler)
(2 rows)

Canonical cumulative migration to final 2.0: ok
 config_version | missed_samples | version_default
----------------+----------------+-----------------
 2.0            |             42 | '2.0'::text
(1 row)

      metric       |            value
-------------------+-----------------------------
 version           | 2.0
 pg_cron_available | no (use external scheduler)
(2 rows)

Severity scan (ERROR|FATAL|WARNING) across installer and migration logs: none
Dedicated database dropped and absent: yes
Temporary files removed: yes

Checks

  • rebased onto current origin/main at 62beb8c705d424d8e8cd12931d456f9be5f21e56 after chore: retire pre-2.0 benchmark suite #187 landed;
  • python3 devel/scripts/test_release_stamp.py -v: 14 passed (all 11 original tests plus three focused regression/hardening tests);
  • shipped v2.0-beta1 tag/payload identity: accepted;
  • synthetic final v2.0 / 2.0 identity: accepted;
  • three-part, malformed, mismatched, and internally inconsistent identities: rejected;
  • discovered full-upgrade chain: seven includes; current reapply chain: empty and unchanged;
  • pushed-head GitHub Actions: 11/11 checks passed across PostgreSQL 14–19beta1, the PG17 no-cron variant, docs lint, and CodeQL;
  • workflow YAML parsed successfully; documentation guards and git diff --check: clean;
  • real PostgreSQL 17.9 beta-to-final rehearsal: passed with sentinel retention and no severity hits.

Final landing rebase and verification

Hand-rebased onto current main at bfde011 after #192. Exact merge candidate: eba138f9408fd33f38065abaff73eb7024daec0f.

  • All four original PR commits range-diff patch-identically. The only current-main overlap was .github/workflows/test.yml; it applied text-clean and retains all 848 inline assertions, PG19beta2, the release: keep compacted query attribution honest #198/release: keep stale rollups honest without losing fast path #199 extracted gates, and every release: add behavioral feature-gate coverage #192 feature/degraded surface. The workflow is 509,333 bytes, below GitHub’s 512,000-byte limit.
  • The owner-selected contract remains exact: v2.0 / payload 2.0; the shipped v2.0-beta1 identity passes; matching v2.0.0 is rejected. This PR does not stamp or tag the final release and changes no released SQL.
  • Final audit found and fixed two additional chain-preflight gaps. A lone development installer must stay on the released prerelease’s X.Y line, and a final shipped payload requires a connected development migration. After promotion, sql/ash-install.sql must also name the released migration graph head, so compatibility shims cannot mask an omitted edge.
  • RED: before those guards, a 2.1 development installer over a graph ending at 2.0, a same-line lone installer after final 2.0, and a promoted 2.1 installer without a 2.0→2.1 migration each failed their new regression with SystemExit not raised; the old helper emitted/includes or accepted the chain. The negative fixtures require exactly empty stdout.
  • GREEN: all 17 focused identity/chain tests pass. Same-line beta-to-final full/reapply/pinned paths and connected-development-migration ownership remain positive controls.
  • Exact disposable PG17 upgrade-chain passes all nine selected steps, including the pinned actual-v1.5 wrapper and re-apply, reader-grant/least-privilege checks, config ordinals, and both fresh-vs-upgrade schema-equivalence comparisons.
  • Exact-head GitHub Actions is green across docs and PostgreSQL 14–19beta2: https://github.com/NikolayS/pg_ash/actions/runs/30317124198
  • Exact-head CodeQL is green: https://github.com/NikolayS/pg_ash/actions/runs/30317122014

The eventual v2.0 release-stamp PR must still update the installer and migration’s human-readable version comments along with the three enforced SQL stamps, as docs/RELEASE_PROCESS.md requires.

@NikolayS
NikolayS force-pushed the agent/wave1-stamp branch 2 times, most recently from b8ff802 to 22fe149 Compare July 27, 2026 17:23
@NikolayS

Copy link
Copy Markdown
Owner Author

Blocking pre-merge review — codex review standing in for REV

REV is not installed on this host. I ran a separate non-interactive codex review --base origin/main and independently reproduced its findings.

TASK2/audit verdict being verified

#179 — prerelease payload identity (#146). pg_ash keeps the two-part vMAJOR.MINOR tag scheme; 2.0 tags as v2.0, not v2.0.0. Verify the PR reflects that and does not reintroduce three-part SemVer.

The two-part identity portion holds: the final head accepts v2.0 / the shipped v2.0-beta1 shapes and rejects v2.0.0. The broader stated overlay contract does not yet hold.

RED / GREEN verification

  • RED: checked out the pre-fix implementation at 207a1beda05b7bbe4198b8a843dcb42a30077b42, overlaid the final two-part test assertions from 22fe149dc5e95c02fb31a4de34e76a9491ead368, and ran python3 devel/scripts/test_release_stamp.py -v. It exited 1 with the same six failures documented in the PR body: v2.0, all three two-part prerelease stages, and the existing beta payload were rejected, while v2.0.0 was accepted.
  • GREEN: on rebased head 22fe149dc5e95c02fb31a4de34e76a9491ead368, all 11 dedicated tests passed. v2.0-beta1 matched the shipped stamp, and v2.0.0 was rejected.

codex review findings

  1. [P1] Include the overlay in pinned v1.5 upgrade checks (devel/scripts/ash_sql_chain.py:140-143). When a post-prerelease devel/sql/ash-install.sql is staged, helper-generated chains apply it, but the existing pinned v1.5 behavioural and schema-equivalence gates still execute sql/ash-1.5-to-2.0.sql directly. Reproduction with a temporary development installer stamped 2.0: the fresh candidate ended at 2.0, while the direct v1.5 path ended at 2.0-beta1. Those gates derive expected_version from the development installer, so they fail as soon as the documented overlay workflow is used.
  2. [P2] Reject a disconnected chain before appending the overlay (devel/scripts/ash_sql_chain.py:160-162). A synthetic released graph with 1.0→1.1 plus disconnected 1.2→1.3 emitted sql/ash-1.0.sql, ash-1.0-to-1.1.sql, and then devel/sql/ash-install.sql, silently skipping the missing edge. The installer can recreate enough schema for upgrade CI to pass without exercising required data migrations.

These are behavioural contradictions to the PR body's claim that post-prerelease development installers are safely discoverable as upgrade/reapply overlays. Per TASK2's stop rule, I am leaving #179 draft and unmerged. No source changes or force-push were made.

@NikolayS
NikolayS force-pushed the agent/wave1-stamp branch from 22fe149 to 0a47899 Compare July 27, 2026 18:26

NikolayS commented Jul 27, 2026

Copy link
Copy Markdown
Owner Author

Addressed both blocking findings from the pre-merge review in 0a47899645926e90e1164197ab3526f1e1976760.

  1. P1 — pinned v1.5 gates: added pinned-upgrade-chain START. It validates the graph, emits the public compatibility wrapper first, continues through connected migrations, and appends the lone development installer when no development migration owns the overlay. The behavioral gate (initial apply and re-apply) and schema-equivalence gate now consume that generated chain. With a temporary devel/sql/ash-install.sql stamped 2.0, both the fresh and pinned paths ended at 2.0; the exact PostgreSQL 17.9 behavioral and schema-equivalence workflow steps passed.
  2. P2 — disconnected graph: chain generation now preflights every released/development edge for reachability from a released installer and verifies each requested start reaches the graph head before printing any \i. The reviewer’s 1.0→1.1 plus detached 1.2→1.3 graph exits loudly with no emitted SQL. An additional below-head detached-edge case is covered too.

Validation after rebasing onto current origin/main (62beb8c): 14/14 focused tests passed; the original 11 passed separately; v2.0 / v2.0-beta1 remain accepted and v2.0.0 rejected; YAML, actionlint, docs guards, diff checks, and frozen-sql/ checks passed. The pushed head then completed 11/11 GitHub checks successfully across PostgreSQL 14–19beta1, the PG17 no-cron variant, docs lint, and CodeQL.

The PR body contains the verbatim RED/GREEN evidence for both findings and the corrected overlay guarantee. The PR remains draft.

@NikolayS
NikolayS force-pushed the agent/wave1-stamp branch from 0a47899 to a9b21b4 Compare July 28, 2026 00:07
@NikolayS
NikolayS marked this pull request as ready for review July 28, 2026 00:07
The prior helper appended any lone development installer after validating only the migration files. A 2.1 installer over a graph ending at 2.0 therefore emitted SQL and could hide a missing 2.0-to-2.1 migration.

Preflight the overlay before any include is emitted. Migration-free overlays must stay on the validated release line and are allowed only while the shipped payload is a prerelease; a final payload requires a connected development migration.

RED: the next-line fixture failed with "SystemExit not raised". GREEN: all 16 release-stamp/chain tests pass, including same-line beta-to-final, connected-migration ownership, next-line rejection, and final-release rejection.
After promotion removes devel/sql/ash-install.sql, the overlay-only guard no longer runs. A shipped 2.1 installer could therefore sit over a released graph ending at 2.0; historical shims replay the current installer, allowing upgrade and schema-equivalence gates to mask the missing edge.

Validate the shipped installer release line against the released graph head before tracing or emitting any upgrade chain. Development migrations may still extend beyond that released head, while promoted payloads require the corresponding migration to be promoted too.

RED: the promoted-next-line fixture failed with "SystemExit not raised". GREEN: all 17 release-stamp/chain tests pass and every rejection asserts zero emitted SQL.

@samo-agent samo-agent left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Final pre-merge review — codex review standing in for REV

Verdict: PASS on exact head eba138f9408fd33f38065abaff73eb7024daec0f.

  • Hand-rebased onto exact base bfde011. All four original commits are patch-identical in range-diff; the only overlap was the workflow, which applied text-clean and preserves #192’s 848 inline assertions, PG19beta2, extracted #198/#199 gates, and all feature/degraded surfaces. Size: 509,333 bytes.
  • Owner identity decision is implemented exactly: final v2.0 ↔ payload 2.0; v2.0-beta1 passes; v2.0.0 is rejected. Released SQL is untouched and no tag/release is created.
  • The prior blocking P1/P2 findings remain fixed: generated pinned v1.5 chains include the candidate overlay, and disconnected graphs fail before emission.
  • Final audit found two adjacent preflight gaps and fixed them in 7c34c57/eba138f: migration-free development overlays must be same-line and post-prerelease, and a promoted shipped installer must match the released migration head.
  • RED is discriminating: the old helper raised no SystemExit for next-line, post-final same-line, or promoted-next-line missing-migration fixtures. GREEN is 17/17; every negative fixture also requires empty stdout. Positive controls retain beta→final full/reapply/pinned paths and connected development migrations.
  • Disposable PG17 upgrade-chain passes, including actual-v1.5 wrapper/reapply, reader grants and least privilege, config ordinal checks, and both schema-equivalence comparisons.
  • Exact-head Test is green: https://github.com/NikolayS/pg_ash/actions/runs/30317124198
  • Exact-head CodeQL is green: https://github.com/NikolayS/pg_ash/actions/runs/30317122014
  • YAML/Python syntax, helper parser tests 7/7, diff check, and frozen released-SQL check pass.

Non-blocking release-stamp reminder: the eventual v2.0 stamp must update human-readable installer/migration comments as well as the three machine-checked stamps.

No merge blocker remains.

@NikolayS
NikolayS merged commit 87c22a3 into main Jul 28, 2026
11 checks passed
@NikolayS
NikolayS deleted the agent/wave1-stamp branch July 28, 2026 00:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants