Replace the homegrown "Context Engineering" convention with the canonical Project Context Records (PCR) block in AGENTS.md, and migrate the .agents/docs/ records to match. - cross-links: [[wiki-link]] -> relative markdown [name](./name.md) - provenance: the old "Maintainer decision (DATE): KEEP" markers -> canonical [VOUCHED @hyf0] stamps (dates dropped, KEEP/OVERRIDE verdicts kept), covering every variant ((DATE, user-blessed), (maintainer decision DATE), and "(Decision recorded after review surfaced it.)") - methodology prose describing the mechanism reworded to the vouch vocabulary (generic [VOUCHED @handle]) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
7.7 KiB
Common Pitfalls & Best Practices
- AGENTS.md is the source of truth. CLAUDE.md is a symlink to it.
- Always use Vue's
shallowRefoverrefby default. Usingrefrequires a solid justification and a code comment explaining why deep reactivity is needed. - Always use
defineComponent()to define components. Never use bare{ setup() {} }objects — they lack component scope, soinject,watch, andonScopeDisposewon't work correctly. - Vue SFCs must use
<script setup>unless there's an explicit reason not to. - When passing function-valued props into composables, do not pass a one-time prop value
like
useInput(props.onInput). Pass a live source withtoRef(props, "onInput"), or pass a wrapper closure that readsprops.onInput(...)at event time. For composable APIs that accept function handlers, preferMaybeRef<Handler>+unref()overMaybeRefOrGetter<Handler>: handler functions and getter functions are ambiguous. - For ordinary Vue UI, start with template syntax. Use JSX/TSX when it makes test fixtures or highly dynamic structures clearer, and reserve
h()for renderer internals or genuinely programmatic vnode construction where template/JSX would be the wrong tool. - Prefer kebab-case for new file names, including Vue SFCs and JSX/TSX files. Keep local consistency when touching existing areas, and do not rename existing files only for casing unless the task is explicitly about naming.
- When code must deviate from normal/idiomatic style because the situation genuinely requires it (e.g. a control-character regex in a terminal parser, a deliberate string code-point spread, a lint rule suppressed for a justified reason), add a comment explaining why it has to be written that way. Don't silence a linter or write surprising code without a note — the next reader should not have to guess whether it's intentional.
- Bug fixes must follow test-first: write a failing test that reproduces the bug, then fix the code and verify the test passes.
- Tests must simulate real user conditions. Non-TTY environments disable chalk colors — use
FORCE_COLORenv var so ANSI output is always exercised. A bug invisible in tests but visible in a real terminal is a testing gap, not a minor issue. Each spawned subprocess is a fresh Node process with its own chalk, so PTY/child helpers must setFORCE_COLORin the child env too, not just the vitest config. - When debugging color/ANSI output in non-TTY environments (e.g. Claude Code shell), use
FORCE_COLOR=3env var to force chalk to output ANSI codes. - Test files run in parallel (
fileParallelism: true), but tests WITHIN a file run serially. We deliberately do NOT setsequence.concurrent: many render tests assert timing-sensitive counts driven by the renderer's ~32ms commit throttle, and in-file concurrency starves them of wall-clock on a 4-core CI runner (it passes on higher-core dev machines — the classic local-vs-CI trap). PTY tests needpool: "forks"(node-pty requireschild_process.fork, not worker threads). - Tests that depend on process-global state — fake timers (
vi.useFakeTimers, which mutates globalsetTimeout/performance) or assertions on shared globals (process.listenerCount, live yoga-node counts) — live in*.sequential.test.*files. Even file-level parallelism can perturb them, and grouping them by name documents the constraint. Add a header comment saying which global forces it. - Tests must not implicitly depend on the host environment. The CI runner sets
CI=true, which flipsinteractive = !isInCi && isTTYoff (disabling the resize listener, cursor, ANSI erases) — so both vitest configs forceenv: { CI: "false" }, and PTY child helpers setCI: "false"per-spawn. If a test needs a specific CI/TTY/color behavior, inject it explicitly (mount option, child env) rather than relying on the ambient value. Reproduce CI locally withCI=true vp run cion a fresh checkout (rm -rf packages/*/dist). - After completing any task, run
vp run ready(orvpr ready) to verify: lint, type-check, test all packages, and build. - Commit messages and PR titles must follow Conventional Commits, e.g.
fix(runtime): align Ink parity behavior. - Never commit anything under
docs/. That directory is for local working notes and specs — it must stay out of git. - To read Ink's source (parity / divergence work), clone it once to a fixed local path and read from there —
git clone https://github.com/vadimdemedes/ink /tmp/inkonly when/tmp/inkis missing, otherwise reuse the existing clone (Ink isn't an npm dependency, so it's not innode_modules). Before trusting anything you read, check out and confirm the pinned baseline —.agents/docs/ink-divergences.mdrecords the exact version/commit (currently v7.0.4); a claim read against the wrong Ink version is worse than none. - Behavior claims must be run, not reasoned: a parity assertion or
ink-divergences.md"what Ink does" line is a hypothesis until a real harness against the pinned version (real frames/stderr/exit) confirms it. Source-reading and memory can mislead; when a run contradicts the code you read, trust the run. - When documenting an intentional Ink divergence, update
.agents/docs/ink-divergences.mdand follow its "How to Classify a Divergence" flow. Do not add placeholder or unsorted entries; if the classification is unclear, state that uncertainty in the entry's rationale.
Project Context Records (PCR)
This project follows Project Context Records (PCR) — methodology: https://github.com/hyf0/project-context-records. PCR keeps the project's durable design context — the why, the decisions, the architecture — so you inherit it instead of re-deriving or re-litigating what's already settled.
When working here:
- Where they live. Records are in
.agents/docs/— one topic per file, cross-linked with relative Markdown links ([name](./name.md)). - Read first. If a record covers the area you're touching, read it before acting.
- Record as you go. Proactively write down context worth keeping — and whenever a human asks you to. No required format, no fixed list of what qualifies: if it's true about this project, not visible in the code, and useful beyond the moment, it's worth a record.
- Keep it fresh. If your change affects a record, update it in the same change — a stale record is a trap, not an asset.
- Provenance. An unstamped line is AI-accumulated: challenge and verify it freely.
A
[VOUCHED @handle]stamp (on a line, or at the top of a file) means a human vouched for it — treat it as settled; reopen or re-verify only on new evidence, a changed constraint, or a human's say-so. Add a stamp only on a human's explicit instruction; reading past a line, or not objecting, is not a stamp.
Using Vite+, the Unified Toolchain for the Web
This project is using Vite+, a unified toolchain built on top of Vite, Rolldown, Vitest, tsdown, Oxlint, Oxfmt, and Vite Task. Vite+ wraps runtime management, package management, and frontend tooling in a single global CLI called vp. Vite+ is distinct from Vite, and it invokes Vite through vp dev and vp build. Run vp help to print a list of commands and vp <command> --help for information about a specific command.
Docs are local at node_modules/vite-plus/docs or online at https://viteplus.dev/guide/.
Review Checklist
- Run
vp installafter pulling remote changes and before getting started. - Run
vp checkandvp testto format, lint, type check and test changes. - Check if there are
vite.config.tstasks orpackage.jsonscripts necessary for validation, run viavp run <script>. - If setup, runtime, or package-manager behavior looks wrong, run
vp env doctorand include its output when asking for help.