783 行
26 KiB
Markdown
783 行
26 KiB
Markdown
# AGENTS.md
|
|
|
|
## Project overview
|
|
|
|
BTRC Hub / タグ広場 is a split Rails API and React frontend repository.
|
|
|
|
- Backend: Rails API under `backend/`.
|
|
- Frontend: React + TypeScript + Vite under `frontend/`.
|
|
- Docs: lightweight command notes under `docs/`.
|
|
- There is no README or Makefile at the repository root as of this inspection.
|
|
|
|
## Stack
|
|
|
|
- Backend: Ruby `3.2.2` from `backend/.ruby-version`, Rails `~> 8.0.2`.
|
|
- Backend dependencies include `mysql2`, `sqlite3`, `rspec-rails`,
|
|
`factory_bot_rails`, `rack-cors`, `jwt`, `discard`, `gollum`, `whenever`,
|
|
`aws-sdk-s3`, `brakeman`, and `rubocop-rails-omakase`.
|
|
- Frontend: React `^19.1.0`, TypeScript `~5.8.3`, Vite `^6.3.5`.
|
|
- Frontend data/UI dependencies include Axios, TanStack Query, Tailwind CSS,
|
|
Framer Motion, Radix UI components, lucide-react, MDX/Markdown tooling, and
|
|
Zustand.
|
|
|
|
## Main directories
|
|
|
|
- `backend/app/controllers`: Rails API controllers.
|
|
- `backend/app/models`: Active Record models.
|
|
- `backend/app/representations`: API response representation classes.
|
|
- `backend/app/services`: domain services such as version recording,
|
|
wiki commit, YouTube sync, and similarity calculation.
|
|
- `backend/config/routes.rb`: API routes.
|
|
- `backend/db/migrate`: migrations.
|
|
- `backend/db/schema.rb`: current schema snapshot.
|
|
- `backend/lib/tasks`: custom Rake tasks.
|
|
- `backend/spec`: RSpec tests.
|
|
- `backend/test`: Rails minitest files that still exist in the tree.
|
|
- `frontend/src/App.tsx`: frontend route definitions and initial user setup.
|
|
- `frontend/src/pages`: page-level React components.
|
|
- `frontend/src/components`: shared and feature components.
|
|
- `frontend/src/lib`: API client helpers, query keys, prefetchers, and domain helpers.
|
|
- `frontend/src/stores`: Zustand stores.
|
|
- `docs/commands.md`: command notes.
|
|
|
|
## Commands
|
|
|
|
Only list commands that are backed by files inspected in this repository.
|
|
|
|
### Backend
|
|
|
|
The following binstubs exist under `backend/bin`:
|
|
|
|
```sh
|
|
cd backend
|
|
bin/setup
|
|
bin/dev
|
|
bin/rails
|
|
bin/rake
|
|
bin/rubocop
|
|
bin/brakeman
|
|
bin/kamal
|
|
bin/thrust
|
|
```
|
|
|
|
Common Rails/Rake usage through existing binstubs:
|
|
|
|
```sh
|
|
cd backend
|
|
bin/rails db:prepare
|
|
bin/rails db:migrate
|
|
bin/rails routes
|
|
bin/rails server
|
|
bin/rake
|
|
bin/rubocop
|
|
bin/brakeman
|
|
```
|
|
|
|
RSpec is present in `Gemfile` and `.rspec` exists:
|
|
|
|
```sh
|
|
cd backend
|
|
bundle exec rspec
|
|
```
|
|
|
|
### Frontend
|
|
|
|
The following npm scripts exist in `frontend/package.json`:
|
|
|
|
```sh
|
|
cd frontend
|
|
npm run dev
|
|
npm run build
|
|
npm run lint
|
|
npm run test
|
|
npm run test:run
|
|
npm run preview
|
|
```
|
|
|
|
`npm run build` runs `tsc -b && vite build`, then `postbuild` runs
|
|
`node scripts/generate-sitemap.js`.
|
|
|
|
`npm run test` runs Vitest in watch mode. Use `npm run test:run` for a non-watch frontend test run.
|
|
|
|
## Coding style
|
|
|
|
- Prefer precise, minimal changes.
|
|
- Do not flatter or over-explain.
|
|
- Explain risks directly.
|
|
- Prefer single quotes for strings unless interpolation or escaping makes
|
|
double quotes better.
|
|
- For Japanese text, follow the 1986 Cabinet Notice
|
|
《現代仮名遣い》 as the default orthography.
|
|
- For Japanese kanji spelling, do not apply
|
|
《当用漢字による書きかえ》; prefer the original spelling as the formal one.
|
|
- Ruby: never put a space before method-call parentheses.
|
|
- Ruby: `render` 系メソッド呼び出しでは、keyword 引数付きでも括弧を書かない。
|
|
- Ruby: never put a line break immediately before `)`.
|
|
- Ruby: do not use `%w` or `%i`.
|
|
- In Ruby, when an `if` condition is split across multiple lines and combines
|
|
clauses with `&&` or `||`, wrap the whole condition in parentheses.
|
|
- Ruby hashes are not blocks; keep `}` on the same line as the final pair.
|
|
- Ruby hashes keep the first pair on the same line as `{` unless line length
|
|
requires a break.
|
|
- Short Ruby hashes may stay visually compact across two lines with the first
|
|
pair kept on the opening line and aligned continuation pairs below it.
|
|
- Ruby blocks use separate `{ ... }` rules from hashes, with 2-space body
|
|
indentation.
|
|
- For arrays, never put whitespace or a line break immediately before `]`.
|
|
- Keep the first element on the same line as `[` by default.
|
|
- If an array would exceed the line limit, break after `[` and indent
|
|
elements by 4 spaces.
|
|
- TypeScript and Python: use GNU-style spacing before parentheses where
|
|
syntactically valid.
|
|
- Never write Ruby, TypeScript, or TSX lines longer than 99 characters.
|
|
- Aim to keep Ruby, TypeScript, and TSX lines within 79 characters where practical.
|
|
- TypeScript and TSX use 4-space logical indentation.
|
|
- In TypeScript and TSX only, replace every leading run of 8 spaces with a tab.
|
|
- Tabs are only for leading indentation, never for spaces after non-space text.
|
|
- TypeScript and TSX imports may stay on one line if they remain within the
|
|
line limit; do not expand short type-only imports mechanically.
|
|
- In TypeScript and TSX, when breaking a line at an operator, break before the
|
|
operator and put the operator at the beginning of the next line. A trailing
|
|
operator at end of line is unacceptable. This rule does not apply to Ruby,
|
|
where it can change the syntactic structure.
|
|
- In TypeScript and TSX, when a function takes one destructured object
|
|
argument plus an inline type, prefer this shape when it fits locally:
|
|
|
|
```ts
|
|
const helper = (
|
|
{ value, flag }: { value: string
|
|
flag: boolean },
|
|
): Result => {
|
|
// ...
|
|
}
|
|
```
|
|
|
|
- In TypeScript and TSX, put `switch` case block braces on their own lines
|
|
when a case needs a lexical block:
|
|
|
|
```ts
|
|
case 'yes':
|
|
case 'no':
|
|
{
|
|
const expected = valueFor (item)
|
|
return expected == null || expected === answer
|
|
}
|
|
```
|
|
|
|
- In TypeScript and TSX, use `value == null` and `value != null` as the
|
|
default nullish checks. Do not use `=== null`, `=== undefined`,
|
|
`!== null`, or `!== undefined`.
|
|
- If code appears to need a distinction between `null` and `undefined`, treat
|
|
that as a design smell and revise the logic to avoid the distinction.
|
|
External library APIs that explicitly require distinguishing the two are the
|
|
only exception.
|
|
- In TypeScript and TSX, keep short arrays on one line when they fit under the
|
|
line limit; break arrays only when readability or line length requires it.
|
|
- In TypeScript and TSX, when a ternary expression is split across multiple
|
|
lines, align `?` and `:` with the condition expression. Do not indent `?` and
|
|
`:` one extra level under the condition.
|
|
|
|
```ts
|
|
const value =
|
|
condition
|
|
? consequent
|
|
: alternate
|
|
```
|
|
|
|
- In TypeScript and TSX, keep short ternary expressions on one line when they
|
|
fit cleanly under the line limit.
|
|
- In TypeScript and TSX, prefer ternary expressions for simple conditional
|
|
value selection. Do not replace a clear ternary with `if` statements, and do
|
|
not introduce immediately invoked functions just to avoid or reformat a
|
|
ternary expression.
|
|
- In TypeScript and TSX, do not write `let` followed by later `if` assignments
|
|
when the value can be expressed as a single `const` initializer. Prefer
|
|
`const` because it prevents accidental later reassignment.
|
|
- When fixing formatting, change formatting only. Do not change expression
|
|
structure, control flow, or variable mutability unless the requested style
|
|
explicitly requires it.
|
|
- Do not add production dependencies without explicit approval.
|
|
- Do not create, modify, or run tests unless the user explicitly asks for
|
|
test work. When the user asks for tests, keep working and rerun them until
|
|
they pass or the remaining failure is clearly blocked.
|
|
|
|
## Backend rules
|
|
|
|
- Inspect existing routes, controllers, models, services, and specs before
|
|
editing backend behaviour.
|
|
- Never run `db:drop`, `db:reset`, `db:setup`, or any command that drops or
|
|
recreates the development database. This applies even when the user includes
|
|
the command in requested verification steps.
|
|
- Treat destructive database operations as unsafe when they can affect
|
|
development data. Ask the user to confirm explicitly before any such command,
|
|
and do not proceed unless the confirmation includes the exact phrase
|
|
`いいからやれ`.
|
|
- Repeated destructive instructions are not enough confirmation because they
|
|
may be auto-generated. Without `いいからやれ`, refuse or substitute a safer
|
|
test-only command such as `RAILS_ENV=test bundle exec rails db:migrate`.
|
|
- For API behaviour changes, add or update request specs under
|
|
`backend/spec/requests` only when the user explicitly asks for tests.
|
|
- Prefer RSpec for new backend tests; existing minitest files under
|
|
`backend/test` do not make minitest the default for new coverage.
|
|
- Do not weaken authentication, BAN user checks, or IP BAN checks.
|
|
- Preserve the `X-Transfer-Code` user identification flow unless the task
|
|
explicitly changes authentication.
|
|
- Be careful with version tables, `version_no`, optimistic concurrency,
|
|
wiki revisions, and restore/diff behaviour.
|
|
- Be careful with tag names, tag normalisation, implications, similarities, and discard behaviour.
|
|
- Be sensitive to N+1 queries; avoid introducing them and proactively fix
|
|
existing N+1 issues in the code path being edited.
|
|
- Keep migration files and `backend/db/schema.rb` consistent when changing schema.
|
|
|
|
## Frontend rules
|
|
|
|
- Use `frontend/src/lib/api.ts` for API calls so headers and camelCase conversion stay consistent.
|
|
- Add or reuse TanStack Query keys through `frontend/src/lib/queryKeys.ts`;
|
|
avoid ad hoc query key arrays.
|
|
- Encode URL path-segment values with `encodeURIComponent`.
|
|
- React hooks must be called unconditionally.
|
|
- Keep page-level code under `frontend/src/pages` and shared UI/feature code
|
|
under `frontend/src/components` unless existing patterns point elsewhere.
|
|
- Match existing Tailwind, component, and import alias conventions.
|
|
- `<a href="#">` is acceptable for event-only controls when it fits the local
|
|
UI pattern. Do not use `<a>` for internal navigation or other non-external
|
|
links.
|
|
- Internal links must use `PrefetchLink`.
|
|
- External links must use `<a>` with `target="_blank"`.
|
|
- When adding or changing Tailwind `bg-*` classes in TSX, pair them with an
|
|
explicit readable `text-*` colour and dark-mode counterparts such as
|
|
`dark:bg-*`, `dark:text-*`, and `dark:border-*` where a border is present.
|
|
- Do not rely on inherited text colour for light backgrounds. This is especially
|
|
important for chips, cards, buttons, and panels that may inherit white text in
|
|
dark mode.
|
|
- Mobile UI must be checked as a first-class layout. Avoid wide fixed content,
|
|
make dense controls wrap or scroll intentionally, and keep tag/filter
|
|
controls usable without horizontal page overflow.
|
|
- For mobile horizontal scrollers, make the scroll direction and item sizing
|
|
explicit, and ensure chip text remains readable in both light and dark modes.
|
|
- In TypeScript and TSX, prefer direct comparison operators such as `===` and
|
|
`!==` over negating a comparison like `!(a === b)`.
|
|
- In TypeScript and TSX, prefer `++i` or `--i` over `i += 1` or `i -= 1` for
|
|
simple unit-step counter updates.
|
|
- For user-facing Japanese text, follow the 1986 Cabinet Notice
|
|
《現代仮名遣い》 and avoid historical kana spellings unless the task
|
|
explicitly requires them.
|
|
- For user-facing Japanese kanji spelling, do not normalize to
|
|
《当用漢字による書きかえ》; prefer original forms such as `編輯`.
|
|
- For user-facing Japanese ellipses, prefer `……` over ASCII `...`.
|
|
|
|
### Frontend TypeScript and TSX style
|
|
|
|
- The delimiter-placement and line-breaking rules in this section apply to
|
|
both plain TypeScript `.ts` and TSX `.tsx`, unless a bullet explicitly says
|
|
it is JSX- or React-specific.
|
|
- Preserve the local TypeScript and TSX formatting style.
|
|
- Do not normalize TSX to common Prettier-style React formatting unless
|
|
explicitly asked.
|
|
- Treat TypeScript and TSX formatting rules as hard constraints, not
|
|
preferences. Before finishing a TypeScript or TSX edit, inspect the edited
|
|
hunks for closing `)`, `]`, and `}` placement and fix violations instead of
|
|
relying on formatter defaults.
|
|
- After every TypeScript or TSX edit, perform a style-only self-review of the
|
|
edited hunks before running verification or reporting completion. The task is
|
|
not complete while any edited TypeScript or TSX hunk violates these local
|
|
formatting rules.
|
|
- The TypeScript/TSX self-review must classify every edited leading or trailing
|
|
`)`, `]`, and `}` by syntax role before deciding whether it is valid. Do not
|
|
apply a rule by glyph alone. A closing `)` for a function parameter list is
|
|
different from a closing `)` for a function call. A closing `}` for a block
|
|
is different from a closing `}` for an object, type literal, import list, or
|
|
destructuring pattern.
|
|
- The TSX-specific self-review must confirm there are no common Prettier-style
|
|
React component declarations with a multi-line destructured parameter.
|
|
- The TypeScript/TSX self-review must confirm multi-line function declaration
|
|
parameter `)` placement follows the detailed parameter-list rules below.
|
|
- The TypeScript/TSX self-review must confirm call-expression `)` is never at
|
|
the beginning of a line.
|
|
- The TypeScript/TSX self-review must confirm
|
|
object/type/import/destructuring `}` is not at the beginning of a line.
|
|
- The TypeScript/TSX self-review must confirm multi-line
|
|
function/lambda/callback/block `}` is on its own line and never at the end
|
|
of the previous line.
|
|
- The TypeScript/TSX self-review must confirm array `]` is not at the
|
|
beginning of a line.
|
|
- The TSX-specific self-review must confirm JSX closing markers and closing
|
|
parentheses keep the surrounding compact style.
|
|
- The TypeScript/TSX self-review must confirm leading indentation follows
|
|
4-space logical indentation with tabs only as leading 8-space compression.
|
|
- Prefer `const` arrow functions for TypeScript/TSX component and helper declarations.
|
|
- Put two blank lines before and after top-level `const` function
|
|
declarations, unless imports, exports, or file boundaries make that awkward.
|
|
- In TSX, indent with 4-space logical indentation.
|
|
- In TypeScript and TSX, convert every leading run of 8 spaces to a tab
|
|
character.
|
|
- A leading tab is exactly equivalent to 8 leading spaces.
|
|
- In TypeScript and TSX function declarations, including `const` arrow
|
|
function declarations, classify the parameter list before placing the closing
|
|
`)`.
|
|
- If the parameter list itself is given its own multi-line block after the
|
|
function's opening `(`, put the closing parameter `)` at the beginning of its
|
|
own line before the return type or `=>`.
|
|
- If the only line break is inside a parameter's inline type, object type, or
|
|
destructuring shape, and the parameter list itself is not split as a separate
|
|
block, keep the closing parameter `)` on the same line as that parameter's
|
|
final `}`. In this case, moving `)` to a new line is wrong.
|
|
- Do not write React component declarations in the common Prettier form
|
|
`const Component = ({ ... }) => (` when the destructured parameter spans
|
|
multiple lines. Use the project form with the opening `(` after `=`, the
|
|
destructured object as the argument, and the closing parameter `)` on its own
|
|
line before `=>`.
|
|
- In TypeScript and TSX, never place a closing parenthesis at the beginning of
|
|
a line except for a multi-line function declaration parameter list.
|
|
- Never place a closing square bracket at the beginning of a line.
|
|
- For object literals, type literals, import/export named bindings, destructuring
|
|
patterns, and other associative-array-style braces, do not place the closing
|
|
brace at the beginning of a line. Keep `}` on the same line as the final
|
|
property, binding, or specifier unless that would violate the line limit.
|
|
Function, lambda, callback, and block closing braces are exempt and should
|
|
stay on their own line when that fits the local style. When a function,
|
|
lambda, callback, or block body spans multiple lines, do not put its closing
|
|
`}` at the end of the previous line.
|
|
- For arrays and tuple-like lists, do not place the closing `]` at the
|
|
beginning of a line. Keep `]` on the same line as the final element unless
|
|
that would violate the line limit.
|
|
- For function and method calls, do not place the closing `)` at the beginning
|
|
of a line. The only TypeScript/TSX exception is the closing parameter `)` of a
|
|
multi-line function declaration.
|
|
- When writing braces on a single line in TypeScript or TSX JavaScript
|
|
context, put exactly one space inside the braces, as in `{ value }` or
|
|
`{ key: value }`.
|
|
- Do not add inner spaces to React/JSX expression braces, as in
|
|
`prop={value}`, `{children}`, or `<Component>{{...props}}</Component>`.
|
|
- Keep a tag's closing marker on the same line as the final prop when the tag
|
|
spans multiple lines.
|
|
- Do not put `/>` or `>` on its own line unless the existing surrounding code
|
|
does so.
|
|
- Keep JSX closing parentheses in the existing compact style, for example
|
|
`</div>)` rather than moving `)` onto a separate line.
|
|
- Do not add braces around `if`, `else`, or `for` bodies when the body is a
|
|
single physical line.
|
|
- Always add braces around `if`, `else`, or `for` bodies when the body spans
|
|
two or more physical lines, even if it is one statement.
|
|
- Do not use a leading semicolon for expression statements such as
|
|
`;([...]).forEach(...)`; rewrite the expression to avoid ASI hazards
|
|
explicitly, for example with `void`.
|
|
- Use correct British English spelling for new identifiers, filenames,
|
|
component names, helper names, comments, and developer-facing prose unless
|
|
editing an already established American-English API that must keep its
|
|
existing spelling for compatibility.
|
|
- Prefer British English spellings such as `behaviour`, `colour`, `realise`,
|
|
`theatre`, `centre`, `favourite`, `optimise`, and `catalogue`.
|
|
- Avoid American or Canadian spellings such as `behavior`, `color`, `realize`,
|
|
`theater`, `center`, `favorite`, `optimize`, and `catalog`.
|
|
- Even when an external library or API uses the wrong spelling, prefer to
|
|
correct it at the local boundary and use proper British English names in this
|
|
codebase. For example, prefer `import { color: colour } from '@external-lib'`
|
|
over spreading `color` through local code.
|
|
- Apply the same boundary correction to object destructuring, wrapper helpers,
|
|
adapter layers, and local variable names when doing so does not break the
|
|
external contract.
|
|
- For this repository, prefer names such as `BehaviourSettingsSection.tsx`, not
|
|
`BehaviorSettingsSection.tsx`.
|
|
|
|
### Frontend delimiter decision table
|
|
|
|
Use this table before accepting any edited TypeScript or TSX hunk. The table is
|
|
more authoritative than formatter habit.
|
|
|
|
#### Import and export named bindings
|
|
|
|
Bad:
|
|
|
|
```ts
|
|
import {
|
|
Button,
|
|
Card,
|
|
} from '@/components/ui'
|
|
```
|
|
|
|
Good:
|
|
|
|
```ts
|
|
import { Button,
|
|
Card } from '@/components/ui'
|
|
```
|
|
|
|
Also acceptable when short:
|
|
|
|
```ts
|
|
import { Button, Card } from '@/components/ui'
|
|
```
|
|
|
|
Rule: named-binding `}` is associative-array-style syntax. It must not be alone
|
|
at the beginning of a line. Prefer keeping `{` with the first binding and `}`
|
|
with the final binding when this fits the line limit.
|
|
|
|
#### Type literals
|
|
|
|
Bad:
|
|
|
|
```ts
|
|
type Props = {
|
|
open: boolean
|
|
onOpenChange: (open: boolean) => void
|
|
}
|
|
```
|
|
|
|
Good:
|
|
|
|
```ts
|
|
type Props = {
|
|
open: boolean
|
|
onOpenChange: (open: boolean) => void }
|
|
```
|
|
|
|
Rule: type-literal `}` is not a block close. It must stay on the same line as
|
|
the final property unless that would break the hard line limit.
|
|
|
|
#### Object literals
|
|
|
|
Bad:
|
|
|
|
```ts
|
|
const value = {
|
|
open,
|
|
activeScope,
|
|
}
|
|
```
|
|
|
|
Good:
|
|
|
|
```ts
|
|
const value = {
|
|
open,
|
|
activeScope }
|
|
```
|
|
|
|
Bad:
|
|
|
|
```ts
|
|
const value = useMemo (() => ({
|
|
open,
|
|
activeScope,
|
|
}), [open, activeScope])
|
|
```
|
|
|
|
Good:
|
|
|
|
```ts
|
|
const value = useMemo (() => ({
|
|
open,
|
|
activeScope }), [open, activeScope])
|
|
```
|
|
|
|
Rule: object-literal `}` is associative-array-style syntax. It must not be on a
|
|
line by itself. Keep it with the final property, and keep call `)` off the
|
|
beginning of a line.
|
|
|
|
#### Destructuring parameters
|
|
|
|
Bad:
|
|
|
|
```tsx
|
|
const Component: FC<Props> = ({
|
|
open,
|
|
onOpenChange,
|
|
}) => {
|
|
return null
|
|
}
|
|
```
|
|
|
|
Good:
|
|
|
|
```tsx
|
|
const Component: FC<Props> = (
|
|
{ open,
|
|
onOpenChange },
|
|
) => {
|
|
return null
|
|
}
|
|
```
|
|
|
|
Rule: when a React component or helper takes a destructured object parameter
|
|
that spans multiple lines, do not use the Prettier-style `= ({ ... }) =>`
|
|
shape. Put the function parameter list on its own lines. The destructuring `}`
|
|
stays with the final binding. The parameter-list `)` is then allowed and
|
|
required at the beginning of its own line.
|
|
|
|
#### Inline typed destructuring parameter
|
|
|
|
Good:
|
|
|
|
```ts
|
|
const RouteTransitionWrapper = ({ user, setUser }: {
|
|
user: User | null
|
|
setUser: Dispatch<SetStateAction<User | null>> }) => {
|
|
return null
|
|
}
|
|
```
|
|
|
|
Bad:
|
|
|
|
```ts
|
|
const RouteTransitionWrapper = ({ user, setUser }: {
|
|
user: User | null
|
|
setUser: Dispatch<SetStateAction<User | null>>
|
|
}) => {
|
|
return null
|
|
}
|
|
```
|
|
|
|
Rule: this is not a separately split parameter-list block. The line break is
|
|
inside the inline type. Keep the type-literal `}` and parameter-list `)` on the
|
|
same line as the final type property.
|
|
|
|
#### Multi-line normal parameter list
|
|
|
|
Bad:
|
|
|
|
```ts
|
|
const updateDraft = <Key extends keyof Settings,> (
|
|
key: Key,
|
|
value: Settings[Key]) => {
|
|
return null
|
|
}
|
|
```
|
|
|
|
Good:
|
|
|
|
```ts
|
|
const updateDraft = <Key extends keyof Settings,> (
|
|
key: Key,
|
|
value: Settings[Key],
|
|
) => {
|
|
return null
|
|
}
|
|
```
|
|
|
|
Rule: when the parameter list itself is split across multiple parameter lines,
|
|
the closing parameter `)` goes at the beginning of its own line before `=>` or
|
|
the return type.
|
|
|
|
#### Function and callback blocks
|
|
|
|
Bad:
|
|
|
|
```ts
|
|
const handleSave = () => { save ()
|
|
}
|
|
```
|
|
|
|
Bad:
|
|
|
|
```ts
|
|
const handleSave = () => {
|
|
save () }
|
|
```
|
|
|
|
Good:
|
|
|
|
```ts
|
|
const handleSave = () => {
|
|
save ()
|
|
}
|
|
```
|
|
|
|
Rule: block `}` closes executable code, not associative data. Multi-line
|
|
function, lambda, callback, `if`, `for`, `switch`, and similar block braces
|
|
belong on their own line.
|
|
|
|
#### Function and method calls
|
|
|
|
Bad:
|
|
|
|
```ts
|
|
const value = compute (
|
|
first,
|
|
second
|
|
)
|
|
```
|
|
|
|
Good:
|
|
|
|
```ts
|
|
const value = compute (
|
|
first,
|
|
second)
|
|
```
|
|
|
|
Rule: call-expression `)` must not be at the beginning of a line. The exception
|
|
for leading `)` applies only to function declaration parameter lists, never to
|
|
calls.
|
|
|
|
#### JSX closing markers
|
|
|
|
Bad:
|
|
|
|
```tsx
|
|
<Button
|
|
type="button"
|
|
onClick={handleSave}
|
|
>
|
|
保存
|
|
</Button>
|
|
)
|
|
```
|
|
|
|
Good:
|
|
|
|
```tsx
|
|
<Button
|
|
type="button"
|
|
onClick={handleSave}>
|
|
保存
|
|
</Button>)
|
|
```
|
|
|
|
Bad:
|
|
|
|
```tsx
|
|
<Input
|
|
value={value}
|
|
onChange={handleChange}
|
|
/>
|
|
```
|
|
|
|
Good:
|
|
|
|
```tsx
|
|
<Input
|
|
value={value}
|
|
onChange={handleChange}/>
|
|
```
|
|
|
|
Rule: keep `>` or `/>` with the final prop, and keep JSX closing parentheses in
|
|
the local compact form such as `</div>)`.
|
|
|
|
#### Arrays and tuples
|
|
|
|
Bad:
|
|
|
|
```ts
|
|
const items = [
|
|
first,
|
|
second,
|
|
]
|
|
```
|
|
|
|
Good:
|
|
|
|
```ts
|
|
const items = [
|
|
first,
|
|
second]
|
|
```
|
|
|
|
Good when short:
|
|
|
|
```ts
|
|
const items = [first, second]
|
|
```
|
|
|
|
Rule: array and tuple `]` must not be at the beginning of a line. Keep it with
|
|
the final element unless that would break the hard line limit.
|
|
|
|
#### Single-line braces
|
|
|
|
Good:
|
|
|
|
```ts
|
|
const next = { ...current, enabled: true }
|
|
const tag = { id, name }
|
|
```
|
|
|
|
Bad:
|
|
|
|
```tsx
|
|
<Component prop={ value }/>
|
|
```
|
|
|
|
Good:
|
|
|
|
```tsx
|
|
<Component prop={value}/>
|
|
```
|
|
|
|
Rule: JavaScript object braces on one line get one inner space. JSX expression
|
|
braces do not get inner spaces.
|
|
|
|
#### Final TypeScript/TSX self-review checklist
|
|
|
|
Before reporting completion after a TypeScript or TSX edit, check the edited
|
|
hunks line by line. Unless a step explicitly mentions JSX, it applies equally
|
|
to `.ts` and `.tsx`:
|
|
|
|
1. No import/export/type/object/destructuring `}` appears alone at the beginning
|
|
of a line.
|
|
2. No call-expression `)` appears at the beginning of a line.
|
|
3. Any leading `)` is definitely closing a function declaration parameter list,
|
|
not a call.
|
|
4. Any parameter-list `)` at the end of a line is valid because the parameter
|
|
list itself was not split, only an inline type or destructuring shape was.
|
|
5. No array or tuple `]` appears at the beginning of a line.
|
|
6. Multi-line executable block `}` is on its own line.
|
|
7. JSX `>` and `/>` stay with the final prop unless nearby code proves
|
|
otherwise.
|
|
8. JSX closing parentheses keep the compact local style.
|
|
9. Leading indentation is 4-space logical indentation with tabs used only as
|
|
leading 8-space compression.
|
|
10. No line has trailing whitespace.
|
|
|
|
Preferred:
|
|
|
|
```tsx
|
|
const PostFormTagsArea: FC<Props> = ({ tags, setTags, errors, ...rest }) => {
|
|
return (
|
|
<TextArea
|
|
{...rest}
|
|
ref={ref}
|
|
value={tags}
|
|
invalid={errors && errors.length > 0}
|
|
onChange={ev => setTags (ev.target.value)}/>)
|
|
}
|
|
```
|
|
|
|
Avoid:
|
|
|
|
```tsx
|
|
function PostFormTagsArea ({ tags, setTags }: Props) {
|
|
return (
|
|
<TextArea
|
|
value={tags}
|
|
onChange={ev => setTags (ev.target.value)}
|
|
/>
|
|
)
|
|
}
|
|
```
|
|
|
|
## Codex workflow
|
|
|
|
- First inspect existing patterns; do not invent new architecture when a local convention exists.
|
|
- Keep changes scoped to the requested issue.
|
|
- Do not scan or summarize dependency/generated/runtime directories such as
|
|
`node_modules`, `dist`, `tmp`, `log`, and `storage` unless explicitly needed.
|
|
- Before touching wiki, tag, versioning, BAN, IP BAN, or authentication
|
|
behaviour, inspect the related request specs and service objects.
|
|
- If frontend code changes, run only non-test verification commands that
|
|
apply, such as `npm run build` and `npm run lint`. Run `npm run test:run`
|
|
only when the user explicitly asks for tests.
|
|
- If backend code changes, do not run RSpec unless the user explicitly asks
|
|
for tests.
|
|
- If a verification command cannot be run or fails, report the exact command and failure.
|
|
|
|
## Completion criteria
|
|
|
|
A task is complete only when:
|
|
|
|
- implementation is complete,
|
|
- relevant non-test verification commands pass, or failures are clearly
|
|
explained,
|
|
- unrelated files are not changed,
|
|
- migrations and schema are consistent when schema changes are made,
|
|
- user-facing behaviour is documented when needed.
|