Files
factory/.wiki/concepts/factory-bootstrap.md
vitya cb9f6b033d fix(factory.yaml): v0.2.0 — interns-mcp + projects-meta-mcp as subdirs of .common, not standalone repos
The `source.type: git` blocks for interns-mcp and projects-meta-mcp pointed
to repos that don't exist as standalone (interns-mcp never existed,
projects-meta-mcp is archived). Both live as subdirectories of the .common
repo. Remove source blocks, keep deps + target + setup_skill + health_check.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-07 13:52:45 +03:00

16 KiB
Raw Blame History

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__* живой, 1314 страниц
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/ (subdirs of .common, not standalone repos — см. [migrate-to-common-lib]) живые
Communications .meeting-room/ живой

Что не работало для онбординга нового сотрудника:

  1. Нет orchestrator'аsetup-* дёргаются по одному вручную.
  2. Нет L0 entry point — пока Claude не запущен, ни один setup-* не доступен.
  3. Нет manifest'а компонентов — версий, зависимостей, health-check'ов нет нигде.
  4. Hardcoded ~/projects/ в путях — переезд = ручная починка.
  5. Multi-vendor (Cursor / Copilot CLI / Gemini CLI): setup-* пишут только в ~/.claude.json.
  6. Фабрика сама не убрана.

Решение

Создать новую дот-папку ~/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_dirhome.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
        # Subdirectory of .common repo — no standalone git source
        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

Главные аргументы: размер бинаря (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

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.

Что не покрыто (нужны новые скаффолды):

  1. Корневые мета-репо.common/, .meeting-room/, .organization/, .templates/, claude-skills-fork.
  2. 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 pinned name@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.yaml v0.2 / templates/enterprise/<repo>/.

v0 plan — live bootstrap нового ноута как field-test (выполнено 2026-05-06)

Stop-condition: не сидеть в чистом дизайне до победного — у пользователя есть свежая машина, на ней проверяем дизайн руками.

Алгоритм:

  1. Узнать ОС нового ноута.
  2. Бутстрапить пошагово, я директирую каждую команду.
  3. Каждая команда логгируется в .factory/L0/install-log.md — сырьё для будущих bootstrap.ps1 / bootstrap.sh.
  4. После end-to-end успеха — формализуем log в скрипты.
  5. Только после 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/ склонированы

Что подтвердилось:

  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 повторить.
  4. Plugin-route для context7 — правильное решение (legacy setup-context7 скил не запускался, конфликта нет).

Gap'ы / кандидаты для bootstrap-скрипта (полный список — в install-log.md):

  • 11b принципиально не автоматизируется (требует браузер-redirect / device-code) — bootstrap.ps1 должен парковаться здесь и ждать пользователя.
  • Порядок 11c-скилов критичен: internsprojects-meta → плагины (или их sanity) → фикстуры. Это контракт скрипта, не выбор пользователя.
  • Каждый setup-* скил уже идемпотентен — bootstrap может звать их без проверки «надо ли». Но pre-check блок самого скрипта (есть ли git, mise, claude, плагины) обязан быть.

Источник

Промоушн брейнсторма из .meeting-room/.archive/2026-05-06-factory-bootstrap.md. Участники: user, claude-cso. Старт: 2026-05-06.