# Folder + Repo Rename `scadalink-design` → `ScadaBridge` Implementation Plan

> **For Claude:** REQUIRED SUB-SKILL: Use superpowers-extended-cc:executing-plans to implement this plan task-by-task.

**Goal:** Rename the repo folder `~/Desktop/scadalink-design` → `~/Desktop/ScadaBridge`, rename the Gitea repository `dohertj2/scadalink-design` → `dohertj2/ScadaBridge`, and scrub every residual `scadalink`/`ScadaLink` reference inside the repo to its `ScadaBridge` equivalent.

**Architecture:** A scripted, most-specific-first `sed` pass over git-tracked text files does the content scrub; the folder rename is a plain OS `mv` (git tracks contents, not the repo-root directory name); the Gitea rename is a user web-UI action followed by a local `origin` URL update. Migration records (the prior rename tooling/design and the DB-rename helper) are carved out so their before→after meaning survives. Hard env-var cutover, no DB changes.

**Tech Stack:** bash 3.2 (macOS), BSD `sed -i ''`, git, `git grep`, dotnet (`ZB.MOM.WW.ScadaBridge.slnx`), docker compose.

**Design doc:** `docs/plans/2026-05-31-folder-repo-rename-scadabridge-design.md`

> **CRITICAL — path change after Task 0:** Task 0 moves the repo. From Task 1 onward, the repo root is `/Users/dohertj2/Desktop/ScadaBridge` (NOT `scadalink-design`). Every command below `cd`s there.

---

### Task 0: Safety checkpoint, clear the collision, move the folder

**Classification:** standard
**Estimated implement time:** ~3 min
**Parallelizable with:** none

**Files:** (filesystem operations only — no file edits)
- Move: `~/Desktop/ScadaBridge` → `~/Desktop/ScadaBridge-old`
- Move: `~/Desktop/scadalink-design` → `~/Desktop/ScadaBridge`

**Step 1: Confirm the working tree is clean and record the branch**

Run:
```bash
cd /Users/dohertj2/Desktop/scadalink-design && git status --short && git branch --show-current
```
Expected: no output from `git status --short` (clean tree) and a branch name (e.g. `main`). If there is uncommitted work, STOP and ask the user whether to commit or stash before proceeding.

**Step 2: Verify both move endpoints are safe**

Run:
```bash
ls -ld /Users/dohertj2/Desktop/ScadaBridge /Users/dohertj2/Desktop/ScadaBridge-old /Users/dohertj2/Desktop/scadalink-design 2>&1
```
Expected: `ScadaBridge` exists (the old non-git project), `scadalink-design` exists, and `ScadaBridge-old` does **not** exist (`No such file or directory`). If `ScadaBridge-old` already exists, STOP and ask the user for a different aside-name.

**Step 3: Move the existing ScadaBridge aside, then move the repo into place**

Run:
```bash
mv /Users/dohertj2/Desktop/ScadaBridge /Users/dohertj2/Desktop/ScadaBridge-old
mv /Users/dohertj2/Desktop/scadalink-design /Users/dohertj2/Desktop/ScadaBridge
```
Expected: no output (success).

**Step 4: Verify the move and that git still works in the new location**

Run:
```bash
cd /Users/dohertj2/Desktop/ScadaBridge && git status --short && git log --oneline -1
```
Expected: clean tree; the HEAD commit is the design-doc commit (`docs: add folder/repo rename design doc ...`). Confirms git history survived the folder move.

**Step 5: No commit** — filesystem moves are not git changes. Proceed to Task 1.

**Acceptance:** `~/Desktop/ScadaBridge` is the git repo (clean tree, intact history); `~/Desktop/ScadaBridge-old` holds the former non-git project; `~/Desktop/scadalink-design` no longer exists.

---

### Task 1: Create the scrub script

**Classification:** small
**Estimated implement time:** ~3 min
**Parallelizable with:** none

**Files:**
- Create: `/Users/dohertj2/Desktop/ScadaBridge/tools/scrub-scadalink-refs.sh`

**Step 1: Write the script**

Create `tools/scrub-scadalink-refs.sh` with exactly this content:

