@speclife/core 0.1.7 → 0.3.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.
- package/dist/adapters/git-adapter.d.ts +15 -2
- package/dist/adapters/git-adapter.d.ts.map +1 -1
- package/dist/adapters/git-adapter.js +75 -4
- package/dist/adapters/git-adapter.js.map +1 -1
- package/dist/adapters/github-adapter.d.ts +39 -26
- package/dist/adapters/github-adapter.d.ts.map +1 -1
- package/dist/adapters/github-adapter.js +154 -93
- package/dist/adapters/github-adapter.js.map +1 -1
- package/dist/adapters/index.d.ts +5 -4
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/index.js +6 -5
- package/dist/adapters/index.js.map +1 -1
- package/dist/config.d.ts +52 -4
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +58 -0
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +124 -15
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/format.d.ts +57 -0
- package/dist/utils/format.d.ts.map +1 -0
- package/dist/utils/format.js +154 -0
- package/dist/utils/format.js.map +1 -0
- package/dist/utils/index.d.ts +5 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +5 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/workflows/implement.d.ts +24 -16
- package/dist/workflows/implement.d.ts.map +1 -1
- package/dist/workflows/implement.js +70 -258
- package/dist/workflows/implement.js.map +1 -1
- package/dist/workflows/index.d.ts +6 -0
- package/dist/workflows/index.d.ts.map +1 -1
- package/dist/workflows/index.js +7 -0
- package/dist/workflows/index.js.map +1 -1
- package/dist/workflows/init.d.ts +11 -7
- package/dist/workflows/init.d.ts.map +1 -1
- package/dist/workflows/init.js +16 -107
- package/dist/workflows/init.js.map +1 -1
- package/dist/workflows/merge.d.ts +9 -13
- package/dist/workflows/merge.d.ts.map +1 -1
- package/dist/workflows/merge.js +11 -103
- package/dist/workflows/merge.js.map +1 -1
- package/dist/workflows/release.d.ts +28 -0
- package/dist/workflows/release.d.ts.map +1 -0
- package/dist/workflows/release.js +212 -0
- package/dist/workflows/release.js.map +1 -0
- package/dist/workflows/submit.d.ts +7 -1
- package/dist/workflows/submit.d.ts.map +1 -1
- package/dist/workflows/submit.js +92 -4
- package/dist/workflows/submit.js.map +1 -1
- package/dist/workflows/worktree.d.ts +62 -0
- package/dist/workflows/worktree.d.ts.map +1 -0
- package/dist/workflows/worktree.js +97 -0
- package/dist/workflows/worktree.js.map +1 -0
- package/package.json +2 -2
- package/dist/adapters/claude-cli-adapter.d.ts +0 -72
- package/dist/adapters/claude-cli-adapter.d.ts.map +0 -1
- package/dist/adapters/claude-cli-adapter.js +0 -232
- package/dist/adapters/claude-cli-adapter.js.map +0 -1
- package/dist/adapters/claude-sdk-adapter.d.ts +0 -49
- package/dist/adapters/claude-sdk-adapter.d.ts.map +0 -1
- package/dist/adapters/claude-sdk-adapter.js +0 -278
- package/dist/adapters/claude-sdk-adapter.js.map +0 -1
- package/dist/adapters/cursor-adapter.d.ts +0 -26
- package/dist/adapters/cursor-adapter.d.ts.map +0 -1
- package/dist/adapters/cursor-adapter.js +0 -54
- package/dist/adapters/cursor-adapter.js.map +0 -1
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Release workflow for speclife_release
|
|
3
|
+
*
|
|
4
|
+
* Creates a release PR with version bump, changelog, and git tag.
|
|
5
|
+
*/
|
|
6
|
+
import { readFile, writeFile } from 'fs/promises';
|
|
7
|
+
import { join } from 'path';
|
|
8
|
+
import { SpecLifeError, ErrorCodes, } from '../types.js';
|
|
9
|
+
/** Parse a conventional commit message */
|
|
10
|
+
export function parseConventionalCommit(message) {
|
|
11
|
+
// Match conventional commit format: type(scope)!: description
|
|
12
|
+
const match = message.match(/^(\w+)(?:\(([^)]+)\))?(!)?:\s*(.+)$/);
|
|
13
|
+
if (!match) {
|
|
14
|
+
return { isBreaking: message.includes('BREAKING CHANGE'), description: message };
|
|
15
|
+
}
|
|
16
|
+
const [, type, scope, bang, description] = match;
|
|
17
|
+
const isBreaking = !!bang || message.includes('BREAKING CHANGE');
|
|
18
|
+
return { type, scope, isBreaking, description };
|
|
19
|
+
}
|
|
20
|
+
/** Determine version bump type from commits */
|
|
21
|
+
export function suggestVersionBump(commits, currentVersion) {
|
|
22
|
+
const isPreV1 = currentVersion.startsWith('0.');
|
|
23
|
+
// Check for breaking changes
|
|
24
|
+
const hasBreaking = commits.some(c => c.isBreaking);
|
|
25
|
+
if (hasBreaking) {
|
|
26
|
+
// Pre-1.0: breaking changes bump minor, not major
|
|
27
|
+
return isPreV1 ? 'minor' : 'major';
|
|
28
|
+
}
|
|
29
|
+
// Check for features
|
|
30
|
+
const hasFeature = commits.some(c => c.type === 'feat');
|
|
31
|
+
if (hasFeature) {
|
|
32
|
+
return 'minor';
|
|
33
|
+
}
|
|
34
|
+
// Default to patch
|
|
35
|
+
return 'patch';
|
|
36
|
+
}
|
|
37
|
+
/** Bump a semver version */
|
|
38
|
+
export function bumpVersion(version, bumpType) {
|
|
39
|
+
const match = version.match(/^v?(\d+)\.(\d+)\.(\d+)/);
|
|
40
|
+
if (!match) {
|
|
41
|
+
throw new SpecLifeError(ErrorCodes.CONFIG_INVALID, `Invalid version format: ${version}`);
|
|
42
|
+
}
|
|
43
|
+
let [, major, minor, patch] = match.map(Number);
|
|
44
|
+
switch (bumpType) {
|
|
45
|
+
case 'major':
|
|
46
|
+
major++;
|
|
47
|
+
minor = 0;
|
|
48
|
+
patch = 0;
|
|
49
|
+
break;
|
|
50
|
+
case 'minor':
|
|
51
|
+
minor++;
|
|
52
|
+
patch = 0;
|
|
53
|
+
break;
|
|
54
|
+
case 'patch':
|
|
55
|
+
patch++;
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
return `${major}.${minor}.${patch}`;
|
|
59
|
+
}
|
|
60
|
+
/** Generate changelog from commits */
|
|
61
|
+
export function generateChangelog(commits, version) {
|
|
62
|
+
const date = new Date().toISOString().split('T')[0];
|
|
63
|
+
const lines = [`## [${version}](../../releases/tag/v${version}) (${date})`, ''];
|
|
64
|
+
// Group commits by type
|
|
65
|
+
const features = commits.filter(c => c.type === 'feat');
|
|
66
|
+
const fixes = commits.filter(c => c.type === 'fix');
|
|
67
|
+
const breaking = commits.filter(c => c.isBreaking);
|
|
68
|
+
const other = commits.filter(c => !['feat', 'fix'].includes(c.type || '') && !c.isBreaking);
|
|
69
|
+
if (breaking.length > 0) {
|
|
70
|
+
lines.push('### ⚠ BREAKING CHANGES', '');
|
|
71
|
+
for (const commit of breaking) {
|
|
72
|
+
lines.push(`* ${commit.message}`);
|
|
73
|
+
}
|
|
74
|
+
lines.push('');
|
|
75
|
+
}
|
|
76
|
+
if (features.length > 0) {
|
|
77
|
+
lines.push('### Features', '');
|
|
78
|
+
for (const commit of features) {
|
|
79
|
+
const parsed = parseConventionalCommit(commit.message);
|
|
80
|
+
lines.push(`* ${parsed.description}`);
|
|
81
|
+
}
|
|
82
|
+
lines.push('');
|
|
83
|
+
}
|
|
84
|
+
if (fixes.length > 0) {
|
|
85
|
+
lines.push('### Bug Fixes', '');
|
|
86
|
+
for (const commit of fixes) {
|
|
87
|
+
const parsed = parseConventionalCommit(commit.message);
|
|
88
|
+
lines.push(`* ${parsed.description}`);
|
|
89
|
+
}
|
|
90
|
+
lines.push('');
|
|
91
|
+
}
|
|
92
|
+
if (other.length > 0) {
|
|
93
|
+
lines.push('### Other Changes', '');
|
|
94
|
+
for (const commit of other) {
|
|
95
|
+
lines.push(`* ${commit.message}`);
|
|
96
|
+
}
|
|
97
|
+
lines.push('');
|
|
98
|
+
}
|
|
99
|
+
return lines.join('\n');
|
|
100
|
+
}
|
|
101
|
+
/** Update package.json version in a directory */
|
|
102
|
+
async function updatePackageVersion(dir, version) {
|
|
103
|
+
const pkgPath = join(dir, 'package.json');
|
|
104
|
+
const content = await readFile(pkgPath, 'utf-8');
|
|
105
|
+
const pkg = JSON.parse(content);
|
|
106
|
+
pkg.version = version;
|
|
107
|
+
await writeFile(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
|
|
108
|
+
}
|
|
109
|
+
/** Main release workflow */
|
|
110
|
+
export async function releaseWorkflow(options, adapters, onProgress) {
|
|
111
|
+
const { git, github, repoPath } = adapters;
|
|
112
|
+
// Get latest tag
|
|
113
|
+
onProgress?.({ type: 'step_completed', message: 'Finding latest release...' });
|
|
114
|
+
const latestTag = await git.getLatestTag();
|
|
115
|
+
const previousVersion = latestTag ? latestTag.replace(/^v/, '') : '0.0.0';
|
|
116
|
+
// Get commits since last tag
|
|
117
|
+
onProgress?.({ type: 'step_completed', message: 'Analyzing commits...' });
|
|
118
|
+
const rawCommits = latestTag
|
|
119
|
+
? await git.getCommitsSince(latestTag)
|
|
120
|
+
: await git.getCommitsSince('HEAD~20'); // Fallback: last 20 commits
|
|
121
|
+
if (rawCommits.length === 0) {
|
|
122
|
+
throw new SpecLifeError(ErrorCodes.NO_CHANGES, 'No commits found since last release');
|
|
123
|
+
}
|
|
124
|
+
// Parse commits
|
|
125
|
+
const commits = rawCommits.map(({ sha, message }) => {
|
|
126
|
+
const parsed = parseConventionalCommit(message);
|
|
127
|
+
return {
|
|
128
|
+
sha,
|
|
129
|
+
message,
|
|
130
|
+
type: parsed.type,
|
|
131
|
+
scope: parsed.scope,
|
|
132
|
+
isBreaking: parsed.isBreaking,
|
|
133
|
+
};
|
|
134
|
+
});
|
|
135
|
+
// Determine version
|
|
136
|
+
const bumpType = suggestVersionBump(commits, previousVersion);
|
|
137
|
+
const newVersion = options.version || bumpVersion(previousVersion, bumpType);
|
|
138
|
+
onProgress?.({ type: 'step_completed', message: `Version: ${previousVersion} → ${newVersion} (${bumpType})` });
|
|
139
|
+
// Generate changelog
|
|
140
|
+
const changelog = options.skipChangelog ? undefined : generateChangelog(commits, newVersion);
|
|
141
|
+
// Dry run - return analysis without making changes
|
|
142
|
+
if (options.dryRun) {
|
|
143
|
+
return {
|
|
144
|
+
version: newVersion,
|
|
145
|
+
previousVersion,
|
|
146
|
+
bumpType,
|
|
147
|
+
commits,
|
|
148
|
+
changelog,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
// Create release branch
|
|
152
|
+
const releaseBranch = `release/v${newVersion}`;
|
|
153
|
+
onProgress?.({ type: 'step_completed', message: `Creating branch: ${releaseBranch}` });
|
|
154
|
+
await git.createBranch(releaseBranch, 'main');
|
|
155
|
+
// Update package.json versions
|
|
156
|
+
onProgress?.({ type: 'step_completed', message: 'Updating package versions...' });
|
|
157
|
+
await updatePackageVersion(repoPath, newVersion);
|
|
158
|
+
await updatePackageVersion(join(repoPath, 'packages/core'), newVersion);
|
|
159
|
+
await updatePackageVersion(join(repoPath, 'packages/cli'), newVersion);
|
|
160
|
+
await updatePackageVersion(join(repoPath, 'packages/mcp-server'), newVersion);
|
|
161
|
+
// Commit changes
|
|
162
|
+
await git.add(['.']);
|
|
163
|
+
await git.commit(`chore(release): v${newVersion}`);
|
|
164
|
+
// Push branch
|
|
165
|
+
onProgress?.({ type: 'step_completed', message: 'Pushing release branch...' });
|
|
166
|
+
await git.push('origin', releaseBranch, true);
|
|
167
|
+
// Create PR
|
|
168
|
+
onProgress?.({ type: 'step_completed', message: 'Creating release PR...' });
|
|
169
|
+
const prBody = `## Release v${newVersion}
|
|
170
|
+
|
|
171
|
+
${changelog || 'No changelog generated.'}
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
When merged:
|
|
176
|
+
1. A git tag \`v${newVersion}\` will be created
|
|
177
|
+
2. A GitHub Release will be published
|
|
178
|
+
3. Packages will be published to npm
|
|
179
|
+
|
|
180
|
+
*Created with [SpecLife](https://github.com/malarbase/speclife)*`;
|
|
181
|
+
const pr = await github.createPullRequest({
|
|
182
|
+
title: `chore(release): v${newVersion}`,
|
|
183
|
+
head: releaseBranch,
|
|
184
|
+
base: 'main',
|
|
185
|
+
body: prBody,
|
|
186
|
+
draft: false,
|
|
187
|
+
});
|
|
188
|
+
onProgress?.({ type: 'step_completed', message: `Created PR #${pr.number}: ${pr.url}` });
|
|
189
|
+
// Enable auto-merge if requested
|
|
190
|
+
let autoMergeEnabled = false;
|
|
191
|
+
if (options.autoMerge) {
|
|
192
|
+
onProgress?.({ type: 'step_completed', message: 'Enabling auto-merge...' });
|
|
193
|
+
autoMergeEnabled = await github.enableAutoMerge(pr.number, 'SQUASH');
|
|
194
|
+
if (autoMergeEnabled) {
|
|
195
|
+
onProgress?.({ type: 'step_completed', message: 'Auto-merge enabled - PR will merge when CI passes' });
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
onProgress?.({ type: 'step_completed', message: 'Auto-merge not available (check repo settings)' });
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return {
|
|
202
|
+
version: newVersion,
|
|
203
|
+
previousVersion,
|
|
204
|
+
bumpType,
|
|
205
|
+
commits,
|
|
206
|
+
changelog,
|
|
207
|
+
prUrl: pr.url,
|
|
208
|
+
branch: releaseBranch,
|
|
209
|
+
autoMergeEnabled,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
//# sourceMappingURL=release.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"release.js","sourceRoot":"","sources":["../../src/workflows/release.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,7 +5,7 @@ import { type GitAdapter } from '../adapters/git-adapter.js';
|
|
|
5
5
|
import { type GitHubAdapter } from '../adapters/github-adapter.js';
|
|
6
6
|
import { type OpenSpecAdapter } from '../adapters/openspec-adapter.js';
|
|
7
7
|
import { type SpecLifeConfig } from '../config.js';
|
|
8
|
-
import { type PullRequest, type ProgressCallback } from '../types.js';
|
|
8
|
+
import { type PullRequest, type ProgressCallback, type ValidationReport } from '../types.js';
|
|
9
9
|
export interface SubmitOptions {
|
|
10
10
|
/** Change ID to submit */
|
|
11
11
|
changeId: string;
|
|
@@ -15,6 +15,10 @@ export interface SubmitOptions {
|
|
|
15
15
|
commitMessage?: string;
|
|
16
16
|
/** Skip archiving the change */
|
|
17
17
|
skipArchive?: boolean;
|
|
18
|
+
/** Skip validation check */
|
|
19
|
+
skipValidation?: boolean;
|
|
20
|
+
/** Strict mode - fail on any validation warnings */
|
|
21
|
+
strict?: boolean;
|
|
18
22
|
}
|
|
19
23
|
export interface SubmitResult {
|
|
20
24
|
/** Commit SHA */
|
|
@@ -29,6 +33,8 @@ export interface SubmitResult {
|
|
|
29
33
|
prMarkedReady: boolean;
|
|
30
34
|
/** Whether change was archived */
|
|
31
35
|
archived: boolean;
|
|
36
|
+
/** Validation report (if validation was run) */
|
|
37
|
+
validation?: ValidationReport;
|
|
32
38
|
}
|
|
33
39
|
interface SubmitDependencies {
|
|
34
40
|
git: GitAdapter;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"submit.d.ts","sourceRoot":"","sources":["../../src/workflows/submit.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"submit.d.ts","sourceRoot":"","sources":["../../src/workflows/submit.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAA6B,KAAK,WAAW,EAAE,KAAK,gBAAgB,EAAE,KAAK,gBAAgB,EAAyB,MAAM,aAAa,CAAC;AAE/I,MAAM,WAAW,aAAa;IAC5B,0BAA0B;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,yBAAyB;IACzB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,iEAAiE;IACjE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gCAAgC;IAChC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,4BAA4B;IAC5B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,oDAAoD;IACpD,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,iBAAiB;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,6BAA6B;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,6BAA6B;IAC7B,WAAW,EAAE,WAAW,CAAC;IACzB,sDAAsD;IACtD,SAAS,EAAE,OAAO,CAAC;IACnB,+DAA+D;IAC/D,aAAa,EAAE,OAAO,CAAC;IACvB,kCAAkC;IAClC,QAAQ,EAAE,OAAO,CAAC;IAClB,gDAAgD;IAChD,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC/B;AAED,UAAU,kBAAkB;IAC1B,GAAG,EAAE,UAAU,CAAC;IAChB,MAAM,EAAE,aAAa,CAAC;IACtB,QAAQ,EAAE,eAAe,CAAC;IAC1B,MAAM,EAAE,cAAc,CAAC;CACxB;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,aAAa,EACtB,IAAI,EAAE,kBAAkB,EACxB,UAAU,CAAC,EAAE,gBAAgB,GAC5B,OAAO,CAAC,YAAY,CAAC,CA+LvB"}
|
package/dist/workflows/submit.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Submit workflow - commit, push, create PR, and archive change
|
|
3
3
|
*/
|
|
4
|
+
import { execa } from 'execa';
|
|
4
5
|
import { SpecLifeError, ErrorCodes } from '../types.js';
|
|
5
6
|
/**
|
|
6
7
|
* Submit a change: commit, push, create PR, archive
|
|
7
8
|
*/
|
|
8
9
|
export async function submitWorkflow(options, deps, onProgress) {
|
|
9
|
-
const { changeId, draft = false, commitMessage, skipArchive = false } = options;
|
|
10
|
+
const { changeId, draft = false, commitMessage, skipArchive = false, skipValidation = false, strict = false } = options;
|
|
10
11
|
const { git, github, openspec, config } = deps;
|
|
11
12
|
const branch = `spec/${changeId}`;
|
|
12
13
|
// Verify we're on the right branch
|
|
@@ -18,6 +19,71 @@ export async function submitWorkflow(options, deps, onProgress) {
|
|
|
18
19
|
if (!await openspec.changeExists(changeId)) {
|
|
19
20
|
throw new SpecLifeError(ErrorCodes.CHANGE_NOT_FOUND, `Change '${changeId}' not found`, { changeId });
|
|
20
21
|
}
|
|
22
|
+
// Run validation if not skipped
|
|
23
|
+
let validation;
|
|
24
|
+
if (!skipValidation) {
|
|
25
|
+
onProgress?.({ type: 'step_completed', message: 'Validating spec formatting and structure...' });
|
|
26
|
+
try {
|
|
27
|
+
const args = ['validate', changeId, '--json', '--no-interactive'];
|
|
28
|
+
if (strict) {
|
|
29
|
+
args.push('--strict');
|
|
30
|
+
}
|
|
31
|
+
const result = await execa('openspec', args, {
|
|
32
|
+
cwd: process.cwd(),
|
|
33
|
+
reject: false,
|
|
34
|
+
});
|
|
35
|
+
// Try to parse JSON output
|
|
36
|
+
let output;
|
|
37
|
+
try {
|
|
38
|
+
output = JSON.parse(result.stdout);
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
// If JSON parsing fails, treat as raw output
|
|
42
|
+
validation = {
|
|
43
|
+
status: result.exitCode === 0 ? 'pass' : 'fail',
|
|
44
|
+
errors: result.exitCode !== 0 ? [result.stdout || result.stderr || 'Validation failed'] : [],
|
|
45
|
+
warnings: [],
|
|
46
|
+
output: result.stdout || result.stderr,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
if (output) {
|
|
50
|
+
let status = 'pass';
|
|
51
|
+
const errors = output.errors ?? [];
|
|
52
|
+
const warnings = output.warnings ?? [];
|
|
53
|
+
if (errors.length > 0 || output.valid === false) {
|
|
54
|
+
status = 'fail';
|
|
55
|
+
}
|
|
56
|
+
else if (warnings.length > 0) {
|
|
57
|
+
status = 'pass_with_warnings';
|
|
58
|
+
}
|
|
59
|
+
validation = {
|
|
60
|
+
status,
|
|
61
|
+
errors,
|
|
62
|
+
warnings,
|
|
63
|
+
output: result.stdout,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
if (validation) {
|
|
67
|
+
onProgress?.({
|
|
68
|
+
type: 'step_completed',
|
|
69
|
+
message: `Validation: ${validation.status.toUpperCase().replace('_', ' ')}`,
|
|
70
|
+
});
|
|
71
|
+
if (strict && validation.status === 'pass_with_warnings') {
|
|
72
|
+
throw new SpecLifeError(ErrorCodes.CONFIG_INVALID, `Validation failed in strict mode: ${validation.warnings.length} warnings`, { validation: validation });
|
|
73
|
+
}
|
|
74
|
+
if (validation.status === 'fail') {
|
|
75
|
+
throw new SpecLifeError(ErrorCodes.CONFIG_INVALID, `Validation failed: ${validation.errors.length} errors`, { validation: validation });
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
if (error instanceof SpecLifeError) {
|
|
81
|
+
throw error;
|
|
82
|
+
}
|
|
83
|
+
// openspec validate might not be available - continue without validation
|
|
84
|
+
onProgress?.({ type: 'step_completed', message: `openspec validate not available: ${error instanceof Error ? error.message : String(error)}, proceeding` });
|
|
85
|
+
}
|
|
86
|
+
}
|
|
21
87
|
// Get git status
|
|
22
88
|
const status = await git.status();
|
|
23
89
|
const hasChanges = status.staged.length > 0 ||
|
|
@@ -51,7 +117,7 @@ export async function submitWorkflow(options, deps, onProgress) {
|
|
|
51
117
|
if (!pullRequest) {
|
|
52
118
|
// Create PR
|
|
53
119
|
onProgress?.({ type: 'step_completed', message: 'Creating pull request' });
|
|
54
|
-
const prBody = generatePRBody(change);
|
|
120
|
+
const prBody = generatePRBody(change, validation);
|
|
55
121
|
pullRequest = await github.createPullRequest({
|
|
56
122
|
title: generatePRTitle(changeId, change.proposal.why),
|
|
57
123
|
body: prBody,
|
|
@@ -82,13 +148,16 @@ export async function submitWorkflow(options, deps, onProgress) {
|
|
|
82
148
|
archived = true;
|
|
83
149
|
}
|
|
84
150
|
onProgress?.({ type: 'step_completed', message: 'Submit complete' });
|
|
151
|
+
// pullRequest is guaranteed non-null at this point
|
|
152
|
+
// (either from getPullRequestByBranch or createPullRequest)
|
|
85
153
|
return {
|
|
86
154
|
commitSha,
|
|
87
155
|
branch,
|
|
88
|
-
pullRequest,
|
|
156
|
+
pullRequest: pullRequest,
|
|
89
157
|
prCreated,
|
|
90
158
|
prMarkedReady,
|
|
91
159
|
archived,
|
|
160
|
+
validation,
|
|
92
161
|
};
|
|
93
162
|
}
|
|
94
163
|
/**
|
|
@@ -127,7 +196,7 @@ function generatePRTitle(changeId, why) {
|
|
|
127
196
|
/**
|
|
128
197
|
* Generate PR body from change proposal
|
|
129
198
|
*/
|
|
130
|
-
function generatePRBody(change) {
|
|
199
|
+
function generatePRBody(change, validation) {
|
|
131
200
|
const lines = [
|
|
132
201
|
'## Why',
|
|
133
202
|
change.proposal.why,
|
|
@@ -137,6 +206,25 @@ function generatePRBody(change) {
|
|
|
137
206
|
for (const item of change.proposal.whatChanges) {
|
|
138
207
|
lines.push(`- ${item}`);
|
|
139
208
|
}
|
|
209
|
+
// Add validation section if validation was run
|
|
210
|
+
if (validation) {
|
|
211
|
+
lines.push('', '## Spec Validation');
|
|
212
|
+
const statusEmoji = validation.status === 'pass' ? '✅' :
|
|
213
|
+
validation.status === 'pass_with_warnings' ? '⚠️' : '❌';
|
|
214
|
+
lines.push(`**Status:** ${statusEmoji} ${validation.status.replace(/_/g, ' ').toUpperCase()}`);
|
|
215
|
+
if (validation.errors.length > 0) {
|
|
216
|
+
lines.push('', '### Errors');
|
|
217
|
+
for (const error of validation.errors) {
|
|
218
|
+
lines.push(`- ❌ ${error}`);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
if (validation.warnings.length > 0) {
|
|
222
|
+
lines.push('', '### Warnings');
|
|
223
|
+
for (const warning of validation.warnings) {
|
|
224
|
+
lines.push(`- ⚠️ ${warning}`);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
140
228
|
lines.push('', '---', '*Created with [SpecLife](https://github.com/malarbase/speclife)*');
|
|
141
229
|
return lines.join('\n');
|
|
142
230
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"submit.js","sourceRoot":"","sources":["../../src/workflows/submit.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"submit.js","sourceRoot":"","sources":["../../src/workflows/submit.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Worktree workflow - manage git worktrees for isolated change development
|
|
3
|
+
*/
|
|
4
|
+
import { type GitAdapter } from '../adapters/git-adapter.js';
|
|
5
|
+
import { type EnvironmentRegistry, type BootstrapResult } from '../adapters/environment-adapter.js';
|
|
6
|
+
import { type SpecLifeConfig } from '../config.js';
|
|
7
|
+
import { type ProgressCallback } from '../types.js';
|
|
8
|
+
export interface WorktreeCreateOptions {
|
|
9
|
+
/** Change identifier (kebab-case) */
|
|
10
|
+
changeId: string;
|
|
11
|
+
/** Base branch to create worktree from (defaults to config.git.baseBranch) */
|
|
12
|
+
baseBranch?: string;
|
|
13
|
+
/** Skip environment bootstrap */
|
|
14
|
+
skipBootstrap?: boolean;
|
|
15
|
+
}
|
|
16
|
+
export interface WorktreeCreateResult {
|
|
17
|
+
/** Created branch name */
|
|
18
|
+
branch: string;
|
|
19
|
+
/** Worktree path */
|
|
20
|
+
worktreePath: string;
|
|
21
|
+
/** Environment bootstrap results */
|
|
22
|
+
bootstrapResults?: BootstrapResult[];
|
|
23
|
+
}
|
|
24
|
+
export interface WorktreeRemoveOptions {
|
|
25
|
+
/** Change identifier */
|
|
26
|
+
changeId: string;
|
|
27
|
+
/** Force removal even if there are uncommitted changes */
|
|
28
|
+
force?: boolean;
|
|
29
|
+
}
|
|
30
|
+
export interface WorktreeRemoveResult {
|
|
31
|
+
/** Removed branch name */
|
|
32
|
+
branch: string;
|
|
33
|
+
/** Removed worktree path */
|
|
34
|
+
worktreePath: string;
|
|
35
|
+
}
|
|
36
|
+
export interface WorktreeListResult {
|
|
37
|
+
/** List of active worktrees */
|
|
38
|
+
worktrees: Array<{
|
|
39
|
+
changeId: string;
|
|
40
|
+
branch: string;
|
|
41
|
+
path: string;
|
|
42
|
+
}>;
|
|
43
|
+
}
|
|
44
|
+
interface WorktreeDependencies {
|
|
45
|
+
git: GitAdapter;
|
|
46
|
+
config: SpecLifeConfig;
|
|
47
|
+
environmentRegistry?: EnvironmentRegistry;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Create a new worktree for isolated change development
|
|
51
|
+
*/
|
|
52
|
+
export declare function worktreeCreate(options: WorktreeCreateOptions, deps: WorktreeDependencies, onProgress?: ProgressCallback): Promise<WorktreeCreateResult>;
|
|
53
|
+
/**
|
|
54
|
+
* Remove a worktree and its branch
|
|
55
|
+
*/
|
|
56
|
+
export declare function worktreeRemove(options: WorktreeRemoveOptions, deps: Pick<WorktreeDependencies, 'git' | 'config'>, onProgress?: ProgressCallback): Promise<WorktreeRemoveResult>;
|
|
57
|
+
/**
|
|
58
|
+
* List all active worktrees
|
|
59
|
+
*/
|
|
60
|
+
export declare function worktreeList(deps: Pick<WorktreeDependencies, 'git' | 'config'>, _onProgress?: ProgressCallback): Promise<WorktreeListResult>;
|
|
61
|
+
export {};
|
|
62
|
+
//# sourceMappingURL=worktree.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worktree.d.ts","sourceRoot":"","sources":["../../src/workflows/worktree.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,eAAe,EAErB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAA6B,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/E,MAAM,WAAW,qBAAqB;IACpC,qCAAqC;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iCAAiC;IACjC,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,oBAAoB;IACnC,0BAA0B;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,oBAAoB;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,oCAAoC;IACpC,gBAAgB,CAAC,EAAE,eAAe,EAAE,CAAC;CACtC;AAED,MAAM,WAAW,qBAAqB;IACpC,wBAAwB;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,0DAA0D;IAC1D,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,oBAAoB;IACnC,0BAA0B;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,4BAA4B;IAC5B,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB;IACjC,+BAA+B;IAC/B,SAAS,EAAE,KAAK,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;KACd,CAAC,CAAC;CACJ;AAED,UAAU,oBAAoB;IAC5B,GAAG,EAAE,UAAU,CAAC;IAChB,MAAM,EAAE,cAAc,CAAC;IACvB,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;CAC3C;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,qBAAqB,EAC9B,IAAI,EAAE,oBAAoB,EAC1B,UAAU,CAAC,EAAE,gBAAgB,GAC5B,OAAO,CAAC,oBAAoB,CAAC,CAiE/B;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,qBAAqB,EAC9B,IAAI,EAAE,IAAI,CAAC,oBAAoB,EAAE,KAAK,GAAG,QAAQ,CAAC,EAClD,UAAU,CAAC,EAAE,gBAAgB,GAC5B,OAAO,CAAC,oBAAoB,CAAC,CA6B/B;AAED;;GAEG;AACH,wBAAsB,YAAY,CAChC,IAAI,EAAE,IAAI,CAAC,oBAAoB,EAAE,KAAK,GAAG,QAAQ,CAAC,EAClD,WAAW,CAAC,EAAE,gBAAgB,GAC7B,OAAO,CAAC,kBAAkB,CAAC,CAkB7B"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Worktree workflow - manage git worktrees for isolated change development
|
|
3
|
+
*/
|
|
4
|
+
import { createDefaultEnvironmentRegistry, } from '../adapters/environment-adapter.js';
|
|
5
|
+
import { SpecLifeError, ErrorCodes } from '../types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Create a new worktree for isolated change development
|
|
8
|
+
*/
|
|
9
|
+
export async function worktreeCreate(options, deps, onProgress) {
|
|
10
|
+
const { changeId, baseBranch, skipBootstrap = false } = options;
|
|
11
|
+
const { git, config, environmentRegistry } = deps;
|
|
12
|
+
// Validate changeId format (kebab-case)
|
|
13
|
+
if (!/^[a-z][a-z0-9]*(-[a-z0-9]+)*$/.test(changeId)) {
|
|
14
|
+
throw new SpecLifeError(ErrorCodes.CONFIG_INVALID, `Invalid changeId format: "${changeId}". Must be kebab-case (e.g., "add-user-auth")`, { changeId });
|
|
15
|
+
}
|
|
16
|
+
const branchPrefix = config.git?.branchPrefix ?? 'spec/';
|
|
17
|
+
const worktreeDir = config.git?.worktreeDir ?? 'worktrees';
|
|
18
|
+
const base = baseBranch ?? config.git?.baseBranch ?? 'main';
|
|
19
|
+
const branch = `${branchPrefix}${changeId}`;
|
|
20
|
+
const worktreePath = `${worktreeDir}/${changeId}`;
|
|
21
|
+
// Check if branch already exists
|
|
22
|
+
if (await git.branchExists(branch)) {
|
|
23
|
+
throw new SpecLifeError(ErrorCodes.BRANCH_EXISTS, `Branch '${branch}' already exists`, { branch });
|
|
24
|
+
}
|
|
25
|
+
// Create worktree
|
|
26
|
+
onProgress?.({ type: 'step_completed', message: `Creating worktree at ${worktreePath}` });
|
|
27
|
+
await git.createWorktree(worktreePath, branch, base);
|
|
28
|
+
// Bootstrap environment
|
|
29
|
+
let bootstrapResults;
|
|
30
|
+
if (!skipBootstrap) {
|
|
31
|
+
const registry = environmentRegistry ?? createDefaultEnvironmentRegistry();
|
|
32
|
+
const strategy = config.worktree?.bootstrap?.strategy ?? 'symlink';
|
|
33
|
+
onProgress?.({ type: 'step_completed', message: 'Bootstrapping environments' });
|
|
34
|
+
const sourceRoot = process.cwd();
|
|
35
|
+
bootstrapResults = await registry.bootstrapAll(worktreePath, sourceRoot, strategy, onProgress);
|
|
36
|
+
const successful = bootstrapResults.filter(r => r.success);
|
|
37
|
+
if (successful.length > 0) {
|
|
38
|
+
onProgress?.({
|
|
39
|
+
type: 'step_completed',
|
|
40
|
+
message: `Bootstrapped: ${successful.map(r => r.environment).join(', ')}`,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
onProgress?.({ type: 'step_completed', message: 'Worktree created' });
|
|
45
|
+
return {
|
|
46
|
+
branch,
|
|
47
|
+
worktreePath,
|
|
48
|
+
bootstrapResults,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Remove a worktree and its branch
|
|
53
|
+
*/
|
|
54
|
+
export async function worktreeRemove(options, deps, onProgress) {
|
|
55
|
+
const { changeId, force = false } = options;
|
|
56
|
+
const { git, config } = deps;
|
|
57
|
+
const branchPrefix = config.git?.branchPrefix ?? 'spec/';
|
|
58
|
+
const worktreeDir = config.git?.worktreeDir ?? 'worktrees';
|
|
59
|
+
const branch = `${branchPrefix}${changeId}`;
|
|
60
|
+
const worktreePath = `${worktreeDir}/${changeId}`;
|
|
61
|
+
// Remove worktree
|
|
62
|
+
onProgress?.({ type: 'step_completed', message: `Removing worktree at ${worktreePath}` });
|
|
63
|
+
await git.removeWorktree(worktreePath, force);
|
|
64
|
+
// Delete local branch (remote branch may have been deleted by PR merge)
|
|
65
|
+
onProgress?.({ type: 'step_completed', message: `Deleting branch ${branch}` });
|
|
66
|
+
try {
|
|
67
|
+
await git.deleteBranch(branch, force);
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
// Branch may already be deleted or merged
|
|
71
|
+
onProgress?.({ type: 'step_completed', message: 'Branch already deleted or merged' });
|
|
72
|
+
}
|
|
73
|
+
onProgress?.({ type: 'step_completed', message: 'Worktree removed' });
|
|
74
|
+
return {
|
|
75
|
+
branch,
|
|
76
|
+
worktreePath,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* List all active worktrees
|
|
81
|
+
*/
|
|
82
|
+
export async function worktreeList(deps, _onProgress) {
|
|
83
|
+
const { git, config } = deps;
|
|
84
|
+
const branchPrefix = config.git?.branchPrefix ?? 'spec/';
|
|
85
|
+
const worktreeDir = config.git?.worktreeDir ?? 'worktrees';
|
|
86
|
+
const worktrees = await git.listWorktrees();
|
|
87
|
+
// Filter to only spec worktrees
|
|
88
|
+
const specWorktrees = worktrees
|
|
89
|
+
.filter(wt => wt.branch?.startsWith(branchPrefix) && wt.path.includes(worktreeDir))
|
|
90
|
+
.map(wt => ({
|
|
91
|
+
changeId: wt.branch.replace(branchPrefix, ''),
|
|
92
|
+
branch: wt.branch,
|
|
93
|
+
path: wt.path,
|
|
94
|
+
}));
|
|
95
|
+
return { worktrees: specWorktrees };
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=worktree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worktree.js","sourceRoot":"","sources":["../../src/workflows/worktree.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@speclife/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Core library for SpecLife - adapters and workflows",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
},
|
|
27
27
|
"scripts": {
|
|
28
28
|
"build": "tsc",
|
|
29
|
-
"test": "vitest run
|
|
29
|
+
"test": "vitest run",
|
|
30
30
|
"test:watch": "vitest",
|
|
31
31
|
"typecheck": "tsc --noEmit"
|
|
32
32
|
},
|