tac-karpathy-discipline
Load before ANY non-trivial task in tac-express. Enforces four principles: Think-Before-Coding, Simplicity-First, Surgical-Changes, Goal-Driven-Execution. Includes TAC Express–specific checks, anti-pa
Files1
View on GitHubSKILL.md.claude/skills/tac-karpathy-discipline/SKILL.md
GitHubKarpathy Coding Protocol — TAC Express Edition
Adapted from Andrej Karpathy's observations on LLM coding pitfalls. Bias: caution over speed. For trivial one-liners, use judgment — not every change needs full rigor.
PRINCIPLE 1 — Think Before Coding
Don't assume. Don't hide confusion. Surface trade-offs.
Before writing a single line:
- State assumptions explicitly. If uncertain about scope, data shape, or intent — ASK.
- Surface ambiguity. If the request has multiple valid interpretations, present them. Never pick silently.
- Push back when warranted. If a simpler approach exists, say so. If the ask violates The Fourteen Laws, name the violation and propose the compliant alternative.
TAC Express checks BEFORE coding:
- Which package does this belong in? (
packages/ui/packages/services/packages/database/apps/web/apps/dashboard) - Does this violate any of The Fourteen Laws?
- Is a forbidden package about to be installed?
- Is business logic ending up in a component instead of
packages/services? - Am I about to call Supabase directly from a component (LAW 6/8)?
- Does the status update need a TrackingEvent insert (ADR-004)?
❌ "Update the shipment status" → sets shipment.status directly
✅ Flags: ADR-004 says status is event-derived. Inserts a TrackingEvent instead.
❌ "Add a filter" → writes filter logic in the component
✅ Moves filter logic to packages/services, passes result as prop
PRINCIPLE 2 — Simplicity First
Minimum code that solves the problem. Nothing speculative.
- No features beyond what was asked
- No abstractions for single-use code
- No error handling for impossible scenarios
- If you write 200 lines and it could be 50 — rewrite it
TAC Express–specific simplicity rules:
- Don't pre-build multi-variant CVA components when only one variant is needed yet
- Don't create a service function for something called only once from one place
- Don't add loading/error states to a component that has no async data yet
- Don't add Zod schemas for data that isn't user-facing input yet
- Don't create new CSS tokens when existing ones already express the intent
PRINCIPLE 3 — Surgical Changes
Touch only what you must. Clean up only your own mess.
When editing existing files:
- Do NOT "improve" adjacent code, comments, or formatting
- Do NOT refactor things that aren't broken
- Match existing style even if you'd do it differently
- If you notice unrelated dead code — mention it, don't delete it
When YOUR changes create orphans:
- Remove imports, variables, and functions that your changes made unused
- Do NOT remove pre-existing unused code unless explicitly asked
TAC Express–specific surgical rules:
- Don't reorder exports in
packages/ui/src/components/index.tsunless the task requires it - Don't rename CSS custom properties you didn't introduce
- Don't touch
apps/web/app/layout.tsxfonts unless the task is font-related (ADR-005) - Don't "clean up"
globals.csstokens while fixing a layout bug - Don't switch
var(--token)to inline hex while "just fixing padding"
PRINCIPLE 4 — Goal-Driven Execution
Define success criteria. Loop until verified.
Transform imperative tasks into verifiable goals:
| Instead of... | Transform to... |
|---|---|
| "Add validation" | "Write tests for invalid inputs → make them pass" |
| "Fix the bug" | "Write a test that reproduces it → make it pass" |
| "Make it look better" | "Apply Violet Grid token pattern → verify no raw colors" |
| "Integrate the service" | "Mock at DB boundary → unit test passes → integration test passes" |
TAC Express verification ladder (run in order):
1. pnpm typecheck → zero TypeScript errors
2. pnpm lint --max-warnings 0 → zero ESLint warnings
3. pnpm test → all tests pass
4. pnpm build → succeeds in all packages
5. Browser check → feature works end-to-end in dev
6. Visual review → Violet Grid token compliance, no hardcoded values
Quick Decision Matrix
| Task Type | Mode | Apply Principles |
|---|---|---|
| Obvious 1-liner / typo fix | Speed | 3 only |
| Bug fix | Caution | 1 + 3 + 4 |
| New feature | Full rigor | All 4 |
| Refactor | Caution | 1 + 2 + 3 + 4 |
| Code review | Full rigor | All 4 |
| Design/token change | Full rigor | 1 + 3 + Law compliance |
Violation Response Protocol
When asked to do something that violates The Fourteen Laws:
"I can't do that — it violates [LAW X].
What you asked: [restate request]
Why it violates: [brief explanation]
Compliant approach: [concrete alternative]"
Never silently comply with a violation. Always name it and propose the fix.
Worktree & artifact hygiene (end-of-session teardown)
Added 2026-05-18 after the post-#162 follow-up surfaced an inert
tac-whatsapp-sends-102/directory sitting at the repo root — a stale clone from a previous worktree-style session that nobody tore down. Inert directories at the repo root pollute grep, pollutegit status, and make worktree-list inspection misleading.
At the start of a session that creates a worktree
- Use
git worktree addto a path outside the repo root (C:/tac/tw-<short-task-name>is the established convention — see existingtw-dod,tw-launch,tw-prodscope,tw-sb1…) OR use the harnessAgent({ isolation: "worktree" }), which auto-cleans on no-op. - Never
git clonea sibling copy of the repo inside the primary clone's directory. The repo root is for the primary working tree only.
At the end of every session
Whenever the session created a worktree, before declaring the run done:
- List worktrees:
git worktree list. - Identify the ones this session created. Branch name + path should match.
- For each whose PR is merged or abandoned:
git worktree remove <path>— drops the worktree.git branch -D <branch>— ONLY if the branch is fully merged or deliberately abandoned. Otherwise keep it.
- If a stale non-worktree directory exists inside the repo root
(an old clone, a scratchpad copy, an untracked sibling repo):
- Verify it is NOT a registered worktree (
git worktree listdoes not show it AND<dir>/.gitdoes not exist). - Confirm with the owner before deleting if there's any chance it contains uncommitted work.
- Otherwise
rm -rf <dir>— repo-root pollution is a real cost.
- Verify it is NOT a registered worktree (
Sentinel against recurrence
If the same untracked-stale-directory artifact appears again across
sessions, that's a tac-skillify trigger — convert this section into
a hooked cleanup step rather than written discipline. Until then, the
written rule + end-of-session checklist is the floor.