
Dev Espresso #2 – Documentation That Doesn’t Rot (AI‑Accelerated Hygiene)
Starve AI of current context and you get generic noise. Feed it concise, structured, fresh docs and it becomes a leverage engine.
Core Idea (One Sip)
Lightweight, continuously refreshed documentation (PRDs, decision records, README/service docs) is a compression layer for both humans and AI. The goal isn’t volume — it’s high‑signal artifacts you can diff, update, and trust.
Why Docs Rot (and Mislead AI)
Rot vectors:
- Ownership drift (original author leaves – intent fog)
- Silent architectural changes (code evolved, narrative didn’t)
- Metric / constraint shifts (SLOs, scale assumptions outdated)
- Markdown graveyards (too long → skipped → decay accelerates)
Result: team + model both hallucinate missing context.
Minimum Viable Doc Stack
Keep it brutally small:
- PRD (Problem, Users, Constraints, Success Metrics, Open Questions that must be answered before acceptance)
- Decision records (short tradeoff marker) → promote to ADR only if durable + stack impact
- Service / README (How to run, Core responsibilities, Key Env Vars, Links)
- Delta updates via diffs (avoid rewriting entire files)
AI Assist – Good vs Bad
Good: skeleton generation, gap finding, rot detection, enumerating alternatives & risks. Bad: inventing business goals, fabricating constraints/metrics, rewriting intent unverified.
Guardrail prompt footer (add everywhere): “Do not speculate beyond code or provided text. If unsure, list clarification questions.”
Practical Workflow (End‑to‑End)
Instead of passively “writing docs,” treat the system as a repeatable loop:
flowchart TD
A[Idea / Feature Seed] --> B[PRD Skeleton]
B --> C[Constraints & Metrics Added]
C --> D[Implementation Options]
D --> E[Decision Note]
E --> F[ADR Candidate]
C --> G[Build / Code Changes]
G --> H[Diff Scan]
H --> I[Doc Refresh]
I --> B
classDef node fill:#222,stroke:#555,color:#fff;
class A,B,C,D,E,F,G,H,I node;
Step 1: PRD Skeleton
Prompt: “Generate a concise PRD skeleton for a feature that <GOAL>. Include: Problem, Users, Use Cases, Non‑Goals, Constraints, Success Metrics, Open Questions. Do not speculate beyond provided text.”
Fill it manually with known constraints (SLOs, scale assumptions) and mark unknowns as TBD—don’t let AI invent them.
Step 2: Gap & Risk Scan
Prompt: “Given this draft PRD, list 3–5 missing constraints or metrics. If data absent, respond with clarifying questions.”
Step 3: Implementation Options
Prompt: “Using this PRD excerpt, propose 3 implementation approaches; compare performance, complexity, risk; flag assumptions.”
You choose—AI enumerates, you own selection.
Step 4: Capture a Decision Record
When you commit to an approach, write a short decision record (template below). Escalate only impactful ones into ADRs later.
Decision Record Seed Prompt: “From this commit message + diff, draft a 6‑line decision record: Context, Decision, Alternatives (2), Consequences (one +, one -), Follow‑Up. Do not fabricate unstated rationale.”
Step 5: Diff‑Driven Refresh
After a meaningful code change: Prompt: “Old README section + diff summary. Suggest minimal updated replacement. Avoid marketing; reflect code truth only. If uncertain, output questions.”
Step 6: Rot / Drift Detection
Periodic scan: Prompt: “Here is PRD v1 and latest diff summaries. List sections likely outdated + clarifying questions. Don’t guess new values.”
AI Update Loop Diagram
flowchart TD
A[Existing Doc + Code Diff] --> B[Rot / Gap Prompt]
B --> C[AI Suggestions]
C --> D[Human Prune & Verify]
D --> E[Commit Minimal Delta]
E --> F[Periodic Re-Scan]
F --> B
style A fill:#222,stroke:#555,color:#fff
style B fill:#222,stroke:#555,color:#fff
style C fill:#222,stroke:#555,color:#fff
style D fill:#222,stroke:#555,color:#fff
style E fill:#222,stroke:#555,color:#fff
style F fill:#222,stroke:#555,color:#fff
Decision Record vs PRD vs ADR
| Artifact | When | Lifetime | Depth |
|---|---|---|---|
| Decision Record | Opportunistic (emerging tradeoff) | Often transitional | Short context + choice |
| PRD | Before / early build | Evolves → Accepted → Archived | Feature framing |
| ADR | High-impact architectural decision | Long (may be superseded) | Problem→Decision→Alternatives→Consequences |
Heuristic to escalate a decision record to ADR: (Impact × Irreversibility × Cost of Misstep) >= team threshold.
Example Artifacts
Please keep in mind that those are examples only and those might not be a good decisions 😅. Purpose of those examples is to present sample structure for those docs.
Decision Record Example (Business / Product)
# Decision Record: Limit MVP Export Window to 7 Days
Date: 2025-09-22
Status: Proposed
Owner: Product (John Doe)
Decision Type: Scope Constraint
## Context
Early customers requested “full history” exports. Engineering estimates show a full-history path adds ~3 weeks (index tuning + batching infra) and risks missing the planned launch window. 80% of audit/support use cases reference only the last few days of activity.
## Decision
Ship MVP with a fixed 7-day export window; defer full-history & scheduling to post-MVP iteration.
## Alternatives Considered
1. Full History in MVP – Higher perceived value, but +3 weeks delay + higher infra cost.
2. 30-Day Window – Slightly broader utility, still needs extra indexes; adds ~1 week.
3. On-Demand “Extended Export” Ticket – Keeps scope small but reintroduces manual engineer time.
## Rationale
Maximizes time-to-value while covering majority of real support/audit cases; avoids premature scaling.
## Consequences
Positive: Faster launch; lower initial infra cost; simpler monitoring.
Negative: Some power users will still open tickets for older data; potential perception of limitation.
## Mitigations
- Add tooltip: “Need older data? Contact support (full export coming soon).”
- Track requests for >7 day window (support tag `export:extended-request`).
## Success Signals
- 90% of export usage completes without support escalation.
- <10% of export-related tickets ask for >7 days in first month.
## Follow-Up (Post-MVP Triggers)
Expand to rolling 30-day window once either: (a) >10% of weekly export requests exceed 7 days OR (b) churn risk cited due to limitation.
## Open Questions
1. Should billing plans gate longer retention windows?
2. Do we need an approval flow for exports >7 days (compliance)?
PRD Snippet
# PRD: Lightweight Activity Export
Date: 2025-09-22
Status: Draft
Owner: (TBD)
## Problem
Admins and Support need a quick way to extract recent user activity for audits and issue investigation. Today they run ad-hoc SQL or wait on engineering.
## Goal (1 Sentence)
Provide a self-service CSV export of recent activity that is fast, bounded in size, and safe to run frequently.
## Users / Primary Actor
- Primary: Admin
- Secondary: Support Engineer
## Scope (MVP)
- Export last 7 days of activity events (create/update/login)
- Download as CSV via UI button
- Optional filter by user email
## Out of Scope (MVP)
- Full historical exports (>7 days)
- Scheduled / recurring delivery
- PDF or JSON output
- Additional PII masking beyond existing model
## Functional Requirements
1. User clicks “Export Activity” → download starts within 1 second.
2. Optional email filter reduces result set before generation.
3. If result set exceeds limit, show message (no silent truncation).
4. Log each export (who, when, filter, row count).
## Non-Functional / Constraints
- Performance: P95 end-to-end ≤ 3s for typical (≤10k rows) export.
- Size: Max 25k rows OR ~50MB (whichever first).
- Frequency: ≤1 export / minute / user (rate limited).
- Load: Must not block primary write path (use read replica or background job).
- Security: Roles allowed = Admin, Support.
## Success Metrics
- 80% reduction in manual SQL export requests (baseline TBD → track after 30 days).
- 90% of exports complete <3s P95.
- <1% failed exports / week.
## Telemetry
- Log: duration_ms, row_count, filter_applied, success|failure_reason.
- Alert if P95 >3s for 3 consecutive days.
## Edge Cases
- No matching rows → return header-only CSV.
- Rate limit hit → return clear retry-after message.
- Over limit → instruct user to narrow date or email filter.
## Risks
- Performance degradation if run on primary DB.
- Memory spike if whole CSV buffered in memory.
- Abuse via repeated wide exports.
## Open Questions
1. Exact event types in scope? (login, password reset, etc.)
2. Is 7-day window configurable per environment?
3. Need masking for any sensitive columns?
4. Should we paginate instead of rejecting when exceeding limit?
## Follow-Up (Post-MVP)
- Scheduled weekly export
- JSON / NDJSON variant
- Multi-tenant scoping filter
ADR Example
# Architecture Decision Record: Incremental Cursor-Based Exports
Date: 2025-09-22
Status: Accepted (MVP implementation pending)
## Context
Activity events table ~20M rows, growing ~1.2M / month. Export feature (see PRD) requires P95 ≤3s for typical admin exports (≤10k recent rows). Full table scans already exceed 3s on staging benchmarks.
## Decision
Adopt incremental cursor-based export (store last exported high-water mark per admin request + bounded window) instead of ad-hoc full scans each time.
## Alternatives Considered
1. Full Scan + Filter per Request – Simple, but >3s now and grows unbounded with table size.
2. Cached Daily Snapshot – Fast reads but introduces staleness (up to 24h) and added storage + invalidation complexity.
3. Streaming Query with Client-Side Throttle – Would still traverse large cold ranges; operational complexity not justified.
## Consequences
Positive:
- Predictable latency (bounded delta set)
- Low I/O vs full historical traversal
- Natural hook for future incremental scheduling
Negative / Risks:
- Cursor invalidation if retention window changes
- Need to handle deleted/rewritten rows gracefully
- Slight state management overhead (persistent cursor store)
## Verification / Metrics
- Benchmark: Export 5k & 10k recent rows P95 < 2s in staging.
- Alert if cursor lag (oldest un-exported record age) > 2h.
- Log: cursor_start_ts, cursor_end_ts, row_count, duration_ms.
## Rollback Plan
Fallback to on-demand filtered scan (limited to 25k rows) if cursor logic fails or produces gaps (feature flag controlled).
## Follow-Up
- Reassess approach when row volume > 40M or retention policy changes.
- Evaluate adding snapshot compression if daily export adoption spikes.
## Notes
No PII expansion introduced; security posture unchanged.
## Glossary (Quick)
- P95 (95th Percentile Latency): 95% of measured requests finish at or below this time; focuses on near-worst typical performance rather than average.
- PII (Personally Identifiable Information): Data that can identify a person (e.g., email, name, IP when combined). Mentioned here to confirm the decision does not expand exposure surface.
Updating Without Pain
Treat docs like code:
- Small commits (“docs: refresh env var section after cache layer change”)
- Link commits → PRDs / decision records
- Run periodic rot scan: “Which sections reference removed modules / outdated metrics?”
- Prefer additive deltas over wholesale rewrites
Verification Prompts
- “Compare this README update to the diff: any claims not traceable to code?”
- “List 5 failure modes not covered in this PRD; mark which need monitoring.”
- “Which metrics might be vanity vs actionable?”
Anti‑Rot Checklist (Paste Into Repo)
- PRD has explicit Success Metrics + Open Questions
- Recent code diff scanned for doc deltas
- Decision captured (note or ADR) for non-trivial tradeoff
- Removed stale sections instead of piling new ones on top
- Each doc < 5 min read (or split)
Daily Micro Practice
Pick one stale section. Provide code diff + doc snippet to AI. Ask for minimal update. Manually prune, commit. 10 minutes max. Compounded weekly → living docs.
Hands‑On Challenge
In under 60 minutes:
- Draft a PRD skeleton for a small feature.
- Add real constraints & success metrics (even if TBD placeholders).
- Refresh one stale README section via a diff‑driven update prompt.
- Capture one decision note (do not overthink wording).
- Commit with message:
docs: bootstrap discovery layer.
Call To Action
Run the challenge. Track how often AI surfaced a gap you’d otherwise miss. Then schedule a 10‑minute weekly “doc rot scan” using the prompts above. Share the most surprising outdated assumption you found—use that as evidence the loop works.
“Fresh docs → sharper AI → faster you.”
Found this helpful? Power up my next content!