Spec-driven development on OpenSpec, with mechanical spec-as-source enforcement: a custom 'spec-as-source' OpenSpec schema adds file-ownership (targets) and test-verification ([@test]) metadata to every capability spec, three scripts (link check, ownership check, manifest build) keep code and specs from drifting apart, plus requirement-gathering, spec-writer, work-review, and a session-handoff skill with a proactive context-warning hook.
71
89%
Does it follow best practices?
Impact
—
No eval scenarios have been run
Advisory
Suggest reviewing before use
Create and maintain openspec/specs/<capability>/spec.md files that capture functional requirements, declare file ownership, and link to their verification tests — following the spec-as-source OpenSpec schema installed by spec-as-source-setup.
This is the focused, manual counterpart to the specs artifact that openspec-propose/openspec-apply-change generate as part of a full change. Use it directly when you need to write or fix a spec file outside a full change workflow (e.g. retrofitting targets:/**Verified by** onto a spec openspec archive created without frontmatter), or as the detailed reference for what a correct spec.md looks like.
requirement-gathering produces a confirmed requirements summary.targets: frontmatter (e.g. a capability openspec archive created fresh, per the known OpenSpec-core limitation) and needs one added.Determine scope. Decide whether to create a new capability or update an existing one. One spec per logical capability — don't combine unrelated features. New capability names are kebab-case (e.g. user-auth, data-export) and become openspec/specs/<name>/spec.md.
Write the frontmatter. Every spec.md starts with YAML frontmatter, before the title heading:
---
targets:
- src/path/to/implementation.py
- src/path/to/related/file.py
---targets: project-root-relative paths (not relative to the spec file) to every source file this capability is the authoritative source of truth for. Use targets: [] if the capability has no dedicated source files yet.Write (or confirm) the body structure. A capability spec is:
# <Capability> Specification
## Purpose
<!-- one or two sentences: why this capability exists -->
## Requirements
### Requirement: <name>
<!-- normative SHALL/MUST sentence -->
**Verified by**: [@test] <path/to/test/file>
#### Scenario: <name>
- **WHEN** <condition>
- **THEN** <expected outcome>When writing a delta spec inside a change (openspec/changes/<change>/specs/<capability>/spec.md), use OpenSpec's delta operations instead of the full body:
## ADDED Requirements — new requirements## MODIFIED Requirements — changed behavior, MUST include the full updated requirement block## REMOVED Requirements — deprecated, MUST include Reason and Migration## RENAMED Requirements — name changes only, FROM:/TO: formatFormat every requirement correctly:
### Requirement: <name> — free-text name, not an ID. Names must be unique within the capability.**Verified by**: [@test] <path/to/test/file>, project-root-relative. Multiple tests: additional **Verified by** lines, or space-separated on one line.#### Scenario: <name> — exactly 4 hashtags. 3 hashtags or bullets fail silently.MODIFIED requirements workflow (when changing existing behavior):
openspec/specs/<capability>/spec.md.## MODIFIED Requirements in the delta spec, edit to reflect new behavior.Using MODIFIED with partial content loses detail at archive/merge time. If you're adding a new concern without changing existing behavior, use ADDED instead.
Retrofitting a frontmatter-less spec. A capability spec created fresh by openspec archive has no targets: block (OpenSpec's built-in skeleton doesn't add one). The first time you touch such a spec non-trivially, add the targets: frontmatter per Step 2 — this is expected, not a bug to report.
Save the spec at openspec/specs/<capability>/spec.md (main spec) or openspec/changes/<change>/specs/<capability>/spec.md (delta spec inside an in-flight change).
---
targets:
- src/cart.py
- src/checkout.py
---
# Shopping Cart Specification
## Purpose
Manage adding, removing, and checking out items in a user's cart.
## Requirements
### Requirement: Add item to cart
The system SHALL allow a user to add a product to their cart with a quantity.
**Verified by**: [@test] tests/cart/test_add_item.py
#### Scenario: Adding a new item
- **WHEN** a user adds a product not already in the cart
- **THEN** the cart contains that product with the given quantity
#### Scenario: Adding an existing item
- **WHEN** a user adds a product already in the cart
- **THEN** the existing quantity is incremented, not duplicated
### Requirement: Reject invalid quantity
The system MUST reject a quantity of zero or less.
**Verified by**: [@test] tests/cart/test_quantity_validation.py
#### Scenario: Zero quantity rejected
- **WHEN** a user attempts to add a product with quantity 0
- **THEN** the system raises a validation error and the cart is unchangedA spec.md file that:
scripts/check-spec-links.sh (every [@test] path exists),scripts/check-target-ownership.sh (declares targets: for everything it owns),spec-verify to validate end-to-end once the implementation exists..tessl-plugin
skills
handoff
openspec-apply-change
openspec-archive-change
openspec-explore
openspec-propose
openspec-sync-specs
requirement-gathering
spec-as-source-setup
templates
openspec-schema
spec-as-source
templates
spec-ci-sync
spec-rebuild
spec-verify
spec-writer
work-review