feat: L0b bootstrap scripts + L1 Go CLI structure

L0b (factory bootstrap):
- bootstrap.ps1 (Windows): pre-checks, interactive config, clone .factory, home.toml
- bootstrap.sh (Linux/Mac): same functionality for bash
- Idempotent re-run with home.toml verification

L1 (Go CLI):
- factory.yaml: manifest schema with components, deps, health-checks
- cmd/factory: Cobra CLI (install/update/status/diagnose)
- pkg/config: home.toml reader
- pkg/manifest: factory.yaml parser + topological sort
- pkg/health: health-check logic (file/dir/mcp_tool/command)

Scripts:
- build.sh: cross-compile for linux/win/darwin × amd64/arm64
- build.ps1: PowerShell cross-compile

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-06 23:59:09 +03:00
parent 47b41aa2f7
commit 561a7fd66f
12 changed files with 1380 additions and 43 deletions

182
bootstrap.sh Normal file
View File

@@ -0,0 +1,182 @@
#!/usr/bin/env bash
# L0b Factory Bootstrap — Linux/macOS
# Auto-generated from install-log.md field-test 2026-05-06
set -euo pipefail
GITEA_DEFAULT="https://git.kzntsv.site"
ORG_DEFAULT="OpeItcLoc03"
FACTORY_REPO_DEFAULT="factory"
HOME_TOML="$HOME/.config/factory/home.toml"
PROJECTS_DIR_DEFAULT="$HOME/projects"
step() { echo -e "\n▶ $*"; }
ok() { echo "$*"; }
skip() { echo "$*"; }
gap() { echo "$*" >&2; }
check_cmd() {
command -v "$1" &>/dev/null
}
# Pre-checks
step "L0b Pre-checks"
missed=()
check_cmd git || missed+=("git (install: brew install git / apt install git)")
check_cmd curl || missed+=("curl (install: brew install curl / apt install curl)")
check_cmd mise || missed+=("mise (install: curl https://mise.run | bash)")
check_cmd claude || missed+=("claude (install: curl https://claude.ai/install.sh | bash)")
if [[ ${#missed[@]} -gt 0 ]]; then
gap "Missing dependencies:"
for m in "${missed[@]}"; do
echo " - $m"
done
echo ""
echo "Install missing tools and re-run bootstrap."
exit 1
fi
ok "Pre-checks passed"
# Check if already bootstrapped
if [[ -f "$HOME_TOML" ]]; then
skip "Already bootstrapped. Re-run mode: verify only."
if [[ $(grep -oP "projects_dir\s*=\s*'\K[^']+" "$HOME_TOML" 2>/dev/null) ]]; then
existing_dir=$(grep -oP "projects_dir\s*=\s*'\K[^']+" "$HOME_TOML")
echo " projects_dir: $existing_dir"
if [[ -d "$existing_dir/.factory" ]]; then
ok ".factory exists"
else
gap ".factory missing at $existing_dir/.factory"
exit 1
fi
fi
ok "Bootstrap verified. Exiting (no-op)."
exit 0
fi
# Interactive: ask for configuration
step "Configuration"
read -rp "Gitea URL [$GITEA_DEFAULT]: " gitea
gitea=${gitea:-$GITEA_DEFAULT}
read -rp "Gitea org/user [$ORG_DEFAULT]: " org
org=${org:-$ORG_DEFAULT}
read -rp "Factory repo name [$FACTORY_REPO_DEFAULT]: " factoryRepo
factoryRepo=${factoryRepo:-$FACTORY_REPO_DEFAULT}
read -rp "Projects directory [$PROJECTS_DIR_DEFAULT]: " projectsDir
projectsDir=${projectsDir:-$PROJECTS_DIR_DEFAULT}
read -rp "AI client [claude-code/copilot-cli/gemini-cli] (default: claude-code): " client
client=${client:-claude-code}
# Validate projects_dir
if [[ ! -d "$projectsDir" ]]; then
read -rp "Directory '$projectsDir' does not exist. Create? [Y/n] " create
if [[ "$create" != "n" && "$create" != "N" ]]; then
mkdir -p "$projectsDir"
ok "Created $projectsDir"
else
gap "Cannot continue without projects_dir"
exit 1
fi
fi
# Clone .factory
step "Cloning .factory repo"
factoryLocal="$projectsDir/.factory"
factoryUrl="$gitea/$org/$factoryRepo.git"
if [[ -d "$factoryLocal" ]]; then
skip ".factory already exists, skipping clone"
if [[ ! -d "$factoryLocal/.git" ]]; then
gap "$factoryLocal exists but is not a git repo. Remove it and re-run."
exit 1
fi
else
echo "Cloning from: $factoryUrl"
# Check if we have credentials for gitea
need_auth=false
if ! git ls-remote "$factoryUrl" &>/dev/null; then
need_auth=true
fi
if [[ "$need_auth" == true ]]; then
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo " PAT REQUIRED"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
echo "1. Open in browser: $gitea/user/settings/applications"
echo "2. Generate PAT with scopes: read:repository, write:repository, read:user"
echo "3. Press Enter when ready..."
echo ""
read -r
echo "Cloning with Git Credential Manager prompt..."
fi
git clone "$factoryUrl" "$factoryLocal" || {
gap "Clone failed. Check URL and credentials."
exit 1
}
ok "Cloned to $factoryLocal"
fi
# Write home.toml
step "Writing ~/.config/factory/home.toml"
configDir="$HOME/.config/factory"
mkdir -p "$configDir"
installed_at=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
cat > "$configDir/home.toml" <<EOF
# factory home — single source of machine-level state
# auto-generated by L0b bootstrap; safe to edit by hand
projects_dir = '$projectsDir'
client = '$client'
installed_at = '$installed_at'
EOF
ok "Wrote $HOME_TOML"
# Print next steps
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo " L0b COMPLETE"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
echo "Factory bootstrapped. Next steps (manual):"
echo ""
echo "1. Start Claude Code:"
echo " cd $factoryLocal"
echo " claude"
echo ""
echo "2. In Claude, run:"
echo " /login"
echo " /plugin install superpowers@claude-plugins-official"
echo " /plugin install context7@claude-plugins-official"
echo " /reload-plugins"
echo " /exit"
echo ""
echo "3. Run setup skills:"
echo " cd $projectsDir"
echo " claude"
echo " /setup-projects-meta"
echo " /setup-interns"
echo " /setup-tasks"
echo " /setup-wiki"
echo ""
echo "See .wiki/concepts/factory-bootstrap.md for full design."
echo "Re-run this script anytime — it's idempotent."