The Gitea issue body is the single source of truth for a spec; the only per-feature artifact in git is the RTM row (REQ-ID -> issue # -> test). Drops per-feature spec.md/tasks.md/checklist files from the workflow (the _example stays as a template/reference). Updates the guide, ADR-041, AGENTS.md, CLAUDE.md, templates, the RTM (adds an Issue column), the implement/review-pr skills, and replaces the file-spec CI jobs with an rtm-check. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
90 lines
4.1 KiB
Markdown
90 lines
4.1 KiB
Markdown
<!--
|
||
Feature Spec template — paste this into the Gitea issue body (issue-only: this IS the spec;
|
||
there is no committed spec.md). The .gitea/ISSUE_TEMPLATE/feature.md mirror gives the same
|
||
structure with the right labels. Replace every <placeholder>. Delete this comment before submitting.
|
||
EARS = Easy Approach to Requirements Syntax. Every requirement uses one of the five patterns
|
||
shown in ## Requirements and carries a unique REQ-NNN id (three-digit, scoped to THIS feature).
|
||
Use plain code-path references (not relative markdown links) — links don't resolve inside a Gitea issue.
|
||
-->
|
||
|
||
# <Feature title — match the Gitea issue: "As a <role> I want <capability> so <reason>">
|
||
|
||
## Context & Why
|
||
|
||
<Business motivation in 2–4 sentences: who needs this and why now.>
|
||
|
||
Constitution principles this feature depends on (see `.specify/constitution.md`):
|
||
- §<n> <principle name> — <why it applies>
|
||
|
||
Related: <links to prior issues / ADRs>.
|
||
|
||
## User Journey
|
||
|
||
<Plain-prose steps the user takes to get value, from the user's perspective — per COLLABORATING.md. Anything not in this journey is out of scope.>
|
||
|
||
## Requirements
|
||
|
||
> One requirement per line, each with a `REQ-NNN` id and one EARS pattern. Include the
|
||
> patterns the feature actually needs — do not force all five, but a mutating feature almost
|
||
> always needs at least one Event-driven and one Unwanted-behavior requirement.
|
||
|
||
- **REQ-001** (Ubiquitous) — The `<system component>` shall `<always-true behavior>`.
|
||
- **REQ-002** (Event-driven) — When `<trigger / endpoint receives X>`, the `<system component>` shall `<response>`.
|
||
- **REQ-003** (State-driven) — While `<system is in state X>`, the `<system component>` shall `<behavior>`.
|
||
- **REQ-004** (Optional-feature) — Where `<the caller has Permission.X / a feature flag is set>`, the `<system component>` shall `<behavior>`.
|
||
- **REQ-005** (Unwanted-behavior) — If `<undesired condition, e.g. caller is unauthenticated / input invalid>`, then the `<system component>` shall `<safe response, e.g. return 401 / ErrorCode.X>`.
|
||
|
||
## Acceptance Criteria
|
||
|
||
> One measurable criterion per REQ-NNN. Numbers, limits, status codes — never adjectives.
|
||
|
||
- **REQ-001** — <measurable, e.g. "the response always includes a non-null `id` (UUID)">.
|
||
- **REQ-002** — <measurable, e.g. "POST returns 201 and the persisted row within the same request">.
|
||
- **REQ-003** — <measurable>.
|
||
- **REQ-004** — <measurable, e.g. "a caller without Permission.X receives 403 with ErrorCode.FORBIDDEN">.
|
||
- **REQ-005** — <measurable, e.g. "an unauthenticated request receives 401 and nothing is persisted">.
|
||
|
||
## Out of Scope
|
||
|
||
- <Explicit boundary statement — the nearest tempting scope creep, named and excluded.>
|
||
- <…>
|
||
|
||
## API / Contract Stub
|
||
|
||
<Inline OpenAPI stub. Name the new/changed paths, methods, request/response shapes, status codes, and `@RequirePermission`. Use the `.specify/templates/api-contract-stub.md` skeleton as a writing aid.>
|
||
|
||
## Data Model Changes
|
||
|
||
<Entity/schema delta: new tables/columns, constraints, the next free Flyway `V<n>`, and the rollback note. Write "none" if not applicable.>
|
||
|
||
## Security Considerations
|
||
|
||
<STRIDE categories touched (Spoofing/Tampering/Repudiation/Information disclosure/DoS/Elevation). For AI-agent/tool features, also ASTRIDE. Include an inline STRIDE table (use `.specify/templates/threat-model.md`) if the feature has a non-trivial attack surface.>
|
||
|
||
## Open Questions
|
||
|
||
> Each item is a BLOCKER until resolved. Empty this list before implementation starts.
|
||
|
||
- [ ] <question> — owner: <name>
|
||
- [ ] <question> — owner: <name>
|
||
|
||
## Traceability
|
||
|
||
| REQ-ID | Task ID(s) | Test ID(s) | Status |
|
||
|---|---|---|---|
|
||
| REQ-001 | <T-1> | <test name> | Planned |
|
||
| REQ-002 | <T-2> | <test name> | Planned |
|
||
|
||
<After approval, add one committed row per REQ-NNN to `.specify/rtm.md` with this issue's number. Fill Task/Test IDs as work progresses.>
|
||
|
||
## Persona Review Results
|
||
|
||
| Persona | Status | Key Findings | Resolved |
|
||
|---|---|---|---|
|
||
| Requirements Engineer | PENDING | | |
|
||
| Developer | PENDING | | |
|
||
| Security | PENDING | | |
|
||
| DevOps | PENDING | | |
|
||
| UI/UX | PENDING | | |
|
||
| Architect | PENDING | | |
|