4.0 KiB
Instructions for Claude working in this repo
Never fabricate, never bluff
Do not state a number, a test result, a "verified" claim, or a capability estimate unless it is backed by something you actually ran or actually read. If you haven't checked something, say so explicitly ("not verified yet", "estimate, not measured") instead of presenting a guess as fact.
Why: this project involves parsing a medical reference book into a chatbot's knowledge base — false confidence here is not a cosmetic bug, it propagates into medical answers. During the ingestion-strategy investigation, a size-based heading threshold silently dropped ~15% of real monographs before whole-document validation caught it; a monograph-boundary scan was initially run on 1405 of 1668 pages before being caught and corrected. Confident-sounding claims that turn out wrong cost real rework and could cost real answer quality once this is live.
How to apply:
- Prefer "I ran X and got Y" over "X should work" — run the check.
- When asked something you don't know for certain (throughput estimates, whether a tool/library works on this environment, whether a heuristic holds at scale), say what's measured vs. estimated, explicitly.
- Whole-document / whole-scope validation over small-sample claims — if the user states a total (e.g. "1668 pages"), any check must cover that literal total before being reported as done, not a convenient subset.
- When a claim turns out wrong after fuller checking, say so plainly and show the corrected result — don't quietly smooth over the miss.
See docs/pdf-parsing-outlier-catalog.md and
docs/adr/0003-pdf-parsing-strategy.md for the concrete track record this
rule comes from.
Real code follows Clean Code / Clean Architecture / SoC / DRY / SOLID
Applies to anything meant to be committed as part of the actual system
(apps/*, ingestion/*, packages/*) — not throwaway investigation
scripts (e.g. a one-off scan to check a hypothesis), which may stay quick
and disposable as long as they're never confused for production code and
get deleted once their finding is written down.
Why this is a written rule, not just an intention: intentions from one conversation don't carry into the next session, and under time pressure or mid-refactor it's easy to let a principle slip without noticing — a written checklist is what actually catches that, the same reasoning behind the "never fabricate" rule above.
How to apply, concretely, in this repo:
- SoC: keep the
ingestion/pipeline stages (extract/,segment/,chunk/,embed/,load/) genuinely independent — extraction code must not know about chunking, chunking must not call OpenAI, etc. - DRY: shared logic (e.g. the bold-span heading/boundary detector) lives in exactly one module that both the real pipeline and any validation script import — never re-implemented per script, which is what happened during exploratory investigation and is fine there, but must not carry into real code.
- SOLID: single-responsibility modules/classes (a detector detects, it
doesn't also chunk); open/closed section taxonomy (adding a new section
label — e.g. a field like "Tên thương mại" not in the book's own
documented list — must not require editing existing matching code, only
adding an entry); dependency inversion at infrastructure boundaries
(
ai-service's domain/retrieval logic depends on an interface, not a hard import of the Qdrant SDK or OpenAI client directly, so it stays testable without live services). - Clean Architecture: domain/business logic (parsing rules, chunking rules, retrieval/grounding logic) stays independent of infrastructure (OpenAI SDK, Qdrant client, filesystem, NestJS framework details) so it's testable in isolation.
- Clean Code: meaningful names, small functions, minimal comments (only where the why isn't obvious from the code itself) — matches the no-comments-unless-non-obvious style already used throughout this project's docs and ADRs.