Cadence
| Window | Promise |
|---|---|
| First 90 days post-v1.0 (2026-05-27 → 2026-08-25) | A release every Tuesday at 18:00 UTC, even if the only change is a documentation fix. |
| Steady state (day 91+) | Release whenever ## [Unreleased] in CHANGELOG.md accumulates user-visible changes, at minimum once per month. |
| Security fixes | Out-of-cycle on the day the patch is ready. Tracked in SECURITY.md. |
MAINTAINERS.md.
What triggers a release
We cut a release when either condition is true:## [Unreleased]inCHANGELOG.mdhas at least one bullet, and it is a Tuesday during the first-90-days window.- A security fix is ready (any day, any week).
How a release is cut
The release manager runs:scripts/release.sh does five things and refuses to do anything else:
- Validates the working tree is clean and on
main. - Bumps
src/agent_guardian/_version.py(hatch’s version source). - Promotes
## [Unreleased]to## [<version>] — <date>inCHANGELOG.mdand inserts a fresh empty## [Unreleased]stub. - Creates a DCO-signed commit (
chore(release): v<version>). - Creates an annotated tag
v<version>whose body is the new changelog section.
.github/workflows/publish.yml,
which builds the wheel + sdist reproducibly, generates a CycloneDX
SBOM, signs every artifact with Sigstore, and publishes to PyPI via
Trusted Publishing — no
long-lived API tokens. The GitHub Release is created with the signed
artifacts attached; the release manager pastes the changelog body into
the Release notes textarea after the workflow goes green.
Changelog conventions
We follow Keep a Changelog and Semantic Versioning 2.0.Section headings
| Heading | Means |
|---|---|
### Added | New user-visible feature. |
### Changed | User-visible behaviour change that is not a bug fix. |
### Deprecated | Still works, scheduled for removal. |
### Removed | Removed in this release (was previously deprecated). |
### Fixed | Bug fix. |
### Security | Security fix. Link the advisory. |
Bullet style
During the M2 architecture push we wrote multi-paragraph bullets because they documented foundational work. Steady-state weeks should not ship that volume. The rule is:- One to two sentences per bullet. First sentence: what changed. Second sentence: why it matters to a user.
- Link the PR or commit. Format:
[#123](https://github.com/glacien-technologies/agent-guardian/pull/123). - Reference the test that locks it in, e.g.
tests/unit/test_thing.py::test_specific_case.
CHANGELOG.md.
Semver policy
| Change | Bump |
|---|---|
| Bug fix, docs fix, test-only change, dependency pin within a compatible range | PATCH (1.1.0 → 1.1.1) |
| New CLI flag, new public Python API, new probe, new agent, new report format | MINOR (1.1.0 → 1.2.0) |
| Removed or renamed CLI flag, removed Python API, breaking SARIF schema change, behaviour change that breaks a documented invariant | MAJOR (1.1.0 → 2.0.0) |
smart to full is the
reference case — it landed as a minor only because the prior default
was not yet documented as stable.
Issue-response SLA
During the first-90-days window we promise:- Acknowledgement within 48 hours, Monday–Friday UTC. “Acknowledgement” means a maintainer has commented on the issue with either a triage label, a reproduction question, or a fix ETA. It does not mean the bug is fixed.
- One human comment per week on every open issue, even if the comment is “still investigating.” Silence past seven days is a process failure, not a busy week.
- Critical and security issues are acknowledged within 24 hours,
any day. Use the private vulnerability-report channel in
SECURITY.mdfor anything you would not want public.
.github/workflows/stale-issue-responder.yml
workflow enforces the back half of this promise mechanically:
- After 21 days with no maintainer comment, the bot posts an
acknowledgement and applies the
stalelabel. - After a further 21 days with no further activity, the bot closes the issue with a pointer back to Discussions.
- Issues labelled
pinned,critical,security, ortrackedare exempt from both steps.
Where this is reported
- The “Project Status: Active” badge in the repo README is the at-a-glance signal.
- PyPI’s release history is the audit log.
- GitHub Releases carries the signed artifacts.
- The current on-call release manager is in
MAINTAINERS.md.