Skip to content

Release Checklist

Use this checklist before tagging a Nuzo release.

Use the complete checklist for every versioned public release.

Scope

  • Confirm the target milestone is complete or intentionally deferred.
  • Confirm no priority:p0 or release-blocking priority:p1 issues remain open.
  • Confirm known non-blockers are documented in GitHub Issues.
  • Confirm README, roadmap, and docs describe the actual shipped state.
  • Before or immediately after publishing, run a general issue-hunting pass and open focused post-release roadmap issues only. Do not expand the release scope unless the finding is release-blocking.

Useful commands:

gh issue list --repo fabionfsc/nuzo-memory --state open --label priority:p0
gh issue list --repo fabionfsc/nuzo-memory --state open --label priority:p1

Workspace

Start from a clean worktree:

git status --short

Confirm a supported runtime is active:

node --version
npm --version

The release baseline is Node.js 22 LTS or 24 LTS with npm 10 or newer. Confirm that the engine declarations, CI matrix, and docs/operations/runtime-support.md still agree.

Install dependencies from the lockfile:

npm ci

Use npm install only when intentionally changing dependencies and reviewing package-lock.json.

Validation

Confirm the CI workflow is green:

gh run list --repo fabionfsc/nuzo-memory --workflow ci.yml --limit 5
gh run list --repo fabionfsc/nuzo-memory --workflow codeql.yml --limit 5

Run:

npm run check
npm run release:check
npm test
npm run build
npm run benchmark:recall
npm run benchmark:capture
npm run benchmark:capture -- --expect bounded
npm run benchmark:relations
npm run benchmark:governance
npm run benchmark:semantics
npm run benchmark:semantics -- --store-size medium
npm run package:plugins
npm run validate:npm
npm run smoke:cli
npm run smoke:host-hooks
npm run smoke:host-canary
npm run smoke:claude-code-plugin
npm run smoke:codex-plugin
NUZO_HOST_CANARY_NATIVE=1 npm run smoke:host-canary

Before tagging, confirm the CI job Installed artifacts passed for every supported OS/Node lane documented in Runtime Support:

ubuntu-latest / Node 22
ubuntu-latest / Node 24
macos-15-intel / Node 22
macos-15-intel / Node 24
windows-latest / Node 22
windows-latest / Node 24

Do not claim a new OS, architecture, or Node combination in release notes until that combination is represented in CI or explicitly called out as untested and unsupported.

For 0.9.0+, prove local-store integrity and recovery with fake data before release:

nuzo memory --store /tmp/nuzo-release/memories.sqlite init
nuzo memory --store /tmp/nuzo-release/memories.sqlite remember \
  "Release backup validation uses fake data only." --kind note --tag release
nuzo memory --store /tmp/nuzo-release/memories.sqlite integrity
nuzo memory --store /tmp/nuzo-release/memories.sqlite backup \
  --path /tmp/nuzo-release/memories.backup.sqlite --overwrite
nuzo memory --store /tmp/nuzo-release/restored.sqlite restore \
  /tmp/nuzo-release/memories.backup.sqlite --yes
nuzo memory --store /tmp/nuzo-release/restored.sqlite integrity
nuzo memory --store /tmp/nuzo-release/restored.sqlite recall "backup validation"

The SQLite backup step must use nuzo memory backup or an equivalent SQLite online backup API. Do not validate release recovery by copying only memories.sqlite from a WAL-mode store.

For 0.7.0, additionally provision the pinned local model in a temporary location and run the real-provider benchmark and staged optional install:

node tools/semantic-benchmark.mjs \
  --local-transformers-model /absolute/path/to/pinned-model \
  --similarity-floor 0.34
NUZO_SEMANTIC_MODEL_PATH=/absolute/path/to/pinned-model npm run validate:npm

The normal npm run validate:npm invocation must prove that Transformers.js and model files are absent from a default install. The environment-enabled invocation must install the exact optional peer, rebuild a staged sidecar, and recall the expected paraphrase through the staged @nuzo/memory artifact. nuzo memory semantic status and semantic provision must not report ready or skip repair for tampered, truncated, missing, unreadable, or symlinked pinned model files.

Before release:prepare, also run published/package-resolution smokes for the current release:

npm run smoke:published:cli
npm run smoke:published:mcp
npm run smoke:published:semantics

The plugin artifact smokes use staged npm tarballs before publication while still validating the generated version-pinned commands. After publishing, run them against the exact public commands:

NUZO_PLUGIN_SMOKE_PUBLISHED=1 npm run smoke:host-canary
NUZO_PLUGIN_SMOKE_PUBLISHED=1 npm run smoke:claude-code-plugin
NUZO_PLUGIN_SMOKE_PUBLISHED=1 npm run smoke:codex-plugin

The published host canary sets npm's internal log level to error for its version-pinned npm exec hook subprocesses. This prevents non-fatal dependency warnings from being mistaken for hook failures while preserving strict failure on a non-zero hook status or hook stderr.

