241 lines
10 KiB
Markdown
241 lines
10 KiB
Markdown
# Superpowers Artifact Ignore Policy Implementation Plan
|
|
|
|
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|
|
|
**Goal:** Remove operational Superpowers artifacts from the current repository tip, prevent them from being committed in future projects, and resolve PR #2's `.gitignore` merge conflict without rewriting history.
|
|
|
|
**Architecture:** Apply defense in depth: the user-level Git excludes file protects every local repository, while this repository's `.gitignore` protects collaborators and other machines. Merge current `origin/main` into `feature/uups-bank-demo`, retain local `.superpowers/` copies as ignored files, remove those artifacts from Git's index, and keep intentional documents under `docs/superpowers/` tracked.
|
|
|
|
**Tech Stack:** Git, Bash, Make, the repository's existing Foundry/Node verification gate, and Gitea CLI `tea`.
|
|
|
|
**Spec:** `docs/superpowers/specs/2026-08-25-superpowers-artifact-ignore-policy-design.md`
|
|
|
|
## Global Constraints
|
|
|
|
- Operational Superpowers and worktree directories are private local state and must not be committed: `**/.superpowers/`, `**/.claude/superpowers/`, and `**/.worktrees/`.
|
|
- Intentional design and implementation documents remain tracked under `docs/superpowers/specs/` and `docs/superpowers/plans/`.
|
|
- Enforce the policy in both the machine-wide Git excludes file and this repository's `.gitignore`.
|
|
- Remove `.superpowers/` from the current repository index without deleting local copies.
|
|
- Do not rewrite published history or force-push.
|
|
- Do not move or recreate `demo-start` or `demo-complete`.
|
|
- Preserve existing global ignore entries byte-for-byte apart from appending the approved rules once.
|
|
- Never print or inspect operational artifact contents during cleanup.
|
|
- If any merge conflict other than `.gitignore` appears, stop and report it rather than applying a broad resolution.
|
|
- Run the complete `make verify` gate before publishing the resolved branch.
|
|
|
|
## File and Interface Map
|
|
|
|
| Area | Files | Responsibility |
|
|
| --- | --- | --- |
|
|
| Machine policy | `/home/golem/.config/git/ignore` | Ignore operational Superpowers and worktree directories in all local repositories |
|
|
| Repository policy | `.gitignore` | Carry the same protection for collaborators while retaining application-specific generated/build exclusions |
|
|
| Repository cleanup | `.superpowers/**` index entries introduced by current `origin/main` | Remove generated operational artifacts from the resulting repository tree while retaining local ignored copies |
|
|
| Intentional docs | `docs/superpowers/specs/**`, `docs/superpowers/plans/**` | Remain tracked as authored project source |
|
|
|
|
---
|
|
|
|
### Task 1: Add the machine-wide Git ignore safeguard
|
|
|
|
**Files:**
|
|
- Modify: `/home/golem/.config/git/ignore`
|
|
|
|
**Interfaces:**
|
|
- Consumes: Git's default XDG user excludes file at `/home/golem/.config/git/ignore`.
|
|
- Produces: machine-wide ignored-directory behavior for `.superpowers/`, `.claude/superpowers/`, and `.worktrees/` in repositories that have no local `.gitignore` rule.
|
|
|
|
- [ ] **Step 1: Verify the current global policy does not yet ignore the three directories**
|
|
|
|
Create an isolated repository with no local ignore file:
|
|
|
|
```bash
|
|
probe_dir=$(mktemp -d /tmp/superpowers-ignore-policy.XXXXXX)
|
|
git -C "$probe_dir" init -q
|
|
mkdir -p "$probe_dir/.superpowers/sdd" "$probe_dir/.claude/superpowers" "$probe_dir/.worktrees/feature"
|
|
touch "$probe_dir/.superpowers/sdd/report.md" "$probe_dir/.claude/superpowers/state.json" "$probe_dir/.worktrees/feature/marker"
|
|
git -C "$probe_dir" check-ignore -v .superpowers/sdd/report.md .claude/superpowers/state.json .worktrees/feature/marker
|
|
```
|
|
|
|
Expected RED: `git check-ignore` exits `1` and prints no matching ignore rule. If all three paths are already ignored by the user-level file, do not duplicate them; record the existing matching rules and continue to Step 3.
|
|
|
|
- [ ] **Step 2: Append the exact global exclusions once**
|
|
|
|
Preserve the existing `**/.claude/settings.local.json` line and append exactly:
|
|
|
|
```gitignore
|
|
**/.superpowers/
|
|
**/.claude/superpowers/
|
|
**/.worktrees/
|
|
```
|
|
|
|
Use `apply_patch` directly when permitted. If the sandbox blocks editing `/home/golem/.config/git/ignore`, copy the file to a uniquely named `/tmp` path, use `apply_patch` on that copy, verify its diff against the original, then request narrowly scoped approval to install that exact prepared file back at `/home/golem/.config/git/ignore`. Do not use an in-place shell append that can duplicate entries.
|
|
|
|
- [ ] **Step 3: Verify the global policy in an isolated repository**
|
|
|
|
Run against the same `probe_dir`:
|
|
|
|
```bash
|
|
git -C "$probe_dir" check-ignore -v .superpowers/sdd/report.md .claude/superpowers/state.json .worktrees/feature/marker
|
|
```
|
|
|
|
Expected GREEN: exit `0`; all three paths print a matching rule sourced from `/home/golem/.config/git/ignore`.
|
|
|
|
- [ ] **Step 4: Verify uniqueness and preserve the existing rule**
|
|
|
|
```bash
|
|
test "$(rg -n -x -F '**/.superpowers/' /home/golem/.config/git/ignore | wc -l)" -eq 1
|
|
test "$(rg -n -x -F '**/.claude/superpowers/' /home/golem/.config/git/ignore | wc -l)" -eq 1
|
|
test "$(rg -n -x -F '**/.worktrees/' /home/golem/.config/git/ignore | wc -l)" -eq 1
|
|
rg -n -x -F '**/.claude/settings.local.json' /home/golem/.config/git/ignore
|
|
```
|
|
|
|
Expected: each new rule occurs exactly once and the pre-existing settings rule remains present.
|
|
|
|
- [ ] **Step 5: Remove only the isolated probe**
|
|
|
|
Validate the prefix before deleting:
|
|
|
|
```bash
|
|
case "$probe_dir" in
|
|
/tmp/superpowers-ignore-policy.*) rm -rf "$probe_dir" ;;
|
|
*) echo "refusing unexpected probe path: $probe_dir" >&2; exit 1 ;;
|
|
esac
|
|
```
|
|
|
|
No repository commit is created for this user-level configuration task.
|
|
|
|
---
|
|
|
|
### Task 2: Merge main, resolve the policy conflict, and untrack runtime artifacts
|
|
|
|
**Files:**
|
|
- Modify: `.gitignore`
|
|
- Remove from index only: `.superpowers/**`
|
|
- Preserve tracked: `docs/superpowers/specs/**`
|
|
- Preserve tracked: `docs/superpowers/plans/**`
|
|
|
|
**Interfaces:**
|
|
- Consumes: `origin/main` at the latest fetched commit, `feature/uups-bank-demo`, and the global exclusions produced by Task 1.
|
|
- Produces: a normal merge commit whose tree contains no `.superpowers/**` paths, keeps intentional `docs/superpowers/**` documents, and is conflict-free against the fetched `origin/main`.
|
|
|
|
- [ ] **Step 1: Confirm the exact pre-merge state**
|
|
|
|
```bash
|
|
git fetch origin main feature/uups-bank-demo
|
|
git status --short --branch
|
|
git rev-parse HEAD
|
|
git rev-parse origin/main
|
|
git rev-parse origin/feature/uups-bank-demo
|
|
git merge-tree --write-tree --messages origin/main HEAD
|
|
```
|
|
|
|
Expected RED: the branch is clean and named `feature/uups-bank-demo`; `git merge-tree` reports exactly one content conflict, `.gitignore`. If another path conflicts, stop and report it.
|
|
|
|
- [ ] **Step 2: Start a non-fast-forward merge without committing**
|
|
|
|
```bash
|
|
git merge --no-ff --no-commit origin/main
|
|
```
|
|
|
|
Expected: Git stops with one unresolved path, `.gitignore`; files newly tracked by `origin/main` may appear under `.superpowers/`.
|
|
|
|
- [ ] **Step 3: Resolve `.gitignore` to the exact repository policy**
|
|
|
|
Replace the conflicted file with:
|
|
|
|
```gitignore
|
|
# Local agent/session state
|
|
.claude/superpowers/
|
|
.superpowers/
|
|
.worktrees/
|
|
|
|
.env
|
|
.env.local
|
|
.demo/
|
|
cache/
|
|
out/
|
|
broadcast/
|
|
deployments/*.json
|
|
deployments/**/*.json
|
|
!deployments/*.example.json
|
|
node_modules/
|
|
web/node_modules/
|
|
web/dist/
|
|
web/coverage/
|
|
web/public/deployment.json
|
|
web/src/generated/*.ts
|
|
!.gitkeep
|
|
```
|
|
|
|
Do not retain `main`'s granular `.superpowers/brainstorm/...` rules; the broad `.superpowers/` rule is the approved policy.
|
|
|
|
- [ ] **Step 4: Keep operational artifacts locally while removing them from Git's index**
|
|
|
|
```bash
|
|
git add .gitignore
|
|
git rm -r --cached .superpowers
|
|
```
|
|
|
|
Expected: `.superpowers/**` paths are staged as deletions from the merge result but remain present locally and ignored.
|
|
|
|
- [ ] **Step 5: Verify the resolved merge before committing**
|
|
|
|
```bash
|
|
test -z "$(git diff --name-only --diff-filter=U)"
|
|
test -z "$(git ls-files '.superpowers/**')"
|
|
git check-ignore -v --no-index .superpowers/sdd/example.md .claude/superpowers/state.json .worktrees/example/marker
|
|
git ls-files 'docs/superpowers/specs/**' 'docs/superpowers/plans/**'
|
|
git diff --cached --check
|
|
git status --short
|
|
```
|
|
|
|
Expected: no unresolved paths; no `.superpowers/**` index entries; all three operational paths ignored by `.gitignore`; the approved design and implementation plan remain tracked; no whitespace errors.
|
|
|
|
- [ ] **Step 6: Commit the merge cleanup**
|
|
|
|
Inspect the staged path set without opening operational artifact contents, then commit:
|
|
|
|
```bash
|
|
git diff --cached --name-status
|
|
git commit -m "chore: keep superpowers artifacts local"
|
|
```
|
|
|
|
Expected: a merge commit with `origin/main` and the former feature HEAD as parents; no history rewrite and no tag movement.
|
|
|
|
- [ ] **Step 7: Run focused policy verification**
|
|
|
|
```bash
|
|
git merge-base --is-ancestor origin/main HEAD
|
|
test -z "$(git ls-tree -r --name-only HEAD -- .superpowers)"
|
|
git check-ignore -v --no-index .superpowers/sdd/example.md .claude/superpowers/state.json .worktrees/example/marker
|
|
git ls-tree -r --name-only HEAD -- docs/superpowers/specs docs/superpowers/plans
|
|
git diff --check origin/feature/uups-bank-demo..HEAD
|
|
git status --short --branch
|
|
```
|
|
|
|
Expected: `origin/main` is an ancestor; the committed tree has no `.superpowers` paths; intentional docs remain; the branch is ahead of `origin/feature/uups-bank-demo` only by the policy/design and merge-cleanup commits; the worktree has no tracked changes.
|
|
|
|
- [ ] **Step 8: Run the complete repository gate**
|
|
|
|
```bash
|
|
export PATH=/tmp/node-v24.18.0-linux-x64/bin:$PATH
|
|
export npm_config_cache=/tmp/uups-demo-npm-cache
|
|
export npm_config_offline=true
|
|
make verify
|
|
git diff --check
|
|
```
|
|
|
|
Expected GREEN: all Solidity, finalizer, process-safety, Base configuration, scanner, web lint/typecheck/test/build checks exit `0`; `git diff --check` exits `0`.
|
|
|
|
---
|
|
|
|
## Final Review and Publication
|
|
|
|
After both tasks pass their independent SDD review gates:
|
|
|
|
1. Run the whole-plan review over the design commit and merge-cleanup range.
|
|
2. Run a fresh controller `make verify` and `git diff --check` at the reviewed HEAD.
|
|
3. Confirm `demo-start` and `demo-complete` still peel to their pre-cleanup targets.
|
|
4. Push `feature/uups-bank-demo` normally with no force option.
|
|
5. Query Gitea PR #2 and require `state: open`, `base: main`, `head: feature/uups-bank-demo`, and `mergeable: true`.
|
|
6. Preserve the existing linked worktree for PR feedback.
|