| name | plan-data-schemas |
| description | Entity type definitions, validation rules per WP |
| argument-hint | Invoked by Planner Coordinator - do not call directly |
plan-data-schemas
Phase: 2 (Contract Generation)
Common contract: .github/skills/PLAN-SKILL-CONTRACT.md
Spec refs: FR-040, FR-041, FR-042
This skill is dispatched by the Planner Coordinator during Phase 2. It reads the plan accumulator (WP files from Phase 1) and generates language-specific data schema contract files scoped per work package.
Input Contract (FR-023)
| # | Input | Description |
|---|
| 1 | skill_path | Path to this SKILL.md file |
| 2 | plan_dir | Path to .sdd/plans/ directory |
| 3 | contracts_dir | Path to .sdd/plans/contracts/ directory |
| 4 | spec_path | Path to the source spec file |
| 5 | spec_artifacts_dir | Path to spec companion artifacts |
| 6 | research_summary | Key findings from the research phase |
| 7 | target_language | Programming language for contract generation |
| 8 | patterns | Active plan-domain patterns to avoid |
| 9 | phase | Phase indicator (always 2 for this skill) |
Execution Sequence (FR-024)
- Read SKILL.md - Load this file for data schema generation instructions
- Read plan state - Read README and all WP files to identify which WPs touch data model entities
- Read spec + artifacts - Read the spec and the companion artifact
data-schemas.<ext> from spec_artifacts_dir. Read spec and artifact files in parallel.
- Write contract files - Write
data-schemas.<ext> to contracts_dir/<WP-slug>/ per applicable WP
Step 1 - Analyze Plan Accumulator
Read the plan README and all WP files. For each WP, determine if it:
- Creates new data entities
- Modifies existing entity fields or types
- Introduces new relationships between entities
- Adds validation rules or constraints
Skip WPs that:
- Do not create or modify data entities
- Only interact with entities through existing interfaces (read-only consumers)
- Are pure infrastructure, tooling, or documentation WPs
Build an entity-to-WP ownership map:
User -> WP01 (defines)
Order -> WP02 (defines)
User -> WP03 (extends with preferences field)
Payment -> WP02 (defines)
Step 2 - Read Spec Companion Artifact (FR-041)
Check if spec_artifacts_dir contains a data-schemas.<ext> file. If it exists:
- Parse the spec-level entity definitions with all fields, types, and constraints
- These are the canonical schemas -- WP-level contracts MUST match field names and types
- Scope each WP's schema to only the entities that WP creates or modifies
If the spec artifact does NOT exist:
- Generate schemas from the spec prose (data model section, FR descriptions)
- Note in a comment that these were derived from spec prose, not from a companion artifact
Step 3 - Resolve Entity Ownership (FR-042)
Process WPs in numerical order (WP01, WP02, ...) to determine entity ownership:
- First definer: The WP with the lowest number that creates an entity owns the full definition
- Subsequent users: Later WPs that modify the entity import it from the original owner and extend it
Build the ownership table:
| Entity | Owner WP | Extended by |
|---|
| User | WP01 | WP03 (adds preferences) |
| Order | WP02 | - |
| Payment | WP02 | WP04 (adds refund fields) |
Step 4 - Generate Data Schema Contract Files (FR-040)
For each applicable WP, generate <contracts_dir>/<WP-slug>/data-schemas.<ext>:
4a. Manifest Header (FR-039)
Every contract file MUST start with the manifest header:
// Generated by: plan-data-schemas skill
// Source spec: <spec_path>
// Work package: WP<NN>-<slug>
// Target language: <target_language>
// DO NOT EDIT MANUALLY -- regenerated on plan revision
Adjust comment syntax for the target language.
4b. Entity Type Definitions (FR-040.1)
For entities the WP owns (first definer):
export interface User {
id: string;
email: string;
name: string;
createdAt: Date;
updatedAt: Date;
}
from pydantic import BaseModel, EmailStr
from datetime import datetime
class User(BaseModel):
id: str
email: EmailStr
name: str
created_at: datetime
updated_at: datetime
Requirements:
- ALL fields MUST be typed
- Field names MUST match the spec's data model exactly
- Include required/optional annotations where applicable
- Use the target language's idiomatic type system
4c. Field Validation Rules (FR-040.2)
Express validation rules as code in the target language's idiom:
export const UserSchema = z.object({
id: z.string().uuid(),
email: z.string().email().max(255),
name: z.string().min(1).max(100),
createdAt: z.date(),
updatedAt: z.date(),
});
class User(BaseModel):
id: str = Field(..., pattern=r'^[0-9a-f-]{36}$')
email: EmailStr = Field(..., max_length=255)
name: str = Field(..., min_length=1, max_length=100)
created_at: datetime
updated_at: datetime
Include constraints from the spec:
- Type (string, number, boolean, date, etc.)
- Format (email, UUID, URL, etc.)
- Min/max length or value
- Required vs optional
- Unique constraints (as comments)
4d. Shared Entity Contracts
For entities that will be consumed by subsequent WPs (referenced in multiple WPs' tasks):
- Write the full entity definition to BOTH
<contracts_dir>/<WP-slug>/data-schemas.<ext> AND <contracts_dir>/shared/data-schemas.<ext>.
- The shared file accumulates entity definitions across WPs -- append new entities to it; do NOT overwrite existing content.
- Subsequent WPs' contract files SHALL import shared entities from
../shared/data-schemas rather than from the owning WP's directory.
- If
<contracts_dir>/shared/data-schemas.<ext> does not exist, create it with the standard manifest header.
This enables the Coder to read contracts/shared/ for cross-WP type availability without needing to know which WP originally defined an entity.
4e. Relationship Definitions (FR-040.3)
For entity relationships:
export interface Order {
id: string;
userId: string;
items: OrderItem[];
payment?: Payment;
}
Express relationships using:
- Foreign key annotations
- Collection types for one-to-many
- Optional types for nullable relationships
- Comments for relationship cardinality
Step 5 - Handle Entity Extensions (FR-042)
For WPs that extend entities owned by another WP:
import { User as BaseUser } from '../WP01-user-management/data-schemas';
export interface User extends BaseUser {
preferences: UserPreferences;
}
export interface UserPreferences {
theme: 'light' | 'dark';
language: string;
notifications: boolean;
}
from ..wp01_user_management.data_schemas import User as BaseUser
class User(BaseUser):
preferences: UserPreferences
class UserPreferences(BaseModel):
theme: Literal['light', 'dark']
language: str
notifications: bool
Rules:
- Import the base entity from the owner WP's contracts
- Extend or augment -- never redefine fields from the base
- If a field is modified (type change), document the reason in a comment
Step 6 - 800-Line Block Compliance (FR-013)
If a WP's data schema file exceeds 800 lines:
- Split the generation into multiple write operations
- Read the prior output before writing the next block
- Ensure the final file is valid syntax
Constraints
- Output MUST be valid syntax in the target language -- the file must parse without errors
- Do NOT include business logic, service methods, or test code in schema files
- Do NOT modify WP markdown files -- read only
- Do NOT modify spec artifacts -- read only
- Only write to
<contracts_dir>/<WP-slug>/data-schemas.<ext>
- Do NOT generate schema files for WPs that do not touch the data model
- Entity field names MUST match the spec data model exactly -- no renaming
- Use plain ASCII hyphens and straight quotes only -- no em dashes, smart quotes, or curly apostrophes