From idd-skills
Convert solution narratives into BDD feature files and protocol contracts. Use when translating user stories into testable specifications and API/event/RPC definitions. Consumes output from solution-narrative skill, produces artifacts consumed by architecture skills.
How this skill is triggered — by the user, by Claude, or both
Slash command
/idd-skills:behavior-contract [feature-area or story][feature-area or story]This skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Transform narrative artifacts into executable specifications and API contracts. This is the bridge between "what" and "how."
Transform narrative artifacts into executable specifications and API contracts. This is the bridge between "what" and "how."
Store in specs/ directory:
specs/
├── features/
│ └── {feature-area}/
│ └── {feature-name}.feature
├── contracts/
│ ├── openapi/
│ │ └── api.yaml ← HTTP boundary
│ ├── asyncapi/
│ │ └── events.yaml ← event boundary
│ └── json-rpc/
│ └── service.yaml ← RPC boundary
└── fixtures/
└── {feature-area}/
└── {fixture-name}.json
{
"_meta": {
"id": "{fixture-name}",
"type": "fixture",
"story": "specs/stories/{area}/{story}.md",
"feature": "specs/features/{area}/{feature}.feature",
"scenario": "{scenario name}"
},
"request": {},
"response": {}
}
Before defining contract schemas, check specs/models/:
x-story, x-feature, and x-journey._meta block with the story and scenario they support.# specs/features/{area}/{name}.feature
# id: {feature-name}
# type: feature
# story: specs/stories/{area}/{story}.md
# journey: specs/journeys/{journey}.md
# contract: {METHOD} {endpoint}
@{feature-area}
Feature: {Feature Title}
As a {persona}
I want to {capability}
So that {benefit}
Background:
Given I am authenticated as {persona-type}
@happy-path
Scenario: {Success scenario name}
Given {precondition}
When {action}
Then {expected outcome}
And {additional verification}
@validation
Scenario: {Validation scenario name}
Given {precondition}
When {action with invalid input}
Then I receive a {error-type} error
And the error message indicates {reason}
@authorization
Scenario: {Authorization scenario name}
Given I am authenticated as {different-persona}
When {action on protected resource}
Then I receive a {forbidden/not-found} error
@edge-case
Scenario Outline: {Parameterized scenario}
Given {precondition}
When {action with <parameter>}
Then {outcome with <expected>}
Examples:
| parameter | expected |
| value1 | result1 |
| value2 | result2 |
Journey system responses map to API endpoints:
| Journey Says | Contract Defines |
|---|---|
| "System displays list of X" | GET /x |
| "System creates X" | POST /x |
| "System shows X details" | GET /x/{id} |
| "System updates X" | PUT /x/{id} or PATCH /x/{id} |
| "System removes X" | DELETE /x/{id} |
| "System does Y to X" | POST /x/{id}/y (action endpoint) |
| "System searches for X" | GET /x?query=... |
# specs/contracts/openapi/api.yaml
openapi: 3.1.0
info:
title: {Service Name} API
version: 1.0.0
description: |
API contract for {service description}.
## Changelog
- 1.0.0: Initial release
servers:
- url: /api/v1
description: API v1
security:
- bearerAuth: []
tags:
- name: audits
description: Identity audit operations
- name: accounts
description: User account operations
paths:
/audits:
$ref: './paths/audits.yaml#/collection'
/audits/{auditId}:
$ref: './paths/audits.yaml#/item'
/audits/{auditId}/cancel:
$ref: './paths/audits.yaml#/cancel'
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: Supabase JWT token
# specs/contracts/openapi/paths/audits.yaml
collection:
get:
operationId: listAudits
summary: List user's audits
tags: [audits]
x-story: list-audits
x-feature: specs/features/audits/list-audits.feature
x-journey: specs/journeys/{journey}.md
parameters:
- $ref: '../components/parameters.yaml#/PageSize'
- $ref: '../components/parameters.yaml#/PageToken'
responses:
'200':
description: Audits retrieved successfully
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/AuditList'
'401':
$ref: '../components/responses.yaml#/Unauthorized'
post:
operationId: createAudit
summary: Create a new identity audit
tags: [audits]
x-story: create-first-audit
x-feature: specs/features/audits/create-audit.feature
x-journey: specs/journeys/{journey}.md
requestBody:
required: true
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/CreateAuditRequest'
responses:
'201':
description: Audit created successfully
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/Audit'
'400':
$ref: '../components/responses.yaml#/BadRequest'
'401':
$ref: '../components/responses.yaml#/Unauthorized'
item:
get:
operationId: getAudit
summary: Get audit details
tags: [audits]
parameters:
- $ref: '../components/parameters.yaml#/AuditId'
responses:
'200':
description: Audit retrieved successfully
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/Audit'
'404':
$ref: '../components/responses.yaml#/NotFound'
cancel:
post:
operationId: cancelAudit
summary: Cancel a pending audit
tags: [audits]
x-story: cancel-pending-audit
x-feature: specs/features/audits/cancel-audit.feature
x-journey: specs/journeys/{journey}.md
parameters:
- $ref: '../components/parameters.yaml#/AuditId'
responses:
'200':
description: Audit cancelled successfully
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/Audit'
'409':
description: Audit cannot be cancelled
content:
application/json:
schema:
$ref: '../components/schemas.yaml#/Error'
example:
code: "AUDIT_NOT_CANCELLABLE"
message: "Audit in 'completed' status cannot be cancelled"
# specs/contracts/openapi/components/schemas.yaml
Audit:
type: object
required: [id, status, entityName, entityType, createdAt]
properties:
id:
type: string
pattern: '^aud_[a-zA-Z0-9]+$'
example: "aud_abc123"
status:
$ref: '#/AuditStatus'
entityName:
type: string
minLength: 1
maxLength: 200
example: "Acme Plumbing LLC"
entityType:
$ref: '#/EntityType'
createdAt:
type: string
format: date-time
completedAt:
type: string
format: date-time
nullable: true
cancelledAt:
type: string
format: date-time
nullable: true
AuditStatus:
type: string
enum: [pending, analyzing, completed, cancelled]
description: |
- pending: Audit created, waiting to start
- analyzing: LLM analysis in progress
- completed: Analysis finished, results available
- cancelled: User cancelled before completion
EntityType:
type: string
enum: [individual, business]
CreateAuditRequest:
type: object
required: [entityName, entityType]
properties:
entityName:
type: string
minLength: 1
maxLength: 200
entityType:
$ref: '#/EntityType'
Error:
type: object
required: [code, message]
properties:
code:
type: string
description: Machine-readable error code
message:
type: string
description: Human-readable error message
details:
type: object
additionalProperties: true
description: Additional error context
{
"_meta": {
"id": "create-audit-happy-path",
"type": "fixture",
"description": "Successful audit creation",
"story": "specs/stories/audits/create-first-audit.md",
"feature": "specs/features/audits/create-audit.feature",
"scenario": "Successfully create an audit"
},
"request": {
"entityName": "Acme Plumbing LLC",
"entityType": "business"
},
"response": {
"id": "aud_abc123",
"status": "pending",
"entityName": "Acme Plumbing LLC",
"entityType": "business",
"createdAt": "2024-01-15T10:00:00Z",
"completedAt": null,
"cancelledAt": null
}
}
Every artifact must reference its source. Use front-matter fields (id, type, and typed refs) so tools can parse links uniformly. See docs/idd/front-matter-spec.md for the full schema.
In feature files (comment-based front-matter):
# id: cancel-audit
# type: feature
# story: specs/stories/audits/cancel-pending-audit.md
# journey: specs/journeys/cancel-audit.md
# contract: POST /audits/{id}/cancel
In contract (OpenAPI extensions — unchanged):
x-story: cancel-pending-audit
x-feature: specs/features/audits/cancel-audit.feature
In fixtures (_meta block with id and type):
{
"_meta": {
"id": "cancel-audit-happy-path",
"type": "fixture",
"story": "specs/stories/audits/cancel-pending-audit.md",
"feature": "specs/features/audits/cancel-audit.feature",
"scenario": "Successfully cancel a pending audit"
}
}
x- extensions for traceability metadata.Before handoff to implementation:
Background:
Given I am authenticated as a small business owner
Maps to:
bearerAuthScenario: Cannot access another user's audit
Given another user has an audit
When I request their audit
Then I receive a not found error
Return 404, not 403, to avoid leaking existence information.
Scenario: Cannot cancel a completed audit
Given I have an audit in "completed" status
When I attempt to cancel the audit
Then I receive a conflict error
Use 409 Conflict with descriptive error code.
When complete:
specs/capabilities/{name}.capability.yaml so it includes the relevant scope.models, scope.features, and scope.contracts before implementation handoff.npx claudepluginhub slusset/intention-driven-design --plugin idd-skillsProvides behavioral guidelines to reduce common LLM coding mistakes, focusing on simplicity, surgical changes, assumption surfacing, and verifiable success criteria.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.