| 1 | # Releasing Reasonix |
| 2 | |
| 3 | Reasonix has one user-facing release line: the official `X.Y.Z` version. The |
| 4 | release engine keeps the proven Stable publication topology: three immutable |
| 5 | Git tags on one `main-v2` commit and one protected orchestrator. |
| 6 | |
| 7 | | Surface | Immutable tag | Public result | |
| 8 | | --- | --- | --- | |
| 9 | | CLI | `vX.Y.Z` | GitHub Release and Homebrew | |
| 10 | | npm | `npm-vX.Y.Z` | root and platform packages; `latest`, `canary`, and `next` compatibility aliases | |
| 11 | | Desktop | `desktop-vX.Y.Z` | signed GitHub Release, immutable R2 directory, and `latest/latest.json` | |
| 12 | |
| 13 | The three tags are implementation identities, not user-selectable channels. |
| 14 | They must always resolve to the same commit and may never be moved or deleted. |
| 15 | |
| 16 | The Go SDK module (`sdk/go`) is versioned independently of the three product |
| 17 | surfaces: its tags look like `sdk/go/vX.Y.Z` (first: `sdk/go/v1.0.0`) and |
| 18 | point at the release commit that first shipped the corresponding Extension |
| 19 | Protocol major. SDK tags do not trigger product releases, do not move, and |
| 20 | do not change the three-tag contract above. |
| 21 | |
| 22 | ## Daily release flow |
| 23 | |
| 24 | The normal developer path has one version input, one reviewed Notes PR, one |
| 25 | terminal command, and one environment approval: |
| 26 | |
| 27 | 1. Open Actions → **Prepare release** and enter `X.Y.Z`. |
| 28 | 2. Review and merge the generated bilingual release-notes PR. |
| 29 | 3. From an authenticated maintainer checkout, run: |
| 30 | |
| 31 | ```sh |
| 32 | ./scripts/release-stable.sh X.Y.Z |
| 33 | ``` |
| 34 | |
| 35 | 4. Approve the resulting **Release stable** run once in the `release` |
| 36 | environment. |
| 37 | 5. Wait for its postflight to verify CLI, npm, Desktop, R2, Homebrew, and the |
| 38 | changelog. |
| 39 | |
| 40 | If repository policy prevents Actions from opening the Notes PR, the workflow |
| 41 | still pushes `release-notes/vX.Y.Z` and prints this recoverable handoff: |
| 42 | |
| 43 | ```sh |
| 44 | gh pr create --repo esengine/DeepSeek-Reasonix \ |
| 45 | --base main-v2 --head release-notes/vX.Y.Z --fill |
| 46 | ``` |
| 47 | |
| 48 | Do not rerun Notes generation merely because PR creation was denied. |
| 49 | |
| 50 | ## What the tag helper proves |
| 51 | |
| 52 | `scripts/release-stable.sh` fails before creating any public ref unless: |
| 53 | |
| 54 | - the version is canonical `MAJOR.MINOR.PATCH`; |
| 55 | - remote `main-v2` is the commit that introduces or updates the complete, |
| 56 | reviewed Stable catalog record; |
| 57 | - exact-commit `main-v2` CI completed successfully; |
| 58 | - `vX.Y.Z`, `npm-vX.Y.Z`, and `desktop-vX.Y.Z` are all absent. |
| 59 | |
| 60 | It then pushes a no-op guard for that exact `main-v2` SHA and all three |
| 61 | lightweight tags with one atomic Git transaction. If `main-v2` advanced while |
| 62 | CI was running, the complete transaction is rejected and no version tag is |
| 63 | consumed. A partial tag set is therefore not a normal failure mode. The |
| 64 | `vX.Y.Z` event starts the existing protected Stable relay; maintainers do not |
| 65 | dispatch child CLI, npm, or Desktop publishers. |
| 66 | |
| 67 | ## Publication and approval |
| 68 | |
| 69 | The protected Stable workflow re-resolves all three tags to one SHA on |
| 70 | `main-v2` history, revalidates that normal candidates introduced their reviewed |
| 71 | Notes and passed exact-SHA push CI, and runs the cache guard before requesting |
| 72 | the sole human approval. `main-v2` may safely advance after the atomic tag |
| 73 | transaction without invalidating that candidate. After approval it performs a |
| 74 | no-publication SignPath preflight, then runs CLI, npm, and Desktop publishers |
| 75 | against the immutable candidate. |
| 76 | |
| 77 | The npm publisher advances `latest`, `canary`, and `next` to the same official |
| 78 | version. `canary` and `next` remain only so historical scripts continue to |
| 79 | install a supported build; they are not testing channels and are not advertised. |
| 80 | |
| 81 | No custom GitHub App, App private key, repository-owner setting change, manual |
| 82 | tag UI, or child-workflow approval is required. |
| 83 | |
| 84 | ## Recovery |
| 85 | |
| 86 | For a partial Stable publication, open **Release stable** on protected |
| 87 | `main-v2`, enter the existing `vX.Y.Z`, select only the missing surfaces, and |
| 88 | approve `release` once. Recovery accepts only an immutable three-tag set that |
| 89 | remains on `main-v2` history. It must reuse matching public content and fail |
| 90 | closed on conflicting checksums, signatures, manifests, npm provenance, or R2 |
| 91 | objects. |
| 92 | |
| 93 | Never move, delete, or recreate a published tag. Ship product corrections as a |
| 94 | higher patch version. |
| 95 | |
| 96 | ## Retired prerelease paths |
| 97 | |
| 98 | Normal Preview, Canary, and RC publication entrypoints are disabled. Historical |
| 99 | tags, Releases, package versions, changelog pages, and the final bridge endpoints |
| 100 | remain available for compatibility, but they do not appear in current download |
| 101 | navigation or release preparation. |
| 102 | |
| 103 | Old CLI and Desktop channel settings resolve to the official line. Frozen |
| 104 | Preview endpoints continue to lead old clients to the bridge build, which can |
| 105 | then upgrade to the current official release. |
| 106 | |
| 107 | ## First release after cutover |
| 108 | |
| 109 | For the first release after this change, independently prove: |
| 110 | |
| 111 | - the three tags resolve to the reviewed Notes merge SHA; |
| 112 | - both GitHub Releases contain their complete expected assets; |
| 113 | - npm root and all six platform packages report that SHA and |
| 114 | `latest == canary == next`; |
| 115 | - R2 immutable and latest manifests are byte-identical and every URL works; |
| 116 | - Homebrew and reasonix.io show the same version; |
| 117 | - old bridge clients can upgrade to the official release. |
| 118 | |
| 119 | The release is incomplete until every public surface reaches a terminal, |
| 120 | verified state. |
| 121 |