This repository follows an AI-first workflow. Keep this file short and use it as
an index. Detailed rules live in docs/.
AI_FIRST.md: high-level contract and agent behavior.docs/architecture.md: real module boundaries for this monorepo.docs/conventions.md: coding and naming conventions.docs/golden-principles.md: non-negotiable engineering principles.docs/quality-grades.md: current quality baseline and debt map.docs/glossary.md: project language and key domain terms.docs/runbooks/: triage and operational checklists.docs/exec-plans/: active/completed execution plans.adr/: architecture decision records.
bot/: Telegram bot code (core/,infrastructure/,routers/,tests/).webapp/: FastAPI-based signing app.shared/: shared schemas/constants..linters/: local structural checks used by CI.
just fmt: format code.just lint: static checks.just test: full test suite.just test-fast: fast local subset.just test-e2e-smoke: deterministic user-flow smoke tests.just test-external: docker/external integration tests.just arch-test: architecture guardrails.just secret-scan: repository secret leak scan (gitleaks).just check: full local gate (fmt + lint + test + arch-test).just check-fast: CI-safe gate (lint + test-fast + arch-test).just metrics: local repository metrics snapshot.just start-task <id> title="...": create an execution plan stub.just finish-task <plan-file>: move plan from active to completed.just typecheck-full: full mypy sweep (legacy debt visibility).
- Do not guess data contracts or architecture; read docs first.
- Keep diffs minimal and verifiable.
- For DB writes in bot code, always call
await session.commit()in the sameasync withsession block. - Read
bot/tests/README.mdbefore adding/changing tests. - Router tests must use
mock_telegram. - Do not weaken tests, linters, or CI checks to make a change pass.
- Do not add or modify
justfilecommands without explicit user approval. - Do not introduce
python ...oruv run python ...command patterns in recipes/docs/workflows without explicit user approval. - Router screens with inline keyboards must use
infrastructure.utils.telegram_utils.send_message()unless there is a documented reason not to. Directmessage.answer()/callback.message.answer()does not updatelast_message_idand can make callback middleware reject fresh buttons as old. - Command handlers that start a fresh flow should call
clear_state(state)and thenclear_last_message_id(user_id, app_context=app_context)before rendering the first screen.
- First state which files/directories need changes.
- Do not edit until explicit permission names allowed paths.
- Markdown documentation files (
*.md) may be edited or moved without naming each path explicitly when the edit/move is required by the current task or by execution-plan lifecycle bookkeeping. - Before first repo edit in any non-trivial task, create an execution plan:
just start-task <task-id> title="...". - Before first repo edit, ensure the active plan has:
Files/Directories To Changeand checkedEdit Permissionsection. - If no active plan exists, stop work and ask for allowed paths.
- Intermediate commits may keep a plan in
docs/exec-plans/active/, but once every item in## Change Planis checked[x], move that plan todocs/exec-plans/completed/withjust finish-task <plan-file>before the next commit.
- Enable local hook path once per clone:
git config core.hooksPath .githooks - This repo ships
.githooks/pre-committhat blocks commits touchingbot/,webapp/, orshared/when no execution plan file is staged. - The hook also blocks commits that stage a fully completed plan in
docs/exec-plans/active/; completed plans must move tocompleted/.
- After every successful
git push, runjust push-gitdocker.