```bash
#!/usr/bin/env bash
# One-time scrub of residual ScadaLink/scadalink references → ScadaBridge.
# Operates on git-tracked TEXT files only (git grep -I skips binaries),
# minus carve-out migration records whose before→after meaning must survive.
# Substitutions are applied most-specific-first so a broad rule cannot
# double-replace an earlier result. Idempotent: re-running is a no-op.
set -euo pipefail
cd "$(git rev-parse --show-toplevel)"

# Carve-outs (migration records): prior rename tooling/design, the DB-rename
# helper, this script itself, and the two rename design docs.
EXCLUDES_RE='^(tools/rename-to-scadabridge\.sh|tools/scrub-scadalink-refs\.sh|docker/rename-databases\.sh|docs/plans/2026-05-28-scadabridge-rename-design\.md|docs/plans/2026-05-31-folder-repo-rename-scadabridge-design\.md)$'

files=()
while IFS= read -r f; do
  [[ "$f" =~ $EXCLUDES_RE ]] && continue
  files+=("$f")
done < <(git grep -liI 'scadalink' -- .)

if [[ ${#files[@]} -eq 0 ]]; then
  echo "No files to scrub."
  exit 0
fi

printf 'Scrubbing %d file(s):\n' "${#files[@]}"
printf '  %s\n' "${files[@]}"

sed -i '' \
  -e 's/ScadaLink\.Host\.exe/ZB.MOM.WW.ScadaBridge.Host.exe/g' \
  -e 's/ScadaLink__/ScadaBridge__/g' \
  -e 's/SCADALINK_/SCADABRIDGE_/g' \
  -e 's/scadaLinkVersion/scadaBridgeVersion/g' \
  -e 's/scadalink_app/scadabridge_app/g' \
  -e 's/ScadaLink/ScadaBridge/g' \
  -e 's/scadalink/scadabridge/g' \
  "${files[@]}"

echo "Done."
```

**Step 2: Make it executable**

Run:
```bash
cd /Users/dohertj2/Desktop/ScadaBridge && chmod +x tools/scrub-scadalink-refs.sh
```
Expected: no output.

**Step 3: Dry-run preview (list candidate files WITHOUT editing)**

Run:
```bash
cd /Users/dohertj2/Desktop/ScadaBridge && git grep -liI 'scadalink' -- . | grep -Ev '^(tools/rename-to-scadabridge\.sh|tools/scrub-scadalink-refs\.sh|docker/rename-databases\.sh|docs/plans/2026-05-28-scadabridge-rename-design\.md|docs/plans/2026-05-31-folder-repo-rename-scadabridge-design\.md)$'
```
Expected: a list of ~27 tracked source/config/test/doc files (the same set surfaced in the design doc), and NONE of the five carve-outs. No binary files (e.g. `site_events.db`) appear. If a carve-out appears, the script's `EXCLUDES_RE` is wrong — fix before running.

**Step 4: No commit yet** — the script is committed together with the scrub in Task 4.

**Acceptance:** `tools/scrub-scadalink-refs.sh` exists, is executable, and the dry-run lists only the intended files.

---

### Task 2: Run the scrub and pass the completeness gate

**Classification:** high-risk
**Estimated implement time:** ~3 min
**Parallelizable with:** none

**Files:** (the script edits ~27 tracked files in place; see Task 1 dry-run)

**Step 1: Run the scrub**

Run:
```bash
cd /Users/dohertj2/Desktop/ScadaBridge && bash tools/scrub-scadalink-refs.sh
```
Expected: `Scrubbing N file(s):` followed by the file list and `Done.`

**Step 2: Completeness gate — only the five carve-outs may still match**

Run:
```bash
cd /Users/dohertj2/Desktop/ScadaBridge && git grep -niI 'scadalink' -- . \
  ':!tools/rename-to-scadabridge.sh' \
  ':!tools/scrub-scadalink-refs.sh' \
  ':!docker/rename-databases.sh' \
  ':!docs/plans/2026-05-28-scadabridge-rename-design.md' \
  ':!docs/plans/2026-05-31-folder-repo-rename-scadabridge-design.md'
```
Expected: **no output** (zero hits outside the carve-outs). If any line prints, inspect it — it is either a new case variant the substitution list missed (add a rule and re-run) or a file that should have been carved out.

