diff --git a/.claude/skills/git-feature-commit/SKILL.md b/.claude/skills/git-feature-commit/SKILL.md index 1b1bd14..f11a156 100644 --- a/.claude/skills/git-feature-commit/SKILL.md +++ b/.claude/skills/git-feature-commit/SKILL.md @@ -1,11 +1,11 @@ --- name: git-feature-commit -description: Commit staged + unstaged work across all 3 repos. Submodules first (kicad, wxwidgets), then root with submodule pointer bumps. Asks the user to approve each commit separately and shows the pointer diff for the root commit. Usage - "/git-feature-commit [message]". +description: Commit staged + unstaged work across all 4 repos. Submodules first (kicad, wxwidgets, pcbjam-shared), then root with submodule pointer bumps. Asks the user to approve each commit separately and shows the pointer diff for the root commit. Usage - "/git-feature-commit [message]". --- # git-feature-commit -Commit work-in-progress across root + kicad + wxwidgets in the correct order: **submodules first, then root** (so the root commit captures the new submodule pointers). +Commit work-in-progress across root + kicad + wxwidgets + pcbjam-shared in the correct order: **submodules first, then root** (so the root commit captures the new submodule pointers). ## Arguments @@ -20,7 +20,7 @@ Optional positional message string. If omitted, ask the user for a message via ` - `git -C diff --stat HEAD` so the user sees the full picture before being asked to commit anything. -3. **Submodule commits — kicad first, then wxwidgets.** For each submodule: +3. **Submodule commits — kicad, then wxwidgets, then pcbjam-shared.** For each submodule: - If `git -C status --porcelain` is empty AND no staged changes, print "kicad: no changes, skipping" and continue. - Otherwise, prose-ask: "Commit kicad with message ``? Type `y`, `n`, or `edit` to change the message." - On `y`: `git -C add -A && git -C commit -m ""` (auto-allowed). @@ -28,12 +28,12 @@ Optional positional message string. If omitted, ask the user for a message via ` - On `n`: skip and continue. 4. **Root commit (last).** After submodules: - - Stage submodule pointer bumps explicitly: `git -C add kicad wxwidgets` (only stages the gitlink pointer change if a submodule has a new HEAD). - - Stage other root changes: `git -C add -A -- ':!kicad' ':!wxwidgets' ':!features'` (exclude submodule trees and features/ patch dir). + - Stage submodule pointer bumps explicitly: `git -C add kicad wxwidgets web/pcbjam-shared` (only stages the gitlink pointer change if a submodule has a new HEAD). + - Stage other root changes: `git -C add -A -- ':!kicad' ':!wxwidgets' ':!web/pcbjam-shared' ':!features'` (exclude submodule trees and features/ patch dir). - Check what's staged: `git -C diff --cached --stat`. If nothing is staged, print "root: no changes, skipping" and stop. - Show the user: - `git -C diff --cached --stat` (overview) - - `git -C diff --cached -- kicad wxwidgets` (the raw pointer-bump diff — the user wants to eyeball this every time) + - `git -C diff --cached -- kicad wxwidgets web/pcbjam-shared` (the raw pointer-bump diff — the user wants to eyeball this every time) - Prose-ask: "Commit root with message ``? `y`/`n`/`edit`." - On `y`: `git -C commit -m ""`. @@ -41,7 +41,7 @@ Optional positional message string. If omitted, ask the user for a message via ` ## Edge cases -- All 3 repos clean → print "nothing to commit anywhere" and stop. +- All repos clean → print "nothing to commit anywhere" and stop. - Only submodule changes, no other root changes → root commit still happens, but it'll only contain the pointer bumps. That's correct. - Only root changes (no sub changes) → just root commits, submodules skipped. - Submodule has commits but pointer was already bumped in a prior root commit → pointer add will be a no-op and that's fine. diff --git a/.claude/skills/git-feature-finish/SKILL.md b/.claude/skills/git-feature-finish/SKILL.md index 5b3bd8f..ac7a494 100644 --- a/.claude/skills/git-feature-finish/SKILL.md +++ b/.claude/skills/git-feature-finish/SKILL.md @@ -1,28 +1,28 @@ --- name: git-feature-finish -description: Merge the current feature branch back to main (fast-forward only) and push, across all 3 repos. Submodules first, then root - so the root push includes the merged submodule SHAs. Stops for confirmation at each merge and push. Usage - "/git-feature-finish". +description: Merge the current feature branch back to main (fast-forward only) and push, across all 4 repos. Submodules first (kicad, wxwidgets, pcbjam-shared), then root - so the root push includes the merged submodule SHAs. Stops for confirmation at each merge and push. Usage - "/git-feature-finish". --- # git-feature-finish Land the current feature branch into each repo's main and push. Uses `--ff-only` for clean linear history. -Per-repo main mapping is in `scripts/git-workflow/repos.sh` (root=`main`, subs=`wasm-port`). +Per-repo main mapping is in `scripts/git-workflow/repos.sh` (root=`main`, kicad/wxwidgets=`wasm-port`, pcbjam-shared=`main`). ## Pre-flight (all of these must pass before any merge happens) 1. **Fetch every origin FIRST.** Run `bash scripts/git-workflow/for-each-repo.sh fetch origin`. This is mandatory and must happen *before* the status snapshot. `repo-status.sh` derives `up_to_date_with_main` from the local `origin/
` ref **without fetching** — so without this step a repo whose origin has moved looks "up to date", check 5 passes, and the staleness is only discovered mid-merge (the `pull --ff-only` in the steps below would catch it, but then you've already merged the earlier repos). Fetching here makes the pre-flight STOP cleanly with "run `/git-feature-sync` first" instead of bailing partway through. 2. Run `bash scripts/git-workflow/repo-status.sh`. Parse the JSON. Because step 1 just fetched, `up_to_date_with_main` now reflects true remote state. -3. All 3 repos must have `dirty: false`. If any is dirty, STOP and tell the user to commit (`/git-feature-commit`) or stash first. -4. All 3 repos must be on the same feature branch (use root's branch as the reference). If not, STOP and report the mismatch. -5. All 3 repos must have `up_to_date_with_main: true` (i.e. the feature is rebased onto the latest main). If any isn't, STOP and instruct: "run `/git-feature-sync` first". +3. All 4 repos must have `dirty: false`. If any is dirty, STOP and tell the user to commit (`/git-feature-commit`) or stash first. +4. All 4 repos must be on the same feature branch (use root's branch as the reference). If not, STOP and report the mismatch. +5. All 4 repos must have `up_to_date_with_main: true` (i.e. the feature is rebased onto the latest main). If any isn't, STOP and instruct: "run `/git-feature-sync` first". 6. None may have `rebase_in_progress: true`. If so, STOP. -## Steps — order: kicad, wxwidgets, root +## Steps — order: kicad, wxwidgets, pcbjam-shared, root Submodules first so that when root checks out main and merges its feature branch, the pointer-bump commits land on root's main referencing the just-merged submodule mains. -For each repo in order [kicad, wxwidgets, root]: +For each repo in order [kicad, wxwidgets, pcbjam-shared, root]: 1. Skip if already merged: run `git -C branch --merged
` and check if the feature branch appears. If so, print ": feature already merged into
, skipping merge+push" and proceed to step 5 (branch delete prompt). @@ -39,12 +39,13 @@ For each repo in order [kicad, wxwidgets, root]: 5. **Prose-ask:** "Delete local feature branch `` in ?" - `git -C branch -d ` (hits `ask` permission). This is safe (`-d`, not `-D`) — git refuses if the branch isn't fully merged, which is exactly the safety we want. -## After all 3 repos done +## After all 4 repos done Report a summary table: ``` kicad: merged feature/foo into wasm-port, pushed (origin/wasm-port now at ), branch deleted wxwidgets: merged feature/foo into wasm-port, pushed (origin/wasm-port now at ), branch deleted +pcbjam-shared: merged feature/foo into main, pushed (origin/main now at ), branch deleted root: merged feature/foo into main, pushed (origin/main now at ), branch deleted ``` diff --git a/.claude/skills/git-feature-start/SKILL.md b/.claude/skills/git-feature-start/SKILL.md index f46ee04..576e172 100644 --- a/.claude/skills/git-feature-start/SKILL.md +++ b/.claude/skills/git-feature-start/SKILL.md @@ -1,16 +1,17 @@ --- name: git-feature-start -description: Create a new feature branch across all 3 repos (root + kicad + wxwidgets submodules). Fetches each repo's main, fast-forward pulls, and creates the same feature branch in each. Usage - "/git-feature-start ", e.g. "/git-feature-start feature/new-foo". +description: Create a new feature branch across all 4 repos (root + kicad + wxwidgets + pcbjam-shared submodules). Fetches each repo's main, fast-forward pulls, and creates the same feature branch in each. Usage - "/git-feature-start ", e.g. "/git-feature-start feature/new-foo". --- # git-feature-start -Create a new feature branch in all 3 repos (root, kicad submodule, wxwidgets submodule), based on each repo's main branch. +Create a new feature branch in all 4 repos (root, kicad, wxwidgets, and pcbjam-shared submodules), based on each repo's main branch. Per-repo main mapping (hardcoded in `scripts/git-workflow/repos.sh`): - root → `main` - kicad → `wasm-port` - wxwidgets → `wasm-port` +- pcbjam-shared (web/pcbjam-shared) → `main` ## Arguments @@ -20,11 +21,11 @@ If the user invoked the skill without a branch name, ask for one via `AskUserQue ## Steps -1. **Pre-flight: assert all 3 repos are clean.** Run `bash scripts/git-workflow/assert-clean.sh`. If it exits non-zero, STOP and tell the user which repos are dirty and that they need to commit, stash, or discard before starting a new feature. +1. **Pre-flight: assert all repos are clean.** Run `bash scripts/git-workflow/assert-clean.sh`. If it exits non-zero, STOP and tell the user which repos are dirty and that they need to commit, stash, or discard before starting a new feature. 2. **Pre-flight: check no repo is already on a non-main branch.** Run `bash scripts/git-workflow/repo-status.sh` and inspect each line's `branch` field. If any repo's `branch` is not its `main` (or is empty meaning detached HEAD), STOP and tell the user. Suggest: `/git-feature-sync` if they're already mid-feature, or manually checkout the main in that repo first. Do NOT silently switch off in-progress work. -3. **For each repo** in order [root, kicad, wxwidgets], run these commands. Echo what you're about to do in chat before each repo. +3. **For each repo** in order [root, kicad, wxwidgets, pcbjam-shared], run these commands. Echo what you're about to do in chat before each repo. - `git -C fetch origin` - `git -C checkout
` - `git -C pull --ff-only origin
` @@ -35,13 +36,14 @@ If the user invoked the skill without a branch name, ask for one via `AskUserQue root: created from main@ kicad: created from wasm-port@ wxwidgets: created from wasm-port@ + pcbjam-shared: created from main@ ``` 5. Suggest `/git-feature-commit` as the next step when the user has changes to record. ## Failure handling -If any step fails partway (e.g. checkout fails in wxwidgets after root and kicad succeeded), STOP and report exactly which repos already have the new branch and which don't. The user can manually finish or `/git-feature-finish` won't run until all 3 are aligned anyway. +If any step fails partway (e.g. checkout fails in wxwidgets after root and kicad succeeded), STOP and report exactly which repos already have the new branch and which don't. The user can manually finish or `/git-feature-finish` won't run until all 4 are aligned anyway. ## Safety diff --git a/.claude/skills/git-feature-sync/SKILL.md b/.claude/skills/git-feature-sync/SKILL.md index b5a606e..4ea0d34 100644 --- a/.claude/skills/git-feature-sync/SKILL.md +++ b/.claude/skills/git-feature-sync/SKILL.md @@ -1,13 +1,13 @@ --- name: git-feature-sync -description: Rebase the current feature branch onto main in all 3 repos (root + kicad + wxwidgets). Naturally re-runnable - after the user resolves a conflict manually and runs `git rebase --continue`, re-invoke the skill and it picks up where it stopped. Usage - "/git-feature-sync". +description: Rebase the current feature branch onto main in all 4 repos (root + kicad + wxwidgets + pcbjam-shared). Naturally re-runnable - after the user resolves a conflict manually and runs `git rebase --continue`, re-invoke the skill and it picks up where it stopped. Usage - "/git-feature-sync". --- # git-feature-sync -Rebase the current feature branch onto each repo's main, across root, kicad, and wxwidgets. +Rebase the current feature branch onto each repo's main, across root, kicad, wxwidgets, and pcbjam-shared. -Per-repo main mapping is in `scripts/git-workflow/repos.sh` (root=`main`, subs=`wasm-port`). +Per-repo main mapping is in `scripts/git-workflow/repos.sh` (root=`main`, kicad/wxwidgets=`wasm-port`, pcbjam-shared=`main`). ## How "resume after conflict" works @@ -30,15 +30,15 @@ So after the user resolves a conflict manually + runs `git rebase --continue` in - If branch is empty (detached), prose-ask: "wxwidgets is at detached HEAD ``. Want me to `git -C wxwidgets checkout ` first? (y/N)". On yes, run it (auto-allowed). On no, STOP. - If branch is some other name, STOP and tell the user which repo is on which branch. Don't auto-switch. -4. **Determine work plan.** For each repo, mark "needs rebase" if `up_to_date_with_main: false`. If all three are up-to-date, print "all 3 repos already up to date with their mains" and stop cleanly. +4. **Determine work plan.** For each repo, mark "needs rebase" if `up_to_date_with_main: false`. If all repos are up-to-date, print "all repos already up to date with their mains" and stop cleanly. -5. **Execute per repo** in order [root, kicad, wxwidgets]. Skip any repo with `up_to_date_with_main: true`. For each repo that needs rebase: +5. **Execute per repo** in order [root, kicad, wxwidgets, pcbjam-shared]. Skip any repo with `up_to_date_with_main: true`. For each repo that needs rebase: - Prose-announce: "About to rebase (``) onto `origin/
` — proceed?" - `git -C rebase origin/
` (origins were already fetched in step 1; this hits the `ask` permission — user confirms again at tool layer) - If the rebase command exits non-zero (conflict), STOP and emit the handoff message (see below). - On success, continue to the next repo. -6. **After all 3 succeed:** check `git -C status --short` for staged or unstaged changes to the `kicad` / `wxwidgets` submodule entries. If present, suggest: +6. **After all repos succeed:** check `git -C status --short` for staged or unstaged changes to the `kicad` / `wxwidgets` / `web/pcbjam-shared` submodule entries. If present, suggest: > Submodule SHAs changed during rebase. When ready: `/git-feature-commit "sync: bump submodule pointers after rebase"`. Do NOT auto-commit. diff --git a/scripts/git-workflow/assert-clean.sh b/scripts/git-workflow/assert-clean.sh index 26ec760..3c9fc14 100755 --- a/scripts/git-workflow/assert-clean.sh +++ b/scripts/git-workflow/assert-clean.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Exit 0 if all 3 repos are clean (no staged, no unstaged, no untracked files). +# Exit 0 if all repos are clean (no staged, no unstaged, no untracked files). # Exit 1 with a readable message listing the dirty repos otherwise. # Untracked files count as dirty - this is intentional: starting a new feature # while you have uncommitted new files is almost always a mistake. @@ -20,7 +20,7 @@ for repo in "${REPOS[@]}"; do done if [ ${#dirty[@]} -eq 0 ]; then - echo "All 3 repos clean." + echo "All ${#REPOS[@]} repos clean." exit 0 fi diff --git a/scripts/git-workflow/for-each-repo.sh b/scripts/git-workflow/for-each-repo.sh index f198dc2..7ff42b7 100755 --- a/scripts/git-workflow/for-each-repo.sh +++ b/scripts/git-workflow/for-each-repo.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Run a git command in each of the 3 repos. Echoes before each run. +# Run a git command in each repo of the 4-repo tree. Echoes before each run. # Usage: ./for-each-repo.sh # e.g. ./for-each-repo.sh status --short # ./for-each-repo.sh fetch origin diff --git a/scripts/git-workflow/repos.sh b/scripts/git-workflow/repos.sh index b7e187e..2affd2c 100755 --- a/scripts/git-workflow/repos.sh +++ b/scripts/git-workflow/repos.sh @@ -1,18 +1,28 @@ #!/bin/bash -# Sourced library. Single source of truth for the 3-repo layout. +# Sourced library. Single source of truth for the 4-repo layout: +# +# root = pcbjam main +# ├── kicad (kicad/) wasm-port +# ├── wxwidgets (wxwidgets/) wasm-port +# └── pcbjam-shared (web/pcbjam-shared/) main [MIT contract] +# +# Bash variable names can't contain '-', so pcbjam-shared's KEY is +# `pcbjam_shared`; its path/display name keep the dash. # Usage: source "$(dirname "$0")/repos.sh" ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" -REPOS=(root kicad wxwidgets) +REPOS=(root kicad wxwidgets pcbjam_shared) PATH_root="$ROOT_DIR" PATH_kicad="$ROOT_DIR/kicad" PATH_wxwidgets="$ROOT_DIR/wxwidgets" +PATH_pcbjam_shared="$ROOT_DIR/web/pcbjam-shared" MAIN_root="main" MAIN_kicad="wasm-port" MAIN_wxwidgets="wasm-port" +MAIN_pcbjam_shared="main" repo_path() { local var="PATH_$1"