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.
237 lines
23 KiB
Markdown
237 lines
23 KiB
Markdown
---
|
||
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.
|
||
- Главные аргументы: размер бинаря (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**. Решено 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 закрыты; Q2–Q5 явно отложены за v0 (живут в shared wiki после промоушена); Q7, Q9 deferred. Field-test end-to-end успешен. Готов к промоушену.
|