**Step 3: Sanity-check the new env-var names landed**

Run:
```bash
cd /Users/dohertj2/Desktop/ScadaBridge && git grep -nE 'SCADABRIDGE_CONFIG|ScadaBridge__|scadabridge_app|ZB\.MOM\.WW\.ScadaBridge\.Host\.exe' -- src/ deploy/ docker/ docker-env2/ | head
```
Expected: hits showing `SCADABRIDGE_CONFIG` in compose/Host, `ScadaBridge__` and `ZB.MOM.WW.ScadaBridge.Host.exe` in `deploy/wonder-app-vd03/install.ps1`.

**Step 4: Review the diff**

Run:
```bash
cd /Users/dohertj2/Desktop/ScadaBridge && git diff --stat
```
Expected: ~27 files changed, all content-only. Spot-check `git diff docker/docker-compose.yml src/ZB.MOM.WW.ScadaBridge.Host/Program.cs` shows clean `SCADALINK_` → `SCADABRIDGE_` swaps.

**Step 5: No commit yet** — commit after the build/test gate (Task 4).

**Acceptance:** completeness gate returns zero hits outside the five carve-outs; new names present in code/config; diff is content-only.

---

### Task 3: Build, run unit tests, fix any stragglers

**Classification:** standard
**Estimated implement time:** ~5 min
**Parallelizable with:** none

**Files:** (no planned edits; only stragglers surfaced by the build, if any)

**Step 1: Restore + build the solution**

Run:
```bash
cd /Users/dohertj2/Desktop/ScadaBridge && dotnet build ZB.MOM.WW.ScadaBridge.slnx 2>&1 | tail -20
```
Expected: `Build succeeded` with 0 errors. The scrub only renamed env-var string literals, a method parameter (`scadaLinkVersion` → `scadaBridgeVersion`), comments, and docs — no type/namespace changes — so the build should be clean. If an error appears (e.g. a parameter referenced by name elsewhere), fix that single reference and rebuild.

**Step 2: Run the CLI + Transport + ConfigurationDatabase unit tests (the projects whose code changed)**

Run:
```bash
cd /Users/dohertj2/Desktop/ScadaBridge && dotnet test tests/ZB.MOM.WW.ScadaBridge.CLI.Tests/ tests/ZB.MOM.WW.ScadaBridge.Transport.Tests/ 2>&1 | tail -25
```
Expected: all tests pass. These projects assert on the env-var name string literals (`SCADABRIDGE_FORMAT`, `SCADABRIDGE_USERNAME`, …) and the `scadaBridgeVersion` parameter — they were scrubbed in lockstep with the code, so they stay consistent. If a test references an env var the code no longer sets (or vice-versa), reconcile the pair.

**Step 3: No commit yet** — commit in Task 4.

**Acceptance:** `dotnet build` clean; the changed projects' unit tests green.

---

### Task 4: Commit the scrub

**Classification:** trivial
**Estimated implement time:** ~1 min
**Parallelizable with:** none

**Files:** (commit only)

**Step 1: Stage and commit**

Run:
```bash
cd /Users/dohertj2/Desktop/ScadaBridge && git add -A && git commit -m "refactor: scrub residual ScadaLink refs → ScadaBridge (env vars, config keys, assembly name, SQL login)

Renames the 13 SCADALINK_* runtime env vars → SCADABRIDGE_*, the ScadaLink__
.NET config keys → ScadaBridge__, the stale ScadaLink.Host.exe assembly name
→ ZB.MOM.WW.ScadaBridge.Host.exe, the scadalink_app SQL login → scadabridge_app,
and residual identifiers/comments/docs. Migration records (prior rename
tooling/design, DB-rename helper, this scrub script) carved out.

Adds tools/scrub-scadalink-refs.sh."
```
Expected: commit succeeds; `~28` files changed (the 27 scrubbed + the new script).

**Step 2: Verify**

