@nomad-e/bluma-cli 0.1.18 → 0.1.20

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.
Files changed (39) hide show
  1. package/dist/config/skills/git-commit/LICENSE.txt +18 -0
  2. package/dist/config/skills/git-commit/SKILL.md +258 -0
  3. package/dist/config/skills/git-commit/references/REFERENCE.md +249 -0
  4. package/dist/config/skills/git-commit/scripts/validate_commit_msg.py +163 -0
  5. package/dist/config/skills/git-pr/LICENSE.txt +18 -0
  6. package/dist/config/skills/git-pr/SKILL.md +293 -0
  7. package/dist/config/skills/git-pr/references/REFERENCE.md +256 -0
  8. package/dist/config/skills/git-pr/scripts/validate_commits.py +112 -0
  9. package/dist/config/skills/pdf/LICENSE.txt +26 -0
  10. package/dist/config/skills/pdf/SKILL.md +327 -0
  11. package/dist/config/skills/pdf/references/FORMS.md +69 -0
  12. package/dist/config/skills/pdf/references/REFERENCE.md +52 -0
  13. package/dist/config/skills/pdf/scripts/create_report.py +59 -0
  14. package/dist/config/skills/pdf/scripts/merge_pdfs.py +39 -0
  15. package/dist/config/skills/skill-creator/LICENSE.txt +26 -0
  16. package/dist/config/skills/skill-creator/SKILL.md +229 -0
  17. package/dist/config/skills/xlsx/LICENSE.txt +18 -0
  18. package/dist/config/skills/xlsx/SKILL.md +298 -0
  19. package/dist/config/skills/xlsx/references/REFERENCE.md +337 -0
  20. package/dist/config/skills/xlsx/scripts/office/__init__.py +2 -0
  21. package/dist/config/skills/xlsx/scripts/office/__pycache__/__init__.cpython-312.pyc +0 -0
  22. package/dist/config/skills/xlsx/scripts/office/__pycache__/pack.cpython-312.pyc +0 -0
  23. package/dist/config/skills/xlsx/scripts/office/__pycache__/soffice.cpython-312.pyc +0 -0
  24. package/dist/config/skills/xlsx/scripts/office/__pycache__/unpack.cpython-312.pyc +0 -0
  25. package/dist/config/skills/xlsx/scripts/office/__pycache__/validate.cpython-312.pyc +0 -0
  26. package/dist/config/skills/xlsx/scripts/office/pack.py +58 -0
  27. package/dist/config/skills/xlsx/scripts/office/soffice.py +180 -0
  28. package/dist/config/skills/xlsx/scripts/office/unpack.py +63 -0
  29. package/dist/config/skills/xlsx/scripts/office/validate.py +122 -0
  30. package/dist/config/skills/xlsx/scripts/recalc.py +143 -0
  31. package/dist/main.js +201 -50
  32. package/package.json +1 -1
  33. package/dist/config/example.bluma-mcp.json.txt +0 -14
  34. package/dist/config/models_config.json +0 -78
  35. package/dist/skills/git-conventional/LICENSE.txt +0 -3
  36. package/dist/skills/git-conventional/SKILL.md +0 -83
  37. package/dist/skills/skill-creator/SKILL.md +0 -495
  38. package/dist/skills/testing/LICENSE.txt +0 -3
  39. package/dist/skills/testing/SKILL.md +0 -114
