maiass 5.9.53 → 5.10.1

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/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  **Modular AI-Augmented Semantic Scribe** — intelligent Git workflow automation
5
5
 
6
6
  [![npm](https://img.shields.io/npm/v/maiass.svg)](https://www.npmjs.com/package/maiass)
7
- [![Node.js](https://img.shields.io/badge/Node.js-18+-green.svg)](https://nodejs.org/)
7
+ [![Node.js](https://img.shields.io/badge/Node.js-20+-green.svg)](https://nodejs.org/)
8
8
  [![License](https://img.shields.io/badge/License-GPL--3.0-blue.svg)](LICENSE)
9
9
 
10
10
  ---
@@ -21,7 +21,7 @@ MAIASS automates the repetitive parts of your Git workflow: staging, AI-powered
21
21
  npm install -g maiass
22
22
  ```
23
23
 
24
- Requires Node.js 18+.
24
+ Requires Node.js 20+.
25
25
 
26
26
  ---
27
27
 
@@ -60,9 +60,9 @@ maiass config set MAIASS_AI_TOKEN your_api_key
60
60
  AI mode is configured per-project in `.env.maiass`:
61
61
 
62
62
  ```bash
63
- MAIASS_AI_COMMITS=ask # ask each time (default)
64
- MAIASS_AI_COMMITS=always # always use AI
65
- MAIASS_AI_COMMITS=off # disable AI
63
+ MAIASS_AI_MODE=ask # ask each time (default)
64
+ MAIASS_AI_MODE=autosuggest # always use AI
65
+ MAIASS_AI_MODE=off # disable AI
66
66
  ```
67
67
 
68
68
  ---
@@ -73,7 +73,7 @@ MAIASS_AI_COMMITS=off # disable AI
73
73
  - **Version management** — detects and bumps `package.json`, `composer.json`, `VERSION`, `.pbxproj` (Swift/Xcode), and more
74
74
  - **Changelog generation** — user-facing `CHANGELOG.md` and internal developer changelog
75
75
  - **Branch workflow** — feature → develop → staging → main with merge handling
76
- - **JIRA integration** — ticket numbers auto-detected from branch names
76
+ - **Ticket integration** — ticket numbers auto-detected from branch names (Jira `ABC-123`, GitHub/Trello `#123` or `123`)
77
77
  - **First-run friendly** — works immediately with sensible defaults, no blocking setup
78
78
 
79
79
  ---
@@ -92,10 +92,10 @@ Run `maiass --setup` to configure a project interactively, or edit `.env.maiass`
92
92
  Common variables:
93
93
 
94
94
  ```bash
95
- MAIASS_AI_COMMITS=ask
96
- MAIASS_MODE=full # full or ai_only
97
- MAIASS_MAIN_BRANCH=main
98
- MAIASS_DEVELOP_BRANCH=develop
95
+ MAIASS_AI_MODE=ask
96
+ MAIASS_MAINBRANCH=main
97
+ MAIASS_DEVELOPBRANCH=develop
98
+ MAIASS_STAGINGBRANCH=staging
99
99
  MAIASS_VERSION_PRIMARY_FILE=package.json
100
100
  MAIASS_DEBUG=true # verbose output
101
101
  ```
package/lib/changelog.js CHANGED
@@ -82,8 +82,8 @@ export async function updateChangelog(changelogPath = '.', version) {
82
82
  });
83
83
 
84
84
  const formattedCommits = commits.map(commit => {
85
- // Remove JIRA ticket from start
86
- const cleaned = commit.replace(/^\[?[A-Z]+-[0-9]+\]?[\s:—-]+/gm, '');
85
+ // Remove ticket prefix from start of each line: ABC-123, #123, 123
86
+ const cleaned = commit.replace(/^\[?(?:[A-Z]+-[0-9]+|#?\d+)\]?[\s:—-]+/gm, '');
87
87
  const lines = cleaned.split('\n').filter(l => l.trim());
88
88
 
89
89
  if (lines.length === 0) return '';
package/lib/git-info.js CHANGED
@@ -88,13 +88,20 @@ export function getGitAuthor() {
88
88
  export function extractJiraTicket(branchName) {
89
89
  if (!branchName) return null;
90
90
 
91
- // Match after the last slash
92
- const afterSlash = branchName.match(/.*\/([A-Z]+-[0-9]+)/);
93
- if (afterSlash) return afterSlash[1];
91
+ // Jira: ABC-123 — after last slash or at branch root
92
+ const jiraAfterSlash = branchName.match(/.*\/([A-Z]+-[0-9]+)/);
93
+ if (jiraAfterSlash) return jiraAfterSlash[1];
94
94
 
95
- // Match at the beginning of the branch name
96
- const atStart = branchName.match(/^([A-Z]+-[0-9]+)/);
97
- if (atStart) return atStart[1];
95
+ const jiraAtStart = branchName.match(/^([A-Z]+-[0-9]+)/);
96
+ if (jiraAtStart) return jiraAtStart[1];
97
+
98
+ // Numeric with optional hash prefix: #123 or 123 — after last slash or at branch root
99
+ // Requires a dash/underscore after the number to avoid matching version segments (e.g. release/1.2.3)
100
+ const numericAfterSlash = branchName.match(/.*\/(#?\d+)[-_]/);
101
+ if (numericAfterSlash) return numericAfterSlash[1];
102
+
103
+ const numericAtStart = branchName.match(/^(#?\d+)[-_]/);
104
+ if (numericAtStart) return numericAtStart[1];
98
105
 
99
106
  return null;
100
107
  }
@@ -1,7 +1,6 @@
1
1
  import { log, logger } from './logger.js';
2
2
  import { SYMBOLS } from './symbols.js';
3
3
  import { runMaiassPipeline } from './maiass-pipeline.js';
4
- import { createAnonymousSubscriptionIfNeeded } from './commit.js';
5
4
  import colors from './colors.js';
6
5
 
7
6
  /**
@@ -37,16 +36,6 @@ export async function handleMaiassCommand(args) {
37
36
  logger.header('', 'MAIASS - Modular AI-Assisted Semantic Scribe');
38
37
 
39
38
  try {
40
- // Create anonymous subscription if needed (matches bashmaiass behavior).
41
- // Skip in CI environments (GitHub Actions / any env with CI=true) — each runner
42
- // has a different virtual MAC/disk, so every run would generate a new machine
43
- // fingerprint and burn an anonymous subscription slot.
44
- const aiMode = process.env.MAIASS_AI_MODE || 'ask';
45
- const isCI = process.env.CI === 'true' || process.env.CI === '1';
46
- if (aiMode !== 'off' && !isCI) {
47
- await createAnonymousSubscriptionIfNeeded();
48
- }
49
-
50
39
  // Run the complete MAIASS pipeline
51
40
  const result = await runMaiassPipeline({
52
41
  commitsOnly,
@@ -454,12 +454,33 @@ function shouldTagRelease(versionBump, forceTag = false) {
454
454
  async function handleVersionManagement(branchInfo, mergeResult, options = {}) {
455
455
  const { versionBump, versionBumpExplicit = false, dryRun = false, tag = false, force = false, silent = false, originalGitInfo = null } = options;
456
456
  const { developBranch } = branchInfo;
457
-
457
+
458
458
  logger.header(SYMBOLS.INFO, 'Version Management Phase');
459
-
460
- // Check if we have version files
459
+
460
+ // Must be on develop branch for version management — check before reading version files
461
+ const currentBranch = getCurrentBranch();
462
+ if (currentBranch !== developBranch) {
463
+ console.error(colors.Red(`${SYMBOLS.CROSS} Version management must be done on ${developBranch} branch`));
464
+ console.error(colors.Red(`${SYMBOLS.CROSS} Current branch: ${currentBranch}`));
465
+ return { success: false, error: `Not on ${developBranch} branch` };
466
+ }
467
+
468
+ // Pull latest develop from remote before reading version files.
469
+ // This ensures we bump from the correct base even if remote has been updated
470
+ // since our last fetch (e.g. a GH Actions bump from a recently merged PR).
471
+ if (remoteExists()) {
472
+ logger.info(SYMBOLS.PULLING, `Pulling latest ${developBranch} before version bump...`);
473
+ const pullResult = executeGitCommand(`git pull origin ${developBranch}`);
474
+ if (!pullResult.success) {
475
+ logger.error(SYMBOLS.CROSS, 'Git operation failed: pull before version bump');
476
+ logger.error(SYMBOLS.CROSS, 'Please resolve any conflicts and try again');
477
+ return { success: false, error: pullResult.error };
478
+ }
479
+ }
480
+
481
+ // Read version files after pull so we have the freshest version on disk
461
482
  const versionInfo = await getCurrentVersion();
462
-
483
+
463
484
  if (!versionInfo.hasVersionFiles) {
464
485
  // Only warn if the user explicitly asked for a version bump
465
486
  if (versionBumpExplicit) {
@@ -468,15 +489,7 @@ async function handleVersionManagement(branchInfo, mergeResult, options = {}) {
468
489
  logger.debug('No version files — skipping version management');
469
490
  return { success: true, skipped: true };
470
491
  }
471
-
472
- // Must be on develop branch for version management
473
- const currentBranch = getCurrentBranch();
474
- if (currentBranch !== developBranch) {
475
- console.error(colors.Red(`${SYMBOLS.CROSS} Version management must be done on ${developBranch} branch`));
476
- console.error(colors.Red(`${SYMBOLS.CROSS} Current branch: ${currentBranch}`));
477
- return { success: false, error: `Not on ${developBranch} branch` };
478
- }
479
-
492
+
480
493
  // Determine new version
481
494
  const newVersion = bumpVersion(versionInfo.current, versionBump);
482
495
  if (!newVersion) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "maiass",
3
3
  "type": "module",
4
- "version": "5.9.53",
4
+ "version": "5.10.1",
5
5
  "description": "AI commit message generator, semantic versioning, and changelog automation for Git. One command stages, commits with AI, bumps version, and merges branches. Free credits on install — no sign-up needed.",
6
6
  "main": "maiass.mjs",
7
7
  "bin": {
@@ -26,7 +26,7 @@
26
26
  "LICENSE"
27
27
  ],
28
28
  "engines": {
29
- "node": ">=18.0.0"
29
+ "node": ">=20.0.0"
30
30
  },
31
31
  "keywords": [
32
32
  "ai-commit",
@@ -69,11 +69,18 @@
69
69
  "build:nexe": "./scripts/advanced-build.sh nexe",
70
70
  "build:source": "./scripts/advanced-build.sh source",
71
71
  "build:legacy": "node build.js",
72
- "test": "node test/test-runner.js"
72
+ "test": "node test/test-runner.js",
73
+ "test:unit": "vitest run",
74
+ "test:unit:watch": "vitest",
75
+ "test:coverage": "vitest run --coverage"
73
76
  },
74
77
  "dependencies": {
75
78
  "chalk": "^5.4.1",
76
79
  "dotenv": "^16.4.5",
77
80
  "yargs": "^17.7.2"
81
+ },
82
+ "devDependencies": {
83
+ "@vitest/coverage-v8": "^4.1.4",
84
+ "vitest": "^4.1.4"
78
85
  }
79
86
  }