Docs/Reference

Reference

Release and versioning

Tama uses Semantic Versioning. The version of a distributable desktop release is CFBundleShortVersionString in App/Info.plist, the version source .wisent-release.json declares; stado release submit --version must name that exact version, and Stado refuses any other. The build stamps it on the app, the Network Extension, the update feed and the release evidence. Builds outside a Stado release keep their source metadata but are never supported or published.

#Public contract and version policy

Tama uses Semantic Versioning. The version of a distributable desktop release is CFBundleShortVersionString in App/Info.plist, the version source .wisent-release.json declares; stado release submit --version must name that exact version, and Stado refuses any other. The build stamps it on the app, the Network Extension, the update feed and the release evidence. Builds outside a Stado release keep their source metadata but are never supported or published.

The public contract includes:

  • documented UI workflows and their safety confirmations;
  • session-control and installed-release JSON schemas;
  • Application Support state layout;
  • hook-release and build-provenance manifest schemas;
  • supported macOS version and architecture;
  • setup, emergency recovery, upgrade, rollback, and uninstall behavior;
  • integration capability and failure semantics documented in integrations.md.

While the major version is zero, an incompatible change advances MINOR; a compatible addition or correction advances PATCH. Every release-notes section contains exactly these non-empty categories in order: Added, Changed, Fixed, Removed or deprecated, Security, Configuration, Data or state migrations, Compatibility requirements, Operator actions, Known limitations, and Qualification evidence. Use None when a category has no applicable change; never omit it.

#Product and hook identities

The desktop product version and bundled hook release are separate identities:

  • The release version identifies Tama's public desktop contract.
  • The hook releaseId is a SHA-256 content identity for the bundled policy tree; the release verifies the immutable hook source by digest before it builds (Release/tama-source.sh verify).
  • tama-build.json inside the signed app records product version, source commit, channel, build timestamp, target platform, and architecture.
  • TamaProductVersion in the app and Network Extension property lists carries the same version; both components share the same numeric CFBundleVersion.
  • The release evidence evidence/release.json records the product, version, platform, the SHA-256 of Tama.zip, of the update feed and of its signature, the digests of the hook source and the SwiftPM dependency cache the build consumed, and that the app was notarized.

A release is valid only when the committed tree is clean, the version equals the manifest's version source, every quality gate the manifest declares passes (fmt, and compile through Release/stado-release.sh compile), the immutable inputs match their digests, code signing and notarization succeed, and the app's SUPublicEDKey is the public half of the Sparkle key the release signs with.

#Channels

ChannelAudienceGuaranteePromotionAutomatic updates
developmentMaintainersMay be dirty or unsigned; never supportedBuilt locally; never publishedNever
candidateAuthorized Wisent operatorsSigned, notarized bytes built once from one source revisionstado release submit --channel candidateThrough the candidate feed
stableGeneral intended usersBackward-compatible within a major linestado release promote moves the exact candidate bytes; nothing is rebuiltThrough the stable feed

No stable release exists yet. A release reaches stable only by promoting the bytes the candidate built: the same Tama.zip, signature and feed, never a rebuild. stado release rollback restores the previous desired release, and stado release status shows desired and observed rollout state.

#Release artifact

The release stages, under the release's own coordinate:

  • Tama.app and Tama.zip, the archive built from it with fixed file times;
  • Tama.zip.sparkle-signature, the EdDSA signature Sparkle's sign_update wrote for the archive;
  • appcast.xml, the signed update feed whose enclosure is that archive at the fleet's public origin (stado web origin url /api/release/sparkle), so an app that requires a signed feed accepts it;
  • evidence/release.json, evidence/notary.json (the notarization stado product signing notarize recorded) and evidence/DIGESTS in shasum -a 256 -c format.

Installed copies of Tama read their updates from the appcast Stado serves at /api/release/appcast?product=tama-desktop on the same origin. Installation, upgrade and rollback by hand select an exact version and check the archive against evidence/DIGESTS.

#Release process

Owner: the wisent-ai/tama-desktop maintainers. Signing, notarization, Sparkle and provisioning secrets are read from Skarbiec through the manifest's secret_env at build time; nobody handles them by hand.

Before submitting a release, acquire the app and network-filter provisioning profiles through stado credentials signing-profile ensure. Set PROFILE_ITEM to the common item part of the manifest's TAMA_APP_PROFILE_B64 and TAMA_NETWORK_FILTER_PROFILE_B64 bindings, VAULT_HOST to its owner-vault host, and API_KEY_ITEM to the authorized team API key item. Do not create a differently named signing item that the manifest never reads.

stado credentials signing-profile ensure --provider apple \
  --host "$VAULT_HOST" "$PROFILE_ITEM" --credentials "$API_KEY_ITEM" \
  --profile app_provisioning_profile_base64=ai.wisent.tama.desktop \
  --profile network_filter_provisioning_profile_base64=ai.wisent.tama.network-filter \
  --json

