From 111911d0614a5a9c2e9bd4cd12a38088163ea356 Mon Sep 17 00:00:00 2001 From: geobelsky Date: Wed, 29 Apr 2026 14:32:18 +0000 Subject: [PATCH 1/3] =?UTF-8?q?release:=20v0.5.0=20=E2=80=94=20Windows=20n?= =?UTF-8?q?ative=20+=20multi-client=20docs=20+=20semantic=20search?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Combined release skipping 0.3.0 / 0.4.0. Bumps version in 5 places (package.json, .claude-plugin/plugin.json, templates/plugin-README.md badge, package-lock.json via npm install --package-lock-only, README tests badge 511→536) and ships the v0.5.0 CHANGELOG entry covering PRs #118, #119, #120, #121, #122, #123, #124. Highlights: - Native Windows support (#122) — install.ps1, 3-OS CI matrix, Phase 1-4 production fixes, D-136 standalone-bundle SDK path. - Multi-client docs surfaced in README (#123) — Cursor / Windsurf / Cline / Claude Desktop / any MCP client. - Semantic search (B-005, #124) — axme_get_memory / axme_get_decision / axme_search_kb, opt-in tiered context.mode, lazy install of @huggingface/transformers, brute-force cosine, CLI config get/set + reindex, MUST-style >100-entry hint. - SEO + Glama infra (#118-#121). Verified locally: - npm test 536/536 pass - npx tsc --noEmit clean - npm run build clean Combined E2E (separately, before merge of #122/#123/#124): - Linux: setup + install runtime + reindex 30/30 + axme_search_kb semantic ranking correct ($0.47 setup, $0 search/get). - Windows native (Azure Win11 Pro 24H2 D2s_v5): same flow, 31/31 indexed, agent uses catalog correctly. VC++ Redist required for onnxruntime-node native binding (clear error message on missing). Co-Authored-By: Claude Opus 4.7 (1M context) --- .claude-plugin/plugin.json | 2 +- CHANGELOG.md | 31 +++++++++++++++++++++++++++++++ README.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- templates/plugin-README.md | 2 +- 6 files changed, 37 insertions(+), 6 deletions(-) diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 0558c43..4a167ad 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "axme-code", - "version": "0.2.9", + "version": "0.5.0", "description": "(Alpha) Persistent memory, architectural decisions, and safety guardrails for Claude Code. Your agent starts every session with full project context — stack, decisions, patterns, safety rules, and a handoff from the previous session.", "author": { "name": "AXME AI", diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f7858e..1299bea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,36 @@ # Changelog +## [0.5.0] - 2026-04-29 + +Skips 0.3.0 / 0.4.0 — combined release for native Windows support, multi-client docs surfacing, and the semantic-search MCP tools (B-005). + +### Added + +- **Native Windows support** (#122). axme-code now runs natively on Windows (x64 + arm64) without WSL2. Single TypeScript codebase produces 6 binary artifacts from one source tree (D-133, supersedes the now-obsolete D-120). New `install.ps1` downloads the standalone Node bundle into `%LOCALAPPDATA%\Programs\axme-code\`, generates a `.cmd` wrapper, and adds the dir to the User PATH. Three-OS CI matrix (ubuntu / macos / windows-latest) gates every PR. Production fixes: `atomicWrite` fsync uses a write-fd (Windows FlushFileBuffers needs write access); `findClaudePath` switches to `where.exe` and prefers the underlying `claude.exe` from `node_modules\@anthropic-ai\claude-code\bin\` over npm's `.cmd` shim (CVE-2024-27980 EINVAL avoided); `execSync("sleep")` replaced with `Atomics.wait` (POSIX `sleep` is missing on cmd.exe); 13 instances of `path.split("/").pop()` replaced with `path.basename()`. Hook commands written by `axme-code setup` now use absolute `node` + script path, all segments quoted, so they work cross-platform without PATH dependency. The plugin's SessionStart shell fragment moved into the new `check-init` Node subcommand. Verified end-to-end on Azure Win11 Pro 24H2 with real OAuth Claude session + detached audit worker (`audit_complete` event written, parent process can exit cleanly without orphaning the worker). +- **Semantic search MCP tools** (B-005, #124). Three new read-only tools: `axme_get_memory(slug)`, `axme_get_decision(id_or_slug)`, `axme_search_kb(query, type?, k?)`. The first two fetch full bodies on demand (useful in any mode). The third does brute-force cosine over Float32 embeddings of every memory + decision (~10ms at 1000 vectors, no native bindings). Embeddings produced locally by `Xenova/all-MiniLM-L6-v2` via `@huggingface/transformers` — runs on CPU, **no token cost**, no API calls, no key required. +- **Tiered context-loading mode** (B-005, #124). New `config.context.mode` field with values `full` (default, every memory + decision body loaded at session start — existing behaviour) and `search` (catalog only — title + 1-line description + `[type/enforce]` label, ~10× lower startup tokens). Switching is user-driven only: `axme-code config set context.mode search` (or env var `AXME_CONTEXT_MODE`, or hand-edit of `config.yaml`). When the user is on `full` mode and the KB exceeds 100 entries, `axme_context` emits a directive (MUST-style) instruction telling the agent to surface the option to the user and ask whether to run the install command. +- **Lazy install of the embeddings runtime** (B-005, #124). `@huggingface/transformers` (~100MB node_modules + ~30MB MiniLM ONNX weights cached at `~/.cache/huggingface/`) is **not** bundled into the binary. It installs into `~/.local/share/axme-code/runtime/` only when the user opts in via `axme-code config set context.mode search`. That command is atomic: install → reindex every memory + decision → write `context.mode = search`. If install or reindex fails, the config rolls back to `full` and an actionable error is printed. +- **`axme-code config get / set` CLI subcommand** (#124). Reads and writes `.axme-code/config.yaml` from the terminal. Currently supported keys: `context.mode` (the only set-able key in this release; get also exposes `model`, `auditor_model`, `review_enabled`). +- **`axme-code reindex` CLI subcommand** (#124). Force a full re-embed of every memory + decision into `.axme-code/_index/embeddings.json`. Useful after hand-editing markdown files or upgrading the runtime. +- **"Works With Any MCP Client" section in README** (#123). Surfaces multi-client compatibility (Cursor, Windsurf, Cline, Claude Desktop, any MCP client) that was previously documented only in `docs/MULTI_CLIENT.md`. Includes a compatibility matrix, the universal MCP server entry snippet, and per-client config-file paths. Hook-based features (safety enforcement, post-tool-use file tracker, background auditor) remain Claude Code-specific; MCP tools work everywhere. +- **Glama MCP directory validation Dockerfile** (#121). Minimal `Dockerfile` at repo root so https://glama.ai/mcp/servers/AxmeAI/axme-code can validate the server. Image installs via standard `install.sh` and exposes `axme-code serve` as ENTRYPOINT. +- **Glama directory claim** (#120). `glama.json` for ownership verification. +- **README SEO + star/watch CTA** (#119). First paragraph leads with niche keywords (persistent memory across sessions, pre-execution safety hooks, architectural decision enforcement, structured session handoff). ⭐/🔔/💬 CTA below badges. Description rewritten in same order. Topics expanded to 14. Homepage = code.axme.ai. GitHub Discussions enabled. +- **Plugin marketplace install instructions** (#118). README and site list `claude plugin marketplace add anthropics/claude-plugins-community` + `claude plugin install axme-code@claude-community` as the **recommended** install path. Standalone binary install demoted to "Option 2 — useful for scripting outside Claude Code". + +### Fixed + +- **Standalone bundle on Windows: SDK fallback crash** (#122 + #124). The Claude Agent SDK's own claude-binary resolution path (`fileURLToPath(import.meta.url)` followed by `require.resolve("./cli.js")`) crashes inside our esbuild-bundled CJS distribution because esbuild stubs `import_meta` as `{}` so `import_meta.url` is undefined. The pre-#122 workaround returned `undefined` from `claudePathForSdk()` on win32 to let the SDK use its fallback — that worked when running from `dist/` + `node_modules/` (SDK loaded as ESM, `import.meta.url` defined) but broke on the standalone bundle that `install.ps1` actually deploys. Fix (D-136): `claudePathForSdk()` now returns the concrete `claude.exe` path (derived from npm's `claude.cmd` shim location → `node_modules\@anthropic-ai\claude-code\bin\claude.exe`) on every platform, not undefined. Spawning `claude.exe` directly avoids both the SDK fallback crash AND CVE-2024-27980 EINVAL. +- **Cross-platform dynamic import of the embeddings runtime** (#124). `await import(absolutePath)` throws on Windows because Node treats raw `C:\...` paths as bare specifiers. Wrapping the resolved path with `pathToFileURL(...).href` produces a `file:///C:/...` URL that imports cleanly on every platform. + +### Known requirement (Windows) + +- **`axme-code config set context.mode search` requires Microsoft Visual C++ Redistributable** to be installed on Windows. The `onnxruntime-node` native binding (transitively required by `@huggingface/transformers`) loads `onnxruntime_binding.node` which depends on `vcruntime140.dll` / `msvcp140.dll`. On a fresh Windows install without VC++ Redist, `axme-code` now prints an actionable hint pointing to https://aka.ms/vs/17/release/vc_redist.x64.exe (~25 MB silent install) and the retry command. After installing the Redist, reindex completes in 5s for ~30 entries. + +### Changed + +- **Test count: 511 → 536** (+25 new tests across `test/embeddings.test.ts` (cosine math, topK ranking, JSON round-trip, mtime staleness, runtime detection) and `test/kb-search.test.ts` (3 handlers' fallback paths + format round-trip)). + ## [0.2.9] - 2026-04-17 ### Added diff --git a/README.md b/README.md index b66e999..cabb39c 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ You keep using Claude Code exactly as before. AXME Code works transparently in t [![Alpha](https://img.shields.io/badge/status-alpha-orange)]() [![GitHub Release](https://img.shields.io/github/v/release/AxmeAI/axme-code)](https://github.com/AxmeAI/axme-code/releases) [![License: MIT](https://img.shields.io/badge/license-MIT-blue)](LICENSE) -[![Tests](https://img.shields.io/badge/tests-413%20passing-brightgreen)]() +[![Tests](https://img.shields.io/badge/tests-536%20passing-brightgreen)]() > ⭐ **Star this repo** if it saves you time · 🔔 **Watch releases** for new features · 💬 [**Discussions**](https://github.com/AxmeAI/axme-code/discussions) diff --git a/package-lock.json b/package-lock.json index 7cc3f25..310ecfb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@axme/code", - "version": "0.2.9", + "version": "0.5.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@axme/code", - "version": "0.2.9", + "version": "0.5.0", "license": "MIT", "dependencies": { "@anthropic-ai/claude-agent-sdk": "^0.2.112", diff --git a/package.json b/package.json index 322f93d..0b07ffa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@axme/code", - "version": "0.2.9", + "version": "0.5.0", "description": "Persistent memory, decisions, and safety guardrails for Claude Code", "type": "module", "main": "./dist/server.js", diff --git a/templates/plugin-README.md b/templates/plugin-README.md index 657dfd8..18b8775 100644 --- a/templates/plugin-README.md +++ b/templates/plugin-README.md @@ -5,7 +5,7 @@ Persistent memory, architectural decisions, and safety guardrails for Claude Code. Your agent starts every session with full project context — stack, decisions, patterns, safety rules, and a handoff from the previous session. [![Alpha](https://img.shields.io/badge/status-alpha-orange)]() -[![Version](https://img.shields.io/badge/version-0.2.9-blue)]() +[![Version](https://img.shields.io/badge/version-0.5.0-blue)]() [![License: MIT](https://img.shields.io/badge/license-MIT-blue)](LICENSE) **[Main Repository](https://github.com/AxmeAI/axme-code)** · **[Website](https://code.axme.ai)** · **[Issues](https://github.com/AxmeAI/axme-code/issues)** From 8e67ae88dc3ab3562471a0252e6babf17e132d8f Mon Sep 17 00:00:00 2001 From: geobelsky Date: Wed, 29 Apr 2026 14:34:11 +0000 Subject: [PATCH 2/3] docs(install.ps1): bump example version in error message to v0.5.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pure cosmetic — the error path in install.ps1 still mentioned v0.2.9 as an example argument. Update so users on a fresh install see the current release as the suggested fallback. Co-Authored-By: Claude Opus 4.7 (1M context) --- install.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install.ps1 b/install.ps1 index 7542673..d946bf9 100644 --- a/install.ps1 +++ b/install.ps1 @@ -58,7 +58,7 @@ $arch = Get-Arch $platform = "windows-$arch" $version = if ($args.Count -ge 1 -and $args[0]) { $args[0] } else { Get-LatestTag } -if (-not $version) { throw 'Could not determine version. Specify as first argument, e.g. install.ps1 v0.2.9' } +if (-not $version) { throw 'Could not determine version. Specify as first argument, e.g. install.ps1 v0.5.0' } Write-Host "Installing axme-code $version ($platform) to $InstallDir..." From 5dfcef338880bc2a896a5113619f01a7091963be Mon Sep 17 00:00:00 2001 From: geobelsky Date: Wed, 29 Apr 2026 14:36:39 +0000 Subject: [PATCH 3/3] docs(release): add RELEASE_CHECKLIST.md + memory pointer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every recent release (v0.2.7 → v0.5.0) has shipped or been about to ship with at least one stale version literal that the agent missed in the initial bump pass — lockfile not regenerated, README tests badge outdated, install.ps1 example version still pointing at the previous tag. The fix is institutional, not memorisation. docs/RELEASE_CHECKLIST.md enumerates: - The six version-literal locations to bump (package.json, .claude-plugin/plugin.json, templates/plugin-README.md badge, README.md tests badge, install.ps1 example, package-lock.json via npm install --package-lock-only). - Two grep commands that verify nothing stale remains and that the new version appears in exactly the expected six places. - CHANGELOG structure: theme paragraph + Added/Fixed/Changed/Removed + a Known-requirement section for non-obvious user-side prereqs like the Windows VC++ Redistributable. - Post-merge tag command for the user (D-024 — agent never tags). - The four chained release-binary.yml jobs to watch (build → release → publish-npm → sync-plugin-repo). - Smoke-test steps on Linux + Windows + plugin install. - A growing "Common things that have gone wrong" section that future releases append to. Also saved a memory ("read-docs-release-checklist-md-before-any- release-prep-pr") so future agent sessions are reminded to read the checklist end-to-end before starting any release-prep PR. Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/RELEASE_CHECKLIST.md | 121 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 docs/RELEASE_CHECKLIST.md diff --git a/docs/RELEASE_CHECKLIST.md b/docs/RELEASE_CHECKLIST.md new file mode 100644 index 0000000..89f9228 --- /dev/null +++ b/docs/RELEASE_CHECKLIST.md @@ -0,0 +1,121 @@ +# Release Checklist + +**Read this end-to-end before starting any release-prep PR.** It exists because the same items keep getting missed across releases — example versions in error messages, the test count in the README badge, hidden version references in workflow files, the lockfile drift after a manual `package.json` edit. Treat every item as required unless explicitly noted otherwise. + +The instructions assume you are an agent working with axme-code conventions: D-047 (feature branch naming), D-117 (no amend on pushed branches), D-023 (humans merge PRs), D-024 (humans tag releases), D-110/D-113 (`#!axme` gate suffix on every git commit/push). + +--- + +## 0. Pre-flight — before opening the release-prep PR + +- [ ] Read this file end-to-end. No skimming. +- [ ] Confirm `git status` is clean and current branch is up-to-date with `origin/main`. +- [ ] Re-run `npm test` on a fresh build. **Record the exact pass count** — you will need it for the README badge below. +- [ ] List the PRs that will ship in this release (`git log --oneline ..main`). Group them by Added / Fixed / Changed / Removed for the CHANGELOG. + +## 1. Pick the version + +- [ ] **Decide the bump** (major / minor / patch / skip-version) and capture the rationale in one sentence — that sentence becomes the first paragraph of the CHANGELOG entry. +- [ ] Per D-046 we are SemVer 0.x.y during alpha — breaking changes are allowed in minor bumps. You can also skip versions (we did 0.2.9 → 0.5.0); record the reason if so. + +## 2. Create the branch + +- [ ] Branch from a fresh `main`: `git checkout main && git pull --ff-only && git checkout -b release/v-`. + +## 3. Bump every version reference (the bit that keeps getting missed) + +These are the **six** places that hold a literal `X.Y.Z` string. Update **all of them** before continuing: + +- [ ] `package.json` — `"version"` field +- [ ] `.claude-plugin/plugin.json` — `"version"` field +- [ ] `templates/plugin-README.md` — `version-X.Y.Z-blue` shields.io badge URL +- [ ] `README.md` — `tests-NNN%20passing` shields.io badge (use the **exact** pass count from step 0) +- [ ] `install.ps1` — the example version in the `throw 'Could not determine version. ... e.g. install.ps1 vX.Y.Z'` line +- [ ] `package-lock.json` — sync via `npm install --package-lock-only` (do NOT hand-edit; npm has to recompute the dependency closure) + +After bumping, run two greps and confirm they both return **only** expected matches: + +```bash +# 1. Should return zero hits in source/config (CHANGELOG history hits are fine) +grep -rn "" --include="*.json" --include="*.ts" --include="*.mjs" \ + --include="*.yml" --include="*.yaml" --include="*.sh" --include="*.ps1" \ + | grep -v "node_modules\|dist/\|CHANGELOG\|.axme-code\|/.git/" + +# 2. Should return six matches (the six places above) all = +grep -rn "" --include="*.json" --include="*.ts" --include="*.md" \ + --include="*.ps1" | grep -v "node_modules\|dist/\|.axme-code\|/.git/" +``` + +If grep #1 turns up *any* hit you don't recognise, stop and fix it. There has been a stale version literal hiding in some non-obvious file every release. + +## 4. CHANGELOG entry + +- [ ] Add a `## [X.Y.Z] - YYYY-MM-DD` section at the **top** of `CHANGELOG.md` (newest first). +- [ ] One-paragraph summary tying together the release theme — what the user gains, why it shipped now, any combined-release rationale (e.g. "skips 0.3.0 / 0.4.0 because we batched Windows + B-005"). +- [ ] Sub-sections in order: `### Added`, `### Fixed`, `### Changed`, `### Removed`, `### Known requirement` (if any). Skip empty sections. +- [ ] **Cross-reference every PR** that ships in this release inline (`(#NNN)`). Reviewers should be able to map a CHANGELOG bullet back to a PR without `git log`-archaeology. +- [ ] If the release introduces a non-obvious user-side requirement (e.g. VC++ Redistributable on Windows, a new env var, a manual config flip), surface it under `### Known requirement` with the install URL or command so it's discoverable from the changelog alone. + +## 5. Verify the build will actually ship + +- [ ] `npx tsc --noEmit` — clean. +- [ ] `npm run build` — clean. +- [ ] `npm test` — every test passes; pass count matches the README badge. +- [ ] Inspect `dist/plugin/.claude-plugin/plugin.json` — confirm it shows the new version (esbuild reads from package.json at build time via `__VERSION__`). +- [ ] `node dist/axme-code.js --version` — confirm it prints the new version. +- [ ] Sanity-check the release workflow trigger: `.github/workflows/release-binary.yml` should fire on `push.tags: ['v*']`. Confirm the matrix still has all 6 platforms (linux-x64, linux-arm64, darwin-x64, darwin-arm64, windows-x64, windows-arm64). + +## 6. Open the release-prep PR + +- [ ] Commit with `release: v` and `#!axme pr=none repo=` suffix. +- [ ] Push the branch (regular push to a new branch — never force-push a branch with an open PR per D-117). +- [ ] Open the PR. Body must include: the CHANGELOG-paragraph summary, the file-by-file bump list, what's verified locally, and the **post-merge tag command for the user** (because per D-024 the agent never tags). +- [ ] Wait for the 3-OS CI matrix to go green. Do **not** ask for merge approval before that. + +## 7. After CI is green — get human approval + +- [ ] Surface the green-CI status to the user with the PR URL. +- [ ] Wait for the user to merge — D-023 forbids the agent merging PRs. +- [ ] Once merged, hand the user the **exact** tag commands (do NOT run them — D-024): + ```bash + git checkout main && git pull --ff-only + git tag v + git push --tags + ``` + +## 8. Watch `release-binary.yml` + +The workflow has 4 chained jobs (`build → release → publish-npm → sync-plugin-repo`). Watch each: + +- [ ] **build** — 6 jobs, one per matrix target. Each produces `axme-code-` (~2.4 MB self-contained Node bundle). +- [ ] **release** — `softprops/action-gh-release@v2` creates the GitHub Release for `vX.Y.Z` with `generate_release_notes: true`. Confirm the page shows 6 attached assets. +- [ ] **publish-npm** — `npm publish --access public` with `NODE_AUTH_TOKEN` from `secrets.NPM_TOKEN`. Confirm `@axme/code@X.Y.Z` is live on npmjs.org. +- [ ] **sync-plugin-repo** — clones `AxmeAI/axme-code-plugin`, wipes everything except `.git`/`.gitignore`, copies `dist/plugin/*` (and `.mcp.json` + `.claude-plugin/`), strips sourcemaps + `node_modules`, commits with `sync: v from axme-code`. Confirm the plugin repo's latest commit is from `github-actions` and `plugin.json` shows the new version. + +If any job fails, stop and triage **before** announcing the release. A half-published release (binaries up but npm publish failed, or npm up but plugin repo not synced) confuses every install path the next time someone runs `install.sh`/`install.ps1` or `claude plugin install`. + +## 9. Smoke-test the published release on a fresh dir + +- [ ] `mkdir /tmp/axme-release-smoke-$$ && cd /tmp/axme-release-smoke-$$ && git init -q && touch package.json README.md` +- [ ] On Linux/macOS: `curl -fsSL https://raw.githubusercontent.com/AxmeAI/axme-code/main/install.sh | bash` — confirm it downloads `vX.Y.Z`, places `~/.local/bin/axme-code`, and `axme-code --version` prints `X.Y.Z`. +- [ ] On Windows (Azure VM, deallocate when done): `irm https://raw.githubusercontent.com/AxmeAI/axme-code/main/install.ps1 | iex` — confirm it downloads `vX.Y.Z`, places `%LOCALAPPDATA%\Programs\axme-code\axme-code.js` + `.cmd` shim, and version prints correctly. +- [ ] Plugin install path: `claude plugin install axme-code@claude-community` — confirm the new version is what gets pulled (the marketplace caches; may need to wait 5-10 min for Anthropic's index to refresh). + +## 10. Announcement & cleanup + +- [ ] Run `axme_social_bot.py` once if appropriate. Verify stdout shows `LinkedIn link-comment posted: ...` (was silent 404 before the URN percent-encoding fix). +- [ ] Close any deferred backlog items that this release resolved. +- [ ] Delete the merged release branch locally and on origin (the branch is finished; the tag is the immutable reference now). +- [ ] Deallocate any Azure VMs you started for E2E (`az vm deallocate -g axme-test -n axme-win11` and check `az vm list -d --query "[?powerState!='VM deallocated'].{name:name}"`). + +--- + +## Common things that have gone wrong before + +- **Forgot to bump the lockfile** (v0.2.9 release-prep, PR #111). `package.json` was 0.2.9 but `package-lock.json` stayed on 0.2.8 because manual edits don't re-run npm. Always finish version bumps with `npm install --package-lock-only`. +- **Forgot to update an example version in an error string** (`install.ps1`, this v0.5.0 release-prep). Cosmetic but visible to every user who hits the error path. Grep for the old version with no source-file filter and audit each hit. +- **Released without verifying the npm publish step had a token** (early v0.2.7 attempts). `secrets.NPM_TOKEN` must be configured in repo settings; check `npm whoami` on the publish runner if a publish silently no-ops. +- **Released without verifying plugin repo synced** — always open `https://github.com/AxmeAI/axme-code-plugin` after the workflow finishes and confirm the latest commit is `sync: vX.Y.Z from axme-code` from `github-actions`. Workflows have failed silently on the sync step before due to the `PLUGIN_REPO_TOKEN` not having `contents: write` on the target repo. +- **Skipped CHANGELOG entry until after the tag** (one early version). Once a tag is pushed, the CHANGELOG is hard to update without confusing users; D-128 makes it a required step before bumping `package.json`. + +When you finish a release, write any new "things that went wrong" to this section so the next agent sees them.