Development Tasks
本頁內容尚未翻譯。
Quick navigation for common TomoriBot implementation tasks and coding conventions.
Task Index
Section titled “Task Index”Each guide below is self-contained with steps, notes, and a quality gate.
| Task | Guide |
|---|---|
| Add a slash command | adding-slash-command.md |
| Add an event handler | adding-event-handler.md |
| Add a built-in tool | adding-builtin-tool.md |
| Add a DB column | adding-db-column.md |
| Add a Full Install setup module | adding-setup-module.md |
| Add a locale | adding-locale/ |
| Add a new AI provider | adding-new-provider.md |
| Add a feature flag-controlled tool | adding-feature-flag-tool.md |
| Add a persona preset | adding-persona-preset.md |
| Add an environment variable | adding-env-variable.md |
| Add or move docs pages | docs-authoring.md |
| Localize the docs site or READMEs | docs-site-localization.md |
| Write or review code comments | comment-policy.md |
Development Checklist
Section titled “Development Checklist”Run these before merging any change:
bun run check # TypeScript strict modebun run lint # Biome lint/formatbun run check-locales # locale key parity (when locale keys or command metadata changed)bun run db:lifecycle # schema lifecycle test (when schema.sql changed; needs local PostgreSQL)bun run lint applies fixes in place, so it can leave your working tree changed after it reports
success. Commit whatever it rewrites: CI runs bun run lint:ci, which is the same Biome check
without --fix, and that one fails on formatting instead of silently correcting it.
bun run db:lifecycle requires a local disposable PostgreSQL target with CREATE/DROP database
permission. It creates and drops its own temporary database, then tests fresh initialization plus
backup/restore and DB maintenance scripts.
To run selected regression files through the same disposable-database harness, pass their paths to the test script:
bun run test tests/regression/db/llm.regression.test.tsOne command for every gate
Section titled “One command for every gate”bun run vl runs the whole check suite and prints one verdict per gate, so it is the fastest way to
answer “is this branch green” without remembering each script name:
bun run vlIts last line is machine readable, which matters when a wrapper or an agent reads the result rather than a person:
vl-status: PASS exit=0 pass=<n> warn=<n> fail=<n> skip=<n>Output is quiet by default. No flag means quiet; --verbose is opt-in. A gate that passes prints
nothing, and its row in the results block carries the verdict. A gate that fails always prints its full
detail, so quiet mode can never hide a finding; it only removes the passing noise around one. Advisory
detail, such as locale parity or the lockfile-wide bun audit listing, collapses to a count or to the
entries that changed the verdict.
Pass --verbose to restore every line each gate would otherwise print:
bun run vl --verbose--no-verbose is the explicit spelling of the default rather than a mode of its own: it produces the
same output as passing nothing. It exists so vl can force quiet onto the checks it invokes, and it
wins over --verbose regardless of the order the two appear in. It is never required.
Individual gates accept both flags, and vl forwards one to them. Redirect the output to a file
if you want to keep the exit code while reading selectively, and never pipe a gate through grep or
tail: the pipeline reports the filter’s exit status instead of the gate’s.
bun run vl > /tmp/vl.log 2>&1; echo "VL_EXIT=$?" >> /tmp/vl.logCoding Conventions
Section titled “Coding Conventions”These rules apply to all TomoriBot source code regardless of task type.
Formatting and Style
Section titled “Formatting and Style”- Use 2 spaces for indentation (Biome project setting).
- Use double quotes for strings.
- Write comments that explain rationale, constraints, or non-obvious behavior. See the
comment policy. - Run
bun run lintafter edits.
TypeScript and Validation
Section titled “TypeScript and Validation”- Keep TypeScript strict; avoid
any. - Prefer explicit shared types under
src/types/. - Use Zod/runtime validation for untrusted external input.
- Add concise JSDoc for exported/public functions when behavior is non-obvious.
File Organization and Imports
Section titled “File Organization and Imports”- Use
camelCasefile names. - Use
@/*path aliases forsrc/*imports. - Use
node:protocol for Node built-ins (node:path,node:fs, etc.).
Configuration and Magic Numbers
Section titled “Configuration and Magic Numbers”- Do not hardcode operational limits/timeouts/thresholds in feature logic.
- Use env vars with fallback defaults:
const VALUE = Number.parseInt(process.env.CONFIG_VAR || "10", 10);- Add required setup vars to
.env.exampleand optional/tuning vars to.env.optional.example, each with a clear comment. Seeadding-env-variable.mdfor the tier system and placement conventions.
Database and Migrations
Section titled “Database and Migrations”- Use Bun SQL template literals for queries.
- Keep schema migrations idempotent (
IF NOT EXISTS, helper functions, guarded blocks). - For DB model details, see
docs/en/architecture/subsystems/database-schema.md.
Cache-Safe Write Pattern
Section titled “Cache-Safe Write Pattern”When a write affects cached reads:
- Perform the DB write successfully.
- Then invalidate affected cache key(s).
Do not invalidate before failed writes, and do not manually mutate cached objects.
See docs/en/architecture/subsystems/caching.md for the cache map and invalidation APIs.
Logging and Error Handling
Section titled “Logging and Error Handling”- Use
logfromsrc/utils/misc/logger.ts. - Include useful context metadata (
errorType, IDs, action context). - Treat startup-critical failures differently from recoverable runtime failures.
Discord Command Rules
Section titled “Discord Command Rules”- Slash commands only (no legacy prefix command surface).
- All user-facing text must be localized via
localizer(). - Follow interaction timing patterns in
docs/en/architecture/subsystems/command-system.md.