specweave 1.0.276 → 1.0.277

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "specweave",
3
- "version": "1.0.276",
3
+ "version": "1.0.277",
4
4
  "description": "Spec-driven development framework for AI coding agents. First-class support for Claude Code — compatible with any LLM-powered coding tool. Living documentation, autonomous execution, quality gates, and multilingual support (9 languages).",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -121,6 +121,7 @@ fi
121
121
 
122
122
  Operate on CWD as normal. Set:
123
123
  ```bash
124
+ UMBRELLA_ROOT=""
124
125
  PKG_DIR="."
125
126
  PKG_NAME=$(node -p "require('./package.json').name")
126
127
  PKG_VERSION=$(node -p "require('./package.json').version")
@@ -128,6 +129,10 @@ PKG_VERSION=$(node -p "require('./package.json').version")
128
129
 
129
130
  ### If umbrella repo (`UMBRELLA=true`)
130
131
 
132
+ ```bash
133
+ UMBRELLA_ROOT="$(pwd)"
134
+ ```
135
+
131
136
  Scan for all publishable npm packages:
132
137
 
133
138
  ```bash
@@ -417,6 +422,7 @@ gh release view "v$NEW_VERSION" --json tagName,url
417
422
  - Published to npmjs.org (explicit registry!)
418
423
  - Version commit + tag pushed to GitHub
419
424
  - **GitHub Release created with release notes**
425
+ - **Umbrella sync**: all sibling repos committed+pushed, umbrella repo committed+pushed
420
426
 
421
427
  ---
422
428
 
@@ -537,6 +543,7 @@ git push origin $BRANCH
537
543
  - Published to npmjs.org (explicit registry!)
538
544
  - Version commit pushed to GitHub
539
545
  - Tag NOT pushed (no GitHub Actions)
546
+ - **Umbrella sync**: all sibling repos committed+pushed, umbrella repo committed+pushed
540
547
 
541
548
  ---
542
549
 
@@ -785,6 +792,87 @@ fi
785
792
 
786
793
  ---
787
794
 
795
+ ## FINAL STEP: UMBRELLA SYNC (Multi-Repo) — RUNS AFTER EVERY MODE
796
+
797
+ **Skip this step ONLY for `--only --local` mode.** For ALL other modes, this runs as the very last step.
798
+
799
+ When operating inside an umbrella repo (`UMBRELLA=true` from Step 0), the release workflow only commits+pushes the **selected package repo**. But the umbrella typically has:
800
+ - **Sibling repos** with their own uncommitted/unpushed work
801
+ - **The umbrella repo itself** with `.specweave/` increments, docs, and config changes
802
+
803
+ **All of these must be synced.** Otherwise the user sees dirty files after the release.
804
+
805
+ ### Umbrella Sync Procedure
806
+
807
+ ```bash
808
+ # Save the release repo path
809
+ RELEASE_REPO_DIR="$PKG_DIR"
810
+
811
+ # Navigate to umbrella root
812
+ cd "$UMBRELLA_ROOT" # The original CWD where repositories/ was detected
813
+
814
+ # 1. Sync ALL sibling repos under repositories/
815
+ for repo_dir in repositories/*/*/; do
816
+ # Skip if no .git directory (not a git repo)
817
+ [ -d "$repo_dir/.git" ] || continue
818
+
819
+ # Skip the repo we already released (already pushed)
820
+ [ "$(cd "$repo_dir" && pwd)" = "$(cd "$RELEASE_REPO_DIR" && pwd)" ] && continue
821
+
822
+ cd "$repo_dir"
823
+ REPO_NAME=$(basename "$repo_dir")
824
+ REPO_BRANCH=$(git rev-parse --abbrev-ref HEAD)
825
+
826
+ # Check for dirty files
827
+ if [ -n "$(git status --porcelain)" ]; then
828
+ git add -A
829
+ git commit -m "sync $REPO_NAME changes"
830
+ echo "Committed dirty changes in $REPO_NAME"
831
+ fi
832
+
833
+ # Check for unpushed commits
834
+ AHEAD=$(git rev-list @{u}..HEAD --count 2>/dev/null || echo "0")
835
+ if [ "$AHEAD" -gt 0 ]; then
836
+ git push origin "$REPO_BRANCH"
837
+ echo "Pushed $AHEAD commit(s) in $REPO_NAME -> $REPO_BRANCH"
838
+ fi
839
+
840
+ cd "$UMBRELLA_ROOT"
841
+ done
842
+
843
+ # 2. Sync the umbrella repo itself
844
+ if [ -d ".git" ]; then
845
+ if [ -n "$(git status --porcelain)" ]; then
846
+ git add -A
847
+ git commit -m "sync umbrella after release"
848
+ fi
849
+
850
+ UMBRELLA_BRANCH=$(git rev-parse --abbrev-ref HEAD)
851
+ AHEAD=$(git rev-list @{u}..HEAD --count 2>/dev/null || echo "0")
852
+ if [ "$AHEAD" -gt 0 ]; then
853
+ git push origin "$UMBRELLA_BRANCH"
854
+ echo "Pushed umbrella repo -> $UMBRELLA_BRANCH"
855
+ fi
856
+ fi
857
+ ```
858
+
859
+ ### Report Sync Results
860
+
861
+ After syncing, append to the release report:
862
+
863
+ ```markdown
864
+ **Umbrella sync**:
865
+ - [repo-name]: [committed N files | already clean] + [pushed N commits | up to date]
866
+ - ... (one line per repo)
867
+ - umbrella: [committed N files | already clean] + [pushed | up to date]
868
+ ```
869
+
870
+ ### When NOT in an umbrella (`UMBRELLA=false`)
871
+
872
+ Skip this step entirely — there's only one repo and it was already pushed.
873
+
874
+ ---
875
+
788
876
  ## Quick Reference
