Context
Found while dogfooding v0.22.0 (bstack bootstrap loop wiring) on two existing real repos (stimulus, broomva.tech). Bootstrap is built for fresh workspaces; on existing repos with their own hooks/CI/gitignore it does two unsafe things and lacks one needed capability.
1. install-l3-stability.sh clobbers a tracked .githooks/pre-commit (safety bug)
On broomva.tech, the repo has a tracked .githooks/pre-commit (a multimedia-asset validator). install-l3-stability overwrote it with the bstack L3 rate-gate hook (moving the original to .pre-commit.local) — even though core.hooksPath was .git/hooks, not .githooks, so the bstack hook wouldn't even fire.
- Fix: never overwrite a tracked
.githooks/pre-commit. Detect git ls-files --error-unmatch; if tracked, skip (or chain via an exec/source append) and [warn] instead of clobber. Also gate on whether core.hooksPath actually points at .githooks.
2. No gitignore-awareness / public-repo detection (the bigger gap)
.claude/, /CLAUDE.md, /AGENTS.md were gitignored on broomva.tech — so bootstrap scaffolded a CLAUDE.md that could never be committed, and wired a settings.json with absolute paths into a gitignored dir. Conversely, a repo that broadly ignores .control/ would silently lose the loop definitions (arcs.yaml, rcs-parameters.toml) the loop needs.
Bootstrap should reconcile against a committable-vs-machine-local manifest:
| Class |
Files |
Rule |
| Committable (team-wide, no secrets) |
CLAUDE.md, AGENTS.md, METALAYER.md, .control/policy.yaml, .control/arcs.yaml, .control/rcs-parameters.toml |
must NOT be ignored; warn if they are |
| Machine-local (paths/telemetry) |
.claude/settings.json, .control/audit/*.jsonl |
must BE ignored; add to .gitignore if missing |
| Deliberately private |
anything the repo already ignores (e.g. /CLAUDE.md) |
never un-ignore without explicit opt-in |
- Public-repo detection: when the remote is public, default to local-only loop wiring (substrate stays gitignored) unless the operator opts into committing governance. Surfaced, not silent.
- Manifest reconciliation:
bootstrap adds the machine-local entries to .gitignore, and warns (doesn't auto-un-ignore) when a committable file is ignored — leaving the publish decision to the human.
3. Doctor follow-on
doctor §23 already reads both settings.json + settings.local.json (good). Consider a §-check that flags committable-substrate files that are gitignored (coverage gap) vs machine-local files that are tracked (leak risk).
Provenance
🤖 Generated with Claude Code
Context
Found while dogfooding v0.22.0 (
bstack bootstraploop wiring) on two existing real repos (stimulus, broomva.tech). Bootstrap is built for fresh workspaces; on existing repos with their own hooks/CI/gitignore it does two unsafe things and lacks one needed capability.1.
install-l3-stability.shclobbers a tracked.githooks/pre-commit(safety bug)On broomva.tech, the repo has a tracked
.githooks/pre-commit(a multimedia-asset validator).install-l3-stabilityoverwrote it with the bstack L3 rate-gate hook (moving the original to.pre-commit.local) — even thoughcore.hooksPathwas.git/hooks, not.githooks, so the bstack hook wouldn't even fire..githooks/pre-commit. Detectgit ls-files --error-unmatch; if tracked, skip (or chain via anexec/source append) and[warn]instead of clobber. Also gate on whethercore.hooksPathactually points at.githooks.2. No gitignore-awareness / public-repo detection (the bigger gap)
.claude/,/CLAUDE.md,/AGENTS.mdwere gitignored on broomva.tech — so bootstrap scaffolded aCLAUDE.mdthat could never be committed, and wired asettings.jsonwith absolute paths into a gitignored dir. Conversely, a repo that broadly ignores.control/would silently lose the loop definitions (arcs.yaml,rcs-parameters.toml) the loop needs.Bootstrap should reconcile against a committable-vs-machine-local manifest:
CLAUDE.md,AGENTS.md,METALAYER.md,.control/policy.yaml,.control/arcs.yaml,.control/rcs-parameters.toml.claude/settings.json,.control/audit/*.jsonl.gitignoreif missing/CLAUDE.md)bootstrapadds the machine-local entries to.gitignore, and warns (doesn't auto-un-ignore) when a committable file is ignored — leaving the publish decision to the human.3. Doctor follow-on
doctor§23 already reads bothsettings.json+settings.local.json(good). Consider a §-check that flags committable-substrate files that are gitignored (coverage gap) vs machine-local files that are tracked (leak risk).Provenance
settings.local.jsonfor hooks) — broomva/stimulus#1811.🤖 Generated with Claude Code