Agent Spec Authoring
Version: 3.1.0 | Last Updated: 2026-03-08
You are an expert at writing agent-spec Task Contracts. Help users by:
- Creating specs: Scaffold new files with correct structure
- Editing specs: Improve intent, constraints, boundaries, scenarios
- Writing scenarios: BDD-style with proper test selectors and step tables
- Debugging specs: Fix lint warnings, improve quality scores
- Self-hosting: Maintain specs for the agent-spec project itself
Core Philosophy
A Contract is not a vague Issue — it's a precise specification that shifts the review point:
Traditional: Human reviews 500 lines of code diff (slow, error-prone)
agent-spec: Human writes 50-80 lines of Contract (fast, high-value)
Machine verifies code against Contract (deterministic)
Writing a Contract is the highest-value human activity in the agent-spec workflow. You're defining "what is correct" — the machine handles "is the code correct".
Quick Reference
| Section | Chinese Header | English Header | Purpose |
|---|
| Intent | | | What to do and why |
| Constraints | | | Must / Must NOT rules |
| Decisions | / | | Fixed technical choices |
| Boundaries | | | Allowed / Forbidden / Out-of-scope |
| Acceptance Criteria | / | / | BDD scenarios |
| Out of Scope | | | Explicitly excluded items |
Documentation
Refer to the local files for authoring patterns and examples:
- - Complete authoring patterns with examples
IMPORTANT: Documentation Completeness Check
Before answering questions, Claude MUST:
- Read for authoring patterns
- If file read fails: Inform user "references/patterns.md is missing, answering from SKILL.md patterns"
- Still answer based on SKILL.md patterns + built-in knowledge
Before Writing a Contract
Not every task needs a Contract. Ask yourself:
| Question | If No |
|---|
| Can I define what "done" looks like? | Vibe code first, write Contract later |
| Can I write at least one deterministic test? | Not Contract-ready yet |
| Is the scope bounded enough to list Allowed Changes? | Split into smaller tasks |
| Do I know the key technical decisions? | Do a spike/prototype first |
If all "yes" — proceed with authoring. If not, doing exploratory work first is the right call.
The Four Elements of a Contract
1. Intent — What and Why
One focused paragraph. Not a feature list — a clear statement of purpose.
spec
## Intent
为现有的认证模块添加用户注册 endpoint。新用户通过邮箱+密码注册,
注册成功后发送验证邮件。这是用户体系的第一步,后续会在此基础上
添加登录和密码重置。
Rules:
- Focus on "what to do and why"
- Mention context (what already exists, where this fits)
- Keep it to 2-4 sentences
2. Decisions — Fixed Technical Choices
Already-decided choices. Not aspirational. Not options to explore.
spec
## Decisions
- 路由: POST /api/v1/auth/register
- 密码哈希: bcrypt, cost factor = 12
- 验证 Token: crypto.randomUUID(), 存数据库, 24h 过期
- 邮件: 使用现有 EmailService,不新建
Rules:
- Only choices that are already fixed — not "we should consider..."
- Include specific technologies, versions, parameters
- Agent follows these without questioning — they're not open for debate
3. Boundaries — What to Touch, What Not to Touch
Triple constraint: Allowed, Forbidden, Out-of-scope.
spec
## Boundaries
### Allowed Changes
- crates/api/src/auth/**
- crates/api/tests/auth/**
- migrations/
### Forbidden
- 不要添加新的 npm/cargo 依赖
- 不要修改现有的登录 endpoint
- 不要在注册流程中创建 session
## Out of Scope
- 登录功能
- 密码重置
- OAuth 第三方登录
Rules:
- Path globs () are mechanically enforced by BoundariesVerifier
- Natural language prohibitions are checked by lint but not file-path enforced
- Out of Scope prevents scope creep — Agent knows what NOT to attempt
4. Completion Criteria — Deterministic Pass/Fail
BDD scenarios with explicit test bindings.
Critical principle: Exception scenarios >= happy path scenarios.
spec
## Completion Criteria
场景: 注册成功 ← 1 happy path
测试: test_register_returns_201
假设 不存在邮箱为 "alice@example.com" 的用户
当 客户端提交注册请求:
| 字段 | 值 |
| email | alice@example.com |
| password | Str0ng!Pass#2026 |
那么 响应状态码为 201
并且 响应体包含 "user_id"
场景: 重复邮箱被拒绝 ← exception path 1
测试: test_register_rejects_duplicate_email
假设 已存在邮箱为 "alice@example.com" 的用户
当 客户端提交相同邮箱的注册请求
那么 响应状态码为 409
场景: 弱密码被拒绝 ← exception path 2
测试: test_register_rejects_weak_password
假设 不存在邮箱为 "bob@example.com" 的用户
当 客户端提交密码为 "123" 的注册请求
那么 响应状态码为 400
场景: 缺少必填字段 ← exception path 3
测试: test_register_rejects_missing_fields
当 客户端提交缺少 email 字段的注册请求
那么 响应状态码为 400
This forces you to think through edge cases before coding begins. The Agent can't skip error handling because each exception path has a bound test.
Spec File Structure
Frontmatter (YAML)
spec
spec: task # Level: org, project, task
name: "Task Name" # Human-readable name
inherits: project # Parent spec (optional)
tags: [feature, api] # Tags for filtering
---
Three-Layer Inheritance
org.spec → project.spec → task.spec
| Layer | Scope | Example Content |
|---|
| Organization-wide | Coding standards, security rules, forbidden patterns |
| Project-level | Tech stack decisions, API conventions, test requirements |
| Single task | Intent, boundaries, specific acceptance criteria |
Constraints and decisions are inherited downward. Task specs inherit from project, which inherits from org.
BDD Step Keywords
| English | Chinese | Usage |
|---|
| | Precondition |
| | Action |
| | Expected result |
| | Additional step (same type as previous) |
| | Negative additional step |
Test Selector Patterns
Simple selector
spec
Scenario: Happy path
Test: test_happy_path
Given precondition
When action
Then result
Structured selector (cross-crate)
spec
Scenario: Cross-crate verification
Test:
Package: spec-gateway
Filter: test_contract_prompt_format
Given a task spec
When verified
Then passes
Chinese equivalents
spec
场景: 正常路径
测试: test_happy_path
场景: 跨包验证
测试:
包: spec-gateway
过滤: test_contract_prompt_format
Step Tables
For structured inputs, use tables instead of inventing custom prose:
spec
Scenario: Batch validation
Test: test_batch_validation
Given the following input records:
| name | email | valid |
| Alice | alice@test.com | true |
| Bob | invalid | false |
When the validator processes the batch
Then "1" record passes and "1" record fails
Boundary Patterns
Machine-enforced (path globs)
spec
### Allowed Changes
- crates/spec-parser/**
- tests/parser_contract.rs
BoundariesVerifier checks actual changed files against these globs.
Natural language prohibitions
spec
### Forbidden
- Do not break the existing JSON shape
- Do not introduce .unwrap()
Checked by lint, not mechanically enforced against file paths.
Use both when needed. Path globs for file-level control, natural language for behavioral prohibitions.
Common Errors
| Lint Warning | Cause | Fix |
|---|
| "handle", "manage", "process", "处理" | Be specific: "validate email format" not "handle email" |
| "fast", "efficient", "应该快速" | Add metrics: "respond within 200ms" not "respond quickly" |
| Steps that can't be mechanically verified | Use observable assertions: "returns error code X" |
| Constraint with no covering scenario | Add a scenario that exercises the constraint |
| Non-deterministic step wording | Remove "should", "might"; use definitive assertions |
| Missing selector on scenario | Add or structured block |
| Bug-finding bias language | Remove "find all bugs", "must find issues" |
Authoring Checklist
Before handing a Contract to an Agent, verify:
| # | Check | Why |
|---|
| 1 | Intent is 2-4 focused sentences | Agent needs clear direction, not a novel |
| 2 | Decisions are specific (tech, version, params) | Agent shouldn't be choosing technology |
| 3 | Boundaries have path globs for Allowed Changes | Enables mechanical enforcement |
| 4 | Exception scenarios >= happy path scenarios | Forces edge-case thinking upfront |
| 5 | Every scenario has a selector | Required for TestVerifier to run |
| 6 | Steps use deterministic wording | "returns 201" not "should return 201" |
| 7 | score >= 0.7 | Quality gate before Agent starts |
Deprecated Patterns (Don't Use)
| Deprecated | Use Instead | Reason |
|---|
| Scenarios without | Always add selector | Required for mechanical verification |
| Vague boundaries like "be careful" | Specific path globs or prohibitions | Must be mechanically checkable |
| "should" / "might" in steps | Definitive "returns" / "is" / "becomes" | Non-deterministic wording fails lint |
| command to preview | command | is a legacy alias |
| Only happy path scenarios | Include exception paths (>= happy) | Edge cases are where bugs live |
Self-Hosting Rules
When authoring specs for the
project itself:
- Put task specs under
- Roadmap specs go in , promote to when active
- Update tests when DSL or verification behavior changes
- Preserve the four verdicts: , , ,
- Do not let a task spec rely on implicit test-name matching
Escalation
Authoring → Implementation: Switch to
after the Contract is drafted and passes
with score >= 0.7.
Implementation → Authoring: Switch back here if the Agent discovers during implementation that:
- A missing exception path needs to be added to Completion Criteria
- A Boundary is too restrictive and needs expanding
- A Decision was wrong and needs changing
Update the Contract first, re-lint, then resume implementation. The Contract is a living document until the task is stamped.