MarketingClaw Release Maintainer
Use this skill for release and publish-time workflow. Load $release-private if it exists before resolving Peter-owned credential locators or private host topology. Keep ordinary development changes and GHSA-specific advisory work outside this skill.
Respect release guardrails
- Do not change version numbers without explicit operator approval.
- Versions use
YYYY.M.PATCH, wherePATCHis the sequential release-train number within the month, not the calendar day. - Choose a new beta train from stable and beta releases only. Alpha-only tags do not consume or advance the beta/stable patch number. Continue the highest existing unpublished/published beta train with the next
beta.Nwhen appropriate; otherwise increment the highest stable/beta patch by one and start atbeta.1. - Example: after stable
2026.6.5, the next new beta train is2026.6.6-beta.1, even if automated alpha-only tags such as2026.6.10-alpha.1exist. - Obtain explicit operator approval before the first irreversible publish action. Instructions to cut, ship, publish, or get a named release out carry through that release's validated publish and verification steps; do not ask again at final dispatch. Reconfirm only if the target version, tag, channel, publish scope, or a material risk changes.
- This skill should be sufficient to drive the normal release flow end-to-end.
- Use the private maintainer release docs for credentials, recovery steps, and mac signing/notary specifics, and use
docs/reference/RELEASING.mdfor public policy. - Core
marketingclawpublish is manualworkflow_dispatch; creating or pushing a tag does not publish by itself. - Do not edit the root
README.mdas release prep, release closeout, or a substitute for release notes. Package-root README validation is a hard packaging gate, but a release only changes README content when an actual user-facing documentation contract changed. - Normal release work happens on a branch cut from
main, not directly onmain. Userelease/YYYY.M.PATCHfor the branch name. - If the operator asks for a release without saying stable/full, default to beta only. Continue from beta to stable only when the operator explicitly asks for the full release or an automated beta-and-stable train.
- Before release branching, pull latest
mainand confirm currentmainCI is green. Then branch from that commit so regular development can continue onmainwhile release validation runs. - Before release branching, commit any dirty files in coherent groups, push,
pull/rebase, then generate
CHANGELOG.mdonmainfrom merged PRs and all direct commits since the last reachable release tag. Commit/push/pull that changelog rewrite immediately before creating the release branch. - During release planning, inspect both
src/plugins/compat/registry.tsandsrc/commands/doctor/shared/deprecation-compat.tsbefore branching and again before final publish. For every deprecated or removal-pending compatibility record whoseremoveAfterdate is on or before the release date, either remove the compatibility path where safe and validate the affected tests, or write down why removal is blocked and get explicit maintainer approval before shipping the expired compatibility path. - When removing deprecated runtime/config compatibility, preserve any doctor
migration, repair, or hint that is still needed by supported upgrade paths.
Doctor-side compatibility should stay tracked in
src/commands/doctor/shared/deprecation-compat.tsuntil maintainers confirm the repair is no longer needed. - Revalidate compatibility replacement text during release planning. The recommended replacement can shift as plugin ownership, externalization, and config footprint move, so do not blindly copy stale replacement annotations into release notes.
- Do not delete or rewrite beta tags after their matching npm package has been
published. If a pushed beta tag fails before npm publish, the version is not
consumed: keep the same
-beta.N, delete/recreate or force-move the git tag and prerelease to the fixed commit, and rerun preflight. Do not increment to the next beta number until the matching npm package has actually published. If a published beta needs a fix, commit the fix on the release branch and increment to the next-beta.N. - For a beta release train, keep Full Release Validation as a pre-publish gate
unless the operator explicitly waives it. Run the fast local preflight, npm
preflight, full release validation, and performance in parallel where safe.
If anything fails before npm publish, fix it on the release branch,
forward-port the fix to
main, move the unpublished beta tag/prerelease to the fixed commit, and rerun the affected pre-publish gates. If anything fails after npm publish, fix it, forward-port tomain, increment beta number, and repeat. After each beta publish, run the published-package roster focused on install/update/Docker/Parallels/NPM Telegram. For later beta attempts, rerun only lanes whose evidence changed unless the fix touches broad release, install/update, plugin, Docker, Parallels, or live QA behavior. After each beta is live, scan currentmainonce for critical fixes that landed after the release branch cut and backport only important low-risk fixes. Operators may authorize up to 4 autonomous beta attempts; after 4 failed beta attempts, stop and report. - As soon as the release candidate SHA exists, dispatch
MarketingClaw Performancewithtarget_ref=<release-sha>in parallel with the other release work. Do not wait for full release validation to start the performance signal. - Before publish/closeout, compare available product performance metrics with earlier releases: Kova agent-turn/resource metrics, gateway startup ready/listen/RSS/CPU metrics, and CLI startup metrics from release evidence or clawgrit reports. Report regressions explicitly. A major regression is a release blocker unless the operator waives it or the data clearly proves infrastructure noise.
- Heal CI before tagging or publishing. The exact candidate SHA must have green
Full Release Validation, including the root Dockerfile/install-smoke path. Treat a red Docker, package, or release workflow lane as a release-branch defect until the smallest correct fix is landed and proven; do not waive it because npm preflight or another sibling lane passed. - Keep the canonical
scripts/prrunner authoritative for prepare and merge artifacts. A release-gate policy change may use focused candidate tests and exact-SHA hosted CI for proof, but never routeprepare-*ormerge-*through PR-controlled scripts or synthesize prepare artifacts to bootstrap the change. If the current canonical gate cannot validate the new policy, stop for explicit maintainer direction rather than weakening that boundary. - In maintainer Testbox mode, use `MARKETINGCLAW_TESTBOX=1 scripts/pr prepare-run
only after the exact PR head has passedCIand every scheduled hosted gate. For a workflow change, that meansBlacksmith Testbox, Blacksmith ARM Testbox, Blacksmith Build Artifacts Testbox, and Workflow Sanity; only gates GitHub actually scheduled for that exact head are required. This preserves the canonical prepare artifacts while avoiding a redundant broad local suite. A literal CHANGELOG.md-only head gets a clean diff check instead because those workflows intentionally do not dispatch. Documentation and README changes still require CI. If merge-runrequires a mainline sync, run MARKETINGCLAW_TESTBOX=1 scripts/pr prepare-sync-head , wait for those hosted gates on the newly pushed SHA, then run prepare-run` again.
- If an exact PR-head CI run has no active jobs because Blacksmith capacity is
stalled, a maintainer may dispatch the explicit GitHub-hosted fallback from
the PR head branch:
gh workflow run ci.yml --repo promisingcoder/marketingclaw --ref <pr-head-branch> -f target_ref=<full-pr-sha> -f include_android=true -f release_gate=true. Use it only for an observed provider queue stall, never for failed CI or as a routine shortcut. The run must be namedCI release gate <full-pr-sha>and pass on that exact SHA; the native hosted-gate verifier rejects generic manual CI runs. IfBlacksmith Build Artifacts Testboxis the only remaining required gate and it is still queued without a runner, the same completed fallback CI may cover it because itsbuild-artifactsjob builds, packages, and smoke tests those artifacts. The verifier records that coverage. Never use this coverage when the artifact workflow has started, failed, been cancelled, or been skipped. Then rerunMARKETINGCLAW_TESTBOX=1 scripts/pr prepare-run <PR>. - Generate the changelog before every beta, beta rerun, stable release, or
stable rerun, before version/tag preparation. Use
$marketingclaw-changelog-updatefor the rewrite. Do not continue release prep if the targetCHANGELOG.mdsection does not have### Highlights,### Changes, and### Fixes, grouped by user-facing surface while preserving every relevant PR/issue ref and every humanThanks @...attribution in the grouped bullet. - Do not create beta-specific
CHANGELOG.mdheadings. Beta releases use the stable base version section, for examplev2026.4.20-beta.1uses## 2026.4.20release notes. - When any beta or stable release is live, make a best-effort Discord announcement using the configured secret workflow; do not block or roll back the release if the announcement fails.
- When asked to announce on X, use
~/Projects/bird/birdand follow the release tweet style below.
Keep release channel naming aligned
stable: tagged releases only, published to npmbetaby default; operators may target npmlatestexplicitly or promote laterbeta: prerelease tags likevYYYY.M.PATCH-beta.N, with npm dist-tagbeta- Prefer
-beta.N; do not mint new-1or-2beta suffixes dev: moving head onmain- When using a beta Git tag, publish npm with the matching beta version suffix so the plain version is not consumed or blocked
Close stable releases on main
Stable publication is not complete until main carries the actual shipped release state.
- Start from fresh latest
main. Auditrelease/YYYY.M.PATCHagainst it and forward-port real fixes that are absent frommain. Do not blindly merge release-only compatibility, test, or validation adapters into newermain. - Set
mainto the shipped stable version, not a speculative next train. Runpnpm release:prepafter the root version change, thenpnpm deps:shrinkwrap:generate. - Make
CHANGELOG.md's## YYYY.M.PATCHsection onmainexactly match the tagged release branch. Include the stableappcast.xmlupdate when the mac release published one. - Do not add
YYYY.M.PATCH+1, a beta version, or an empty future changelog section tomainuntil the operator explicitly starts that release train. - Run
pnpm release:generated:check,pnpm deps:shrinkwrap:check, andMARKETINGCLAW_TESTBOX=1 pnpm check:changed. Push, then verifyorigin/maincontains the shipped version and changelog before calling the stable release done. - Keep repository variables
RELEASE_ROLLBACK_DRILL_IDandRELEASE_ROLLBACK_DRILL_DATEcurrent after each private rollback drill.marketingclaw-stable-main-closeout.ymlstarts from themainpush carrying the shipped version, changelog, and appcast after stable publication, then binds immutable evidence to the published tag. Do not declare stable complete until it writes the immutable closeout manifest to the GitHub release. The drill must be within 90 days; manual dispatch is only for repair/replay, and private rollback commands remain in the maintainer-only runbook.
Handle versions and release files consistently
- Version locations include:
package.jsonapps/android/app/build.gradle.ktsapps/ios/Sources/Info.plistapps/ios/Tests/Info.plistapps/macos/Sources/MarketingClaw/Resources/Info.plistdocs/install/updating.md- Peekaboo Xcode project and plist version fields
- Before creating a release tag, make every version location above match the version encoded by that tag.
- For fallback correction tags like
vYYYY.M.PATCH-N, the repo version locations still stay atYYYY.M.PATCH. - “Bump version everywhere” means all version locations above except
appcast.xml. - Release signing and notary credentials live outside the repo in the private maintainer docs.
- Every stable MarketingClaw release ships the npm package, macOS app, and signed Windows Hub installers together. Beta releases normally ship npm/package artifacts first and skip native app build/sign/notarize/promote unless the operator requests native beta validation.
- Do not let the slower macOS signing/notary path block npm publication once the npm preflight has passed. Keep mac validation/publish running in parallel, publish npm from the successful npm preflight, then start published npm install/update, Docker, and Parallels verification while mac artifacts continue.
- After a beta is published, overlap remote/manual release rosters where useful, but avoid piling local Docker, Parallels, and QA-Lab work onto the same host when it would create system-load noise. Use selective reruns after failures or fixes, but keep proof that Docker, Parallels, and QA-Lab each passed at least once before stable/latest promotion.
- Mac packaging may be built from a slight release-branch variation of the
tagged commit when the delta is mac packaging, signing, workflow, or
validation-only release machinery. If mac packaging needs release-branch-only
fixes after the stable npm package or GitHub tag is already published, do not
create a
vYYYY.M.PATCH-Ncorrection tag just to change the workflow source. Dispatch the release-ops mac workflows for the originaltag=vYYYY.M.PATCHwithsource_ref=release/YYYY.M.PATCHandpublic_release_branch=release/YYYY.M.PATCH; provenance checks must prove the source SHA descends from the tag and validation/preflight use the same source. ReservevYYYY.M.PATCH-Ncorrection tags for emergency hotfixes that must publish a new npm package/release identity, not for ordinary mac-only packaging recovery. - The production Sparkle feed lives at
https://raw.githubusercontent.com/promisingcoder/marketingclaw/main/appcast.xml, and the canonical published file isappcast.xmlonmainin themarketingclawrepo. - That shared production Sparkle feed is stable-only. Beta mac releases may
upload assets to the GitHub prerelease, but they must not replace the shared
appcast.xmlunless a separate beta feed exists. - For fallback correction tags like
vYYYY.M.PATCH-N, the repo version still stays atYYYY.M.PATCH, but the mac release must use a strictly higher numericAPP_BUILD/ Sparkle build than the original release so existing installs see it as newer. - Stable Windows Hub release closeout requires the signed
MarketingClawCompanion-Setup-x64.exe,MarketingClawCompanion-Setup-arm64.exe, andMarketingClawCompanion-SHA256SUMS.txtassets on the canonicalpromisingcoder/marketingclawGitHub Release. Pass the exact signedmarketingclaw/marketingclaw-windows-noderelease tag aswindows_node_tagtoMarketingClaw Release Publish, together with the candidate-approvedwindows_node_installer_digestsmap; it prevalidates the published source release and required installers against that map before any publish child, dispatches the publicWindows Node Releaseworkflow while the MarketingClaw release is still a draft, carries those pinned source asset digests unchanged, verifies the expected MarketingClaw Foundation Authenticode signer on Windows, re-downloads and checksum-verifies the promoted asset contract, and blocks publication until the canonical asset contract is present. Use directWindows Node Releasedispatch only for recovery, always with an exact tag, neverlatest, and the explicitexpected_installer_digestsJSON map from the approved source release. Recovery rejects unexpectedMarketingClawCompanion-*target asset names, then replaces the expected contract assets with the pinned source bytes. - Website Windows Hub download links should target exact canonical
promisingcoder/marketingclaw/releases/download/vYYYY.M.PATCH/...assets for the current stable release, orreleases/latest/download/...only after verifying the redirect resolves to that same tag, so the installable signed Windows artifact is visible from both the GitHub release page and marketingclaw.ai.
Build changelog-backed release notes
CHANGELOG.mdis release-owned. Normal PRs and directmainfixes should not edit it.- Before release branching or tagging, rewrite the target
CHANGELOG.mdsection from history, not existing notes. Use the last reachable stable or beta release tag as the base, then inspect every commit through the target release SHA. - Generate
$marketingclaw-changelog-update's full contribution manifest before the editorial rewrite. It is the required source for### Highlights,### Changes, and### Fixes; do not preserve old grouped prose without comparing it to the manifest's PRs, contributors, direct commits, and unlinked commits. - The changelog rewrite is not optional for beta reruns: any
beta.Nafter a rebase or backport must refresh the same stable-base## YYYY.M.PATCHsection before the new version/tag commit. - Include both merged PR commits and direct commits on
main. Direct commits matter: infer notes from their subject, body, touched files, linked issues, tests, and nearby code when no PR body exists. - Keep direct commits in the generated manifest and use them to shape grouped
user outcomes, but never dump them into
CHANGELOG.mdor GitHub release bodies. The public complete record is PR-first and exhaustive for PRs. - Prefer PR bodies, issue links, review proof, and commit bodies over commit subjects alone. If a commit fixed an issue directly, the commit body should name the user-visible behavior, affected surface, issue ref, and credited reporter/contributor when known.
- Treat missing context as a release-note audit gap: inspect the diff and linked issue, draft the best accurate entry, and note the uncertainty for maintainer review rather than inventing impact.
- Add missed user-facing changes, remove internal-only noise, dedupe overlapping PR/direct-commit entries, and sort each section from most to least interesting for users.
- Group related highlights, changes, and fixes by user-facing surface and
impact, but never lose traceability: each grouped bullet keeps every relevant
#issue,(#PR),Fixes #..., and every humanThanks @...handle. Multiple thanks in one bullet are expected when multiple contributor PRs are grouped. - Highlights earn their place only when they are a visible capability/workflow unlock, a material reliability or safety repair, a broad user-facing improvement, or a release-defining integration/compatibility change. Keep five to eight user-outcome bullets; omit tests, CI, refactors, docs, and implementation trivia unless their outcome materially affects users.
- Do not give
docs,test,refactor,ci,build,chore, orstylePRs/direct commits their own Highlights, Changes, or Fixes entry. They remain accounted for in the PR record or manifest, but are not product release content. Treat explicit internal title signals such asQA,lint, ortestingthe same way even when the PR has no conventional prefix. - Use the generated
### Complete contribution recordas PR-first accounting: every merged source PR appears once with author/co-author credit, including PRs identified only by an explicit active-commit#NNNreference after a cherry-pick or squash. Keep issues inline as#NNNin titles and grouped prose; do not create a linked-issues inventory or a direct-commit listing. When grouped prose names a PR, keep every contributor and linked-reporter credit from that PR's record on the same bullet. - Changelog entries should be user-facing, not internal release-process notes.
- GitHub release and prerelease bodies must use the full matching
CHANGELOG.mdversion section, not highlights or an excerpt. When creating or editing a release, extract from## YYYY.M.PATCHthrough the line before the next level-2 heading and use that complete block as the release notes. - GitHub limits release bodies to 125,000 characters. If a historical
### Release verificationtail would exceed that cap, omit the tail and keep the complete changelog section; do not truncate the contribution record. - Before publishing or closing a release, run
$marketingclaw-changelog-update'sverify-release-notes.mjswith every stable and beta release tag in the train. Do not publish or leave a page live when it is missing a source-history reference, eligible human credit, or the complete matching changelog body. - To update an existing GitHub Release body, resolve the numeric release id and
patch that resource with the notes file as the
bodyfield:gh api repos/promisingcoder/marketingclaw/releases/tags/vYYYY.M.PATCH --jq .id, thengh api -X PATCH repos/promisingcoder/marketingclaw/releases/<id> -F body=@/tmp/notes.md. Do not trustgh release edit --notes-fileor--inputJSON if verification disagrees; verify withgh api repos/promisingcoder/marketingclaw/releases/<id>because the tag lookup andgh release viewcan lag or show stale body text. - When preparing release notes, scan
src/plugins/compat/registry.tsandsrc/commands/doctor/shared/deprecation-compat.tsfor compatibility records withwarningStartsorremoveAfterwithin 7 days after the release date. Add anUpcoming deprecationsnote to the release notes when any exist, including the compatibility code, target date, replacement, and a link to the record'sdocsPathor/plugins/compatibilitywhen no more specific deprecation page exists. - When cutting a mac release with a beta GitHub prerelease:
- tag
vYYYY.M.PATCH-beta.Nfrom the release commit - create a prerelease titled
marketingclaw YYYY.M.PATCH-beta.N - use release notes from the stable base
CHANGELOG.mdversion section (## YYYY.M.PATCH), not a beta-specific heading - attach at least the zip and dSYM zip, plus dmg if available
- tag
- Keep the top version entries in
CHANGELOG.mdsorted by impact:### Changesfirst### Fixesdeduped with user-facing fixes first
Write release tweets
Use the MarketingClaw account's existing release-post style:
- Format:
MarketingClaw YYYY.M.PATCH 🦞or🦞 MarketingClaw YYYY.M.PATCH is live, blank line, then 3-4 emoji-led bullets, blank line, one short punchline, then the release link. - For beta: say
MarketingClaw YYYY.M.PATCH-beta.N 🦞orMarketingClaw YYYY.M.PATCH beta N is live; keep it clearly beta and avoid implying stable promotion. - Lead with user-visible capabilities, then important integrations, then reliability/security/install fixes. Compress "lots of fixes" into one readable bullet.
- Read the full changelog section before drafting. Do not lead with coverage, CI, validation, or internal release mechanics unless the release is explicitly about those. Peter prefers concrete user wins: features, integrations, workflow improvements, and practical reliability fixes.
- Do not feature QA parity, test coverage, release gates, or validation lanes in user-facing launch tweets. Keep them for release notes or maintainer proof unless the operator explicitly asks for validation-focused copy.
- Do not feature plugin-author or developer tooling such as SDK helpers, tool-plugin scaffolding, build/validate/init commands, or internal CLI plumbing in general user-facing launch tweets unless the operator explicitly asks for developer-focused copy.
- Tone: high-signal, slightly cheeky, confident, not corporate. One joke is enough. Avoid punching down, insulting users, or promising what was not verified.
- Peter likes dry, compact taglines when they feel earned. Good example:
Big release, tiny release notes... kidding.Keep the joke short and let the feature bullets carry the tweet; do not turn the punchline into a second paragraph or a forced bit. - Length: release tweets are always standard tweets under 280 characters, with room for one URL. Trim to 3-4 bullets and count the final text before posting.
- Links/media: include the GitHub release or changelog link at the end of the first release tweet.
- Thread follow-ups: if doing a thread, keep the first release tweet as the compact launch post, then publish one focused feature explainer per reply. Follow-up replies should not repeat "new in VERSION" or the version number when the thread context already makes it obvious.
- Peter's preferred thread workflow: first agree on the generic launch tweet,
then proceed through follow-up tweets one by one. When he says
next, provide or copy the next follow-up only; do not dump the full thread again unless asked. - Every follow-up tweet should include a docs URL for that specific feature.
Prefer a bare URL over
Docs: <url>unless the label is needed for clarity. Keep follow-ups concise: around 160-220 raw characters is usually the sweet spot; under 280 is the hard cap. If a URL makes a tweet fail, trim prose before dropping the URL. Prefer explaining diagnostics, trajectory/export, provider setup, model commands, or other setup-heavy features in follow-ups instead of overloading the first release tweet. - Hotfix/correction: be direct and accountable. State what slipped, what is fixed, and the new version. Keep jokes out of incident-style posts.
Examples to adapt:
MarketingClaw 2026.4.20-beta.1 🦞
🐳 Docker install/update smoke
🖥️ Parallels upgrade checks
🔧 Package verification tightened
Beta first. Stable after the gauntlet.
<release link>
MarketingClaw 2026.4.20 🦞
🚀 Faster install + update
🐳 Docker + Parallels verified
🍎 macOS signed + notarized
🔧 Channel/plugin fixes
Good boring release. Best kind.
<release link>
Packaging issue in 2026.4.20-beta.1.
2026.4.20-beta.2 fixes install/update verification. No tag rewrites; beta moves
forward.
Upgrade with the beta channel.
<release link>
Run publish-time validation
Before tagging or publishing, run:
pnpm release:fast-pretag-check
pnpm check:architecture
pnpm build
pnpm ui:build
pnpm qa:otel:smoke
pnpm release:check
pnpm test:install:smoke
- Treat
pnpm release:fast-pretag-checkas a hard packaging gate. Every publishable plugin must have a non-empty package-rootREADME.md, build its package-local runtime, and pass the npm and ClawHub release metadata checks before a tag or publish workflow can start. Do not defer README, entrypoint, or packed-artifact failures to postpublish verification. - Before tagging, require green CI for the exact release-candidate SHA, not an
earlier branch SHA. Heal every related red CI, release-check, packaging, or
root-Dockerfile lane on the release branch, forward-port the fix to
main, and rerun the affected exact-SHA gates. Never waive a red Docker lane because npm preflight passed. - Root Dockerfile proof is mandatory before every beta and stable tag. Run the
release
install-smokegroup or equivalent root Dockerfile build for the exact candidate SHA and require it to pass. The tag-triggered Docker Release workflow is post-tag publishing, not the first valid proof that the root Dockerfile can build. - Before tagging, diff publishable plugin package manifests against the last
reachable stable/beta release tag. For every newly publishable package
(
marketingclaw.release.publishToNpm: trueorpublishToClawHub: true) whose package name did not exist in the base tag, verify the target registry package already exists in npm/ClawHub or stop and help the owner mint/prepublish the package first. Do not hide or disable release surfaces just to unblock a train unless the owner explicitly decides the plugin should not ship in that release; first-package registry ownership is release prep, not product rollback. The mint/prepublish path must either be the real release publish path for the auto-bumped beta version, or a deliberately non-consuming registry-prep step that cannot occupy the next beta version/tag. Confirm registry owner, npm scope/package-creation permission, provenance path, and first-package publish plan before the full release publish continues. Useful npm probe:npm view <package-name> version dist-tags --json --prefer-online; a 404 for a package newly added to the release is a release-prep blocker, not something to discover from the publish job. - Use
pnpm qa:otel:smokewhen release validation needs telemetry coverage. It starts a local OTLP/HTTP trace receiver, runs QA-lab'sotel-trace-smoke, and checks span names plus content/identifier redaction without external Opik or Langfuse credentials.
For a non-root smoke path:
MARKETINGCLAW_INSTALL_SMOKE_SKIP_NONROOT=1 pnpm test:install:smoke
After npm publish, run:
node --import tsx scripts/marketingclaw-npm-postpublish-verify.ts <published-version>
- This verifies the published registry install path in a fresh temp prefix.
- For stable correction releases like
YYYY.M.PATCH-N, it also verifies the upgrade path fromYYYY.M.PATCHtoYYYY.M.PATCH-Nso a correction publish cannot silently leave existing global installs on the old base stable payload. - Treat install smoke as a pack-budget gate too.
pnpm test:install:smokenow fails the candidate update tarball when npm reports an oversizedunpackedSize, so release-time e2e cannot miss pack bloat that would risk low-memory install/startup failures. - Keep direct npm global coverage enabled in install smoke. It exercises plain
npm install -g <candidate>fresh installs and npm-driven update installs, because many users install with npm even when docs prefer pnpm. - Use
pnpm test:live:media videofor bounded video-provider smoke when video generation is in release scope. The default video smoke skipsfal, runs one text-to-video attempt per provider with a one-second lobster prompt, and caps each provider operation withMARKETINGCLAW_LIVE_VIDEO_GENERATION_TIMEOUT_MS(180000by default). - Run
pnpm test:live:media video --video-providers falonly when FAL-specific proof is required. Its queue latency can dominate release time. - Set
MARKETINGCLAW_LIVE_VIDEO_GENERATION_FULL_MODES=1only when intentionally validating the slower image-to-video and video-to-video transform lanes.
Check all relevant release builds
- Always validate the MarketingClaw npm release path before creating the tag.
- Use the configured secret workflow before live release validation so OpenAI and Anthropic credentials are available without printing secrets.
- Parallels validation and any local live model QA for this train must use both
OPENAI_API_KEYandANTHROPIC_API_KEY. If either cannot be injected, stop before starting those local long lanes and report the missing key. - Live credentialed channel QA is the GitHub Actions workflow
QA-Lab - All Lanes(.github/workflows/qa-live-telegram-convex.yml), not a local substitute. Dispatch it from Actions against the release tag and wait for it to pass before npm preflight/publish readiness. Use a SHA only when it satisfies the workflow's secret-bearing trust gate: main ancestor or open PR head. It runs the QA Lab mock parity gate plus live Matrix and live Telegram lanes using theqa-live-sharedenvironment; Telegram uses Convex CI credential leases. - Default release checks:
pnpm checkpnpm check:test-typespnpm check:architecturepnpm buildpnpm ui:buildpnpm release:checkMARKETINGCLAW_INSTALL_SMOKE_SKIP_NONROOT=1 pnpm test:install:smoke
- Full pre-npm beta test roster:
- default release checks above
- all Docker tests:
pnpm test:docker:all, plus standalone Docker live lanes not covered by the aggregate when operator says "all docker tests":pnpm test:docker:live-acp-bind,pnpm test:docker:live-cli-backend, andpnpm test:docker:live-codex-harness - all Parallels install/update tests:
pnpm test:parallels:npm-update -- --jsonplus any needed individual rerun lanes frommarketingclaw-parallels-smoke - all QA release validation: dispatch GitHub Actions >
QA-Lab - All Lanesagainst the release tag and require success. This is the release gate for live credentialed Matrix/Telegram channel coverage. Use a SHA only when it satisfies the workflow trust gate. Run local OpenAI/Anthropic suites or repo-backed character evals only when the operator asks for extra model coverage or a failure needs local debugging.
- Post-published beta verification roster:
node --import tsx scripts/marketingclaw-npm-postpublish-verify.ts <beta-version>- install/update smoke against the published beta channel
- Docker install/update coverage that exercises the published beta package
- published npm Telegram proof: dispatch Actions >
NPM Telegram Beta E2Efrommainwithpackage_spec=marketingclaw@<beta-version>andprovider_mode=mock-openai, and require success. This workflow is maintainer-dispatched and intentionally has nonpm-releaseapproval gate;qa-live-sharedonly supplies the shared QA secrets. This is the default button path for installed-package onboarding, Telegram setup, and real Telegram E2E against the published npm package. Use the localpnpm test:docker:npm-telegram-livelane with the matchingMARKETINGCLAW_NPM_TELEGRAM_PACKAGE_SPECand Convex CI env only as a fallback or debugging path. - Parallels published beta install/update coverage with both OpenAI and Anthropic provider keys available
- Parallels install/update proof must keep plugin installs enabled unless the operator explicitly scopes a harness-only isolation check; a lane that disables bundled plugin installs is not valid plugin/dependency release evidence.
- targeted QA reruns only for areas touched by fixes after the full pre-npm
roster, unless the operator requests the full QA roster again. If the fix
touches live channel QA, credential plumbing, Matrix, Telegram, or the QA
harness, rerun Actions >
QA-Lab - All Lanes.
- Check all release-related build surfaces touched by the release, not only the npm package.
- For beta-style full e2e batteries, hard-cap top-level long lanes instead of letting them run indefinitely. Use host
timeout --foreground/gtimeout --foregroundcaps such as:45mforMARKETINGCLAW_INSTALL_SMOKE_SKIP_NONROOT=1 pnpm test:install:smoke90mforpnpm test:docker:all60meach for standalone Docker live lanes180mfor local full QA live OpenAI + Anthropic rosters when explicitly requested; the default release channel QA gate is Actions >QA-Lab - All Lanes- Parallels caps from the
marketingclaw-parallels-smokeskill If a lane hits its cap, stop and inspect/fix the affected lane before continuing; do not continue to wait on the same process.
- Actual npm install/update phases are capped at 5 minutes. If
npm install -g, installer package install, ormarketingclaw updatetakes longer than 300s in release e2e, stop treating the run as healthy progress and debug the installer/updater or harness. - Serialize host build/package mutations ahead of VM lanes. Finish
pnpm build,pnpm ui:build,pnpm release:check, install smoke, and any Docker/package-prep lanes before starting Parallelsnpm packlanes; otherwisedistcan disappear during VM pack prep and produce false failures. - Include mac release readiness in preflight by running the public validation
workflow in
promisingcoder/marketingclawand the release-ops mac preflight inmarketingclaw/releasesfor every release. - Treat the
appcast.xmlupdate onmainas part of mac release readiness, not an optional follow-up. - The workflows remain tag-based. The agent is responsible for making sure preflight runs complete successfully before any publish run starts.
- Any fix after preflight means a new commit. Delete and recreate the tag and matching GitHub release from the fixed commit, then rerun preflight from scratch before publishing. Exception: never delete or recreate a beta tag whose matching npm package has already been published; increment to the next beta number instead. If only the pushed tag/prerelease exists and npm publish has not happened, recreate that same beta tag at the fixed commit.
- For stable mac releases, generate the signed
appcast.xmlbefore uploading public release assets so the updater feed cannot lag the published binaries. - Serialize stable appcast-producing runs across tags so two releases do not
generate replacement
appcast.xmlfiles from the same stale seed. - For stable releases, rely primarily on the latest beta's broader release
workflow confidence. When promoting the matching non-beta build to npm
latest, prefer a light time-bounded verification pass: published npm postpublish verify, Docker install/update smoke, macOS-only Parallels install/update smoke, and required QA signal. Do not rerun the full Docker/Parallels matrix unless the beta evidence is stale, the stable build differs materially from beta, or the operator explicitly asks for full retesting. - If any required build, packaging step, or release workflow is red, do not say the release is ready.
Use the right auth flow
- MarketingClaw publish uses GitHub trusted publishing.
- Stable npm promotion from
betatolatestuses the restricted release-opsmarketingclaw/releases/.github/workflows/marketingclaw-npm-dist-tags.ymlworkflow becausenpm dist-tagmanagement needsNPM_TOKEN, while the public npm release workflow stays OIDC-only. - Prefer fixing the release-ops workflow token path over any local 1Password
fallback. The desired setup is a granular npm token stored as the release-ops
repo's
NPM_TOKENsecret, scoped to themarketingclawpackage with read/write and 2FA bypass for automation. - If the release-ops dist-tag workflow cannot promote because
NPM_TOKENis absent or stale, use the local tmux + 1Password fallback:- Start or reuse a tmux session so interactive
npm loginand OTP prompts are observable and recoverable. - Hard rule: never run
opdirectly in the main agent shell during release work. Any 1Password CLI use must happen inside that tmux session so prompts and alerts are contained and observable. - Use
$release-privatefor the npm credentials and OTP item. Do not print passwords, tokens, or OTPs to the transcript; send them through tmux buffers, env vars scoped to the tmux command, orexpectwithlog_user 0. - Re-authenticate npm inside that tmux session with
npm login --auth-type=legacy, then confirmnpm whoamireportssteipete. - Promote with a fresh OTP:
npm dist-tag add openclaw@YYYY.M.PATCH latest --otp "$OTP". - Verify with a cache-bypassed registry read, for example:
npm view marketingclaw dist-tags --json --prefer-online --cache /tmp/marketingclaw-npm-cache-verify-$$and `npm view openclaw@late
- Start or reuse a tmux session so interactive
…(truncated)