jekyll-theme-zer0 0.22.22 → 1.0.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f5ef694da326e1ac7f10b1deed5494c749d5d28019158356306d07eec00b78dc
4
- data.tar.gz: 84efeba1948bc0a9e6f87fae10b6581febcb91725cfd241fdfb7a2977276d8e5
3
+ metadata.gz: eb0abcd4c89fc980be5dc8a2ca5d073a32e248d7bea194c9eb905bd02453f3b4
4
+ data.tar.gz: 156f5db5110105ad33e03d7e3be40ec8ff56f8d5cdab6c2cd5cdd8ababd190f2
5
5
  SHA512:
6
- metadata.gz: 63221ca36a87bea421089ce50e7b9556b94e9a5e4fd4e75e80f2493b0e4d51f24378dfa25b50033bc0cfb5fd8577da7f90c072d625197b9228d756b757539916
7
- data.tar.gz: 31c6b963de682056a37292e9467873bcae14803efea508432756fccd0176c0668c80e8045e7459d30ed5549ac97adc2a03d9f8bebc9d320423b7e2605482fe05
6
+ metadata.gz: bd44c6d89e293c8d03e6599ff58cb1cc568e0c9281d360ddc49300ef54b9eb56bc32d8e4508fad22b821b3782d87c6ed8a79c706faf65fbc1e9d1399869c16ac
7
+ data.tar.gz: b3823b150fccbcd91c52919686e9f904e28945f0e235e52b7d26b0a5407f51e562f682b3efbd2add0a3e30185c513b26070f1941029813bb15b65e9cf9b5445c
data/CHANGELOG.md CHANGED
@@ -1,18 +1,12 @@
1
1
  # Changelog
2
2
 
3
- ## [0.22.22] - 2026-04-21
3
+ ## [1.0.0] - 2026-04-20
4
4
 
5
- ### Changed
6
- - Version bump: patch release
5
+ First stable major release. Consolidates the breaking-change installer rewrite
6
+ (shipped in error as v0.22.22 due to a silent bug in the version analyzer) and
7
+ the fix that restored the release automation.
7
8
 