789
877
 
790
878
  ```bash
@@ -807,11 +895,11 @@ fi
807
895
  /sw:npm --stable
808
896
  ```
809
897
 
810
- | Scenario | Command | Prerelease Handling | Git Pushed | Tag Pushed | GH Release |
811
- |----------|---------|---------------------|------------|------------|------------|
812
- | **FULL RELEASE** | (no flags) | `rc.1`->`rc.2` (smart) | Yes | Yes | Yes |
813
- | **QUICK RELEASE** | `--quick` | `rc.1`->`rc.2` (smart) | Yes | No | No |
814
- | CI release | `--ci` | `rc.1`->`rc.2` (smart) | Yes | Yes | Yes (via CI) |
815
- | Local publish | `--only` | `rc.1`->`rc.2` (smart) | No | No | No |
816
- | Local bump | `--only --local` | `rc.1`->`rc.2` (smart) | No | No | No |
817
- | **PROMOTE** | `--stable` | `rc.X`->`X.Y.Z+1` | Yes | Yes | Yes |
898
+ | Scenario | Command | Prerelease Handling | Git Pushed | Tag Pushed | GH Release | Umbrella Sync |
899
+ |----------|---------|---------------------|------------|------------|------------|---------------|
900
+ | **FULL RELEASE** | (no flags) | `rc.1`->`rc.2` (smart) | Yes | Yes | Yes | Yes |
901
+ | **QUICK RELEASE** | `--quick` | `rc.1`->`rc.2` (smart) | Yes | No | No | Yes |
902
+ | CI release | `--ci` | `rc.1`->`rc.2` (smart) | Yes | Yes | Yes (via CI) | Yes |
903
+ | Local publish | `--only` | `rc.1`->`rc.2` (smart) | No | No | No | Yes |
904
+ | Local bump | `--only --local` | `rc.1`->`rc.2` (smart) | No | No | No | No |
905
+ | **PROMOTE** | `--stable` | `rc.X`->`X.Y.Z+1` | Yes | Yes | Yes | Yes |
@@ -121,6 +121,7 @@ fi
121
121
 
122
122
  Operate on CWD as normal. Set:
123
123
  ```bash
124
+ UMBRELLA_ROOT=""
124
125
  PKG_DIR="."
125
126
  PKG_NAME=$(node -p "require('./package.json').name")
126
127
  PKG_VERSION=$(node -p "require('./package.json').version")
@@ -128,6 +129,10 @@ PKG_VERSION=$(node -p "require('./package.json').version")
128
129
 
129
130
  ### If umbrella repo (`UMBRELLA=true`)
130
131
 
132
+ ```bash
133
+ UMBRELLA_ROOT="$(pwd)"
134
+ ```
135
+
131
136
  Scan for all publishable npm packages:
132
137
 
133
138
  ```bash
@@ -736,6 +741,87 @@ Show the user:
736
741
 
737
742
  ---
738
743
 
