Versioning & Release Strategy
September 14, 2026 · View on GitHub
Semantic Versioning
This project follows Semantic Versioning (SemVer): MAJOR.MINOR.PATCH
- MAJOR: Backward-incompatible protocol or contract changes (tool method response shape, removed fields).
- MINOR: Backward-compatible feature additions (new tools, new optional response fields) or performance improvements.
- PATCH: Backward-compatible bug fixes; documentation-only changes may share a patch bump when releasing other fixes; docs-only can aggregate until next functional release.
Pre-1.0.0 Policy:
- MINOR increments can include limited breaking changes with strong justification; avoid when possible.
- PATCH increments never introduce breaking changes.
Tool Contract Stability Labels
- experimental: Subject to change; no stability guarantee (default pre-1.0 tools unless promoted).
- stable: Version-locked; breaking changes require MAJOR bump (or MINOR while <1.0 with deprecation notice).
Promotion Path: experimental -> stable (after: test coverage, schema, documented examples, usage in at least 1 integration).
Changelog Conventions
CHANGELOG.md entries grouped per version with date (UTC) and categories:
- Added
- Changed
- Fixed
- Deprecated
- Removed
- Security
Example skeleton:
## [0.2.0] - 2025-08-24
### Added
- New tool: usage_track
### Fixed
- Handle invalid JSON gracefully in loader.
Release Workflow (Canonical Private/Public Flow)
This repository has two distinct Git remotes:
origin- internal development repositorypublic- public mirror repository (jagilber-org/index-server)
The canonical release flow is:
- Start from a clean local
mainsynced withorigin/main. - Decide increment: patch | minor | major.
- Update
package.jsonandCHANGELOG.md.- Preferred bump helper:
node scripts/build/bump-version.mjs patch(orminor/major). - The helper creates the internal release commit and local tag.
- Preferred bump helper:
- Start the canonical release/publish front door.
pwsh -NoProfile -File scripts\Invoke-ReleaseWorkflow.ps1 -DryRun- Review the resolved tag, sanctioned public remote, clean-room path, and planned delivery command.
- Run the release/publish front door for the actual release preparation.
pwsh -NoProfile -File scripts\Invoke-ReleaseWorkflow.ps1 -PushInternal- This runs preflight checks, pushes the internal release branch/tags, verifies refs, waits for internal GitHub Actions checks, builds, deploys locally, prepares the clean-room public snapshot, and prints the human-only public mirror command.
- Publish the public mirror after human review.
- Preferred: run the printed
scripts\Publish-ToMirror.ps1 -CreatePR -WaitForMergecommand, or have a human rerunscripts\Invoke-ReleaseWorkflow.ps1 -CreatePR -WaitForMerge. - If
-WaitForMergetimes out but the PR is merged later, rerun the same command. The script reuses the existing merged PR for the publish branch when the content hash matches and resumes tag creation. - Alternative:
node scripts/publish-direct-to-remote.cjs --tag vX.Y.Z --create-release
- Preferred: run the printed
- Verify both sides.
- Confirm
originandpublicboth containvX.Y.Z. - Confirm the public GitHub release exists and the local repo is back on clean
main.
- Confirm
MCP Registry auth note
The release workflow executes from the internal repo context, so MCP Registry publish should currently be treated as a PAT-authenticated step there via MCP_GITHUB_TOKEN.
GitHub OIDC is only the expected path when the workflow itself runs from the public mirror (jagilber-org/index-server). Until that execution model changes, do not assume OIDC will activate for internal-repo tag releases.
When PAT fallback is required, keep MCP_GITHUB_TOKEN scoped only to the MCP Registry publish action rather than broader repository administration.
Canonical Commands
git checkout main
git pull --ff-only origin main
node scripts/build/bump-version.mjs patch
pwsh -NoProfile -File scripts\Invoke-ReleaseWorkflow.ps1 -DryRun
pwsh -NoProfile -File scripts\Invoke-ReleaseWorkflow.ps1 -PushInternal
# Human-only after clean-room review:
pwsh -NoProfile -File scripts\Publish-ToMirror.ps1 -SourcePath '<clean-room-path>' -RemoteUrl '<public-mirror-url>' -Tag vX.Y.Z -CreatePR -WaitForMerge
Replace X.Y.Z with the version created by the bump step.
For the PR-based path, the public Release workflow is triggered by creating refs/tags/vX.Y.Z on the public mirror. Do not separately run gh release create for that tag; .github/workflows/release.yml owns GitHub Release creation.
Public Publish Alternatives
The underlying two-step PowerShell workflow remains available for manual review-oriented publication flows:
scripts/New-CleanRoomCopy.ps1— safe content preparation with-DryRunto inspect what would be publishedscripts/Publish-ToMirror.ps1— remote delivery with-CreateReviewRepofor team review or-DirectPublishfor direct mirror publication
Use scripts\Invoke-ReleaseWorkflow.ps1 for the standard release path so preflight, internal push/check verification, local deploy, clean-room preparation, and public handoff stay ordered consistently.
Removed Legacy Path
Publish-ToPublicRepo.ps1 has been removed. Use the two-step workflow above (New-CleanRoomCopy.ps1 + Publish-ToMirror.ps1) directly.
Scope Note
The canonical release process documented here covers the internal GitHub repo and the public mirror repo. If npm package publication is added as part of release, document that flow separately with its required credentials, validation gates, and rollback steps.
MCP marketplace migration tracking
Marketplace migration remains a staged release-governance effort rather than a one-shot cutover:
- Stage 1 (current baseline) — publishable npm package, MCP Registry metadata, MCP-native-first docs, release workflow support, and a clearly deprecated VSIX fallback.
- Stage 2 (follow-up) — only remove the VSIX path after registry installation, release flow, and any required parity work are validated.
Current guidance:
- Assume internal-repo releases use
MCP_GITHUB_TOKENPAT fallback for MCP Registry publication. - Keep the legacy VSIX path documented only as a fallback, not as the default release/install story.
- Track remaining migration follow-ups in issue #108 (prompts/resources). Issue #109 (pre-existing
build:verifyfailures) was closed on 2026-04-26; this line asked readers to track a closed issue until #591.
Automation Roadmap
- Validate no uncommitted changes before bump.
- Auto-generate changelog section from conventional commit messages since last tag.
- Pre-release channels (alpha, beta, rc) using metadata suffixes.
- GitHub Action: publish on tag push, attach build artifacts.
Breaking Change Process (Pre-1.0)
- Mark field/tool as deprecated in documentation & responses (e.g., add
deprecated: true). - Provide alternative for at least one MINOR release window.
- Remove in subsequent MINOR (pre-1.0) or next MAJOR (post-1.0).
Integrity with Version Bumps
- Integrity / diff algorithms must maintain backward compatibility for at least one MINOR after upgrade.
- Provide dual-mode diff output behind feature flag before promoting to default.
Version Source of Truth
package.json "version" key is canonical. Scripts or runtime may emit this in health_check.
Current Release Line
Use package.json and CHANGELOG.md as the live release sources of truth. Do not hardcode the current version in this document.
Governance Version Semantics (Post 1.1.0 Enhancements)
Strict SemVer Enforcement (Create & Update)
All supplied version values on index_add (create or overwrite) must match full SemVer MAJOR.MINOR.PATCH optionally with pre-release/build metadata. Malformed versions (e.g., 1.0, 2, 1.0.0+bad+extra) are rejected with error: invalid_semver.
Rationale:
- Prevents non-linear version lineage that complicates deterministic governance hashing.
- Ensures changeLog entries map 1:1 to a valid semantic version.
Auto Patch Bump Logic
If body content changes and caller omits a version, server auto-increments PATCH. ChangeLog entry summary includes an auto-bump note. Body change with same or lower explicit version -> version_not_bumped error.
Metadata-Only Overwrite Hydration
When overwrite:true and the caller omits body (and optionally title), server hydrates existing body/title from the on-disk record before validation. This allows governance-only edits (priority, owner, classification, version bump) without resending full content.
Implications:
- Returned flags:
overwritten:truewhen existing record modified even if body unchanged. - Clients should still supply an explicit higher version for metadata-only semantic changes; omission defers bump logic to body change rules.
Instruction Schema v6 Content-Type Taxonomy
Instruction schema v6 defines the canonical contentType enum as agent,
skill, instruction, prompt, workflow, knowledge, template, and
integration. Runtime input validation, search filters, and tool schemas use
the same enum. Records with values outside the canonical taxonomy fail
validation and are handled by the existing rejection/quarantine paths.
ChangeLog Repair & Normalization
Malformed changeLog arrays (wrong shapes, missing fields) are silently repaired:
- Invalid entries dropped.
- Missing initial entry synthesized from current version.
- Ensures final element corresponds to authoritative version.
Overwrite Flag Accuracy
overwritten:true now reflects any successful overwrite intent where the record existed pre-call (including metadata-only version increments). This improves mutation telemetry reliability for governance analytics.
Client Guidance Summary
| Scenario | Provide Version? | Provide Body? | Outcome |
|---|---|---|---|
| First create | Optional (default 1.0.0) | Required | Created 1.0.0 |
| Body edit, no version | Omitted | New body | Auto bump PATCH |
| Body edit, same version | Same | New body | Error: version_not_bumped |
| Metadata-only change, higher version | Higher | Omitted | Hydrate + overwrite |
| Metadata-only change, no version | Omitted | Omitted | No version bump; governance fields updated (no ChangeLog append) |
| Malformed version | Invalid | Any | Error: invalid_semver |