@shepai/cli 1.30.0 → 1.32.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/packages/core/src/application/ports/output/agents/feature-agent-process.interface.d.ts +4 -0
- package/dist/packages/core/src/application/ports/output/agents/feature-agent-process.interface.d.ts.map +1 -1
- package/dist/packages/core/src/application/ports/output/services/git-pr-service.interface.d.ts +165 -0
- package/dist/packages/core/src/application/ports/output/services/git-pr-service.interface.d.ts.map +1 -0
- package/dist/packages/core/src/application/ports/output/services/git-pr-service.interface.js +34 -0
- package/dist/packages/core/src/application/ports/output/services/index.d.ts +2 -0
- package/dist/packages/core/src/application/ports/output/services/index.d.ts.map +1 -1
- package/dist/packages/core/src/application/ports/output/services/index.js +1 -0
- package/dist/packages/core/src/application/use-cases/features/create/create-feature.use-case.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/features/create/create-feature.use-case.js +5 -0
- package/dist/packages/core/src/application/use-cases/features/create/types.d.ts +2 -0
- package/dist/packages/core/src/application/use-cases/features/create/types.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/features/resume-feature.use-case.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/features/resume-feature.use-case.js +3 -0
- package/dist/packages/core/src/domain/factories/settings-defaults.factory.d.ts.map +1 -1
- package/dist/packages/core/src/domain/factories/settings-defaults.factory.js +5 -0
- package/dist/packages/core/src/domain/generated/output.d.ts +70 -1
- package/dist/packages/core/src/domain/generated/output.d.ts.map +1 -1
- package/dist/packages/core/src/domain/generated/output.js +15 -1
- package/dist/packages/core/src/infrastructure/di/container.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/di/container.js +2 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/feature.mapper.d.ts +10 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/feature.mapper.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/feature.mapper.js +24 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/settings.mapper.d.ts +2 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/settings.mapper.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/settings.mapper.js +10 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations.js +27 -0
- package/dist/packages/core/src/infrastructure/repositories/sqlite-feature.repository.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/repositories/sqlite-feature.repository.js +18 -2
- package/dist/packages/core/src/infrastructure/repositories/sqlite-settings.repository.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/repositories/sqlite-settings.repository.js +7 -3
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/claude-code-executor.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/claude-code-executor.service.js +5 -0
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/cursor-executor.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/cursor-executor.service.js +4 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-graph.d.ts +148 -3
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-graph.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-graph.js +20 -5
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-process.service.d.ts +4 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-process.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-process.service.js +12 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.d.ts +4 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.js +29 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge.node.d.ts +27 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge.node.d.ts.map +1 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge.node.js +146 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.d.ts +5 -2
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.js +9 -3
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/pr-yaml-generator.d.ts +17 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/pr-yaml-generator.d.ts.map +1 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/pr-yaml-generator.js +43 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/merge.prompt.d.ts +17 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/merge.prompt.d.ts.map +1 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/merge.prompt.js +42 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/state.d.ts +8 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/state.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/state.js +33 -0
- package/dist/packages/core/src/infrastructure/services/git/git-pr.service.d.ts +28 -0
- package/dist/packages/core/src/infrastructure/services/git/git-pr.service.d.ts.map +1 -0
- package/dist/packages/core/src/infrastructure/services/git/git-pr.service.js +182 -0
- package/dist/src/presentation/cli/commands/feat/new.command.d.ts.map +1 -1
- package/dist/src/presentation/cli/commands/feat/new.command.js +33 -2
- package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.d.ts +13 -2
- package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.js +4 -13
- package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.stories.d.ts +4 -10
- package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.stories.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.stories.js +7 -19
- package/dist/src/presentation/web/components/common/feature-create-drawer/index.d.ts +1 -1
- package/dist/src/presentation/web/components/common/feature-create-drawer/index.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-drawer/feature-drawer.stories.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-drawer/feature-drawer.stories.js +11 -0
- package/dist/src/presentation/web/components/common/feature-node/feature-node-state-config.d.ts +1 -1
- package/dist/src/presentation/web/components/common/feature-node/feature-node-state-config.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-node/feature-node-state-config.js +10 -0
- package/dist/src/presentation/web/components/common/feature-node/feature-node.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-node/feature-node.js +4 -2
- package/dist/src/presentation/web/components/common/feature-node/feature-node.stories.d.ts +1 -0
- package/dist/src/presentation/web/components/common/feature-node/feature-node.stories.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-node/feature-node.stories.js +21 -0
- package/dist/src/presentation/web/components/common/index.d.ts +1 -1
- package/dist/src/presentation/web/components/common/index.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/index.js +1 -1
- package/dist/src/presentation/web/components/features/control-center/control-center-inner.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/control-center/control-center-inner.js +2 -2
- package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts +3 -3
- package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/control-center/use-control-center-state.js +76 -23
- package/dist/src/presentation/web/components/features/features-canvas/features-canvas.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/features-canvas/features-canvas.js +2 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +5 -3
- package/web/.next/BUILD_ID +1 -1
- package/web/.next/build-manifest.json +2 -2
- package/web/.next/cache/.previewinfo +1 -1
- package/web/.next/cache/.rscinfo +1 -1
- package/web/.next/cache/.tsbuildinfo +1 -1
- package/web/.next/cache/config.json +3 -3
- package/web/.next/fallback-build-manifest.json +2 -2
- package/web/.next/prerender-manifest.json +3 -3
- package/web/.next/required-server-files.js +1 -1
- package/web/.next/required-server-files.json +1 -1
- package/web/.next/server/app/_global-error.html +2 -2
- package/web/.next/server/app/_global-error.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/_not-found.html +2 -2
- package/web/.next/server/app/_not-found.rsc +10 -10
- package/web/.next/server/app/_not-found.segments/_full.segment.rsc +10 -10
- package/web/.next/server/app/_not-found.segments/_head.segment.rsc +3 -3
- package/web/.next/server/app/_not-found.segments/_index.segment.rsc +6 -6
- package/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
- package/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
- package/web/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/web/.next/server/app/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/version.html +2 -2
- package/web/.next/server/app/version.rsc +5 -5
- package/web/.next/server/app/version.segments/_full.segment.rsc +5 -5
- package/web/.next/server/app/version.segments/_head.segment.rsc +1 -1
- package/web/.next/server/app/version.segments/_index.segment.rsc +4 -4
- package/web/.next/server/app/version.segments/_tree.segment.rsc +2 -2
- package/web/.next/server/app/version.segments/version/__PAGE__.segment.rsc +2 -2
- package/web/.next/server/app/version.segments/version.segment.rsc +1 -1
- package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_12059e3e.js +1 -1
- package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_12059e3e.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__f12b60be._.js +1 -1
- package/web/.next/server/chunks/ssr/_09afa42a._.js +2 -7
- package/web/.next/server/chunks/ssr/_09afa42a._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_ed0934e5._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_ed0934e5._.js.map +1 -1
- package/web/.next/server/pages/404.html +2 -2
- package/web/.next/server/pages/500.html +2 -2
- package/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/server/server-reference-manifest.json +1 -1
- package/web/.next/static/chunks/{daacb9d30e4fc428.js → 48b2cea957bfe6ab.js} +2 -7
- package/web/.next/static/chunks/9993505b2a26c454.js +1 -0
- package/web/.next/static/chunks/{fd816afd85fd9a19.css → b98242e5ef2a1bd3.css} +1 -1
- package/web/.next/trace +1 -1
- package/web/.next/trace-build +1 -1
- package/web/.next/static/chunks/b32b17f102226f32.js +0 -1
- /package/web/.next/static/{C_QsuOPQWDrYc18EOtMAm → 9kF5HqLN2Pcx3uc1dCFjr}/_buildManifest.js +0 -0
- /package/web/.next/static/{C_QsuOPQWDrYc18EOtMAm → 9kF5HqLN2Pcx3uc1dCFjr}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{C_QsuOPQWDrYc18EOtMAm → 9kF5HqLN2Pcx3uc1dCFjr}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git PR Service Implementation
|
|
3
|
+
*
|
|
4
|
+
* Manages git operations for PR creation, merging, and CI status checks.
|
|
5
|
+
* Uses constructor dependency injection for the command executor.
|
|
6
|
+
*/
|
|
7
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
8
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
10
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
11
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
12
|
+
};
|
|
13
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
14
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
15
|
+
};
|
|
16
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
17
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
18
|
+
};
|
|
19
|
+
import { injectable, inject } from 'tsyringe';
|
|
20
|
+
import { GitPrError, GitPrErrorCode, } from '../../../application/ports/output/services/git-pr-service.interface.js';
|
|
21
|
+
let GitPrService = class GitPrService {
|
|
22
|
+
execFile;
|
|
23
|
+
constructor(execFile) {
|
|
24
|
+
this.execFile = execFile;
|
|
25
|
+
}
|
|
26
|
+
async hasUncommittedChanges(cwd) {
|
|
27
|
+
const { stdout } = await this.execFile('git', ['status', '--porcelain'], { cwd });
|
|
28
|
+
return stdout.trim().length > 0;
|
|
29
|
+
}
|
|
30
|
+
async commitAll(cwd, message) {
|
|
31
|
+
try {
|
|
32
|
+
await this.execFile('git', ['add', '-A'], { cwd });
|
|
33
|
+
await this.execFile('git', ['commit', '-m', message], { cwd });
|
|
34
|
+
const { stdout } = await this.execFile('git', ['rev-parse', 'HEAD'], { cwd });
|
|
35
|
+
return stdout.trim();
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
throw this.parseGitError(error);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async push(cwd, branch, setUpstream) {
|
|
42
|
+
const args = ['push'];
|
|
43
|
+
if (setUpstream)
|
|
44
|
+
args.push('--set-upstream');
|
|
45
|
+
args.push('origin', branch);
|
|
46
|
+
try {
|
|
47
|
+
await this.execFile('git', args, { cwd });
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
throw this.parseGitError(error);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
async createPr(cwd, prYamlPath) {
|
|
54
|
+
try {
|
|
55
|
+
const { stdout } = await this.execFile('gh', ['pr', 'create', '--title', prYamlPath, '--body-file', prYamlPath], { cwd });
|
|
56
|
+
const url = stdout.trim();
|
|
57
|
+
const number = this.parsePrNumberFromUrl(url);
|
|
58
|
+
return { url, number };
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
throw this.parseGhError(error);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
async mergePr(cwd, prNumber, strategy = 'squash') {
|
|
65
|
+
try {
|
|
66
|
+
await this.execFile('gh', ['pr', 'merge', String(prNumber), `--${strategy}`], { cwd });
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
70
|
+
const cause = error instanceof Error ? error : undefined;
|
|
71
|
+
throw new GitPrError(message, GitPrErrorCode.MERGE_FAILED, cause);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
async mergeBranch(cwd, sourceBranch, targetBranch) {
|
|
75
|
+
try {
|
|
76
|
+
await this.execFile('git', ['checkout', targetBranch], { cwd });
|
|
77
|
+
await this.execFile('git', ['merge', sourceBranch], { cwd });
|
|
78
|
+
await this.execFile('git', ['push'], { cwd });
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
throw this.parseGitError(error);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
async getCiStatus(cwd, branch) {
|
|
85
|
+
const { stdout } = await this.execFile('gh', ['run', 'list', '--branch', branch, '--json', 'conclusion,url', '--limit', '1'], { cwd });
|
|
86
|
+
const runs = JSON.parse(stdout);
|
|
87
|
+
if (runs.length === 0 || !runs[0].conclusion) {
|
|
88
|
+
return { status: 'pending', runUrl: runs[0]?.url };
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
status: runs[0].conclusion === 'success' ? 'success' : 'failure',
|
|
92
|
+
runUrl: runs[0].url,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
async watchCi(cwd, branch, timeoutMs) {
|
|
96
|
+
try {
|
|
97
|
+
const args = ['run', 'watch', '--branch', branch];
|
|
98
|
+
const { stdout } = await this.execFile('gh', args, {
|
|
99
|
+
cwd,
|
|
100
|
+
...(timeoutMs ? { timeout: timeoutMs } : {}),
|
|
101
|
+
});
|
|
102
|
+
const isSuccess = stdout.includes('success') || stdout.includes('completed');
|
|
103
|
+
return {
|
|
104
|
+
status: isSuccess ? 'success' : 'failure',
|
|
105
|
+
logExcerpt: stdout.trim(),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
110
|
+
const cause = error instanceof Error ? error : undefined;
|
|
111
|
+
if (message.includes('timed out') || message.includes('timeout')) {
|
|
112
|
+
throw new GitPrError(message, GitPrErrorCode.CI_TIMEOUT, cause);
|
|
113
|
+
}
|
|
114
|
+
throw new GitPrError(message, GitPrErrorCode.GIT_ERROR, cause);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
async deleteBranch(cwd, branch, deleteRemote) {
|
|
118
|
+
try {
|
|
119
|
+
await this.execFile('git', ['branch', '-d', branch], { cwd });
|
|
120
|
+
if (deleteRemote) {
|
|
121
|
+
await this.execFile('git', ['push', 'origin', '--delete', branch], { cwd });
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
throw this.parseGitError(error);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
async getPrDiffSummary(cwd, baseBranch) {
|
|
129
|
+
const { stdout: diffStat } = await this.execFile('git', ['diff', '--stat', `${baseBranch}...HEAD`], { cwd });
|
|
130
|
+
const { stdout: logOutput } = await this.execFile('git', ['log', '--oneline', `${baseBranch}...HEAD`], { cwd });
|
|
131
|
+
return this.parseDiffStat(diffStat, logOutput);
|
|
132
|
+
}
|
|
133
|
+
parseGitError(error) {
|
|
134
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
135
|
+
const cause = error instanceof Error ? error : undefined;
|
|
136
|
+
if (message.includes('rejected') || message.includes('conflict')) {
|
|
137
|
+
return new GitPrError(message, GitPrErrorCode.MERGE_CONFLICT, cause);
|
|
138
|
+
}
|
|
139
|
+
if (message.includes('Authentication') || message.includes('auth') || message.includes('403')) {
|
|
140
|
+
return new GitPrError(message, GitPrErrorCode.AUTH_FAILURE, cause);
|
|
141
|
+
}
|
|
142
|
+
return new GitPrError(message, GitPrErrorCode.GIT_ERROR, cause);
|
|
143
|
+
}
|
|
144
|
+
parseGhError(error) {
|
|
145
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
146
|
+
const cause = error instanceof Error ? error : undefined;
|
|
147
|
+
const errnoCode = error?.code;
|
|
148
|
+
if (errnoCode === 'ENOENT' || message.includes('ENOENT')) {
|
|
149
|
+
return new GitPrError(message, GitPrErrorCode.GH_NOT_FOUND, cause);
|
|
150
|
+
}
|
|
151
|
+
if (message.includes('Authentication') || message.includes('auth') || message.includes('403')) {
|
|
152
|
+
return new GitPrError(message, GitPrErrorCode.AUTH_FAILURE, cause);
|
|
153
|
+
}
|
|
154
|
+
return new GitPrError(message, GitPrErrorCode.GIT_ERROR, cause);
|
|
155
|
+
}
|
|
156
|
+
parsePrNumberFromUrl(url) {
|
|
157
|
+
const match = url.match(/\/pull\/(\d+)/);
|
|
158
|
+
return match ? parseInt(match[1], 10) : 0;
|
|
159
|
+
}
|
|
160
|
+
parseDiffStat(diffStat, logOutput) {
|
|
161
|
+
const summaryLine = diffStat.trim().split('\n').pop() ?? '';
|
|
162
|
+
const filesMatch = summaryLine.match(/(\d+)\s+files?\s+changed/);
|
|
163
|
+
const addMatch = summaryLine.match(/(\d+)\s+insertions?\(\+\)/);
|
|
164
|
+
const delMatch = summaryLine.match(/(\d+)\s+deletions?\(-\)/);
|
|
165
|
+
const commitCount = logOutput
|
|
166
|
+
.trim()
|
|
167
|
+
.split('\n')
|
|
168
|
+
.filter((l) => l.trim()).length;
|
|
169
|
+
return {
|
|
170
|
+
filesChanged: filesMatch ? parseInt(filesMatch[1], 10) : 0,
|
|
171
|
+
additions: addMatch ? parseInt(addMatch[1], 10) : 0,
|
|
172
|
+
deletions: delMatch ? parseInt(delMatch[1], 10) : 0,
|
|
173
|
+
commitCount,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
GitPrService = __decorate([
|
|
178
|
+
injectable(),
|
|
179
|
+
__param(0, inject('ExecFunction')),
|
|
180
|
+
__metadata("design:paramtypes", [Function])
|
|
181
|
+
], GitPrService);
|
|
182
|
+
export { GitPrService };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"new.command.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/cli/commands/feat/new.command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"new.command.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/cli/commands/feat/new.command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkCpC;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAsF1C"}
|
|
@@ -16,6 +16,20 @@ import { container } from '../../../../../packages/core/src/infrastructure/di/co
|
|
|
16
16
|
import { CreateFeatureUseCase } from '../../../../../packages/core/src/application/use-cases/features/create/create-feature.use-case.js';
|
|
17
17
|
import { colors, messages, spinner } from '../../ui/index.js';
|
|
18
18
|
import { getShepHomeDir } from '../../../../../packages/core/src/infrastructure/services/filesystem/shep-directory.service.js';
|
|
19
|
+
import { getSettings, hasSettings } from '../../../../../packages/core/src/infrastructure/services/settings.service.js';
|
|
20
|
+
/**
|
|
21
|
+
* Read workflow defaults from settings, falling back to false if settings unavailable.
|
|
22
|
+
*/
|
|
23
|
+
function getWorkflowDefaults() {
|
|
24
|
+
if (!hasSettings()) {
|
|
25
|
+
return { openPr: false, autoMerge: false };
|
|
26
|
+
}
|
|
27
|
+
const settings = getSettings();
|
|
28
|
+
return {
|
|
29
|
+
openPr: settings.workflow.openPrOnImplementationComplete,
|
|
30
|
+
autoMerge: settings.workflow.autoMergeOnImplementationComplete,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
19
33
|
/**
|
|
20
34
|
* Create the feat new command
|
|
21
35
|
*/
|
|
@@ -24,26 +38,43 @@ export function createNewCommand() {
|
|
|
24
38
|
.description('Create a new feature')
|
|
25
39
|
.argument('<description>', 'Feature description')
|
|
26
40
|
.option('-r, --repo <path>', 'Repository path (defaults to current directory)')
|
|
41
|
+
.option('--pr', 'Open PR on implementation complete')
|
|
42
|
+
.option('--no-pr', 'Do not open PR on implementation complete')
|
|
43
|
+
.option('--auto-merge', 'Auto-merge on implementation complete')
|
|
44
|
+
.option('--no-auto-merge', 'Do not auto-merge on implementation complete')
|
|
27
45
|
.option('--allow-prd', 'Auto-approve through requirements, pause after')
|
|
28
46
|
.option('--allow-plan', 'Auto-approve through planning, pause at implementation')
|
|
47
|
+
.option('--allow-merge', 'Auto-approve merge phase')
|
|
29
48
|
.option('--allow-all', 'Run fully autonomous (no approval pauses)')
|
|
30
49
|
.action(async (description, options) => {
|
|
31
50
|
try {
|
|
32
51
|
const useCase = container.resolve(CreateFeatureUseCase);
|
|
33
52
|
const repoPath = options.repo ?? process.cwd();
|
|
53
|
+
// Resolve openPr and autoMerge from CLI flags or settings defaults
|
|
54
|
+
const defaults = getWorkflowDefaults();
|
|
55
|
+
const openPr = options.pr ?? defaults.openPr;
|
|
56
|
+
const autoMerge = options.autoMerge ?? defaults.autoMerge;
|
|
34
57
|
// Build approval gates from flags (default: pause after every phase)
|
|
35
58
|
let approvalGates = {
|
|
36
59
|
allowPrd: !!options.allowPrd,
|
|
37
60
|
allowPlan: !!options.allowPlan,
|
|
38
61
|
allowMerge: false,
|
|
39
62
|
};
|
|
40
|
-
if (options.
|
|
63
|
+
if (options.allowPlan)
|
|
64
|
+
approvalGates = { allowPrd: true, allowPlan: true, allowMerge: approvalGates.allowMerge };
|
|
65
|
+
if (options.allowMerge)
|
|
66
|
+
approvalGates = { ...approvalGates, allowMerge: true };
|
|
67
|
+
// --auto-merge implies --allow-merge
|
|
68
|
+
if (autoMerge)
|
|
69
|
+
approvalGates = { ...approvalGates, allowMerge: true };
|
|
70
|
+
if (options.allowAll)
|
|
41
71
|
approvalGates = undefined; // no gates = fully autonomous
|
|
42
|
-
}
|
|
43
72
|
const result = await spinner('Thinking', () => useCase.execute({
|
|
44
73
|
userInput: description,
|
|
45
74
|
repositoryPath: repoPath,
|
|
46
75
|
approvalGates,
|
|
76
|
+
openPr,
|
|
77
|
+
autoMerge,
|
|
47
78
|
}));
|
|
48
79
|
const { feature, warning } = result;
|
|
49
80
|
const repoHash = createHash('sha256').update(repoPath).digest('hex').slice(0, 16);
|
package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.d.ts
CHANGED
|
@@ -1,9 +1,20 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { FileAttachment } from '../../../../../../packages/core/src/infrastructure/services/file-dialog.service.js';
|
|
2
2
|
export type { FileAttachment } from '../../../../../../packages/core/src/infrastructure/services/file-dialog.service.js';
|
|
3
|
+
export interface FeatureCreatePayload {
|
|
4
|
+
name: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
attachments: FileAttachment[];
|
|
7
|
+
repositoryPath: string;
|
|
8
|
+
approvalGates: {
|
|
9
|
+
allowPrd: boolean;
|
|
10
|
+
allowPlan: boolean;
|
|
11
|
+
allowMerge: boolean;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
3
14
|
export interface FeatureCreateDrawerProps {
|
|
4
15
|
open: boolean;
|
|
5
16
|
onClose: () => void;
|
|
6
|
-
onSubmit: (data:
|
|
17
|
+
onSubmit: (data: FeatureCreatePayload) => void;
|
|
7
18
|
repositoryPath: string;
|
|
8
19
|
isSubmitting?: boolean;
|
|
9
20
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature-create-drawer.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"feature-create-drawer.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.tsx"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0DAA0D,CAAC;AAG/F,YAAY,EAAE,cAAc,EAAE,MAAM,0DAA0D,CAAC;AAE/F,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,cAAc,EAAE,CAAC;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE;QACb,QAAQ,EAAE,OAAO,CAAC;QAClB,SAAS,EAAE,OAAO,CAAC;QACnB,UAAU,EAAE,OAAO,CAAC;KACrB,CAAC;CACH;AAcD,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,CAAC,IAAI,EAAE,oBAAoB,KAAK,IAAI,CAAC;IAC/C,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,wBAAgB,mBAAmB,CAAC,EAClC,IAAI,EACJ,OAAO,EACP,QAAQ,EACR,cAAc,EACd,YAAoB,GACrB,EAAE,wBAAwB,2CA+L1B"}
|
package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.js
CHANGED
|
@@ -22,17 +22,6 @@ const EMPTY_GATES = {
|
|
|
22
22
|
allowPlan: false,
|
|
23
23
|
allowMerge: false,
|
|
24
24
|
};
|
|
25
|
-
function composeUserInput(name, description, attachments) {
|
|
26
|
-
let userInput = `Feature: ${name}`;
|
|
27
|
-
if (description) {
|
|
28
|
-
userInput += `\n\n${description}`;
|
|
29
|
-
}
|
|
30
|
-
if (attachments.length > 0) {
|
|
31
|
-
const paths = attachments.map((a) => `- ${a.path}`).join('\n');
|
|
32
|
-
userInput += `\n\nAttached files:\n${paths}`;
|
|
33
|
-
}
|
|
34
|
-
return userInput;
|
|
35
|
-
}
|
|
36
25
|
export function FeatureCreateDrawer({ open, onClose, onSubmit, repositoryPath, isSubmitting = false, }) {
|
|
37
26
|
const [name, setName] = useState('');
|
|
38
27
|
const [description, setDescription] = useState('');
|
|
@@ -54,9 +43,11 @@ export function FeatureCreateDrawer({ open, onClose, onSubmit, repositoryPath, i
|
|
|
54
43
|
e.preventDefault();
|
|
55
44
|
if (!name.trim())
|
|
56
45
|
return;
|
|
57
|
-
const
|
|
46
|
+
const trimmedDescription = description.trim() || undefined;
|
|
58
47
|
onSubmit({
|
|
59
|
-
|
|
48
|
+
name: name.trim(),
|
|
49
|
+
description: trimmedDescription,
|
|
50
|
+
attachments,
|
|
60
51
|
repositoryPath,
|
|
61
52
|
approvalGates: {
|
|
62
53
|
allowPrd: approvalGates.allowPrd ?? false,
|
|
@@ -18,13 +18,12 @@ import { FeatureCreateDrawer } from './feature-create-drawer.js';
|
|
|
18
18
|
* |------|------|-------------|
|
|
19
19
|
* | `open` | `boolean` | Controls drawer visibility |
|
|
20
20
|
* | `onClose` | `() => void` | Called on dismiss (close button, cancel, or backdrop) |
|
|
21
|
-
* | `onSubmit` | `(data:
|
|
21
|
+
* | `onSubmit` | `(data: FeatureCreatePayload) => void` | Called with `{ name, description, attachments, repositoryPath, approvalGates }` |
|
|
22
22
|
* | `repositoryPath` | `string` | Repository path (mandatory) included in the submitted data |
|
|
23
|
-
* | `isSubmitting` | `boolean` | Disables all fields and shows "Creating..." on submit button |
|
|
24
23
|
*
|
|
25
24
|
* ### Behavior
|
|
26
25
|
* - Form resets (name, description, attachments, checkboxes) when the drawer closes
|
|
27
|
-
* - Submit button is disabled when name is empty
|
|
26
|
+
* - Submit button is disabled when name is empty
|
|
28
27
|
* - `approvalGates` always included: `{ allowPrd, allowPlan, allowMerge }` (all false by default)
|
|
29
28
|
* - Non-modal (`modal={false}`) — canvas stays interactive behind the drawer
|
|
30
29
|
* - Fixed width: 384px (`w-96`)
|
|
@@ -41,11 +40,6 @@ export declare const Default: Story;
|
|
|
41
40
|
* Demonstrates the form in a "ready to submit" state.
|
|
42
41
|
*/
|
|
43
42
|
export declare const PreFilled: Story;
|
|
44
|
-
/**
|
|
45
|
-
* Submitting/loading state — all form fields are disabled, submit button shows "Creating...".
|
|
46
|
-
* Click the trigger to open and observe the disabled form.
|
|
47
|
-
*/
|
|
48
|
-
export declare const Submitting: Story;
|
|
49
43
|
/**
|
|
50
44
|
* Validation state — open the drawer with an empty name field.
|
|
51
45
|
* The "+ Create Feature" button is disabled because name validation fails.
|
|
@@ -77,8 +71,8 @@ export declare const MergeOnly: Story;
|
|
|
77
71
|
* Fully interactive story — open the drawer, fill the form, toggle checkboxes,
|
|
78
72
|
* and click "Add Files" to attach files via the native OS file picker.
|
|
79
73
|
*
|
|
80
|
-
* **Submitted data** is displayed in a styled panel showing `
|
|
81
|
-
* with `
|
|
74
|
+
* **Submitted data** is displayed in a styled panel showing `FeatureCreatePayload`
|
|
75
|
+
* with `{ name, description, attachments, repositoryPath, approvalGates }`.
|
|
82
76
|
*
|
|
83
77
|
* In Storybook, the native picker won't work (no backend), but submitted data
|
|
84
78
|
* would show the paths if files were attached programmatically.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature-create-drawer.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAQ9D
|
|
1
|
+
{"version":3,"file":"feature-create-drawer.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAQ9D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,mBAAmB,CAyB1C,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,mBAAmB,CAAC,CAAC;AA0ClD,uFAAuF;AACvF,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,SAAS,EAAE,KAiBvB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAE,KAMhC,CAAC;AAEF,4DAA4D;AAC5D,eAAO,MAAM,SAAS,EAAE,KAMvB,CAAC;AAMF;;;GAGG;AACH,eAAO,MAAM,YAAY,EAAE,KAM1B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,UAAU,EAAE,KAUxB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,OAAO,EAAE,KAUrB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,SAAS,EAAE,KAUvB,CAAC;AAMF;;;;;;;;;GASG;AACH,eAAO,MAAM,WAAW,EAAE,KAsCzB,CAAC"}
|
|
@@ -24,13 +24,12 @@ import { Button } from '../../ui/button.js';
|
|
|
24
24
|
* |------|------|-------------|
|
|
25
25
|
* | `open` | `boolean` | Controls drawer visibility |
|
|
26
26
|
* | `onClose` | `() => void` | Called on dismiss (close button, cancel, or backdrop) |
|
|
27
|
-
* | `onSubmit` | `(data:
|
|
27
|
+
* | `onSubmit` | `(data: FeatureCreatePayload) => void` | Called with `{ name, description, attachments, repositoryPath, approvalGates }` |
|
|
28
28
|
* | `repositoryPath` | `string` | Repository path (mandatory) included in the submitted data |
|
|
29
|
-
* | `isSubmitting` | `boolean` | Disables all fields and shows "Creating..." on submit button |
|
|
30
29
|
*
|
|
31
30
|
* ### Behavior
|
|
32
31
|
* - Form resets (name, description, attachments, checkboxes) when the drawer closes
|
|
33
|
-
* - Submit button is disabled when name is empty
|
|
32
|
+
* - Submit button is disabled when name is empty
|
|
34
33
|
* - `approvalGates` always included: `{ allowPrd, allowPlan, allowMerge }` (all false by default)
|
|
35
34
|
* - Non-modal (`modal={false}`) — canvas stays interactive behind the drawer
|
|
36
35
|
* - Fixed width: 384px (`w-96`)
|
|
@@ -53,16 +52,12 @@ const meta = {
|
|
|
53
52
|
description: 'Callback fired when the drawer is dismissed (close button, cancel, or backdrop click).',
|
|
54
53
|
},
|
|
55
54
|
onSubmit: {
|
|
56
|
-
description: 'Callback fired with `
|
|
55
|
+
description: 'Callback fired with `FeatureCreatePayload` when the form is submitted. Receives `{ name, description, attachments, repositoryPath, approvalGates }`.',
|
|
57
56
|
},
|
|
58
57
|
repositoryPath: {
|
|
59
58
|
control: 'text',
|
|
60
59
|
description: 'Repository path (mandatory) included in the submitted data.',
|
|
61
60
|
},
|
|
62
|
-
isSubmitting: {
|
|
63
|
-
control: 'boolean',
|
|
64
|
-
description: 'When true, all form fields and buttons are disabled, and the submit button shows "Creating...".',
|
|
65
|
-
},
|
|
66
61
|
},
|
|
67
62
|
};
|
|
68
63
|
export default meta;
|
|
@@ -75,7 +70,7 @@ const logClose = fn().mockName('onClose');
|
|
|
75
70
|
* Trigger wrapper — every story uses this so nothing auto-opens on Docs page
|
|
76
71
|
* ------------------------------------------------------------------------- */
|
|
77
72
|
/** Starts closed — click button to open. Actions are logged. */
|
|
78
|
-
function CreateDrawerTrigger({
|
|
73
|
+
function CreateDrawerTrigger({ label = 'Open Create Feature' }) {
|
|
79
74
|
const [open, setOpen] = useState(false);
|
|
80
75
|
return (_jsxs("div", { className: "flex h-screen items-start p-4", children: [_jsx(Button, { variant: "outline", onClick: () => setOpen(true), children: label }), _jsx(FeatureCreateDrawer, { open: open, onClose: () => {
|
|
81
76
|
setOpen(false);
|
|
@@ -83,7 +78,7 @@ function CreateDrawerTrigger({ isSubmitting = false, label = 'Open Create Featur
|
|
|
83
78
|
}, onSubmit: (data) => {
|
|
84
79
|
logSubmit(data);
|
|
85
80
|
setOpen(false);
|
|
86
|
-
}, repositoryPath: "/Users/dev/my-repo"
|
|
81
|
+
}, repositoryPath: "/Users/dev/my-repo" })] }));
|
|
87
82
|
}
|
|
88
83
|
/* ---------------------------------------------------------------------------
|
|
89
84
|
* Per-state stories
|
|
@@ -109,13 +104,6 @@ export const PreFilled = {
|
|
|
109
104
|
await userEvent.type(descInput, 'Implement OAuth2 authentication with GitHub as the identity provider. Includes login, callback handling, and token refresh.');
|
|
110
105
|
},
|
|
111
106
|
};
|
|
112
|
-
/**
|
|
113
|
-
* Submitting/loading state — all form fields are disabled, submit button shows "Creating...".
|
|
114
|
-
* Click the trigger to open and observe the disabled form.
|
|
115
|
-
*/
|
|
116
|
-
export const Submitting = {
|
|
117
|
-
render: () => _jsx(CreateDrawerTrigger, { isSubmitting: true, label: "Open (Submitting)" }),
|
|
118
|
-
};
|
|
119
107
|
/**
|
|
120
108
|
* Validation state — open the drawer with an empty name field.
|
|
121
109
|
* The "+ Create Feature" button is disabled because name validation fails.
|
|
@@ -198,8 +186,8 @@ export const MergeOnly = {
|
|
|
198
186
|
* Fully interactive story — open the drawer, fill the form, toggle checkboxes,
|
|
199
187
|
* and click "Add Files" to attach files via the native OS file picker.
|
|
200
188
|
*
|
|
201
|
-
* **Submitted data** is displayed in a styled panel showing `
|
|
202
|
-
* with `
|
|
189
|
+
* **Submitted data** is displayed in a styled panel showing `FeatureCreatePayload`
|
|
190
|
+
* with `{ name, description, attachments, repositoryPath, approvalGates }`.
|
|
203
191
|
*
|
|
204
192
|
* In Storybook, the native picker won't work (no backend), but submitted data
|
|
205
193
|
* would show the paths if files were attached programmatically.
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { FeatureCreateDrawer, type FeatureCreateDrawerProps, type FileAttachment, } from './feature-create-drawer.js';
|
|
1
|
+
export { FeatureCreateDrawer, type FeatureCreateDrawerProps, type FeatureCreatePayload, type FileAttachment, } from './feature-create-drawer.js';
|
|
2
2
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-create-drawer/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,KAAK,wBAAwB,EAC7B,KAAK,cAAc,GACpB,MAAM,yBAAyB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-create-drawer/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,KAAK,wBAAwB,EAC7B,KAAK,oBAAoB,EACzB,KAAK,cAAc,GACpB,MAAM,yBAAyB,CAAC"}
|
package/dist/src/presentation/web/components/common/feature-drawer/feature-drawer.stories.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature-drawer.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer/feature-drawer.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAKjD,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,aAAa,CAOpC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,aAAa,CAAC,CAAC;AAgG5C,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,KAE5B,CAAC;AAEF,eAAO,MAAM,IAAI,EAAE,KAElB,CAAC;AAEF,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAEF,eAAO,MAAM,KAAK,EAAE,KAEnB,CAAC;AAMF,wEAAwE;AACxE,eAAO,MAAM,WAAW,EAAE,KAEzB,CAAC;AAEF,qFAAqF;AACrF,eAAO,MAAM,SAAS,EAAE,KAqBvB,CAAC;
|
|
1
|
+
{"version":3,"file":"feature-drawer.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer/feature-drawer.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAKjD,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,aAAa,CAOpC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,aAAa,CAAC,CAAC;AAgG5C,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,KAE5B,CAAC;AAEF,eAAO,MAAM,IAAI,EAAE,KAElB,CAAC;AAEF,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAEF,eAAO,MAAM,KAAK,EAAE,KAEnB,CAAC;AAMF,wEAAwE;AACxE,eAAO,MAAM,WAAW,EAAE,KAEzB,CAAC;AAEF,qFAAqF;AACrF,eAAO,MAAM,SAAS,EAAE,KAqBvB,CAAC;AAmEF,0DAA0D;AAC1D,eAAO,MAAM,SAAS,EAAE,KAEvB,CAAC;AA6CF,wDAAwD;AACxD,eAAO,MAAM,aAAa,EAAE,KAE3B,CAAC;AAMF,qDAAqD;AACrD,eAAO,MAAM,gBAAgB,EAAE,KAO9B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,KAE/B,CAAC;AAoCF,wDAAwD;AACxD,eAAO,MAAM,gBAAgB,EAAE,KAE9B,CAAC;AAEF,yEAAyE;AACzE,eAAO,MAAM,aAAa,EAAE,KAE3B,CAAC;AAEF,+FAA+F;AAC/F,eAAO,MAAM,kBAAkB,EAAE,KAEhC,CAAC"}
|
package/dist/src/presentation/web/components/common/feature-drawer/feature-drawer.stories.js
CHANGED
|
@@ -129,7 +129,18 @@ export const AllFields = {
|
|
|
129
129
|
/* ---------------------------------------------------------------------------
|
|
130
130
|
* Matrix stories — interactive state/lifecycle switcher
|
|
131
131
|
* ------------------------------------------------------------------------- */
|
|
132
|
+
const creatingData = {
|
|
133
|
+
name: 'User Onboarding',
|
|
134
|
+
description: 'Implement guided onboarding wizard',
|
|
135
|
+
featureId: '',
|
|
136
|
+
lifecycle: 'requirements',
|
|
137
|
+
state: 'creating',
|
|
138
|
+
progress: 0,
|
|
139
|
+
repositoryPath: '/home/user/my-repo',
|
|
140
|
+
branch: '',
|
|
141
|
+
};
|
|
132
142
|
const stateFixtures = {
|
|
143
|
+
creating: creatingData,
|
|
133
144
|
running: runningData,
|
|
134
145
|
'action-required': actionRequiredData,
|
|
135
146
|
done: doneData,
|
package/dist/src/presentation/web/components/common/feature-node/feature-node-state-config.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type LucideIcon } from 'lucide-react';
|
|
2
2
|
import type { Node } from '@xyflow/react';
|
|
3
3
|
import type { AgentTypeValue } from './agent-type-icons.js';
|
|
4
|
-
export type FeatureNodeState = 'running' | 'action-required' | 'done' | 'blocked' | 'error';
|
|
4
|
+
export type FeatureNodeState = 'creating' | 'running' | 'action-required' | 'done' | 'blocked' | 'error';
|
|
5
5
|
export type FeatureLifecyclePhase = 'requirements' | 'research' | 'implementation' | 'review' | 'deploy' | 'maintain';
|
|
6
6
|
/** Human-readable display labels for lifecycle phases. */
|
|
7
7
|
export declare const lifecycleDisplayLabels: Record<FeatureLifecyclePhase, string>;
|
package/dist/src/presentation/web/components/common/feature-node/feature-node-state-config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature-node-state-config.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-node/feature-node-state-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmD,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAChG,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD,MAAM,MAAM,gBAAgB,
|
|
1
|
+
{"version":3,"file":"feature-node-state-config.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-node/feature-node-state-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmD,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAChG,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD,MAAM,MAAM,gBAAgB,GACxB,UAAU,GACV,SAAS,GACT,iBAAiB,GACjB,MAAM,GACN,SAAS,GACT,OAAO,CAAC;AAEZ,MAAM,MAAM,qBAAqB,GAC7B,cAAc,GACd,UAAU,GACV,gBAAgB,GAChB,QAAQ,GACR,QAAQ,GACR,UAAU,CAAC;AAEf,0DAA0D;AAC1D,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,qBAAqB,EAAE,MAAM,CAOxE,CAAC;AAEF,gFAAgF;AAChF,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,qBAAqB,EAAE,MAAM,CAOvE,CAAC;AAEF,MAAM,WAAW,eAAe;IAC9B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,qBAAqB,CAAC;IACjC,KAAK,EAAE,gBAAgB,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,8CAA8C;IAC9C,cAAc,EAAE,MAAM,CAAC;IACvB,uCAAuC;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,4DAA4D;IAC5D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0CAA0C;IAC1C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,0DAA0D;IAC1D,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,eAAe,EAAE,aAAa,CAAC,CAAC;AAEnE,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,UAAU,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,gBAAgB,EAAE,sBAAsB,CA6DnF,CAAC"}
|
package/dist/src/presentation/web/components/common/feature-node/feature-node-state-config.js
CHANGED
|
@@ -18,6 +18,16 @@ export const lifecycleRunningVerbs = {
|
|
|
18
18
|
maintain: 'Maintaining',
|
|
19
19
|
};
|
|
20
20
|
export const featureNodeStateConfig = {
|
|
21
|
+
creating: {
|
|
22
|
+
icon: Loader2,
|
|
23
|
+
borderClass: 'border-l-blue-500',
|
|
24
|
+
labelClass: 'text-blue-500',
|
|
25
|
+
progressClass: 'bg-blue-500',
|
|
26
|
+
badgeClass: 'text-blue-700',
|
|
27
|
+
badgeBgClass: 'bg-blue-50',
|
|
28
|
+
label: 'Creating...',
|
|
29
|
+
showProgressBar: false,
|
|
30
|
+
},
|
|
21
31
|
running: {
|
|
22
32
|
icon: Loader2,
|
|
23
33
|
borderClass: 'border-l-blue-500',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature-node.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-node/feature-node.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"feature-node.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-node/feature-node.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AA0BnE,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,QAAQ,GACT,EAAE;IACD,IAAI,EAAE,eAAe,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,2CAsKA"}
|
|
@@ -12,6 +12,8 @@ function AgentIcon({ agentType, className }) {
|
|
|
12
12
|
function getBadgeText(data) {
|
|
13
13
|
const config = featureNodeStateConfig[data.state];
|
|
14
14
|
switch (data.state) {
|
|
15
|
+
case 'creating':
|
|
16
|
+
return 'Creating...';
|
|
15
17
|
case 'running':
|
|
16
18
|
return lifecycleRunningVerbs[data.lifecycle];
|
|
17
19
|
case 'done':
|
|
@@ -27,10 +29,10 @@ function getBadgeText(data) {
|
|
|
27
29
|
export function FeatureNode({ data, selected, }) {
|
|
28
30
|
const config = featureNodeStateConfig[data.state];
|
|
29
31
|
const Icon = config.icon;
|
|
30
|
-
return (_jsxs("div", { className: "group relative", children: [data.showHandles ? (_jsx(Handle, { type: "target", position: Position.Left, isConnectable: false, className: "opacity-0!" })) : null, _jsxs("div", { "data-testid": "feature-node-card", className: cn('bg-card flex min-h-35 w-72 flex-col rounded-lg border p-3 shadow-sm', selected && 'ring-primary ring-2'), children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("span", { "data-testid": "feature-node-lifecycle-label", className: cn('text-[10px] font-semibold tracking-wider'), children: lifecycleDisplayLabels[data.lifecycle] }), data.onSettings ? (_jsx("button", { type: "button", "aria-label": "Settings", "data-testid": "feature-node-settings-button", onClick: (e) => {
|
|
32
|
+
return (_jsxs("div", { className: "group relative", children: [data.showHandles ? (_jsx(Handle, { type: "target", position: Position.Left, isConnectable: false, className: "opacity-0!" })) : null, _jsxs("div", { "data-testid": "feature-node-card", "aria-busy": data.state === 'creating' ? 'true' : undefined, className: cn('bg-card flex min-h-35 w-72 flex-col rounded-lg border p-3 shadow-sm', selected && 'ring-primary ring-2'), children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("span", { "data-testid": "feature-node-lifecycle-label", className: cn('text-[10px] font-semibold tracking-wider'), children: lifecycleDisplayLabels[data.lifecycle] }), data.onSettings ? (_jsx("button", { type: "button", "aria-label": "Settings", "data-testid": "feature-node-settings-button", onClick: (e) => {
|
|
31
33
|
e.stopPropagation();
|
|
32
34
|
data.onSettings?.();
|
|
33
|
-
}, className: "nodrag text-muted-foreground hover:text-foreground -mt-1 -mr-1 p-1", children: _jsx(Settings, { className: "h-3.5 w-3.5" }) })) : null] }), _jsx("h3", { className: "mt-1 truncate text-sm font-bold", children: data.name }), data.description ? (_jsx("p", { "data-testid": "feature-node-description", className: "text-muted-foreground mt-0.5 truncate text-xs", children: data.description })) : null, _jsx("div", { className: "mt-auto pt-2", children: data.state === 'running' ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "mt-1.5 flex items-center gap-1.5 text-xs", children: [_jsx(AgentIcon, { agentType: data.agentType, className: "h-3.5 w-3.5 shrink-0" }), _jsx("span", { className: "text-muted-foreground", children: getBadgeText(data) })] }), _jsx("div", { "data-testid": "feature-node-progress-bar", className: "bg-muted mt-1.5 h-1 w-full overflow-hidden rounded-full", children: _jsx("div", { className: "animate-indeterminate-progress bg-foreground/30 h-full w-1/3 rounded-full" }) })] })) : config.showProgressBar ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "text-muted-foreground flex items-center justify-end text-[10px]", children: _jsxs("span", { children: [data.progress, "%"] }) }), _jsx("div", { "data-testid": "feature-node-progress-bar", className: "bg-muted mt-1.5 h-1 w-full overflow-hidden rounded-full", children: _jsx("div", { className: cn('h-full rounded-full transition-all', config.progressClass), style: { width: `${data.progress}%` } }) })] })) : (_jsxs(_Fragment, { children: [_jsx("div", { className: "text-muted-foreground text-[10px]", children: _jsx("span", { children: data.featureId }) }), _jsxs("div", { "data-testid": "feature-node-badge", className: cn('mt-1.5 flex items-center justify-center gap-1.5 rounded-full px-2.5 py-1 text-[11px] font-medium', config.badgeBgClass, config.badgeClass), children: [_jsx(Icon, { className: "h-3.5 w-3.5 shrink-0" }), _jsx("span", { className: "truncate", children: getBadgeText(data) })] })] })) })] }), data.onAction ? (_jsx(Handle, { type: "source", position: Position.Right, className: "h-0! w-0! border-0! bg-transparent!", children: _jsx("button", { type: "button", "aria-label": "Add", "data-testid": "feature-node-action-button", onClick: (e) => {
|
|
35
|
+
}, className: "nodrag text-muted-foreground hover:text-foreground -mt-1 -mr-1 p-1", children: _jsx(Settings, { className: "h-3.5 w-3.5" }) })) : null] }), _jsx("h3", { className: "mt-1 truncate text-sm font-bold", children: data.name }), data.description ? (_jsx("p", { "data-testid": "feature-node-description", className: "text-muted-foreground mt-0.5 truncate text-xs", children: data.description })) : null, _jsx("div", { className: "mt-auto pt-2", children: data.state === 'creating' ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "mt-1.5 flex items-center gap-1.5 text-xs", children: [_jsx(Icon, { className: "h-3.5 w-3.5 shrink-0 animate-spin" }), _jsx("span", { className: "text-muted-foreground", children: getBadgeText(data) })] }), _jsx("div", { "data-testid": "feature-node-progress-bar", className: "bg-muted mt-1.5 h-1 w-full overflow-hidden rounded-full", children: _jsx("div", { className: "motion-safe:animate-indeterminate-progress bg-foreground/30 h-full w-1/3 rounded-full" }) })] })) : data.state === 'running' ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "mt-1.5 flex items-center gap-1.5 text-xs", children: [_jsx(AgentIcon, { agentType: data.agentType, className: "h-3.5 w-3.5 shrink-0" }), _jsx("span", { className: "text-muted-foreground", children: getBadgeText(data) })] }), _jsx("div", { "data-testid": "feature-node-progress-bar", className: "bg-muted mt-1.5 h-1 w-full overflow-hidden rounded-full", children: _jsx("div", { className: "animate-indeterminate-progress bg-foreground/30 h-full w-1/3 rounded-full" }) })] })) : config.showProgressBar ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "text-muted-foreground flex items-center justify-end text-[10px]", children: _jsxs("span", { children: [data.progress, "%"] }) }), _jsx("div", { "data-testid": "feature-node-progress-bar", className: "bg-muted mt-1.5 h-1 w-full overflow-hidden rounded-full", children: _jsx("div", { className: cn('h-full rounded-full transition-all', config.progressClass), style: { width: `${data.progress}%` } }) })] })) : (_jsxs(_Fragment, { children: [_jsx("div", { className: "text-muted-foreground text-[10px]", children: _jsx("span", { children: data.featureId }) }), _jsxs("div", { "data-testid": "feature-node-badge", className: cn('mt-1.5 flex items-center justify-center gap-1.5 rounded-full px-2.5 py-1 text-[11px] font-medium', config.badgeBgClass, config.badgeClass), children: [_jsx(Icon, { className: "h-3.5 w-3.5 shrink-0" }), _jsx("span", { className: "truncate", children: getBadgeText(data) })] })] })) })] }), data.onAction ? (_jsx(Handle, { type: "source", position: Position.Right, className: "h-0! w-0! border-0! bg-transparent!", children: _jsx("button", { type: "button", "aria-label": "Add", "data-testid": "feature-node-action-button", onClick: (e) => {
|
|
34
36
|
e.stopPropagation();
|
|
35
37
|
data.onAction?.();
|
|
36
38
|
}, className: "nodrag absolute top-1/2 left-1/2 flex h-6 w-6 -translate-x-1/2 -translate-y-1/2 cursor-pointer items-center justify-center rounded-full bg-blue-500 text-white opacity-0 shadow-md transition-opacity group-hover:opacity-100 hover:bg-blue-600", children: _jsx(Plus, { className: "h-3.5 w-3.5" }) }) })) : data.showHandles ? (_jsx(Handle, { type: "source", position: Position.Right, isConnectable: false, className: "opacity-0!" })) : null] }));
|
|
@@ -11,6 +11,7 @@ export declare const WithAction: Story;
|
|
|
11
11
|
export declare const LongContent: Story;
|
|
12
12
|
export declare const DoneWithRuntime: Story;
|
|
13
13
|
export declare const BlockedByFeature: Story;
|
|
14
|
+
export declare const Creating: Story;
|
|
14
15
|
export declare const ErrorWithMessage: Story;
|
|
15
16
|
export declare const Interactive: Story;
|
|
16
17
|
//# sourceMappingURL=feature-node.stories.d.ts.map
|
package/dist/src/presentation/web/components/common/feature-node/feature-node.stories.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature-node.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-node/feature-node.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAKvD,OAAO,KAAK,EACV,eAAe,EAIhB,MAAM,6BAA6B,CAAC;AAiCrC,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,eAAe,CAc/B,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,eAAe,CAAC,CAAC;AAEvC,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;
|
|
1
|
+
{"version":3,"file":"feature-node.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-node/feature-node.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAKvD,OAAO,KAAK,EACV,eAAe,EAIhB,MAAM,6BAA6B,CAAC;AAiCrC,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,eAAe,CAc/B,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,eAAe,CAAC,CAAC;AAEvC,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAoEF,eAAO,MAAM,SAAS,EAAE,KAQvB,CAAC;AAWF,eAAO,MAAM,aAAa,EAAE,KAqB3B,CAAC;AAsEF,eAAO,MAAM,aAAa,EAAE,KAQ3B,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,KAMxB,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KAOzB,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,KAW7B,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,KAW9B,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAUtB,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,KAW9B,CAAC;AA4EF,eAAO,MAAM,WAAW,EAAE,KAOzB,CAAC"}
|
|
@@ -29,6 +29,16 @@ export const Default = {
|
|
|
29
29
|
render: (args) => _jsx(FeatureNodeCanvas, { data: args }),
|
|
30
30
|
};
|
|
31
31
|
const allStatesData = [
|
|
32
|
+
{
|
|
33
|
+
name: 'User Onboarding',
|
|
34
|
+
description: 'Implement guided onboarding wizard',
|
|
35
|
+
featureId: '',
|
|
36
|
+
lifecycle: 'requirements',
|
|
37
|
+
state: 'creating',
|
|
38
|
+
progress: 0,
|
|
39
|
+
repositoryPath: '/home/user/my-repo',
|
|
40
|
+
branch: '',
|
|
41
|
+
},
|
|
32
42
|
{
|
|
33
43
|
name: 'Auth Module',
|
|
34
44
|
description: 'Implement OAuth2 authentication flow',
|
|
@@ -214,6 +224,17 @@ export const BlockedByFeature = {
|
|
|
214
224
|
},
|
|
215
225
|
render: (args) => _jsx(FeatureNodeCanvas, { data: args }),
|
|
216
226
|
};
|
|
227
|
+
export const Creating = {
|
|
228
|
+
args: {
|
|
229
|
+
name: 'User Onboarding',
|
|
230
|
+
description: 'Implement guided onboarding wizard',
|
|
231
|
+
featureId: '',
|
|
232
|
+
lifecycle: 'requirements',
|
|
233
|
+
state: 'creating',
|
|
234
|
+
progress: 0,
|
|
235
|
+
},
|
|
236
|
+
render: (args) => _jsx(FeatureNodeCanvas, { data: args }),
|
|
237
|
+
};
|
|
217
238
|
export const ErrorWithMessage = {
|
|
218
239
|
args: {
|
|
219
240
|
name: 'Email Service',
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { AddRepositoryNode, type AddRepositoryNodeData, type AddRepositoryNodeType, } from './add-repository-node/index.js';
|
|
2
2
|
export { ElapsedTime, formatElapsed } from './elapsed-time/index.js';
|
|
3
3
|
export { EmptyState, type EmptyStateProps } from './empty-state/index.js';
|
|
4
|
-
export { FeatureCreateDrawer, type FeatureCreateDrawerProps } from './feature-create-drawer/index.js';
|
|
4
|
+
export { FeatureCreateDrawer, type FeatureCreateDrawerProps, type FeatureCreatePayload, } from './feature-create-drawer/index.js';
|
|
5
5
|
export { FeatureDrawer, type FeatureDrawerProps } from './feature-drawer/index.js';
|
|
6
6
|
export { FeatureListItem, type FeatureListItemProps } from './feature-list-item/index.js';
|
|
7
7
|
export { useFeatureActions, type FeatureActionsInput, type FeatureActionsState, } from './feature-drawer/use-feature-actions.js';
|