From packmind-proprietary
Orchestrate a full Packmind proprietary release: verify Main CI/CD Pipeline is green on both OSS and proprietary main, drive the release on the OSS sibling repo (version bumps, CHANGELOG, tag, push), wait for the oss-sync workflow to land the release commit on the proprietary fork, then tag and push `release/{{version}}` on the proprietary repo. Invoke from the proprietary repo.
How this skill is triggered — by the user, by Claude, or both
Slash command
/packmind-proprietary:release-proprietaryThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Create a full Packmind proprietary release with version `{{version}}`.
Create a full Packmind proprietary release with version {{version}}.
This skill orchestrates a cross-repository release that spans the OSS sibling (../packmind, cloned next to the proprietary repo) and the proprietary repo itself (the current working directory). All real release content (version bumps, CHANGELOG) lives on OSS; the proprietary side receives the OSS commit through the oss-sync workflow and gets its own release/{{version}} tag pointing at a different SHA than the OSS tag — see below.
Invocation requirement: run this skill from the root of the proprietary repo, with the OSS sibling checked out at ../packmind. All commands below assume that layout.
Dual-SHA model — important:
release/{{version}} tag points at the release commit itself (subject chore: release {{version}}). That commit's tree contains OSS code, which is what OSS deployments need.main. The OSS release commit has no proprietary-only files in its tree, so tagging it on proprietary would break deployments (the build can't find @packmind/proprietary/* modules). The sync-merge commit's tree combines OSS-at-release with the proprietary-only files, which is what proprietary deployments need.The wait/tag scripts handle this for you — Phase 2 emits the proprietary merge SHA, and Phase 3 tags that SHA.
Repository layout assumed by every command in this file:
../packmind (remote PackmindHub/packmind). — the current working directory (remote PackmindHub/packmind-proprietary)Scripts live next to this file under ./scripts/. From the proprietary repo root, paths are .claude/skills/release-proprietary/scripts/<name>.
Before doing anything, stop and ask the user:
Has the
feature-flags-auditskill been run on the proprietary repo for this release? (yes / no)
If the answer is anything other than an explicit yes, abort and tell the user to run feature-flags-audit on the proprietary repo first.
If the audit surfaced any loose / stale flags that should have been removed, instruct the user to:
../packmind. Most code flows from OSS → proprietary via oss-sync, so flags should generally be cleaned up on the OSS side.oss-sync PR./.claude/skills/release-proprietary/scripts/check-oss-sync-pr.sh PackmindHub/packmind-proprietary
When the auto-sync hits a merge conflict it opens a PR on branch oss-sync instead of fast-forwarding. If such a PR is open, Phase 2 polling cannot succeed. Abort and ask the user to resolve and merge the PR first.
Run the check script for both repositories:
./.claude/skills/release-proprietary/scripts/check-ci.sh PackmindHub/packmind
./.claude/skills/release-proprietary/scripts/check-ci.sh PackmindHub/packmind-proprietary
Exit codes:
0 — green, proceed.1 — the run failed (or no run found, or auth missing). Abort, surface the URL.2 — the run is still in progress / queued. Not a failure: ask the user whether to wait and retry, or abort.git status --porcelain # must be empty
git fetch origin main
git merge-base --is-ancestor HEAD origin/main \
|| (echo "local main has diverged from origin/main — reconcile before releasing" && exit 1)
If the working tree is dirty, or local HEAD is not an ancestor of origin/main, abort and ask the user to reconcile.
../packmind)All commands in this phase target the OSS repo via git -C or cd.
git -C ../packmind status --porcelain # must be empty
git -C ../packmind checkout main
git -C ../packmind pull --ff-only origin main
If the working tree is dirty or the pull is not fast-forward, abort and ask the user to reconcile.
node ./.claude/skills/release-proprietary/scripts/bump-versions.mjs {{version}} ../packmind
( cd ../packmind && npm install )
npm install regenerates package-lock.json with the new version.
Resolve today's date in ISO 8601 (YYYY-MM-DD) — call it {{today}}.
node ./.claude/skills/release-proprietary/scripts/changelog-release.mjs {{version}} {{today}} ../packmind
./.claude/skills/release-proprietary/scripts/commit-release.sh ../packmind {{version}}
This stages package.json, apps/api/docker-package.json, package-lock.json, and CHANGELOG.MD, commits with the exact subject chore: release {{version}} (Phase 2 polls for this fixed string), and pushes main. The script never uses --no-verify.
./.claude/skills/release-proprietary/scripts/tag-release.sh ../packmind {{version}}
Creates release/{{version}} at HEAD (the release commit just pushed) and pushes the tag. If the tag already exists, the script verifies it points at HEAD before re-pushing.
node ./.claude/skills/release-proprietary/scripts/changelog-next.mjs {{version}} ../packmind
./.claude/skills/release-proprietary/scripts/commit-next-cycle.sh ../packmind
The sync-from-oss-repository.yml workflow on the proprietary repo merges OSS commits into proprietary main automatically (usually under a minute). It will land BOTH the release commit AND the subsequent "prepare next development cycle" commit; each goes through its own sync-merge commit on proprietary main.
PROP_TAG_SHA=$(./.claude/skills/release-proprietary/scripts/wait-for-oss-sync.sh \
. {{version}})
The script writes the proprietary sync-merge SHA to stdout (captured into PROP_TAG_SHA) and progress to stderr. Internally it:
origin/main every 5 seconds for the OSS release commit (subject exactly chore: release {{version}}), with a 10-minute timeout.{{version}}, not {{next}}-next.This is the SHA you tag on proprietary. It is NOT the OSS release SHA — that one's tree contains only OSS code and would break proprietary deployments. See the "Dual-SHA model" note at the top.
If it times out, abort and instruct the user to:
sync-from-oss-repository workflow on PackmindHub/packmind-proprietary.oss-sync PR appeared after Phase 0 ran.If the script reports OSS release commit … is on proprietary origin/main, but no merge commit has it as its direct upstream (2nd) parent, the auto-sync either fast-forwarded or batched release + next-cycle into one merge. The operator must resolve manually before continuing — there is no merge commit with the right tree to tag.
Once PROP_TAG_SHA is set, fast-forward the local proprietary checkout (purely to keep the working tree in sync — we do NOT rely on HEAD for the tag):
git checkout main
git pull --ff-only origin main
The sync just pushed new commits to proprietary main; the Phase 0 CI gate is now stale. Re-run it (allowing exit 2 = still running) and either wait or abort:
./.claude/skills/release-proprietary/scripts/check-ci.sh PackmindHub/packmind-proprietary
./.claude/skills/release-proprietary/scripts/tag-release.sh \
. {{version}} "${PROP_TAG_SHA}"
Passing the SHA explicitly is essential — tagging HEAD would tag a later sync-merge or the next-cycle commit. The script re-verifies that the target is either a direct release commit OR a merge commit whose 2nd parent is the release commit, and refuses to tag otherwise. It will not allow retagging an existing tag at a different commit.
Report to the user:
https://github.com/PackmindHub/packmind/releases/tag/release/{{version}} (or the compare link)https://github.com/PackmindHub/packmind-proprietary/releases/tag/release/{{version}}release/* tags will trigger.--no-verify on any commit. If a hook fails, fix the root cause and create a new commit.chore: release {{version}} — Phase 2 matches subjects by exact equality and tag-release.sh verifies subject equality before tagging. Any prefix/suffix (e.g. gitmoji) will break the flow.YYYY-MM-DD).If the flow fails at a known phase, recover as follows:
tag-release.sh <oss-dir> {{version}} from Phase 1.5. The script tags HEAD only if HEAD's subject is chore: release {{version}}.changelog-next.mjs + commit-next-cycle.sh. Then proceed to Phase 2.PROP_TAG_SHA. Recover it by re-running wait-for-oss-sync.sh (idempotent — it finds and emits the same merge SHA as before) or manually with:
OSS_SHA=$(git log origin/main \
--format='%H%x09%s' -500 | awk -F '\t' -v subj="chore: release {{version}}" '$2 == subj { print $1; exit }')
git log origin/main --merges \
--format='%H %P' -500 | awk -v oss="${OSS_SHA}" '$3 == oss { print $1; exit }'
npx claudepluginhub packmindhub/packmind-marketplace --plugin packmind-proprietaryCreates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.