Run:
```bash
cd /Users/dohertj2/Desktop/ScadaBridge && git log --oneline -2 && git status --short
```
Expected: the refactor commit on top of the design-doc commit; clean tree.

**Acceptance:** scrub committed; clean working tree.

---

### Task 5: Update the local Git remote after the Gitea web-UI rename

**Classification:** small
**Estimated implement time:** ~2 min
**Parallelizable with:** Task 6

**Files:** (git remote config only)

**Step 1: Manual gate — user renames the repo in the Gitea web UI**

Ask the user to rename the repository at `https://gitea.dohertylan.com/dohertj2/scadalink-design` to `ScadaBridge` via **Settings → Repository Name**, and to confirm when done. Do NOT proceed until confirmed.

**Step 2: Point `origin` at the new URL**

Run:
```bash
cd /Users/dohertj2/Desktop/ScadaBridge && git remote set-url origin https://gitea.dohertylan.com/dohertj2/ScadaBridge.git && git remote -v
```
Expected: both fetch and push lines show `.../dohertj2/ScadaBridge.git`.

**Step 3: Verify the remote is reachable and refs match**

Run:
```bash
cd /Users/dohertj2/Desktop/ScadaBridge && git ls-remote origin HEAD
```
Expected: prints a commit SHA for `HEAD` (auth via macOS keychain succeeds). If it fails with not-found, the web-UI rename has not propagated — re-confirm with the user.

**Step 4: Push the new commits**

Run:
```bash
cd /Users/dohertj2/Desktop/ScadaBridge && git push origin HEAD
```
Expected: push succeeds; the design-doc + scrub commits land on the renamed remote.

**Acceptance:** `origin` points at `dohertj2/ScadaBridge`; `git ls-remote` and `git push` succeed.

---

### Task 6: Runtime cutover — rebuild + redeploy so containers read the new env vars (conditional)

**Classification:** high-risk
**Estimated implement time:** ~5 min
**Parallelizable with:** Task 5

**Files:** (no edits — runtime only)

**Step 1: Check whether a stack is running**

Run:
```bash
docker ps --format '{{.Names}}' | grep -E 'scadabridge|central|site' || echo "no stack running"
```
Expected: either a list of running containers, or `no stack running`. **If `no stack running`, SKIP this task** — the new env-var names apply automatically on the next `bash docker/deploy.sh`. Note this to the user and mark the task done.

**Step 2: Rebuild the image and recreate the primary cluster**

Run:
```bash
cd /Users/dohertj2/Desktop/ScadaBridge && bash docker/deploy.sh 2>&1 | tail -30
```
Expected: image rebuilds; containers recreated. (`deploy.sh` already force-recreates.) Containers now receive `SCADABRIDGE_*` from the scrubbed `docker/docker-compose.yml`.

**Step 3: Recreate the second cluster (if it was running)**

Run:
```bash
cd /Users/dohertj2/Desktop/ScadaBridge && bash docker-env2/deploy.sh 2>&1 | tail -30
```
Expected: env2 cluster recreated from the scrubbed `docker-env2/docker-compose.yml`.

**Step 4: Smoke-test readiness + CLI**

Run:
```bash
sleep 20
curl -s http://localhost:9000/health/ready && echo
cd /Users/dohertj2/Desktop/ScadaBridge && dotnet run --project src/ZB.MOM.WW.ScadaBridge.CLI -- --username multi-role --password password template list 2>&1 | tail -15
```
Expected: `/health/ready` reports healthy; the CLI returns a template list (proves the Host read its config via the renamed `SCADABRIDGE_*` env vars). No DB rename/wipe is needed — database names are unchanged by this effort.

**Acceptance:** either the stack is confirmed not-running (skipped), or the redeployed cluster is healthy and the CLI smoke passes against the new env-var names.

---

## Execution Notes

- Tasks are strictly sequential 0 → 1 → 2 → 3 → 4, then 5 and 6 may run in parallel (both depend only on 4).
- The completeness gate in Task 2 and the build/test gate in Task 3 are the safety net for a missed reference.
- Rollback: `git reset --hard HEAD~1` (or `~2`) undoes the scrub commit; `mv` reverses the folder moves; `git remote set-url` reverts the remote.
