aios-core 2.3.1 → 3.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.
@@ -267,6 +267,60 @@ github:
267
267
  pr_creation: true
268
268
  issue_management: true
269
269
 
270
+ # Pull Request Configuration
271
+ # Controls how @devops *create-pr generates PR titles and descriptions
272
+ pr:
273
+ # Title format options:
274
+ # - "conventional": Uses Conventional Commits format for semantic-release
275
+ # Example: "feat(auth): implement OAuth login [Story 6.17]"
276
+ # - "story-first": Story ID first (legacy/simple projects)
277
+ # Example: "[Story 6.17] Implement OAuth Login"
278
+ # - "branch-based": Converts branch name to title
279
+ # Example: "Feature User Auth"
280
+ title_format: conventional # Options: conventional | story-first | branch-based
281
+
282
+ # Include story ID in PR title when available
283
+ include_story_id: true
284
+
285
+ # Conventional commits mapping (only used when title_format: conventional)
286
+ # Maps branch prefixes to commit types
287
+ conventional_commits:
288
+ enabled: true
289
+ branch_type_map:
290
+ feature/: feat
291
+ feat/: feat
292
+ fix/: fix
293
+ bugfix/: fix
294
+ hotfix/: fix
295
+ docs/: docs
296
+ chore/: chore
297
+ refactor/: refactor
298
+ test/: test
299
+ perf/: perf
300
+ ci/: ci
301
+ style/: style
302
+ build/: build
303
+ default_type: feat
304
+
305
+ # Base branch for PRs (auto-detected if not set)
306
+ # base_branch: main
307
+
308
+ # Auto-assign reviewers based on story type
309
+ auto_assign_reviewers: false
310
+
311
+ # Draft PRs by default
312
+ draft_by_default: false
313
+
314
+ # Semantic Release Integration (Story 6.17)
315
+ # When enabled, PR titles follow Conventional Commits for automatic releases
316
+ semantic_release:
317
+ enabled: true # Set to false if project doesn't use semantic-release
318
+ # Release types triggered by commit prefixes:
319
+ # - feat: → Minor release (2.3.0 → 2.4.0)
320
+ # - fix: → Patch release (2.3.0 → 2.3.1)
321
+ # - feat!: or BREAKING CHANGE: → Major release (2.3.0 → 3.0.0)
322
+ # - docs:, chore:, test:, etc. → No release
323
+
270
324
  # ============================================
271
325
  # SECTION 9: CodeRabbit Integration (Story 6.3.3)
272
326
  # MASTER TOGGLE: When enabled=false, ALL CodeRabbit behavior is disabled
@@ -262,22 +262,209 @@ function extractStoryInfo(storyPath) {
262
262
  }
263
263
  ```
264
264
 
265
- ### Step 4: Generate PR Title
265
+ ### Step 4: Generate PR Title (Configurable Format)
266
+
267
+ > **Configuration-Driven:** PR title format is controlled by `core-config.yaml` → `github.pr.title_format`
268
+ > This allows each project to choose the format that matches their workflow.
266
269
 
267
270
  ```javascript
