chati-dev 1.4.0 → 2.0.2
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 +40 -24
- package/framework/agents/build/dev.md +343 -0
- package/framework/agents/clarity/architect.md +112 -0
- package/framework/agents/clarity/brief.md +182 -0
- package/framework/agents/clarity/brownfield-wu.md +181 -0
- package/framework/agents/clarity/detail.md +110 -0
- package/framework/agents/clarity/greenfield-wu.md +153 -0
- package/framework/agents/clarity/ux.md +112 -0
- package/framework/config.yaml +3 -3
- package/framework/constitution.md +31 -1
- package/framework/context/governance.md +37 -0
- package/framework/context/protocols.md +34 -0
- package/framework/context/quality.md +27 -0
- package/framework/context/root.md +24 -0
- package/framework/data/entity-registry.yaml +1 -1
- package/framework/domains/agents/architect.yaml +51 -0
- package/framework/domains/agents/brief.yaml +47 -0
- package/framework/domains/agents/brownfield-wu.yaml +49 -0
- package/framework/domains/agents/detail.yaml +47 -0
- package/framework/domains/agents/dev.yaml +49 -0
- package/framework/domains/agents/devops.yaml +43 -0
- package/framework/domains/agents/greenfield-wu.yaml +47 -0
- package/framework/domains/agents/orchestrator.yaml +49 -0
- package/framework/domains/agents/phases.yaml +47 -0
- package/framework/domains/agents/qa-implementation.yaml +43 -0
- package/framework/domains/agents/qa-planning.yaml +44 -0
- package/framework/domains/agents/tasks.yaml +48 -0
- package/framework/domains/agents/ux.yaml +50 -0
- package/framework/domains/constitution.yaml +77 -0
- package/framework/domains/global.yaml +64 -0
- package/framework/domains/workflows/brownfield-discovery.yaml +16 -0
- package/framework/domains/workflows/brownfield-fullstack.yaml +26 -0
- package/framework/domains/workflows/brownfield-service.yaml +22 -0
- package/framework/domains/workflows/brownfield-ui.yaml +22 -0
- package/framework/domains/workflows/greenfield-fullstack.yaml +26 -0
- package/framework/hooks/constitution-guard.js +101 -0
- package/framework/hooks/mode-governance.js +92 -0
- package/framework/hooks/model-governance.js +76 -0
- package/framework/hooks/prism-engine.js +89 -0
- package/framework/hooks/session-digest.js +60 -0
- package/framework/hooks/settings.json +44 -0
- package/framework/i18n/en.yaml +3 -3
- package/framework/i18n/es.yaml +3 -3
- package/framework/i18n/fr.yaml +3 -3
- package/framework/i18n/pt.yaml +3 -3
- package/framework/intelligence/decision-engine.md +1 -1
- package/framework/migrations/v1.4-to-v2.0.yaml +167 -0
- package/framework/migrations/v2.0-to-v2.0.1.yaml +132 -0
- package/framework/orchestrator/chati.md +284 -6
- package/framework/tasks/architect-api-design.md +63 -0
- package/framework/tasks/architect-consolidate.md +47 -0
- package/framework/tasks/architect-db-design.md +73 -0
- package/framework/tasks/architect-design.md +95 -0
- package/framework/tasks/architect-security-review.md +62 -0
- package/framework/tasks/architect-stack-selection.md +53 -0
- package/framework/tasks/brief-consolidate.md +249 -0
- package/framework/tasks/brief-constraint-identify.md +277 -0
- package/framework/tasks/brief-extract-requirements.md +339 -0
- package/framework/tasks/brief-stakeholder-map.md +176 -0
- package/framework/tasks/brief-validate-completeness.md +121 -0
- package/framework/tasks/brownfield-wu-architecture-map.md +394 -0
- package/framework/tasks/brownfield-wu-deep-discovery.md +312 -0
- package/framework/tasks/brownfield-wu-dependency-scan.md +359 -0
- package/framework/tasks/brownfield-wu-migration-plan.md +483 -0
- package/framework/tasks/brownfield-wu-report.md +325 -0
- package/framework/tasks/brownfield-wu-risk-assess.md +424 -0
- package/framework/tasks/detail-acceptance-criteria.md +372 -0
- package/framework/tasks/detail-consolidate.md +138 -0
- package/framework/tasks/detail-edge-case-analysis.md +300 -0
- package/framework/tasks/detail-expand-prd.md +389 -0
- package/framework/tasks/detail-nfr-extraction.md +223 -0
- package/framework/tasks/dev-code-review.md +404 -0
- package/framework/tasks/dev-consolidate.md +543 -0
- package/framework/tasks/dev-debug.md +322 -0
- package/framework/tasks/dev-implement.md +252 -0
- package/framework/tasks/dev-iterate.md +411 -0
- package/framework/tasks/dev-pr-prepare.md +497 -0
- package/framework/tasks/dev-refactor.md +342 -0
- package/framework/tasks/dev-test-write.md +306 -0
- package/framework/tasks/devops-ci-setup.md +412 -0
- package/framework/tasks/devops-consolidate.md +712 -0
- package/framework/tasks/devops-deploy-config.md +598 -0
- package/framework/tasks/devops-monitoring-setup.md +658 -0
- package/framework/tasks/devops-release-prepare.md +673 -0
- package/framework/tasks/greenfield-wu-analyze-empty.md +169 -0
- package/framework/tasks/greenfield-wu-report.md +266 -0
- package/framework/tasks/greenfield-wu-scaffold-detection.md +203 -0
- package/framework/tasks/greenfield-wu-tech-stack-assess.md +255 -0
- package/framework/tasks/orchestrator-deviation.md +260 -0
- package/framework/tasks/orchestrator-escalate.md +276 -0
- package/framework/tasks/orchestrator-handoff.md +243 -0
- package/framework/tasks/orchestrator-health.md +372 -0
- package/framework/tasks/orchestrator-mode-switch.md +262 -0
- package/framework/tasks/orchestrator-resume.md +189 -0
- package/framework/tasks/orchestrator-route.md +169 -0
- package/framework/tasks/orchestrator-spawn-terminal.md +358 -0
- package/framework/tasks/orchestrator-status.md +260 -0
- package/framework/tasks/orchestrator-suggest-mode.md +372 -0
- package/framework/tasks/phases-breakdown.md +91 -0
- package/framework/tasks/phases-dependency-mapping.md +67 -0
- package/framework/tasks/phases-mvp-scoping.md +94 -0
- package/framework/tasks/qa-impl-consolidate.md +522 -0
- package/framework/tasks/qa-impl-performance-test.md +487 -0
- package/framework/tasks/qa-impl-regression-check.md +413 -0
- package/framework/tasks/qa-impl-sast-scan.md +402 -0
- package/framework/tasks/qa-impl-test-execute.md +344 -0
- package/framework/tasks/qa-impl-verdict.md +339 -0
- package/framework/tasks/qa-planning-consolidate.md +309 -0
- package/framework/tasks/qa-planning-coverage-plan.md +338 -0
- package/framework/tasks/qa-planning-gate-define.md +339 -0
- package/framework/tasks/qa-planning-risk-matrix.md +631 -0
- package/framework/tasks/qa-planning-test-strategy.md +217 -0
- package/framework/tasks/tasks-acceptance-write.md +75 -0
- package/framework/tasks/tasks-consolidate.md +57 -0
- package/framework/tasks/tasks-decompose.md +80 -0
- package/framework/tasks/tasks-estimate.md +66 -0
- package/framework/tasks/ux-a11y-check.md +49 -0
- package/framework/tasks/ux-component-map.md +55 -0
- package/framework/tasks/ux-consolidate.md +46 -0
- package/framework/tasks/ux-user-flow.md +46 -0
- package/framework/tasks/ux-wireframe.md +76 -0
- package/package.json +2 -2
- package/scripts/bundle-framework.js +2 -0
- package/scripts/changelog-generator.js +222 -0
- package/scripts/codebase-mapper.js +728 -0
- package/scripts/commit-message-generator.js +167 -0
- package/scripts/coverage-analyzer.js +260 -0
- package/scripts/dependency-analyzer.js +280 -0
- package/scripts/framework-analyzer.js +308 -0
- package/scripts/generate-constitution-domain.js +253 -0
- package/scripts/health-check.js +481 -0
- package/scripts/ide-sync.js +327 -0
- package/scripts/performance-analyzer.js +325 -0
- package/scripts/plan-tracker.js +278 -0
- package/scripts/populate-entity-registry.js +481 -0
- package/scripts/pr-review.js +317 -0
- package/scripts/rollback-manager.js +310 -0
- package/scripts/stuck-detector.js +343 -0
- package/scripts/test-quality-assessment.js +257 -0
- package/scripts/validate-agents.js +367 -0
- package/scripts/validate-tasks.js +465 -0
- package/src/autonomy/autonomous-gate.js +293 -0
- package/src/autonomy/index.js +51 -0
- package/src/autonomy/mode-manager.js +225 -0
- package/src/autonomy/mode-suggester.js +283 -0
- package/src/autonomy/progress-reporter.js +268 -0
- package/src/autonomy/safety-net.js +320 -0
- package/src/context/bracket-tracker.js +79 -0
- package/src/context/domain-loader.js +107 -0
- package/src/context/engine.js +144 -0
- package/src/context/formatter.js +184 -0
- package/src/context/index.js +4 -0
- package/src/context/layers/l0-constitution.js +28 -0
- package/src/context/layers/l1-global.js +37 -0
- package/src/context/layers/l2-agent.js +39 -0
- package/src/context/layers/l3-workflow.js +42 -0
- package/src/context/layers/l4-task.js +24 -0
- package/src/decision/analyzer.js +167 -0
- package/src/decision/engine.js +270 -0
- package/src/decision/index.js +38 -0
- package/src/decision/registry-healer.js +450 -0
- package/src/decision/registry-updater.js +330 -0
- package/src/gates/circuit-breaker.js +119 -0
- package/src/gates/g1-planning-complete.js +153 -0
- package/src/gates/g2-qa-planning.js +153 -0
- package/src/gates/g3-implementation.js +188 -0
- package/src/gates/g4-qa-implementation.js +207 -0
- package/src/gates/g5-deploy-ready.js +180 -0
- package/src/gates/gate-base.js +144 -0
- package/src/gates/index.js +46 -0
- package/src/installer/brownfield-upgrader.js +249 -0
- package/src/installer/core.js +82 -11
- package/src/installer/file-hasher.js +51 -0
- package/src/installer/manifest.js +117 -0
- package/src/installer/templates.js +17 -15
- package/src/installer/transaction.js +229 -0
- package/src/installer/validator.js +18 -1
- package/src/intelligence/registry-manager.js +2 -2
- package/src/memory/agent-memory.js +255 -0
- package/src/memory/gotchas-injector.js +72 -0
- package/src/memory/gotchas.js +361 -0
- package/src/memory/index.js +35 -0
- package/src/memory/search.js +233 -0
- package/src/memory/session-digest.js +239 -0
- package/src/merger/env-merger.js +112 -0
- package/src/merger/index.js +56 -0
- package/src/merger/replace-merger.js +51 -0
- package/src/merger/yaml-merger.js +127 -0
- package/src/orchestrator/agent-selector.js +285 -0
- package/src/orchestrator/deviation-handler.js +350 -0
- package/src/orchestrator/handoff-engine.js +271 -0
- package/src/orchestrator/index.js +67 -0
- package/src/orchestrator/intent-classifier.js +264 -0
- package/src/orchestrator/pipeline-manager.js +492 -0
- package/src/orchestrator/pipeline-state.js +223 -0
- package/src/orchestrator/session-manager.js +409 -0
- package/src/tasks/executor.js +195 -0
- package/src/tasks/handoff.js +226 -0
- package/src/tasks/index.js +4 -0
- package/src/tasks/loader.js +210 -0
- package/src/tasks/router.js +182 -0
- package/src/terminal/collector.js +216 -0
- package/src/terminal/index.js +30 -0
- package/src/terminal/isolation.js +129 -0
- package/src/terminal/monitor.js +277 -0
- package/src/terminal/spawner.js +269 -0
- package/src/upgrade/checker.js +1 -1
- package/src/wizard/i18n.js +3 -3
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: ux-wireframe
|
|
3
|
+
agent: ux
|
|
4
|
+
trigger: detail
|
|
5
|
+
phase: clarity
|
|
6
|
+
requires_input: false
|
|
7
|
+
parallelizable: true
|
|
8
|
+
outputs: [wireframes.yaml]
|
|
9
|
+
handoff_to: ux-user-flow
|
|
10
|
+
autonomous_gate: true
|
|
11
|
+
criteria:
|
|
12
|
+
- Wireframes created for all key screens
|
|
13
|
+
- Layout and component hierarchy defined
|
|
14
|
+
- Responsive breakpoints documented
|
|
15
|
+
---
|
|
16
|
+
# Create Wireframes for Key Screens
|
|
17
|
+
|
|
18
|
+
## Purpose
|
|
19
|
+
Design wireframes (text-based descriptions with ASCII diagrams) for all key user-facing screens.
|
|
20
|
+
|
|
21
|
+
## Prerequisites
|
|
22
|
+
- `prd.yaml` with UI requirements
|
|
23
|
+
|
|
24
|
+
## Steps
|
|
25
|
+
|
|
26
|
+
### 1. Identify All Screens
|
|
27
|
+
From PRD: home, post detail, register, login, dashboard, create post, edit post, search results.
|
|
28
|
+
|
|
29
|
+
### 2. For Each Screen, Define
|
|
30
|
+
- Layout structure (header, main, sidebar, footer)
|
|
31
|
+
- Key UI elements (forms, buttons, lists, cards)
|
|
32
|
+
- Component hierarchy
|
|
33
|
+
- Responsive breakpoints (mobile 320px, tablet 768px, desktop 1024px+)
|
|
34
|
+
|
|
35
|
+
### 3. Create ASCII Wireframes
|
|
36
|
+
Text-based visual representations.
|
|
37
|
+
|
|
38
|
+
### 4. Document Interactions
|
|
39
|
+
Hover states, focus states, loading states.
|
|
40
|
+
|
|
41
|
+
### 5. Define Navigation
|
|
42
|
+
How users move between screens.
|
|
43
|
+
|
|
44
|
+
## Output Format
|
|
45
|
+
```yaml
|
|
46
|
+
# wireframes.yaml
|
|
47
|
+
screens:
|
|
48
|
+
- name: Home Page
|
|
49
|
+
route: /
|
|
50
|
+
layout: |
|
|
51
|
+
[Header: Logo | Search | Login/Register]
|
|
52
|
+
[Hero: Welcome message, CTA]
|
|
53
|
+
[Post Grid: 3 columns on desktop, 1 on mobile]
|
|
54
|
+
[Pagination]
|
|
55
|
+
[Footer]
|
|
56
|
+
components:
|
|
57
|
+
- Header (sticky)
|
|
58
|
+
- SearchBar
|
|
59
|
+
- PostCard (repeating)
|
|
60
|
+
- Pagination
|
|
61
|
+
responsive:
|
|
62
|
+
mobile: Single column
|
|
63
|
+
tablet: 2 columns
|
|
64
|
+
desktop: 3 columns
|
|
65
|
+
- name: Login Page
|
|
66
|
+
route: /login
|
|
67
|
+
layout: |
|
|
68
|
+
[Header]
|
|
69
|
+
[Centered Card:
|
|
70
|
+
Email input
|
|
71
|
+
Password input
|
|
72
|
+
Login button
|
|
73
|
+
Link to /register
|
|
74
|
+
]
|
|
75
|
+
[Footer]
|
|
76
|
+
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chati-dev",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.2",
|
|
4
4
|
"description": "AI-Powered Multi-Agent Orchestration System — 13 agents, 6 IDEs, 4 languages",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"semver": "^7.6.0"
|
|
61
61
|
},
|
|
62
62
|
"engines": {
|
|
63
|
-
"node": ">=
|
|
63
|
+
"node": ">=20.0.0"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
66
|
"@eslint/js": "^10.0.1",
|
|
@@ -35,7 +35,9 @@ const dirs = [
|
|
|
35
35
|
'agents/clarity', 'agents/quality', 'agents/build', 'agents/deploy',
|
|
36
36
|
'templates', 'workflows', 'quality-gates',
|
|
37
37
|
'schemas', 'frameworks', 'intelligence', 'patterns',
|
|
38
|
+
'hooks', 'domains',
|
|
38
39
|
'i18n', 'migrations', 'data',
|
|
40
|
+
'tasks', 'context',
|
|
39
41
|
];
|
|
40
42
|
|
|
41
43
|
for (const dir of dirs) {
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Changelog Generator — Produces markdown changelogs from conventional commits.
|
|
3
|
+
*
|
|
4
|
+
* Reads git history, parses conventional commit messages, groups them by type,
|
|
5
|
+
* and formats the output as a structured markdown document.
|
|
6
|
+
*
|
|
7
|
+
* @module scripts/changelog-generator
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { execSync } from 'node:child_process';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @typedef {Object} ParsedCommit
|
|
14
|
+
* @property {string} type
|
|
15
|
+
* @property {string|null} scope
|
|
16
|
+
* @property {string} description
|
|
17
|
+
* @property {boolean} breaking
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @typedef {Object} GitCommit
|
|
22
|
+
* @property {string} hash
|
|
23
|
+
* @property {string} message
|
|
24
|
+
* @property {string} date
|
|
25
|
+
* @property {string} author
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
const TYPE_LABELS = {
|
|
29
|
+
feat: 'Features',
|
|
30
|
+
fix: 'Bug Fixes',
|
|
31
|
+
docs: 'Documentation',
|
|
32
|
+
chore: 'Chores',
|
|
33
|
+
refactor: 'Refactoring',
|
|
34
|
+
test: 'Tests',
|
|
35
|
+
ci: 'CI/CD',
|
|
36
|
+
perf: 'Performance',
|
|
37
|
+
style: 'Style',
|
|
38
|
+
build: 'Build',
|
|
39
|
+
revert: 'Reverts',
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const TYPE_ORDER = ['feat', 'fix', 'perf', 'refactor', 'docs', 'test', 'ci', 'chore', 'style', 'build', 'revert'];
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Parses a conventional commit message.
|
|
46
|
+
*
|
|
47
|
+
* Format: type(scope): description
|
|
48
|
+
* Breaking: type(scope)!: description OR BREAKING CHANGE: in body
|
|
49
|
+
*
|
|
50
|
+
* @param {string} message
|
|
51
|
+
* @returns {ParsedCommit|null}
|
|
52
|
+
*/
|
|
53
|
+
export function parseConventionalCommit(message) {
|
|
54
|
+
if (!message || typeof message !== 'string') return null;
|
|
55
|
+
|
|
56
|
+
// Match: type(scope)!: description or type!: description or type(scope): description or type: description
|
|
57
|
+
const regex = /^(\w+)(?:\(([^)]*)\))?(!)?\s*:\s*(.+)/;
|
|
58
|
+
const match = message.trim().match(regex);
|
|
59
|
+
|
|
60
|
+
if (!match) return null;
|
|
61
|
+
|
|
62
|
+
const [, type, scope, bang, description] = match;
|
|
63
|
+
const breaking = bang === '!' || /\bBREAKING[\s-]CHANGE\b/i.test(message);
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
type: type.toLowerCase(),
|
|
67
|
+
scope: scope || null,
|
|
68
|
+
description: description.trim(),
|
|
69
|
+
breaking,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Retrieves git commits since a given ref (tag, commit, or date).
|
|
75
|
+
* If `since` is null, returns all commits.
|
|
76
|
+
*
|
|
77
|
+
* @param {string|null} since — git ref or null for all
|
|
78
|
+
* @param {string} [cwd=process.cwd()]
|
|
79
|
+
* @returns {GitCommit[]}
|
|
80
|
+
*/
|
|
81
|
+
export function getGitCommits(since = null, cwd = process.cwd()) {
|
|
82
|
+
const range = since ? `${since}..HEAD` : 'HEAD';
|
|
83
|
+
const format = '%H||%s||%ai||%an';
|
|
84
|
+
|
|
85
|
+
let output;
|
|
86
|
+
try {
|
|
87
|
+
output = execSync(`git log ${range} --pretty=format:"${format}"`, {
|
|
88
|
+
cwd,
|
|
89
|
+
encoding: 'utf-8',
|
|
90
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
91
|
+
});
|
|
92
|
+
} catch {
|
|
93
|
+
return [];
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (!output.trim()) return [];
|
|
97
|
+
|
|
98
|
+
return output
|
|
99
|
+
.trim()
|
|
100
|
+
.split('\n')
|
|
101
|
+
.filter(Boolean)
|
|
102
|
+
.map((line) => {
|
|
103
|
+
const parts = line.split('||');
|
|
104
|
+
return {
|
|
105
|
+
hash: (parts[0] || '').trim(),
|
|
106
|
+
message: (parts[1] || '').trim(),
|
|
107
|
+
date: (parts[2] || '').trim(),
|
|
108
|
+
author: (parts[3] || '').trim(),
|
|
109
|
+
};
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Groups parsed commits by their conventional type.
|
|
115
|
+
*
|
|
116
|
+
* @param {GitCommit[]} commits
|
|
117
|
+
* @returns {Record<string, Array<{ commit: GitCommit, parsed: ParsedCommit }>>}
|
|
118
|
+
*/
|
|
119
|
+
export function groupCommits(commits) {
|
|
120
|
+
const groups = {};
|
|
121
|
+
|
|
122
|
+
for (const commit of commits) {
|
|
123
|
+
const parsed = parseConventionalCommit(commit.message);
|
|
124
|
+
if (!parsed) {
|
|
125
|
+
// Put non-conventional commits under 'other'
|
|
126
|
+
if (!groups.other) groups.other = [];
|
|
127
|
+
groups.other.push({ commit, parsed: { type: 'other', scope: null, description: commit.message, breaking: false } });
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
const type = parsed.type;
|
|
131
|
+
if (!groups[type]) groups[type] = [];
|
|
132
|
+
groups[type].push({ commit, parsed });
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return groups;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Formats a single changelog section for a version.
|
|
140
|
+
*
|
|
141
|
+
* @param {string} version
|
|
142
|
+
* @param {string} date
|
|
143
|
+
* @param {Record<string, Array<{ commit: GitCommit, parsed: ParsedCommit }>>} grouped
|
|
144
|
+
* @returns {string}
|
|
145
|
+
*/
|
|
146
|
+
export function formatChangelogSection(version, date, grouped) {
|
|
147
|
+
const lines = [];
|
|
148
|
+
lines.push(`## ${version} (${date})`);
|
|
149
|
+
lines.push('');
|
|
150
|
+
|
|
151
|
+
// Breaking changes first
|
|
152
|
+
const breakingChanges = [];
|
|
153
|
+
for (const entries of Object.values(grouped)) {
|
|
154
|
+
for (const { commit, parsed } of entries) {
|
|
155
|
+
if (parsed.breaking) {
|
|
156
|
+
const scope = parsed.scope ? `**${parsed.scope}**: ` : '';
|
|
157
|
+
breakingChanges.push(`- ${scope}${parsed.description} (${commit.hash.slice(0, 7)})`);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (breakingChanges.length > 0) {
|
|
163
|
+
lines.push('### BREAKING CHANGES');
|
|
164
|
+
lines.push('');
|
|
165
|
+
lines.push(...breakingChanges);
|
|
166
|
+
lines.push('');
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Sections in defined order
|
|
170
|
+
for (const type of TYPE_ORDER) {
|
|
171
|
+
const entries = grouped[type];
|
|
172
|
+
if (!entries || entries.length === 0) continue;
|
|
173
|
+
|
|
174
|
+
const label = TYPE_LABELS[type] || type;
|
|
175
|
+
lines.push(`### ${label}`);
|
|
176
|
+
lines.push('');
|
|
177
|
+
|
|
178
|
+
for (const { commit, parsed } of entries) {
|
|
179
|
+
if (parsed.breaking) continue; // already listed above
|
|
180
|
+
const scope = parsed.scope ? `**${parsed.scope}**: ` : '';
|
|
181
|
+
lines.push(`- ${scope}${parsed.description} (${commit.hash.slice(0, 7)})`);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
lines.push('');
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Other (non-conventional) commits
|
|
188
|
+
if (grouped.other && grouped.other.length > 0) {
|
|
189
|
+
lines.push('### Other');
|
|
190
|
+
lines.push('');
|
|
191
|
+
for (const { commit } of grouped.other) {
|
|
192
|
+
lines.push(`- ${commit.message} (${commit.hash.slice(0, 7)})`);
|
|
193
|
+
}
|
|
194
|
+
lines.push('');
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return lines.join('\n');
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Generates a full changelog string.
|
|
202
|
+
*
|
|
203
|
+
* @param {Object} [options]
|
|
204
|
+
* @param {string} [options.since] — git ref to start from (tag or commit)
|
|
205
|
+
* @param {string} [options.version] — version label (default: 'Unreleased')
|
|
206
|
+
* @param {string} [options.cwd] — working directory
|
|
207
|
+
* @returns {string}
|
|
208
|
+
*/
|
|
209
|
+
export function generateChangelog(options = {}) {
|
|
210
|
+
const cwd = options.cwd || process.cwd();
|
|
211
|
+
const since = options.since || null;
|
|
212
|
+
const version = options.version || 'Unreleased';
|
|
213
|
+
const date = new Date().toISOString().slice(0, 10);
|
|
214
|
+
|
|
215
|
+
const commits = getGitCommits(since, cwd);
|
|
216
|
+
if (commits.length === 0) {
|
|
217
|
+
return `## ${version} (${date})\n\nNo changes.\n`;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const grouped = groupCommits(commits);
|
|
221
|
+
return formatChangelogSection(version, date, grouped);
|
|
222
|
+
}
|