docs: document workspace and safe onboarding

This commit is contained in:
2026-09-13 20:14:15 +03:00
parent ee2adc9fda
commit 9f5baed3a3
4 changed files with 176 additions and 44 deletions
+6 -43
View File
@@ -1,43 +1,6 @@
# OS
.DS_Store
# IDE / local environment
.idea
.vscode/
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
# Runtime data
pids
*.pid
*.pid.lock
*.seed
# Node / frontend / backend artifacts
node_modules
dist
dist-ssr
build
coverage
/.nyc_output
# Local and generated env/runtime files
.env
.env.*
!.env.example
# Generated and temporary
.tmp
.temp
# Tooling metadata
.opencode
.playwright-mcp
graphify-out
# Root owns only these files; nested repositories and local data stay local.
/*
!/.gitignore
!/AGENTS.md
!/README.md
!/test-workspace-tracking.py
+4 -1
View File
@@ -3,7 +3,10 @@
## Workspace
`frontend`, `backend`, `docs` и `specs` — независимые Git-репозитории.
Root не является Git-репозиторием; команды Git выполняй из нужного repo.
Root — отдельный Git-репозиторий `WealthLedger/main`; команды Git выполняй
из нужного repo. Root tracking ограничен allowlist в `.gitignore`;
вложенные repos и локальные данные в main не добавляй, включая `git add -f`.
Структура checkout и запуск — в [README](README.md).
`references/**`, dated audits и архивы — read-only источники.
## Работа
+119
View File
@@ -0,0 +1,119 @@
# WealthLedger
Локальное приложение для портфеля T-Bank, операций, дохода и будущих выплат,
а также ручного учёта банковских карт и расходов.
[Обзор продукта](docs/overview.md) и [документация системы](docs/README.md).
## Структура workspace
Workspace состоит из пяти независимых Git-репозиториев. Root — репозиторий
`WealthLedger/main`; вложенные checkout не являются submodules.
| Путь от root | Репозиторий Gitea | Назначение |
| --- | --- | --- |
| `.` | `WealthLedger/main` | Вход в workspace, инструкции и правила root tracking |
| `frontend/` | `WealthLedger/frontend` | [React/Vite UI](frontend/README.md) |
| `backend/` | `WealthLedger/backend` | [NestJS API, Prisma и SQLite](backend/README.md) |
| `docs/` | `WealthLedger/docs` | [Объяснение системы и сопровождение](docs/README.md) |
| `specs/` | `WealthLedger/specs` | [Требования и OpenSpec](specs/README.md) |
### Получение checkout
Нужны Git и SSH-доступ к Gitea на порту 2222. Из родительского каталога,
где ещё нет `WealthLedger`, выполните:
```bash
git clone ssh://git@git.personal.ksv741.ru:2222/WealthLedger/main.git WealthLedger
cd WealthLedger
git clone ssh://git@git.personal.ksv741.ru:2222/WealthLedger/frontend.git frontend
git clone ssh://git@git.personal.ksv741.ru:2222/WealthLedger/backend.git backend
git clone ssh://git@git.personal.ksv741.ru:2222/WealthLedger/docs.git docs
git clone ssh://git@git.personal.ksv741.ru:2222/WealthLedger/specs.git specs
```
Для существующего workspace клонируйте только отсутствующие checkout в пустые
каталоги. Проверяйте состояние каждого repo отдельно, например
`git -C frontend status`. Обновление main не обновляет соседние repos;
общего lockfile revisions нет. Относительные ссылки требуют указанных имён каталогов.
### Что хранится в main
Root отслеживает только `.gitignore`, `AGENTS.md`, `README.md` и
`test-workspace-tracking.py`. Остальные root-пути игнорируются по умолчанию:
вложенные repos, `.env`, базы и WAL, импорты выписок, PDF, `references/`,
`design/`, `todo/` и локальные настройки инструментов.
Новый общий файл включается отдельной правкой allowlist после проверки содержимого.
Перед commit смотрите `git diff --cached --name-status` в нужном repo.
Не используйте `git add -f` для обхода границ root. Ignore не защищает уже
отслеживаемые файлы и не меняет правила внутри вложенных repos.
Не запускайте очистку workspace через `git clean -fdx`: ignored-пути содержат
локальные данные. Правила tracking не удаляют файлы и вложенные `.git`.
## Подготовка и запуск
Нужны nvm и Node из `.nvmrc` каждого npm-repo (сейчас 24.21.0, npm 11.19).
Root не содержит npm-проекта. В frontend, backend и docs отдельно выполните
`nvm install`, `nvm use --silent`, `npm ci`.
Предпосылки native dependencies и разрешения install scripts описаны в
[локальном окружении](docs/development/local-workspace.md).
Для нового backend создайте `.env` по [backend README](backend/README.md),
замените оба placeholder-секрета и проверьте `DATABASE_URL`.
Существующий `.env` сохраняйте. Из backend:
```bash
nvm use --silent
npm run build
npx prisma migrate deploy
npm run start:dev
```
Build генерирует Prisma client. Перед миграцией существующей базы сохраните
согласованный backup и ключ шифрования; процедуру и ограничения отката смотрите
в [локальном окружении](docs/development/local-workspace.md#сохранение-данных-и-откат).
Известная ошибка fresh migration при `RUST_LOG=warn/error` устранена в
`backend/prisma.config.ts`: CLI удаляет унаследованную переменную.
Используйте штатный `prisma migrate deploy` из backend; прежний Prisma blocker
снят. [Подробности и границы проверки](docs/development/verification.md#известное-ограничение-сквозной-проверки).
В другом терминале подготовьте `.env` по [frontend README](frontend/README.md),
затем из frontend:
```bash
nvm use --silent
npm run dev
```
Стандартные адреса: frontend `http://localhost:5173`, API
`http://localhost:3000`. Origin backend и адрес API frontend должны совпадать
с выбранными адресами. T-Bank token вводится через настройки приложения;
без него доступны вход и ручной банковский учёт.
Для вымышленных UI-примеров выполните `npm run dev:catalog` из frontend.
### OpenSpec
OpenSpec не нужен для запуска приложения и применяется по явному запросу.
Specs использует Node из `frontend/.nvmrc`; проверенная версия CLI — 1.10.0.
Store `wealth-ledger-specs` расположен в `specs/openspec/`.
[Роль и необязательный lifecycle](docs/development/openspec-authority-and-lifecycle.md),
[команды validation](specs/README.md#проверка).
## Проверки
Перед npm-командами активируйте `.nvmrc` соответствующего repo.
| Где | Команда | Что проверяет |
| --- | --- | --- |
| root | `python3 test-workspace-tracking.py` | Массовый add на вымышленных данных; сохранность файлов и вложенных Git |
| root | `git diff --check` | Whitespace в изменениях root |
| frontend | `npm run verify` | Типы, lint, тесты, зависимости, OpenAPI snapshot и сборки |
| backend | `npm run verify` | Lint, типы, unit tests и build |
| backend | `npm run test:e2e` | HTTP/SQLite suites и контракт с соседним frontend |
| docs | `npm run verify` | Markdown, относительные ссылки и diff |
Python 3 нужен только для проверки root tracking. Backend e2e использует
временные базы; verify отдельно не доказывает HTTP/DB-сценарии или доступность
T-Bank. Полные команды и ограничения принадлежат repo README и
[руководству по проверке](docs/development/verification.md).
Для изменения проекта начните с [AGENTS](AGENTS.md).
+47
View File
@@ -0,0 +1,47 @@
"""Check root tracking on fictional data; never stage the real workspace."""
from pathlib import Path
import subprocess
import tempfile
def check(ignore_rules):
with tempfile.TemporaryDirectory(prefix="wealthledger-tracking-") as directory:
root = Path(directory)
def git(*args):
return subprocess.check_output(
["git", "-C", str(root), *args], text=True
)
git("init", "--quiet")
allowed = {".gitignore", "AGENTS.md", "README.md", "test-workspace-tracking.py"}
for name in allowed:
(root / name).write_text("fictional fixture\n")
(root / ".gitignore").write_text(ignore_rules)
for name in ("frontend", "backend", "docs", "specs"):
nested = root / name
nested.mkdir()
subprocess.run(["git", "init", "--quiet", str(nested)], check=True)
for name in (
"frontend/source.ts", "backend/prisma/dev.db", "docs/README.md",
"specs/README.md", "statement-imports/report.csv", "private.db",
"private.db-wal", ".env", ".env.example", "audit.pdf",
"design/preview.html", "todo/notes.md", "references/source.md",
".agents/local.md", "unknown-directory/data.txt", "unknown-file.txt",
):
target = root / name
target.parent.mkdir(parents=True, exist_ok=True)
target.write_text("fictional private data\n")
before = {p.relative_to(root): p.read_bytes() for p in root.rglob("*")
if p.is_file() and ".git" not in p.relative_to(root).parts[:1]}
git("add", ".")
assert set(git("ls-files").splitlines()) == allowed
assert all((root / p).read_bytes() == content for p, content in before.items())
assert all((root / name / ".git").is_dir()
for name in ("frontend", "backend", "docs", "specs"))
if __name__ == "__main__":
check(Path(__file__).with_name(".gitignore").read_text())
print("PASS: only root allowlist staged; fictional data and nested Git preserved")