744
+ ## FINAL STEP: UMBRELLA SYNC (Multi-Repo) — RUNS AFTER EVERY MODE
745
+
746
+ **Skip this step ONLY for `--only --local` mode.** For ALL other modes, this runs as the very last step.
747
+
748
+ When operating inside an umbrella repo (`UMBRELLA=true` from Step 0), the release workflow only commits+pushes the **selected package repo**. But the umbrella typically has:
749
+ - **Sibling repos** with their own uncommitted/unpushed work
750
+ - **The umbrella repo itself** with `.specweave/` increments, docs, and config changes
751
+
752
+ **All of these must be synced.** Otherwise the user sees dirty files after the release.
753
+
754
+ ### Umbrella Sync Procedure
755
+
756
+ ```bash
757
+ # Save the release repo path
758
+ RELEASE_REPO_DIR="$PKG_DIR"
759
+
760
+ # Navigate to umbrella root
761
+ cd "$UMBRELLA_ROOT" # The original CWD where repositories/ was detected
762
+
763
+ # 1. Sync ALL sibling repos under repositories/
764
+ for repo_dir in repositories/*/*/; do
765
+ # Skip if no .git directory (not a git repo)
766
+ [ -d "$repo_dir/.git" ] || continue
767
+
768
+ # Skip the repo we already released (already pushed)
769
+ [ "$(cd "$repo_dir" && pwd)" = "$(cd "$RELEASE_REPO_DIR" && pwd)" ] && continue
770
+
771
+ cd "$repo_dir"
772
+ REPO_NAME=$(basename "$repo_dir")
773
+ REPO_BRANCH=$(git rev-parse --abbrev-ref HEAD)
774
+
775
+ # Check for dirty files
776
+ if [ -n "$(git status --porcelain)" ]; then
777
+ git add -A
778
+ git commit -m "sync $REPO_NAME changes"
779
+ echo "Committed dirty changes in $REPO_NAME"
780
+ fi
781
+
782
+ # Check for unpushed commits
783
+ AHEAD=$(git rev-list @{u}..HEAD --count 2>/dev/null || echo "0")
784
+ if [ "$AHEAD" -gt 0 ]; then
785
+ git push origin "$REPO_BRANCH"
786
+ echo "Pushed $AHEAD commit(s) in $REPO_NAME -> $REPO_BRANCH"
787
+ fi
788
+
789
+ cd "$UMBRELLA_ROOT"
790
+ done
791
+
792
+ # 2. Sync the umbrella repo itself
793
+ if [ -d ".git" ]; then
794
+ if [ -n "$(git status --porcelain)" ]; then
795
+ git add -A
796
+ git commit -m "sync umbrella after release"
797
+ fi
798
+
799
+ UMBRELLA_BRANCH=$(git rev-parse --abbrev-ref HEAD)
800
+ AHEAD=$(git rev-list @{u}..HEAD --count 2>/dev/null || echo "0")
801
+ if [ "$AHEAD" -gt 0 ]; then
802
+ git push origin "$UMBRELLA_BRANCH"
803
+ echo "Pushed umbrella repo -> $UMBRELLA_BRANCH"
804
+ fi
805
+ fi
806
+ ```
807
+
808
+ ### Report Sync Results
809
+
810
+ After syncing, append to the release report:
811
+
812
+ ```markdown
813
+ **Umbrella sync**:
814
+ - [repo-name]: [committed N files | already clean] + [pushed N commits | up to date]
815
+ - ... (one line per repo)
816
+ - umbrella: [committed N files | already clean] + [pushed | up to date]
817
+ ```
818
+
819
+ ### When NOT in an umbrella (`UMBRELLA=false`)
820
+
821
+ Skip this step entirely — there's only one repo and it was already pushed.
822
+
823
+ ---
824
+
739
825
  ## Quick Reference
740
826
 
741
827
  ```bash
@@ -758,14 +844,14 @@ Show the user:
758
844
  /sw-release:npm --stable
759
845
  ```
760
846
 
761
- | Scenario | Command | Prerelease Handling | Git Pushed | Tag Pushed | GH Release |
762
- |----------|---------|---------------------|------------|------------|------------|
763
- | **FULL RELEASE** | (no flags) | `rc.1`→`rc.2` (smart) | ✅ Yes | ✅ Yes | ✅ Yes |
764
- | **QUICK RELEASE** | `--quick` | `rc.1`→`rc.2` (smart) | ✅ Yes | ❌ No | ❌ No |
765
- | CI release | `--ci` | `rc.1`→`rc.2` (smart) | ✅ Yes | ✅ Yes | ✅ (via CI) |
766
- | Local publish | `--only` | `rc.1`→`rc.2` (smart) | ❌ No | ❌ No | ❌ No |
767
- | Local bump | `--only --local` | `rc.1`→`rc.2` (smart) | ❌ No | ❌ No | ❌ No |
768
- | **PROMOTE** | `--stable` | `rc.X`→`X.Y.Z+1` | ✅ Yes | ✅ Yes | ✅ Yes |
847
+ | Scenario | Command | Prerelease Handling | Git Pushed | Tag Pushed | GH Release | Umbrella Sync |
848
+ |----------|---------|---------------------|------------|------------|------------|---------------|
849
+ | **FULL RELEASE** | (no flags) | `rc.1`→`rc.2` (smart) | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes |
850
+ | **QUICK RELEASE** | `--quick` | `rc.1`→`rc.2` (smart) | ✅ Yes | ❌ No | ❌ No | ✅ Yes |
851
+ | CI release | `--ci` | `rc.1`→`rc.2` (smart) | ✅ Yes | ✅ Yes | ✅ (via CI) | ✅ Yes |
852
+ | Local publish | `--only` | `rc.1`→`rc.2` (smart) | ❌ No | ❌ No | ❌ No | ✅ Yes |
853
+ | Local bump | `--only --local` | `rc.1`→`rc.2` (smart) | ❌ No | ❌ No | ❌ No | ❌ No |
854
+ | **PROMOTE** | `--stable` | `rc.X`→`X.Y.Z+1` | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes |
769
855
 
770
856
  ---
771
857