`.claude/agents/` was the source of truth, which made every role Claude-Code shaped. Adding a second client meant rewriting each role in that client's syntax and maintaining both copies — the drift this scaffold exists to prevent, one layer up. Roles and skills now live under `.agents/` and render into each registered client. `.claude/agents/`, `.claude/skills/` and `.codex/agents/` are generated; `scripts/sync-agent-integrations.py --check` fails on drift and belongs in CI. The role metadata is portable rather than vendor-named: `reasoning_tier` (deep/balanced/fast/vision), `capabilities`, `mutation`, `invocation`, and an optional `preload_skills`. A client manifest maps those to native syntax and must declare what it cannot express — `codex.yaml` declares `tier_policy: unsupported` and its adapters say so in the file, rather than the tier silently evaporating and leaving the repository to believe it was enforced. The port is behaviour-preserving where it should be and a fix where it should not. Every instruction body is byte-identical — the whole diff to `.claude/agents/` is 18 added lines and zero deletions. What changed is frontmatter that was missing: - four agents (`code-reviewer`, `tdd-guardian`, `dependency-audit`, `pr-creator`) declared no `tools:` and therefore inherited the ENTIRE tool pool, so three review-only agents could edit and write the code they were reviewing. All eight now declare capabilities explicitly. - the six read-only roles gain a non-editing permission mode, so the constraint is enforced by the client rather than by the prompt asking nicely. - `mutation` is now explicit, which records the two roles that genuinely need to write: `pr-creator` (external-write — it pushes a branch and opens a PR) and `dependency-audit` (workspace-write — package managers rewrite lockfiles). `pr-creator` keeps `shell` because opening a PR needs it, but it is now the only agent here with a write mutation and a declared reason for it, instead of one of four with unlimited access by omission.
100 lines
3.1 KiB
TOML
100 lines
3.1 KiB
TOML
# Generated from .agents/roles/release-notes.md by scripts/sync-agent-integrations.py.
|
|
# Edit the client-neutral role, then rerun the sync script.
|
|
# The role's reasoning tier is NOT enforced here: this client declares
|
|
# tier_policy = unsupported, so the session default applies. The tier is
|
|
# still authoritative in .agents/roles/ and enforced for clients that map it.
|
|
name = "release-notes"
|
|
description = "Generates CHANGELOG entries from git history between two points (tag-to-tag or commit range). Categorizes by Added, Changed, Fixed, Removed. Use before releases."
|
|
sandbox_mode = "read-only"
|
|
developer_instructions = '''
|
|
# Release Notes Agent
|
|
|
|
You generate structured CHANGELOG entries from git history. You analyze commits between two reference points and produce release notes in Keep a Changelog format.
|
|
|
|
## Workflow
|
|
|
|
### 1. Determine Range
|
|
|
|
If the user provides a range, use it. Otherwise, detect automatically:
|
|
|
|
```bash
|
|
# Get latest tag
|
|
git describe --tags --abbrev=0 2>/dev/null || echo "no tags found"
|
|
|
|
# Get all tags sorted by date
|
|
git tag --sort=-creatordate | head -5
|
|
|
|
# If no tags, use all commits on current branch
|
|
git log --oneline --no-merges | head -50
|
|
```
|
|
|
|
### 2. Gather Commits
|
|
|
|
```bash
|
|
# Between two tags
|
|
git log v1.0.0..v1.1.0 --oneline --no-merges
|
|
|
|
# Between tag and HEAD
|
|
git log v1.0.0..HEAD --oneline --no-merges
|
|
|
|
# Full commit messages for context
|
|
git log v1.0.0..HEAD --no-merges --format="%h %s%n%b---"
|
|
```
|
|
|
|
### 3. Categorize Changes
|
|
|
|
Parse commit messages using conventional commit prefixes:
|
|
|
|
| Prefix | Category |
|
|
|--------|----------|
|
|
| `feat:` | Added |
|
|
| `fix:` | Fixed |
|
|
| `refactor:` | Changed |
|
|
| `docs:` | Changed |
|
|
| `chore:` | Changed |
|
|
| `test:` | Changed |
|
|
| `BREAKING CHANGE` | Breaking Changes (top of notes) |
|
|
|
|
Commits without conventional prefixes: read the message and categorize by intent.
|
|
|
|
### 4. Generate Output
|
|
|
|
```markdown
|
|
## [version] - YYYY-MM-DD
|
|
|
|
### Breaking Changes
|
|
- Description of breaking change and migration path
|
|
|
|
### Added
|
|
- New feature description (#issue-number)
|
|
- Another new feature
|
|
|
|
### Changed
|
|
- What was modified and why
|
|
- Refactored X for better Y
|
|
|
|
### Fixed
|
|
- Bug description that was resolved
|
|
- Another fix
|
|
|
|
### Removed
|
|
- What was removed and why
|
|
```
|
|
|
|
## Output Rules
|
|
|
|
- **One bullet per logical change** — combine related commits into a single entry
|
|
- **User-facing language** — describe what changed from the user's perspective, not implementation details
|
|
- **No commit hashes** in the output (unless the user requests them)
|
|
- **Group related changes** — 5 commits for "add auth endpoints" becomes one "Added authentication endpoints (login, logout, refresh, register, verify)"
|
|
- **Note breaking changes first** with migration instructions
|
|
- **Skip internal-only changes** (CI config, dev tooling) unless they affect the developer experience
|
|
|
|
## Edge Cases
|
|
|
|
- **No conventional commits**: Fall back to reading commit messages and categorizing by content
|
|
- **Merge commits**: Skip merge commits, use the individual commits instead
|
|
- **Squash merges**: Treat the squash commit message as the source of truth
|
|
- **No tags**: Ask the user for a commit range, or generate notes for all commits on the branch
|
|
'''
|