Deploy to Staging / Build Images (push) Successful in 5m32s
Deploy to Staging / Deploy to Staging (push) Successful in 44s
Deploy to Staging / Verify Staging (push) Successful in 5s
Deploy to Staging / Notify Staging Ready (push) Successful in 4s
Deploy to Staging / Notify Staging Failure (push) Has been skipped
Removes the old planner/decision-critic/role-agents/domain-agents system (step-injector scripts, stale scopes, sprint-era workflow) and replaces it with 16 ground-truth-verified skills under .claude/skills/: change control, debugging playbook, failure archaeology, architecture contract, domain reference, OCR/Gemini pipeline, config and secrets, build and env, run and operate, diagnostics (with tested scripts), validation and QA, docs and writing, launch readiness, deploy-safety campaign, proof and analysis toolkit, and research frontier. RULE 0/1/2, the temporal-contamination rule, and the decision stress-test protocol are carried forward into the new skills; the retired content remains in git history. Co-Authored-By: Claude Fable 5 <[email protected]>
222 lines
20 KiB
Markdown
222 lines
20 KiB
Markdown
---
|
|
name: mvp-docs-and-writing
|
|
description: Load before reading OR writing any documentation in this repo. Covers which docs to trust vs which are stale-dangerous (ARCHITECTURE-OVERVIEW, DATABASE-SCHEMA, AUDIT, PLATFORM-SERVICES all contain false claims), house style (tables, CLAUDE.md indexes, SCREAMING-KEBAB names, no emojis), the doc-sync discipline, and the temporal-contamination rule for comments. Triggers - updating a README or CLAUDE.md after a code change, citing a doc as evidence, "docs say X but code does Y", writing a feature README, adding code comments to a PR, "is this doc current", updating .ai/context.json, or maintaining this skill library itself.
|
|
---
|
|
|
|
# MotoVaultPro Documentation and Writing
|
|
|
|
## When to use / When NOT to use
|
|
|
|
**Use this skill when:**
|
|
- You are about to trust a `docs/` file as a source of truth (check the trust table first).
|
|
- You are writing or updating any doc: `docs/*.md`, a `CLAUDE.md` index, a feature README, `.ai/context.json`, or a skill in this library.
|
|
- You are writing code comments in a PR (temporal-contamination rule applies).
|
|
- A doc contradicts code and you need the tiebreak rule (short answer: code wins).
|
|
|
|
**Do NOT use this skill for:**
|
|
- The issue/branch/PR/label workflow itself — `mvp-change-control`.
|
|
- What counts as test evidence or definition of done — `mvp-validation-and-qa`.
|
|
- Recording an incident post-mortem — `mvp-failure-archaeology` (this skill only tells you WHEN to add one, section 5).
|
|
- Architecture facts themselves — `mvp-architecture-contract` (this skill tells you which architecture DOCS lie).
|
|
|
|
**Prime directive:** where docs contradict code, code wins. Verify against source before repeating any doc claim. Several docs below contain confidently-worded false statements.
|
|
|
|
## 1. Docs-of-record map with trust levels
|
|
|
|
Verified against code 2026-07-07. All paths repo-relative.
|
|
|
|
### Trustworthy (verify-then-use)
|
|
|
|
| Doc | Covers | Notes |
|
|
|-----|--------|-------|
|
|
| `docs/CICD-DEPLOY.md` | Staging-first deploy, blue-green prod, secrets, rollback | Most current infra doc. All 4 workflows exist in `.gitea/workflows/`; image list (postgres:18-alpine, redis:8.4-alpine, traefik:v3.6) matches `docker-compose.yml`. |
|
|
| `docs/LOGGING.md` | LOG_LEVEL matrix, Grafana dashboards/alerts, LogQL cookbook | Dashboards and alerting files verified in `config/grafana/`. Matches Pino log shape. |
|
|
| `docs/TESTING.md` | Mock strategy; per-workspace test scripts | Partially stale-dangerous: its container-based test workflow is impossible against the shipped images — the backend production image has no jest (`npm ci --omit=dev`, dist-only) and the frontend image is nginx-only with tests dockerignored, so `make shell-backend && npm test` and `docker compose exec mvp-frontend npm test` both fail (see `mvp-deploy-safety-campaign` 1B/1D and `mvp-build-and-env`). Its "All 15 features have test suites" list is also stale — 21 features exist. Trust the mock-strategy prose and per-workspace script names only. |
|
|
| `docs/USER-GUIDE.md` | End-user manual, every page and Pro feature | Most detailed and recent doc. One known error: line ~572 says Pro = "Up to 10 vehicles"; the Tier Comparison (~line 624) and Downgrade table (~line 864) say 5, and code says 5 (`backend/src/core/config/feature-tiers.ts`, `VEHICLE_LIMITS: { free: 2, pro: 5, enterprise: null }`). The "10" is wrong. |
|
|
| `docs/VEHICLES-API.md` | Vehicles CRUD, images, dropdown cascade | Field names (`trimLevel`, `driveType`, `fuelType`) match code — more current than DATABASE-SCHEMA. Missing: `POST /api/vehicles/decode-vin` and the TCO fields from migration 006. |
|
|
| `docs/TIER-GATING.md` | Tier hierarchy, `requireTier`, `useTierAccess` | Mechanics accurate. Does not document `VEHICLE_LIMITS`; calls Stripe billing "future" though `backend/src/features/subscriptions/` exists. |
|
|
| `docs/DATABASE-MIGRATION.md` | pg_dump export/import scripts, backup cron | Scripts exist; `npm run migrate:all` verified in `backend/package.json`. WARNING: `scripts/import-database.sh --drop-existing` is a destructive operation — fresh backup required first (owner non-negotiable). |
|
|
|
|
### Stale-dangerous (do NOT cite without re-verifying)
|
|
|
|
| Doc | Why dangerous |
|
|
|-----|---------------|
|
|
| `docs/ARCHITECTURE-OVERVIEW.md` | Self-contradictory: header says PostgreSQL 18 / Redis 8, its own Service Details say `postgres:15-alpine` / `redis:7-alpine`, `traefik:v3.0`; actual compose is postgres:18-alpine, redis:8.4-alpine, traefik:v3.6. Says VIN decoding "Planned/Future - not yet implemented" — FALSE: `POST /api/vehicles/decode-vin` ships (`backend/src/features/vehicles/api/vehicles.routes.ts:79`, Pro/Enterprise gated). Lists "Current Features (15)"; 21 exist. |
|
|
| `docs/DATABASE-SCHEMA.md` | Materially stale. Vehicles table shows `trim VARCHAR(100)` and omits `trim_level`/`drive_type`/`fuel_type` (migration 002) and all TCO fields (migration 006). Missing entire table sets: audit_logs, subscriptions, user_notifications, ownership-costs, user-import. Shows `user_id VARCHAR(255)` everywhere with NO mention of the UUID identity migration (`backend/src/core/identity-migration/migrations/001_migrate_user_id_to_uuid.sql`), which adds `user_profile_id UUID` to 17 feature tables. For schema truth, read the migration files, not this doc. |
|
|
| `docs/AUDIT.md` | Historical snapshot dated 2025-12-13, never updated post-remediation. Presents FIXED criticals as open: the Math.random storage-key finding is fixed (`crypto.randomBytes(32)` in `documents.controller.ts`); magic-byte validation exists; an audit_logs table now exists; backend ESLint exists. Also claims Winston logging — backend uses Pino. Treat as archive only. Never cite its findings as current. |
|
|
| `docs/ocr-pipeline-tech-stack.md` | Describes a never-shipped design: lists Celery task queue and S3/MinIO storage as stack components, but `ocr/requirements.txt` has no celery and no object store is deployed. Also omits `ocr/app/engines/gemini_engine.py`, which exists. The engine-abstraction section is real; the infrastructure sections are aspirational and unlabeled. For OCR truth use `mvp-ocr-gemini-pipeline`. |
|
|
| `docs/PLATFORM-SERVICES.md` | Says VIN decoding "planned but not yet implemented" — false, same as ARCHITECTURE-OVERVIEW. Largely redundant with it too. Endpoint list is accurate; the VIN claim is not. |
|
|
| `docs/E2E-TESTING.md` | A 9-line fragment (a VIN/license-plate scenario table). `docs/CLAUDE.md` bills it as "Cypress E2E test setup" — it contains zero Cypress content. E2E tooling is effectively undocumented. |
|
|
| `.ai/context.json` | Declared canonical by CLAUDE.md, but its feature list has 15 entries (21 capsules exist in `backend/src/features/`) and it repeats the false "VIN decoding is planned/future" claim. If you touch it, fix these — flag the update in your PR. |
|
|
| `.ai/workflow-contract.json` | Says sub-issues get `status/in-progress` labels; CLAUDE.md says status is tracked on the PARENT only and sub-issues stay `status/backlog`. CLAUDE.md wins. Also still mandates sprints/milestones — abandoned by owner directive 2026-05-12; work flows directly from issues. |
|
|
|
|
Also note: root `CLAUDE.md` and `README.md` instruct `npm test` / `npm run lint` at repo root, but root `package.json` has NO scripts block. Run commands from `backend/`, `frontend/`, or `ocr/`. And CI gates nothing beyond image build + staging boot (canonical statement: `mvp-validation-and-qa` section 1). No doc that says otherwise is correct.
|
|
|
|
### The systemic cause — and the rule
|
|
|
|
Every stale-dangerous doc above rotted the same way: it froze a count or version as a literal ("15 features", "PostgreSQL 15", "not yet implemented") instead of pointing at the source of truth. Each feature addition then silently invalidated four documents at once. The docs closest to operations (CICD-DEPLOY, LOGGING) stayed honest because they are exercised; the summaries rotted because nothing exercises them.
|
|
|
|
**Rule for all new writing:** never embed a count, version number, or implementation-status literal that a normal code change can invalidate. Instead:
|
|
|
|
| Instead of writing | Write |
|
|
|--------------------|-------|
|
|
| "There are 15 features" | "Feature capsules live in `backend/src/features/` (one directory each; `ls` it for the current set)" |
|
|
| "PostgreSQL 15" | "PostgreSQL (version pinned in `docker-compose.yml`)" |
|
|
| "VIN decoding is not yet implemented" | Nothing — implementation status belongs in code and issues, not prose |
|
|
| "Pro tier allows 5 vehicles" (in a doc that is not the limits' home) | "Vehicle limits per tier: see `VEHICLE_LIMITS` in `backend/src/core/config/feature-tiers.ts`" |
|
|
|
|
If a volatile fact MUST appear as a literal (e.g., in this skill), date-stamp it and give a re-verification command (see Provenance section for the pattern).
|
|
|
|
## 2. House style
|
|
|
|
All of the following are enforced project conventions, verified against existing docs 2026-07-07.
|
|
|
|
| Convention | Rule |
|
|
|------------|------|
|
|
| No emojis | Anywhere. Ever. Hard project rule. |
|
|
| Table-first | Prefer Markdown tables over prose for any enumerable content (options, files, endpoints, comparisons). |
|
|
| Doc file names | SCREAMING-KEBAB in `docs/` (`DATABASE-SCHEMA.md`). The lone violation, `ocr-pipeline-tech-stack.md`, is the outlier — do not copy it. |
|
|
| Diagrams | ASCII box diagrams, not Mermaid or images. Existing docs mix pure ASCII (`+--+`) and Unicode box-drawing; either is acceptable, be consistent within one doc. |
|
|
| Cross-links | End substantive docs with a "Related Documentation" footer listing repo-relative paths (pattern in `docs/ARCHITECTURE-OVERVIEW.md`, `docs/VEHICLES-API.md`). |
|
|
| Per-directory CLAUDE.md | Every directory carries a CLAUDE.md that is a PURE INDEX: the exact three-column table pattern below, no prose, no architecture, no overview sections. |
|
|
| Feature docs | `backend/src/features/{name}/README.md` is the per-feature record. `docs/` is cross-cutting only. A feature-specific fact belongs in the feature README, full stop. |
|
|
| Canonical sources | Per CLAUDE.md: `.ai/context.json` (architecture metadata), `docs/README.md` (hub), feature READMEs. Note `.ai/context.json` is itself stale (section 1) — updating it is part of honoring this convention, not optional. |
|
|
|
|
CLAUDE.md index pattern (exact):
|
|
|
|
```markdown
|
|
## Files
|
|
|
|
| File | What | When to read |
|
|
| ---- | ---- | ------------ |
|
|
| `cache.ts` | LRU cache with O(1) get/set | Implementing caching, debugging misses |
|
|
|
|
## Subdirectories
|
|
|
|
| Directory | What | When to read |
|
|
| --------- | ---- | ------------ |
|
|
| `api/` | Fastify route handlers | Adding endpoints, changing request flow |
|
|
```
|
|
|
|
Column rules: backticks around names; "What" is a factual noun-phrase; "When to read" is task-oriented with action verbs (implementing, debugging, adding). Quality test: given a task, can a model scan the "When to read" column and pick the right file? Anti-pattern: `| config/ | Configuration | Working with configuration |` — matches everything, selects nothing.
|
|
|
|
## 3. Doc-sync discipline
|
|
|
|
Carried forward from the retired doc-sync skill; these three rules are the whole discipline.
|
|
|
|
### The Invisible Knowledge Test
|
|
|
|
Create or keep a README.md ONLY for knowledge not visible from reading the code: non-obvious contracts between components, design tradeoffs that constrain modification, ordering rules the compiler will not enforce, failure modes invisible in any single file.
|
|
|
|
For every sentence, ask: "Could a developer learn this by reading the source files?"
|
|
- YES: delete the sentence.
|
|
- NO: keep it.
|
|
|
|
Do NOT create a README for a purely organizational directory, for self-explanatory code, or to restate what the CLAUDE.md index already conveys. A README earns its tokens by carrying the reasoning behind the code, not descriptions of the code. Keep new READMEs under roughly 500 tokens.
|
|
|
|
### Update docs in the same PR
|
|
|
|
Any PR that changes behavior, adds/removes/renames files, or alters a contract updates the affected CLAUDE.md indexes, the feature README, and any `docs/` file it invalidates — in that same PR. The stale-dangerous list in section 1 is what "docs later" produces. There is no doc-sync sweep coming to save you; the retired doc-sync skill's periodic-audit model demonstrably did not keep pace.
|
|
|
|
Same-PR checklist:
|
|
- [ ] New/deleted/renamed files reflected in the directory's CLAUDE.md table
|
|
- [ ] Feature README updated if the feature's contract or invariants changed
|
|
- [ ] Grep `docs/` for literals your change invalidates: `grep -rn "<old-name-or-claim>" docs/ .ai/`
|
|
- [ ] No new frozen counts/versions introduced (section 1 rule)
|
|
|
|
### CLAUDE.md vs README.md
|
|
|
|
| Content | Home |
|
|
|---------|------|
|
|
| What files exist, when to open them | CLAUDE.md (pure index) |
|
|
| Architecture, data flow, component interaction | README.md |
|
|
| Design decisions and tradeoffs | README.md |
|
|
| Invariants not enforced by code | README.md |
|
|
| Build/test commands | Root CLAUDE.md only |
|
|
| Prose of any kind in a subdirectory CLAUDE.md | Nowhere — migrate to README.md, strip the index |
|
|
|
|
## 4. The temporal-contamination rule
|
|
|
|
Carried forward from the retired planner skill. Applies to all docs AND code comments.
|
|
|
|
> **Timeless Present Rule:** write from the perspective of a reader meeting the code for the first time, with no knowledge of what came before. The code simply IS. Change-narrative comments ("Added X to fix Y") are an LLM artifact — the change process is ephemeral; documentation describes ongoing existence. The change narrative already lives in git history and the issue; duplicating it in a comment is contamination.
|
|
|
|
### Detection questions
|
|
|
|
Evaluate every comment/sentence against these; signal words are examples, extrapolate semantically:
|
|
|
|
1. **Does it describe an action taken rather than what exists?** ("Added", "Changed to", "Now uses", "Updated", "Refactored")
|
|
2. **Does it compare to something not in the code?** ("Previously", "Instead of", "Replaces", "Unlike the old", "No longer")
|
|
3. **Does it describe where to put code rather than what code does?** ("After the X call", "Insert before", "At line N") — always delete; location is encoded in the diff.
|
|
4. **Does it describe intent or futures rather than behavior?** ("TODO later", "Will be extended", "Temporary until") — delete, implement, or reframe as a current constraint.
|
|
5. **Does it narrate the author's choice rather than the technical reason?** ("Intentionally", "We decided", "Chose X for reliability") — extract the justification, discard the decision narrative.
|
|
|
|
Catch-all: if a comment only makes sense to someone who knows the code's history, it is contaminated.
|
|
|
|
### Transformations
|
|
|
|
| Contaminated | Timeless present |
|
|
|--------------|------------------|
|
|
| `// Added mutex to fix race condition` | `// Mutex serializes cache access from concurrent requests` |
|
|
| `// Previously handled in caller` | `// Encapsulated here; caller does not manage lifecycle` |
|
|
| `// Temporary workaround until API v2` | `// API v1 lacks filtering; client-side filter required` |
|
|
| `// We decided to cache at this layer` | `// Cache here: cuts DB round-trips on the hot path` |
|
|
|
|
Subtle case: "Now blocks until connection ready" is CLEAN ("now" = runtime moment); "Now handles edge cases properly" is CONTAMINATED ("properly" implies a defective past). Judgment, not keyword matching.
|
|
|
|
Transformation recipe: (1) find the useful information buried in the narrative — the problem or the behavior; (2) restate it as a present-tense fact; (3) delete the rest.
|
|
|
|
## 5. Writing for AI readers, and maintaining this skill library
|
|
|
|
The primary readers of everything you write here are future AI sessions with zero context and a finite window. CLAUDE.md's doctrine: "All development practices should be made taking into account the most context efficient interaction with another AI."
|
|
|
|
| Standard | Practice |
|
|
|----------|----------|
|
|
| One home per fact | Every fact has exactly one canonical location; every other mention is a pointer to it. The version/feature-count rot in section 1 lives precisely where facts were restated in four places. |
|
|
| Date-stamp volatile facts | Any literal that a code change can invalidate carries "(verified YYYY-MM-DD)" and, ideally, a re-verification command. |
|
|
| Trigger-rich descriptions | This library's convention: a skill's frontmatter `description` states exactly WHEN to load it, including symptom keywords a session would actually have in context ("docs say X but code does Y"), not just topic labels. |
|
|
| Copy-pasteable commands | Repo-relative paths, no placeholders the reader must guess. Remember: no working local dev loop exists — end-to-end verification happens on staging via the PR pipeline, so commands must state where they run. |
|
|
| Define jargon at first use | Assume a mid-level engineer or Sonnet-class session with zero project context. |
|
|
|
|
### Maintenance protocol for this skill library
|
|
|
|
All skills live at `.claude/skills/mvp-*/SKILL.md`, YAML frontmatter with exactly `name` and `description`. Most skills are the single SKILL.md file; a skill may additionally carry a `scripts/` directory of read-only checks (`mvp-diagnostics-and-logging` does) - that is legitimate content, not clutter to purge.
|
|
|
|
**To update a skill:**
|
|
1. Verify the new fact against the repo (code, not docs) before writing it.
|
|
2. Edit the SKILL.md; keep the "When to use / When NOT to use" routing and the "Provenance and maintenance" section current — add a re-verification command for every new volatile fact.
|
|
3. Apply this skill's own rules to the edit: no frozen counts without date-stamps, timeless present, no emojis.
|
|
4. Ship the update in the same PR as the change that invalidated it (section 3 rule — skills are docs).
|
|
|
|
**When to add an incident to `mvp-failure-archaeology`:** a failure cost more than an hour, produced a revert, revealed a false doc claim that misled a session, or settled a design battle that must not be re-fought. Record symptom, root cause, evidence (file:line or commit), and status. Do not record routine bugs.
|
|
|
|
**Skill-directory hygiene:** skill directories are write-once-per-PR artifacts, not scratch space. The previous library shipped four 0-byte junk files (shell-redirection accidents) into git because nobody audited `.claude/skills/` before committing. Check `git status .claude/skills/` before every commit that touches this tree.
|
|
|
|
## Provenance and maintenance
|
|
|
|
Authored 2026-07-07 from direct repo inspection at commit e729d42; doc trust assessments reflect that date. Volatile facts and how to re-verify each:
|
|
|
|
| Fact (as of 2026-07-07) | Re-verify with |
|
|
|--------------------------|----------------|
|
|
| 21 feature capsules | `ls backend/src/features/ \| grep -v CLAUDE.md \| wc -l` |
|
|
| Vehicle limits free 2 / pro 5 / enterprise unlimited | `grep -A4 "VEHICLE_LIMITS" backend/src/core/config/feature-tiers.ts` |
|
|
| VIN decode implemented at `/vehicles/decode-vin` | `grep -n "decode-vin" backend/src/features/vehicles/api/vehicles.routes.ts` |
|
|
| Image versions postgres:18-alpine / redis:8.4-alpine / traefik:v3.6 | `grep -n "postgres:\|redis:\|traefik:" docker-compose.yml` |
|
|
| Root package.json has no scripts | `python3 -c "import json;print('scripts' in json.load(open('package.json')))"` |
|
|
| `.ai/context.json` still lists 15 features / VIN "planned" | `grep -n "vin\|VIN" .ai/context.json; python3 -c "import json;print(len(json.load(open('.ai/context.json'))['feature_dependencies']['sequence']))"` |
|
|
| AUDIT.md Math.random finding is fixed | `grep -n "crypto.randomBytes" backend/src/features/documents/api/documents.controller.ts` |
|
|
| UUID identity migration exists, undocumented in DATABASE-SCHEMA.md | `head -6 backend/src/core/identity-migration/migrations/001_migrate_user_id_to_uuid.sql; grep -c "user_profile_id" docs/DATABASE-SCHEMA.md` |
|
|
| USER-GUIDE "Up to 10 vehicles" error still present | `grep -n "Up to 10 vehicles" docs/USER-GUIDE.md` |
|
|
| E2E-TESTING.md still a 9-line fragment | `wc -l docs/E2E-TESTING.md` |
|
|
| ocr doc still lists Celery; no celery dependency | `grep -in celery docs/ocr-pipeline-tech-stack.md ocr/requirements.txt` |
|
|
| CI runs zero tests / zero lint | `grep -inwE "test\|lint" .gitea/workflows/staging.yaml` (expect NO output; the word-bound `-w` matters - without it every `:latest` image tag substring-matches "test") |
|
|
|
|
If a re-verification shows a doc has been FIXED, move it out of the stale-dangerous table in the same PR — this skill must not itself become a frozen snapshot.
|
|
|
|
## Related Documentation
|
|
|
|
- `.claude/skills/mvp-change-control/SKILL.md` — PR workflow the same-PR doc rule plugs into
|
|
- `.claude/skills/mvp-validation-and-qa/SKILL.md` — evidence standards for claims docs make
|
|
- `.claude/skills/mvp-failure-archaeology/SKILL.md` — where doc-misled incidents get recorded
|
|
- `docs/README.md` — the docs hub this skill triages
|