The key item must expose key_id, issuer_id and private_key_p8_base64 to Stado. A missing-field refusal ends acquisition before a profile is issued; it is not evidence of an Apple sign-in failure or a ready signing configuration. Unregistered bundle identifiers are refused by name. Stado reuses an active profile of the requested name or creates one through App Store Connect, then stores the profile fields in the selected owner vault.

Inspect nonsecret stored-field metadata with stado credentials item show --host "$VAULT_HOST" "$PROFILE_ITEM" --json. In Stado Desktop, select the owner host, then Credentials → Available operations… → Store code-signing provisioning profiles in a signing item, using the same manifest item, profile pairs and API key item. The form uses the same acquisition command; neither its presence nor a stored profile proves that a release was built or signed. Qualification requires the actual acquisition result, persisted field metadata, and the release's signing and notarization evidence.

  1. Update README first for any changed promise, audience, workflow, interface, environment, or safety boundary.
  2. Review downstream onboarding, core, integration, canonical-example, and test contracts.
  3. Classify the change, select the next semantic version, set it in App/Info.plist, and update CHANGELOG.md.
  4. Review configuration and stored-state compatibility. Add a reversible migration or declare rollback limits.
  5. Commit, push, and submit the exact commit: stado release submit --source <tama-desktop checkout> --version <version> --channel candidate. Stado runs the declared gates on the submitting host before it claims the release coordinate, then builds on a darwin-arm64 builder with Release/stado-release.sh build: it verifies the immutable hook source and SwiftPM cache by digest, imports the Developer ID certificate into a keychain that lives only for the build, refuses any identity that is not a Developer ID Application identity, builds the app with Scripts/build-app.sh, notarizes it, signs the archive and the feed with Sparkle, and writes the evidence. Every refusal prints its own sentence and exits non-zero before anything is published.
  6. Stado publishes each staged object to the release coordinate, reads it back, and byte-compares it with the staged bytes; a write without a matching read-back is a failed publication.
  7. Exercise every safe local canonical example against the candidate, control and record every credentialed, device or destructive example, and run the suites defined in testing.md on a clean supported Mac, with the observed product and hook identities.
  8. Promote that candidate to stable with stado release promote only when the evidence matches it; the stable channel carries the candidate's exact bytes.
  9. Keep the previous stable release and its recovery instructions: stado release rollback restores it.

Build, publication, and runtime credentials are separate. Runtime Wisent credentials are never available to the release build.

#Release-note format

Every release note contains these headings, even when the value is None:

  • Added
  • Changed
  • Fixed
  • Removed or deprecated
  • Security
  • Configuration
  • Data or state migrations
  • Compatibility requirements
  • Operator actions
  • Known limitations
  • Qualification evidence

Commit titles alone are not release notes.

#Compatibility and migrations

Tama 0.x supports only the state schemas documented by that minor line. Unsupported schemas fail before mutation. A migration must define preconditions, backup, duration, restart impact, partial-failure behavior, resume behavior, reversibility, and the compatible rollback version.

Version 0.2.0 introduces no forward-only data migration. It continues to read the existing installed hook release and session-control v2 records. It changes startup behavior: service registration and runtime installation become explicit user actions. This is a breaking onboarding change from 0.1.0, hence the 0.2.0 version.

Mixed desktop versions must not operate concurrently on one user state directory. Agent supervisors may be resumed only when their loaded hook release and catalog checksum are visible and compatible with the app's bundled catalog.

#Upgrade

  1. Record the current Tama version, source revision, installed hook release ID, and catalog checksum.
  2. Take the exact newer Tama.zip and its evidence/DIGESTS from the promoted release, or let Sparkle offer it from the signed appcast.
  3. Verify the digest and read migration/operator actions before quitting the old version.
  4. Back up ~/Library/Application Support/Tama when release notes identify a state change.
  5. Replace the app while supervised sessions are stopped.
  6. Open the new version, confirm build identity, then explicitly install a newer bundled hook runtime if offered.
  7. Confirm backend and live runtime status before resuming work.

Skipping intermediate versions is supported only when every skipped release note says its migration is cumulative.

#Rollback

  1. Stop supervised sessions and quit Tama.
  2. If no forward-only migration ran, restore the exact previous app artifact and its compatible Application Support backup.
  3. Open the previous app and re-enable its integrity-sealed hook release if needed.
  4. Confirm product version, source revision, hook release ID, catalog checksum, and backend readiness before resuming sessions.
  5. If a release declares a forward-only migration, do not downgrade; use its documented recovery procedure instead.

Rollback success is an observable matching build identity plus a loaded runtime without reloadRequired or registry errors.