AGENTS.md
Agent guide
- NEVER write unit tests after you write code.
- Highly prefer E2E tests as the sole testing mechanism. Use them to verify complex features work. At the end of E2E tests, produce a verifiable and repeatable artifact.
- If you must test a system in isolation, FIRST write all the ways it could fail, THEN write the code.
Unit tests written after the code restate it: they always pass, catch almost nothing and break on every refactor. Here E2E means the suite in e2e/ that runs against a deployed stack, including each PR's preview. A case added to an existing service or component test counts as an isolated test.
Make the smallest direct change. Use inferred types and named exports. New abstractions, helpers and test files need user approval. Keep any and casting wrappers out of application code. Lint enforces most of the code rules; its messages say what to use instead.
Read for the task
- Solid: the
solidjs-v2skill. Effect: theeffectskill. Panda: thepanda-cssskill. Installed types beat the skills. - Library docs, installed source paths, renamed APIs and known pitfalls: docs/LIBRARIES.md. Read it before you search
node_modulesor the web. - Writing or reviewing code: docs/CONVENTIONS.md. Placement and request scope: docs/STRUCTURE.md. Effect reads in Solid: docs/SOLID-EFFECT-BINDING.md. Tools: docs/STACK.md.
- Product scope: docs/VISION.md. Plans, prices, limits: docs/PRODUCT.md. Judgment and tone: docs/SOUL.md.
- Upload, resume, download, cancel: docs/RELIABILITY.md and docs/BENCHMARKS.md. Tests and scenarios: docs/TESTING.md.
- Remaining work: docs/plan/, starting with
01-foundation.mdanddeslop/00-index.md. - Local serving: the
portlessskill, thenvp run dev. - External precedent:
~/dev/tranzfer2-references/README.md. Those checkouts use other prereleases; verify syntax locally. - Never put a URL, query string, cookie, email or link token in a span attribute or log. Traces go to Axiom (STACK.md).
Change and verify
- In a new worktree run
vp installfirst; it generatesstyled-systemand the route types. After changes runvp check --quiet,vp run testand the relevantvp run build, unpiped, or withset -o pipefail: the exit code is the verdict. Report missing tests or blocked checks as such. - Reactivity changes: dev builds report Solid diagnostics. Treat every code as a defect and never allowlist one you haven't understood. Read the codes while you exercise the change in
vp run dev; common repairs are in LIBRARIES.md. If you cannot run the dev server (a worktree has no.env), say so. - Keep lint enabled. An exception needs user approval, a file-scoped override and a one-line reason. A new rule goes in at error with every hit fixed: custom rules in
tools/oxlint/anti-slop/tranzfer/, each with a RuleTester test, the one exception to the test-file rule. - Comments explain runtime quirks and non-obvious constraints.
- Verify by running, not by reading. Quote counts from command output. Reproduce a failing check on unchanged
origin/devbefore blaming the diff, and a review-bot finding before fixing it. - After the same step fails twice, stop and report the exact error. Cap a spike on a prerelease (Solid, Effect, Alchemy, Panda, drizzle-kit) at 30 minutes, then report a minimal repro.
- Never read
.env*or print secrets. Pass them through the environment (node --env-file). - Migrations: rebase on
origin/dev, thencd packages/db && vp run generate --name <slug>. Ifvp exec drizzle-kit checkreports a fork after a merge,git rm -ryours and generate again. Never editsnapshot.json. - The API Worker's resources and bindings live in
apps/api(resources.ts,index.ts);infra/alchemy.run.tscomposes the stack. A rate limit is one row inbindingLimits(apps/api/src/rate-limiter.ts); one the client sees also goes inrateLimits(contracts) and the webtooManycopy. Workernameprops stay unset: an explicit name once let staging overwrite production's Workers.
Deploys
- Deploy only from the main checkout, after build and plan review. From a worktree, push and check the PR preview.
- Each same-repo PR deploys stage
pr-<number>athttps://pr-<number>.tranzfer.appand runs the e2e suite there.devdeploys staging.tranzfer.app (sign in withPOST /api/auth/staging-login);maindeploys production. - A worktree can still plan a preview:
ALCHEMY_STAGE=pr-0 POLAR_SANDBOX_ACCESS_TOKEN=x TEST_LOGIN_KEY=<32+ chars> vp run --filter @tranzfer/infra plan:preview. Staging and production plans need the main checkout's.env.
Parallel work
- At most 3 subagents at once, each in its own worktree under
~/dev/scratchpad/tranzfer2on its own branch, committing and pushing after every green step so a killed agent leaves a branch. Reviewers get a shell and the check to run: read-only reviewers approved bugs that one with a shell caught. - Never
rm,git clean,git stashorgit checkout <branch>in a checkout another thread may use, and neverpkill -f; stop only the PID you started. - Wait for CI with one backgrounded
gh pr checks <number> --watch --interval 60. Read a failure once withgh run view <id> --log-failed. - Local pages:
agent-browser, with its own--sessionper agent. Dash shells with a 30 s limit: wrap bash syntax inbash -cand start servers withsetsid nohup ... &.
Keep the record useful
Docs hold standing decisions. Manifests and configuration hold versions and commands. Commits, PRs and issues hold investigation and progress. When a mistake repeats, make it a lint rule, a type or a check before you write prose about it.
Update a rule when a decision changes and cite the PR. Plan files contain remaining work; delete finished items and empty files. Before retrying a rejected approach, search recent commits and merged PRs for the reason.