Onboard OpenSpec
Guide the user through a conversational interview to produce a complete,
project-specific openspec/config.yaml configured for the QRSPI methodology.
NEVER Do When Onboarding OpenSpec
- NEVER run codebase inference serially when subagents are available — Phase 3 spawns parallel subagents for different discovery domains. Serial scanning wastes time on codebases with many config files spread across directories. Spawn all 4 discovery agents simultaneously.
Companion Skill
This skill produces the project DNA layer of the agent instruction stack:
structural facts about what the project is. It is the companion to the
accelint-onboard-agents skill, which produces the behavior layer (AGENTS.md /
CLAUDE.md): how the agent acts, communicates, and makes decisions.
If during this interview the user volunteers behavioral content (commit
conventions, workflow steps, decision heuristics, tool preferences), acknowledge
it and redirect: "That's behavioral — it belongs in AGENTS.md. I'll note it
here for reference, but the accelint-onboard-agents skill is the right place to
capture it." Do not write behavioral content into config.yaml.
AGENTS.md / CLAUDE.md → accelint-onboard-agents skill → HOW the agent behaves
openspec/config.yaml → this skill → WHAT the project is
Mental Model
The config has two jobs:
context: — Objective facts about the codebase injected into every AI
artifact. Think of it as the "DNA" that makes AI suggestions feel native to
the project. Facts only, no opinions.
rules: — Per-artifact checkpoints (proposal / design / tasks / spec)
that encode the team's quality bar.
Phases
Phase 0 — File State Detection
Before any interview question is asked, check whether openspec/config.yaml
exists and assess its state. Never silently pick a mode — always announce the
detected mode to the user and confirm before proceeding.
Step 1 — Check for Related Documents
Before detecting config.yaml state, check for related onboarding documents:
- Check for ARCHITECTURE.md
- If exists: Read it to understand deployment and infrastructure
- Use it to pre-fill answers for Turn 2 (infrastructure/deployment questions)
- Note its existence for the "Related Documentation" section
- Announce: "Found ARCHITECTURE.md — I'll use it to avoid asking questions
about deployment that are already documented."
Note: AGENTS.md and README.md should NOT influence config.yml generation since
they contain behavioral/usage info, not project DNA.
Step 2 — Detect Config State
After checking related documents, assess the config file state:
Does openspec/config.yaml exist?
│
├── No → MODE 1: Create
│ Full interview from scratch.
│
└── Yes → Read the file, then assess:
│
├── Empty or near-blank (schema: line only, no context/rules)?
│ → MODE 1: Create (with overwrite confirmation)
│ Ask: "config.yaml exists but appears empty — should I
│ populate it from scratch, or preserve any current content?"
│
├── Contains recognised fields?
│ (context: block present, rules: block with known artifact keys)
│ → MODE 3: Refresh
│ Abbreviated interview covering only detected drift and
│ unresolved # TODO: fill in markers.
│
└── Contains real content in an unrecognised shape?
→ MODE 2: Import
Present three options (A / B / C) before proceeding.
Recognised shape = file is valid YAML with at least a context: key
whose value is a non-empty string, or a rules: key with at least one
of the known artifact IDs (proposal, specs, design, tasks).
Mode 1: Create
Run the full Phase 1 → Phase 2 → Phase 3 → Phase 4 interview. This is the
happy path for a fresh repo.
Mode 2: Import
The file has real content that was not generated by this skill. Present the
user with three options before touching anything:
"This config.yaml has existing content with a structure I don't
recognise. How would you like to proceed?
(a) Restructure — I'll import your existing content, map it onto the
context: / rules: schema, flag any material that belongs in AGENTS.md
instead (workflow steps, commit conventions, tool preferences), run a
targeted interview to fill gaps, and produce a merged file ready to replace
the current one.
(b) Append — I'll run the full interview and add the skill's context:
and rules: sections alongside your existing content without modifying
what's already there.
(c) Dry run — I'll run the full interview and show you exactly what I
would have generated, with no changes to the filesystem. Use this to
evaluate fit before committing."
If option (a) is chosen:
- Read the file in full.
- Map existing content onto
context: sub-sections and rules: artifact
keys where possible.
- Flag any content that violates the separation-of-concerns boundary
(e.g., commit conventions, workflow steps, tool preferences, agent
decision heuristics) — these belong in
AGENTS.md. For each violation,
ask: "This looks behavioral — it belongs in AGENTS.md. Should I move it
there and remove it from config.yaml?"
- Run a targeted interview covering only the gaps (context sub-sections
with no existing coverage; artifact keys with no rules).
- Show a merged preview before writing. Existing content is labelled
# from existing file; new content is labelled # new.
If option (b) is chosen:
Run the full Phase 1 → Phase 4 interview and write the generated context:
and rules: blocks alongside existing content. Add a comment at the top:
# Sections below added by accelint-onboard-openspec skill.
If option (c) is chosen:
Run the full Phase 1 → Phase 4 interview and present the output in the
conversation. Explicitly state: "No files were changed." Offer to re-run
as (a) or (b) if the user is satisfied.
Mode 3: Refresh
The file matches the skill's expected schema — it was likely produced by a
previous run. Run an abbreviated interview covering only:
Extract external findings — check if the invoking prompt includes a findings: list:
- Parse the prompt for a
findings: section (a bulleted list of factual statements)
- Each finding is phrased as something already known to be true, never as an instruction
- Example: "config.yaml's Anti-Patterns section says to avoid polling, but two archived changes chose polling for stated reasons"
- Store these findings for merging in step 4
Drift detection — scan the codebase for changes since the file was
last updated:
| Signal |
Where to look |
| Runtime / Node version changed |
.nvmrc, .node-version, Dockerfile |
| New packages / frameworks added |
package.json deps, workspace roots |
| TypeScript config tightened |
tsconfig.json — new strict* flags |
| New packages in monorepo |
pnpm-workspace.yaml, turbo.json |
| Build tooling changed |
vite.config.*, tsup.config.* |
| CI/CD workflows added |
.github/workflows/ |
| New domain concepts |
New top-level directories, new entity types in source |
| Anti-patterns deprecated |
@deprecated tags, // TODO: replace comments added |
Unresolved TODOs — find all # TODO: fill in markers left from the
previous run and surface them as targeted questions.
Merge and announce all findings before asking anything:
- Combine external findings (from step 1) with drift findings (from step 2) and TODOs (from step 3)
- Present the merged list to the user:
"I found [N] external findings, [M] context sections that may have drifted, and [P] unresolved TODOs.
I'll only ask about those — the rest looks current."
- If external findings exist, note their source (e.g., "from completed OpenSpec change")
After the targeted interview, show only the changed sections in the
preview before writing. Do not re-emit unchanged sections.
Phase 1 — Discovery Interview
Run the interview conversationally. Don't dump all questions at once. Group them
into natural topic turns. If the user mentions a stack, infer related tooling and
confirm rather than asking again.
Turn 1 — Project Identity
- What is the project name and its primary purpose?
- Monorepo, single package, or something else? If monorepo, what workspaces?
- Build system / task orchestration? (Turbo, Nx, Make, npm scripts, Makefile…)
- Package manager and any private registries? (npm, pnpm, yarn, bun…)
Turn 2 — Tech Stack (ask as a grouped block, not one by one)
- Runtime and version (Node.js 20, Bun 1.x, Python 3.12, etc.)
- Language + config (TypeScript strict?
exactOptionalPropertyTypes? Python type
hints?)
- Framework(s) and version (React 18, Next.js 14, Express, FastAPI, etc.)
- Key domain libraries (Deck.gl, Apache Arrow, Prisma, SQLAlchemy, etc.)
- Data layer (Postgres, MongoDB, DynamoDB, ORM/query builder, data formats)
- Testing setup (Vitest, Jest, Pytest, testing-library, Playwright, etc.)
- Linting / formatting (ESLint, Biome, Prettier, Black, Ruff, etc.)
- Build tools (Vite, tsup, esbuild, Webpack, etc.)
- CI/CD (GitHub Actions, CircleCI, etc.)
- Versioning approach (Changesets, standard-version, conventional commits, etc.)
Turn 3 — Architecture
- How is the codebase organised? (feature-based, layer-based, domain-driven?)
- Where does shared/utility code live?
- Any path aliases? (
@/, ~/, src/, #lib/, etc.)
- Design patterns commonly in use? (factory, repository, observer, CQRS, etc.)
Turn 4 — Domain Concepts
- What are the 3–5 most important domain entities?
Example prompt: "For a mapping app this might be Layer, Source, Viewport,
Feature, Style."
- Any domain-specific terminology the AI should know?
- Any specialised concepts with non-obvious meanings in this codebase?
Example: "orchestration" means something specific to us — it's the runtime
layer that merges style with data, not a general workflow term.
Turn 5 — Performance
- Any concrete performance targets? (p95 < 200 ms, 60 fps, < 50 MB heap, etc.)
- Known hot paths or performance-critical areas?
- Memory or bundle-size constraints?
Turn 6 — Code Patterns
- Export style: named exports, default exports, or mixed?
- Naming conventions: files, variables, functions, constants?
Example: "kebab-case files, camelCase vars, SCREAMING_SNAKE_CASE for
constants, PascalCase for types."
- Error handling: throw,
Result<T,E>, error boundaries, something else?
- Testing structure:
describe/it, test/expect, AAA pattern?
- Test file location: co-located with source or a separate
__tests__/ tree?
- Fixture / factory approach for test data?
Note: Commit message convention is a workflow procedure — it belongs in
AGENTS.md, not here. If the user raises it now, capture it mentally and
surface it in the accelint-onboard-agents skill. Do not add it to config.yaml.
Turn 7 — Anti-Patterns
- Any patterns explicitly banned in code review?
- Deprecated patterns still in the codebase that new code should NOT emulate?
- Known performance traps specific to this stack?
Turn 8 — Proposal Rules
What does YOUR team require in a proposal? Good prompts:
- "Do you need proposals to call out database migration impact?"
- "Do you need proposals to flag API breaking changes?"
- "Any security review checklist items?"
Turn 9 — Design Rules
Project-specific design concerns to encode? Good prompts:
- "Docker / Kubernetes resource changes to document?"
- "Performance implications section required?"
- "Specific architecture diagram style (ASCII, Mermaid)?"
Turn 10 — Task Rules
- How do you tag tasks by package or module?
Example:
[PKG:auth], [MODULE:pipeline], GitHub labels…
- Rollback plan required for database changes?
- Deployment-specific test gates (smoke tests, canary checks)?
Phase 2 — Smart Defaults
After each stack answer, surface relevant conventions to confirm. Use these
examples as a pattern; extend to other stacks as appropriate.
Next.js + TypeScript + Tailwind → suggest confirming:
- App Router vs Pages Router and which patterns apply
- Server Component vs Client Component boundary rules
"use client" directive placement convention
- API route organisation (
app/api/ vs pages/api/)
React + Vitest + testing-library → suggest confirming:
userEvent over fireEvent preference
screen query priority (role > label > testid)
render wrapper for providers
Python + FastAPI → suggest confirming:
- Pydantic v1 vs v2 (different field-validator syntax)
- Dependency injection for DB sessions (
Depends)
- Alembic migration workflow
lifespan vs startup/shutdown event hooks
Node.js + Prisma → suggest confirming:
prisma.$transaction patterns
- Soft-delete vs hard-delete convention
- Migration naming convention
Phase 3 — Parallel Codebase Inference
After the interview, spawn parallel discovery subagents to fill remaining config
gaps. All config sections are load-bearing — a missing field degrades every
downstream AI artifact, so inference is always preferable to omission.
Spawn discovery subagents in parallel — don't scan serially. Each agent focuses
on one inference domain and returns structured findings. Wait for all agents to
complete, then merge results before Phase 4.
Spawn these agents simultaneously:
Agent A — Stack & Build Tooling
- Runtime / Node version:
.nvmrc, .node-version, package.json#engines, Dockerfile
- TypeScript config:
tsconfig.json (compilerOptions flags, paths aliases)
- Package manager:
package-lock.json, yarn.lock, pnpm-lock.yaml, bun.lockb
- Monorepo workspaces:
package.json#workspaces, pnpm-workspace.yaml, turbo.json, nx.json
- Build tools:
vite.config.*, webpack.config.*, tsup.config.*, esbuild scripts
- Return: runtime version, TS config flags, package manager, workspace list, build tools
Agent B — Testing & Code Quality
- Test framework:
vitest.config.*, jest.config.*, pytest.ini, pyproject.toml#tool.pytest
- Linting / formatting:
.eslintrc*, biome.json, .prettierrc*, ruff.toml
- Test structure: Sample test files — describe/it nesting depth, file location relative to source
- Test file type checking: CI scripts, package.json — check if
tsc --noEmit runs on *.test.ts files
- Property-based testing: Check for
fast-check in dependencies
- Vitest mock cleanup:
vitest.config.ts — check for clearMocks, mockReset, restoreMocks
- Return: test framework, code quality tools, test structure patterns, type checking config
Agent C — Architecture & Code Patterns
- Architecture organisation: Directory tree of
src/ or workspace roots — infer feature-based vs layer-based
- Path aliases:
tsconfig.json#compilerOptions.paths, vite.config#resolve.alias
- Design patterns: Sample source files — look for factory functions, repository objects, observer hooks
- Export style: Sample 3–5 source files; tally named vs default exports
- Naming conventions: Sample file names, exported identifiers; describe what you observe
- Error handling: Grep for
throw, Result, Either, tryCatch, error boundary components
- TypeScript baseline patterns: If
tsconfig.json exists, flag that TS/JS baseline patterns should be included
- Return: architecture style, path aliases, design patterns, export conventions, naming patterns, error handling approach
Agent D — CI/CD & Versioning
- CI/CD:
.github/workflows/, .circleci/, Jenkinsfile
- Versioning:
.changeset/, CHANGELOG.md, commitlint.config.*, .releaserc*
- Anti-patterns:
eslint rule overrides marked off or warn, comments like // TODO: replace, @deprecated
- Return: CI/CD platform, versioning approach, documented anti-patterns
After all agents complete: merge their findings into a unified inference map.
Tag each field as INFERRED [source] or UNKNOWN. Fields tagged UNKNOWN
should be marked as # TODO: fill in in the config preview.
For each field resolved via inference, note the source in the preview with a
trailing comment, e.g.:
- Runtime: Node.js 20 LTS # inferred from .nvmrc
- Language: TypeScript 5.4, strict, exactOptionalPropertyTypes # inferred from tsconfig.json
If a field genuinely cannot be inferred (e.g., performance targets, domain
concepts, team-specific rules), mark it with # TODO: fill in rather than
omitting it. The user can resolve these after reviewing the preview. Do not
silently drop a section — an explicit TODO is a prompt to act; an absent section
is an invisible gap.
Phase 4 — Generation
- Show a labeled preview of the full config before writing anything.
Inferred values carry their source comment; unresolved fields carry
# TODO: fill in. This gives the user a complete picture of confidence level
across every field.
- Ask: "Does this look right? Any sections to correct or expand before I write
the file?"
- After confirmation, write to
openspec/config.yaml (create directory if
needed), stripping the inference source comments — they are for review
only, not the final file. For the Related Documentation section: only include
links to files that actually exist in the repository. Check for each file
(ARCHITECTURE.md, AGENTS.md/CLAUDE.md, README.md) before including its link.
- Validate the generated YAML — after writing, read the file back and verify:
- No tabs (YAML requires spaces for indentation)
- Values with special characters are properly quoted
- No syntax errors (unmatched brackets, quotes, etc.)
- The file can be conceptually parsed as valid YAML
If validation reveals issues, fix them immediately and rewrite the file.
- Print a brief summary of what was configured, what was inferred vs answered
directly, and which
# TODO fields still need human input.
YAML Generation Safety Rules
CRITICAL: YAML syntax is strict about special characters. Follow these rules when generating config.yaml to avoid syntax errors:
Quoting Requirements
Rule: Values that start with special YAML characters need quoting.
Special characters: |, >, ", ', (, ), [, ], {, }, *, &, !, %, @, `
Examples:
# Parentheses at start of value
❌ description: (internal) auth module # Syntax error
✅ description: "(internal) auth module" # Quoted
# Square brackets (looks like YAML list syntax)
❌ tag: [PKG:auth] # YAML thinks it's a list
✅ tag: "[PKG:auth]" # Quoted string
# Pipe character (YAML thinks it's block scalar)
❌ pattern: some|other # Syntax error
✅ pattern: "some|other" # Quoted
# Colon in value (YAML thinks it's a nested key)
❌ note: Time: 5pm # Syntax error
✅ note: "Time: 5pm" # Quoted
# Value containing quotes - escape with opposite quote type
✅ command: 'npm run "test:unit"' # Single quotes protect doubles
✅ command: "npm run 'test:unit'" # Double quotes protect singles
Multi-line String Handling
Use block scalar indicators for multi-line content:
# Literal block (preserves newlines) - preferred for context field
context: |
Line 1
Line 2
Line 3
# Folded block (folds newlines into spaces) - rarely needed
description: >
This is a long
description that
flows together.
Indentation Rules
- Use spaces only — never tabs
- Consistent indent — typically 2 spaces per level
- Block scalars — content inside
| or > must be indented relative to the key
Rules for List Values
# Simple list items - no quotes needed for plain text
rules:
proposal:
- Keep proposals under 100 lines
- Include scope boundaries
# List items with special chars - quote them
rules:
tasks:
- "Tag with [PKG:name] format" # Quotes protect [ and ]
- 'Use "Test:" prefix for validation' # Single quotes protect inner "
Validation Checklist
After generating the config, mentally verify:
- No bare
(, ), |, ", ' immediately after colons (unless using | or > for multiline)
- No tab characters anywhere in the file
- Consistent 2-space indentation throughout
- All list items (
-) aligned at the same indent level within their parent
- Quoted strings use matching quote types
If any of these rules are violated, the YAML will fail to parse.
Config Template
Use this exact structure. Fill every [placeholder] with content from the
interview or codebase inference. If a field cannot be resolved by either means,
replace its placeholder with # TODO: fill in — never omit the field. Every
section is load-bearing for downstream AI artifact quality.
schema: spec-driven
# Project Context
# Injected into every AI-generated artifact (proposal, design, spec, tasks).
# QRSPI principle: objective research layer — facts only, no opinions.
context: |
# ═══════════════════════════════════════════════════════════════════════════
# STACK FACTS
# ═══════════════════════════════════════════════════════════════════════════
## Project Identity
[project name and one-sentence purpose]
[repo structure: monorepo / single-package / workspaces list]
[build system and task orchestration]
[package manager + registries]
## Tech Stack
- Runtime: [e.g., Node.js 20 LTS]
- Language: [e.g., TypeScript 5.4, strict mode, exactOptionalPropertyTypes]
- Framework: [e.g., Next.js 14 App Router]
- Key Libraries: [domain-specific dependencies with versions]
- Data Layer: [databases, ORMs, data formats, query builders]
- Testing: [framework, utilities, coverage tooling]
- Linting/Formatting: [tools and config files in use]
- Build Tools: [bundlers, compilers, transpilers]
- CI/CD: [platform and key workflow names]
- Versioning: [release strategy and changelog tooling]
## Architecture Patterns
- Organisation: [feature-based / layer-based / domain-driven / other]
- Shared code: [path to shared utilities / packages]
- Path aliases: [list of aliases and their resolved paths]
- Key patterns: [design patterns in common use]
## Domain Concepts
- [Entity or concept]: [one-line definition]
- [Entity or concept]: [one-line definition]
- [Entity or concept]: [one-line definition]
## Performance Targets
- [metric]: [target value and context]
### TypeScript/JavaScript Performance (if applicable)
- Hot paths: [functions executed >1000 times per interaction or >100 times/sec]
- Frame budget: [for real-time systems: 60fps = 16.67ms, 120fps = 8.33ms]
- Constraints: Bounded iteration (explicit limits on loops/queues), O(n) or better algorithmic complexity
# ═══════════════════════════════════════════════════════════════════════════
# PATTERNS TO FOLLOW
# ═══════════════════════════════════════════════════════════════════════════
## Code Patterns
- Exports: [named / default / mixed — and when each applies]
- Naming: [files, variables, functions, constants, types]
- Error handling: [throw / Result<T,E> / boundaries / other]
- Validation: [approach and library]
- Constants: Use `as const` objects, never `enum`
- Classes: Prefer functions over classes unless state management required or extending existing class
- Return values: Return zero values (empty array, empty string, 0, false) instead of null/undefined
- Leaf functions: Leaf functions (bottom of call stack) should be pure — same inputs produce same outputs, no side effects. Centralize state manipulation in parent/orchestrator functions.
- Type safety: Avoid `any` (use `unknown` or generics); avoid `enum` (use `as const` objects); use `type` over `interface`
- Immutability: Prefer `const`, immutable data structures, pure functions
- Documentation: Comprehensive JSDoc for all exported code (@param, @returns, @template, @example)
- Order: Internal functions, variables and types should be defined before they are used (internal/export types -> internal/export constants -> internal/export functions)
- Parameter order: Data-last ordering — place the data being operated on as the final parameter. Enables partial application and composition.
- Composition: Use curried functions when the same first parameter(s) recur across call sites.
## Architecture Patterns
- [pattern name]: [brief description of how it's used here]
## Testing Patterns
- Pattern: AAA (Arrange, Act, Assert) with clear boundaries
- Property-based: (If available) Use `fast-check` for encode/decode pairs, validators, normalizers, pure functions
- Test scope: Never test library internals; never export internals to test them; never mock own pure functions
- Structure: [describe/it nesting convention]
- File location: [co-located / __tests__ / other]
- Test doubles: Hierarchy: real implementation > fakes > stubs > spies > mocks
- Fixtures: [factory functions / fixture files / inline data]
- Assertions: [preferred assertion style]
- Nesting: Max 2 levels of describe blocks — use descriptive test names instead
- Verification: MUST run `tsc --noEmit` on test files before marking complete
- Benchmarks: [approach if any]
# NOTE: Commit message convention, PR workflow, and tool preferences
# are behavioral — they belong in AGENTS.md, not here.
# ═══════════════════════════════════════════════════════════════════════════
# PATTERNS TO AVOID
# ═══════════════════════════════════════════════════════════════════════════
## Code Anti-Patterns
- Using `any` instead of `unknown` or generics
- Using `enum` instead of `as const` objects
- Using `interface` when `type` works (prefer type)
- Returning `null`/`undefined` instead of zero values (empty arrays, empty strings, 0, false)
- Not validating external data with schemas
- Deep nesting instead of early returns
- [anti-pattern]: [why it's banned or deprecated]
## Performance Anti-Patterns
- Chaining array methods (`.filter().map().reduce()`) — use single reduce pass
- Using `Array.includes()` for repeated lookups (use `Set.has()` for O(1) lookups)
- Recomputing constants inside loops (hoist invariants outside)
- Unbounded loops or queues (set explicit limits to prevent runaway resource consumption)
- Placing `try/catch` in hot paths (V8 cannot inline, 3-5x slowdown)
- [anti-pattern]: [why it's banned or deprecated]
## Testing Anti-Patterns
- Testing library internals (e.g., verifying Array.prototype.map works)
- Exporting internal functions just to test them
- Loose assertions in tests (toBeTruthy, toBeDefined)
- Nested describe blocks >2 levels deep
- Testing implementation details instead of behavior
- [anti-pattern]: [why it's banned or deprecated]
## Documentation Anti-Patterns
- Missing JSDoc on exported functions/types
- Documenting HOW instead of WHAT/WHY in JSDoc
- Vague comment markers (`// TODO: fix this` instead of `// TODO: Replace with binary search for O(log n)`)
# ═══════════════════════════════════════════════════════════════════════════
# PER-ARTIFACT RULES
# ═══════════════════════════════════════════════════════════════════════════
rules:
proposal:
# QRSPI: Scope definition, not a plan.
- State the requirement or ticket driving this change
- Define scope boundaries — explicitly list what is OUT of scope
- Keep under 100 lines (tight and focused)
[user-specific proposal rules]
design:
# QRSPI: The "brain surgery" checkpoint — reviewed before any code is written.
# Target ~200 lines capturing current state, desired state, open questions.
# Required sections (in this order):
- Start with "Current State": what the code does today, key files, entry
points, relevant data flows
- "Desired End State": what changes after this work, what stays the same
- "Patterns to Follow": ONLY if specific files/functions to reference exist
for this change's domain
- "Patterns to Avoid": ONLY if specific anti-patterns apply to this change
- "Open Questions": genuine uncertainties requiring human input. If none,
state explicitly "No unresolved questions."
- "Resolved Decisions": numbered (Decision 1, Decision 2…) with Choice,
Rationale, Alternatives Considered
# Technical depth:
- Use ASCII diagrams for data flows, state machines, architecture
- Call out performance implications where relevant
[user-specific design rules]
# Constraints:
- Keep under 250 lines total
tasks:
# QRSPI: Vertical slicing for early failure detection.
# Vertical slicing (strong preference):
- Order as vertical slices — each task delivers a testable end-to-end path
- Do NOT group by architectural layer unless explicitly justified
- Horizontal (layer-by-layer) only for pure infrastructure; include
justification in the task description when used
- Each task MUST include an explicit "Test:" line describing what to verify
before proceeding to the next task
- Prefer 3–5 major slices; more than 5 suggests scope is too large
# Granularity:
- Max 2 hours per task; break larger work into subtasks
[user-specific task tagging, e.g., [PKG:name] or [MODULE:name]]
- Call out inter-task dependencies explicitly
[user-specific rollback requirements]
[user-specific deployment test gates]
spec:
- Use Given/When/Then for behaviour specifications
- Include concrete example data relevant to the domain
- Document edge cases explicitly
[user-specific spec rules]
# ═══════════════════════════════════════════════════════════════════════════
# RELATED DOCUMENTATION
# ═══════════════════════════════════════════════════════════════════════════
# Include only files that actually exist in the repository:
# - ARCHITECTURE.md: System overview, deployment, component interactions, data flows
# - AGENTS.md: Agent behavior rules, workflow procedures, communication style
# - README.md: Installation, quick start, usage guide
Interaction Principles
- Conversational, not interrogative. Bundle related questions into a single
turn. Use natural language, not bullet-dump forms.
- Infer and confirm. "You mentioned Vitest — I'll assume you're using
@testing-library/react for component tests; correct?" is better than asking
from scratch.
- Examples reduce ambiguity. When asking about naming conventions, give an
example first so the user can pattern-match.
- Iterative. Let the user amend answers. Don't lock them into the first
response.
- Preview before writing. Always show the full generated config and get
explicit confirmation before touching the filesystem.
- Infer before asking, ask before omitting. Always attempt codebase
inference for any unanswered field. If inference fails, surface a
# TODO
rather than dropping the section. A config with explicit TODOs is actionable;
a config with missing sections silently degrades every artifact it drives.
1---2name: accelint-onboard-openspec3description: Interactively onboard a project to OpenSpec by running a structured interview and generating a complete QRSPI-configured openspec/config.yaml. Use this skill whenever a user mentions "openspec config", "config.yaml for openspec", "set up openspec", "onboard to openspec", "generate openspec config", "QRSPI config", or asks how to configure OpenSpec for their project — even if they just say "help me set up openspec" or "I want to use openspec". Always prefer this skill over ad-hoc config generation.4license: Apache-2.05---6
7# Onboard OpenSpec
8
9Guide the user through a conversational interview to produce a complete,
10project-specific `openspec/config.yaml` configured for the QRSPI methodology.
11
12## NEVER Do When Onboarding OpenSpec
13
14- **NEVER run codebase inference serially when subagents are available** — Phase 3 spawns parallel subagents for different discovery domains. Serial scanning wastes time on codebases with many config files spread across directories. Spawn all 4 discovery agents simultaneously.
15
16## Companion Skill
17
18This skill produces the **project DNA layer** of the agent instruction stack:
19structural facts about what the project is. It is the companion to the
20`accelint-onboard-agents` skill, which produces the **behavior layer** (`AGENTS.md` /
21`CLAUDE.md`): how the agent acts, communicates, and makes decisions.
22
23If during this interview the user volunteers behavioral content (commit
24conventions, workflow steps, decision heuristics, tool preferences), acknowledge
25it and redirect: *"That's behavioral — it belongs in AGENTS.md. I'll note it
26here for reference, but the `accelint-onboard-agents` skill is the right place to
27capture it."* Do not write behavioral content into `config.yaml`.
28
29```
30AGENTS.md / CLAUDE.md → accelint-onboard-agents skill → HOW the agent behaves
31openspec/config.yaml → this skill → WHAT the project is
32```
33
34---
35
36## Mental Model
37
38The config has two jobs:
391. **`context:`** — Objective facts about the codebase injected into every AI
40 artifact. Think of it as the "DNA" that makes AI suggestions feel native to
41 the project. Facts only, no opinions.
422. **`rules:`** — Per-artifact checkpoints (proposal / design / tasks / spec)
43 that encode the team's quality bar.
44
45## Phases
46
47### Phase 0 — File State Detection
48
49Before any interview question is asked, check whether `openspec/config.yaml`
50exists and assess its state. Never silently pick a mode — always announce the
51detected mode to the user and confirm before proceeding.
52
53**Step 1 — Check for Related Documents**
54
55Before detecting config.yaml state, check for related onboarding documents:
56
571. **Check for ARCHITECTURE.md**
58 - If exists: Read it to understand deployment and infrastructure
59 - Use it to pre-fill answers for Turn 2 (infrastructure/deployment questions)
60 - Note its existence for the "Related Documentation" section
61 - Announce: "Found ARCHITECTURE.md — I'll use it to avoid asking questions
62 about deployment that are already documented."
63
64Note: AGENTS.md and README.md should NOT influence config.yml generation since
65they contain behavioral/usage info, not project DNA.
66
67**Step 2 — Detect Config State**
68
69After checking related documents, assess the config file state:
70
71```
72Does openspec/config.yaml exist?
73│
74├── No → MODE 1: Create
75│ Full interview from scratch.
76│
77└── Yes → Read the file, then assess:
78 │
79 ├── Empty or near-blank (schema: line only, no context/rules)?
80 │ → MODE 1: Create (with overwrite confirmation)
81 │ Ask: "config.yaml exists but appears empty — should I
82 │ populate it from scratch, or preserve any current content?"
83 │
84 ├── Contains recognised fields?
85 │ (context: block present, rules: block with known artifact keys)
86 │ → MODE 3: Refresh
87 │ Abbreviated interview covering only detected drift and
88 │ unresolved # TODO: fill in markers.
89 │
90 └── Contains real content in an unrecognised shape?
91 → MODE 2: Import
92 Present three options (A / B / C) before proceeding.
93```
94
95**Recognised shape** = file is valid YAML with at least a `context:` key
96whose value is a non-empty string, or a `rules:` key with at least one
97of the known artifact IDs (`proposal`, `specs`, `design`, `tasks`).
98
99---
100
101#### Mode 1: Create
102
103Run the full Phase 1 → Phase 2 → Phase 3 → Phase 4 interview. This is the
104happy path for a fresh repo.
105
106---
107
108#### Mode 2: Import
109
110The file has real content that was not generated by this skill. Present the
111user with three options before touching anything:
112
113> "This `config.yaml` has existing content with a structure I don't
114> recognise. How would you like to proceed?
115>
116> **(a) Restructure** — I'll import your existing content, map it onto the
117> `context:` / `rules:` schema, flag any material that belongs in `AGENTS.md`
118> instead (workflow steps, commit conventions, tool preferences), run a
119> targeted interview to fill gaps, and produce a merged file ready to replace
120> the current one.
121>
122> **(b) Append** — I'll run the full interview and add the skill's `context:`
123> and `rules:` sections alongside your existing content without modifying
124> what's already there.
125>
126> **(c) Dry run** — I'll run the full interview and show you exactly what I
127> would have generated, with no changes to the filesystem. Use this to
128> evaluate fit before committing."
129
130**If option (a) is chosen:**
1311. Read the file in full.
1322. Map existing content onto `context:` sub-sections and `rules:` artifact
133 keys where possible.
1343. Flag any content that violates the separation-of-concerns boundary
135 (e.g., commit conventions, workflow steps, tool preferences, agent
136 decision heuristics) — these belong in `AGENTS.md`. For each violation,
137 ask: *"This looks behavioral — it belongs in AGENTS.md. Should I move it
138 there and remove it from config.yaml?"*
1394. Run a targeted interview covering only the gaps (context sub-sections
140 with no existing coverage; artifact keys with no rules).
1415. Show a merged preview before writing. Existing content is labelled
142 `# from existing file`; new content is labelled `# new`.
143
144**If option (b) is chosen:**
145Run the full Phase 1 → Phase 4 interview and write the generated `context:`
146and `rules:` blocks alongside existing content. Add a comment at the top:
147`# Sections below added by accelint-onboard-openspec skill`.
148
149**If option (c) is chosen:**
150Run the full Phase 1 → Phase 4 interview and present the output in the
151conversation. Explicitly state: "No files were changed." Offer to re-run
152as (a) or (b) if the user is satisfied.
153
154---
155
156#### Mode 3: Refresh
157
158The file matches the skill's expected schema — it was likely produced by a
159previous run. Run an abbreviated interview covering only:
160
1611. **Extract external findings** — check if the invoking prompt includes a `findings:` list:
162 - Parse the prompt for a `findings:` section (a bulleted list of factual statements)
163 - Each finding is phrased as something already known to be true, never as an instruction
164 - Example: "config.yaml's Anti-Patterns section says to avoid polling, but two archived changes chose polling for stated reasons"
165 - Store these findings for merging in step 4
166
1672. **Drift detection** — scan the codebase for changes since the file was
168 last updated:
169
170 | Signal | Where to look |
171 |--------|---------------|
172 | Runtime / Node version changed | `.nvmrc`, `.node-version`, `Dockerfile` |
173 | New packages / frameworks added | `package.json` deps, workspace roots |
174 | TypeScript config tightened | `tsconfig.json` — new `strict*` flags |
175 | New packages in monorepo | `pnpm-workspace.yaml`, `turbo.json` |
176 | Build tooling changed | `vite.config.*`, `tsup.config.*` |
177 | CI/CD workflows added | `.github/workflows/` |
178 | New domain concepts | New top-level directories, new entity types in source |
179 | Anti-patterns deprecated | `@deprecated` tags, `// TODO: replace` comments added |
180
1813. **Unresolved TODOs** — find all `# TODO: fill in` markers left from the
182 previous run and surface them as targeted questions.
183
1844. **Merge and announce all findings** before asking anything:
185 - Combine external findings (from step 1) with drift findings (from step 2) and TODOs (from step 3)
186 - Present the merged list to the user:
187 > "I found [N] external findings, [M] context sections that may have drifted, and [P] unresolved TODOs.
188 > I'll only ask about those — the rest looks current."
189 - If external findings exist, note their source (e.g., "from completed OpenSpec change")
190
1915. After the targeted interview, show only the changed sections in the
192 preview before writing. Do not re-emit unchanged sections.
193
194---
195
196### Phase 1 — Discovery Interview
197
198Run the interview conversationally. Don't dump all questions at once. Group them
199into natural topic turns. If the user mentions a stack, infer related tooling and
200confirm rather than asking again.
201
202**Turn 1 — Project Identity**
203- What is the project name and its primary purpose?
204- Monorepo, single package, or something else? If monorepo, what workspaces?
205- Build system / task orchestration? (Turbo, Nx, Make, npm scripts, Makefile…)
206- Package manager and any private registries? (npm, pnpm, yarn, bun…)
207
208**Turn 2 — Tech Stack** *(ask as a grouped block, not one by one)*
209- Runtime and version (Node.js 20, Bun 1.x, Python 3.12, etc.)
210- Language + config (TypeScript strict? `exactOptionalPropertyTypes`? Python type
211 hints?)
212- Framework(s) and version (React 18, Next.js 14, Express, FastAPI, etc.)
213- Key domain libraries (Deck.gl, Apache Arrow, Prisma, SQLAlchemy, etc.)
214- Data layer (Postgres, MongoDB, DynamoDB, ORM/query builder, data formats)
215- Testing setup (Vitest, Jest, Pytest, testing-library, Playwright, etc.)
216- Linting / formatting (ESLint, Biome, Prettier, Black, Ruff, etc.)
217- Build tools (Vite, tsup, esbuild, Webpack, etc.)
218- CI/CD (GitHub Actions, CircleCI, etc.)
219- Versioning approach (Changesets, standard-version, conventional commits, etc.)
220
221**Turn 3 — Architecture**
222- How is the codebase organised? (feature-based, layer-based, domain-driven?)
223- Where does shared/utility code live?
224- Any path aliases? (`@/`, `~/`, `src/`, `#lib/`, etc.)
225- Design patterns commonly in use? (factory, repository, observer, CQRS, etc.)
226
227**Turn 4 — Domain Concepts**
228- What are the 3–5 most important domain entities?
229 *Example prompt: "For a mapping app this might be Layer, Source, Viewport,
230 Feature, Style."*
231- Any domain-specific terminology the AI should know?
232- Any specialised concepts with non-obvious meanings in this codebase?
233 *Example: "orchestration" means something specific to us — it's the runtime
234 layer that merges style with data, not a general workflow term.*
235
236**Turn 5 — Performance**
237- Any concrete performance targets? (p95 < 200 ms, 60 fps, < 50 MB heap, etc.)
238- Known hot paths or performance-critical areas?
239- Memory or bundle-size constraints?
240
241**Turn 6 — Code Patterns**
242- Export style: named exports, default exports, or mixed?
243- Naming conventions: files, variables, functions, constants?
244 *Example: "kebab-case files, camelCase vars, SCREAMING_SNAKE_CASE for
245 constants, PascalCase for types."*
246- Error handling: throw, `Result<T,E>`, error boundaries, something else?
247- Testing structure: `describe/it`, `test/expect`, AAA pattern?
248- Test file location: co-located with source or a separate `__tests__/` tree?
249- Fixture / factory approach for test data?
250
251> **Note:** Commit message convention is a workflow procedure — it belongs in
252> `AGENTS.md`, not here. If the user raises it now, capture it mentally and
253> surface it in the `accelint-onboard-agents` skill. Do not add it to `config.yaml`.
254
255**Turn 7 — Anti-Patterns**
256- Any patterns explicitly banned in code review?
257- Deprecated patterns still in the codebase that new code should NOT emulate?
258- Known performance traps specific to this stack?
259
260**Turn 8 — Proposal Rules**
261What does YOUR team require in a proposal? Good prompts:
262- "Do you need proposals to call out database migration impact?"
263- "Do you need proposals to flag API breaking changes?"
264- "Any security review checklist items?"
265
266**Turn 9 — Design Rules**
267Project-specific design concerns to encode? Good prompts:
268- "Docker / Kubernetes resource changes to document?"
269- "Performance implications section required?"
270- "Specific architecture diagram style (ASCII, Mermaid)?"
271
272**Turn 10 — Task Rules**
273- How do you tag tasks by package or module?
274 *Example: `[PKG:auth]`, `[MODULE:pipeline]`, GitHub labels…*
275- Rollback plan required for database changes?
276- Deployment-specific test gates (smoke tests, canary checks)?
277
278---
279
280### Phase 2 — Smart Defaults
281
282After each stack answer, surface relevant conventions to confirm. Use these
283examples as a pattern; extend to other stacks as appropriate.
284
285**Next.js + TypeScript + Tailwind → suggest confirming:**
286- App Router vs Pages Router and which patterns apply
287- Server Component vs Client Component boundary rules
288- `"use client"` directive placement convention
289- API route organisation (`app/api/` vs `pages/api/`)
290
291**React + Vitest + testing-library → suggest confirming:**
292- `userEvent` over `fireEvent` preference
293- `screen` query priority (role > label > testid)
294- `render` wrapper for providers
295
296**Python + FastAPI → suggest confirming:**
297- Pydantic v1 vs v2 (different field-validator syntax)
298- Dependency injection for DB sessions (`Depends`)
299- Alembic migration workflow
300- `lifespan` vs `startup`/`shutdown` event hooks
301
302**Node.js + Prisma → suggest confirming:**
303- `prisma.$transaction` patterns
304- Soft-delete vs hard-delete convention
305- Migration naming convention
306
307---
308
309### Phase 3 — Parallel Codebase Inference
310
311After the interview, spawn parallel discovery subagents to fill remaining config
312gaps. All config sections are load-bearing — a missing field degrades every
313downstream AI artifact, so inference is always preferable to omission.
314
315Spawn discovery subagents in parallel — don't scan serially. Each agent focuses
316on one inference domain and returns structured findings. Wait for all agents to
317complete, then merge results before Phase 4.
318
319**Spawn these agents simultaneously:**
320
321**Agent A — Stack & Build Tooling**
322- Runtime / Node version: `.nvmrc`, `.node-version`, `package.json#engines`, `Dockerfile`
323- TypeScript config: `tsconfig.json` (compilerOptions flags, paths aliases)
324- Package manager: `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml`, `bun.lockb`
325- Monorepo workspaces: `package.json#workspaces`, `pnpm-workspace.yaml`, `turbo.json`, `nx.json`
326- Build tools: `vite.config.*`, `webpack.config.*`, `tsup.config.*`, `esbuild` scripts
327- Return: runtime version, TS config flags, package manager, workspace list, build tools
328
329**Agent B — Testing & Code Quality**
330- Test framework: `vitest.config.*`, `jest.config.*`, `pytest.ini`, `pyproject.toml#tool.pytest`
331- Linting / formatting: `.eslintrc*`, `biome.json`, `.prettierrc*`, `ruff.toml`
332- Test structure: Sample test files — describe/it nesting depth, file location relative to source
333- Test file type checking: CI scripts, package.json — check if `tsc --noEmit` runs on `*.test.ts` files
334- Property-based testing: Check for `fast-check` in dependencies
335- Vitest mock cleanup: `vitest.config.ts` — check for `clearMocks`, `mockReset`, `restoreMocks`
336- Return: test framework, code quality tools, test structure patterns, type checking config
337
338**Agent C — Architecture & Code Patterns**
339- Architecture organisation: Directory tree of `src/` or workspace roots — infer feature-based vs layer-based
340- Path aliases: `tsconfig.json#compilerOptions.paths`, `vite.config#resolve.alias`
341- Design patterns: Sample source files — look for factory functions, repository objects, observer hooks
342- Export style: Sample 3–5 source files; tally named vs default exports
343- Naming conventions: Sample file names, exported identifiers; describe what you observe
344- Error handling: Grep for `throw`, `Result`, `Either`, `tryCatch`, error boundary components
345- TypeScript baseline patterns: If `tsconfig.json` exists, flag that TS/JS baseline patterns should be included
346- Return: architecture style, path aliases, design patterns, export conventions, naming patterns, error handling approach
347
348**Agent D — CI/CD & Versioning**
349- CI/CD: `.github/workflows/`, `.circleci/`, `Jenkinsfile`
350- Versioning: `.changeset/`, `CHANGELOG.md`, `commitlint.config.*`, `.releaserc*`
351- Anti-patterns: `eslint` rule overrides marked `off` or `warn`, comments like `// TODO: replace`, `@deprecated`
352- Return: CI/CD platform, versioning approach, documented anti-patterns
353
354**After all agents complete:** merge their findings into a unified inference map.
355Tag each field as `INFERRED [source]` or `UNKNOWN`. Fields tagged `UNKNOWN`
356should be marked as `# TODO: fill in` in the config preview.
357
358**For each field resolved via inference**, note the source in the preview with a
359trailing comment, e.g.:
360
361```yaml
362- Runtime: Node.js 20 LTS # inferred from .nvmrc
363- Language: TypeScript 5.4, strict, exactOptionalPropertyTypes # inferred from tsconfig.json
364```
365
366**If a field genuinely cannot be inferred** (e.g., performance targets, domain
367concepts, team-specific rules), mark it with `# TODO: fill in` rather than
368omitting it. The user can resolve these after reviewing the preview. Do not
369silently drop a section — an explicit TODO is a prompt to act; an absent section
370is an invisible gap.
371
372---
373
374### Phase 4 — Generation
375
3761. **Show a labeled preview** of the full config before writing anything.
377 Inferred values carry their source comment; unresolved fields carry
378 `# TODO: fill in`. This gives the user a complete picture of confidence level
379 across every field.
3802. Ask: *"Does this look right? Any sections to correct or expand before I write
381 the file?"*
3823. After confirmation, write to `openspec/config.yaml` (create directory if
383 needed), **stripping the inference source comments** — they are for review
384 only, not the final file. **For the Related Documentation section:** only include
385 links to files that actually exist in the repository. Check for each file
386 (ARCHITECTURE.md, AGENTS.md/CLAUDE.md, README.md) before including its link.
3874. **Validate the generated YAML** — after writing, read the file back and verify:
388 - No tabs (YAML requires spaces for indentation)
389 - Values with special characters are properly quoted
390 - No syntax errors (unmatched brackets, quotes, etc.)
391 - The file can be conceptually parsed as valid YAML
392 If validation reveals issues, fix them immediately and rewrite the file.
3935. Print a brief summary of what was configured, what was inferred vs answered
394 directly, and which `# TODO` fields still need human input.
395
396---
397
398## YAML Generation Safety Rules
399
400**CRITICAL:** YAML syntax is strict about special characters. Follow these rules when generating config.yaml to avoid syntax errors:
401
402### Quoting Requirements
403
404**Rule:** Values that start with special YAML characters need quoting.
405
406Special characters: `|`, `>`, `"`, `'`, `(`, `)`, `[`, `]`, `{`, `}`, `*`, `&`, `!`, `%`, `@`, `` ` ``
407
408**Examples:**
409```yaml
410# Parentheses at start of value
411❌ description: (internal) auth module # Syntax error
412✅ description: "(internal) auth module" # Quoted
413
414# Square brackets (looks like YAML list syntax)
415❌ tag: [PKG:auth] # YAML thinks it's a list
416✅ tag: "[PKG:auth]" # Quoted string
417
418# Pipe character (YAML thinks it's block scalar)
419❌ pattern: some|other # Syntax error
420✅ pattern: "some|other" # Quoted
421
422# Colon in value (YAML thinks it's a nested key)
423❌ note: Time: 5pm # Syntax error
424✅ note: "Time: 5pm" # Quoted
425
426# Value containing quotes - escape with opposite quote type
427✅ command: 'npm run "test:unit"' # Single quotes protect doubles
428✅ command: "npm run 'test:unit'" # Double quotes protect singles
429```
430
431### Multi-line String Handling
432
433Use block scalar indicators for multi-line content:
434
435```yaml
436# Literal block (preserves newlines) - preferred for context field
437context: |
438 Line 1
439 Line 2
440 Line 3
441
442# Folded block (folds newlines into spaces) - rarely needed
443description: >
444 This is a long
445 description that
446 flows together.
447```
448
449### Indentation Rules
450
451- **Use spaces only** — never tabs
452- **Consistent indent** — typically 2 spaces per level
453- **Block scalars** — content inside `|` or `>` must be indented relative to the key
454
455### Rules for List Values
456
457```yaml
458# Simple list items - no quotes needed for plain text
459rules:
460 proposal:
461 - Keep proposals under 100 lines
462 - Include scope boundaries
463
464# List items with special chars - quote them
465rules:
466 tasks:
467 - "Tag with [PKG:name] format" # Quotes protect [ and ]
468 - 'Use "Test:" prefix for validation' # Single quotes protect inner "
469```
470
471### Validation Checklist
472
473After generating the config, mentally verify:
4741. No bare `(`, `)`, `|`, `"`, `'` immediately after colons (unless using `|` or `>` for multiline)
4752. No tab characters anywhere in the file
4763. Consistent 2-space indentation throughout
4774. All list items (`-`) aligned at the same indent level within their parent
4785. Quoted strings use matching quote types
479
480If any of these rules are violated, the YAML will fail to parse.
481
482---
483
484## Config Template
485
486Use this exact structure. Fill every `[placeholder]` with content from the
487interview or codebase inference. If a field cannot be resolved by either means,
488replace its placeholder with `# TODO: fill in` — never omit the field. Every
489section is load-bearing for downstream AI artifact quality.
490
491```yaml
492schema: spec-driven
493
494# Project Context
495# Injected into every AI-generated artifact (proposal, design, spec, tasks).
496# QRSPI principle: objective research layer — facts only, no opinions.
497
498context: |
499 # ═══════════════════════════════════════════════════════════════════════════
500 # STACK FACTS
501 # ═══════════════════════════════════════════════════════════════════════════
502
503 ## Project Identity
504 [project name and one-sentence purpose]
505 [repo structure: monorepo / single-package / workspaces list]
506 [build system and task orchestration]
507 [package manager + registries]
508
509 ## Tech Stack
510 - Runtime: [e.g., Node.js 20 LTS]
511 - Language: [e.g., TypeScript 5.4, strict mode, exactOptionalPropertyTypes]
512 - Framework: [e.g., Next.js 14 App Router]
513 - Key Libraries: [domain-specific dependencies with versions]
514 - Data Layer: [databases, ORMs, data formats, query builders]
515 - Testing: [framework, utilities, coverage tooling]
516 - Linting/Formatting: [tools and config files in use]
517 - Build Tools: [bundlers, compilers, transpilers]
518 - CI/CD: [platform and key workflow names]
519 - Versioning: [release strategy and changelog tooling]
520
521 ## Architecture Patterns
522 - Organisation: [feature-based / layer-based / domain-driven / other]
523 - Shared code: [path to shared utilities / packages]
524 - Path aliases: [list of aliases and their resolved paths]
525 - Key patterns: [design patterns in common use]
526
527 ## Domain Concepts
528 - [Entity or concept]: [one-line definition]
529 - [Entity or concept]: [one-line definition]
530 - [Entity or concept]: [one-line definition]
531
532 ## Performance Targets
533 - [metric]: [target value and context]
534
535 ### TypeScript/JavaScript Performance (if applicable)
536 - Hot paths: [functions executed >1000 times per interaction or >100 times/sec]
537 - Frame budget: [for real-time systems: 60fps = 16.67ms, 120fps = 8.33ms]
538 - Constraints: Bounded iteration (explicit limits on loops/queues), O(n) or better algorithmic complexity
539
540 # ═══════════════════════════════════════════════════════════════════════════
541 # PATTERNS TO FOLLOW
542 # ═══════════════════════════════════════════════════════════════════════════
543
544 ## Code Patterns
545 - Exports: [named / default / mixed — and when each applies]
546 - Naming: [files, variables, functions, constants, types]
547 - Error handling: [throw / Result<T,E> / boundaries / other]
548 - Validation: [approach and library]
549 - Constants: Use `as const` objects, never `enum`
550 - Classes: Prefer functions over classes unless state management required or extending existing class
551 - Return values: Return zero values (empty array, empty string, 0, false) instead of null/undefined
552 - Leaf functions: Leaf functions (bottom of call stack) should be pure — same inputs produce same outputs, no side effects. Centralize state manipulation in parent/orchestrator functions.
553 - Type safety: Avoid `any` (use `unknown` or generics); avoid `enum` (use `as const` objects); use `type` over `interface`
554 - Immutability: Prefer `const`, immutable data structures, pure functions
555 - Documentation: Comprehensive JSDoc for all exported code (@param, @returns, @template, @example)
556 - Order: Internal functions, variables and types should be defined before they are used (internal/export types -> internal/export constants -> internal/export functions)
557 - Parameter order: Data-last ordering — place the data being operated on as the final parameter. Enables partial application and composition.
558 - Composition: Use curried functions when the same first parameter(s) recur across call sites.
559
560 ## Architecture Patterns
561 - [pattern name]: [brief description of how it's used here]
562
563 ## Testing Patterns
564 - Pattern: AAA (Arrange, Act, Assert) with clear boundaries
565 - Property-based: (If available) Use `fast-check` for encode/decode pairs, validators, normalizers, pure functions
566 - Test scope: Never test library internals; never export internals to test them; never mock own pure functions
567 - Structure: [describe/it nesting convention]
568 - File location: [co-located / __tests__ / other]
569 - Test doubles: Hierarchy: real implementation > fakes > stubs > spies > mocks
570 - Fixtures: [factory functions / fixture files / inline data]
571 - Assertions: [preferred assertion style]
572 - Nesting: Max 2 levels of describe blocks — use descriptive test names instead
573 - Verification: MUST run `tsc --noEmit` on test files before marking complete
574 - Benchmarks: [approach if any]
575
576 # NOTE: Commit message convention, PR workflow, and tool preferences
577 # are behavioral — they belong in AGENTS.md, not here.
578
579 # ═══════════════════════════════════════════════════════════════════════════
580 # PATTERNS TO AVOID
581 # ═══════════════════════════════════════════════════════════════════════════
582
583 ## Code Anti-Patterns
584 - Using `any` instead of `unknown` or generics
585 - Using `enum` instead of `as const` objects
586 - Using `interface` when `type` works (prefer type)
587 - Returning `null`/`undefined` instead of zero values (empty arrays, empty strings, 0, false)
588 - Not validating external data with schemas
589 - Deep nesting instead of early returns
590
591 - [anti-pattern]: [why it's banned or deprecated]
592
593 ## Performance Anti-Patterns
594 - Chaining array methods (`.filter().map().reduce()`) — use single reduce pass
595 - Using `Array.includes()` for repeated lookups (use `Set.has()` for O(1) lookups)
596 - Recomputing constants inside loops (hoist invariants outside)
597 - Unbounded loops or queues (set explicit limits to prevent runaway resource consumption)
598 - Placing `try/catch` in hot paths (V8 cannot inline, 3-5x slowdown)
599
600 - [anti-pattern]: [why it's banned or deprecated]
601
602 ## Testing Anti-Patterns
603 - Testing library internals (e.g., verifying Array.prototype.map works)
604 - Exporting internal functions just to test them
605 - Loose assertions in tests (toBeTruthy, toBeDefined)
606 - Nested describe blocks >2 levels deep
607 - Testing implementation details instead of behavior
608
609 - [anti-pattern]: [why it's banned or deprecated]
610
611 ## Documentation Anti-Patterns
612 - Missing JSDoc on exported functions/types
613 - Documenting HOW instead of WHAT/WHY in JSDoc
614 - Vague comment markers (`// TODO: fix this` instead of `// TODO: Replace with binary search for O(log n)`)
615
616# ═══════════════════════════════════════════════════════════════════════════
617# PER-ARTIFACT RULES
618# ═══════════════════════════════════════════════════════════════════════════
619
620rules:
621 proposal:
622 # QRSPI: Scope definition, not a plan.
623 - State the requirement or ticket driving this change
624 - Define scope boundaries — explicitly list what is OUT of scope
625 - Keep under 100 lines (tight and focused)
626 [user-specific proposal rules]
627
628 design:
629 # QRSPI: The "brain surgery" checkpoint — reviewed before any code is written.
630 # Target ~200 lines capturing current state, desired state, open questions.
631
632 # Required sections (in this order):
633 - Start with "Current State": what the code does today, key files, entry
634 points, relevant data flows
635 - "Desired End State": what changes after this work, what stays the same
636 - "Patterns to Follow": ONLY if specific files/functions to reference exist
637 for this change's domain
638 - "Patterns to Avoid": ONLY if specific anti-patterns apply to this change
639 - "Open Questions": genuine uncertainties requiring human input. If none,
640 state explicitly "No unresolved questions."
641 - "Resolved Decisions": numbered (Decision 1, Decision 2…) with Choice,
642 Rationale, Alternatives Considered
643
644 # Technical depth:
645 - Use ASCII diagrams for data flows, state machines, architecture
646 - Call out performance implications where relevant
647 [user-specific design rules]
648
649 # Constraints:
650 - Keep under 250 lines total
651
652 tasks:
653 # QRSPI: Vertical slicing for early failure detection.
654
655 # Vertical slicing (strong preference):
656 - Order as vertical slices — each task delivers a testable end-to-end path
657 - Do NOT group by architectural layer unless explicitly justified
658 - Horizontal (layer-by-layer) only for pure infrastructure; include
659 justification in the task description when used
660 - Each task MUST include an explicit "Test:" line describing what to verify
661 before proceeding to the next task
662 - Prefer 3–5 major slices; more than 5 suggests scope is too large
663
664 # Granularity:
665 - Max 2 hours per task; break larger work into subtasks
666 [user-specific task tagging, e.g., [PKG:name] or [MODULE:name]]
667 - Call out inter-task dependencies explicitly
668 [user-specific rollback requirements]
669 [user-specific deployment test gates]
670
671 spec:
672 - Use Given/When/Then for behaviour specifications
673 - Include concrete example data relevant to the domain
674 - Document edge cases explicitly
675 [user-specific spec rules]
676
677# ═══════════════════════════════════════════════════════════════════════════
678# RELATED DOCUMENTATION
679# ═══════════════════════════════════════════════════════════════════════════
680# Include only files that actually exist in the repository:
681# - ARCHITECTURE.md: System overview, deployment, component interactions, data flows
682# - AGENTS.md: Agent behavior rules, workflow procedures, communication style
683# - README.md: Installation, quick start, usage guide
684```
685
686---
687
688## Interaction Principles
689
690- **Conversational, not interrogative.** Bundle related questions into a single
691 turn. Use natural language, not bullet-dump forms.
692- **Infer and confirm.** "You mentioned Vitest — I'll assume you're using
693 `@testing-library/react` for component tests; correct?" is better than asking
694 from scratch.
695- **Examples reduce ambiguity.** When asking about naming conventions, give an
696 example first so the user can pattern-match.
697- **Iterative.** Let the user amend answers. Don't lock them into the first
698 response.
699- **Preview before writing.** Always show the full generated config and get
700 explicit confirmation before touching the filesystem.
701- **Infer before asking, ask before omitting.** Always attempt codebase
702 inference for any unanswered field. If inference fails, surface a `# TODO`
703 rather than dropping the section. A config with explicit TODOs is actionable;
704 a config with missing sections silently degrades every artifact it drives.