factory-pitfalls
Synced from
factory-kit/skills/factory-pitfalls.mdat v0.1.2. The source of truth is the factory-kit repo.
Factory pitfalls
Section titled “Factory pitfalls”The skills are now structured Principle → Why → Recipe → Failure mode, with each anti-pattern co-located with the principle it violates. This file is a flat scan across those failure modes plus process-level pitfalls that don’t fit any one skill.
How to use this skill
Section titled “How to use this skill”- At project kickoff. Read this index; ensure the starting setup avoids the top-tier pitfalls (no test coverage, no DECISIONS.md, hardcoded allowlist).
- In code review. Scan recent diffs for matches; link the relevant skill section in the PR comment.
- After incidents. Add the failure mode to the skill where its principle lives (not here); if it doesn’t fit any skill, add a process pitfall below.
Cross-skill failure index
Section titled “Cross-skill failure index”Each entry: one line, pointing at the skill section that owns it.
Stack / architecture
Section titled “Stack / architecture”- Mixed tRPC + server actions —
factory-api.md §API style — pick one - Custom auth adapter when an official one exists —
factory-auth.md §Better Auth — plugin composition - Triple-fallback auth surface (Clerk → token → header) —
factory-auth.md §The wrapper interface - No auth at all (
publicProcedureeverywhere) —factory-auth.md §Auth from day one - Hardcoded email allowlist —
factory-auth.md §Hardcoded email allowlists - Admin client at module scope —
factory-auth.md §Admin client — always wrapped
- Monolithic 1,500-line form —
factory-forms.md §Modular section files from day one
Frontend
Section titled “Frontend”- Two-way state-DB sync —
factory-frontend.md §One direction of truth - Currency formatting drift across views —
factory-frontend.md §Format helpers
- Querying inside JSONB at app speed —
factory-data-layer.md §Custom attributes as JSONB - Raw SQL with hand-mapped row→object —
factory-data-layer.md §ORM pick - Mixed migration-file naming —
factory-data-layer.md §Migration file naming
Pipelines
Section titled “Pipelines”- Pre-built
libs/py-libs/before second consumer —factory-data-pipelines.md §Don't pre-build shared libs - Pydantic models copy-pasted across entry points —
factory-data-pipelines.md §Three-entry-point pattern
LLM workflows
Section titled “LLM workflows”- Pydantic state for LangGraph —
factory-llm-workflows.md §State shape - No versioning on editable content (chat vs claims) —
factory-llm-workflows.md §Version anything editable later
Security
Section titled “Security”- In-memory rate limiter on serverless —
factory-security.md §Rate limiting - PHI in email without runtime BAA check —
factory-security.md §PHI in email/SMS - AI-generated code without a review queue —
factory-security.md §AI-generated code — read-only by default
Deployment
Section titled “Deployment”- Migrations at runtime (in Cloud Run CMD) —
factory-deployment.md §Migrations — CI, never runtime
Observability
Section titled “Observability”- Regenerated trace IDs at service hops —
factory-observability.md §Trace ID — propagate, don't regenerate
Commits
Section titled “Commits”- Commits with no Linear linkage —
factory-commits.md §Tie every commit to a Linear issue
Process pitfalls — no skill home
Section titled “Process pitfalls — no skill home”These are kit-shape and project-shape failures that don’t fit any one skill’s domain. They live here.
Three competing solutions for the same problem
Section titled “Three competing solutions for the same problem”Legacy applicationProgress.ts, intermediate sectionProgress.ts, and unified progress-calculator.ts all live in the same repo. The newer file is the source of truth but the older ones never got deleted.
Right move: when you write a unifier, delete the inputs in the same PR. Half-finished refactors are worse than untouched code — they imply the newer file is the truth while leaving the older ones as plausible alternatives that future contributors will pull from.
No tests under src/
Section titled “No tests under src/”A production-grade CRUD repo with zero test coverage. Nothing to extract as a “testing skill” because tests have to be authored from scratch.
Right move: Vitest + a smoke test for each feature folder from project setup. Add to the project’s DECISIONS.md as a layer-3 commitment.
No DECISIONS.md per project
Section titled “No DECISIONS.md per project”Decision-criteria choices (which auth, which UI lib, which API style) get relitigated each session. The kit’s factory-stack.md documents the criteria; the project’s DECISIONS.md records the picks.
Right move: every new project starts with a DECISIONS.md containing one-line entries per decision-criteria choice from factory-stack.md. Update on every architectural call.
Empty .claude/ or .agents/ directories
Section titled “Empty .claude/ or .agents/ directories”Implies intent without value. New contributors interpret the empty directory as “this is where convention lives” and put unrelated things there.
Right move: delete empty stubs. If intent matters, write the placeholder explicitly with TODO: so future-you knows what was planned.
Aspirational docs
Section titled “Aspirational docs”CLAUDE.md describing the architecture you wish you had, not the one the code actually has. New contributors get the wrong mental model. AI agents read it and propose work against a fiction.
Right move: treat CLAUDE.md as code. Update in the same PR as the refactor. If you write an AGENTS.md or CLAUDE.md, make it load-bearing or delete it.
Inconsistent CLAUDE.md formats across repos
Section titled “Inconsistent CLAUDE.md formats across repos”Each new project relitigates the format. The kit’s template (see CLAUDE.md in the kit’s root) is the canonical shape — extend it per project, don’t reinvent.
Right move: copy the kit’s CLAUDE.md template into the project’s root, fill in the project-specific bits (domain, decisions, layout). Same shape every time.