@@ -0,0 +1,18 @@
1
+ BluMa — Base Language Unit · Model Agent
2
+ Proprietary License
3
+
4
+ Copyright (c) 2024-2026 BluMa Contributors
5
+
6
+ This skill is part of the BluMa CLI distribution.
7
+ It is provided as a bundled native skill and may not be
8
+ redistributed, modified, or used outside of the BluMa agent
9
+ framework without prior written permission.
10
+
11
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
12
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
13
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
14
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
15
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
16
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
17
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
18
+ OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,258 @@
1
+ ---
2
+ name: git-commit
3
+ description: >
4
+ Use this skill whenever the user asks to commit code, stage changes, write
5
+ a commit message, or finalize work. Triggers: "commit", "commit my changes",
6
+ "stage and commit", "save my work", "git commit", "write a commit message",
7
+ "commit this", "amend commit", or any request to record changes in Git
8
+ history. Do NOT use for pull requests — use git-pr instead.
9
+ license: Proprietary. LICENSE.txt has complete terms
10
+ ---
11
+
12
+ # Git Commit — Professional Workflow
13
+
14
+ ## Golden Rule
15
+
16
+ > Every commit tells a story. The subject says WHAT, the body says WHY,
17
+ > and the diff shows HOW. Never repeat the diff in the message.
18
+
19
+ ## Step 1 — Inspect the Working Tree
20
+
21
+ Before committing anything, understand the current state:
22
+
23
+ ```bash
24
+ git status --short
25
+ git diff --stat
26
+ ```
27
+
28
+ Identify which files belong to which logical change. If there are
29
+ unrelated changes, they MUST go into separate commits (see Atomic
30
+ Commits below).
31
+
32
+ ## Step 2 — Stage with Intent
33
+
34
+ Stage only the files that belong to ONE logical change:
35
+
36
+ ```bash
37
+ git add <file1> <file2>
38
+ ```
39
+
40
+ Use `git add -A` only when ALL changes belong to the same logical unit.
41
+
42
+ Review what is staged:
43
+
44
+ ```bash
45
+ git diff --staged
46
+ ```
47
+
48
+ Read the diff carefully. You need it to write an accurate message.
49
+
50
+ ## Step 3 — Determine the Commit Type
51
+
52
+ | Prefix | Meaning |
53
+ |------------|--------------------------------------------------|
54
+ | `feat` | New feature or user-facing capability |
55
+ | `fix` | Bug fix |
56
+ | `refactor` | Code restructuring, no behavior change |
57
+ | `docs` | Documentation only |
58
+ | `test` | Adding or updating tests |
59
+ | `perf` | Performance improvement |
60
+ | `style` | Formatting, whitespace, linting (no logic) |
61
+ | `chore` | Build, CI, dependencies, tooling |
62
+ | `security` | Security fix or hardening |
63
+ | `revert` | Reverting a previous commit |
64
+
65
+ ## Step 4 — Write the Commit Message
66
+
67
+ ### Format
68
+
69
+ ```
70
+ <type>(<scope>): <subject>
71
+
72
+ <body>
73
+
74
+ <footer>
75
+
76
+ Generated-by: BluMa — Base Language Unit · Model Agent
77
+ ```
78
+
79
+ ### Subject Line Rules
80
+
81
+ - Imperative mood: "add", "fix", "remove" (not "added", "fixes", "removed")
82
+ - Lowercase first letter after the colon
83
+ - No period at the end
84
+ - Maximum 72 characters
85
+ - Include scope when the change targets a specific module
86
+
87
+ Good examples:
88
+ ```
89
+ feat(auth): add JWT refresh token rotation
90
+ fix(parser): handle empty input without panic
91
+ refactor(db): extract connection pooling into module
92
+ docs(readme): add installation instructions for ARM64
93
+ chore(deps): bump openai SDK to v4.50.0
94
+ ```
95
+
96
+ Bad examples:
97
+ ```
98
+ Updated stuff # vague, no type, no scope
99
+ fix: Fixed the bug in auth module. # past tense, period, scope missing
100
+ feat(auth): Add JWT refresh token rotation for users to be able to
101
+ refresh their tokens automatically # too long, wraps
102
+ ```
103
+
104
+ ### Body Rules
105
+
106
+ - Leave ONE blank line between subject and body
107
+ - Explain WHY the change was needed, not WHAT changed
108
+ - Wrap at 72 characters
109
+ - Use bullet points for multiple reasons or details
110
+ - Reference design decisions or trade-offs if relevant
111
+
112
+ ### Footer Rules
113
+
114
+ - Reference issues: `Closes #123`, `Refs #456`, `Fixes #789`
115
+ - Note breaking changes: `BREAKING CHANGE: <description>`
116
+ - Co-authors: `Co-authored-by: Name <email>`
117
+
118
+ ### Watermark (MANDATORY)
119
+
120
+ The last line of every commit message MUST be:
121
+
122
+ ```
123
+ Generated-by: BluMa — Base Language Unit · Model Agent
124
+ ```
125
+
126
+ This provides auditability. No exceptions.
127
+
128
+ ## Step 5 — Execute the Commit
129
+
130
+ Use heredoc for clean multi-line messages:
131
+
132
+ ```bash
133
+ git commit -m "$(cat <<'EOF'
134
+ feat(skills): add git-commit skill for professional workflows
135
+
136
+ Introduce a dedicated skill that guides the agent through
137
+ Conventional Commits with proper subject, body, and footer
138
+ formatting. Ensures every commit carries the BluMa watermark
139
+ trailer for auditability.
140
+
141
+ - Atomic commit principles enforced
142
+ - Subject line validation (72 chars, imperative mood)
143
+ - Mandatory BluMa watermark trailer
144
+
145
+ Closes #55
146
+
147
+ Generated-by: BluMa — Base Language Unit · Model Agent
148
+ EOF
149
+ )"
150
+ ```
151
+
152
+ For simple single-line commits (rare, only for truly trivial changes):
153
+
154
+ ```bash
155
+ git commit -m "chore(deps): bump typescript to v5.5.0
156
+
157
+ Generated-by: BluMa — Base Language Unit · Model Agent"
158
+ ```
159
+
160
+ ## Step 6 — Verify
161
+
162
+ ```bash
163
+ git log -1 --format=fuller
164
+ ```
165
+
166
+ Confirm the message is well-formed and the watermark is present.
167
+
168
+ ## Atomic Commits
169
+
170
+ Each commit MUST represent exactly ONE logical change:
171
+
172
+ | Scenario | Commits |
173
+ |----------|---------|
174
+ | Added a feature + updated docs | 2 commits: `feat(...)` + `docs(...)` |
175
+ | Fixed a bug + added a test for it | 1 commit: `fix(...)` (test is part of the fix) |
176
+ | Renamed a variable across 10 files | 1 commit: `refactor(...)` |
177
+ | Fixed 2 unrelated bugs | 2 commits: `fix(...)` + `fix(...)` |
178
+ | New feature + refactored old code to support it | 2 commits: `refactor(...)` first, then `feat(...)` |
179
+
180
+ When in doubt: if you can describe the commit with "X and Y", it should
181
+ probably be two commits.
182
+
183
+ ## Handling Special Cases
184
+
185
+ ### Amending the Last Commit
186
+
187
+ Only amend if the commit has NOT been pushed:
188
+
189
+ ```bash
190
+ git add <forgotten-file>
191
+ git commit --amend --no-edit
192
+ ```
193
+
194
+ To change the message:
195
+
196
+ ```bash
197
+ git commit --amend -m "$(cat <<'EOF'
198
+ <corrected message>
199
+
200
+ Generated-by: BluMa — Base Language Unit · Model Agent
201
+ EOF
202
+ )"
203
+ ```
204
+
205
+ ### Empty Commits (for CI triggers)
206
+
207
+ ```bash
208
+ git commit --allow-empty -m "$(cat <<'EOF'
209
+ chore(ci): trigger pipeline rebuild
210
+
211
+ Generated-by: BluMa — Base Language Unit · Model Agent
212
+ EOF
213
+ )"
214
+ ```
215
+
216
+ ### Reverting a Commit
217
+
218
+ ```bash
219
+ git revert <hash> --no-edit
220
+ ```
221
+
222
+ Then amend to add context and watermark:
223
+
224
+ ```bash
225
+ git commit --amend -m "$(cat <<'EOF'
226
+ revert(auth): undo token expiry change
227
+
228
+ Reverts commit <hash>. The 30-minute expiry caused session drops
229
+ for users on slow connections. Reverting until a proper sliding
230
+ window solution is implemented.
231
+
232
+ Refs #130
233
+
234
+ Generated-by: BluMa — Base Language Unit · Model Agent
235
+ EOF
236
+ )"
237
+ ```
238
+
239
+ ## Quality Checklist
240
+
241
+ Before finalizing any commit, verify:
242
+
243
+ 1. Type prefix is correct for the change
244
+ 2. Scope accurately reflects the affected module
245
+ 3. Subject is imperative, lowercase, under 72 chars
246
+ 4. Body explains WHY (not WHAT)
247
+ 5. Footer references relevant issues
248
+ 6. Watermark `Generated-by: BluMa` is the last line
249
+ 7. Only related changes are included (atomic)
250
+ 8. No secrets, credentials, or .env files are staged
251
+
252
+ ## Available References
253
+
254
+ - REFERENCE.md: Advanced patterns (signed commits, co-authors, commit hooks, monorepo conventions, interactive rebase guidance)
255
+
256
+ ## Available Scripts
257
+
258
+ - validate_commit_msg.py: Validates a commit message string against Conventional Commits rules and BluMa watermark presence
@@ -0,0 +1,249 @@
1
+ # Git Commit — Advanced Patterns Reference
2
+
3
+ ## Signed Commits (GPG / SSH)
4
+
5
+ When the repository or organization requires signed commits:
6
+
7
+ ```bash
8
+ git commit -S -m "$(cat <<'EOF'
9
+ feat(auth): add PKCE support for OAuth2
10
+
11
+ <body>
12
+
13
+ Generated-by: BluMa — Base Language Unit · Model Agent
14
+ EOF
15
+ )"
16
+ ```
17
+
18
+ Verify signature:
19
+
20
+ ```bash
21
+ git log --show-signature -1
22
+ ```
23
+
24
+ Note: BluMa should NOT configure GPG keys. If signing fails, inform the
25
+ user that they need to set up `user.signingkey` in their git config.
26
+
27
+ ## Co-authored Commits
28
+
29
+ When the commit includes contributions from multiple people, add
30
+ co-author trailers BEFORE the BluMa watermark:
31
+
32
+ ```
33
+ feat(ui): redesign settings page layout
34
+
35
+ Implement the new card-based layout for the settings page as
36
+ discussed in the design review.
37
+
38
+ Co-authored-by: Maria Silva <maria@example.com>
39
+ Co-authored-by: João Santos <joao@example.com>
40
+
41
+ Generated-by: BluMa — Base Language Unit · Model Agent
42
+ ```
43
+
44
+ The BluMa watermark ALWAYS goes last.
45
+
46
+ ## Monorepo Commit Conventions
47
+
48
+ In monorepos, the scope should reflect the package path:
49
+
50
+ ```
51
+ feat(packages/auth): add session management
52
+ fix(apps/web): correct routing for nested layouts
53
+ chore(packages/shared-types): export AuthConfig interface
54
+ ```
55
+
56
+ For changes that span multiple packages, use the most specific common
57
+ ancestor as scope:
58
+
59
+ ```
60
+ refactor(packages): standardize error handling across all packages
61
+ ```
62
+
63
+ If there is no common ancestor, use no scope and list affected packages
64
+ in the body:
65
+
66
+ ```
67
+ chore: update TypeScript to v5.5 across all packages
68
+
69
+ Affected packages:
70
+ - packages/auth
71
+ - packages/api
72
+ - apps/web
73
+ - apps/mobile
74
+ ```
75
+
76
+ ## Commit Message Templates by Type
77
+
78
+ ### feat — New Feature
79
+
80
+ ```
81
+ feat(<scope>): <what the feature does>
82
+
83
+ <Why this feature is needed. What problem it solves for users.
84
+ Mention any design decisions or alternatives considered.>
85
+
86
+ - <Implementation detail 1>
87
+ - <Implementation detail 2>
88
+
89
+ Closes #<issue>
90
+
91
+ Generated-by: BluMa — Base Language Unit · Model Agent
92
+ ```
93
+
94
+ ### fix — Bug Fix
95
+
96
+ ```
97
+ fix(<scope>): <what was broken and how it's fixed>
98
+
99
+ <Root cause analysis. What was happening, why, and how this
100
+ commit prevents it from recurring.>
101
+
102
+ Steps to reproduce (before fix):
103
+ 1. <step>
104
+ 2. <step>
105
+ 3. <observe bug>
106
+
107
+ Fixes #<issue>
108
+
109
+ Generated-by: BluMa — Base Language Unit · Model Agent
110
+ ```
111
+
112
+ ### refactor — Code Restructuring
113
+
114
+ ```
115
+ refactor(<scope>): <what was restructured>
116
+
117
+ <Why the refactoring was necessary. What becomes easier or
118
+ cleaner as a result. Confirm no behavior change.>
119
+
120
+ No functional changes. All existing tests pass unchanged.
121
+
122
+ Generated-by: BluMa — Base Language Unit · Model Agent
123
+ ```
124
+
125
+ ### perf — Performance Improvement
126
+
127
+ ```
128
+ perf(<scope>): <what was optimized>
129
+
130
+ <Before/after metrics if available. What bottleneck was
131
+ identified and how it was resolved.>
132
+
133
+ Benchmark results:
134
+ - Before: <metric>
135
+ - After: <metric>
136
+ - Improvement: <percentage>
137
+
138
+ Generated-by: BluMa — Base Language Unit · Model Agent
139
+ ```
140
+
141
+ ### security — Security Fix
142
+
143
+ ```
144
+ security(<scope>): <what vulnerability was addressed>
145
+
146
+ <Nature of the vulnerability (without exposing exploit details).
147
+ Severity level and impact assessment.>
148
+
149
+ Severity: Critical / High / Medium / Low
150
+ CVE: <if applicable>
151
+
152
+ Generated-by: BluMa — Base Language Unit · Model Agent
153
+ ```
154
+
155
+ ## Interactive Rebase Guidance
156
+
157
+ BluMa should NEVER run `git rebase -i` automatically (it requires
158
+ interactive input). Instead, suggest it to the user:
159
+
160
+ ```
161
+ I recommend squashing the last 3 commits before pushing.
162
+ You can run:
163
+
164
+ git rebase -i HEAD~3
165
+
166
+ In the editor, change "pick" to "squash" (or "s") for the
167
+ commits you want to combine. Keep the first one as "pick".
168
+ ```
169
+
170
+ ### When to Suggest Squashing
171
+
172
+ - Multiple "WIP" or "fix typo" commits
173
+ - Commits that undo then redo the same change
174
+ - A series of small fixes that logically belong together
175
+
176
+ ### When NOT to Suggest Squashing
177
+
178
+ - Each commit represents a distinct, meaningful change
179
+ - The commit history tells a useful story for reviewers
180
+ - Different commits touch completely different areas
181
+
182
+ ## Commit Hooks Awareness
183
+
184
+ BluMa should be aware that repositories may have commit hooks:
185
+
186
+ - **pre-commit**: Runs linters, formatters, tests before commit
187
+ - **commit-msg**: Validates commit message format
188
+ - **prepare-commit-msg**: Prepopulates commit message
189
+
190
+ If a commit fails due to a hook:
191
+
192
+ 1. Read the hook's error output carefully
193
+ 2. Fix the issue (formatting, linting, etc.)
194
+ 3. Stage the fixes
195
+ 4. Create a NEW commit (do NOT use --no-verify)
196
+
197
+ BluMa should NEVER use `--no-verify` to bypass hooks unless the user
198
+ explicitly requests it.
199
+
200
+ ## Handling Large Changesets
201
+
202
+ If the staged changes are too large for a single atomic commit:
203
+
204
+ 1. Use `git add -p` guidance (suggest to the user, don't run interactively)
205
+ 2. Break the work into logical stages
206
+ 3. Commit each stage separately
207
+
208
+ Suggested approach for the user:
209
+
210
+ ```
211
+ The staged changes touch 3 different concerns. I recommend
212
+ splitting this into separate commits:
213
+
214
+ 1. First, stage only the refactoring:
215
+ git add src/utils/helpers.ts src/utils/format.ts
216
+ git commit -m "refactor(utils): extract formatting helpers"
217
+
218
+ 2. Then stage the new feature:
219
+ git add src/features/export.ts src/features/export.test.ts
220
+ git commit -m "feat(export): add CSV export for reports"
221
+
222
+ 3. Finally, the documentation:
223
+ git add docs/export.md README.md
224
+ git commit -m "docs(export): add CSV export usage guide"
225
+ ```
226
+
227
+ ## Branch-Aware Commit Messages
228
+
229
+ When committing on feature branches, the scope can optionally mirror
230
+ the branch topic:
231
+
232
+ ```
233
+ Branch: feature/user-onboarding
234
+ Commit: feat(onboarding): add email verification step
235
+ ```
236
+
237
+ For hotfix branches, always include urgency context:
238
+
239
+ ```
240
+ Branch: hotfix/auth-crash
241
+ Commit: fix(auth): prevent null dereference on expired tokens
242
+
243
+ This is a production hotfix. The null check was missing when
244
+ the token cache returns undefined for expired entries.
245
+
246
+ Fixes #789
247
+
248
+ Generated-by: BluMa — Base Language Unit · Model Agent
249
+ ```
@@ -0,0 +1,163 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Validate a commit message against Conventional Commits format
4
+ and BluMa watermark requirements.
5
+
6
+ Usage:
7
+ python validate_commit_msg.py "<commit message>"
8
+ python validate_commit_msg.py --last
9
+ python validate_commit_msg.py --range main..HEAD
10
+
11
+ Exit codes:
12
+ 0 Message is valid
13
+ 1 Message has issues
14
+ """
15
+
16
+ import subprocess
17
+ import sys
18
+ import re
19
+
20
+ TYPES = {"feat", "fix", "refactor", "docs", "test", "perf", "style", "chore", "security", "revert"}
21
+
22
+ SUBJECT_RE = re.compile(
23
+ r'^(' + '|'.join(TYPES) + r')'
24
+ r'(\([a-zA-Z0-9_/.-]+\))?'
25
+ r'!?:\s'
26
+ r'.{1,68}$'
27
+ )
28
+
29
+ WATERMARK = "Generated-by: BluMa"
30
+
31
+
32
+ def validate_message(msg: str) -> list[str]:
33
+ issues = []
34
+ lines = msg.strip().split('\n')
35
+
36
+ if not lines:
37
+ return ["Empty commit message"]
38
+
39
+ subject = lines[0].strip()
40
+
41
+ if not SUBJECT_RE.match(subject):
42
+ parts = subject.split(':', 1)
43
+ if not parts or parts[0].split('(')[0] not in TYPES:
44
+ issues.append(f"Invalid type prefix. Expected one of: {', '.join(sorted(TYPES))}")
45
+ elif len(subject) > 72:
46
+ issues.append(f"Subject too long ({len(subject)} chars, max 72)")
47
+ else:
48
+ issues.append(f"Subject format invalid: \"{subject}\"")
49
+
50
+ if subject and subject[-1] == '.':
51
+ issues.append("Subject should not end with a period")
52
+
53
+ if subject and subject.split(': ', 1)[-1][:1].isupper():
54
+ issues.append("Subject description should start with lowercase")
55
+
56
+ if len(lines) > 1 and lines[1].strip() != '':
57
+ issues.append("Missing blank line between subject and body")
58
+
59
+ if WATERMARK not in msg:
60
+ issues.append("Missing BluMa watermark trailer")
61
+ else:
62
+ last_non_empty = ''
63
+ for line in reversed(lines):
64
+ if line.strip():
65
+ last_non_empty = line.strip()
66
+ break
67
+ if not last_non_empty.startswith("Generated-by:"):
68
+ issues.append("BluMa watermark should be the last non-empty line")
69
+
70
+ return issues
71
+
72
+
73
+ def get_last_commit_msg() -> str:
74
+ result = subprocess.run(
75
+ ["git", "log", "-1", "--format=%B"],
76
+ capture_output=True, text=True
77
+ )
78
+ if result.returncode != 0:
79
+ print(f"Error: {result.stderr.strip()}")
80
+ sys.exit(1)
81
+ return result.stdout.strip()
82
+
83
+
84
+ def get_commit_msgs(commit_range: str) -> list[tuple[str, str]]:
85
+ result = subprocess.run(
86
+ ["git", "log", commit_range, "--format=%h|||%B---END---"],
87
+ capture_output=True, text=True
88
+ )
89
+ if result.returncode != 0:
90
+ print(f"Error: {result.stderr.strip()}")
91
+ sys.exit(1)
92
+
93
+ commits = []
94
+ for block in result.stdout.split("---END---"):
95
+ block = block.strip()
96
+ if not block:
97
+ continue
98
+ parts = block.split("|||", 1)
99
+ if len(parts) == 2:
100
+ commits.append((parts[0].strip(), parts[1].strip()))
101
+ return commits
102
+
103
+
104
+ def print_result(label: str, msg: str, issues: list[str]):
105
+ subject = msg.split('\n')[0][:60]
106
+ if issues:
107
+ print(f" FAIL [{label}] {subject}")
108
+ for issue in issues:
109
+ print(f" - {issue}")
110
+ else:
111
+ print(f" OK [{label}] {subject}")
112
+
113
+
114
+ def main():
115
+ if len(sys.argv) < 2:
116
+ print("Usage:")
117
+ print(' python validate_commit_msg.py "<message>"')
118
+ print(" python validate_commit_msg.py --last")
119
+ print(" python validate_commit_msg.py --range main..HEAD")
120
+ sys.exit(1)
121
+
122
+ has_errors = False
123
+
124
+ if sys.argv[1] == "--last":
125
+ msg = get_last_commit_msg()
126
+ issues = validate_message(msg)
127
+ print("Validating last commit:\n")
128
+ print_result("HEAD", msg, issues)
129
+ has_errors = bool(issues)
130
+
131
+ elif sys.argv[1] == "--range":
132
+ if len(sys.argv) < 3:
133
+ print("Error: --range requires a commit range (e.g. main..HEAD)")
134
+ sys.exit(1)
135
+ commits = get_commit_msgs(sys.argv[2])
136
+ if not commits:
137
+ print(f"No commits in range {sys.argv[2]}")
138
+ sys.exit(0)
139
+ print(f"Validating {len(commits)} commit(s) in {sys.argv[2]}:\n")
140
+ for h, msg in commits:
141
+ issues = validate_message(msg)
142
+ print_result(h, msg, issues)
143
+ if issues:
144
+ has_errors = True
145
+
146
+ else:
147
+ msg = sys.argv[1]
148
+ issues = validate_message(msg)
149
+ print("Validating message:\n")
150
+ print_result("input", msg, issues)
151
+ has_errors = bool(issues)
152
+
153
+ print()
154
+ if has_errors:
155
+ print("Some commits need attention.")
156
+ sys.exit(1)
157
+ else:
158
+ print("All messages are valid.")
159
+ sys.exit(0)
160
+
161
+
162
+ if __name__ == "__main__":
163
+ main()
@@ -0,0 +1,18 @@
1
+ BluMa — Base Language Unit · Model Agent
2
+ Proprietary License
3
+
4
+ Copyright (c) 2024-2026 BluMa Contributors
5
+
6
+ This skill is part of the BluMa CLI distribution.
7
+ It is provided as a bundled native skill and may not be
8
+ redistributed, modified, or used outside of the BluMa agent
9
+ framework without prior written permission.
10
+
11
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
12
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
13
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
14
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
15
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
16
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
17
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
18
+ OTHER DEALINGS IN THE SOFTWARE.