The smoke:published:* commands resolve the current target from npm and are expected to fail until that version is published. Run them again after publishing the target packages. The optional-semantics published smoke always validates the default no-model fallback and package boundary. To require a real local semantic rebuild and recall against the exact published package, run:

NUZO_SEMANTIC_MODEL_PATH=/absolute/path/to/pinned-model \
  npm run smoke:published:semantics -- --require-model

For 0.6.0, keep a release-gate note with the command output or CI links that prove:

  • the capture benchmark records the 0.5.0 baseline profile and the bounded 0.6.0 profile;
  • English relationship quality fails independently from other languages;
  • policy blocks, scope isolation, archived isolation, candidate/output bounds, zero memory writes, zero audit writes, and revision conflicts pass;
  • staged CLI, MCP, Codex, and Claude Code flows all use explicit memory.confirm_capture decisions for capture confirmation.

Confirm the generated host artifacts contain no monorepo runtime paths:

rg -n '\.\./mcp-server|packages/mcp-server' build/plugins

The command should return no matches.

Confirm the target @nuzo/memory-core, @nuzo/memory, and, starting with 1.1.0, @nuzo/memory-mcp versions are not already published before publishing. After publishing, @nuzo/memory must exist before shipping the plugin artifacts, and @nuzo/memory-mcp must exist before publishing server.json to the MCP Registry.

Follow docs/operations/npm-publishing.md. Confirm the @nuzo organization scope and maintainer access before changing source package privacy or running any publish command.

Confirm npm trusted publishing is configured for each package that the target release will publish.

For 0.9.0, confirm:

@nuzo/memory-core
@nuzo/memory
@nuzo/memory-cli
@nuzo/mcp-server

For 1.0.x, confirm:

@nuzo/memory-core
@nuzo/memory

For 1.1.0 and later, confirm:

@nuzo/memory-core
@nuzo/memory
@nuzo/memory-mcp

For the first @nuzo/memory-mcp@1.1.0 publication, npm cannot configure a trusted publisher or staged publish before the package exists. Confirm the release workflow publishes core and unified memory but reports the Registry package as deferred. Bootstrap that exact reviewed package once from an authenticated maintainer session after core is public, then configure its trusted publisher immediately. Never add a long-lived npm token to the workflow for this exception.

All package settings must point to GitHub Actions, repository fabionfsc/nuzo-memory, workflow release-npm.yml, environment npm-publish, and allowed action npm publish.

Build docs strictly:

python3 -m venv .venv-docs
.venv-docs/bin/pip install -r requirements-docs.txt
.venv-docs/bin/mkdocs build --strict

Check dependency state:

npm ls --depth=0
npm audit --audit-level=moderate
npm audit signatures

Confirm repository security automation is active:

  • Dependabot alerts and security updates are enabled.
  • Dependabot config covers npm, GitHub Actions, and Python docs dependencies.
  • CodeQL runs on pushes, pull requests, and the weekly scheduled scan.
  • Secret scanning and push protection remain enabled.
  • Branch protection applies to administrators and requires pull requests for routine changes.
  • Required Node.js 22, Node.js 24, documentation, and CodeQL checks use strict current-branch validation.

Supply-Chain Inputs

CI, CodeQL, Pages, and npm release workflows must not depend on mutable third-party action tags.

Before a release branch, run:

npm run check:supply-chain

The gate requires:

  • every external uses: entry under .github/workflows/ to point at a 40-character commit SHA;
  • every pinned action to keep a trailing reviewed version comment such as # v7, so Dependabot and reviewers can still identify the upstream line;
  • global npm installation in release workflows to use an exact reviewed version, not a range;
  • npm exec --package=... workflow inputs to use exact package versions.

Dependabot already covers the github-actions ecosystem monthly in .github/dependabot.yml. Treat those PRs as supply-chain review PRs: verify the upstream release notes, confirm the SHA still matches the documented version comment, and require the full repository checks before merging.

Repository Actions settings were evaluated on 2026-06-30: Actions were enabled, all actions were allowed, and repository-level SHA pinning enforcement was not enabled. Do not rely on that mutable repository setting as the only guard. The versioned npm run check:supply-chain gate is the repository contract. If GitHub repository-level SHA enforcement or action allowlisting is later enabled, first test it on a dry-run PR and confirm CI, CodeQL, Pages, and the manual npm release workflow still accept GitHub-owned actions pinned by SHA.

Node.js 22 and 24, Python 3.12, and GitHub-hosted runner images remain documented support lanes rather than immutable supply-chain artifacts. Changes to those runtime lanes still require a normal reviewed pull request and passing CI.

Emergency rollback path:

  1. Revert the workflow pin bump or failed supply-chain PR.
  2. Re-run npm run check:supply-chain, npm run check, docs strict, and the affected workflow.
  3. If an upstream action SHA is suspected compromised, replace it with the last known-good reviewed SHA in a dedicated security PR and record the evidence in the PR body.

Clean Install

Run the clean install walkthrough:

docs/getting-started/clean-install.md

Use fake data only.

If better-sqlite3 falls back to a native build, validate the documented platform toolchain path in docs/operations/runtime-support.md.

