ファイル
btrc-hub/AGENTS.md
T
みてるぞ f5b632ed89 設定画面 (#34) (#397)
Reviewed-on: #397
Co-authored-by: miteruzo <miteruzo@naver.com>
Co-committed-by: miteruzo <miteruzo@naver.com>
2026-07-07 00:48:41 +09:00

32 KiB

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:

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:

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:

cd backend
bundle exec rspec

Frontend

The following npm scripts exist in frontend/package.json:

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:
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:
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.
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.
  • Do not insert void mechanically before ordinary event-handler or callback calls merely because the callee returns a Promise. If the surrounding code already uses a plain expression statement such as onClick={() => requestActiveTab ('theme')}, preserve that style unless a local rule or type requirement truly forces void. Adding unnecessary void is a medium-severity style violation.
  • When fixing formatting, never change operator binding, evaluation order, tuple/comma behaviour, or any other expression structure. A formatting pass that changes how !==, ??, ?:, &&, ||, or , binds is a capital offence.
  • In TypeScript and TSX, do not mechanically verticalise short call tails, short object literals, or short callback bodies that already fit the local line-length and delimiter rules. Expanding compact local code without a readability need is a minor style violation.
  • In TypeScript and TSX, treat short object literals, short returned objects, short typed object shapes, and short function-call object arguments as compact associative syntax by default. If they fit locally, keep the opening { on the same line as the first property and keep the closing } on the same line as the final property. Do not explode them into vertical Prettier-style blocks without a concrete readability or line-length reason.
  • In TypeScript and TSX, when a compact associative form is broken across two lines, keep the opening { with the first property and the closing } with the final property. A shape like {\n key: value,\n} is wrong even when line length would permit it.
  • In TypeScript and TSX, when a short call such as apiGet<...> (...), apiPatch<...> (...), setState (...), updateClientSettings (...), or window.dispatchEvent (...) already fits within the local style, do not add extra vertical layers around the object argument or callback body.
  • In TypeScript and TSX, after editing a file, inspect the file tail and remove meaningless blank lines before export default or the end of file. A stray empty line before export default is a minor style offence.
  • 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.

Additional style offences and penalties

Use this section for recurrent failure modes that are easy to miss when applying the delimiter rules mechanically.

Unnecessary void before ordinary callbacks

Bad:

onClick={() => void requestActiveTab ('theme')}

Good:

onClick={() => requestActiveTab ('theme')}

Penalty: medium-severity offence. The code still works, but it pollutes the local style and usually signals that the edit was made mechanically rather than by reading the surrounding code.

Formatting that changes expression structure

Bad:

const hasUnsavedChanges =
    serialiseThemeDraft (draftThemeSlots)
    !== (serialiseThemeDraft (savedThemeSlots),
	 draftActiveThemeMode !== savedThemeMode)

Good:

const hasUnsavedChanges =
    serialiseThemeDraft (draftThemeSlots)
    !== serialiseThemeDraft (savedThemeSlots)
    || draftThemeMode !== savedThemeMode

Penalty: capital offence. Formatting must never corrupt the meaning of an expression.

Mechanical vertical expansion of compact local code

Bad:

const nextState = {
    open,
    activeTab }

setDirtyStates (
    current => ({
	current,
	key:  value }),
)

Good:

const nextState = { open, activeTab }

setDirtyStates (
    current => ({
	current,
	key:  value }))

Penalty: minor offence when semantics stay intact. It is not necessarily broken, but it ignores the repository's compact associative style.

Prettier-style exploded object literals that should stay compact

Bad:

const next = {
    enabled: keyboard?.enabled !== false,
    bindings: normaliseKeyboardBindings (keyboard?.bindings),
}

Good:

const next = {
    enabled: keyboard?.enabled !== false,
    bindings: normaliseKeyboardBindings (keyboard?.bindings) }

Also good when short enough:

const next = { enabled: keyboard?.enabled !== false,
	       bindings: normaliseKeyboardBindings (keyboard?.bindings) }

Rule: for compact associative syntax, keep { with the first property and } with the final property unless line length truly forces a different shape. Do not mechanically apply the common Prettier block form. Penalty: medium-severity offence. The code still runs, but it violates a core repository formatting habit that must be preserved consistently.

Exploded object arguments inside short calls

Bad:

updateClientSettings (settings => ({
    ...settings,
    keyboard: next,
}))

Good:

updateClientSettings (settings => ({
    ...settings,
    keyboard: next }))

Rule: a call-expression closing ) must not drift onto its own line, and a short object argument should not be exploded more than necessary. Keep the callback's returned object compact when it fits. Penalty: medium-severity offence. This usually means the edit was formatted mechanically instead of by reading the local style.

