Task — engineering-spec@1

"Store build-number monotonicity — release-time floor decouples re-tags from BUILD_NUMBER bumps (Play versionCode 10706 collision)"

doneTASK-IMP-078
module improvement · class product · priority p0 · created 2026-07-13 · shipped 2026-07-13
depends on none · blocks none

§1

  1. stamp-release-version.mjs MUST accept --store-monotonic: effective build number = max(BUILD_NUMBER, floor(now/60s)). Without the flag, behavior is byte-identical to today (committed baseline, --check drift detection, version.yml bump commits all unchanged).
  2. release.yml's android and iOS stamp steps MUST pass the flag; no other call site does. The high-water-mark guard keeps validating the FILE value (the committed floor), and the effective value can only be >= it.
  3. BUILD_NUMBER keeps its existing role and is NOT bumped here: one mechanism owns re-tag safety (the wall-clock floor), one owns the committed baseline (version bumps). A second incrementer was considered and rejected - it re-introduces the operator-memory dependency this task removes.
  4. Wall-clock minutes, not commit timestamps: a re-tag of the SAME commit must still get a fresh number (commit-time would collide; run-time cannot). ~29.7M in 2026 vs Play's 2100000000 cap - headroom measured in millennia.

Lean profile: one flag + two step args; defect, fix, and both-mode behavior machine-verified in-session; store acceptance proven by the next tag run.

§5 (run 2026-07-13)

§9

§10

FailureDetectionRecovery
two release runs inside the same minutestore rejects the second upload, loudre-run: next minute, next number
runner clock skew backwardsfloor still >= committed BUILD_NUMBER; worst case equals a consumed number -> loud store rejectionre-run after NTP settles
flag typo'd/dropped in a future workflow editnext re-tag reproduces the 10706-class failure loudly at uploadre-add flag; this spec's §5 grep pins the 2 call sites
someone passes the flag in version.ymlcommitted files would carry a wall-clock number - visible in the bump commit diff, and --check flags drift on the next runrevert; flag is release.yml-only by §1 clause 2

End of TASK-IMP-078.

Audit

  • ISS-001: draft fixed only the android lane (the reported failure) - resolved: the same 10706 is already consumed at ASC for iOS 1.0.0, so the iOS stamp step gets the flag in the same change; fixing one lane would have moved the failure, not removed it (spec risk_if_skipped).
  • ISS-002: draft derived the floor from the tagged commit's timestamp (deterministic, same value across jobs) - resolved: rejected because re-tagging the SAME commit would reuse the number and collide; wall-clock minutes are collision-free across runs (spec §1 clause 4 records the trade). Score = 10/10.