smd-release
Skill3 starsChanged 7 days agoMITView on GitHub
Branch, version, verify and publish Semantic Markdown releases (VS Code extension, npm package `semantic-markdown`, agent skills, GitHub release) without breaking existing users. Use this skill for any change destined for the public bislink360/semantic-markdown repository — starting a feature or fix branch, preparing or reviewing a pull request, bumping versions, writing the changelog, checking backward compatibility, tagging, or publishing to the VS Code Marketplace, Open VSX, npm or GitHub Releases (the tag-triggered Release workflow) — even if the user just says "ship it", "release this", "bump the version", "merge this" or "publish".
- Commits and pushes
1 other project uses a version of this.
Adopted by
Most recently taken up by
- bislink360/semantic-markdownword for word, first seen Nov 8, 2026
Other versions1 project uses a version of this.
Word for word · 1
- bislink360/semantic-markdown★ 3100% same
Edited · 0
None found.
Wrote their own version · 0
None found.
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository4 other files it gives its agents.
- sonarqube-scanSkill
- version-controlSkill
- semantic-markdown-readerSkill
- semantic-markdown-writerSkill
The file
We split this skill into the rules it gives an agent
11 rules. About 0 are common, 6 are distinctive, and 5 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈6
Distinctive · estimate
This author's own choices. Worth a look.
5
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 26
Every feature or fix gets its own branch from the release branch: feat/<slug>, fix/<slug>, docs/<slug>, chore/<slug>.
- Distinctive: line 28
After the release is tagged and published, the release branch is merged into main with a merge commit.
- Distinctive: line 30
Never commit to main directly, and never open feature PRs against main.
- Very specific: line 36
Before designing a change, read references/compatibility.md.
- Distinctive: line 38
Add, don't change: Add new blocks, directives, attributes, values, commands, flags, exports and settings.
- Distinctive: line 40
Deprecate before removing: Keep an alias, emit a deprecation hint, document it, and remove it only in the next major.
- Very specific: line 63
Every new syntax feature must also add a document exercising it to extension/test/compat/corpus/, so future releases are compared against …
- Very specific: line 75
Update docs for any new syntax: docs/reference/spec.md, docs/reference/features.md, the matching …
- Distinctive: line 85
Before tagging, show the human the checker report and a short summary:
- Distinctive: line 94
Don't proceed until the human approves in chat.
- Very specific: line 157
If a release is bad, don't unpublish.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Releasing Semantic Markdown
One repository ships four artifacts that must stay in lockstep:
| Artifact | Where | Version source |
VS Code extension bislink360.semantic-markdown | VS Code Marketplace, Open VSX + .vsix on GitHub Releases | extension/package.json |
npm package semantic-markdown (library + smd CLI) | npmjs.com | npm/package.json (same version) |
Agent skills semantic-markdown-reader / -writer | skills/, zips on GitHub Releases | bundle the CLI, so they follow the same version |
| Format spec | smd: 2 in new documents (smd: 1 documents keep the v1 rules) | SMD_VERSION in extension/src/core/spec.ts; changes only for format-breaking releases |
Existing documents, CI pipelines (smd validate), library users and agents all depend on today's behaviour. The primary goal of this process is that nothing breaks silently. Every incompatible change is found by the checker, called out to the human, and shipped only as a major version.
Workflow
1. Branching: follow the release train (version-control skill)
Branches follow the version-control skill's release train:
release/vX.Y.Zis created frommainand opened at its version byplan-release.mjs.- Every feature or fix gets its own branch from the release branch:
feat/<slug>,fix/<slug>,docs/<slug>,chore/<slug>. - Feature PRs target the release branch and are squash-merged.
- After the release is tagged and published, the release branch is merged into
mainwith a merge commit.
Never commit to main directly, and never open feature PRs against main.
Use Conventional Commit messages (feat(tables): add captions, fix(cli): …, docs: …), because they feed the changelog. Mark breaking commits with ! and a BREAKING CHANGE: footer. Do not add AI co-author trailers or "Generated with" lines to commits or PRs in this repository. Read references/branching.md for the PR checklist and merge rules.
2. Keep every change backward compatible by default
Before designing a change, read references/compatibility.md. It lists what counts as breaking on each surface (syntax, validation, HTML, agent view, CLI, npm API, extension manifest, skills) and the compatible alternative for each. In short:
- Add, don't change. Add new blocks, directives, attributes, values, commands, flags, exports and settings. Leave old ones working.
- Never make valid documents invalid. New checks start as
warning/info; only a major release may introduce new errors on previously valid input. - Deprecate before removing. Keep an alias, emit a deprecation hint, document it, and remove it only in the next major.
- Stable identifiers are contracts: diagnostic codes, CLI flags and JSON output fields,
smd-*CSS classes, agent-view tags, extension command/setting IDs, skill names.
3. Prove it on every PR
From the repository root:
node .claude/skills/smd-release/scripts/release-check.mjs --pr # on feature PRs into a release branch
node .claude/skills/smd-release/scripts/release-check.mjs # on the release branch before tagging (versions and changelog enforced)
node .claude/skills/smd-release/scripts/release-check.mjs --skip-vscode --skip-tests # quick iterationThe checker builds the last release in a temporary worktree (cached) and compares it with the working tree. "The last release" is the newest vX.Y.Z tag, with one exception: once a version is tagged, the tree with exactly that tag's files (the tracking PR into main, whose CI runs again after the tag is pushed) is compared with the release before it and reported as already released, instead of failing as "not greater than the last release". A tag of the same version on a different tree still fails: the version was not bumped, or the tag is on the wrong commit.
- format vocabulary, diagnostic codes, validation results, agent view, Markdown export and emitted CSS classes on a document corpus
- CLI commands and flags, and templates
- npm exports, entry points and types
- extension commands, settings, defaults, language IDs, keybindings and snippets
- skills
It also runs the typecheck, unit tests and VS Code integration tests, checks version consistency and the changelog, and computes the required bump. It exits 1 if anything blocks.
Every new syntax feature must also add a document exercising it to extension/test/compat/corpus/, so future releases are compared against it. Create the folder if it doesn't exist yet.
4. Finish the release on release/vX.Y.Z
The release branch was opened at its version when the train was planned:
plan-release.mjsrunsbump-version.mjs, which updatesextension/package.json,extension/package-lock.json,npm/package.json, the Obsidian plugin'sintegrations/obsidian/manifest.jsonandversions.json, the MkDocs plugin'spyproject.toml, the Claude Code plugin's.claude-plugin/plugin.jsonand the MCP registry entryserver.json, and adds the CHANGELOG heading. Each feature PR added its own changelog bullets under that heading. If the version must change (e.g. a breaking change turned up and it must become a major), run:node .claude/skills/smd-release/scripts/bump-version.mjs <patch|minor|major|X.Y.Z>on the release branch, and rename the release branch and tracking PR to match.
- Once every planned feature PR is merged into the release branch (or dropped from the train), complete the changelog entry. List every item from the checker's Breaking section under
### ⚠️ Breaking changes, each with a migration note. Delete empty headings. - Update docs for any new syntax:
docs/reference/spec.md,docs/reference/features.md, the matchingskills/semantic-markdown-writer/references/syntax/<topic>.md(listed inreferences/syntax.md), and the README feature list. - Rebuild (
cd extension && npm run build && npm run build:npm) and run the full check with no skip flags. Run the static analysis gate (sonarqube-scan skill). GitHub CI has no static analysis, so this local SonarQube run is the only check for bugs, vulnerabilities, security hotspots and code smells. It must pass: fix blocking findings, or suppress them with a reasoned
NOSONAR. Growbaseline.jsononly with the maintainer's approval.node .claude/skills/sonarqube-scan/scripts/sonar-scan.mjs
5. Stop and get human approval (mandatory)
Before tagging, show the human the checker report and a short summary:
- Version:
vPREV → vNEXT(required bump / actual bump) - Breaking changes: each one with who is affected and the migration path. If there are none, say so explicitly.
- Behaviour changes the checker flagged for review (agent-view, HTML or Markdown-export diffs, new warnings, changed defaults), with your assessment of each.
- New features.
- Tests: pass counts for unit and VS Code integration tests.
- Static analysis: the SonarQube gate result and metrics, plus any suppressions or baseline changes made in this release (sonarqube-scan skill, "Reporting").
Don't proceed until the human approves in chat. For a major release, get approval for each breaking change individually.
6. Tag the release branch; the Release workflow builds, releases and publishes
Tag the head of the release branch (the exact commit that ships) and push the tag. Pushing the tag publishes, so do it only after the human's approval in §5:
git tag -a vX.Y.Z origin/release/vX.Y.Z -m "Semantic Markdown X.Y.Z" && git push origin vX.Y.ZThe tag starts
.github/workflows/release.yml. Its logic lives in small tested scripts inextension/scripts/release/:Job What it does verify check-versions.mjs: the tag equals the version inextension/package.json,package-lock.json,npm/package.json,integrations/mkdocs/pyproject.toml,integrations/obsidian/manifest.json,.claude-plugin/plugin.jsonandserver.json(its version and its npm package's); the CHANGELOG has a non-empty## X.Y.Zsection; the tagged commit is onmainor arelease/*branch. Then typecheck and unit tests.build .vsix(npm run package), npm.tgz(npm run build:npm,npm pack) skill zips (zip -r), the playground zip (npm run build:playground) the MkDocs plugin wheel and sdist (python -m build integrations/mkdocs) the Obsidian plugin zip (main.js,manifest.json,styles.cssfromintegrations/obsidian) and the JetBrains plugin zip (./gradlew buildPlugininintegrations/jetbrains, with Java 21; it ships the tag'ssmd.cjs). Checks they are real zips with the LICENSE and the right version, and thatskills/*/scripts/smd.cjsmatch a fresh build. Notes:changelog-excerpt.mjs --downloads(downloads table + the changelog section). All uploaded as therelease-assetsworkflow artifact.github-release Creates the GitHub Release with those notes and the nine assets (the .vsix, the.tgz, both skill zips,semantic-markdown-playground.zip, the MkDocs plugin wheel and.tar.gz,semantic-markdown-obsidian-X.Y.Z.zipand, since 2.1.0,semantic-markdown-jetbrains-X.Y.Z.zip). If the release already exists, it keeps its notes and attaches only missing assets. Verifies the release lists all nine.publish-marketplace, publish-openvsx, publish-npm, publish-pypi Publish the exact .vsix/.tgz/ wheel and sdist attached to the release (vsce publish --packagePath,ovsx publish,npm publish --provenance,twine uploadwithPYPI_TOKEN), then poll the registry until it lists X.Y.Z (wait-for-version.mjs).publish-jetbrains Uploads the exact JetBrains plugin zip attached to the release to the JetBrains Marketplace ( upload-jetbrains.mjs, plugin 35420, withJETBRAINS_TOKEN). JetBrains reviews each upload by hand, so the job doesn't wait for the listing; an upload of a version the Marketplace already has counts as done.Each publish job skips with a notice (a green job, not a failure) on a dry run, while its secret is missing, or when the registry already lists the version (
publish-gate.mjs). So re-running is safe: Actions → Release → Run workflow with the tag and dry run unticked finishes only what is missing, e.g. after adding a secret or when a registry was slow.- To rehearse, run the workflow by hand with an existing tag and dry run ticked (the default): it verifies, builds and checks every artifact and shows the release notes in the job summary, but creates no release and publishes nothing. A manual run uses the scripts at the tag, so it works for tags from v1.5.0 on.
- Watch it with
gh run watch(orgh run list --workflow release.yml) and read the notices of the publish jobs.
7. Verify each registry (the human holds the credentials)
Never ask for, type, paste or store tokens yourself. Only report something as published after the registry itself shows the new version. If a listing isn't live (its job skipped or failed), say so plainly and don't update docs to point at it.
| Where | Verify (don't trust the workflow's output alone) |
| GitHub release | gh release view vX.Y.Z lists 4 assets (.vsix, .tgz, two skill zips) |
| VS Code Marketplace | npx vsce show bislink360.semantic-markdown shows X.Y.Z (verification can take a few minutes) |
| Open VSX | curl -s https://open-vsx.org/api/bislink360/semantic-markdown/X.Y.Z returns that version |
| npm | npm view semantic-markdown@X.Y.Z version returns X.Y.Z |
| JetBrains Marketplace | node extension/scripts/release/wait-for-version.mjs jetbrains X.Y.Z --attempts 1 passes once JetBrains has approved the upload (it can take a few days; until then the plugin page lists no update) |
One-time setup, done by the maintainer. Until a secret exists its publish job skips, and releases stay GitHub-only as before. Add each one in GitHub → Settings → Secrets and variables → Actions → New repository secret, or with gh secret set NAME (it prompts for the value, so the token never lands in shell history):
| Secret | How to create it |
VSCE_PAT | Sign in to dev.azure.com with the account that owns the bislink360 publisher (marketplace.visualstudio.com/manage) → User settings → Personal access tokens → New token: Organization All accessible organizations, scope Marketplace → Manage, an expiry you track. |
OVSX_PAT | Sign in to open-vsx.org with GitHub, link an Eclipse account and sign the Publisher Agreement (profile page), then Settings → Access Tokens → Generate. Create the bislink360 namespace once from your own shell: npx ovsx create-namespace bislink360 (reads the token from OVSX_PAT). Optionally claim the namespace (EclipseFdn/open-vsx.org issue) for the verified badge. |
NPM_TOKEN | On npmjs.com, as the account that will own semantic-markdown (with 2FA) → Access Tokens → Generate New Token → Granular: read and write, packages semantic-markdown (the very first publish needs "all packages" until the package exists; narrow it afterwards), bypass 2FA for automation, an expiry you track. |
PYPI_TOKEN | On pypi.org, as the account that will own mkdocs-semantic-markdown (with 2FA) → Account settings → API tokens → Add API token (the very first upload needs an account-wide token until the project exists; replace it with a token scoped to mkdocs-semantic-markdown afterwards). |
JETBRAINS_TOKEN | On plugins.jetbrains.com, signed in with the JetBrains account that develops plugin 35420 → profile → My Tokens → Generate Token (permanent tokens; revoke and replace it if it leaks). The first version was uploaded by hand; the job uploads every release after that. |
The publish jobs run in the release GitHub environment (created on first use). Add required reviewers to it to approve every publish, and store the secrets as environment secrets there if you want them scoped to publishing. An expired token fails its job: update the secret and re-run the workflow for the tag.
Manual fallback (the workflow is unavailable). Build from the tag in a separate worktree: npm run package (→ .vsix), npm run build:npm then npm pack in npm/ (→ .tgz), skill zips from skills/, and semantic-markdown-playground.zip from npm run build:playground (zip the playground folder in extension/dist/) — on Windows with C:\Windows\System32\tar.exe -a -c -f <name>.zip <folder> (Git Bash's tar writes a tar file named .zip; check with file *.zip), elsewhere with zip -r. Notes: node extension/scripts/release/changelog-excerpt.mjs X.Y.Z --downloads -o notes.md. Publish in this order, only with credentials already present on the machine (npx vsce ls-publishers lists bislink360, npm whoami succeeds); otherwise stop and give the human the exact command:
| Step | Command |
| GitHub release | gh release create vX.Y.Z --verify-tag --title "Semantic Markdown X.Y.Z" --notes-file notes.md <vsix> <tgz> <skill zips> |
| VS Code Marketplace | cd extension && npx vsce publish --packagePath semantic-markdown-X.Y.Z.vsix |
| Open VSX | npx ovsx publish semantic-markdown-X.Y.Z.vsix (token from OVSX_PAT) |
| npm | cd npm && npm publish |
Then verify each one as in the table above.
8. After publishing
- Merge the release branch into
main: merge the tracking PRrelease/vX.Y.Z → mainwith a merge commit (never squash), so the tagged commit is inmain's history. Then delete the release and feature branches, and mergemaininto any other open release branch (version-control skill §5). - Confirm the README badges and install instructions resolve. Push doc changes that point at the new version only after all registries show it.
- If a release is bad, don't unpublish. Ship a patch train from the tag (
plan-release.mjs X.Y.Z+1 fix/<slug> --base vX.Y.Z). For npm,npm deprecate semantic-markdown@X.Y.Z "<reason>"warns installers.
References
references/compatibility.md— the breaking-change catalogue per surface, and the compatible alternatives. Read it before designing any change.references/versioning.md— semver rules for this repository, spec-version policy and deprecation timeline.references/branching.md— branch naming, commit conventions, PR checklist, merge and tag rules.- sonarqube-scan skill — the local SonarQube static-analysis gate required before every release.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