Stray blank line before export default

Bad:

const Component: FC = () => {
  return <div/>
}


export default Component

Good:

const Component: FC = () => {
  return <div/>
}

export default Component

Rule: do not leave an extra empty line between the last top-level declaration and export default unless some surrounding file structure genuinely requires visual separation. Penalty: minor offence. It is small, but it is easy to avoid and should not recur.

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:

import {
    Button,
    Card,
} from '@/components/ui'

Good:

import { Button,
	 Card } from '@/components/ui'

Also acceptable when short:

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. Penalty: capital offence. This is one of the core associative-brace rules.

Type literals

Bad:

type Props = {
    open: boolean
    onOpenChange: (open: boolean) => void
}

Good:

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. Penalty: capital offence. Mistaking a type-literal } for a block } is one of the recurring death-class errors.

Object literals

Bad:

const value = {
    open,
    activeScope,
}

Good:

const value = {
    open,
    activeScope }

Bad:

const value = useMemo (() => ({
    open,
    activeScope,
}), [open, activeScope])

Good:

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. Penalty: capital offence. Wrong object-literal } placement and wrong call ) placement are both death-class violations here.

Destructuring parameters

Bad:

const Component: FC<Props> = ({
    open,
    onOpenChange,
}) => {
  return null
}

Good:

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. Penalty: capital offence. This pattern is a primary source of repeated TSX style regressions.

Inline typed destructuring parameter

Good:

const RouteTransitionWrapper = ({ user, setUser }: {
    user:     User | null
    setUser:  Dispatch<SetStateAction<User | null>> }) => {
  return null
}

Bad:

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. Penalty: capital offence. Misclassifying this case means the delimiter review has failed at the syntax-role level.

Multi-line normal parameter list

Bad:

const updateDraft = <Key extends keyof Settings,> (
    key: Key,
    value: Settings[Key]) => {
  return null
}

Good:

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. Penalty: capital offence. This is the main allowed exception for a leading ), so getting it wrong destroys the whole rule set.

Function and callback blocks

Bad:

const handleSave = () => { save ()
}

Bad:

const handleSave = () => {
  save () }

Good:

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. Penalty: capital offence. Confusing block } with associative } is a death-class delimiter error.

Function and method calls

Bad:

const value = compute (
    first,
    second
)

Good:

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. Penalty: capital offence. A leading call ) is one of the clearest death-class violations in this codebase.

JSX closing markers

Bad:

<Button
    type="button"
    onClick={handleSave}
>
  保存
</Button>
)

Good:

<Button
    type="button"
    onClick={handleSave}>
  保存
</Button>)

Bad:

<Input
    value={value}
    onChange={handleChange}
/>

Good:

<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>). Penalty: medium-severity offence. It is usually not semantically broken, but it is a conspicuous TSX-style failure.

Arrays and tuples

Bad:

const items = [
    first,
    second,
]

Good:

const items = [
    first,
    second]

Good when short:

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. Penalty: capital offence. A leading ] is forbidden by the same class of hard delimiter rule as leading associative } and leading call ).

Single-line braces

Good:

const next = { ...current, enabled: true }
const tag = { id, name }

Bad:

<Component prop={ value }/>

Good:

<Component prop={value}/>

Rule: JavaScript object braces on one line get one inner space. JSX expression braces do not get inner spaces. Penalty: minor offence. This is not normally semantic breakage, but it still counts as a style miss.

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:

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:

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.