Files
WslLoopBuild/.loop-build/scripts/init.sh

215 lines
4.0 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
LB_DIR="$ROOT_DIR/.loop-build"
STATE_DIR="$LB_DIR/state"
CONFIG_DIR="$LB_DIR/config"
TASKS_FILE="$LB_DIR/TASKS.md"
STATE_FILE="$STATE_DIR/current_task.json"
HISTORY_FILE="$STATE_DIR/history.ndjson"
need_approval_files=("$TASKS_FILE" "$STATE_FILE" "$HISTORY_FILE")
log() {
printf '%s\n' "$*"
}
check_dependencies() {
local missing=0
for dep in git bash rg jq; do
if ! command -v "$dep" >/dev/null 2>&1; then
printf '[init][MISSING] %s\n' "$dep"
printf ' install suggestion: use your package manager (e.g. apt, brew, or winget)\n'
missing=1
else
printf '[init][OK] %s\n' "$dep"
fi
done
if (( missing != 0 )); then
log "[init] dependency check found missing tools. init continues with warnings only."
fi
}
render_task_template() {
cat > "$TASKS_FILE" <<'EOF_TPL'
# loop-build Task Template
## Task
- task_id:
- goal:
- constraints:
- repo_context_hint:
- created_at:
- updated_at:
## Plan source
- generated_by: prompts/planner.md
- plan_status: not_started
- current_step:
- verify_targets:
## Progress
- completed_steps:
- next_step:
- open_questions:
- last_verification:
## Notes
- plan diff scope should stay <= 2 files/step
- each step should be one incremental change and one verification
- avoid full-file rewrites
EOF_TPL
}
init_state_file() {
if [[ -f "$STATE_FILE" ]]; then
return 0
fi
cat > "$STATE_FILE" <<EOF_STATE
{
"task_id": "",
"goal": "",
"constraints": [],
"plan_steps": [],
"success_criteria": [],
"risk_notes": [],
"required_files": [],
"verify_targets": [],
"plan_status": "not_started",
"pending_action": "need_plan_approval",
"next_step": 1,
"completed_steps": [],
"open_questions": [],
"current_step": null,
"last_verification": null,
"created_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
"updated_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
}
EOF_STATE
}
init_default_config() {
if [[ -f "$CONFIG_DIR/policy.env" ]]; then
return 0
fi
cat > "$CONFIG_DIR/policy.env" <<'EOF_CFG'
# Loop Build policy toggles
# Commands in denylist can execute only after explicit unlock + secondary confirm.
POLICY_SECONDARY_CONFIRM=0
ALLOW_SUDO=0
ALLOW_RM_RF=0
ALLOW_NETWORK=0
ALLOW_CURL_BASH=0
ALLOW_INSTALL=0
ALLOW_GIT_NETWORK=0
ALLOW_PROFILE_MODIFY=0
EOF_CFG
}
ensure_default_files() {
if [[ ! -f "$STATE_DIR/history.ndjson" ]]; then
: > "$HISTORY_FILE"
fi
if [[ ! -f "$TASKS_FILE" ]]; then
render_task_template
fi
if [[ ! -f "$CONFIG_DIR/allowlist.txt" ]]; then
cat > "$CONFIG_DIR/allowlist.txt" <<'EOF_ALLOW'
ls
ls -la
cat
rg
grep
tree
git status
git diff
git rev-parse
git log
git show
git branch
git branch --show-current
git status --short
git blame
sed
awk
head
tail
wc
printf
echo
find
pwd
false
true
EOF_ALLOW
fi
if [[ ! -f "$CONFIG_DIR/denylist.txt" ]]; then
cat > "$CONFIG_DIR/denylist.txt" <<'EOF_DENY'
sudo
rm -rf
rm -fr
git clone
git push
git pull
git commit
git rebase
git reset
curl
wget
npm install
npm i
yarn add
yarn install
pnpm add
pnpm install
pip install
pip3 install
composer install
bash -c
sh -c
curl | bash
wget | sh
EOF_DENY
fi
}
check_git_state_hint() {
if [[ -d "$ROOT_DIR/.git" ]] && command -v git >/dev/null 2>&1; then
changed=$(git -C "$ROOT_DIR" status --short | wc -l | tr -d ' ')
if [[ "$changed" != "0" ]]; then
log "[init][WARN] repository is not clean; recommended for safer incremental steps."
else
log "[init] repo clean check: passed"
fi
else
log "[init][WARN] no .git metadata detected; diff/rollback features are limited."
fi
}
main() {
log "[init] starting loop-build bootstrap"
check_dependencies
mkdir -p "$STATE_DIR" "$CONFIG_DIR"
init_state_file
ensure_default_files
init_default_config
check_git_state_hint
log "[init] done."
log "[init] next steps:"
log " 1) complete .loop-build/state/current_task.json from a planner response"
log " 2) run ./ .loop-build/scripts/run_task.sh APPROVE_PLAN"
log " 3) run ./ .loop-build/scripts/run_task.sh step"
}
main "$@"