Versioning
- Keep version updates in sync across all four canonical version files:
pyproject.toml,setup.py,src/__init__.py, andsrc/specfact_cli/__init__.py. - Automated check: Before tagging or publishing, run
hatch run check-version-sources(orpython scripts/check_version_sources.py). It exits non-zero with a clear diff ifpyproject.toml,setup.py,src/__init__.py, andsrc/specfact_cli/__init__.pydisagree. The Tests job in.github/workflows/pr-orchestrator.ymlruns the same script so mismatches fail CI. Pre-commit runs it whenever a version file is staged (see thecheck-version-sourceshook in.pre-commit-config.yamlandscripts/pre-commit-quality-checks.sh) instead of treating version-only commits as “safe” without verification. - PyPI ahead-of check: Run
hatch run check-pypi-ahead(orpython scripts/check_local_version_ahead_of_pypi.pywithout flags) for a strict compare to PyPI. CI and pre-commit pass--skip-when-version-unchanged-vs(merge base on PRs, previous commit on pushes,HEADin pre-commit) so touchingpyproject.tomlfor dependencies only does not query PyPI whenproject.versionis unchanged; when the declared version does change relative to that revision, the check still requires local strictly greater than PyPI (matching.github/workflows/scripts/check-and-publish-pypi.sh). CI runs the step in the Tests job aftercheck_version_sources, only when the PR changes canonical version files (pyproject.toml,setup.py,src/__init__.py,src/specfact_cli/__init__.py— same idea as the pre-commit hook’sfiles:filter). For offline work only,SPECFACT_SKIP_PYPI_VERSION_CHECK=1skips the check (do not use in CI). hatch run releaseis reserved for maintainers to chaincheck-version-sourcesbefore manual release steps; extend that script if you add more release automation.feature/*branches imply a minor bump,bugfix/*andhotfix/*imply a patch bump, and major bumps require explicit confirmation.
Changelog
- Update
CHANGELOG.mdin the same commit as the version bump. - Follow Keep a Changelog sections:
Added,Changed,Fixed,Removed,Security.
Commits
- Use Conventional Commits.
- If signed commits fail in a non-interactive shell, stage files and hand the exact
git commit -S -m "<message>"command to the user instead of bypassing signing.
Documentation and README
- Keep docs current with every user-facing behavior change.
- Preserve all Jekyll frontmatter on docs edits.
- Update navigation when adding or moving pages.
- Keep
README.mdand the docs landing page aligned with what SpecFact actually does.
Internal wiki (sibling specfact-cli-internal)
After merging changes that affect OpenSpec or GitHub-linked planning, and when a sibling specfact-cli-internal checkout is available, run the wiki scripts only after cd into that internal repo so the working directory matches what the scripts expect (running from specfact-cli or elsewhere will break them). From this repo’s root, for example:
cd ../specfact-cli-internal && python3 scripts/wiki_openspec_gh_status.py
If the change touched lots of docs frontmatter (especially under docs/agent-rules/), also run:
cd ../specfact-cli-internal && python3 scripts/wiki_rebuild_graph.py
When you materially edit an active OpenSpec change (scope, design, tasks story or dependencies), also update the mirrored wiki/sources/<change-id>.md in the sibling internal repo when it is available, then run wiki_rebuild_graph.py as in 40-openspec-and-tdd.md. If the internal checkout is missing, record a merge checklist or follow-up instead of assuming the wiki is current.
See Internal wiki maintenance under 40-openspec-and-tdd.md.