8.1 KiB
Steering Template
This template defines the structure for generated steering documents. All steerings follow the Intent → Rules → Practices → Meta format.
Standard Steering Structure
# {Steering Title}
{Brief 1-2 sentence overview of what this steering covers}
## Intent (Why)
{Single concise sentence explaining why these conventions matter}
## Rules (What)
{Numbered list of concrete, enforceable rules. Keep statements imperative and actionable.}
1. {Clear rule statement}
2. {Clear rule statement}
3. {Clear rule statement}
{Continue for 5-10 rules per steering}
## Practices (How)
{Concrete examples showing how to apply the rules. Keep format simple: heading + explanation + code.}
### {Practice Category 1}
{Brief explanation of the practice}
{Code example, file structure example, or workflow example}
---
### {Practice Category 2}
{Brief explanation of the practice}
{Code/workflow example}
---
{Continue for 3-5 practice categories}
## Meta
**Scope**: {project | team | developer}
**Task Types**: {comma-separated list: write-code, write-tests, refactor, etc.}
**Source Interview**:
- Session ID: `{sessionId}`
- Date: `{YYYY-MM-DD}`
- Pack: `{pack-id}`
**Generated**: `{ISO 8601 timestamp}`
**Dependencies**: {Related steerings that should be read together}
- `{other-steering-name.md}` — {Why it's related}
Filename Conventions
Steering filenames must:
- Use kebab-case (lowercase with hyphens)
- Reflect the knowledge area
- Be descriptive but concise (2-4 words)
Examples:
codebase-topology.mdarchitecture-invariants.mdtesting-strategy.md
Content Guidelines
Intent Section
Requirement: Single concise sentence explaining the core "why"
Good Intent:
## Intent (Why)
We organize code by feature rather than by layer to keep related code co-located, enable feature-level ownership, and support independent feature evolution.
Weak Intent:
## Intent (Why)
This is how we organize code.
Rules Section
Requirement: Numbered prescriptive statements without metadata
Rules should guide HOW to do assigned tasks, not tell agents to do extra work. Use conditional ("When X, do Y") or prescriptive ("Structure X as Y") patterns.
Rule Patterns:
✅ Conditional rules:
1. When implementing features, keep functions under 50 lines by extracting helpers
2. When refactoring, extract functions with single responsibilities
✅ Prescriptive rules:
1. Place shared types and utilities in `src/shared/`
2. Features must not import from other features
3. Use TypeScript path aliases (@core/_, @features/_) for all internal imports
✅ Scoped requirement rules:
1. New features require unit tests covering happy path and error cases
2. Extract shared logic used 3+ times into `src/shared/utils/`
❌ Avoid proactive commands (tell agent to do extra work):
1. Proactively refactor complex functions exceeding 50 lines
2. Add comprehensive test coverage to existing modules
3. Improve error handling in legacy code
4. Look for opportunities to extract reusable utilities
Avoid:
- Proactive commands that tell agents to do work outside assigned task scope
- Adding Source/Rationale/Applies metadata
- Overly verbose explanations
- Weak statements like "Try to keep code organized"
Practices Section
Requirement: Simple format with heading + explanation + code example
Good Practice:
### Creating a New Shared Utility
Place reusable functions in `src/shared/utils/`:
\`\`\`typescript
// src/shared/utils/format-currency.ts
export function formatCurrency(amount: number): string {
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
}).format(amount);
}
\`\`\`
Avoid:
- Structured subsections (What/How/Example/Anti-pattern) unless multiple competing approaches exist
- Overly detailed step-by-step procedures
- Generic advice without concrete examples
When to add structure: Only when there are multiple valid approaches to show. Example:
### Handling Cross-Module Communication
**Option 1: Direct calls** (same module)
\`\`\`typescript
await this.updateInventory(order.items);
\`\`\`
**Option 2: Domain events** (cross-module)
\`\`\`typescript
this.eventBus.publish(new OrderCompletedEvent(order));
\`\`\`
Meta Section Guidelines
Scope Values
project: Applies to all code in this repositoryteam: Applies to this team's work across projectsdeveloper: Personal conventions for individual contributors
Task Type Values
Common task types:
write-code— Implementing new featureswrite-tests— Creating testswrite-docs— Documentationrefactor— Restructuring codereview— Code reviewdebug— Bug fixingsetup— Project configuration
Dependencies
List related steerings:
**Dependencies**:
- `architecture-invariants.md` — Defines layer boundaries referenced here
- `testing-strategy.md` — Impacts module structure for testability
Validation Checklist
Before finalizing a steering:
- Single H1 heading present
- Intent is one concise sentence
- Rules are numbered imperative statements (no metadata)
- Practices use simple format (heading + explanation + code)
- No Enforcement section
- Filename is kebab-case
- All required sections present (Intent, Rules, Practices, Meta)
- File is < 200 lines (split if longer)
- Meta section complete
Code Example Guidelines
Code snippets in Practices section should be:
Concise: Show only the essential pattern (5-15 lines typical, max 25 lines)
- Focus on the concept being demonstrated
- Omit boilerplate unless it's part of the pattern
- Use
// ...to indicate omitted code when helpful
Meaningful: Include enough context to understand the pattern
- Add file paths as comments (
// src/features/auth/auth.service.ts) - Include necessary imports if they're part of the convention
- Show types/interfaces if they clarify the pattern
Realistic: Use actual project conventions
- Match the naming conventions from interview responses
- Use real imports and paths from the codebase
- Reflect actual patterns, not generic examples
Focused: One clear concept per example
- Don't mix multiple patterns in one snippet
- If showing alternatives, separate them clearly
- Avoid unrelated details
Good example:
// src/features/auth/auth.service.ts
export class AuthService {
async login(email: string): Promise<Session> {
const user = await this.userRepo.findByEmail(email);
return this.sessionManager.create(user);
}
}
Avoid:
- Full file dumps (50+ lines of code)
- Trivial examples without context (
const x = 1) - Multiple unrelated patterns in one snippet
- Placeholder code like
// TODO: implement - Generic "hello world" examples that don't reflect real patterns
Splitting Large Steerings
If a steering exceeds ~200 lines, split it logically:
Example: architecture-invariants.md (too large)
Split into:
architecture-layering.md— Layer structure and dependenciesarchitecture-imports.md— Import rules and path aliasesarchitecture-events.md— Event-driven patterns
Cross-reference in Meta dependencies.
Outcome Mapping
Each interview pack generates a specific steering document:
| Pack | Generated Steering |
|---|---|
| Codebase Topology & Ownership | code-ownership.md |
| Architecture & Design Invariants | architecture-invariants.md |
| Business Domain Contracts | domain-invariants.md |
| Quality & Style Assurance | quality-and-style.md |
| Testing & Verification Strategy | testing-strategy.md |
| Risk & Historical Landmines | risk-registry.md |
| Security, Data & Compliance | security-and-compliance.md |
| Delivery Lifecycle & Change Flow | delivery-lifecycle.md |