271
+ const yaml = require('js-yaml');
272
+ const fs = require('fs');
273
+ const path = require('path');
274
+
275
+ /**
276
+ * Load PR configuration from core-config.yaml
277
+ * @returns {Object} PR configuration with defaults
278
+ */
279
+ function loadPRConfig() {
280
+ const configPath = path.join(process.cwd(), '.aios-core', 'core-config.yaml');
281
+
282
+ // Default configuration (for projects without core-config)
283
+ const defaults = {
284
+ title_format: 'story-first', // Safe default for most projects
285
+ include_story_id: true,
286
+ conventional_commits: {
287
+ enabled: false,
288
+ branch_type_map: {
289
+ 'feature/': 'feat',
290
+ 'feat/': 'feat',
291
+ 'fix/': 'fix',
292
+ 'bugfix/': 'fix',
293
+ 'hotfix/': 'fix',
294
+ 'docs/': 'docs',
295
+ 'chore/': 'chore',
296
+ 'refactor/': 'refactor',
297
+ 'test/': 'test',
298
+ 'perf/': 'perf',
299
+ 'ci/': 'ci',
300
+ 'style/': 'style',
301
+ 'build/': 'build'
302
+ },
303
+ default_type: 'feat'
304
+ }
305
+ };
306
+
307
+ try {
308
+ if (fs.existsSync(configPath)) {
309
+ const config = yaml.load(fs.readFileSync(configPath, 'utf8'));
310
+ return { ...defaults, ...config?.github?.pr };
311
+ }
312
+ } catch (error) {
313
+ console.warn('Could not load core-config.yaml, using defaults');
314
+ }
315
+
316
+ return defaults;
317
+ }
318
+
319
+ /**
320
+ * Generate PR title based on project configuration.
321
+ *
322
+ * Supported formats (configured in core-config.yaml → github.pr.title_format):
323
+ *
324
+ * 1. "conventional" - Conventional Commits format (for semantic-release)
325
+ * Example: "feat(auth): implement OAuth login [Story 6.17]"
326
+ *
327
+ * 2. "story-first" - Story ID first (legacy/simple projects)
328
+ * Example: "[Story 6.17] Implement OAuth Login"
329
+ *
330
+ * 3. "branch-based" - Branch name converted to title
331
+ * Example: "Feature User Auth"
332
+ *
333
+ * @param {string} branchName - Current git branch name
334
+ * @param {Object} storyInfo - Story information (id, title)
335
+ * @returns {string} Formatted PR title
336
+ */
268
337
  function generatePRTitle(branchName, storyInfo) {
338
+ const config = loadPRConfig();
339
+ const format = config.title_format || 'story-first';
340
+
341
+ switch (format) {
342
+ case 'conventional':
343
+ return generateConventionalTitle(branchName, storyInfo, config);
344
+ case 'story-first':
345
+ return generateStoryFirstTitle(branchName, storyInfo, config);
346
+ case 'branch-based':
347
+ return generateBranchBasedTitle(branchName, storyInfo, config);
348
+ default:
349
+ return generateStoryFirstTitle(branchName, storyInfo, config);
350
+ }
351
+ }
352
+
353
+ /**
354
+ * Format: {type}({scope}): {description} [Story {id}]
355
+ * Used for: Projects with semantic-release automation
356
+ */
357
+ function generateConventionalTitle(branchName, storyInfo, config) {
358
+ const typeMap = config.conventional_commits?.branch_type_map || {};
359
+ const defaultType = config.conventional_commits?.default_type || 'feat';
360
+
361
+ // Detect commit type from branch prefix
362
+ let type = defaultType;
363
+ for (const [prefix, commitType] of Object.entries(typeMap)) {
364
+ if (branchName.startsWith(prefix)) {
365
+ type = commitType;
366
+ break;
367
+ }
368
+ }
369
+
370
+ // Extract scope from branch name (e.g., feat/auth/login -> scope=auth)
371
+ const scopeMatch = branchName.match(/^[a-z-]+\/([a-z-]+)\//);
372
+ const scope = scopeMatch ? scopeMatch[1] : null;
373
+ const scopeStr = scope ? `(${scope})` : '';
374
+
375
+ // Generate description
376
+ if (storyInfo && storyInfo.id && storyInfo.title) {
377
+ let cleanTitle = storyInfo.title
378
+ .replace(/^Story\s*\d+\.\d+[:\s-]*/i, '')
379
+ .trim();
380
+ cleanTitle = cleanTitle.charAt(0).toLowerCase() + cleanTitle.slice(1);
381
+
382
+ const storyRef = config.include_story_id ? ` [Story ${storyInfo.id}]` : '';
383
+ return `${type}${scopeStr}: ${cleanTitle}${storyRef}`;
384
+ }
385
+
386
+ // Fallback: convert branch name to description
387
+ const description = branchName
388
+ .replace(/^(feature|feat|fix|bugfix|hotfix|docs|chore|refactor|test|perf|ci|style|build)\//, '')
389
+ .replace(/^[a-z-]+\//, '')
390
+ .replace(/-/g, ' ')
391
+ .toLowerCase()
392
+ .trim();
393
+
394
+ return `${type}${scopeStr}: ${description}`;
395
+ }
396
+
397
+ /**
398
+ * Format: [Story {id}] {Title}
399
+ * Used for: Simple projects, legacy workflows, non-NPM projects
400
+ */
401
+ function generateStoryFirstTitle(branchName, storyInfo, config) {
269
402
  if (storyInfo && storyInfo.id && storyInfo.title) {
270
403
  return `[Story ${storyInfo.id}] ${storyInfo.title}`;
271
404
  }
272
405
 
273
406
  // Fallback: convert branch name to title
274
407
  return branchName
275
- .replace(/^feature\//, '')
408
+ .replace(/^(feature|feat|fix|bugfix|hotfix|docs|chore|refactor|test|perf|ci|style|build)\//, '')
276
409
  .replace(/-/g, ' ')
277
410
  .replace(/\b\w/g, c => c.toUpperCase());
278
411
  }
412
+
413
+ /**
414
+ * Format: {Branch Name As Title}
415
+ * Used for: Minimal projects, quick iterations
416
+ */
417
+ function generateBranchBasedTitle(branchName, storyInfo, config) {
418
+ const title = branchName
419
+ .replace(/^(feature|feat|fix|bugfix|hotfix|docs|chore|refactor|test|perf|ci|style|build)\//, '')
420
+ .replace(/-/g, ' ')
421
+ .replace(/\b\w/g, c => c.toUpperCase());
422
+
423
+ if (config.include_story_id && storyInfo?.id) {
424
+ return `${title} [Story ${storyInfo.id}]`;
425
+ }
426
+
427
+ return title;
428
+ }
429
+ ```
430
+
431
+ ## Configuration Reference
432
+
433
+ Add to your project's `core-config.yaml`:
434
+
435
+ ```yaml
436
+ github:
437
+ pr:
438
+ # Options: conventional | story-first | branch-based
439
+ title_format: conventional # For semantic-release projects
440
+ # title_format: story-first # For simple projects (default)
441
+
442
+ include_story_id: true
443
+
444
+ conventional_commits:
445
+ enabled: true
446
+ branch_type_map:
447
+ feature/: feat
448
+ fix/: fix
449
+ docs/: docs
450
+ # Add custom mappings as needed
451
+ default_type: feat
452
+
453
+ semantic_release:
454
+ enabled: true # Set false if not using semantic-release
279
455
  ```
280
456
 
457
+ ## Title Format Examples
458
+
459
+ | Format | Branch | Story | Generated Title |
460
+ |--------|--------|-------|-----------------|
461
+ | `conventional` | `feature/user-auth` | 6.17: User Auth | `feat: user auth [Story 6.17]` |
462
+ | `conventional` | `fix/cli/parsing` | 6.18: CLI Fix | `fix(cli): cLI fix [Story 6.18]` |
463
+ | `story-first` | `feature/user-auth` | 6.17: User Auth | `[Story 6.17] User Auth` |
464
+ | `story-first` | `fix/cli-bug` | - | `Cli Bug` |
465
+ | `branch-based` | `feature/user-auth` | 6.17 | `User Auth [Story 6.17]` |
466
+ | `branch-based` | `docs/readme` | - | `Readme` |
467
+
281
468
  ### Step 5: Generate PR Description
282
469
 
283
470
  ```javascript
@@ -415,10 +602,60 @@ Called by `@github-devops` via `*create-pr` command.
415
602
  ## Validation
416
603
 
417
604
  - PR created in correct repository (detected URL)
418
- - PR title includes story ID if available
605
+ - PR title follows Conventional Commits format (required for semantic-release)
606
+ - PR title includes story ID if available (e.g., `[Story 6.17]`)
419
607
  - PR description includes repository context
420
608
  - Base branch is correct (usually main/master)
421
609
 
610
+ ## Semantic-Release Integration (Optional)
611
+
612
+ > **Note:** This section only applies when `core-config.yaml` has:
613
+ > - `github.pr.title_format: conventional`
614
+ > - `github.semantic_release.enabled: true`
615
+ >
616
+ > Projects without semantic-release should use `title_format: story-first` (default).
617
+
618
+ **When enabled:** PRs merged via "Squash and merge" use the PR title as commit message, triggering semantic-release:
619
+
620
+ | Branch Pattern | Generated Title | Release |
621
+ |---------------|-----------------|---------|
622
+ | `feature/user-auth` | `feat: user auth` | ✅ Minor |
623
+ | `feat/auth/sso-login` | `feat(auth): sso login` | ✅ Minor |
624
+ | `fix/cli-parsing` | `fix: cli parsing` | ✅ Patch |
625
+ | `docs/readme-update` | `docs: readme update` | ❌ None |
626
+ | `chore/deps-update` | `chore: deps update` | ❌ None |
627
+
628
+ For breaking changes, manually edit the PR title to include `!`:
629
+ - `feat!: redesign authentication API [Story 7.1]`
630
+
631
+ ## Configuration for Different Project Types
632
+
633
+ ### NPM Package with Semantic-Release (aios-core)
634
+ ```yaml
635
+ github:
636
+ pr:
637
+ title_format: conventional
638
+ semantic_release:
639
+ enabled: true
640
+ ```
641
+
642
+ ### Simple Web App (no releases)
643
+ ```yaml
644
+ github:
645
+ pr:
646
+ title_format: story-first # [Story 6.17] Title
647
+ semantic_release:
648
+ enabled: false
649
+ ```
650
+
651
+ ### Quick Prototypes
652
+ ```yaml
653
+ github:
654
+ pr:
655
+ title_format: branch-based # Just branch name as title
656
+ include_story_id: false
657
+ ```
658
+
422
659
  ## Notes
423
660
 
424
661
  - Works with ANY repository
@@ -88,6 +88,47 @@ deployment:
88
88
  staging: ["staging", "needs-review"]
89
89
  production: ["production", "promotion"]
90
90
 
91
+ # =============================================================================
92
+ # GITHUB INTEGRATION
93
+ # Pull Request and semantic-release configuration
94
+ # =============================================================================
95
+ github:
96
+ enabled: true
97
+ cli_required: false
98
+
99
+ # Pull Request Configuration
100
+ # Controls how @devops *create-pr generates PR titles
101
+ pr:
102
+ # Title format options:
103
+ # - "conventional": For semantic-release (feat: description [Story X.Y])
104
+ # - "story-first": Simple format ([Story X.Y] Description) - DEFAULT
105
+ # - "branch-based": Just branch name as title
106
+ title_format: {{PR_TITLE_FORMAT}}
107
+
108
+ include_story_id: true
109
+
110
+ # Only used when title_format: conventional
111
+ conventional_commits:
112
+ enabled: {{CONVENTIONAL_COMMITS_ENABLED}}
113
+ branch_type_map:
114
+ feature/: feat
115
+ feat/: feat
116
+ fix/: fix
117
+ bugfix/: fix
118
+ hotfix/: fix
119
+ docs/: docs
120
+ chore/: chore
121
+ refactor/: refactor
122
+ test/: test
123
+ default_type: feat
124
+
125
+ auto_assign_reviewers: false
126
+ draft_by_default: false
127
+
128
+ # Semantic Release (only for NPM packages)
129
+ semantic_release:
130
+ enabled: {{SEMANTIC_RELEASE_ENABLED}}
131
+
91
132
  # =============================================================================
92
133
  # AGENT CONFIGURATION
93
134
  # Agent-specific settings
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aios-core",
3
- "version": "2.3.1",
3
+ "version": "3.0.0",
4
4
  "description": "Synkra AIOS: AI-Orchestrated System for Full Stack Development - Core Framework",
5
5
  "main": "index.js",
6
6
  "module": "index.esm.js",