This handbook defines how automation agents collaborate safely and effectively on the TrainLCD mobile application. Follow these instructions for every bot- or AI-assisted contribution, regardless of scope.
- Honor instruction priority: repository owners & maintainers → latest task prompt → this handbook → other documentation. Surface conflicting requirements immediately.
- Preserve the working tree: operate on the current snapshot, never discard user changes, and avoid destructive commands (
git reset --hard,git clean -fd, etc.). - Favor minimal, auditable diffs: prefer additive edits, keep formatting deterministic, and annotate non-obvious changes with concise comments.
- Document reproducibility: record every manual command you execute and note any local assumptions about environment variables or credentials.
- Validate assumptions proactively: confirm tool versions, workflow expectations, and environment needs instead of relying on cached knowledge.
- Clarify uncertainty: request guidance or leave TODO notes rather than guessing at intent.
- Prioritize quality and performance over speed: prefer well-structured, performant implementations over quick solutions. Take extra time to consider edge cases, optimize hot paths, and ensure code correctness rather than rushing to deliver.
- Intake: read the full issue, PR discussion, or prompt; restate deliverables and constraints before coding.
- Reconnaissance: map relevant files with
rg,ls, orfind; review interfaces and existing patterns to plan compatible changes. - Plan: outline discrete steps, keep the plan updated as you progress, and expose blockers early.
- Implement: use
apply_patchfor targeted edits, commit in small logical units, and avoid regenerating large files unless required. - Validate: run only the necessary commands (
npm run lint,npm test,npm run typecheck, etc.) and capture summarized output. - Document & Handoff: update READMEs or docs when behavior changes, summarize modifications, list executed commands, and attach artifacts (logs, screenshots) before opening PRs.
src/: Expo React Native app code.src/components/,src/screens/: UI components and screen containers.src/hooks/,src/store/,src/stacks/: shared state, navigation, and composition hooks.src/lib/,src/providers/,src/config/: integrations, context providers, configuration utilities.src/constants/,src/utils/,src/translation.ts,src/lineSymbolImage.ts: constants, helpers, localization maps, and asset selectors.@types/,src/__mocks__/,src/__fixtures__/,test/: global typings, reusable mocks, fixtures, and test helpers.
assets/: static media (images, fonts, icons).docs/: human-facing documentation including changelog and incident notes.utils/: developer tooling scripts such as GraphQL codegen config.android/,ios/: native projects.
The Cloudflare Workers backend (TTS via Azure Speech, feedback triage via Workers AI, review notifiers) has been moved out of this repository into the TrainLCD/BFF monorepo. The former
functions/directory no longer lives here.
- Target Node.js 22.x and npm 10.x.
- Run
npm installwhen dependencies shift; avoid re-locking packages unless instructed. - Metro cache issues: run
expo start --clearonly when debugging build failures and document the action. - For native builds, rely on project scripts (
npm run android,npm run ios). - GraphQL codegen requires
GQL_API_URLin.env.local; runnpm run gql:codegenafter document or schema updates.
npm run start: start the Expo Dev Client locally.npm run android/npm run ios: build native binaries.npm run web: run the web preview.npm run lint: execute Biome linting (biome ci ./srcin CI).npm run format: apply Biome formatting fixes.npm test: run Jest in UTC; add--watchor--runInBandfor debugging.npm test -- --updateSnapshot: refresh Jest snapshots when output diffs are intentional.npm run typecheck: enforce TypeScript constraints.npm run gql:codegen: regenerate generated GraphQL types.
.editorconfigenforces UTF-8, two-space indentation, single quotes, and ES5 trailing commas.- Biome is authoritative; avoid
// biome-ignoreunless a rule is truly incompatible and document the rationale inline. - Components → PascalCase (
StationBanner.tsx); hooks →use*(useStationFeed.ts); Jotai atoms →store/atoms/*.ts; GraphQL operations →FeatureVerbQuery. - Jotai state is held in field-level primitive atoms (named exports such as
arrivedAtom,headerStateAtom). Always subscribe to those for reads; the default-exportedstationState/navigationState/lineStateare write-compatible facades and subscribing to them re-renders on every field change. Seedocs/state-management.md. - Void side-effect hooks that subscribe to high-frequency atoms (
locationAtomupdates every second while riding) must not be called in a screen component's body. Host them in a renderless effects component instead (MainScreenEffectsinsrc/screens/Main.tsx,PermittedLayoutEffectsinsrc/components/Permitted.tsx; one hook perFx*component so per-hook render cost stays measurable). Gate platform- or setting-specific hooks by conditionally mounting their host (FxTTS,FxUpdateLiveActivities). For objects with high-frequency fields such aspictureInPictureAtom.activityState, subscribe the narrow derived atoms (pictureInPictureEnabledAtom/pictureInPictureActiveAtom) instead of the whole atom. Details indocs/state-management.md. - Co-locate style modules or constants near their consumers; share cross-cutting utilities through
src/utils/. - Keep comments purposeful: explain intent or non-obvious constraints, not obvious mechanics.
- React StrictMode intentionally re-runs effect setup/cleanup in development. Treat mount-time effects as repeatable, and never rely on an empty dependency array to mean "runs exactly once" for visible side effects.
- Do not call
Alert.alertdirectly fromuseEffector from async functions launched byuseEffect. StrictMode can evaluate the same persisted condition twice before the first alert is dismissed, which may stack duplicate native alerts. - For automatic alerts, use the shared alert presentation guard in
src/utils/alertPresentation.tsor an equivalent keyed presentation layer. The guard should prevent duplicate alerts only while the same logical alert is already being presented, and should release the key when the user presses a button or dismisses the alert. - User-initiated alerts from event handlers such as
onPressmay callAlert.alertdirectly when they are not triggered by mount-time or subscription effects. - If an effect writes shared app state during cleanup, confirm that the cleanup represents a real lifecycle event such as a navigation
beforeRemove, not only StrictMode's development-only unmount check.
markdownlint-cli2 準拠。CodeRabbit も同ルールで指摘するため、執筆時点で以下を守る:
- MD040 (fenced code language): フェンスコードブロックには必ず言語指定を付ける。用途別の既定: 平文の図示・実行計画サマリは
text、シェル例はbash、差分はdiff、埋め込みテンプレ本文はmarkdown、構造化データはjson/yaml。 - MD038 (no spaces in code spans): インラインコード(バッククォート)の内側先頭・末尾に空白を入れない。
`**v<release_version>**`は OK、`**v<release_version>** `は NG。 - MD031 / MD032 (blanks around fences / lists): フェンスコードブロック・リストブロックの前後に空行を 1 行入れる。
- MD029 (ordered list numbering): 順序リストの番号付けは単一ファイル内で統一する(全て
1.で書くか、1.2.3.と逐次番号を振るか)。 - MD033 (inline HTML): Markdown で表現できる構造は HTML タグに落とさない。例外として
<details><summary>…</summary>と表セル内の<br>は許可。
- Jest global setup lives in
jest.setup.jsandsrc/setupTests.ts. - Co-locate unit tests as
.test.tsor.test.tsxsiblings to the module. - Reuse helper utilities from
src/utils/test/to avoid duplicate setup code. - Mock network and backend API layers with
jest.mock, and calljest.clearAllMocks()inafterEach. - For integration flows, extend
src/test/e2e.tsand prefer fixtures fromsrc/__fixtures__/. - When modifying behavior, update or add tests in the same change set; document skipped tests with TODOs and owner rationale.
- Commit messages must be single-sentence statements in Japanese (e.g.,
テレメトリー送信機をリファクタリングしてnull状態を回避); prefix production hot fixes withHotfix:. - Keep commits logically scoped (implementation, tests, docs) and mention generated artifacts in the description.
- Pull requests must follow
.github/pull_request_template.md; do not add or remove sections from the template without maintainer approval. - Pull requests must be assigned to
@TinyKitten. - Pull requests must include:
- Purpose and summary of key changes.
- Regression risk assessment and mitigation.
- Commands executed locally (e.g.,
npm run lint && npm test && npm run typecheck). - Linked issues or tickets.
- Screenshots or recordings for UI/UX deltas with device names (e.g., Pixel 8, iPhone 15 Pro).
- If CI fails, pause reviews until you add root-cause notes plus reproduction steps or open an issue for blocking infrastructure problems.
- Keep PR metadata in sync with the branch state. Whenever you push new commits to an open PR, refresh both the PR title and the body:
- Title: re-evaluate whether the current title still describes the full scope of the branch. If new commits introduce a subject that the title does not cover, propose an updated title and, once approved by the user, apply it via
gh pr edit --title. - Body: update the
変更の種類checkboxes, the変更内容summary, and the test-result section so they reflect the updated diff. Preserve human-authored prose sections (概要, narrative added under変更内容,関連Issue,スクリーンショット) unless the changes invalidate them.
- Title: re-evaluate whether the current title still describes the full scope of the branch. If new commits introduce a subject that the title does not cover, propose an updated title and, once approved by the user, apply it via
- Store secrets in
.env.local; treat.env.exampleas the template for onboarding (copy it to.env.localand fill in values). - Never commit credentials, access tokens, or production endpoints.
- Protect Expo credentials with 2FA and rotate access when automations change.
- After dependency upgrades (
npm update) or Expo SDK migrations, runexpo-doctor,npm run lint,npm test, andnpm run typecheck, then capture results indocs/changelog.md.
Before submitting code changes
- Confirm requirements and flag conflicts.
- Update or add tests relevant to code changes.
- Run
npm run lint,npm test, andnpm run typecheck; record summaries. - Update documentation (README, docs/, inline comments) if behaviors shift.
- Capture screenshots/video for UI changes with device labels.
For documentation-only tasks
- Ensure docs match current directory structure and script names.
- Update cross-references (README, docs/) to prevent drift.
- Spell-check or self-review for clarity and typos.
For workflow, release, or CI updates
- Cross-check
.github/workflows/for consistency. - Provide dry-run instructions or environment prerequisites.
- Document required secrets, environment variables, or service accounts.
- Surface blockers or ambiguities in the task thread; do not proceed on assumptions.
- When discovering regressions or flaky tests, open an issue with reproduction steps and assign the relevant code owner.
- After incidents or hot fixes, append learnings to
docs/changelog.mdand notify maintainers for follow-up.