Repository navigation
Establish shared-state Stable/Developer channel feeds and release artifacts #148
Description
Problem
CodexHub v0.1.5 has one Stable updater path but no typed, user-selectable release channel or Developer prerelease feed. The former Beta design used a second product/runtime home, separate ports, and side-by-side ownership; that model conflicts with the accepted one-installation, shared-state product contract.
The current implementation distinguishes compile-time BuildFlavor (normal/debug) and keeps both flavors on one application identity, but updater selection is still derived from BuildFlavor. Without a separate ReleaseChannel contract and channel-aware signed manifests, later immediate switching would either conflate diagnostics with product cadence or guess artifact identity.
Accepted outcome
Establish the behavior-preserving shared-state release-channel foundation: typed ReleaseChannel values Stable and Developer, persisted independently of BuildFlavor; deterministic signed feed/manifest selection for every ReleaseChannel × BuildFlavor pair; and release automation that can publish complete Developer prereleases or record HOLD.
This foundation must not expose a selectable channel control that only changes the next update feed. The user-facing selector remains disabled or absent until the dependent immediate-transition Issue completes signed install, lower-version Stable rollback, compatibility checks, backups, and restart confirmation.
Scope and invariants
- Add typed
ReleaseChannelvaluesStableandDeveloperin the Rust command/state boundary and frontend/shared types where readback is required. - Keep
ReleaseChannelindependent of compile-timeBuildFlavor(normal/debug). - Persist the effective channel in the existing shared runtime home without changing application identifier, installation path, ports, Gateway owner, Provider/model state, history, settings, or client backups.
- Define deterministic signed updater endpoint/manifest selection for all four
ReleaseChannel × BuildFlavorcombinations. - Require channel, flavor, version, platform, URL, signature metadata, and artifact identity in the manifest contract so a later transition can fail closed on mismatch.
- Use SemVer prereleases such as
0.1.6-dev.1for Developer and normal releases such as0.1.6for Stable. - Add release-pipeline support for complete Developer candidates and Stable manifests for both
BuildFlavors. - Treat each working day as a Developer release window, not a mandatory release. When no complete, reversible, green increment exists, record
HOLDinstead of publishing an empty or partial build. - Preserve all current Stable update behavior while the immediate-transition Issue is unfinished.
- Keep the frontend selector disabled or absent until the dependent immediate-transition Issue atomically enables the full signed transition contract. Internal test/probe controls must not present partial production behavior.
- Record the accepted
ReleaseChannelversusBuildFlavorterminology in the repository domain/decision documentation touched by this work.
Non-goals
- Installing or restarting into another channel.
- Lower-version Stable downgrade authorization, custom version comparison, pending-transition completion, shared-data compatibility checks, or pre-install backup; the dependent transition Issue owns them.
- Side-by-side Stable/Developer applications, separate data homes, separate ports, or concurrent Gateways.
- Reintroducing Beta as a product,
BuildFlavor, or runtime owner. - An arbitrary version picker, unsigned installer, or bypass of Tauri updater signature verification.
- The full revisioned settings patch API or generated cross-language JSON Schema program.
- Changing Provider routing, model semantics, Responses/Chat conversion, or diagnostic
BuildFlavorbehavior. - Automatically publishing a Developer build every day.
Acceptance criteria
-
ReleaseChannelhas exactlyStableandDeveloper, round-trips through the shared settings/runtime boundary, and is not inferred from or serialized asBuildFlavor. - Stable and Developer retain the same application identifier, installation, runtime home, settings, Providers/models, history, client backups, Gateway ports, and Gateway ownership.
- Signed manifest/feed selection is deterministic for every
ReleaseChannel × BuildFlavorpair and rejects channel/flavor/platform/artifact identity mismatches in focused tests. - Existing Stable update checks remain behaviorally unchanged when no channel transition is requested.
- Release automation can build a SemVer Developer prerelease and matching signed manifest for normal/debug without changing the Stable artifact identity.
- The release workflow can explicitly record
HOLD; it does not manufacture an empty or incomplete Developer candidate. - No production UI can leave the app in a state where only the future feed changed. The selector remains disabled/absent until the dependent immediate-transition Issue is complete.
- Repository terminology clearly distinguishes
ReleaseChannelfromBuildFlavorand removes no existing diagnostic behavior.
Expected hotset
src-tauri/src/app_updates.rssrc-tauri/src/build_info.rsand/or one focusedReleaseChannelmodule- Shared settings/config persistence only for channel metadata
- Frontend types/readback and UI-contract tests only as needed to keep the incomplete selector disabled
scripts/build-windows-release.ps1, release workflow/contracts, manifest fixtures, and bilingual release documentation
Dependencies and relationships
Blocked by #112 because release/update foundation work must consume the terminal lifecycle boundary rather than create a parallel restart owner. #112 consumes #143, which is blocked by #139.
Blocks the separate immediate signed channel-transition Issue. That Issue owns the selectable UI, signed installation, narrowly scoped lower-version Stable rollback, shared-data compatibility, atomic backup, exact-target confirmation, and legacy Beta-backup compatibility.
Related, not duplicate: #116 owns compile-time normal/debug BuildFlavor and is complete. #135's separate active Beta-home premise remains superseded.
Verification
cd src-tauri; cargo test --lockedcd src-tauri; cargo clippy --locked --all-targets -- -D warningscd frontend; npm run build; npm run test:ui-contract- Focused signed-manifest identity and release-pipeline contract tests
python -m pytest -qwhen shared release scripts/contracts exercise Python fixturespython scripts/report_quality_gates.py(report-only; non-blocking)
Execution contract
Execution-Contract: v2
Verification-Class: strict
Verification-Commands: cd src-tauri; cargo test --locked; cd src-tauri; cargo clippy --locked --all-targets -- -D warnings; cd frontend; npm run build; npm run test:ui-contract; focused signed-manifest/release-pipeline contract tests; python -m pytest -q when applicable; python scripts/report_quality_gates.py (report-only)
Manual-Evidence: Validate one signed Developer prerelease manifest per BuildFlavor and one explicit HOLD release-window result without installing or changing the running channel.
Architecture-Decision: resolved
Review-Owner: orchestrator
Activity
[-]Add shared-state Stable/Developer channels with immediate signed Stable rollback[/-][+]Establish shared-state Stable/Developer channel feeds and release artifacts[/+]