* build: update dependencies Update the AI SDK providers, Vue, Reka UI, Valibot, Zod, es-toolkit, CodeMirror, Storybook, Playwright, Hono and other dependencies to their current releases, consistently across workspaces. The Tauri plugin packages must match their Rust crates, and the new plugin crates require Tauri 2.12, so Cargo.lock, @tauri-apps/api and the Tauri CLI move to 2.12 as well. * build(harness): update the AI SDK harness packages @ai-sdk/harness 1.0.74 pinned ai 7.0.67, so the workspace carried a second copy of ai next to the root one; 1.0.138 depends on the same ai release. The Pi adapter no longer takes a model: HarnessAgent does. The settings were spread from untyped records, so the compiler could not reject the stale key and the chosen model would have been dropped; they are plain literals now. PiAuthOptions is now PiAuthenticationMode, and auth accepts an environment record. Pass the gateway key that way instead of writing it into the process-wide environment while a session is created. Derive the thinking level from the adapter's settings, which adds 'max'. * build: hold vue-tsc at 3.3.11 vue-tsc 3.3.12 no longer sees a v-slot binding inside a component that also has an event listener, so check:vue reports "Cannot find name 'control'" in MCPConnectionEditor and ProfileEditor. 3.3.11 checks them cleanly. * fix(ai): keep retryability for provider errors reported mid-stream From ai 7.0.80 a provider error after the response stream starts is a StreamProviderError rather than an APICallError, so classifyAIChatError lost its isRetryable. * feat(desktop): accept updates only when signed for their version Tauri CLI 2.12 records the app version in each updater signature, and updater 2.13 checks it against the version latest.json announces. With requireSignedVersion it also rejects signatures that carry no version, so a tampered manifest cannot pair a newer version number with an older, still validly signed bundle. Release assembly now fails when a signature does not name the version being released, instead of shipping one that installed apps would reject. * docs: note the dependency update's security fixes in the changelog * feat(ai): recommend the latest models The provider packages now know Claude Sonnet 5.5 and Opus 5.5 and the GPT-6 series. Make Sonnet 5.5 and GPT-6.1 Sol the defaults, list Opus 5.5, Fable 5.1, GPT-6 Astra and GPT-6 Luna, and replace the two free OpenRouter models that OpenRouter no longer serves. * build: align the fig package's valibot with the workspace
6 KiB
Release packages and native artifacts
src/workflow.ts owns npm release policy and reuses package-artifacts/package-quality mechanics. src/native/ owns desktop release orchestration. Cross-directory imports within this package use #release/*; sibling modules remain relative.
Canonical release workflow
.github/workflows/build.yml runs on a new stable tag, or through workflow_dispatch with an existing vX.Y.Z tag. A dispatch uses the selected workflow revision but builds the immutable application commit resolved from that tag. The source must be an ancestor of origin/master.
- Plan: resolve the source commit and generate the native matrix from
native/catalog.ts. - Frontend: build packages and the desktop frontend once; prepare and pack npm archives without rebuilding. Archive
dist, desktop icons, and generated menus together and record its SHA-256. - Native: five independent jobs check out that same source, verify and extract the shared inputs, then build through Node's Tauri CLI launcher. A generated config sets only
build.beforeBuildCommandtonull; the checked-in local build hook is unchanged. No native job uploads release assets. - Publish: require the complete matrix with identical source/workflow/run/attempt/frontend identity. Verify file inventories, hashes, every updater signature and the release version it records (the desktop updater sets
requireSignedVersion), and exact source changelog notes. Generate the updater JSON, source/workflow manifest, and checksums; attest and verify the complete output set. Verify npm consumers and publish the original tarballs with npm provenance. Replace every expected draft asset, then download and verify all uploaded bytes.
Workflow tooling is checked out separately in .pipeline and installed from its own frozen lockfile where it runs. Application dependency installation and builds remain owned by the tagged checkout; rebuilding an older tag must not accidentally execute its older release orchestration. Dependency installation is not frontend/package compilation.
The workflow leaves the GitHub Release draft. After successful verification, publish it with the exact tagged changelog body and publish any accompanying security advisory separately. Never move a release tag to repair CI.
Artifact policy and provenance
native/catalog.ts is OpenPencil's required asset/naming policy, not a replacement for Tauri artifact discovery. Collection consumes tauri-action's artifactPaths output and refuses missing, duplicate, unexpected, empty, or escaping files. The macOS .app directory is ignored in favor of its required signed archive. Stable architecture-qualified macOS archive names are preserved.
GitHub's default provenance identifies the workflow execution revision, which can differ from the tagged application source in a manual rebuild. The independently attested release-manifest.json records both commits, the workflow run/attempt, shared frontend digest, target file digests, and npm tarball digests. Do not describe the default workflow provenance alone as proof of the application's checked-out source. npm also emits its own provenance from the same workflow execution; the signed manifest binds its exact tarballs to the application source.
Verify downloaded release files with:
gh attestation verify release-manifest.json --repo open-pencil/open-pencil \
--signer-workflow open-pencil/open-pencil/.github/workflows/build.yml \
--deny-self-hosted-runners
sha256sum --check SHA256SUMS
Each release asset, including SHA256SUMS, also has its own attestation. For a pinned audit, pass the independently obtained workflow commit to --signer-digest; compare the attested manifest's source commit with the immutable tag. Do not treat an unverified manifest as trusted configuration.
Homebrew distribution
The macOS app is distributed through the official openpencil cask: brew install --cask openpencil. This installs the desktop app, not the separately published npm CLI.
Homebrew's BrewTestBot automatically proposes version bumps for this cask (its tooling currently reports a roughly three-hour cadence). Homebrew owns review and merge timing; publishing our GitHub release does not immediately update the cask. Do not add parallel bump-PR automation or push to the archived open-pencil/homebrew-tap repository.
After each release:
- Check the official cask version and search
Homebrew/homebrew-caskfor an existingopenpencilbump PR. - Check that both architecture hashes match the attested release manifest. Follow the bot's PR through upstream review; do not report the cask as updated until it merges.
- If an update is delayed or fails, investigate the upstream bot/PR and follow Homebrew's current contribution policy rather than bypassing autobump restrictions. Direct GitHub downloads and the app updater remain available in the meantime.
The old HOMEBREW_TAP_TOKEN workflow secret is no longer used and can be removed after the obsolete workflow is retired. Revoking the underlying token is a separate credential-owner action if it is shared elsewhere.
Failure and recovery
- There are explicit job/build/startup/command deadlines. Native builds do not silently retry or upload partial release outputs.
- Missing or mixed matrix identities stop publication. Rerun all jobs, not only failed jobs, to obtain a single new run-attempt identity.
- Existing published GitHub releases, moved tags, unexpected draft assets, or already-published npm versions stop preflight. Already-published npm versions require an explicit provenance/recovery review; they are never silently mixed with this run.
- npm publication and GitHub multi-asset uploads are not atomic. A mid-publication failure requires review; the draft is not automatically published or deleted. A failed upload can leave a partial draft, not a successful canonical release.
- Caches improve repeat installs/builds but do not establish provenance. Their scope and writer limits are documented in
.github/actions/setup-bun/README.md.