From e856c77f0c07f8cf08835fc4ab5c5118d482225c Mon Sep 17 00:00:00 2001 From: golem Date: Tue, 25 Aug 2026 01:33:32 -0600 Subject: [PATCH] docs: plan superpowers artifact cleanup --- ...8-25-superpowers-artifact-ignore-policy.md | 240 ++++++++++++++++++ 1 file changed, 240 insertions(+) create mode 100644 docs/superpowers/plans/2026-08-25-superpowers-artifact-ignore-policy.md diff --git a/docs/superpowers/plans/2026-08-25-superpowers-artifact-ignore-policy.md b/docs/superpowers/plans/2026-08-25-superpowers-artifact-ignore-policy.md new file mode 100644 index 0000000..cdfae6f --- /dev/null +++ b/docs/superpowers/plans/2026-08-25-superpowers-artifact-ignore-policy.md @@ -0,0 +1,240 @@ +# 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.