Project Documentation
Overview
Maintains two documentation layers: operational docs (what happened, what needs doing, what exists) and a hierarchical architecture map (how the project works, how components integrate). The architecture map gives AI agents instant project understanding without scanning code.
Session Start Check
At the start of every session, check if documentation exists. Create from templates if missing.
Operational Docs (existing — unchanged)
| File | Purpose | Create If Missing |
|---|---|---|
history.md |
Activity log — every change, dated | Yes |
tasks.md |
Task tracker — priorities, status, blockers | Yes |
index.md |
File/directory index | Yes |
session_control.md |
Active session tracker | Yes |
Templates for these are unchanged from the original skill. See operational-templates section below.
Cross-tool instruction files (also check at session start)
In addition to the operational docs above, check for cross-CLI instruction files:
| File | Purpose | Notes |
|---|---|---|
AGENTS.md |
Canonical agent instructions — read by GitHub Copilot CLI natively, by Codex CLI natively, by Gemini via @AGENTS.md import. Recommended as the source of truth in the cross-tool canonical pattern. |
If absent and the project should support multiple AI CLIs, suggest creating it |
CLAUDE.md |
Claude Code instructions. May be a symlink or @AGENTS.md import. If divergent from AGENTS.md, that's a coordination issue. |
Existing user pattern: ~/.claude/AGENTS.md -> ~/.claude/CLAUDE.md (symlink in either direction works) |
GEMINI.md |
Gemini CLI instructions. Should typically be @AGENTS.md import. |
Verify Gemini supports the import syntax |
.github/copilot-instructions.md |
Generated by copilot init, repo-scoped Copilot instructions. |
If present, treat as project-canonical for Copilot; cross-reference with AGENTS.md |
.github/instructions/**/*.instructions.md |
Path-scoped Copilot instructions (UNVERIFIED feature) | Optional, advanced |
See research-for-skills/cross-tool-portability/agents-md-canonical.md for the canonical pattern. The user's existing setup uses a ~/.claude/AGENTS.md -> ~/.claude/CLAUDE.md symlink, with CLAUDE.md as the source — this is inverted from the recommended pattern but works for Claude + Codex.
Architecture Map (new)
| File | Level | Purpose | Create If Missing |
|---|---|---|---|
PROJECT.md |
0 | Project overview, component map, integration edges | Yes — on first session |
docs/components/<id>/COMPONENT.md |
1 | Component internals, interfaces, internal flow | Yes — per detected component |
docs/components/<id>/<slug>.md |
2 | Sub-component detail (opt-in, hotspots only) | No — only when threshold met |
Required Directories
| Directory | Purpose | Create If Missing |
|---|---|---|
docs/ |
Documentation root | Yes |
docs/plans/ |
Design documents from forge | Yes |
docs/components/ |
Component architecture docs | Yes |
docs/flows/ |
Application flow diagrams | Yes |
research/ |
Research outputs | Yes |
Architecture Map
What It Is
A layered documentation hierarchy optimized for AI agent consumption:
Level 0: PROJECT.md — whole project, 10,000-foot view (max 120 lines)
Level 1: COMPONENT.md — one major component, interfaces + flow (max 160 lines)
Level 2: <slug>.md — sub-component detail, opt-in only (max 80 lines)
| Level | Question Answered | Who Reads First |
|---|---|---|
| 0 | "What is this project and how do pieces fit together?" | forge, any new agent |
| 1 | "How does this component work and what does it expose?" | team-manager, specialists |
| 2 | "How is this sub-area implemented?" | coding agents on specific files |
Templates
See architecture-templates.md for full templates with metadata headers. Key points:
Every architecture doc has a YAML metadata header:
---
doc_type: project | component | subcomponent
id: unique-identifier
status: active | draft | deprecated
owned_paths: [paths this doc covers]
depends_on: [other component ids]
last_verified_at: YYYY-MM-DD
confidence: high | medium | low
---
PROJECT.md must contain:
- Purpose (2-3 lines)
- Components table (id, purpose, doc link)
- Interaction Edges table (canonical — from, to, interface, mode, failure_impact)
- External Dependencies table
- Entry Points table
COMPONENT.md must contain:
- Purpose (2-3 lines)
- Public Interfaces table (name, type, consumers, contract)
- Consumed Interfaces table
- Internal Flow (table or ASCII)
- Key Files (max 8 — not a full file map)
Test Framework Auto-Detection (when creating PROJECT.md)
When creating PROJECT.md for a new project, auto-detect the test framework to populate the Testing section:
- Check
package.jsonscripts.testfield - Check
pyproject.toml[tool.pytest]section - Check
MakefileorTaskfilefor test targets - Check CI config files (
.github/workflows/,.gitlab-ci.yml) - Scan for test directories:
tests/,test/,__tests__/,spec/
Populate the Testing table with discovered commands. Leave unknown fields as [not detected].
Component Detection (First Run)
On first session in a project without PROJECT.md:
- Scan for component roots:
src/*/,app/*/,services/*/,packages/*/, top-level packages with own entrypoint - Exclude non-components:
tests/,utils/,helpers/,common/, vendor/generated dirs - Score candidates: own startup path (+3), own config (+2), depended on by 2+ peers (+2), external service (+2), mostly shared helpers (-3)
- Present to user for confirmation: show detected components with confidence, let user adjust
- Create PROJECT.md + COMPONENT.md stubs for confirmed components
Subcomponent Threshold (Level 2 — opt-in only)
Do NOT create subcomponent docs by default. Only create when:
- Component exceeds its 160-line budget and needs splitting
- Sub-area has edge cases likely to cause regressions
- Sub-area implements protocol translation, auth, caching, or state machines
- Sub-area owns 5+ key files with a stable local contract
Gap Detection
Before routing to a child skill (architecture-templates, cascade-rules, flow-diagrams, context-detection):
- Verify target exists (check
~/.claude/skills/<path>) - If missing: follow gap-detection protocol at
~/.claude/skills/research-for-skills/gap-detection.md - If exists: invoke with context
Context-Aware Update Cascading
The skill must determine WHO is calling it and at WHAT level to decide what to update. See cascade-rules.md for full decision tree.
Caller Detection
| Caller | How to Detect | Typical Scope |
|---|---|---|
| forge | Design phase, creating architecture | Creates/updates PROJECT.md + COMPONENT.md stubs |
| team-manager | Assigned as coordinator | Updates COMPONENT.md, creates subcomponent if threshold met |
| coding agent | Working on specific files | Updates subcomponent/COMPONENT.md internals |
| user directly | Direct session | Any level — determined by what changed |
Cascade Gate
"Does this change affect how this component INTERACTS with other components, external services, or entry points?"
- YES → cascade up one level. Each level independently re-evaluates.
- NO → update current level only.
Change Classification (5 types)
| Type | Example | Doc Update |
|---|---|---|
| Trivial | Comments, formatting, variable rename, tests for unchanged behavior | None |
| Internal implementation | Algorithm swap, refactor within component | COMPONENT.md internals only if material |
| Local contract | Sub-area changes input/output within same component | Sub-area doc + COMPONENT.md |
| Component boundary | New/changed public interface, new consumed dependency | COMPONENT.md + PROJECT.md (same session) |
| Project topology | New component, new external service, new entry point | PROJECT.md + affected COMPONENT.md files |
Ownership Rule
The actor that makes the change updates ALL affected levels in the same session. Do NOT defer PROJECT.md updates to a separate async follow-up — that guarantees drift.
| Situation | Owner |
|---|---|
| Single-agent change | Same agent updates all affected levels |
| Multi-agent component work | Component owner updates COMPONENT.md; coordinator reconciles PROJECT.md before task close |
| New component / cross-component contract change | Coordinator updates PROJECT.md immediately |
Documentation Preferences (Ask Once Per Project)
On first init, ask user (one at a time). Save to docs/DOCUMENTATION-PREFERENCES.md.
- Confluence export? A) Yes B) No C) Both — if yes, invoke
confluence-documentationskill - Screenshots? A) Yes B) No C) UI-only — if yes, store in
docs/screenshots/ - Flow diagrams? A) Visual (generated images) B) Text-based (Mermaid/ASCII) C) None
On subsequent sessions: read preferences file, don't re-ask.
Integration with Other Skills
Forge
- Step 1: check for PROJECT.md, create if missing (with component detection)
- Step 8: after design approval, create COMPONENT.md stubs for new components
- Step 11: verify architecture docs match what was built, update PROJECT.md edges
Team-Manager
- Reads PROJECT.md (context) + COMPONENT.md (interfaces) before task decomposition
- Updates COMPONENT.md after specialists complete work
- Flags topology changes for PROJECT.md update
Agent-Teams
- Reads PROJECT.md for cross-team context
- Updates PROJECT.md when component boundary changes detected
Development Lifecycle
- DOCUMENT phase: update history.md, index.md, and applicable architecture level
Context Detection
Determines whether work is standalone or part of an integrated system, maps dependencies, and identifies impact radius before changes. See context-detection.md for full detection flow, scanning methods, and integration patterns.
Any skill can call this. Not forge/bob/PA-specific.
Detection Flow (Summary)
1. Check PROJECT.md → integrated project? Read component map.
2. Check package manifests → dependencies list.
3. Match CWD to component owned_paths → which component am I in?
4. Check who consumes this component → downstream impact.
5. Score dependency depth → standalone / component / library / service.
Context Types
| Type | When | Testing Impact |
|---|---|---|
| standalone | No PROJECT.md, no consumers, single entry point | Test locally only |
| component | Inside documented component, has consumers/providers | Test this + integration points |
| library | Multiple consumers import from this | Must preserve public API, test all consumers |
| service | Own entry point + API consumers + external deps | Check API contract, coordinated deployment |
When to Run
- Before any task that modifies code or configuration
- Skip for read-only queries and pure documentation tasks
- Re-run if PROJECT.md or package manifests changed since last detection
Breaking Change Check
When context detection finds consumers and the task changes a public interface:
- Flag the change with consumer count
- List affected consumers with file paths
- Recommend: update consumers or add backward compatibility
Flow Diagrams
Documents application flows — any chain of actions through the system, whether triggered by a user, scheduler, event, or internal process. See flow-diagrams.md for full templates, formats, and conventions.
When to Create
Create a flow diagram when:
- New feature has 3+ steps in sequence
- 3+ components interact for a specific use case
- Process has decision points, branches, or retry logic
- Entity has 4+ state transitions
- Scheduled/background process with non-obvious behavior
- AI/LLM pipeline (prompt build → model call → parse → validate)
- Integration between systems (pull → transform → push)
Flow Types
| Type | Prefix | Trigger |
|---|---|---|
| User-initiated | user- |
User action starts the chain |
| System-initiated | system- |
Scheduler/cron/timer |
| Event-driven | event- |
Webhook/message/signal |
| Background process | worker- |
Queue consumer/polling loop |
| Integration | integration- |
System-to-system exchange |
| State machine | state- |
Entity lifecycle |
Where They Live
docs/flows/<type>-<name>.md
Each flow doc has YAML metadata, a Mermaid or ASCII diagram (per documentation preferences), a steps table, and error paths. Max 80 lines per file, max 15 steps per diagram.
Integration with Architecture Docs
- PROJECT.md: add a "Key Flows" table linking entry points to flow docs
- COMPONENT.md: add a "Related Flows" table showing what flows each component participates in
Update Triggers
| Change | Action |
|---|---|
| New multi-step feature | Create flow doc |
| Step added/removed | Update flow doc |
| Component added/removed from flow | Update flow doc + COMPONENT.md |
| Flow involves 3+ components | Update PROJECT.md Key Flows |
| Flow removed | Mark deprecated, remove from Key Flows/Related Flows |
Operational Doc Updates
- history.md — after every implementation (date, action, files, reason)
- index.md — when files created or deleted
- tasks.md — status flow:
todo→in-progress→review→done - session_control.md — claim slot at session start, release at end
History rotation policy
history.md is read on every session start and grows unbounded by default — eventually it dominates the context budget. This skill enforces a bounded-size policy with monthly archives.
Defaults
| Knob | Default | Override path |
|---|---|---|
N (target session count) |
3 | docs/DOCUMENTATION-PREFERENCES.md history_rotation: block |
CAP (line ceiling, circuit-breaker) |
600 | same |
MIN_SESSION_LINES (merge-tiny floor) |
20 | same |
mode |
auto |
auto / suggest / never |
Override example (inline):
history_rotation: { N: 5, CAP: 800, mode: suggest }
Or block form:
history_rotation:
N: 5
CAP: 800
mode: suggest
File layout after rotation
<project-root>/
├── history.md # live; ≤ N sessions OR ≤ CAP lines
├── history.md.pre-rotation-bak # one-level undo (overwritten on next roll)
└── history/ # archives, created on first roll
├── INDEX.md # auto-maintained TOC (regenerated each roll)
├── 2026-04.md # monthly bucket
├── 2026-03.md
└── pre-rotation-bulk.md # only if E2 bulk-archive was chosen at first-touch
Auto-roll on every history.md write (scripts/rotate.py)
After every append, the rotation engine counts session markers (S) and total lines (L). If S ≤ N AND L ≤ CAP, it appends silently (~95% of writes; <50ms hot path). Otherwise it archives the oldest session into history/<YYYY-MM>.md (file created if absent), recounts, and repeats. Floor: if S=1 (or S=0 / unparseable) and L > CAP, the file is kept with a floor_warning header — content is never silently dropped.
Every rotation:
- Acquires
flockon<live_history_dir>/.history.lock(5s timeout) - Records mtime before read; aborts if changed mid-rotation (user-edit guard)
- Backs up to
history.md.pre-rotation-bakbefore any archive write - Writes archives + live atomically (temp +
os.replace) - Verifies sha256(backup) == sha256(original) before declaring success
- Rolls back (delete archives, restore
.pre-rotation-bak) on any failure - Adds an idempotency stamp
<!-- rotated: <iso-ts> by=<actor> schema=v1 sha256=<hex> -->so re-runs are no-ops
First-touch evergreen migration (scripts/first_touch.py)
When this skill runs at session start in a project where history.md exists, lacks the rotation stamp, and exceeds 100 lines, it computes a plan and asks the operator (one-time per project):
- E1. Bucket-by-date — parse + archive into monthly buckets; current behavior of auto-roll on subsequent writes
- E2. Bulk-archive — move whole file to
history/pre-rotation-bulk.mdunchanged; start with a stub (ALWAYS-SAFE, no parsing) - E3. Skip — make no changes; ask again next session (default if no answer)
- E4. Never — write
mode: nevertoDOCUMENTATION-PREFERENCES.md; no auto-rotation ever
After any path, the file is stamped — operator is never prompted again for this project. No bulk migration. Rotation attaches per project on natural session entry.
Manual override
| Surface | Invocation |
|---|---|
| Claude Code | /roll [flags] (slash command at ~/.claude/commands/roll.md) |
| Codex CLI | Skill('project-documentation', args='roll [flags]') |
| Direct CLI | python ~/.claude/skills/project-documentation/scripts/rotate.py <project> [flags] |
| Power-user proactive | python ~/.claude/skills/project-documentation/scripts/migrate.py <path> (default --dry-run; --apply to execute) |
Flags: --dry-run (preview), --keep N / --cap N (overrides), --restore (one-level undo), --force (bypass floor).
Boundary detection ladder (scripts/_boundary_detect.py)
Used by rotate and first_touch to find session boundaries in unstamped files. Priority order, first tier with ≥2 matches AND <30% ambiguous lines wins:
H1 explicit <!-- SESSION_BOUNDARY --> → H2 ## Session N → H3 ## YYYY-MM-DD → H4 ### S\d+ → H5 ### YYYY-MM-DD → F1 paragraph heuristic → F2 lossy-safe bulk
F2 is preferred over a low-confidence parse: a bad parse silently drops/duplicates content; F2 (whole file as one unit) loses bucketing convenience but never loses content.
Code-fence-aware: heading patterns inside ``` and ~~~ blocks are ignored.
Rotation anti-patterns
| Don't | Why |
|---|---|
Edit history.md.pre-rotation-bak |
It's the one-level-undo target; treat as read-only |
Edit between <!-- HISTORY_HEADER --> markers |
Auto-managed; the next roll will overwrite |
Delete history/INDEX.md manually |
It's regenerated; deleting just causes a re-write next roll |
| Bulk-migrate the fleet | Per-project on session entry; no batch scripts |
Set mode: never casually |
The file grows unbounded; only do this for archived projects |
Size Constraints
| Document | Max Lines | Max Components/Items |
|---|---|---|
| PROJECT.md | 120 | 12 components, 10 interaction edges |
| COMPONENT.md | 160 | 8 key files, 12 public interfaces |
| Subcomponent doc | 80 | Only for genuine hotspots |
When a doc exceeds its limit: group components, split hot areas, or promote sub-areas.
Anti-Patterns
| Don't | Why |
|---|---|
| Skip updating history.md after changes | History gaps make debugging impossible |
| Let architecture docs go stale | Stale architecture is worse than none — actively misleading |
| Create subcomponent docs for everything | Over-documentation increases context cost, not value |
| Defer PROJECT.md updates to later | Async handoffs guarantee drift |
| Duplicate file listings between index.md and COMPONENT.md | Key Files (max 8) in COMPONENT.md, full listing in index.md |
| Use diagrams as canonical integration map | Edge table is canonical; diagrams are convenience |
| Create PROJECT.md without user-confirmed components | Auto-detection needs user validation |
| Update docs for trivial changes | Comments, formatting, variable renames need no doc update |