Skill v1.0.0
currentLLM-judged scan90/100version: "1.0.0" name: release description: "Prepare and ship a c11 release end-to-end: choose the next version, curate user-facing changelog entries, bump versions, open and monitor a release PR, merge, tag, and verify published artifacts. Use when asked to cut, prepare, publish, or tag a new release."
Release
Run this workflow to prepare and publish a c11 release.
Pre-flight
Surface these four facts in one batch before touching anything else:
- Branch state.
git branch --show-current+git status -s. If HEAD
isn't on main, surface it — the operator may not realize. Wrong-branch is easy to miss and load-bearing for every step downstream.
- Dirty tree disposition. Enumerate tracked diffs. For each, surface
what it does and ask: commit on the release branch, stash, or discard? Untracked files are usually fine; tracked code needs an explicit call.
- In-flight PRs.
gh pr list --state open --json number,title,headRefName.
Each open PR is an explicit include-or-defer decision.
- In-flight sub-agents (c11 only).
c11 tree --no-layout; read each
panel's role / task / status metadata. If another agent has unfinished work that belongs in the release, surface it now — not after the release branch is cut.
If the operator says "skip pre-flight," skip. Otherwise run all four every time.
Workflow
- Determine the version:
- Read
MARKETING_VERSIONfromGhosttyTabs.xcodeproj/project.pbxproj. - Default to a minor bump unless the user explicitly requests patch/major/specific version.
- Create a release branch:
git checkout -b release/vX.Y.Z
- Gather user-facing changes and contributors since the last versioned release tag:
git describe --tags --abbrev=0 --match 'v*'(artifact tags such asnightlyandxcframework-*are not releases)git log --oneline <last-tag>..HEAD --no-merges- Keep only end-user visible changes (features, bug fixes, UX/perf behavior).
- Collect contributors: For each PR, get the author with
gh pr view <N> --repo Stage-11-Agentics/c11 --json author --jq '.author.login'. Also check linked issue reporters withgh issue view <N> --json author --jq '.author.login'. - Build a deduplicated list of all contributor
@handles.
- Update changelogs:
- Update
CHANGELOG.md. - The
## [X.Y.Z] - YYYY-MM-DDsection is the release body;release.ymlandrelease-local.shrefuse a tag without it. - Do not edit a separate docs changelog file;
web/app/[locale]/docs/changelog/page.tsxrenders fromCHANGELOG.md. - Use categories
Added,Changed,Fixed,Removed. - Credit contributors inline (see Contributor Credits below).
- If no user-facing changes exist, confirm with the user before continuing.
- Bump app version metadata:
- Prefer
./scripts/bump-version.sh: ./scripts/bump-version.sh(minor)./scripts/bump-version.sh patch|major|X.Y.Z- Ensure both
MARKETING_VERSIONandCURRENT_PROJECT_VERSIONare updated.
Security threat-model recheck
Before the version bump lands, look at whether this release moved any security-sensitive surface. The canonical posture lives in docs/security-threat-model.md; the diff signals below tell you when a re-read is warranted. Run this grep against the release range and read the threat-model doc end-to-end if any signal fires:
git diff "$(git describe --tags --abbrev=0 --match 'v*')..HEAD" -- \Resources/Info.plist \c11.entitlements \Resources/c11.sdef \Sources/SocketControlSettings.swift \'Sources/SocketControl*' \Sources/AppDelegate.swift \Sources/Panels/BrowserPanel.swift \Sources/Panels/BrowserPanelView.swift \Sources/BrowserWindowPortal.swift \Sources/Panels/MarkdownWebRenderer.swift \Sources/UntrustedRepositoryGit.swift \Sources/MarkdownAssetPolicy.swift \Sources/MarkdownCorpusIndex.swift \Sources/SocketHandlers/MarkdownFeedbackHandlers.swift \Resources/markdown-viewer/ \Sources/Events/EventLog.swift
The URL handler around Sources/AppDelegate.swift:2301 (application(_:open:)) and any new WKWebViewConfiguration / WKContentController configuration are the highest-attention sub-targets — they are the chief untrusted-input vectors into the app. If a signal fires, update docs/security-threat-model.md to match the new posture and surface the change in the release notes so reviewers can see the security posture moved. Benign diffs (NSUsageDescription string tweaks, version bumps that touch the plist incidentally) do not require an update — acknowledge the diff and continue.
This is a checklist trigger, not a CI gate.
- Commit and push branch:
- Stage release files (changelog + version updates).
- Commit with
Bump version to X.Y.Z. git push -u origin release/vX.Y.Z.
6.5. Build the tagged staging artifact:
./scripts/reloads.sh --tag rel-vX.Y.Zproducesc11 STAGING rel-vX.Y.Z.app
(com.stage11.c11.staging), Release configuration, runs side-by-side with the operator's prod c11.
- Before handing off, screenshot the staging window and inspect every surface
the changelog touches (sheets, titlebar, sidebar, new or redesigned modals). Release-only layout regressions have shipped past Debug builds before.
- Hand off to the operator for a smoke pass against the changelog's
user-facing bullets. The smoke list should mirror what goes in the PR's test plan.
6.6. When staging surfaces a bug:
- Fix on the release branch. Commit. Push.
- Then choose explicitly:
- Rebuild staging (default when the fix touches anything timing- or
layout-sensitive — SwiftUI layout, animation, focus, paste, anything Release-mode could behave differently from Debug). The 0.47.0 New Workspace dialog regression was exactly this shape: dev/staging Debug masked a prod-only bug.
- Ship without re-test (acceptable only for trivial cosmetic / doc /
build-script changes AND only with explicit operator accept-the-risk).
- Don't drift past this decision. Default is rebuild; deviating is explicit.
- Create release PR:
gh pr create --title "Release vX.Y.Z" --body "..."- Include a concise changelog summary in the PR body.
- Watch CI and resolve failures:
gh pr checks --watch- Fix failing checks, push, and wait for green.
- Merge and sync
main:
gh pr merge --squash --delete-branchgit checkout main && git pull --ff-only- Confirm the pull actually moved `main`. A stale local tag (notably
nightly) makesgit fetch/git pullexit non-zero on a "would clobber existing tag" error, which aborts the ff-merge —mainsilently stays on the old commit while the fetch line still showsorigin/mainadvancing. Prune the offending tag (git tag -d nightly/git fetch --prune --prune-tags origin) and re-run, or fetch then ff explicitly:git fetch origin main && git merge --ff-only origin/main.
- Create and push tag:
- Gate the tag on a HEAD + version assertion — do not tag and sync in the same blind batch. Tagging stale
main(see the pull-abort trap above) pointsvX.Y.Zat the previous release's content and the release workflow builds the wrong DMG. Verify first:
``bash test "$(git rev-parse HEAD)" = "<merge-commit-sha>" || echo "STOP: main not at merge commit" grep -m1 MARKETING_VERSION GhosttyTabs.xcodeproj/project.pbxproj # must read X.Y.Z `` Only tag once both match the release.
git tag -a vX.Y.Z -m "Release vX.Y.Z"(annotated; lightweightgit tag vX.Y.Zis rejected with "no tag message?" by local git config)git push origin vX.Y.Z- If you tagged the wrong commit and the release run already started:
gh run cancel <id>(release builds take ~11 min, so a quick catch publishes nothing), delete the tag both places (git push origin :refs/tags/vX.Y.Z && git tag -d vX.Y.Z), fixmain, re-verify the gate, then re-tag and push.
- Verify release workflow and assets:
gh run watch --repo Stage-11-Agentics/c11- Confirm release exists in GitHub Releases and includes
c11-macos.dmg.
- Lift a skill-sync hold:
- If
CLAUDE.mdcarries a "Hold until c11 1.0 is installed" line under the skill-sync hard rule, wait until the maintainer has installed this release, then runscripts/sync-installed-skills.shand check one live copy (~/.claude/skills/c11/SKILL.mdmatchesskills/c11/SKILL.md). - Delete the hold line from
CLAUDE.mdand the matching "(until 1.0 is installed, follow the sync hold in the repo's CLAUDE.md)" clause fromskills/c11/SKILL.md(Editing this skill) in one PR; after it merges, syncc11again.
Changelog Rules
- Include only user-visible changes.
- Exclude internal-only changes (CI, tests, docs-only edits, refactors without behavior changes).
- Write concise user-facing bullets in present tense.
Contributor Credits
Credit the people who made each release happen:
- Per-entry: Append
— thanks @user!for code contributions, including c11 maintainers when they made the change. Use— thanks @user for the report!for bug reporters (when different from PR author). When a release imports an upstream commit, preserve its original authorship and credit that contributor; do not credit manaflow-ai's core team by default. - Summary: Add a
### Thanks to N contributors!section at the bottom of each release with an alphabetical list of linked handles for people who contributed to that release, including c11 maintainers and authors of imported upstream commits. - GitHub Release body: The release workflow automatically uses the changelog section, including its "Thanks to N contributors!" section with linked handles.
Version bumping
Prefer ./scripts/bump-version.sh:
./scripts/bump-version.sh # bump minor (0.15.0 → 0.16.0)./scripts/bump-version.sh patch # bump patch (0.15.0 → 0.15.1)./scripts/bump-version.sh major # bump major (0.15.0 → 1.0.0)./scripts/bump-version.sh 1.0.0 # set specific version
Updates both MARKETING_VERSION and CURRENT_PROJECT_VERSION (build number). The build number is auto-incremented and is required for Sparkle auto-update to work.
Default policy: bump the minor version unless the user explicitly asks for patch or major.
Manual release (fallback)
If not using the /release command:
git tag -a vX.Y.Z -m "Release vX.Y.Z"git push origin vX.Y.Zgh run watch --repo Stage-11-Agentics/c11
Use the annotated form (-a -m). A lightweight git tag vX.Y.Z is rejected with "no tag message?" because of local git config (likely tag.gpgSign or equivalent forcing all tags to be annotated).
Local release (Actions unavailable)
When release.yml cannot run (runner billing, outage), scripts/release-local.sh vX.Y.Z performs the same job: the Release build runs on Atlas through scripts/remote-build.sh, and the rest (daemon assets, Sparkle keys, codesign, notarize, staple, DMG, appcast, gh release) runs on this Mac. Walkthrough: .claude/commands/release-local.md.
- Tag first (step 10). Cancel the
release.ymlrun the tag push starts; the script refuses to publish while one is active. - Run
--dry-runfirst. It stops before notarization, rehearses the DMG and appcast with a throwaway Sparkle key, and publishes nothing. - A real run needs the
c11-notarynotarytool keychain profile. It also needs an Atlas build whoseDTXcodematches the script'sRELEASE_DTXCODEpin. It shows one keychain dialog the first time it reads thec11muxSparkle key, so someone has to be at the Mac. - The guards match CI's: existing release assets are never overwritten (
scripts/release_asset_guard.js). The release stays a draft until every asset is verified, so thelatestslot always carriesappcast.xml.
Reference
- Release asset:
c11-macos.dmg, attached to the tag - Download URL:
https://github.com/Stage-11-Agentics/c11/releases/latest/download/c11-macos.dmg - Changelog file:
CHANGELOG.md(the docs changelog page atweb/app/[locale]/docs/changelog/page.tsxrenders from it — do not maintain separately) - Required GitHub secrets:
APPLE_CERTIFICATE_BASE64,APPLE_CERTIFICATE_PASSWORD,APPLE_SIGNING_IDENTITY,APPLE_ID,APPLE_APP_SPECIFIC_PASSWORD,APPLE_TEAM_ID