8
- ### Commits in this release
9
- - 36cd015 feat(installer)!: modular installer + AI + deploy targets + test matrix (#76)
10
- - 555bead docs(readme): add AI-native branding and GitHub Actions automation section
11
-
12
-
13
- ## [Unreleased — targeting 1.0.0]
14
-
15
- ### ⚠️ Breaking changes (1.0.0 prep)
9
+ ### ⚠️ Breaking changes
16
10
 
17
11
  - **Modular installer.** The 2,400-line monolithic `install.sh` is decomposed into a CLI dispatcher (`scripts/bin/install`) backed by focused library modules (`scripts/lib/install/*.sh`) and declarative YAML profiles (`templates/profiles/*.yml`). The legacy `curl | bash` one-liner still works — it bootstraps the same pipeline.
18
12
  - **Legacy mode flags deprecated.** `--full`, `--minimal`, `--fork`, `--remote`, `--github` continue to work in 1.0.x with a one-line deprecation warning. They map 1:1 to `install init --profile <name>`. Targeted removal: 2.0.
@@ -21,7 +15,9 @@
21
15
 
22
16
  See [`docs/installation/migration-from-0.x.md`](docs/installation/migration-from-0.x.md) for the full flag-by-flag mapping.
23
17
 
24
- ### Added (Phases 1-7 of the installer refactor)
18
+ ### Added
19
+
20
+ #### Modular installer (Phases 1-7 of the refactor)
25
21
 
26
22
  - **`scripts/bin/install`** — canonical CLI with subcommands: `init`, `wizard [--ai]`, `agents`, `deploy`, `doctor [--ai] [--quiet] [--json]`, `diagnose [--ai]`, `upgrade`, `list-profiles`, `list-targets`, `version`, `help`.
27
23
  - **`scripts/lib/install/`** — focused modules: `core`, `platform`, `template`, `fs`, `config`, `pages`, `profile`, `wizard_interactive`, `doctor`, `upgrade`, `agents`, `ai/{openai,wizard,diagnose,suggest}`, `deploy/{registry,github-pages,azure-swa,docker-prod}`. All bash 3.2 compatible.
@@ -34,27 +30,40 @@ See [`docs/installation/migration-from-0.x.md`](docs/installation/migration-from
34
30
  - **`install doctor`** — platform/tooling/site/AI health check with PASS/WARN/FAIL counters, `--quiet` and `--json` modes. Used as preflight in `install init` (opt out with `--skip-doctor`).
35
31
  - **`install upgrade`** — idempotent in-place upgrade tracked via `.zer0-installed`. `--from`, `--force`, `--dry-run`, `--auto-accept`. Refreshes agents and checks deploy-workflow drift.
36
32
  - **`docs/installation/`** — full doc tree: `index`, `architecture`, `profiles`, `deploy-targets`, `ai-features`, `migration-from-0.x`, `customization`.
37
- - **`.github/instructions/install.instructions.md`** — agent guidance for installer code (`applyTo: scripts/lib/install/**, scripts/bin/install, install.sh, templates/{profiles,deploy,agents,ai}/**`).
33
+ - **`.github/instructions/install.instructions.md`** — agent guidance for installer code.
38
34
  - **`.github/workflows/doctor.yml`** — CI matrix (ubuntu-latest, macos-latest) running `install doctor --json` on every push/PR touching installer code.
39
- - **`.github/workflows/install-matrix.yml`** — full installer e2e matrix (ubuntu-latest + macos-latest × ruby 2.7/3.0/3.2) plus a `curl|bash` bootstrap smoke job. Runs on installer-touching PRs, weekly drift schedule, and `workflow_dispatch`.
40
- - **Installer e2e suites** under `test/`:
41
- - `test_install_profiles.sh`every profile produces its expected file tree
42
- - `test_install_deploy.sh` — every deploy target writes valid workflow YAML / Dockerfile
43
- - `test_install_ai_mock.sh` `doctor --ai` and `diagnose` survive without `OPENAI_API_KEY`
44
- - `test_install_legacy_flags.sh` — `install.sh --minimal` / `--full` still produce expected layouts
45
- - `test_install_idempotency.sh` re-running install is safe; `_config.yml` stays parseable; backup creep guarded
46
- - **`scripts/bin/test install`** — new test-suite group that executes all `test/test_install_*.sh` files.
35
+ - **`.github/workflows/install-matrix.yml`** — full installer e2e matrix (ubuntu-latest + macos-latest × ruby 2.7/3.0/3.2) plus a `curl|bash` bootstrap smoke job.
36
+ - **Installer e2e suites** under `test/`: `test_install_profiles.sh`, `test_install_deploy.sh`, `test_install_ai_mock.sh`, `test_install_legacy_flags.sh`, `test_install_idempotency.sh`.
37
+ - **`scripts/bin/test install`** new test-suite group that executes all installer e2e tests.
38
+
39
+ #### Versioning & release automation (new in 1.0.0)
40
+
41
+ - New unit-test file `scripts/test/lib/test_analyze_commits.sh` (15 assertions) covering: scoped conventional types, `!` breaking-change marker, `BREAKING CHANGE` / `BREAKING-CHANGE` footers, and stdout/stderr separation. Wired into `scripts/test/lib/run_tests.sh`.
47
42
 
48
43
  ### Fixed
49
44
 
45
+ - **Versioning automation no longer silently swallows analyzer crashes.** `scripts/utils/analyze-commits` called `log_info` / `log_warning` / `log_debug` / `log_error` helpers that were never defined in `scripts/lib/common.sh`, causing the script to exit 127 with empty stdout. The version-bump workflow then fell back to `patch` via `2>/dev/null || echo "patch"`, which is exactly what shipped v0.22.22 instead of the intended v1.0.0 for the breaking-change installer rewrite (PR #76). The analyzer now defines stderr-only logging helpers, and the workflow refuses to publish on analyzer failure or invalid output.
46
+ - **Conventional Commits `!` breaking-change marker is now recognised.** `feat!:`, `fix(scope)!:`, and `refactor(api)!:` correctly trigger a major bump in both the version analyzer and changelog categoriser. Previously only the long-form `BREAKING CHANGE:` footer was detected.
47
+ - **Scoped types are recognised everywhere.** `feat(auth):`, `fix(api):`, `chore(deps):`, etc. are now properly classified by `analyze-commits` and grouped correctly in `changelog.sh`.
50
48
  - `install.sh` — `gh_args[@]: unbound variable` crash when invoking the github profile with no fork environment variables set (`set -u` + empty array). Guarded with `${gh_args[@]+"${gh_args[@]}"}`.
51
49
 
52
50
  ### Changed
53
51
 
52
+ - `scripts/utils/analyze-commits` now guarantees that **only** the bump type (`patch|minor|major|none`) is written to stdout. All progress and debug output is sent to stderr, so callers can safely use `BUMP=$(./analyze-commits ...)`.
53
+ - `.github/workflows/version-bump.yml` streams the analyzer's stderr into a collapsible job-log group and validates the returned bump type, failing the run with an annotated error if the analyzer crashes or returns garbage.
54
54
  - `README.md` Installation Methods section now references the modular CLI alongside the legacy one-liner.
55
55
  - `docs/FORKING.md` includes an `install init --profile fork` flow alongside the standalone `fork-cleanup.sh` script.
56
56
  - `AGENTS.md` instruction map adds the new install instructions row.
57
57
 
58
+ ## [0.22.22] - 2026-04-21
59
+
60
+ ### Changed
61
+ - Version bump: patch release
62
+
63
+ ### Commits in this release
64
+ - 36cd015 feat(installer)!: modular installer + AI + deploy targets + test matrix (#76)
65
+ - 555bead docs(readme): add AI-native branding and GitHub Actions automation section
66
+
58
67
  ## [0.22.21] - 2026-04-19
59
68
 
60
69
  ### Changed
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
  title: zer0-mistakes
3
3
  sub-title: AI-Native Jekyll Theme
4
4
  description: AI-native Jekyll theme for GitHub Pages — Docker-first development, AI-powered installation, multi-agent integration (Copilot, Codex, Cursor, Claude), AI preview-image generation, and AIEO content optimization with Bootstrap 5.3.
5
- version: 0.22.22
5
+ version: 1.0.0
6
6
  layout: landing
7
7
  tags:
8
8
  - jekyll
@@ -1066,7 +1066,7 @@ git push origin feature/awesome-feature
1066
1066
 
1067
1067
  | Metric | Value |
1068
1068
  |--------|-------|
1069
- | **Current Version** | 0.22.22 ([RubyGems](https://rubygems.org/gems/jekyll-theme-zer0), [CHANGELOG](/CHANGELOG)) |
1069
+ | **Current Version** | 1.0.0 ([RubyGems](https://rubygems.org/gems/jekyll-theme-zer0), [CHANGELOG](/CHANGELOG)) |
1070
1070
  | **Documented Features** | 43 ([Feature Registry](https://github.com/bamr87/zer0-mistakes/blob/main/_data/features.yml)) |
1071
1071
  | **Setup Time** | 2-5 minutes ([install.sh benchmarks](https://github.com/bamr87/zer0-mistakes/blob/main/install.sh)) |
1072
1072
  | **Documentation Pages** | 70+ ([browse docs](/pages/)) |
@@ -1117,6 +1117,6 @@ And these AI partners that make zer0-mistakes truly AI-native:
1117
1117
 
1118
1118
  **Built with ❤️ — and a little help from our AI partners — for the Jekyll community**
1119
1119
 
1120
- **v0.22.22** • [Changelog](CHANGELOG.md) • [License](LICENSE) • [Contributing](CONTRIBUTING.md) • [AI Agent Guide](AGENTS.md)
1120
+ **v1.0.0** • [Changelog](CHANGELOG.md) • [License](LICENSE) • [Contributing](CONTRIBUTING.md) • [AI Agent Guide](AGENTS.md)
1121
1121
 
1122
1122
 
@@ -28,50 +28,57 @@ categorize_commit() {
28
28
  local commit_full
29
29
  commit_full=$(get_commit_message "$commit_hash")
30
30
 
31
- if echo "$commit_full" | grep -qi "BREAKING CHANGE\|breaking:"; then
31
+ # Conventional Commits "BREAKING CHANGE:" / "BREAKING:" footer
32
+ if echo "$commit_full" | grep -qiE "^BREAKING[ -]CHANGE:|^BREAKING:"; then
32
33
  echo "breaking"
33
34
  return 0
34
35
  fi
35
36
 
36
- # Conventional commit patterns
37
+ # Conventional Commits "!" subject marker (e.g. feat!:, refactor(api)!:)
38
+ if echo "$subject" | grep -qE "^[a-zA-Z]+(\([^)]+\))?!:"; then
39
+ echo "breaking"
40
+ return 0
41
+ fi
42
+
43
+ # Conventional commit patterns (allow optional scope)
37
44
  case "$subject_lower" in
38
- feat:*|feature:*|add:*|new:*)
45
+ feat:*|feat\(*|feature:*|feature\(*|add:*|add\(*|new:*|new\(*)
39
46
  echo "added"
40
47
  ;;
41
- fix:*|bugfix:*|bug:*|patch:*)
48
+ fix:*|fix\(*|bugfix:*|bugfix\(*|bug:*|bug\(*|patch:*|patch\(*)
42
49
  echo "fixed"
43
50
  ;;
44
- perf:*|performance:*)
51
+ perf:*|perf\(*|performance:*|performance\(*)
45
52
  echo "changed"
46
53
  ;;
47
- refactor:*)
54
+ refactor:*|refactor\(*)
48
55
  echo "changed"
49
56
  ;;
50
- style:*)
57
+ style:*|style\(*)
51
58
  echo "changed"
52
59
  ;;
53
- docs:*|doc:*)
60
+ docs:*|docs\(*|doc:*|doc\(*)
54
61
  echo "changed"
55
62
  ;;
56
- test:*)
63
+ test:*|test\(*)
57
64
  echo "changed"
58
65
  ;;
59
- chore:*)
66
+ chore:*|chore\(*)
60
67
  echo "changed"
61
68
  ;;
62
- ci:*)
69
+ ci:*|ci\(*)
63
70
  echo "changed"
64
71
  ;;
65
- build:*)
72
+ build:*|build\(*)
66
73
  echo "changed"
67
74
  ;;
68
- revert:*|remove:*|delete:*)
75
+ revert:*|revert\(*|remove:*|remove\(*|delete:*|delete\(*)
69
76
  echo "removed"
70
77
  ;;
71
- deprecate:*|deprecated:*)
78
+ deprecate:*|deprecate\(*|deprecated:*|deprecated\(*)
72
79
  echo "deprecated"
73
80
  ;;
74
- security:*|sec:*)
81
+ security:*|security\(*|sec:*|sec\(*)
75
82
  echo "security"
76
83
  ;;
77
84
  *)
@@ -84,8 +91,8 @@ categorize_commit() {
84
91
  clean_commit_message() {
85
92
  local subject="$1"
86
93
 
87
- # Remove conventional commit prefix
88
- subject=$(echo "$subject" | sed -E 's/^(feat|feature|fix|bugfix|bug|patch|perf|performance|refactor|style|docs|doc|test|chore|ci|build|revert|remove|delete|deprecate|deprecated|security|sec)(\([^)]*\))?:\s*//')
94
+ # Remove conventional commit prefix (with optional scope and ! breaking marker)
95
+ subject=$(echo "$subject" | sed -E 's/^(feat|feature|fix|bugfix|bug|patch|perf|performance|refactor|style|docs|doc|test|chore|ci|build|revert|remove|delete|deprecate|deprecated|security|sec)(\([^)]*\))?!?:[[:space:]]*//')
89
96
 
90
97
  # Capitalize first letter
91
98
  subject="$(echo "${subject:0:1}" | tr '[:lower:]' '[:upper:]')${subject:1}"
@@ -126,6 +126,7 @@ main() {
126
126
  source "$TEST_DIR/test_git.sh"
127
127
  source "$TEST_DIR/test_changelog.sh"
128
128
  source "$TEST_DIR/test_gem.sh"
129
+ source "$TEST_DIR/test_analyze_commits.sh"
129
130
 
130
131
  # Summary
131
132
  echo -e "\n${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
@@ -0,0 +1,109 @@
1
+ #!/bin/bash
2
+
3
+ # Unit tests for scripts/utils/analyze-commits
4
+ #
5
+ # These tests build a throwaway git repo per case so we can verify that:
6
+ # 1. The analyzer never crashes on its own log calls (regression test for
7
+ # the silent log_info bug that caused a v1.0.0 release to be published
8
+ # as a patch in v0.22.22).
9
+ # 2. Conventional Commits "!" breaking-change marker triggers a major bump.
10
+ # 3. Scoped types like `feat(scope):` are still recognised.
11
+ # 4. The analyzer writes ONLY the bump type to stdout (logs go to stderr),
12
+ # so callers like the version-bump workflow can rely on
13
+ # `BUMP=$(./analyze-commits ...)`.
14
+
15
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
16
+ ANALYZER="$(cd "$SCRIPT_DIR/../../utils" && pwd)/analyze-commits"
17
+
18
+ set +e
19
+
20
+ print_suite_header "analyze-commits"
21
+
22
+ # Helper: run analyzer in an isolated git repo containing one commit with the
23
+ # given subject (and optional body). Echoes the bump type from stdout only.
24
+ _analyzer_for_commit() {
25
+ local subject="$1"
26
+ local body="${2:-}"
27
+
28
+ local tmp
29
+ tmp=$(mktemp -d)
30
+ (
31
+ cd "$tmp" || exit 1
32
+ git init -q -b main 2>/dev/null || git init -q
33
+ git config user.email "test@example.com"
34
+ git config user.name "Test"
35
+ git config commit.gpgsign false
36
+ echo "seed" > seed.txt
37
+ git add seed.txt
38
+ git commit -q -m "chore: seed"
39
+ echo "change" > change.txt
40
+ git add change.txt
41
+ if [[ -n "$body" ]]; then
42
+ git commit -q -m "$subject" -m "$body"
43
+ else
44
+ git commit -q -m "$subject"
45
+ fi
46
+ # Run analyzer; capture stdout only (stderr goes to caller for debugging on failure)
47
+ "$ANALYZER" HEAD~1..HEAD 2>/dev/null
48
+ )
49
+ local rc=$?
50
+ rm -rf "$tmp"
51
+ return $rc
52
+ }
53
+
54
+ _run_case() {
55
+ local subject="$1"
56
+ local expected="$2"
57
+ local body="${3:-}"
58
+ local label="$4"
59
+
60
+ local actual
61
+ actual=$(_analyzer_for_commit "$subject" "$body")
62
+ assert_equals "$expected" "$actual" "$label"
63
+ }
64
+
65
+ echo "Testing conventional commit bump detection..."
66
+
67
+ _run_case "feat: add login" "minor" "" "feat: → minor"
68
+ _run_case "feat(auth): add login" "minor" "" "feat(scope): → minor"
69
+ _run_case "fix: handle null" "patch" "" "fix: → patch"
70
+ _run_case "fix(api): null guard" "patch" "" "fix(scope): → patch"
71
+ _run_case "chore: cleanup" "patch" "" "chore: → patch"
72
+ _run_case "docs(readme): typo" "patch" "" "docs(scope): → patch"
73
+ _run_case "ci(release): tweak" "patch" "" "ci(scope): → patch"
74
+
75
+ echo -e "\nTesting breaking-change detection..."
76
+
77
+ _run_case "feat!: drop legacy api" "major" "" "feat!: → major"
78
+ _run_case "feat(installer)!: modular rewrite" "major" "" "feat(scope)!: → major"
79
+ _run_case "refactor(api)!: rename endpoint" "major" "" "refactor(scope)!: → major"
80
+ _run_case "fix!: change return shape" "major" "" "fix!: → major"
81
+ _run_case "feat: redesign" "major" "BREAKING CHANGE: removes old config" "BREAKING CHANGE footer → major"
82
+ _run_case "feat: redesign" "major" "BREAKING-CHANGE: removes old config" "BREAKING-CHANGE footer → major"
83
+
84
+ echo -e "\nTesting stdout/stderr separation (regression for silent log_info bug)..."
85
+
86
+ # The whole point: with stderr discarded, stdout MUST be exactly one of
87
+ # patch|minor|major|none. If log helpers leak to stdout, this fails.
88
+ out=$(_analyzer_for_commit "feat: anything")
89
+ case "$out" in
90
+ patch|minor|major|none) assert_true "true" "stdout contains only the bump type" ;;
91
+ *) assert_true "false" "stdout contains only the bump type (got: '$out')" ;;
92
+ esac
93
+
94
+ # And with stderr captured we should also see log lines — proving they exist
95
+ # but go to the right stream.
96
+ tmp=$(mktemp -d)
97
+ (
98
+ cd "$tmp" || exit 1
99
+ git init -q -b main 2>/dev/null || git init -q
100
+ git config user.email "test@example.com"
101
+ git config user.name "Test"
102
+ git config commit.gpgsign false
103
+ echo seed > a; git add a; git commit -q -m "chore: seed"
104
+ echo x > b; git add b; git commit -q -m "feat: x"
105
+ "$ANALYZER" HEAD~1..HEAD 2>err.log >out.log
106
+ grep -qE "Analyzing|bump" err.log
107
+ ) && assert_true "true" "Logs are written to stderr" \
108
+ || assert_true "false" "Logs are written to stderr"
109
+ rm -rf "$tmp"
@@ -18,10 +18,17 @@ source "$LIB_DIR/common.sh"
18
18
  COMMIT_RANGE="${1:-HEAD~1..HEAD}"
19
19
  DEBUG=${DEBUG:-false}
20
20
 
21
- # Override debug function to use DEBUG flag
21
+ # ----------------------------------------------------------------------------
22
+ # IMPORTANT: stdout is reserved for the bump-type result (patch|minor|major|none).
23
+ # All log output MUST go to stderr or it will be captured by callers like the
24
+ # version-bump workflow that uses `BUMP_TYPE=$(./analyze-commits ...)`.
25
+ # ----------------------------------------------------------------------------
26
+ log_info() { echo -e "${BLUE}[INFO]${NC} $*" >&2; }
27
+ log_warning() { echo -e "${YELLOW}[WARN]${NC} $*" >&2; }
28
+ log_error() { echo -e "${RED}[ERROR]${NC} $*" >&2; }
22
29
  log_debug() {
23
- if [[ "$DEBUG" == "true" ]]; then
24
- debug "$1"
30
+ if [[ "$DEBUG" == "true" ]] || [[ "${VERBOSE:-false}" == "true" ]]; then
31
+ echo -e "${PURPLE}[DEBUG]${NC} $*" >&2
25
32
  fi
26
33
  }
27
34
 
@@ -38,14 +45,14 @@ analyze_commit() {
38
45
  log_debug "Analyzing commit: $commit_hash"
39
46
  log_debug "Message: $(echo "$commit_message" | head -1)"
40
47
 
41
- # Check for breaking changes (MAJOR)
42
- if echo "$commit_message" | grep -qi "BREAKING CHANGE\|breaking:"; then
48
+ # Check for breaking changes in body (MAJOR) — Conventional Commits spec
49
+ if echo "$commit_message" | grep -qiE "^BREAKING[ -]CHANGE:|^BREAKING:"; then
43
50
  echo "major"
44
51
  return 0
45
52
  fi
46
53
 
47
54
  # Check for major version indicators in commit message
48
- if echo "$commit_message" | grep -qE "^(major|MAJOR|breaking|BREAKING)[\s:]"; then
55
+ if echo "$commit_message" | grep -qE "^(major|MAJOR|breaking|BREAKING)[[:space:]:]"; then
49
56
  echo "major"
50
57
  return 0
51
58
  fi
@@ -53,32 +60,39 @@ analyze_commit() {
53
60
  # Check commit message patterns for conventional commits
54
61
  local subject_line=$(echo "$commit_message" | head -1)
55
62
 
63
+ # Conventional Commits "!" breaking-change marker (MAJOR)
64
+ # Matches: feat!:, fix!:, feat(scope)!:, refactor(api)!:, etc.
65
+ if echo "$subject_line" | grep -qE "^[a-zA-Z]+(\([^)]+\))?!:"; then
66
+ echo "major"
67
+ return 0
68
+ fi
69
+
56
70
  # MAJOR changes
57
- if echo "$subject_line" | grep -qE "^(revert|remove|delete)[\s:].*[Bb]reaking"; then
71
+ if echo "$subject_line" | grep -qE "^(revert|remove|delete)(\([^)]+\))?:.*[Bb]reaking"; then
58
72
  echo "major"
59
73
  return 0
60
74
  fi
61
75
 
62
- # MINOR changes (new features)
63
- if echo "$subject_line" | grep -qE "^(feat|feature|add|new)[\s:]"; then
76
+ # MINOR changes (new features) — supports optional scope, e.g. feat(api):
77
+ if echo "$subject_line" | grep -qE "^(feat|feature|add|new)(\([^)]+\))?:"; then
64
78
  echo "minor"
65
79
  return 0
66
80
  fi
67
81
 
68
82
  # MINOR changes - significant additions
69
- if echo "$subject_line" | grep -qE "^(enhance|improve|update)[\s:].*[Ff]eature"; then
83
+ if echo "$subject_line" | grep -qiE "^(enhance|improve|update)(\([^)]+\))?:.*feature"; then
70
84
  echo "minor"
71
85
  return 0
72
86
  fi
73
87
 
74
- # PATCH changes (bug fixes, small improvements)
75
- if echo "$subject_line" | grep -qE "^(fix|bug|patch|hotfix|chore|docs|style|refactor|test|perf)[\s:]"; then
88
+ # PATCH changes (bug fixes, small improvements) — supports optional scope
89
+ if echo "$subject_line" | grep -qE "^(fix|bug|patch|hotfix|chore|docs|style|refactor|test|perf|ci|build)(\([^)]+\))?:"; then
76
90
  echo "patch"
77
91
  return 0
78
92
  fi
79
93
 
80
94
  # PATCH changes - maintenance and small improvements
81
- if echo "$subject_line" | grep -qE "^(update|improve|enhance|optimize|clean)[\s:]"; then
95
+ if echo "$subject_line" | grep -qE "^(update|improve|enhance|optimize|clean)(\([^)]+\))?:"; then
82
96
  echo "patch"
83
97
  return 0
84
98
  fi
@@ -288,10 +302,16 @@ ENVIRONMENT:
288
302
  DEBUG=true # Enable debug output
289
303
 
290
304
  CONVENTIONAL COMMIT PATTERNS:
291
- feat:, feature:, add: → minor
292
- fix:, bug:, patch: patch
293
- BREAKING CHANGE, breaking: major
294
- chore:, docs:, style: patch
305
+ feat:, feature:, add: → minor
306
+ feat(scope): minor
307
+ fix:, bug:, patch: patch
308
+ feat!:, fix!:, refactor(api)!: major (Conventional Commits "!" marker)
309
+ BREAKING CHANGE:, BREAKING: → major (commit body footer)
310
+ chore:, docs:, style:, ci: → patch
311
+
312
+ OUTPUT CONTRACT:
313
+ Only the bump type is written to stdout. All progress/log output goes to
314
+ stderr so callers can safely use \`BUMP=\$(./analyze-commits ...)\`.
295
315
  EOF
296
316
  exit 0
297
317
  fi
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jekyll-theme-zer0
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.22.22
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Amr Abdel
@@ -421,6 +421,7 @@ files:
421
421
  - scripts/test/integration/auto-version
422
422
  - scripts/test/integration/mermaid
423
423
  - scripts/test/lib/run_tests.sh
424
+ - scripts/test/lib/test_analyze_commits.sh
424
425
  - scripts/test/lib/test_changelog.sh
425
426
  - scripts/test/lib/test_gem.sh
426
427
  - scripts/test/lib/test_git.sh