15 KiB
date, source, status, type, title, ingested_at, ingested_by, source_project
| date | source | status | type | title | ingested_at | ingested_by | source_project |
|---|---|---|---|---|---|---|---|
| 2026-05-06 | .meeting-room/.archive/2026-05-06-factory-bootstrap.md | promoted | concept | factory-bootstrap | 2026-05-06T18:22:46.484Z | OpeItcLoc03@DESKTOP-NSEF0UK | .meeting-room |
Software factory bootstrap — design
Контекст и диагноз
В ~/projects/ есть точечные папки-модули будущей "ERP":
| Модуль | Артефакт | Состояние (на 2026-05-06) |
|---|---|---|
| HR / org chart | .organization/ (roster.md + personas) |
частично |
| Inventory / templates | .templates/ |
частично (project/ есть, agent//report/ пусты) |
| Knowledge (local) | .wiki/ (Karpathy) |
живой |
| Knowledge (shared) | projects-wiki через mcp__projects-meta__* |
живой, 13–14 страниц |
| Tasks / PMO | .tasks/ (local) + mcp__projects-meta__tasks_* (shared) |
живой, 14 проектов в кэше |
| Shared services | .common/ (lib/scripts/secrets/prompts/config) |
живой |
| Tooling registry | claude-skills/ (~21 скил) |
живой |
| Bus services | .common/lib/projects-meta-mcp/, .common/lib/interns-mcp/ |
живые |
| Communications | .meeting-room/ |
живой |
Что не работало для онбординга нового сотрудника:
- Нет orchestrator'а —
setup-*дёргаются по одному вручную. - Нет L0 entry point — пока Claude не запущен, ни один setup-* не доступен.
- Нет manifest'а компонентов — версий, зависимостей, health-check'ов нет нигде.
- Hardcoded
~/projects/в путях — переезд = ручная починка. - Multi-vendor (Cursor / Copilot CLI / Gemini CLI):
setup-*пишут только в~/.claude.json. - Фабрика сама не убрана.
Решение
Создать новую дот-папку ~/projects/.factory/ — отдельный репо, сиблинг .common/. Manifest-driven cross-platform installer/updater всей мета-инфраструктуры.
Размещение выбрано потому, что factory должна работать до того, как .common склонирован. L0 кладёт .factory/ первым, дальше уже он ставит всё остальное. Альтернативы (.common/lib/factory/, claude-skills/skills/factory/) отвергнуты — обе создают cycle dependency.
Архитектура — три слоя
L0 — Pre-Claude bootstrap (нативный shell, без runtime-зависимостей). Два под-слоя:
L0a — System bootstrap (toolchain). Голая машина → готовая к работе.
- Системный пакет-менеджер:
winget(Win11),brew(Mac),apt/dnf/pacman(Linux). git+curlчерез системный pkg-mgr.mise(бывш. rtx) — single-binary unified runtime manager. Через негоnode@lts,python@latest,go@latest,rustпо требованию. Закрывает nvm/pyenv/goenv одной зависимостью.- Опционально (yes/no/skip): Claude Code, Cursor, VS Code, Ollama, Docker Desktop.
L0b — Factory bootstrap. После L0a.
bootstrap.ps1+bootstrap.sh— запуск черезiwr … | iex/curl … | bash.- Делает только: detect platform → спросить
$PROJECTS_DIR→ clone.factory/(gitea) → передать управление в L1. - Единое состояние машины:
~/.config/factory/home.toml:projects_dir = "C:/Users/vitya/projects" client = "claude-code" # | "copilot-cli" | "gemini-cli" installed_at = "2026-05-06T..." - Если несколько
projects_dir—home.tomlхранит активный, флаг--projects-dir <path>переключает.
L1 — factory.yaml + factory CLI (один скомпилированный Go-бинарь — см. Q1).
- Manifest-схема (черновик):
components: - name: dot-common source: { type: git, url: "{gitea}/.common" } target: "{projects_dir}/.common" health_check: "test -f {target}/scripts/claude-switch.ps1" - name: projects-meta-mcp source: { type: git, url: "{gitea}/projects-meta-mcp" } target: "{projects_dir}/.common/lib/projects-meta-mcp" deps: [dot-common] setup_skill: setup-projects-meta health_check: "mcp_tool_available mcp__projects-meta__meta_status" - name: dot-wiki target: "{projects_dir}/.wiki" deps: [projects-meta-mcp] setup_skill: setup-wiki health_check: "test -f {target}/CLAUDE.md && test -f {target}/index.md" - name: claude-skills source: { type: git, url: "{gitea}/claude-skills" } target: "{projects_dir}/claude-skills" post_install: "bash {target}/scripts/install.sh" health_check: "test -d ~/.claude/skills/project-bootstrap" - Команды:
factory install,factory update,factory status,factory diagnose <name>. - Идемпотентность по health-check'у — re-run = no-op.
L2 — setup-* skills остаются. Factory триггерит через печать инструкции пользователю до тех пор, пока не появится программный slash-command-bridge (см. Q3).
Что закрывает каждое требование
| Требование | Решение |
|---|---|
~/projects в произвольном месте |
{projects_dir} substitution в manifest, источник — home.toml |
| Произвольное имя папки | То же; manifest нигде не хардкодит "projects" |
| Несколько папок на одной машине | Профили в home.toml; флаг --profile |
| Cross-platform | L0 — два нативных скрипта; L1 — single-file бинарь под Win/Mac/Linux; L2 — уже работает |
| Частичные / устаревшие установки | health_check на каждый компонент; factory status показывает дельту; factory update чинит |
| Multi-vendor | client в home.toml; manifest-компоненты помечены clients: [claude-code, copilot-cli] |
Anti-recommendations
- Один монолитный bash/ps скрипт без manifest'а — за год превратится в legacy.
- Python-orchestrator с pip-зависимостями — сам требует bootstrap'а python (chicken-and-egg).
- Повторять логику установки в L0 и L2. health_check — single source of truth.
- Складывать
factoryвclaude-skills/— фабрика > tooling; claude-skills должен быть компонентом manifest'а.
Решённые вопросы
Q1 — runtime для L1: Go
Главные аргументы: размер бинаря (5–10 МБ vs 80–100 МБ Deno), старт ~5 мс, тривиальная кросс-компиляция (включая Win/macOS ARM), go-git/go-git снимает зависимость от системного git, cobra даёт shell-completion из коробки.
Стек: Go 1.23+, go-git/go-git, goccy/go-yaml, spf13/cobra, опционально charmbracelet/lipgloss. Поставка — pre-built бинари в .factory/dist/, скачиваются L0b.
Контраргументы (Deno/Rust/Bun) отброшены: Deno слишком жирный для curl-pipe, Rust learning curve не оправдывает экономию 5 МБ, Bun на Windows ARM ещё не дозрел.
Q6 — toolchain layer в L0: mise поверх системного pkg-mgr
L0a: системный pkg-mgr (winget/brew/apt) → ставит git + curl + mise → mise ставит node/python/go/rust.
Опциональный интерактивный слой: Claude Code, Cursor, VS Code, Ollama, Docker Desktop.
Не отдельные nvm + pyenv + goenv — у каждого свой bootstrap, mise унифицирует. Не свой пакет-менеджер — winget/brew/apt уже стоят на любой целевой ОС.
Q8 — fresh-enterprise bootstrap (greenfield-mode)
factory должен уметь поднимать пустое предприятие — не только клонировать существующие гитеа-репы (clone-mode), но и скаффолдить шесть мета-репо из встроенных templates. Use case: новый юзер хочет повторить эту ERP-архитектуру в своём gitea/github namespace.
Что уже покрыто greenfield'ом (повторно использовать): setup-wiki, setup-tasks, project-bootstrap.
Что не покрыто (нужны новые скаффолды):
- Корневые мета-репо —
.common/,.meeting-room/,.organization/,.templates/, claude-skills-fork. setup-projects-metaиsetup-internsждут готовый source-tree в gitea — нуженinit-mode.
Архитектурное предложение — добавить в factory.yaml per-component clone-or-init-источник:
components:
- name: dot-common
source:
type: clone-or-init
url: "{gitea}/common" # сперва пробуем clone
template: "{factory}/templates/enterprise/common" # fallback — scaffold + init+push
И команда factory init <enterprise-name> --git-host <url>.
Anti-recommendation: не пытаться bootstrap'ить сам git-host (gitea/forgejo/github). Factory ожидает, что писательский git-сервер уже существует.
Цена: +1 папка templates/enterprise/<repo>/ (6 скелетов) + per-component поле source.template:. ~неделя на скелеты + ~3 дня на clone-or-init логику.
Не блокирует v0; реализуется параллельно после v0 production-deploy.
Открытые вопросы (deferred за v0)
- Q2 — где живёт каноничный manifest в production: в
.factory/factory.yaml(один на машину) или в shared Gitea с per-machine override? Склонение: "default в.factory/репе, override через~/.config/factory/home.toml#overrides". - Q3 — slash-command-bridge для L2: ждать программное API от вендоров, или поднять свой через MCP-сервер
factory-mcp(factory_install,factory_status)? - Q4 — версионирование manifest'а: semver на
factory.yamlсам? Или per-component pinnedname@v1.2.3(npm/cargo style)? - Q5 — secrets: где хранятся токены в multi-machine setup? Сейчас ad-hoc в
.common/secrets/и~/.config/projects-mcp/auth.toml. - Q7 — access control / discoverability (deferred to v2): иерархия видимости компонентов (
public/internal/secret). В v0 — всеpublic, secrets живут только в.common/secrets/с.gitignore. - Q9 — переименование
claude-skills→.skills(deferred): репо стилистически выпадает из dotfile-конвенции флота. Scope: только git-имя репо в gitea + cloned dir name. Local runtime path~/.claude/skills/остаётся (hardcoded в Claude Code). Когда поднимать: при дизайнеfactory.yamlv0.2 /templates/enterprise/<repo>/.
v0 plan — live bootstrap нового ноута как field-test (выполнено 2026-05-06)
Stop-condition: не сидеть в чистом дизайне до победного — у пользователя есть свежая машина, на ней проверяем дизайн руками.
Алгоритм:
- Узнать ОС нового ноута.
- Бутстрапить пошагово, я директирую каждую команду.
- Каждая команда логгируется в
.factory/L0/install-log.md— сырьё для будущихbootstrap.ps1/bootstrap.sh. - После end-to-end успеха — формализуем log в скрипты.
- Только после field-test'а — за L1 (Go-бинарь и
factory.yaml).
Field-test results — 2026-05-06
End-to-end на новом Win11 ноуте отработал. Полный лог — .factory/L0/install-log.md (этот же репо).
| Шаг | Что | Статус |
|---|---|---|
| L0a | mise + системный pkg-mgr (winget) | ✅ first-pass |
| L0b | clone factory, инициализация ~/.config/factory/home.toml |
✅ |
| 11a | clone claude-skills, 21 скил доступен через Skill тул |
✅ |
| 11b | claude login + плагины superpowers@claude-plugins-official + context7@claude-plugins-official |
✅ (manual, browser-redirect) |
| 11c.1 | setup-interns — MCP-сервер, секреты в .common/secrets/interns.env |
✅ |
| 11c.2 | setup-projects-meta — repo + wiki clone + MCP entry + initial sync |
✅ idempotent re-run (всё уже было — скил детектил наличие и пошёл по path «update + verify») |
| 11c.3 | context7 sanity (resolve-library-id "react" → 5 matches) |
✅ |
| Фикстуры | .organization/, .templates/, .meeting-room/ склонированы |
✅ |
Что подтвердилось:
- Q1 (Go для L1) валидно — текущий L0 на mise+winget хорошо ложится в манифест, runtime-зависимостей сверху не нужно.
- Q6 (mise поверх системного pkg-mgr) — отработало без сюрпризов. Mise успешно поставил node/python.
setup-projects-metaidempotency-логика — корректно различил «fresh install» vs «update+verify». В bootstrap.ps1 повторить.- Plugin-route для context7 — правильное решение (legacy
setup-context7скил не запускался, конфликта нет).
Gap'ы / кандидаты для bootstrap-скрипта (полный список — в install-log.md):
- 11b принципиально не автоматизируется (требует браузер-redirect / device-code) — bootstrap.ps1 должен парковаться здесь и ждать пользователя.
- Порядок 11c-скилов критичен:
interns→projects-meta→ плагины (или их sanity) → фикстуры. Это контракт скрипта, не выбор пользователя. - Каждый setup-* скил уже идемпотентен — bootstrap может звать их без проверки «надо ли». Но pre-check блок самого скрипта (есть ли git, mise, claude, плагины) обязан быть.
Источник
Промоушн брейнсторма из .meeting-room/.archive/2026-05-06-factory-bootstrap.md. Участники: user, claude-cso. Старт: 2026-05-06.