@shepai/cli 1.29.1 → 1.31.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-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 +70 -7
- 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 +9 -9
- package/web/.next/server/app/_not-found.segments/_full.segment.rsc +9 -9
- package/web/.next/server/app/_not-found.segments/_head.segment.rsc +3 -3
- package/web/.next/server/app/_not-found.segments/_index.segment.rsc +5 -5
- 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 +1 -1
- 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 +4 -4
- package/web/.next/server/app/version.segments/_full.segment.rsc +4 -4
- package/web/.next/server/app/version.segments/_head.segment.rsc +1 -1
- package/web/.next/server/app/version.segments/_index.segment.rsc +3 -3
- package/web/.next/server/app/version.segments/_tree.segment.rsc +1 -1
- 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/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/9993505b2a26c454.js +1 -0
- 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/{xfxn0ObmVPrJQ_jxVxePe → zHWQYn5H7ZmzuYWmx7b2E}/_buildManifest.js +0 -0
- /package/web/.next/static/{xfxn0ObmVPrJQ_jxVxePe → zHWQYn5H7ZmzuYWmx7b2E}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{xfxn0ObmVPrJQ_jxVxePe → zHWQYn5H7ZmzuYWmx7b2E}/_ssgManifest.js +0 -0
package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.js
CHANGED
|
@@ -20,6 +20,7 @@ import { initializeSettings } from '../../../services/settings.service.js';
|
|
|
20
20
|
import { InitializeSettingsUseCase } from '../../../../application/use-cases/settings/initialize-settings.use-case.js';
|
|
21
21
|
import { setHeartbeatContext } from './heartbeat.js';
|
|
22
22
|
import { setPhaseTimingContext } from './phase-timing-context.js';
|
|
23
|
+
import { generatePrYaml } from './nodes/pr-yaml-generator.js';
|
|
23
24
|
/**
|
|
24
25
|
* Parse CLI arguments into a WorkerArgs object.
|
|
25
26
|
* Throws if any required argument is missing.
|
|
@@ -47,6 +48,10 @@ export function parseWorkerArgs(args) {
|
|
|
47
48
|
}
|
|
48
49
|
const resume = args.includes('--resume');
|
|
49
50
|
const resumeFromInterrupt = args.includes('--resume-from-interrupt');
|
|
51
|
+
const push = args.includes('--push');
|
|
52
|
+
const openPr = args.includes('--open-pr');
|
|
53
|
+
const autoMerge = args.includes('--auto-merge');
|
|
54
|
+
const allowMerge = args.includes('--allow-merge');
|
|
50
55
|
const threadIdx = args.indexOf('--thread-id');
|
|
51
56
|
const threadId = threadIdx !== -1 && threadIdx + 1 < args.length ? args[threadIdx + 1] : undefined;
|
|
52
57
|
return {
|
|
@@ -59,6 +64,10 @@ export function parseWorkerArgs(args) {
|
|
|
59
64
|
resume,
|
|
60
65
|
threadId,
|
|
61
66
|
resumeFromInterrupt,
|
|
67
|
+
push,
|
|
68
|
+
openPr,
|
|
69
|
+
autoMerge,
|
|
70
|
+
allowMerge,
|
|
62
71
|
};
|
|
63
72
|
}
|
|
64
73
|
/** Simple worker logger — writes to stdout which is redirected to log file by the parent. */
|
|
@@ -111,13 +120,24 @@ export async function runWorker(args) {
|
|
|
111
120
|
// Create executor from configured agent settings
|
|
112
121
|
log('Creating executor from configured agent settings...');
|
|
113
122
|
const executor = executorProvider.getExecutor();
|
|
123
|
+
// Resolve merge node dependencies
|
|
124
|
+
const gitPrService = container.resolve('IGitPrService');
|
|
125
|
+
const featureRepository = container.resolve('IFeatureRepository');
|
|
126
|
+
const graphDeps = {
|
|
127
|
+
executor,
|
|
128
|
+
mergeNodeDeps: {
|
|
129
|
+
gitPrService,
|
|
130
|
+
generatePrYaml,
|
|
131
|
+
featureRepository,
|
|
132
|
+
},
|
|
133
|
+
};
|
|
114
134
|
// Use threadId for checkpoint path so resume runs share the same checkpoint DB.
|
|
115
135
|
// Falls back to runId for backwards compatibility with existing runs.
|
|
116
136
|
const checkpointId = args.threadId ?? args.runId;
|
|
117
137
|
const checkpointPath = join(homedir(), '.shep', 'checkpoints', `${checkpointId}.db`);
|
|
118
138
|
log(`Creating checkpointer at ${checkpointPath} (thread: ${checkpointId})`);
|
|
119
139
|
const checkpointer = createCheckpointer(checkpointPath);
|
|
120
|
-
const graph = createFeatureAgentGraph(
|
|
140
|
+
const graph = createFeatureAgentGraph(graphDeps, checkpointer);
|
|
121
141
|
// Mark the run as running with our PID
|
|
122
142
|
const now = new Date();
|
|
123
143
|
log(`Updating status to running (PID ${process.pid})...`);
|
|
@@ -153,6 +173,10 @@ export async function runWorker(args) {
|
|
|
153
173
|
specDir: args.specDir,
|
|
154
174
|
error: undefined, // Clear previous error state
|
|
155
175
|
...(args.approvalGates ? { approvalGates: args.approvalGates } : {}),
|
|
176
|
+
push: args.push ?? false,
|
|
177
|
+
openPr: args.openPr ?? false,
|
|
178
|
+
autoMerge: args.autoMerge ?? false,
|
|
179
|
+
allowMerge: args.allowMerge ?? false,
|
|
156
180
|
}, graphConfig);
|
|
157
181
|
}
|
|
158
182
|
else {
|
|
@@ -163,6 +187,10 @@ export async function runWorker(args) {
|
|
|
163
187
|
worktreePath: args.worktreePath ?? args.repo,
|
|
164
188
|
specDir: args.specDir,
|
|
165
189
|
...(args.approvalGates ? { approvalGates: args.approvalGates } : {}),
|
|
190
|
+
push: args.push ?? false,
|
|
191
|
+
openPr: args.openPr ?? false,
|
|
192
|
+
autoMerge: args.autoMerge ?? false,
|
|
193
|
+
allowMerge: args.allowMerge ?? false,
|
|
166
194
|
}, graphConfig);
|
|
167
195
|
}
|
|
168
196
|
log(`Graph invocation completed. Error: ${result.error ?? 'none'}`);
|
package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge.node.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Merge Node — Post-Implementation Merge Flow
|
|
3
|
+
*
|
|
4
|
+
* Handles the complete merge workflow after implementation:
|
|
5
|
+
* 1. Commit uncommitted changes and push
|
|
6
|
+
* 2. Generate pr.yaml (always) and optionally create PR
|
|
7
|
+
* 3. Optionally auto-merge (via PR or direct branch merge)
|
|
8
|
+
* 4. Update feature lifecycle and clean up
|
|
9
|
+
*
|
|
10
|
+
* Uses interrupt() for the merge approval gate when allowMerge=false.
|
|
11
|
+
*/
|
|
12
|
+
import type { FeatureAgentState } from '../state.js';
|
|
13
|
+
import type { IGitPrService } from '../../../../../application/ports/output/services/git-pr-service.interface.js';
|
|
14
|
+
import type { IFeatureRepository } from '../../../../../application/ports/output/repositories/feature-repository.interface.js';
|
|
15
|
+
export interface MergeNodeDeps {
|
|
16
|
+
gitPrService: IGitPrService;
|
|
17
|
+
generatePrYaml: (specDir: string, branch: string, baseBranch: string) => string;
|
|
18
|
+
featureRepository: Pick<IFeatureRepository, 'findById' | 'update'>;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Factory that creates the merge node function.
|
|
22
|
+
*
|
|
23
|
+
* @param deps - External dependencies injected by the graph factory
|
|
24
|
+
* @returns A LangGraph node function
|
|
25
|
+
*/
|
|
26
|
+
export declare function createMergeNode(deps: MergeNodeDeps): (state: FeatureAgentState) => Promise<Partial<FeatureAgentState>>;
|
|
27
|
+
//# sourceMappingURL=merge.node.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge.node.d.ts","sourceRoot":"","sources":["../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge.node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iEAAiE,CAAC;AACrG,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yEAAyE,CAAC;AAKlH,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,aAAa,CAAC;IAC5B,cAAc,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,MAAM,CAAC;IAChF,iBAAiB,EAAE,IAAI,CAAC,kBAAkB,EAAE,UAAU,GAAG,QAAQ,CAAC,CAAC;CACpE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,aAAa,IAGnC,OAAO,iBAAiB,KAAG,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAwI7E"}
|
package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge.node.js
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Merge Node — Post-Implementation Merge Flow
|
|
3
|
+
*
|
|
4
|
+
* Handles the complete merge workflow after implementation:
|
|
5
|
+
* 1. Commit uncommitted changes and push
|
|
6
|
+
* 2. Generate pr.yaml (always) and optionally create PR
|
|
7
|
+
* 3. Optionally auto-merge (via PR or direct branch merge)
|
|
8
|
+
* 4. Update feature lifecycle and clean up
|
|
9
|
+
*
|
|
10
|
+
* Uses interrupt() for the merge approval gate when allowMerge=false.
|
|
11
|
+
*/
|
|
12
|
+
import { interrupt, isGraphBubbleUp } from '@langchain/langgraph';
|
|
13
|
+
import { SdlcLifecycle } from '../../../../../domain/generated/output.js';
|
|
14
|
+
import { createNodeLogger, shouldInterrupt } from './node-helpers.js';
|
|
15
|
+
import { reportNodeStart } from '../heartbeat.js';
|
|
16
|
+
/**
|
|
17
|
+
* Factory that creates the merge node function.
|
|
18
|
+
*
|
|
19
|
+
* @param deps - External dependencies injected by the graph factory
|
|
20
|
+
* @returns A LangGraph node function
|
|
21
|
+
*/
|
|
22
|
+
export function createMergeNode(deps) {
|
|
23
|
+
const log = createNodeLogger('merge');
|
|
24
|
+
return async (state) => {
|
|
25
|
+
log.info('Starting merge flow');
|
|
26
|
+
reportNodeStart('merge');
|
|
27
|
+
const messages = [];
|
|
28
|
+
const startTime = Date.now();
|
|
29
|
+
try {
|
|
30
|
+
const { gitPrService } = deps;
|
|
31
|
+
const cwd = state.worktreePath;
|
|
32
|
+
// Resolve branch name from feature
|
|
33
|
+
const feature = await deps.featureRepository.findById(state.featureId);
|
|
34
|
+
const branch = feature?.branch ?? `feat/${state.featureId}`;
|
|
35
|
+
const baseBranch = 'main';
|
|
36
|
+
// --- Step 1: Commit and Push ---
|
|
37
|
+
let commitHash = state.commitHash;
|
|
38
|
+
const hasChanges = await gitPrService.hasUncommittedChanges(cwd);
|
|
39
|
+
if (hasChanges) {
|
|
40
|
+
log.info('Uncommitted changes detected, committing...');
|
|
41
|
+
commitHash = await gitPrService.commitAll(cwd, `feat: implementation complete for ${state.featureId}`);
|
|
42
|
+
messages.push(`[merge] Committed changes: ${commitHash}`);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
log.info('No uncommitted changes');
|
|
46
|
+
messages.push('[merge] No uncommitted changes to commit');
|
|
47
|
+
}
|
|
48
|
+
// Push is controlled by the push flag (--push, or implied by --pr)
|
|
49
|
+
const shouldPush = state.push || state.openPr;
|
|
50
|
+
if (shouldPush) {
|
|
51
|
+
log.info('Pushing to remote...');
|
|
52
|
+
await gitPrService.push(cwd, branch, true);
|
|
53
|
+
messages.push(`[merge] Pushed branch ${branch}`);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
log.info('Push skipped (--push not set)');
|
|
57
|
+
messages.push('[merge] Push skipped (use --push to push to remote)');
|
|
58
|
+
}
|
|
59
|
+
// --- Step 2: Generate pr.yaml (always) ---
|
|
60
|
+
log.info('Generating pr.yaml...');
|
|
61
|
+
const prYamlPath = deps.generatePrYaml(state.specDir, branch, baseBranch);
|
|
62
|
+
messages.push(`[merge] Generated pr.yaml at ${prYamlPath}`);
|
|
63
|
+
// --- Step 3: Create PR (if openPr=true and not already created) ---
|
|
64
|
+
let prUrl = state.prUrl;
|
|
65
|
+
let prNumber = state.prNumber;
|
|
66
|
+
let ciStatus = state.ciStatus;
|
|
67
|
+
if (state.openPr && !state.prUrl) {
|
|
68
|
+
log.info('Creating pull request...');
|
|
69
|
+
const prResult = await gitPrService.createPr(cwd, prYamlPath);
|
|
70
|
+
prUrl = prResult.url;
|
|
71
|
+
prNumber = prResult.number;
|
|
72
|
+
messages.push(`[merge] PR created: ${prUrl}`);
|
|
73
|
+
// Watch CI if we're going to auto-merge
|
|
74
|
+
if (state.autoMerge) {
|
|
75
|
+
log.info('Watching CI...');
|
|
76
|
+
const ciResult = await gitPrService.watchCi(cwd, branch);
|
|
77
|
+
ciStatus = ciResult.status;
|
|
78
|
+
messages.push(`[merge] CI status: ${ciStatus}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// --- Step 4: Merge approval gate ---
|
|
82
|
+
if (shouldInterrupt('merge', state.approvalGates, state.autoMerge)) {
|
|
83
|
+
log.info('Interrupting for merge approval');
|
|
84
|
+
const diffSummary = await gitPrService.getPrDiffSummary(cwd, baseBranch);
|
|
85
|
+
interrupt({
|
|
86
|
+
node: 'merge',
|
|
87
|
+
message: 'Merge approval required. Review the changes and approve to continue.',
|
|
88
|
+
diffSummary,
|
|
89
|
+
prUrl,
|
|
90
|
+
prNumber,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
// --- Step 5: Auto-merge (if enabled) ---
|
|
94
|
+
let merged = false;
|
|
95
|
+
if (state.autoMerge) {
|
|
96
|
+
if (state.openPr && prNumber) {
|
|
97
|
+
log.info(`Auto-merging PR #${prNumber}...`);
|
|
98
|
+
await gitPrService.mergePr(cwd, prNumber, 'squash');
|
|
99
|
+
messages.push(`[merge] PR #${prNumber} merged via squash`);
|
|
100
|
+
merged = true;
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
log.info(`Auto-merging branch ${branch} into ${baseBranch}...`);
|
|
104
|
+
await gitPrService.mergeBranch(cwd, branch, baseBranch);
|
|
105
|
+
messages.push(`[merge] Branch ${branch} merged into ${baseBranch}`);
|
|
106
|
+
merged = true;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
// --- Step 6: Update feature lifecycle ---
|
|
110
|
+
const newLifecycle = merged ? SdlcLifecycle.Maintain : SdlcLifecycle.Review;
|
|
111
|
+
if (feature) {
|
|
112
|
+
await deps.featureRepository.update({
|
|
113
|
+
...feature,
|
|
114
|
+
lifecycle: newLifecycle,
|
|
115
|
+
prUrl: prUrl ?? undefined,
|
|
116
|
+
prNumber: prNumber ?? undefined,
|
|
117
|
+
updatedAt: new Date(),
|
|
118
|
+
});
|
|
119
|
+
messages.push(`[merge] Feature lifecycle → ${newLifecycle}`);
|
|
120
|
+
}
|
|
121
|
+
const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
|
|
122
|
+
messages.push(`[merge] Complete (${elapsed}s)`);
|
|
123
|
+
log.info(`Merge flow complete (${elapsed}s)`);
|
|
124
|
+
return {
|
|
125
|
+
currentNode: 'merge',
|
|
126
|
+
messages,
|
|
127
|
+
commitHash,
|
|
128
|
+
prUrl,
|
|
129
|
+
prNumber,
|
|
130
|
+
ciStatus,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
catch (err) {
|
|
134
|
+
// Re-throw LangGraph control-flow exceptions (interrupt, etc.)
|
|
135
|
+
if (isGraphBubbleUp(err))
|
|
136
|
+
throw err;
|
|
137
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
138
|
+
const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
|
|
139
|
+
log.error(`Merge failed: ${message} (${elapsed}s)`);
|
|
140
|
+
// Re-throw so LangGraph does NOT checkpoint this node as completed.
|
|
141
|
+
// This allows `feat resume` to retry the merge node instead of
|
|
142
|
+
// restarting the entire graph from scratch.
|
|
143
|
+
throw err;
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
}
|
package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.d.ts
CHANGED
|
@@ -37,12 +37,15 @@ export declare function safeYamlLoad(content: string): unknown;
|
|
|
37
37
|
* Gates control which phases auto-approve:
|
|
38
38
|
* - allowPrd: when true, skip interrupt after requirements phase
|
|
39
39
|
* - allowPlan: when true, skip interrupt after plan phase
|
|
40
|
+
* - allowMerge: when true, skip interrupt after merge phase
|
|
40
41
|
*
|
|
41
42
|
* Nodes not covered by a gate (analyze, research) never interrupt.
|
|
42
43
|
* The implement node always interrupts when gates are present
|
|
43
|
-
* (unless
|
|
44
|
+
* (unless all three gates are true, meaning fully autonomous).
|
|
45
|
+
*
|
|
46
|
+
* @param autoMerge - When true, overrides allowMerge to treat merge as approved.
|
|
44
47
|
*/
|
|
45
|
-
export declare function shouldInterrupt(nodeName: string, gates: ApprovalGates | undefined): boolean;
|
|
48
|
+
export declare function shouldInterrupt(nodeName: string, gates: ApprovalGates | undefined, autoMerge?: boolean): boolean;
|
|
46
49
|
export type ErrorCategory = 'retryable-api' | 'retryable-network' | 'non-retryable' | 'unknown';
|
|
47
50
|
/**
|
|
48
51
|
* Classify an error message into a retry category.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node-helpers.d.ts","sourceRoot":"","sources":["../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EACV,cAAc,EACd,qBAAqB,EACrB,oBAAoB,EACrB,MAAM,+DAA+D,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAIrD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM;kBAE/B,MAAM,GAAG,IAAI;mBAIZ,MAAM,GAAG,IAAI;EAK/B;AAED,MAAM,MAAM,UAAU,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE7D;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAMtE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,iBAAiB,GAAG,qBAAqB,CAMpF;AAeD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAQrD;AAED
|
|
1
|
+
{"version":3,"file":"node-helpers.d.ts","sourceRoot":"","sources":["../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EACV,cAAc,EACd,qBAAqB,EACrB,oBAAoB,EACrB,MAAM,+DAA+D,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAIrD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM;kBAE/B,MAAM,GAAG,IAAI;mBAIZ,MAAM,GAAG,IAAI;EAK/B;AAED,MAAM,MAAM,UAAU,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE7D;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAMtE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,iBAAiB,GAAG,qBAAqB,CAMpF;AAeD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAQrD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,aAAa,GAAG,SAAS,EAChC,SAAS,CAAC,EAAE,OAAO,GAClB,OAAO,CAWT;AAMD,MAAM,MAAM,aAAa,GAAG,eAAe,GAAG,mBAAmB,GAAG,eAAe,GAAG,SAAS,CAAC;AAMhG;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,YAAY,EAAE,MAAM,GAAG,aAAa,CAKjE;AAED,MAAM,WAAW,YAAY;IAC3B,wDAAwD;IACxD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kFAAkF;IAClF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0CAA0C;IAC1C,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB;AAED;;;;;;GAMG;AACH,wBAAsB,YAAY,CAChC,QAAQ,EAAE,cAAc,EACxB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,qBAAqB,EAC9B,SAAS,CAAC,EAAE,YAAY,GACvB,OAAO,CAAC,oBAAoB,CAAC,CA6B/B;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAW5D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,UAAU,GAAG,IAAI,CAwB1F;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CACzB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,cAAc,EACxB,WAAW,EAAE,CAAC,KAAK,EAAE,iBAAiB,EAAE,GAAG,EAAE,UAAU,KAAK,MAAM,GACjE,CAAC,KAAK,EAAE,iBAAiB,KAAK,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CA4EnE"}
|
package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.js
CHANGED
|
@@ -78,20 +78,26 @@ export function safeYamlLoad(content) {
|
|
|
78
78
|
* Gates control which phases auto-approve:
|
|
79
79
|
* - allowPrd: when true, skip interrupt after requirements phase
|
|
80
80
|
* - allowPlan: when true, skip interrupt after plan phase
|
|
81
|
+
* - allowMerge: when true, skip interrupt after merge phase
|
|
81
82
|
*
|
|
82
83
|
* Nodes not covered by a gate (analyze, research) never interrupt.
|
|
83
84
|
* The implement node always interrupts when gates are present
|
|
84
|
-
* (unless
|
|
85
|
+
* (unless all three gates are true, meaning fully autonomous).
|
|
86
|
+
*
|
|
87
|
+
* @param autoMerge - When true, overrides allowMerge to treat merge as approved.
|
|
85
88
|
*/
|
|
86
|
-
export function shouldInterrupt(nodeName, gates) {
|
|
89
|
+
export function shouldInterrupt(nodeName, gates, autoMerge) {
|
|
87
90
|
if (!gates)
|
|
88
91
|
return false;
|
|
89
|
-
|
|
92
|
+
const effectiveAllowMerge = autoMerge ?? gates.allowMerge;
|
|
93
|
+
if (gates.allowPrd && gates.allowPlan && effectiveAllowMerge)
|
|
90
94
|
return false;
|
|
91
95
|
if (nodeName === 'requirements')
|
|
92
96
|
return !gates.allowPrd;
|
|
93
97
|
if (nodeName === 'plan')
|
|
94
98
|
return !gates.allowPlan;
|
|
99
|
+
if (nodeName === 'merge')
|
|
100
|
+
return !effectiveAllowMerge;
|
|
95
101
|
if (nodeName === 'implement')
|
|
96
102
|
return true;
|
|
97
103
|
return false;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generates a pr.yaml file from spec metadata for pull request creation.
|
|
3
|
+
*
|
|
4
|
+
* Reads spec.yaml from the spec directory, extracts feature name, description,
|
|
5
|
+
* scope, and success criteria, then writes a pr.yaml with PR metadata in
|
|
6
|
+
* conventional commit format.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Generate a pr.yaml file in the spec directory with PR metadata.
|
|
10
|
+
*
|
|
11
|
+
* @param specDir - Path to the spec directory containing spec.yaml
|
|
12
|
+
* @param branch - Feature branch name (used as headBranch)
|
|
13
|
+
* @param baseBranch - Target branch for the PR (default: 'main')
|
|
14
|
+
* @returns Path to the generated pr.yaml file
|
|
15
|
+
*/
|
|
16
|
+
export declare function generatePrYaml(specDir: string, branch: string, baseBranch?: string): string;
|
|
17
|
+
//# sourceMappingURL=pr-yaml-generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pr-yaml-generator.d.ts","sourceRoot":"","sources":["../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/pr-yaml-generator.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAsBH;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,SAAS,GAAG,MAAM,CA+B3F"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generates a pr.yaml file from spec metadata for pull request creation.
|
|
3
|
+
*
|
|
4
|
+
* Reads spec.yaml from the spec directory, extracts feature name, description,
|
|
5
|
+
* scope, and success criteria, then writes a pr.yaml with PR metadata in
|
|
6
|
+
* conventional commit format.
|
|
7
|
+
*/
|
|
8
|
+
import yaml from 'js-yaml';
|
|
9
|
+
import { readFileSync, writeFileSync } from 'node:fs';
|
|
10
|
+
import { join } from 'node:path';
|
|
11
|
+
/**
|
|
12
|
+
* Generate a pr.yaml file in the spec directory with PR metadata.
|
|
13
|
+
*
|
|
14
|
+
* @param specDir - Path to the spec directory containing spec.yaml
|
|
15
|
+
* @param branch - Feature branch name (used as headBranch)
|
|
16
|
+
* @param baseBranch - Target branch for the PR (default: 'main')
|
|
17
|
+
* @returns Path to the generated pr.yaml file
|
|
18
|
+
*/
|
|
19
|
+
export function generatePrYaml(specDir, branch, baseBranch = 'main') {
|
|
20
|
+
const specContent = readFileSync(join(specDir, 'spec.yaml'), 'utf-8');
|
|
21
|
+
const spec = yaml.load(specContent);
|
|
22
|
+
const name = spec.name ?? 'Untitled feature';
|
|
23
|
+
const description = spec.description ?? '';
|
|
24
|
+
const scope = spec.scope;
|
|
25
|
+
const successCriteria = spec.successCriteria ?? [];
|
|
26
|
+
const title = scope ? `feat(${scope}): ${name}` : `feat: ${name}`;
|
|
27
|
+
const bodyParts = [];
|
|
28
|
+
bodyParts.push(`## Summary\n\n${description}`);
|
|
29
|
+
if (successCriteria.length > 0) {
|
|
30
|
+
bodyParts.push(`## Test Criteria\n\n${successCriteria.map((c) => `- ${c}`).join('\n')}`);
|
|
31
|
+
}
|
|
32
|
+
const prData = {
|
|
33
|
+
title,
|
|
34
|
+
body: bodyParts.join('\n\n'),
|
|
35
|
+
baseBranch,
|
|
36
|
+
headBranch: branch,
|
|
37
|
+
labels: ['feature'],
|
|
38
|
+
draft: false,
|
|
39
|
+
};
|
|
40
|
+
const outputPath = join(specDir, 'pr.yaml');
|
|
41
|
+
writeFileSync(outputPath, yaml.dump(prData, { indent: 2, lineWidth: -1 }), 'utf-8');
|
|
42
|
+
return outputPath;
|
|
43
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Merge Node Prompts
|
|
3
|
+
*
|
|
4
|
+
* Prompt builders for the merge node: CI fix instructions.
|
|
5
|
+
*/
|
|
6
|
+
export interface CiFixPromptParams {
|
|
7
|
+
logExcerpt: string;
|
|
8
|
+
specSummary: string;
|
|
9
|
+
attempt: number;
|
|
10
|
+
maxAttempts: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Build a constrained prompt for the AI agent when CI fails.
|
|
14
|
+
* Instructs the agent to fix the specific CI failure within bounded scope.
|
|
15
|
+
*/
|
|
16
|
+
export declare function buildCiFixPrompt(params: CiFixPromptParams): string;
|
|
17
|
+
//# sourceMappingURL=merge.prompt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge.prompt.d.ts","sourceRoot":"","sources":["../../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/merge.prompt.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAkClE"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Merge Node Prompts
|
|
3
|
+
*
|
|
4
|
+
* Prompt builders for the merge node: CI fix instructions.
|
|
5
|
+
*/
|
|
6
|
+
const MAX_LOG_EXCERPT_LENGTH = 6000;
|
|
7
|
+
/**
|
|
8
|
+
* Build a constrained prompt for the AI agent when CI fails.
|
|
9
|
+
* Instructs the agent to fix the specific CI failure within bounded scope.
|
|
10
|
+
*/
|
|
11
|
+
export function buildCiFixPrompt(params) {
|
|
12
|
+
const { specSummary, attempt, maxAttempts } = params;
|
|
13
|
+
const truncatedLog = params.logExcerpt.length > MAX_LOG_EXCERPT_LENGTH
|
|
14
|
+
? `${params.logExcerpt.slice(0, MAX_LOG_EXCERPT_LENGTH)}\n... (truncated)`
|
|
15
|
+
: params.logExcerpt;
|
|
16
|
+
return `You are a senior software engineer fixing a CI failure.
|
|
17
|
+
This is attempt ${attempt} of ${maxAttempts}.
|
|
18
|
+
|
|
19
|
+
## Feature Context
|
|
20
|
+
|
|
21
|
+
${specSummary}
|
|
22
|
+
|
|
23
|
+
## CI Failure Log
|
|
24
|
+
|
|
25
|
+
\`\`\`
|
|
26
|
+
${truncatedLog}
|
|
27
|
+
\`\`\`
|
|
28
|
+
|
|
29
|
+
## Instructions
|
|
30
|
+
|
|
31
|
+
1. Analyze the CI failure log above carefully
|
|
32
|
+
2. Identify the root cause of the failure
|
|
33
|
+
3. Apply the minimal fix to resolve the CI issue
|
|
34
|
+
4. Run the failing checks locally to verify your fix
|
|
35
|
+
|
|
36
|
+
## Constraints
|
|
37
|
+
|
|
38
|
+
- Fix ONLY the issue shown in the CI log — do not refactor or improve unrelated code
|
|
39
|
+
- Do not add new features or change behavior beyond what is needed to pass CI
|
|
40
|
+
- Keep changes as small and focused as possible
|
|
41
|
+
- Commit with a conventional commit message (e.g. \`fix(scope): resolve CI failure\`)`;
|
|
42
|
+
}
|
|
@@ -38,6 +38,14 @@ export declare const FeatureAgentAnnotation: import("@langchain/langgraph").Anno
|
|
|
38
38
|
validationRetries: import("@langchain/langgraph").BinaryOperatorAggregate<number, number>;
|
|
39
39
|
lastValidationTarget: import("@langchain/langgraph").BinaryOperatorAggregate<string, string>;
|
|
40
40
|
lastValidationErrors: import("@langchain/langgraph").BinaryOperatorAggregate<string[], string[]>;
|
|
41
|
+
prUrl: import("@langchain/langgraph").BinaryOperatorAggregate<string | null, string | null>;
|
|
42
|
+
prNumber: import("@langchain/langgraph").BinaryOperatorAggregate<number | null, number | null>;
|
|
43
|
+
commitHash: import("@langchain/langgraph").BinaryOperatorAggregate<string | null, string | null>;
|
|
44
|
+
ciStatus: import("@langchain/langgraph").BinaryOperatorAggregate<string | null, string | null>;
|
|
45
|
+
push: import("@langchain/langgraph").BinaryOperatorAggregate<boolean, boolean>;
|
|
46
|
+
openPr: import("@langchain/langgraph").BinaryOperatorAggregate<boolean, boolean>;
|
|
47
|
+
autoMerge: import("@langchain/langgraph").BinaryOperatorAggregate<boolean, boolean>;
|
|
48
|
+
allowMerge: import("@langchain/langgraph").BinaryOperatorAggregate<boolean, boolean>;
|
|
41
49
|
}>;
|
|
42
50
|
export type FeatureAgentState = typeof FeatureAgentAnnotation.State;
|
|
43
51
|
//# sourceMappingURL=state.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/state.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAElE;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB
|
|
1
|
+
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/state.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAElE;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgEjC,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG,OAAO,sBAAsB,CAAC,KAAK,CAAC"}
|
|
@@ -37,4 +37,37 @@ export const FeatureAgentAnnotation = Annotation.Root({
|
|
|
37
37
|
reducer: (_prev, next) => next,
|
|
38
38
|
default: () => [],
|
|
39
39
|
}),
|
|
40
|
+
// --- Merge and workflow state channels ---
|
|
41
|
+
prUrl: Annotation({
|
|
42
|
+
reducer: (_prev, next) => (next !== undefined ? next : _prev),
|
|
43
|
+
default: () => null,
|
|
44
|
+
}),
|
|
45
|
+
prNumber: Annotation({
|
|
46
|
+
reducer: (_prev, next) => (next !== undefined ? next : _prev),
|
|
47
|
+
default: () => null,
|
|
48
|
+
}),
|
|
49
|
+
commitHash: Annotation({
|
|
50
|
+
reducer: (_prev, next) => (next !== undefined ? next : _prev),
|
|
51
|
+
default: () => null,
|
|
52
|
+
}),
|
|
53
|
+
ciStatus: Annotation({
|
|
54
|
+
reducer: (_prev, next) => (next !== undefined ? next : _prev),
|
|
55
|
+
default: () => null,
|
|
56
|
+
}),
|
|
57
|
+
push: Annotation({
|
|
58
|
+
reducer: (_prev, next) => next,
|
|
59
|
+
default: () => false,
|
|
60
|
+
}),
|
|
61
|
+
openPr: Annotation({
|
|
62
|
+
reducer: (_prev, next) => next,
|
|
63
|
+
default: () => false,
|
|
64
|
+
}),
|
|
65
|
+
autoMerge: Annotation({
|
|
66
|
+
reducer: (_prev, next) => next,
|
|
67
|
+
default: () => false,
|
|
68
|
+
}),
|
|
69
|
+
allowMerge: Annotation({
|
|
70
|
+
reducer: (_prev, next) => next,
|
|
71
|
+
default: () => false,
|
|
72
|
+
}),
|
|
40
73
|
});
|
|
@@ -0,0 +1,28 @@
|
|
|
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
|
+
import type { IGitPrService } from '../../../application/ports/output/services/git-pr-service.interface.js';
|
|
8
|
+
import type { CiStatusResult, DiffSummary, MergeStrategy, PrCreateResult } from '../../../application/ports/output/services/git-pr-service.interface.js';
|
|
9
|
+
import type { ExecFunction } from './worktree.service.js';
|
|
10
|
+
export declare class GitPrService implements IGitPrService {
|
|
11
|
+
private readonly execFile;
|
|
12
|
+
constructor(execFile: ExecFunction);
|
|
13
|
+
hasUncommittedChanges(cwd: string): Promise<boolean>;
|
|
14
|
+
commitAll(cwd: string, message: string): Promise<string>;
|
|
15
|
+
push(cwd: string, branch: string, setUpstream?: boolean): Promise<void>;
|
|
16
|
+
createPr(cwd: string, prYamlPath: string): Promise<PrCreateResult>;
|
|
17
|
+
mergePr(cwd: string, prNumber: number, strategy?: MergeStrategy): Promise<void>;
|
|
18
|
+
mergeBranch(cwd: string, sourceBranch: string, targetBranch: string): Promise<void>;
|
|
19
|
+
getCiStatus(cwd: string, branch: string): Promise<CiStatusResult>;
|
|
20
|
+
watchCi(cwd: string, branch: string, timeoutMs?: number): Promise<CiStatusResult>;
|
|
21
|
+
deleteBranch(cwd: string, branch: string, deleteRemote?: boolean): Promise<void>;
|
|
22
|
+
getPrDiffSummary(cwd: string, baseBranch: string): Promise<DiffSummary>;
|
|
23
|
+
private parseGitError;
|
|
24
|
+
private parseGhError;
|
|
25
|
+
private parsePrNumberFromUrl;
|
|
26
|
+
private parseDiffStat;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=git-pr.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-pr.service.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/infrastructure/services/git/git-pr.service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wEAAwE,CAAC;AAC5G,OAAO,KAAK,EACV,cAAc,EACd,WAAW,EACX,aAAa,EACb,cAAc,EACf,MAAM,wEAAwE,CAAC;AAKhF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAE1D,qBACa,YAAa,YAAW,aAAa;IACZ,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,YAAY;IAErE,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKpD,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAWxD,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAYvE,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAelE,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,GAAE,aAAwB,GAAG,OAAO,CAAC,IAAI,CAAC;IAUzF,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUnF,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAkBjE,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAuBjF,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAWhF,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAe7E,OAAO,CAAC,aAAa;IAcrB,OAAO,CAAC,YAAY;IAepB,OAAO,CAAC,oBAAoB;IAK5B,OAAO,CAAC,aAAa;CAiBtB"}
|