Files
discussions/.archive/2026-05-06-factory-bootstrap.md
vitya f3cad514db Promote factory-bootstrap → factory wiki + 2 tasks; archive buffer
Wiki: factory/.wiki/concepts/factory-bootstrap.md (full design + Q1/Q6/Q8
decisions + Q2-Q5/Q7/Q9 deferred + 2026-05-06 field-test results).
Tasks: factory#factory-bootstrap-script (ready), factory#factory-l1-design
(blocked-by script). Side-task: claude-skills#project-creation-lifecycle-skill
(gap surfaced — ad-hoc project creation strands repos outside projects-meta
indexing until manual seed).

Buffer moved to .archive/2026-05-06-factory-bootstrap.md.
2026-05-06 21:23:42 +03:00

237 lines
23 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
topic: factory-bootstrap
started: 2026-05-06
participants: [user, claude-cso]
status: ready-to-promote
problem: >
Установка/обновление инфраструктуры software factory (точечные папки в ~/projects/,
shared MCP-сервера, скилы) для нового сотрудника должна быть "одной кнопкой" —
кросс-платформенной, идемпотентной, нечувствительной к расположению/имени projects-папки,
поддерживающей несколько папок проектов на одной машине, частичные/устаревшие установки
и разные AI-клиенты (Claude Code / Copilot CLI / Gemini CLI).
---
# Software factory bootstrap — design buffer
## Контекст и диагноз (как это выглядит сейчас)
В `~/projects/` есть 6 точечных папок-модулей будущей "ERP":
| Модуль | Артефакт | Состояние |
|---|---|---|
| HR / org chart | `.organization/` (roster.md + personas) | частично (CSO/Dev/Analyst в roster, personas/permissions упомянуты но не наполнены) |
| Inventory / templates | `.templates/` | `project/` — частично (`python-package`, `with-wiki-tasks`); `agent/`, `report/` — пустые |
| Knowledge | `.wiki/` (local Karpathy) | живой |
| Knowledge (shared) | `projects-wiki` через `mcp__projects-meta__*` | живой, 13 страниц |
| Tasks / PMO | `.tasks/` (local) + `mcp__projects-meta__tasks_*` (shared) | живой, 13 проектов в кэше |
| Shared services | `.common/` (lib/scripts/secrets/prompts/config) | живой |
| Tooling registry | `claude-skills/` (~20 скилов: 5 setup-*, project-bootstrap, using-*, caveman-*) | живой |
| Bus services | `.common/lib/projects-meta-mcp/`, `.common/lib/interns-mcp/` | живые |
| Communications | `.meeting-room/` | живой (cwd) |
**Что не работает для онбординга нового сотрудника:**
1. Нет orchestrator'а`setup-*` дёргаются по одному вручную из живого Claude.
2. Нет L0 entry point — пока Claude не запущен, ни один setup-* не доступен (chicken-and-egg).
3. Нет manifest'а компонентов — версий, зависимостей, health-check'ов нет нигде; `factory.yaml` отсутствует.
4. Hardcoded `~/projects/` в путях (например `.common/lib/projects-meta-mcp/dist/sync.js`) — переезд / переименование = ручная починка.
5. Multi-vendor (Cursor / Copilot CLI / Gemini CLI): `using-superpowers` уже это учитывает, но `setup-*` пишут только в `~/.claude.json`.
6. `meeting-room` / `meeting-room2` — дубликаты, фабрика сама не убрана.
7. В кросс-проектных задачах ничего нет про factory bootstrap (релевантные находки: только `web4-phase0-bootstrap` в stostayer.new и `active-platform-eval` в claude-skills). В shared wiki — пусто (`knowledge_search "factory bootstrap onboarding new machine"` → 0 hits).
## Рекомендация (decided)
**Создать новую дот-папку `~/projects/.factory/` — отдельный репо, сиблинг `.common/`. Manifest-driven cross-platform installer/updater всей мета-инфраструктуры.**
Размещение **(a)** выбрано потому, что factory должна работать **до того**, как `.common` склонирован. L0 кладёт `.factory/` первым, дальше уже он ставит всё остальное. Альтернативы (b) `.common/lib/factory/` и (c) `claude-skills/skills/factory/` отвергнуты: обе создают cycle dependency на свои родительские модули.
### Архитектура — три слоя
**L0 — Pre-Claude bootstrap** (нативный shell, без runtime-зависимостей). Разбит на два под-слоя:
**L0a — System bootstrap (toolchain).** Голая машина → готовая к работе.
- Системный пакет-менеджер: `winget` (Win11, встроен), `brew` (Mac, `curl … | bash`), `apt`/`dnf`/`pacman` (Linux native).
- `git` + `curl` через системный pkg-mgr.
- `mise` (бывш. rtx) — single-binary unified runtime manager. Через него `node@lts`, `python@latest`, `go@latest`, `rust` по требованию. Кросс-платформенно, без root, один `mise.toml` на проект. Закрывает 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` со схемой:
```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 или deno-single-file)
- Manifest-схема (черновик):
```yaml
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 # делегируется в L2
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"
# ... .organization, .templates, .meeting-room, dot-tasks, interns-mcp
```
- Команды:
- `factory install` — пройти DAG зависимостей, поставить всё что не прошло health-check
- `factory update` — git pull + re-run health-checks
- `factory status` — таблица: `name | version | health | deps`
- `factory diagnose <name>` — verbose run health-check, печать stderr
- Идемпотентность по health-check'у — re-run = no-op.
**L2 — `setup-*` skills остаются как есть.** `factory` их триггерит через печать инструкции пользователю ("запусти `/setup-projects-meta`") до тех пор, пока не появится программный slash-command-bridge. Когда появится — `setup_skill: <name>` будет вызываться напрямую.
### Что закрывает каждое требование
| Требование | Решение |
|---|---|
| Папка `~/projects` в произвольном месте | `{projects_dir}` substitution в manifest, источник — `~/.config/factory/home.toml` |
| Произвольное имя папки | То же; manifest нигде не хардкодит "projects" |
| Несколько папок на одной машине | Несколько профилей в `home.toml` (`[profiles.work]`, `[profiles.personal]`); флаг `--profile` |
| Cross-platform | L0 — два нативных скрипта; L1 — single-file бинарь под Win/Mac/Linux; L2 — уже работает |
| Частичные / устаревшие установки | health_check на каждый компонент; `factory status` показывает дельту; `factory update` чинит |
| Multi-vendor (не только Anthropic) | `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'а, не корнем.
## Quick wins (параллельные, не блокируют дизайн)
- Заполнить пустые `.templates/agent/`, `.templates/report/`.
- Разобрать duplicate `meeting-room` / `meeting-room2`.
- После promotion — заингестить итог в shared wiki как `concepts/factory-bootstrap` (через `knowledge_ingest`).
- Завести в `claude-skills/.tasks/` задачу `factory-bootstrap-design` со ссылкой на promoted concept.
## Открытые вопросы
### Решённые
- **Q1 — runtime для L1**: ✅ **Go**. Решено 2026-05-06.
- Главные аргументы: размер бинаря (510 МБ vs 80100 МБ 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**. Решено 2026-05-06.
- 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 уже стоят на любой целевой ОС.
### Открытые
- **Q2 — где живёт каноничный manifest в production**: в `.factory/factory.yaml` (один на машину) или в shared Gitea с per-machine override? Склоняюсь к "default в `.factory/` репе, override через `~/.config/factory/home.toml#overrides`".
- **Q3 — slash-command-bridge для L2**: ждать пока Anthropic / другие вендоры дадут программное API, или поднять свой через MCP-сервер `factory-mcp` (тулы: `factory_install`, `factory_status`)? Второе — независимее, но стоит ещё одного сервера.
- **Q4 — версионирование manifest'а**: semver на `factory.yaml` сам? Или per-component версии в pinned-формате `name@v1.2.3`? Last вероятно правильнее, повторяет npm/cargo.
- **Q5 — secrets**: где хранятся токены (gitea, ollama, anthropic) в multi-machine setup? Сейчас ad-hoc в `.common/secrets/` и `~/.config/projects-mcp/auth.toml`. factory должен это унифицировать.
- **Q7 — access control / discoverability** (deferred to v2): иерархия видимости компонентов фабрики (`public` / `internal` / `secret`) с фильтром при `factory install`. В v0 — все компоненты `public`, secrets живут только в `.common/secrets/` с `.gitignore`. Не блокирует v0.
- **Q8 — fresh-enterprise bootstrap (greenfield-mode дистрибутива)**: должен ли `factory` уметь поднимать **пустое предприятие** — не клонировать существующие гитеа-репы (clone-mode), а **скаффолдить шесть мета-репо из встроенных templates**?
- **Use case:** новый юзер хочет повторить эту ERP-архитектуру у себя — у него есть свой gitea/github namespace, но нет ни `.common/`, ни `.meeting-room/`, ни `.organization/`, ни `.templates/`, ни `claude-skills`-форка, ни `projects-meta-mcp` source-tree. Должен иметь возможность сделать `factory init my-enterprise --git-host https://my-gitea.example.com/myorg` — фабрика создаёт пустые репы, пушит скелеты, потом идёт обычный `factory install`.
- **Status:** ✅ нужно поддерживать. Решение принято на field-test'е 2026-05-06; реализация отложена в production-фазу.
- **Что уже покрыто greenfield'ом** (повторно использовать как есть): `setup-wiki` (пустая Karpathy-вики), `setup-tasks` (пустой STATUS.md с легендой), `project-bootstrap` (CLAUDE.md/.gitignore/README в любой папке).
- **Что не покрыто** (нужны новые скаффолды):
1. **Корневые мета-репо** — `.common/`, `.meeting-room/`, `.organization/`, `.templates/` сам, claude-skills-fork. У них нет templates ни в одном из существующих скилов. Сейчас они выросли органически, готовые лежат в `git.kzntsv.site/OpeItcLoc03/`. Для нового предприятия их надо родить.
2. `setup-projects-meta` и `setup-interns` ждут готовый source-tree в gitea — нужен **`init`-mode** (форкать из template-репа `factory/templates/...` либо inline-scaffold).
- **Архитектурное предложение** — добавить в `factory.yaml` per-component `clone-or-init`-источник:
```yaml
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>` — создаёт пустые репы в namespace юзера, пушит scaffolded skeletons, далее обычный `factory install`.
- **Anti-recommendation:** **не** пытаться bootstrap'ить сам git-host (gitea/forgejo/github). Factory ожидает, что писательский git-сервер уже существует и юзер имеет туда write-access. Подъём гитеа — это L0a infra-задача (winget/docker-compose), не L1 (factory).
- **Цена:** +1 папка `templates/enterprise/<repo>/` (6 скелетов: `common`, `meeting-room`, `organization`, `templates`, `projects-meta-mcp-skeleton`, `interns-mcp-skeleton`) + per-component поле `source.template:` в manifest. Оценка: ~неделя на скелеты + ~3 дня на `clone-or-init` логику в Go-биноре.
- **Зависимости:** не блокирует v0 (clone-mode достаточно для текущего fleet'а из 1 юзера + новой машины). Реализуется параллельно после v0 production-deploy.
- **Q9 — переименование `claude-skills` → `.skills`** (deferred): репо `claude-skills` стилистически выпадает из dotfile-конвенции флота (`.common/`, `.organization/`, `.meeting-room/`, `.templates/`, `.wiki/`, `.tasks/`) и фиксирует в имени один движок, хотя `superpowers:using-superpowers` уже ссылается на Copilot CLI / Codex / Gemini tool mappings. Озвучено пользователем 2026-05-06 во время field-test'а, явно «но позже».
- **Scope переименования:** только git-имя репо в gitea + cloned dir name. Local runtime path `~/.claude/skills/` остаётся (hardcoded в Claude Code). Frontmatter скилов с Claude-specific tool names не трогается — `references/copilot-tools.md` / `codex-tools.md` уже покрывают cross-platform.
- **Когда поднимать:** (a) при дизайне `factory.yaml` v0.2 / `templates/enterprise/<repo>/` — естественный момент менять имена; (b) при общем рефакторинге фикстур-репо. Не блокирует v0.
## v0 plan — live bootstrap нового ноута как field-test
Stop-condition этого подхода: **не сидеть в чистом дизайне до победного — у пользователя есть свежая машина, на ней проверяем дизайн руками**.
Алгоритм:
1. Узнать ОС нового ноута (Q6 ответ — определяет первую команду L0a).
2. Бутстрапить машину пошагово, я директирую каждую команду.
3. Каждая выполненная команда логгируется в `.factory/L0/install-log.md` — это сырьё для будущих `bootstrap.ps1` / `bootstrap.sh`.
4. После того как factory поднимется на новом ноуте end-to-end (включая `setup-projects-meta`, `setup-interns`, claude-skills install, `.wiki`/`.tasks`/`.organization` clone), формализуем log в скрипты.
5. Только после успешного field-test'а садимся за L1 (Go-бинарь и `factory.yaml`).
**Артефакты этого этапа:**
- `.factory/L0/install-log.md` — пошаговый лог команд (на новом ноуте).
- Diff между "что я сделал руками" и "что должен делать L0 скрипт" — readme-черновик `.factory/L0/README.md`.
- Список найденных gaps (что не получилось / что было неочевидно) — кандидаты в Q-список.
## Field-test results — 2026-05-06
End-to-end на новом Win11 ноуте отработал. Полный лог — `.factory/L0/install-log.md` (`git.kzntsv.site/OpeItcLoc03/factory`).
| Шаг | Что | Статус |
|---|---|---|
| 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/` склонированы | ✅ |
**Что подтвердилось:**
1. **Q1 решение (Go для L1) валидно** — текущий L0 на mise+winget хорошо ложится в манифест, runtime-зависимостей сверху не нужно.
2. **Q6 решение (mise поверх системного pkg-mgr)** — отработало без сюрпризов. Mise успешно поставил node/python.
3. **`setup-projects-meta` idempotency-логика** — корректно различил «fresh install» vs «update+verify». В bootstrap.ps1 повторить эту же pre-check логику.
4. **Plugin-route для context7** — правильное решение (legacy `setup-context7` скил не запускался, конфликта нет).
**Gap'ы / кандидаты для bootstrap-скрипта** (полный список — в `install-log.md` секция «Gaps / questions surfaced during field-test»):
- 11b принципиально не автоматизируется (требует браузер-redirect / device-code) — bootstrap.ps1 должен **парковаться** здесь и ждать пользователя.
- Порядок 11c-скилов критичен: `interns` → `projects-meta` → плагины (или их sanity) → фикстуры. Это контракт скрипта, не выбор пользователя.
- Каждый setup-* скил уже идемпотентен — bootstrap может звать их без проверки «надо ли». Но pre-check блок самого скрипта (есть ли git, mise, claude, плагины) обязан быть.
## Действия после промоушена (план)
1. `meeting-room-promote-brainstorm factory-bootstrap` →
- shared wiki в проекте `factory`: `concepts/factory-bootstrap` (полный дизайн + Q1/Q6/Q8 решения + Q9 deferred + field-test results).
- tasks в `factory/.tasks/`:
- `factory-bootstrap-script` — status=ready, next_action: «извлечь шаги из install-log.md в `bootstrap.ps1` + `bootstrap.sh`, переиспользовать idempotency-pattern из setup-projects-meta».
- `factory-l1-design` — status=blocked-by `factory-bootstrap-script`, next_action: «после успешного скрипта — Go-бинарь + factory.yaml schema (см. Q2/Q4)».
- архив: `.archive/2026-05-06-factory-bootstrap.md`.
## Stop-condition этого буфера
**Достигнут 2026-05-06.** Q1, Q6, Q8 закрыты; Q2Q5 явно отложены за v0 (живут в shared wiki после промоушена); Q7, Q9 deferred. Field-test end-to-end успешен. Готов к промоушену.