Skip to content

Project Structure

Everything durable lives under specs/; the queue and conversation live in the GitHub issue. Nothing else is permanent.

project/
├── specs/
│   ├── product.md          # mental models + flows
│   ├── glossary.md         # ubiquitous language (optional, recommended)
│   ├── decisions/          # NNNN-<slug>.md decision records
│   ├── queues/             # <name>.md local fallback, only when gh is unavailable
│   └── <feature>/
│       └── spec.md         # load-bearing contract
├── .agents/skills/         # generated skills (canonical)
└── .claude/skills/         # symlinks for Claude Code (only with --tools claude)

specs/product.md — what we are

Mental models, what the project is and isn't, 2–3 representative flows. Human + agent maintained. Every plan/build/review session reads it first.

specs/glossary.md — shared words

Curated ubiquitous language — only terms that are shared, stable, and ambiguous enough to matter. litespec-plan reads it and nudges when a new term appears; other skills consult it without enforcement. Missing file degrades gracefully. See Glossary. One line per term:

- **Widget**: a customer-visible unit of work in the dashboard. Not a database row. Not a UI component.

specs/decisions/NNNN-<slug>.md — durable rulings

Standing architectural reasoning that spans files — why not the obvious road. Created with touch + validate; no CLI. Never deleted after a feature ships; supersede instead.

---
spine: true
---

# Title

## Status
proposed | accepted | superseded

## Context
## Decision
## Consequences

spine: true marks load-bearing decisions that view stars. The bar is high: real contention (someone argued the other road, or observably will) plus no better home (a line comment fits a one-line change; decisions hold reasoning with no single line to attach to). Context records what was measured; Consequences state what would justify revisiting.

specs/<feature>/spec.md — load-bearing contracts

One file per load-bearing feature. Edited in place — no staging, no approved layer, no lifecycle markers. Only promises that break things when wrong earn a spec.

# <feature>

## Requirements

### Requirement: <name>
Body must contain SHALL or MUST.

#### Scenario: <short name>
- **WHEN** <condition>
- **THEN** <outcome>

Small fixes edit it directly; litespec-plan drafts it in clear mode for new features.

specs/queues/<name>.md — offline fallback only

A 1:1 mirror of the GH issue body (Base:/Branch: + proposal + design + queue), written only when gh is unavailable. <name> is the change name from plan[clear]. When gh works, the issue is the queue and this directory stays empty. Local receipts append as Evidence: blocks under their unit; routing metadata appends after all units in separate commits.

.agents/skills/ and .claude/skills/

Canonical generated skills — one SKILL.md plus references/ per skill, regenerated by litespec update from internal/skill/templates/:

.agents/skills/
├── litespec-plan/      # fuzzy/clear + grilling, codebase-design, domain-modeling
├── litespec-build/     # one unit + review-fixing
└── litespec-review/    # adversarial review

--tools claude symlinks these into .claude/skills/ because Claude Code doesn't read .agents/. Project-specific skills (like the-drill) live beside them as tracked files — never generated, never overwritten, ignored by stale-skill detection.

The two lanes on this structure

  • Small fix: read product + relevant spec + decisions/glossary, edit code and spec in place, stop. No issue, no branch.
  • New feature: plan[clear] records Base: + Branch: and creates litespec/<change-name> — all branch work belongs to the issue. build implements one unit at a time there; review screens every local path before reading it. The issue closes only when every unit checkbox is checked, every rebuild request is resolved, review returns PASS, and the issue's Branch: is merged (decision 0008) — merge first, then close.