Project 23: Documentation Generator (Auto-Docs on Commit)
Project 23: Documentation Generator (Auto-Docs on Commit)
Build a hook system that automatically generates or updates documentation when code changes - keeping docs in sync with implementation forever.
Learning Objectives
By completing this project, you will:
- Understand documentation debt and why it accumulates in software projects
- Master git diff analysis to detect meaningful code changes
- Implement incremental documentation updates rather than full rewrites
- Design multi-target documentation (JSDoc, README, CHANGELOG)
- Apply steering rules to maintain consistent documentation style
Deep Theoretical Foundation
The Documentation Debt Problem
Documentation is one of the first casualties of tight deadlines:
Documentation Debt Accumulation:
Week 1: Week 4: Week 12: Week 52:
โโโโโโโ โโโโโโโ โโโโโโโ โโโโโโโ
โCode โ โCode โ โCode โ โCode โ
โ 100%โ โ 400%โ โ1200%โ โ5200%โ
โโโโโโโค โโโโโโโค โโโโโโโค โโโโโโโค
โDocs โ โDocs โ โDocs โ โDocs โ
โ 100%โ โ 110%โ โ 150%โ โ 200%โ
โโโโโโโ โโโโโโโ โโโโโโโ โโโโโโโ
Gap: 0% 72% 88% 96%
โ โ โ โ
Perfect Growing Critical Hopeless
Why this happens:
- Writing docs feels like โextra workโ
- Code changes faster than docs can track
- No immediate feedback when docs are wrong
- Reviewers donโt read docs carefully
The AI Solution:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Code Change Event โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Documentation Generator โ
โ โโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโ โ
โ โ Analyze Change โโโโ Generate Docs โโโโ Apply Updates โ โ
โ โโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Documentation Always in Sync โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Git Diff Analysis
Understanding git diffs is essential for detecting what documentation needs updating:
Git Diff Anatomy:
diff --git a/src/services/user.ts b/src/services/user.ts
index 1234567..abcdefg 100644
--- a/src/services/user.ts โโโ Old file
+++ b/src/services/user.ts โโโ New file
@@ -10,6 +10,15 @@ class UserService { โโโ Hunk header
(line 10, 6 lines old
line 10, 15 lines new)
async create(data: CreateUserDto) {
- return this.db.insert(data); โโโ Removed line
+ // Validate email format โโโ Added lines
+ if (!isValidEmail(data.email)) {
+ throw new ValidationError('Invalid email');
+ }
+ return this.db.insert(data);
}
// New method added โโโ Entirely new section
+ async findByEmail(email: string): Promise<User | null> {
+ return this.db.findOne({ email });
+ }
Diff Classification:
Change Types for Documentation:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Change Type โ Documentation Impact โ
โโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ New function โ Generate new JSDoc, update README API sectionโ
โ Changed params โ Update JSDoc @param, check README examples โ
โ New class โ Create class documentation block โ
โ Removed export โ Remove from API docs, add CHANGELOG entry โ
โ Bug fix โ CHANGELOG entry only โ
โ Refactor โ Usually no doc changes needed โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Documentation Layers
Modern projects have multiple documentation layers, each serving different audiences:
Documentation Layer Hierarchy:
Layer 1: INLINE (for developers reading code)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ /** โ
โ * Creates a new user with the given data. โ
โ * @param data - User creation payload โ
โ * @param data.email - Must be unique in system โ
โ * @returns The created user with generated ID โ
โ * @throws {ValidationError} If email format is invalid โ
โ * @example โ
โ * const user = await service.create({ email: 'a@b.com' }); โ
โ */ โ
โ async create(data: CreateUserDto): Promise<User> โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Layer 2: README (for new developers)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ ## User Service โ
โ โ
โ Handles user CRUD operations. โ
โ โ
โ ### Methods โ
โ - `create(data)` - Create new user โ
โ - `findById(id)` - Find user by ID โ
โ - `update(id, data)` - Update existing user โ
โ โ
โ ### Example โ
โ ```typescript โ
โ const service = new UserService(db); โ
โ await service.create({ email: 'user@example.com' }); โ
โ ``` โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Layer 3: CHANGELOG (for users/stakeholders)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ ## [1.2.0] - 2024-01-15 โ
โ โ
โ ### Added โ
โ - User service now validates email format before creation โ
โ - New `findByEmail()` method for email-based lookups โ
โ โ
โ ### Changed โ
โ - `create()` now throws ValidationError for invalid emails โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Layer 4: API REFERENCE (for API consumers)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Generated from JSDoc โ TypeDoc/Docusaurus โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Incremental vs. Full Generation
Regenerating all documentation on every change is wasteful and loses human edits:
Full Regeneration (BAD):
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ
โ Change 1 line of code โ Regenerate 500 lines of docs โ
โ โ
โ Problems: โ
โ โข Slow (processes everything) โ
โ โข Loses manual improvements โ
โ โข Churns git history โ
โ โข May introduce inconsistencies โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Incremental Updates (GOOD):
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ
โ Change 1 line of code โ Update 3 lines of docs โ
โ โ
โ Benefits: โ
โ โข Fast (only processes changes) โ
โ โข Preserves human edits elsewhere โ
โ โข Minimal git diff โ
โ โข Maintains consistency โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Incremental Update Strategy:
1. Parse old file โ AST with existing docs
2. Parse new file โ AST with current code
3. Diff the ASTs โ Identify changed functions/classes
4. For each change:
- If doc exists: Update in place
- If new export: Generate new doc
- If removed: Flag for removal
5. Preserve unchanged documentation
JSDoc Standard
JSDoc is the de facto standard for JavaScript/TypeScript documentation:
JSDoc Tag Reference:
โโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Tag โ Purpose โ
โโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ @param {Type} โ Document function parameter โ
โ @returns {Type} โ Document return value โ
โ @throws {Error} โ Document exceptions thrown โ
โ @example โ Provide usage example โ
โ @deprecated โ Mark as deprecated with reason โ
โ @see โ Reference related documentation โ
โ @since โ Version when added โ
โ @async โ Indicate async function โ
โ @private โ Mark as internal/private โ
โ @public โ Mark as public API โ
โโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Real-World Analogy: The Technical Writer Assistant
Imagine having a technical writer who:
- Watches over your shoulder as you code
- Notices every change you make
- Updates the manual section by section
- Tracks whatโs new for the release notes
- Never gets tired or forgets to update
Thatโs what youโre building - an AI documentation assistant that never sleeps.
Historical Context
Documentation tooling has evolved significantly:
Documentation Evolution:
1980s: Manual (man pages, comments)
โโโบ Hand-written, easily outdated
1990s: JavaDoc/Doxygen
โโโบ Generate from structured comments
2000s: Wiki-style (Confluence, MediaWiki)
โโโบ Collaborative but disconnected from code
2010s: Docs-as-Code (Sphinx, MkDocs)
โโโบ Version controlled with code
2020s: AI-Assisted โโโโ YOU ARE HERE
โโโบ Auto-generated, always synchronized
Book References
For deeper understanding:
- โDocs Like Codeโ by Anne Gentle - Treating documentation as code
- โLiving Documentationโ by Cyrille Martraire - Documentation that evolves with code
- โThe Art of Readable Codeโ by Boswell & Foucher - Self-documenting code principles
- โTechnical Writing for Software Developersโ by Chris Chinchilla - Professional tech writing
Complete Project Specification
What You Are Building
A hook-based documentation system that:
- Triggers on code changes via PostToolUse hooks
- Analyzes git diffs to understand what changed
- Updates inline documentation (JSDoc/TSDoc)
- Maintains README sections for API documentation
- Generates CHANGELOG entries for version tracking
Functional Requirements
| Feature | Behavior |
|---|---|
| JSDoc Generation | Add/update JSDoc for new/changed functions |
| README Updates | Keep API sections synchronized |
| CHANGELOG Entries | Generate entries for significant changes |
| Style Consistency | Follow project documentation conventions |
| Human Override | Never overwrite intentional human edits |
Non-Functional Requirements
- Latency: Complete documentation updates within 15 seconds
- Accuracy: Generated docs accurately describe the code
- Non-Destructive: Never lose existing manual documentation
- Configurable: Support different documentation styles
Solution Architecture
High-Level Component Diagram
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Kiro CLI โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ Agent Session โโ
โ โ โโ
โ โ [Writes/modifies src/services/user.ts] โโ
โ โ โ โโ
โ โโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ postToolUse event
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Documentation Generator Hook โ
โ โ
โ โโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโ โ
โ โ Git Diff โ โ Change โ โ Doc Target โ โ
โ โ Analyzer โ โ Classifier โ โ Identifier โ โ
โ โ โข Parse diff โ โ โข New func? โ โ โข JSDoc? โ โ
โ โ โข Extract โ โ โข Modified? โ โ โข README? โ โ
โ โ hunks โ โ โข Removed? โ โ โข CHANGELOG? โ โ
โ โโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโ โ
โ โ โ โ โ
โ โโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ AI Doc Generator โ โ
โ โ โข Build context โ โ
โ โ โข Call Kiro โ โ
โ โ โข Parse response โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Doc Applier โ โ
โ โ โข Merge updates โ โ
โ โ โข Preserve manual โ โ
โ โ โข Write files โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Data Flow: JSDoc Update
1. Code Change Detected
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ src/services/user.ts: โ
โ โ
โ - async create(data: CreateUserDto) { โ
โ + async create(data: CreateUserDto, options?: CreateOptions) { โ
โ return this.db.insert(data); โ
โ } โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
2. Change Classification
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Change Type: MODIFIED_SIGNATURE โ
โ Function: create โ
โ Changes: โ
โ - Added parameter: options?: CreateOptions โ
โ Documentation Impact: โ
โ - Update @param for new parameter โ
โ - Review @example if it uses this function โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
3. Existing Doc Analysis
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Current JSDoc: โ
โ /** โ
โ * Creates a new user. โ
โ * @param data - User creation payload โ
โ * @returns The created user โ
โ */ โ
โ โ
โ Missing: @param options documentation โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
4. Generate Update
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Updated JSDoc: โ
โ /** โ
โ * Creates a new user. โ
โ * @param data - User creation payload โ
โ * @param options - Optional creation configuration โ
โ * @param options.skipValidation - Skip email validation โ
โ * @returns The created user โ
โ */ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Key Interfaces
// Change detection
interface CodeChange {
file: string;
type: 'added' | 'modified' | 'deleted';
functions: FunctionChange[];
classes: ClassChange[];
}
interface FunctionChange {
name: string;
changeType: 'new' | 'signature_changed' | 'body_changed' | 'removed';
oldSignature?: string;
newSignature?: string;
oldDoc?: string;
}
// Documentation targets
interface DocUpdate {
target: 'jsdoc' | 'readme' | 'changelog';
file: string;
location: {
startLine: number;
endLine: number;
} | 'append';
content: string;
operation: 'insert' | 'replace' | 'delete';
}
// Configuration
interface DocGeneratorConfig {
targets: ('jsdoc' | 'readme' | 'changelog')[];
jsdoc: {
style: 'jsdoc' | 'tsdoc';
includeExamples: boolean;
includeReturns: boolean;
includeSince: boolean;
};
readme: {
apiSection: string; // "## API Reference"
autoUpdate: boolean;
};
changelog: {
format: 'keepachangelog' | 'conventional';
unreleased: boolean;
};
}
Technology Choices
| Component | Technology | Rationale |
|---|---|---|
| Hook Runtime | Bun | Fast TypeScript execution |
| Git Operations | simple-git | Reliable diff parsing |
| AST Parsing | @typescript-eslint/parser | Accurate code analysis |
| Doc Generation | Kiro CLI | AI-powered content |
| Markdown Parsing | remark | README manipulation |
Phased Implementation Guide
Phase 1: Change Detection (Days 1-2)
Goal: Detect and classify code changes from git diff.
Tasks:
- Set up PostToolUse hook for
writetool - Run
git diffon the changed file - Parse diff to extract changed functions
- Classify changes (new, modified, deleted)
- Log classification results
Hints:
- Use
git diff HEAD -- <file>for uncommitted changes - Parse unified diff format with regex or library
- Focus on function/class level, not line level
Starter Code:
import simpleGit from 'simple-git';
async function analyzeChanges(filePath: string): Promise<CodeChange> {
const git = simpleGit();
const diff = await git.diff(['HEAD', '--', filePath]);
// Parse diff to extract function changes
const changes = parseDiff(diff);
return {
file: filePath,
type: determineChangeType(changes),
functions: extractFunctionChanges(changes),
classes: extractClassChanges(changes),
};
}
Phase 2: JSDoc Generation (Days 3-4)
Goal: Generate or update JSDoc comments for changed functions.
Tasks:
- Read the source file and parse to AST
- Identify functions that need documentation
- Build prompts for AI doc generation
- Generate JSDoc content via Kiro
- Insert/update docs in source file
Hints:
- Use TypeScript compiler API for accurate AST
- Preserve existing manual documentation when possible
- Format JSDoc with consistent indentation
Prompt Template:
const prompt = `
Generate JSDoc documentation for this TypeScript function.
Function:
\`\`\`typescript
${functionCode}
\`\`\`
Requirements:
- Include @param for each parameter with type and description
- Include @returns with type and description
- Include @throws if function can throw
- Include brief @example if helpful
- Keep description concise (1-2 sentences)
Output ONLY the JSDoc comment block (no code).
`;
Phase 3: README Updates (Days 5-6)
Goal: Keep README API sections synchronized with code.
Tasks:
- Parse README to find API documentation section
- Compare documented API with actual exports
- Generate updates for changed/new exports
- Apply updates while preserving structure
- Handle missing API sections gracefully
Hints:
- Use remark to parse and manipulate markdown
- Look for conventional sections like โ## APIโ or โ## Methodsโ
- Create section if it doesnโt exist
README Section Detection:
function findApiSection(markdown: string): { start: number; end: number } | null {
const lines = markdown.split('\n');
let start = -1;
let end = lines.length;
for (let i = 0; i < lines.length; i++) {
if (lines[i].match(/^##\s+(API|Methods|Reference)/i)) {
start = i;
} else if (start !== -1 && lines[i].match(/^##\s+/)) {
end = i;
break;
}
}
return start === -1 ? null : { start, end };
}
Phase 4: CHANGELOG Generation (Day 7)
Goal: Automatically generate CHANGELOG entries.
Tasks:
- Parse CHANGELOG.md to find [Unreleased] section
- Classify changes (Added, Changed, Deprecated, Removed, Fixed)
- Generate human-readable entries for each change
- Append to appropriate section
- Avoid duplicate entries
Hints:
- Follow Keep a Changelog format (keepachangelog.com)
- Check for existing similar entries before adding
- Date entries only on release, not during development
CHANGELOG Format:
## [Unreleased]
### Added
- `findByEmail()` method for email-based user lookups
### Changed
- `create()` now accepts optional `CreateOptions` parameter
- `update()` validates email format before updating
### Deprecated
- `findOne()` is deprecated, use `findById()` instead
### Removed
- `legacyCreate()` method removed
### Fixed
- Fixed race condition in `delete()` method
Testing Strategy
Unit Tests
describe('DocGenerator', () => {
describe('parseDiff', () => {
it('identifies new functions', () => {
const diff = `
+ async newMethod(): Promise<void> {
+ // implementation
+ }`;
const changes = parseDiff(diff);
expect(changes.functions).toContainEqual({
name: 'newMethod',
changeType: 'new',
});
});
it('identifies modified signatures', () => {
const diff = `
- async create(data: Data) {
+ async create(data: Data, options?: Options) {`;
const changes = parseDiff(diff);
expect(changes.functions[0].changeType).toBe('signature_changed');
});
});
describe('generateJSDoc', () => {
it('includes all parameters', async () => {
const func = 'async create(name: string, age: number): Promise<User>';
const doc = await generateJSDoc(func);
expect(doc).toContain('@param name');
expect(doc).toContain('@param age');
});
});
});
Integration Tests
describe('Full Pipeline', () => {
it('updates JSDoc when function changes', async () => {
// 1. Write initial file
await writeFile('src/test-service.ts', `
export function greet(name: string) {
return \`Hello, \${name}\`;
}
`);
// 2. Simulate hook trigger
await runDocGenerator('src/test-service.ts');
// 3. Verify JSDoc was added
const content = await readFile('src/test-service.ts');
expect(content).toContain('/**');
expect(content).toContain('@param name');
});
});
Manual Verification Checklist
# 1. Create a new function
echo 'export function newFunc(x: number): string { return x.toString(); }' >> src/utils.ts
# 2. Trigger Kiro to modify the file
kiro-cli --print "Add a docstring to newFunc in src/utils.ts"
# 3. Verify hook ran
# Check for documentation in the file
# 4. Verify README updated
# Check README.md for new function listing
# 5. Verify CHANGELOG entry
# Check CHANGELOG.md [Unreleased] section
Common Pitfalls and Debugging
Pitfall 1: Overwriting Manual Documentation
Symptom: Carefully crafted human docs get replaced with AI-generated ones
Prevention:
// Check for manual override marker
function shouldPreserveDoc(existingDoc: string): boolean {
// Markers that indicate human curation
const preserveMarkers = [
'@manual',
'@human-written',
'DO NOT AUTO-UPDATE',
];
return preserveMarkers.some(m => existingDoc.includes(m));
}
Pitfall 2: Git Diff Parsing Errors
Symptom: Hook crashes on complex diffs
Debugging:
# Save raw diff for inspection
git diff HEAD -- src/file.ts > /tmp/raw-diff.txt
# Test parsing separately
bun run parse-diff.ts < /tmp/raw-diff.txt
# Handle edge cases:
# - Binary files
# - Renamed files
# - Empty diffs
Pitfall 3: README Structure Corruption
Symptom: README formatting breaks after update
Prevention:
// Validate markdown structure before writing
import { unified } from 'unified';
import remarkParse from 'remark-parse';
import remarkStringify from 'remark-stringify';
async function safeMarkdownUpdate(original: string, updates: string): string {
// Parse both
const tree = unified().use(remarkParse).parse(updates);
// Validate structure
if (!isValidMarkdown(tree)) {
throw new Error('Generated markdown is invalid');
}
return unified().use(remarkStringify).stringify(tree);
}
Pitfall 4: CHANGELOG Duplicates
Symptom: Same entry appears multiple times
Prevention:
function isDuplicate(existing: string[], newEntry: string): boolean {
// Normalize and compare
const normalized = newEntry.toLowerCase().replace(/[^a-z0-9]/g, '');
return existing.some(e =>
e.toLowerCase().replace(/[^a-z0-9]/g, '') === normalized
);
}
Extensions and Challenges
Extension 1: API Documentation Website
Generate a full documentation website using TypeDoc:
# After JSDoc is in place
npx typedoc src/index.ts --out docs/
# Integrate into build process
npm run build && npm run docs
Extension 2: Documentation Coverage Report
Track what percentage of exports are documented:
Documentation Coverage Report:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ File โ Exports โ Documented โ Coverage โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโผโโโโโโโโโโโโโผโโโโโโโโโโโโโโค
โ src/services/user.ts โ 8 โ 8 โ 100% โ
โ src/services/order.ts โ 12 โ 10 โ 83% โ
โ src/utils/format.ts โ 5 โ 3 โ 60% โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโผโโโโโโโโโโโโโผโโโโโโโโโโโโโโค
โ Total โ 25 โ 21 โ 84% โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Extension 3: Multi-Language Support
Extend beyond TypeScript to Python, Go, etc.:
const docStyles: Record<Language, DocStyle> = {
typescript: { format: 'jsdoc', comment: '/**' },
python: { format: 'docstring', comment: '"""' },
go: { format: 'godoc', comment: '//' },
rust: { format: 'rustdoc', comment: '///' },
};
Extension 4: Interactive Approval
Add a review step before applying changes:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ PROPOSED DOCUMENTATION UPDATES โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ [1] src/services/user.ts - Add JSDoc for create() โ
โ Preview: /** Creates a new user. @param data... โ
โ โ
โ [2] README.md - Update API section โ
โ Preview: Added create() method documentation โ
โ โ
โ [3] CHANGELOG.md - Add entry โ
โ Preview: ### Added - create() method for user creation โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Apply changes? [a]ll / [s]elect / [n]one โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Extension 5: Documentation Linting
Validate generated documentation against style guide:
interface DocLintRule {
name: string;
validate: (doc: string) => { valid: boolean; message?: string };
}
const rules: DocLintRule[] = [
{
name: 'description-period',
validate: (doc) => ({
valid: doc.endsWith('.'),
message: 'Descriptions should end with a period',
}),
},
{
name: 'param-description',
validate: (doc) => ({
valid: !doc.match(/@param \w+ -?\s*$/m),
message: 'All @param must have descriptions',
}),
},
];
Real-World Connections
Industry Practices
Documentation automation is used by:
- Stripe: Auto-generates API reference from OpenAPI specs
- AWS: Uses doc-as-code for SDK documentation
- Microsoft: AI-assisted IntelliSense documentation
- Vercel: Automated README updates in Next.js
Production Considerations
| Concern | Solution |
|---|---|
| Quality assurance | Human review before release |
| Localization | AI can translate to other languages |
| Versioning | Docs versioned alongside code |
| Deprecation | Auto-flag deprecated API in docs |
| Search | Index generated docs for search |
Metrics That Matter
Track documentation health:
Documentation Metrics Dashboard:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Coverage: 84% โโโโโโโโโโ โ
โ Freshness: 97% โโโโโโโโโโ (docs updated within 24h of code)โ
โ Completeness: 72% โโโโโโโโโโ (all params documented) โ
โ Examples: 45% โโโโโโโโโโ (functions with @example) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Self-Assessment Checklist
Knowledge Verification
- Can you explain the git diff format and how to parse it?
- What are the different documentation layers and their purposes?
- Why is incremental update better than full regeneration?
- What JSDoc tags are essential for function documentation?
- How does Keep a Changelog format work?
Implementation Verification
- Hook triggers on code file changes
- Git diffs are correctly parsed and classified
- JSDoc is generated for new functions
- Existing documentation is preserved when appropriate
- README API sections stay synchronized
Quality Verification
- Generated docs accurately describe the code
- Formatting is consistent with project style
- Human-written documentation is never lost
- CHANGELOG entries are meaningful, not mechanical
Integration Verification
- Hook integrates seamlessly with normal Kiro workflow
- Performance is acceptable (< 15 seconds)
- Errors are handled gracefully
- Configuration allows customization
Summary
Building a documentation generator teaches you:
- Git Diff Analysis: Understanding code changes at a semantic level
- Multi-Target Documentation: Updating JSDoc, README, and CHANGELOG together
- Incremental Updates: Surgical documentation changes instead of regeneration
- Quality Preservation: Respecting and preserving human-written content
The techniques you have learned here - parsing diffs, classifying changes, and generating targeted updates - apply far beyond documentation. The same pattern works for code review summaries, release notes, and any workflow that reacts to code changes.
Next Project: P24-secret-scanner-hook.md - Security scanning with PreToolUse blocking hooks