0.9.0 Legacy Package Cutoff

For the 0.9.0 release only:

  1. Publish and validate @nuzo/memory-core, @nuzo/memory, @nuzo/memory-cli, and @nuzo/mcp-server at exactly 0.9.0.
  2. Confirm the unified package exposes nuzo, nuzo-mcp-server, and nuzo-memory-hook and passes the published CLI/MCP smokes.
  3. Confirm the transition-package npm READMEs identify @nuzo/memory as the replacement and 0.9.0 as their final release.
  4. Only then apply the two npm deprecation messages documented in npm Publishing.
  5. Verify npm reports both transition packages as deprecated and record the registry evidence in post-release validation.

Deprecation is a post-publication metadata action. Do not perform it during a dry run, rehearsal, or before the unified 0.9.0 replacement is available.

For releases after 0.9.0:

  1. Confirm npm run package:npm, npm run validate:npm, and the npm release workflow stage only the active package set: core and unified memory for 1.0.x, plus @nuzo/memory-mcp starting with 1.1.0.
  2. Confirm build/npm/packages/memory-cli/package.json and build/npm/packages/mcp-server/package.json are absent.
  3. Treat any retired transition package in staging as a release blocker.

Security And Sanitization

Before tagging, confirm no runtime memory, generated files, or credentials are staged:

git status --short
git ls-files | rg '(^site/|/dist/|^dist/|^node_modules/|\.sqlite|memory\.export|\.env)'

Expected tracked output is empty. Public documentation and test fixtures must continue to use fake data only.

Remove generated artifacts before committing:

rm -rf site packages/core/dist packages/cli/dist packages/mcp-server/dist

Do not commit runtime memory stores, real memory exports, .env files, credentials, private user data, dependency caches, or generated docs/build output.

Version And Changelog

Follow:

docs/operations/versioning.md
docs/operations/release-version-map.md

Before tagging:

  • rehearse the target with npm run release:rehearse -- X.Y.Z;
  • optionally run the CI workflow manually with the same release rehearsal version;
  • always provide an explicit future version to the manual workflow; it has no default target and rejects a changelog version that already exists;
  • keep workflow inputs in environment variables and quote them in shell commands; do not interpolate user-controlled dispatch inputs directly;
  • add a dated target version section to CHANGELOG.md and summarize the relevant user-visible changes directly in it;
  • keep the newest released version as the first changelog section;
  • prepare the release version with npm run release:prepare -- X.Y.Z;
  • confirm npm run release:check -- X.Y.Z passes;
  • confirm public release references in docs/operations/release-version-map.md are still complete;
  • review package.json, workspace package versions, host plugin manifests, source version strings, and package-lock.json;
  • commit the version bump as a release commit.

Do not bump versions for ordinary development commits.

The synthetic changelog section used during rehearsal is not release notes and does not replace the real changelog edit required for the release commit.

GitHub Pages

Confirm the docs workflow is green:

gh run list --repo fabionfsc/nuzo-memory --limit 5

Confirm the public docs URLs:

curl -I https://fabionfsc.github.io/nuzo-memory/
curl -I http://nuzo.com.br/

When GitHub finishes custom-domain certificate issuance, also confirm:

curl -I https://nuzo.com.br/

If HTTPS is still not enforced, keep the GitHub Pages HTTPS issue open and mention it in release notes if the release depends on the custom domain.

Review, Tag, And Publish

After validation, version bump, and merge to main, confirm the working tree and exact release commit:

git diff --check
git status --short
git push origin main

Run the npm release workflow from main with the exact package version and publish=false first. Confirm it selects the intended version and packages without using an npm token. Retain the workflow artifact and record the dry-run ID, full source commit, artifact name, and artifact-manifest.json SHA-256.

Only after reviewing that retained artifact, tag the exact reviewed source commit and prepare a draft GitHub release from the matching CHANGELOG.md section:

git tag vX.Y.Z <reviewed-source-commit>
git push origin vX.Y.Z

Keep the GitHub release as a draft until npm publication, Registry publication, and the post-release canaries pass. This preserves the reviewed release identity without announcing a release that has not completed its irreversible publication gates.

Run the same workflow with publish=true, supplying reviewed_run_id and the reviewed manifest SHA-256. The run must verify the successful dry run and publish the exact retained candidates from its immutable artifact; its rebuild remains a separate validation gate. Confirm the npm package pages show provenance and record each matching public dist.integrity.

For the one-time @nuzo/memory-mcp@1.1.0 bootstrap, publish only the retained tarball after verifying its manifest and checksum. Record its matching public dist.integrity. This local first publication is the documented provenance exception; @nuzo/memory-core and @nuzo/memory still require provenance, and all active packages require it from 1.1.1 onward.

Post-Release

  • Publish the reviewed draft GitHub release, then confirm its page is correct.
  • Confirm GitHub Pages still deploys successfully.
  • Confirm the matching active npm package versions are published.
  • Open follow-up issues for deferred work.
  • Leave CHANGELOG.md headed by the released version; add the next dated section only when preparing that release.