# Releases
Vership is the release control plane for `teams-cli`. GitHub Actions is the
execution plane for cross-platform builds, publication, provenance, and
downstream packaging.
## Create a release
Start from a clean, up-to-date `main` branch and run:
```sh
vership preflight
vership bump patch --prepare # or minor/major
# Review the candidate and obtain approval to push and publish.
vership release
tarry cmd --timeout 20m -- vership verify
```
Vership runs `make check`, updates the package version and changelog, creates
the Conventional Commit release commit. `--prepare` stops before tagging or
pushing. After approval, `vership release` publishes that same prepared version;
do not bump again. Its tag starts the release workflow.
Cargo and Python package versions are kept synchronized as one release unit.
## Release 0.1.11
The `0.1.11` candidate builds on the desktop implementation validated in
`0.1.10-alpha.1`, adding direct Enter-to-send with multiline paste handling and a
confirmed Teams debugging restart from the WSL TUI. Managed desktop connection
commands preserve prior settings, share Windows/WSL recovery state and check
process ownership before disconnecting. Send results distinguish submission,
queueing and delivery; possibly-sent TUI drafts require an explicit second-copy
confirmation. Exact client-ID checks inspect the newest 50 cached messages and
leave missing or unspecified delivery evidence unknown. It supports cached chat reads and opt-in plain-text sends
through Teams on macOS, Windows and WSL. The Windows helper speaks protocol 3.
Personal Microsoft accounts use the desktop backend; Graph remains limited to
work/school accounts.
An unsuffixed release can include an explicitly experimental, opt-in backend.
Graph remains the default. Desktop compatibility still depends on Teams internals
and is limited to the operations and tested scope documented below. A beta release
is optional; it is not a prerequisite for publishing `0.1.11`.
The version is already prepared. Finish it with `vership release` after approval;
do not run another bump. Cargo, the Python package and the CLI all use `0.1.11`.
Before publishing, run `make check`, the release dry run and package checks on the
final candidate. Live-test the new TUI send/paste behavior and the WSL restart
confirmation, cancellation and reconnection paths. Release CI must pass its
Linux/macOS/Windows checks and build every intended archive and Python wheel.
After the workflows finish, verify every publication target:
```sh
vership verify 0.1.11 --targets tag,release,crates,pypi
```
The binary build jobs extract and smoke test their packaged CLI before uploading
it. Follow publication with installation tests on macOS, Windows and WSL,
including the matching Windows helper's automatic download under WSL. Desktop
diagnostics can be tested with isolated profiles; successful connection metadata
does not establish sign-in or message access.
### Desktop validation scope
The instrumented runtime checks below used the published `0.1.10-alpha.1`
artifacts. Work/school WSL2 coverage is a separate user report.
| Personal | Instrumented reads, send and exact readback | Instrumented reads, send and exact readback | Instrumented reads, send and exact readback |
| Work/school | Instrumented cache reads | No separate work/school send validation | User-reported reads, send and readback |
The work/school report did not capture the exact CLI or Teams version. Keep it
separate from instrumented evidence. The user also reported Windows working;
individual native Windows TUI interactions were not instrumented.
The `0.1.11` reliability candidate has separate instrumented validation: managed
connect, repeated connect without restarting, disconnect and settings preservation
on macOS and native Windows; a multiline Mac TUI paste that did not send until
Enter and appeared exactly once; and a WSL terminal fixture for lost responses,
guarded resend, exact-ID reconciliation and the structured uncertainty contract.
The fixture made no real Teams calls. Windows state-machine fixtures cover
interrupted setup, external setting changes, conflicting owners, changed
processes, existing debugging flags and repeated disconnects. These checks use
isolated records and simulated platform effects.
WSL live checks also covered restart confirmation and cancellation with Windows
PATH entries removed, one TUI send with exact readback, and native Windows
disconnect after WSL TUI use. The final lifecycle run restored normal Teams,
closed the debugging port and cleared the recovery record without fallback.
Windows fixtures additionally cover auxiliary processes appearing or exiting,
reused process IDs, changed listener ownership and a rebound port during cleanup.
The tested personal Teams cache omitted delivery status even when the exact
message was present. Readback therefore reported `found: true` and delivery
`unknown`; cache presence alone is not a delivery receipt. Each real send was
issued once, with its checkpoint and exact correlation ID retained privately.
Instrumented checks also covered cache pagination, read-only refusal, explicit
account-surface selection and ambiguity refusal, malformed cached text and
sentinel timestamps, macOS Teams restart recovery, WSL helper replacement while
the TUI stayed open, and normal shutdown with debugging closed. A controlled
helper fixture verified one send attempt and an `unconfirmed` error after a lost
response; no real Teams send was deliberately interrupted. Each real test send
was issued once and read back by its exact message ID.
Multi-day daily use, actual account switching, macOS work/school sending, live
Intel Mac coverage, and broader Teams-version and managed-policy coverage remain
to be validated. These are follow-up coverage goals for the experimental backend;
they do not require putting the whole CLI on a prerelease channel.
The cache contains only synced history; only existing chats and plain-text sends
are supported. Missing cached profiles leave names or viewer identity unknown
without breaking reads. Multiple accounts within one selected surface are
refused. Keep these limits visible in the normal release documentation.
## Failure policy
If a release fails before any release, artifact, package, checksum, or
attestation becomes public, delete and recreate the brief tag and retry the
same version. Once anything was published, preserve the tag and issue a patch
release for release-content corrections. Registry and downstream-packaging
jobs are separate recovery domains; retry only the failed job when possible.
## Dry runs
The Release workflow can be dispatched from `main` with `dry_run` enabled. It
uses the package version unless an explicit `version` is supplied, builds the
real artifacts, and exercises registry validation without publishing packages,
creating a GitHub release, generating attestations, or updating downstream
packaging.