@shepai/cli 1.38.0 → 1.40.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 +1 -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/use-cases/agents/approve-agent-run.use-case.d.ts +5 -4
- package/dist/packages/core/src/application/use-cases/agents/approve-agent-run.use-case.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/agents/approve-agent-run.use-case.js +36 -14
- package/dist/packages/core/src/application/use-cases/agents/reject-agent-run.use-case.d.ts +12 -3
- package/dist/packages/core/src/application/use-cases/agents/reject-agent-run.use-case.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/agents/reject-agent-run.use-case.js +88 -8
- package/dist/packages/core/src/application/use-cases/agents/review-feature.use-case.d.ts +35 -0
- package/dist/packages/core/src/application/use-cases/agents/review-feature.use-case.d.ts.map +1 -0
- package/dist/packages/core/src/application/use-cases/agents/review-feature.use-case.js +88 -0
- package/dist/packages/core/src/domain/generated/output.d.ts +102 -0
- package/dist/packages/core/src/domain/generated/output.d.ts.map +1 -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/services/agents/common/agent-executor-factory.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/common/agent-executor-factory.service.js +5 -1
- package/dist/packages/core/src/infrastructure/services/agents/common/agent-validator.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/common/agent-validator.service.js +1 -0
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/gemini-cli-executor.service.d.ts +52 -0
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/gemini-cli-executor.service.d.ts.map +1 -0
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/gemini-cli-executor.service.js +337 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-graph.d.ts +51 -0
- 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 +21 -2
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-process.service.d.ts +1 -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 +3 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.d.ts +1 -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 +31 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.d.ts +19 -3
- 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 +101 -16
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/requirements.prompt.d.ts +2 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/requirements.prompt.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/requirements.prompt.js +53 -27
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/phase-timing-context.d.ts +3 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/phase-timing-context.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/phase-timing-context.js +28 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/state.d.ts +3 -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 +13 -0
- package/dist/src/presentation/cli/commands/agent/reject.command.js +1 -1
- package/dist/src/presentation/cli/commands/feat/reject.command.d.ts.map +1 -1
- package/dist/src/presentation/cli/commands/feat/reject.command.js +6 -4
- package/dist/src/presentation/cli/commands/feat/review.command.d.ts +3 -2
- package/dist/src/presentation/cli/commands/feat/review.command.d.ts.map +1 -1
- package/dist/src/presentation/cli/commands/feat/review.command.js +87 -12
- package/dist/src/presentation/cli/commands/feat/show.command.d.ts.map +1 -1
- package/dist/src/presentation/cli/commands/feat/show.command.js +38 -3
- package/dist/src/presentation/tui/prompts/agent-select.prompt.d.ts +1 -1
- package/dist/src/presentation/tui/prompts/agent-select.prompt.js +1 -1
- package/dist/src/presentation/tui/prompts/prd-review-question.prompt.d.ts +30 -0
- package/dist/src/presentation/tui/prompts/prd-review-question.prompt.d.ts.map +1 -0
- package/dist/src/presentation/tui/prompts/prd-review-question.prompt.js +23 -0
- package/dist/src/presentation/tui/prompts/prd-review-summary.prompt.d.ts +29 -0
- package/dist/src/presentation/tui/prompts/prd-review-summary.prompt.d.ts.map +1 -0
- package/dist/src/presentation/tui/prompts/prd-review-summary.prompt.js +29 -0
- package/dist/src/presentation/tui/wizards/merge-review.wizard.d.ts +13 -0
- package/dist/src/presentation/tui/wizards/merge-review.wizard.d.ts.map +1 -0
- package/dist/src/presentation/tui/wizards/merge-review.wizard.js +43 -0
- package/dist/src/presentation/tui/wizards/plan-review.wizard.d.ts +13 -0
- package/dist/src/presentation/tui/wizards/plan-review.wizard.d.ts.map +1 -0
- package/dist/src/presentation/tui/wizards/plan-review.wizard.js +43 -0
- package/dist/src/presentation/tui/wizards/prd-review.wizard.d.ts +26 -0
- package/dist/src/presentation/tui/wizards/prd-review.wizard.d.ts.map +1 -0
- package/dist/src/presentation/tui/wizards/prd-review.wizard.js +42 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- 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/page/server-reference-manifest.json +9 -9
- package/web/.next/server/app/page_client-reference-manifest.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__03a0dba7._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__03a0dba7._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__19354aea._.js +2 -2
- 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.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_ed0934e5._.js.map +1 -1
- 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 +10 -10
- package/web/.next/standalone/src/presentation/web/.next/BUILD_ID +1 -1
- package/web/.next/standalone/src/presentation/web/.next/build-manifest.json +2 -2
- package/web/.next/standalone/src/presentation/web/.next/prerender-manifest.json +3 -3
- package/web/.next/standalone/src/presentation/web/.next/required-server-files.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.html +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/page/server-reference-manifest.json +9 -9
- package/web/.next/standalone/src/presentation/web/.next/server/app/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__03a0dba7._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__19354aea._.js +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__f12b60be._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/pages/500.html +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/server-reference-manifest.json +10 -10
- package/web/.next/standalone/src/presentation/web/server.js +1 -1
- package/web/.next/static/chunks/{eca1959e083d0a45.js → 8bea0ce8a07abd50.js} +1 -1
- package/web/.next/trace +1 -1
- package/web/.next/trace-build +1 -1
- /package/web/.next/static/{yvV-GEMagQiZhZAF0YqQs → o1NQgNmvCnthgfg2Ubmf_}/_buildManifest.js +0 -0
- /package/web/.next/static/{yvV-GEMagQiZhZAF0YqQs → o1NQgNmvCnthgfg2Ubmf_}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{yvV-GEMagQiZhZAF0YqQs → o1NQgNmvCnthgfg2Ubmf_}/_ssgManifest.js +0 -0
|
@@ -2,14 +2,40 @@
|
|
|
2
2
|
* Requirements Phase Prompt
|
|
3
3
|
*
|
|
4
4
|
* Instructs the agent to build comprehensive requirements from the analysis,
|
|
5
|
-
* including product questions with
|
|
5
|
+
* including product questions with structured QuestionOption[] arrays
|
|
6
|
+
* and AI-recommended default answers.
|
|
6
7
|
* Writes back to spec.yaml with full requirements.
|
|
7
8
|
*/
|
|
9
|
+
import yaml from 'js-yaml';
|
|
8
10
|
import { readSpecFile } from '../node-helpers.js';
|
|
9
11
|
export function buildRequirementsPrompt(state) {
|
|
10
12
|
const specContent = readSpecFile(state.specDir, 'spec.yaml');
|
|
13
|
+
// Extract rejection feedback if present
|
|
14
|
+
let rejectionFeedbackSection = '';
|
|
15
|
+
try {
|
|
16
|
+
const specData = yaml.load(specContent);
|
|
17
|
+
const rejectionFeedback = specData?.rejectionFeedback;
|
|
18
|
+
if (rejectionFeedback && rejectionFeedback.length > 0) {
|
|
19
|
+
const entries = rejectionFeedback
|
|
20
|
+
.map((entry) => `- **Iteration ${entry.iteration}** (${entry.timestamp}): ${entry.message}`)
|
|
21
|
+
.join('\n');
|
|
22
|
+
rejectionFeedbackSection = `
|
|
23
|
+
## Previous Rejection Feedback
|
|
24
|
+
|
|
25
|
+
The user has previously rejected this PRD with the following feedback. You MUST address these concerns in your revised output:
|
|
26
|
+
|
|
27
|
+
${entries}
|
|
28
|
+
|
|
29
|
+
Focus on the most recent feedback (highest iteration number) while ensuring earlier feedback is still addressed.
|
|
30
|
+
|
|
31
|
+
`;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
// If YAML parsing fails, continue without rejection feedback
|
|
36
|
+
}
|
|
11
37
|
return `You are a product analyst performing the REQUIREMENTS phase of feature development.
|
|
12
|
-
|
|
38
|
+
${rejectionFeedbackSection}
|
|
13
39
|
## Your Task
|
|
14
40
|
|
|
15
41
|
1. Read the current spec with codebase analysis below
|
|
@@ -29,13 +55,20 @@ ${specContent}
|
|
|
29
55
|
- **Non-functional requirements (NFR-N)**: performance, security, UX, maintainability constraints
|
|
30
56
|
- **Success criteria**: measurable checkboxes that define "done"
|
|
31
57
|
|
|
32
|
-
### Product Questions with
|
|
58
|
+
### Product Questions with Structured Options
|
|
33
59
|
For every ambiguous product decision, create an openQuestion entry with:
|
|
34
60
|
- A clear question
|
|
35
61
|
- resolved: true (your recommendation is the default)
|
|
36
|
-
-
|
|
62
|
+
- Structured options array with EXACTLY ONE option marked selected: true
|
|
63
|
+
- A selectionRationale explaining the recommendation
|
|
64
|
+
- An answer field containing the text of the selected option (for backward compatibility)
|
|
65
|
+
|
|
66
|
+
Each option MUST have:
|
|
67
|
+
- \`option\`: Short label for the approach (2-5 words)
|
|
68
|
+
- \`description\`: Explanation of this option's trade-offs and benefits
|
|
69
|
+
- \`selected\`: boolean — exactly ONE option per question must be true
|
|
37
70
|
|
|
38
|
-
The user can later review and override these defaults
|
|
71
|
+
The user can later review and override these defaults via interactive TUI.
|
|
39
72
|
|
|
40
73
|
## Output Instructions
|
|
41
74
|
|
|
@@ -63,32 +96,25 @@ Write the COMPLETE file. Preserve name/number/branch/technologies from analysis
|
|
|
63
96
|
- question: 'Should X use approach A, B, or C?'
|
|
64
97
|
resolved: true
|
|
65
98
|
options:
|
|
66
|
-
- option: Approach A
|
|
67
|
-
description:
|
|
99
|
+
- option: 'Approach A'
|
|
100
|
+
description: 'Benefits of A, when to use it, trade-offs'
|
|
68
101
|
selected: true
|
|
69
|
-
- option: Approach B
|
|
70
|
-
description:
|
|
71
|
-
selected: false
|
|
72
|
-
- option: Approach C
|
|
73
|
-
description: (What approach C means and its trade-offs)
|
|
102
|
+
- option: 'Approach B'
|
|
103
|
+
description: 'Benefits of B, when to use it, trade-offs'
|
|
74
104
|
selected: false
|
|
75
|
-
selectionRationale:
|
|
76
|
-
|
|
77
|
-
Reference codebase patterns where relevant.)
|
|
105
|
+
selectionRationale: 'Approach A is recommended because [detailed reasoning]'
|
|
106
|
+
answer: 'Approach A'
|
|
78
107
|
- question: 'What level of Y is needed?'
|
|
79
108
|
resolved: true
|
|
80
109
|
options:
|
|
81
|
-
- option:
|
|
82
|
-
description:
|
|
83
|
-
selected: true
|
|
84
|
-
- option: Level Y
|
|
85
|
-
description: (What level Y means and its trade-offs)
|
|
86
|
-
selected: false
|
|
87
|
-
- option: Level Z
|
|
88
|
-
description: (What level Z means and its trade-offs)
|
|
110
|
+
- option: 'Basic'
|
|
111
|
+
description: 'Minimal implementation, fast to build'
|
|
89
112
|
selected: false
|
|
90
|
-
|
|
91
|
-
|
|
113
|
+
- option: 'Advanced'
|
|
114
|
+
description: 'Full-featured, handles edge cases'
|
|
115
|
+
selected: true
|
|
116
|
+
selectionRationale: 'Advanced is recommended because [reasoning]'
|
|
117
|
+
answer: 'Advanced'
|
|
92
118
|
|
|
93
119
|
content: |
|
|
94
120
|
## Problem Statement
|
|
@@ -132,8 +158,8 @@ Write the COMPLETE file. Preserve name/number/branch/technologies from analysis
|
|
|
132
158
|
## Constraints
|
|
133
159
|
|
|
134
160
|
- Write ONLY to ${state.specDir}/spec.yaml
|
|
135
|
-
- Every open question MUST have
|
|
136
|
-
- Every open question MUST have
|
|
161
|
+
- Every open question MUST have structured options with exactly ONE option marked selected: true
|
|
162
|
+
- Every open question MUST also have an \`answer\` field matching the selected option text
|
|
137
163
|
- Requirements must be specific and testable, not vague
|
|
138
164
|
- Do NOT create any other files
|
|
139
165
|
- Do NOT modify any source code`;
|
|
@@ -24,6 +24,9 @@ export declare function clearPhaseTimingContext(): void;
|
|
|
24
24
|
/**
|
|
25
25
|
* Record the start of a phase. Returns the timing record ID (for later update)
|
|
26
26
|
* or null if context is not set or save fails.
|
|
27
|
+
*
|
|
28
|
+
* Automatically appends an iteration suffix (`:2`, `:3`, …) when the same
|
|
29
|
+
* phase has already been recorded for this run (e.g. after a rejection loop).
|
|
27
30
|
*/
|
|
28
31
|
export declare function recordPhaseStart(phase: string): Promise<string | null>;
|
|
29
32
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"phase-timing-context.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/phase-timing-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,wEAAwE,CAAC;AAMrH;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,GAAG,IAAI,CAE/C;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,sBAAsB,GAAG,IAAI,CAG7F;AAED;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,IAAI,CAI9C;
|
|
1
|
+
{"version":3,"file":"phase-timing-context.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/phase-timing-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,wEAAwE,CAAC;AAMrH;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,GAAG,IAAI,CAE/C;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,sBAAsB,GAAG,IAAI,CAG7F;AAED;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,IAAI,CAI9C;AA+BD;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAsB5E;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAW/F;AAED;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,MAAM,EACb,aAAa,CAAC,EAAE,MAAM,EACtB,YAAY,CAAC,EAAE,sBAAsB,GACpC,OAAO,CAAC,IAAI,CAAC,CAoBf;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAUpF"}
|
package/dist/packages/core/src/infrastructure/services/agents/feature-agent/phase-timing-context.js
CHANGED
|
@@ -33,9 +33,35 @@ export function clearPhaseTimingContext() {
|
|
|
33
33
|
contextRepository = undefined;
|
|
34
34
|
lastTimingId = null;
|
|
35
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Compute the iteration-aware phase name.
|
|
38
|
+
*
|
|
39
|
+
* Queries existing PhaseTiming rows for the current run, counts how many
|
|
40
|
+
* share the same base phase name, and appends `:N` for iterations > 1.
|
|
41
|
+
*
|
|
42
|
+
* Examples:
|
|
43
|
+
* - First "requirements" execution → "requirements"
|
|
44
|
+
* - Second "requirements" execution → "requirements:2"
|
|
45
|
+
* - Third "requirements" execution → "requirements:3"
|
|
46
|
+
*/
|
|
47
|
+
async function resolveIterationPhase(phase, runId, repository) {
|
|
48
|
+
try {
|
|
49
|
+
const existing = await repository.findByRunId(runId);
|
|
50
|
+
// Count rows whose phase is the base name or matches the base:N pattern
|
|
51
|
+
const count = existing.filter((t) => t.phase === phase || t.phase.startsWith(`${phase}:`)).length;
|
|
52
|
+
return count === 0 ? phase : `${phase}:${count + 1}`;
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
// On error, fall back to bare phase name
|
|
56
|
+
return phase;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
36
59
|
/**
|
|
37
60
|
* Record the start of a phase. Returns the timing record ID (for later update)
|
|
38
61
|
* or null if context is not set or save fails.
|
|
62
|
+
*
|
|
63
|
+
* Automatically appends an iteration suffix (`:2`, `:3`, …) when the same
|
|
64
|
+
* phase has already been recorded for this run (e.g. after a rejection loop).
|
|
39
65
|
*/
|
|
40
66
|
export async function recordPhaseStart(phase) {
|
|
41
67
|
if (!contextRunId || !contextRepository)
|
|
@@ -43,10 +69,11 @@ export async function recordPhaseStart(phase) {
|
|
|
43
69
|
const id = randomUUID();
|
|
44
70
|
const now = new Date();
|
|
45
71
|
try {
|
|
72
|
+
const iterationPhase = await resolveIterationPhase(phase, contextRunId, contextRepository);
|
|
46
73
|
await contextRepository.save({
|
|
47
74
|
id,
|
|
48
75
|
agentRunId: contextRunId,
|
|
49
|
-
phase,
|
|
76
|
+
phase: iterationPhase,
|
|
50
77
|
startedAt: now,
|
|
51
78
|
createdAt: now,
|
|
52
79
|
updatedAt: now,
|
|
@@ -38,6 +38,9 @@ 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
|
+
_approvalAction: import("@langchain/langgraph").BinaryOperatorAggregate<string | null, string | null>;
|
|
42
|
+
_rejectionFeedback: import("@langchain/langgraph").BinaryOperatorAggregate<string | null, string | null>;
|
|
43
|
+
_needsReexecution: import("@langchain/langgraph").BinaryOperatorAggregate<boolean, boolean>;
|
|
41
44
|
prUrl: import("@langchain/langgraph").BinaryOperatorAggregate<string | null, string | null>;
|
|
42
45
|
prNumber: import("@langchain/langgraph").BinaryOperatorAggregate<number | null, number | null>;
|
|
43
46
|
commitHash: import("@langchain/langgraph").BinaryOperatorAggregate<string | null, string | null>;
|
|
@@ -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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAqEjC,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG,OAAO,sBAAsB,CAAC,KAAK,CAAC"}
|
|
@@ -37,6 +37,19 @@ export const FeatureAgentAnnotation = Annotation.Root({
|
|
|
37
37
|
reducer: (_prev, next) => next,
|
|
38
38
|
default: () => [],
|
|
39
39
|
}),
|
|
40
|
+
// --- Approval action channels (set by Command({update}) on resume) ---
|
|
41
|
+
_approvalAction: Annotation({
|
|
42
|
+
reducer: (_prev, next) => (next !== undefined ? next : _prev),
|
|
43
|
+
default: () => null,
|
|
44
|
+
}),
|
|
45
|
+
_rejectionFeedback: Annotation({
|
|
46
|
+
reducer: (_prev, next) => (next !== undefined ? next : _prev),
|
|
47
|
+
default: () => null,
|
|
48
|
+
}),
|
|
49
|
+
_needsReexecution: Annotation({
|
|
50
|
+
reducer: (_prev, next) => next,
|
|
51
|
+
default: () => false,
|
|
52
|
+
}),
|
|
40
53
|
// --- Merge and workflow state channels ---
|
|
41
54
|
prUrl: Annotation({
|
|
42
55
|
reducer: (_prev, next) => (next !== undefined ? next : _prev),
|
|
@@ -25,7 +25,7 @@ export function createRejectCommand() {
|
|
|
25
25
|
return;
|
|
26
26
|
}
|
|
27
27
|
const useCase = container.resolve(RejectAgentRunUseCase);
|
|
28
|
-
const result = await useCase.execute(resolved.run.id, opts.reason);
|
|
28
|
+
const result = await useCase.execute(resolved.run.id, opts.reason ?? 'Rejected by user');
|
|
29
29
|
if (result.rejected) {
|
|
30
30
|
messages.success(`Rejected ${colors.accent(resolved.run.id.substring(0, 8))}: ${result.reason}`);
|
|
31
31
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reject.command.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/cli/commands/feat/reject.command.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,wBAAgB,mBAAmB,IAAI,OAAO,
|
|
1
|
+
{"version":3,"file":"reject.command.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/cli/commands/feat/reject.command.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,wBAAgB,mBAAmB,IAAI,OAAO,CAwC7C"}
|
|
@@ -16,7 +16,7 @@ export function createRejectCommand() {
|
|
|
16
16
|
return new Command('reject')
|
|
17
17
|
.description('Reject a feature waiting for review')
|
|
18
18
|
.argument('[id]', 'Feature ID (auto-resolves if omitted)')
|
|
19
|
-
.
|
|
19
|
+
.requiredOption('--reason <text>', 'Rejection feedback (required)')
|
|
20
20
|
.action(async (featureId, options) => {
|
|
21
21
|
try {
|
|
22
22
|
const featureRepo = container.resolve('IFeatureRepository');
|
|
@@ -35,10 +35,12 @@ export function createRejectCommand() {
|
|
|
35
35
|
}
|
|
36
36
|
messages.newline();
|
|
37
37
|
messages.warning(`Rejected: ${feature.name}`);
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
console.log(` ${colors.muted('Reason:')} ${options.reason}`);
|
|
39
|
+
console.log(` ${colors.muted('Iteration:')} ${result.iteration}`);
|
|
40
|
+
if (result.iterationWarning) {
|
|
41
|
+
messages.warning('Warning: 5+ iterations. Consider refining the prompt instead.');
|
|
40
42
|
}
|
|
41
|
-
console.log(` ${colors.muted('Agent:')}
|
|
43
|
+
console.log(` ${colors.muted('Agent:')} re-running requirements`);
|
|
42
44
|
messages.newline();
|
|
43
45
|
}
|
|
44
46
|
catch (error) {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Feature Review Command
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Interactive review of a feature waiting for approval.
|
|
5
|
+
* Routes to phase-specific TUI wizard (PRD, Plan, or Merge),
|
|
6
|
+
* then calls approve or reject use case based on user action.
|
|
6
7
|
*
|
|
7
8
|
* Usage:
|
|
8
9
|
* shep feat review [id]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"review.command.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/cli/commands/feat/review.command.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"review.command.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/cli/commands/feat/review.command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAiEpC,wBAAgB,mBAAmB,IAAI,OAAO,CA2E7C"}
|
|
@@ -1,19 +1,60 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Feature Review Command
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Interactive review of a feature waiting for approval.
|
|
5
|
+
* Routes to phase-specific TUI wizard (PRD, Plan, or Merge),
|
|
6
|
+
* then calls approve or reject use case based on user action.
|
|
6
7
|
*
|
|
7
8
|
* Usage:
|
|
8
9
|
* shep feat review [id]
|
|
9
10
|
*/
|
|
10
11
|
import { Command } from 'commander';
|
|
11
12
|
import { container } from '../../../../../packages/core/src/infrastructure/di/container.js';
|
|
13
|
+
import { ReviewFeatureUseCase } from '../../../../../packages/core/src/application/use-cases/agents/review-feature.use-case.js';
|
|
14
|
+
import { ApproveAgentRunUseCase } from '../../../../../packages/core/src/application/use-cases/agents/approve-agent-run.use-case.js';
|
|
15
|
+
import { RejectAgentRunUseCase } from '../../../../../packages/core/src/application/use-cases/agents/reject-agent-run.use-case.js';
|
|
12
16
|
import { resolveWaitingFeature } from './resolve-waiting-feature.js';
|
|
17
|
+
import { prdReviewWizard } from '../../../tui/wizards/prd-review.wizard.js';
|
|
18
|
+
import { planReviewWizard } from '../../../tui/wizards/plan-review.wizard.js';
|
|
19
|
+
import { mergeReviewWizard } from '../../../tui/wizards/merge-review.wizard.js';
|
|
13
20
|
import { colors, messages } from '../../ui/index.js';
|
|
21
|
+
function parsePhase(runResult) {
|
|
22
|
+
return runResult?.startsWith('node:') ? runResult.slice(5) : 'unknown';
|
|
23
|
+
}
|
|
24
|
+
async function runPhaseWizard(phase, featureId, repoPath) {
|
|
25
|
+
if (phase === 'requirements') {
|
|
26
|
+
const reviewUseCase = container.resolve(ReviewFeatureUseCase);
|
|
27
|
+
const reviewResult = await reviewUseCase.execute(featureId, repoPath);
|
|
28
|
+
if (!reviewResult.success) {
|
|
29
|
+
throw new Error(reviewResult.reason);
|
|
30
|
+
}
|
|
31
|
+
return prdReviewWizard(reviewResult.questions);
|
|
32
|
+
}
|
|
33
|
+
if (phase === 'plan') {
|
|
34
|
+
const result = await planReviewWizard();
|
|
35
|
+
return { action: result.action, feedback: result.feedback };
|
|
36
|
+
}
|
|
37
|
+
if (phase === 'merge') {
|
|
38
|
+
const result = await mergeReviewWizard();
|
|
39
|
+
return { action: result.action, feedback: result.feedback };
|
|
40
|
+
}
|
|
41
|
+
throw new Error(`Unknown approval phase: ${phase}`);
|
|
42
|
+
}
|
|
43
|
+
function phaseNextStep(phase) {
|
|
44
|
+
switch (phase) {
|
|
45
|
+
case 'requirements':
|
|
46
|
+
return 'research';
|
|
47
|
+
case 'plan':
|
|
48
|
+
return 'implementation';
|
|
49
|
+
case 'merge':
|
|
50
|
+
return 'merge';
|
|
51
|
+
default:
|
|
52
|
+
return 'next step';
|
|
53
|
+
}
|
|
54
|
+
}
|
|
14
55
|
export function createReviewCommand() {
|
|
15
56
|
return new Command('review')
|
|
16
|
-
.description('
|
|
57
|
+
.description('Interactive review of a feature waiting for approval')
|
|
17
58
|
.argument('[id]', 'Feature ID (auto-resolves if omitted)')
|
|
18
59
|
.action(async (featureId) => {
|
|
19
60
|
try {
|
|
@@ -26,19 +67,53 @@ export function createReviewCommand() {
|
|
|
26
67
|
featureRepo,
|
|
27
68
|
runRepo,
|
|
28
69
|
});
|
|
29
|
-
const phase =
|
|
70
|
+
const phase = parsePhase(run.result);
|
|
30
71
|
messages.newline();
|
|
31
|
-
messages.info(`
|
|
32
|
-
console.log(` ${colors.muted('ID:')} ${feature.id.slice(0, 8)}`);
|
|
72
|
+
messages.info(`Reviewing: ${colors.accent(feature.name)}`);
|
|
33
73
|
console.log(` ${colors.muted('Phase:')} ${colors.warning(phase)}`);
|
|
34
74
|
console.log(` ${colors.muted('Branch:')} ${colors.accent(feature.branch)}`);
|
|
35
|
-
if (feature.specPath) {
|
|
36
|
-
console.log(` ${colors.muted('Specs:')} ${feature.specPath}`);
|
|
37
|
-
}
|
|
38
|
-
messages.newline();
|
|
39
|
-
console.log(` ${colors.muted('To approve:')} shep feat approve ${feature.id.slice(0, 8)}`);
|
|
40
|
-
console.log(` ${colors.muted('To reject:')} shep feat reject ${feature.id.slice(0, 8)}`);
|
|
41
75
|
messages.newline();
|
|
76
|
+
const wizardResult = await runPhaseWizard(phase, feature.id, repoPath);
|
|
77
|
+
if (wizardResult.action === 'approve') {
|
|
78
|
+
const approveUseCase = container.resolve(ApproveAgentRunUseCase);
|
|
79
|
+
const payload = wizardResult.changedSelections && wizardResult.changedSelections.length > 0
|
|
80
|
+
? { approved: true, changedSelections: wizardResult.changedSelections }
|
|
81
|
+
: undefined;
|
|
82
|
+
const approveResult = await approveUseCase.execute(run.id, payload);
|
|
83
|
+
if (approveResult.approved) {
|
|
84
|
+
messages.newline();
|
|
85
|
+
messages.success(`Approved: ${feature.name}`);
|
|
86
|
+
if (wizardResult.changedSelections && wizardResult.changedSelections.length > 0) {
|
|
87
|
+
console.log(` ${colors.muted('Changes:')} ${wizardResult.changedSelections.length} selection(s) updated`);
|
|
88
|
+
}
|
|
89
|
+
if (wizardResult.feedback) {
|
|
90
|
+
console.log(` ${colors.muted('Comment:')} ${wizardResult.feedback}`);
|
|
91
|
+
}
|
|
92
|
+
console.log(` ${colors.muted('Agent:')} proceeding to ${phaseNextStep(phase)}`);
|
|
93
|
+
messages.newline();
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
throw new Error(approveResult.reason);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
const rejectUseCase = container.resolve(RejectAgentRunUseCase);
|
|
101
|
+
const rejectResult = await rejectUseCase.execute(run.id, wizardResult.feedback);
|
|
102
|
+
if (rejectResult.rejected) {
|
|
103
|
+
messages.newline();
|
|
104
|
+
messages.warning(`Rejected: ${feature.name}`);
|
|
105
|
+
console.log(` ${colors.muted('Feedback:')} ${wizardResult.feedback}`);
|
|
106
|
+
console.log(` ${colors.muted('Iteration:')} ${rejectResult.iteration}`);
|
|
107
|
+
if (rejectResult.iterationWarning) {
|
|
108
|
+
messages.warning('Warning: 5+ iterations. Consider refining the prompt instead.');
|
|
109
|
+
}
|
|
110
|
+
console.log(` ${colors.muted('Agent:')} re-running ${phase}`);
|
|
111
|
+
messages.newline();
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
throw new Error(rejectResult.reason);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
42
117
|
}
|
|
43
118
|
catch (error) {
|
|
44
119
|
const err = error instanceof Error ? error : new Error(String(error));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"show.command.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/cli/commands/feat/show.command.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;
|
|
1
|
+
{"version":3,"file":"show.command.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/cli/commands/feat/show.command.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA+VpC,wBAAgB,iBAAiB,IAAI,OAAO,CAyJ3C"}
|
|
@@ -6,7 +6,10 @@
|
|
|
6
6
|
*
|
|
7
7
|
* Usage: shep feat show <id>
|
|
8
8
|
*/
|
|
9
|
+
import { readFileSync } from 'node:fs';
|
|
10
|
+
import { join } from 'node:path';
|
|
9
11
|
import { Command } from 'commander';
|
|
12
|
+
import yaml from 'js-yaml';
|
|
10
13
|
import { container } from '../../../../../packages/core/src/infrastructure/di/container.js';
|
|
11
14
|
import { ShowFeatureUseCase } from '../../../../../packages/core/src/application/use-cases/features/show-feature.use-case.js';
|
|
12
15
|
import { colors, symbols, messages, renderDetailView } from '../../ui/index.js';
|
|
@@ -94,6 +97,23 @@ function isProcessAlive(pid) {
|
|
|
94
97
|
return false;
|
|
95
98
|
}
|
|
96
99
|
}
|
|
100
|
+
/**
|
|
101
|
+
* Load rejection feedback entries from spec.yaml (best-effort).
|
|
102
|
+
*/
|
|
103
|
+
function loadRejectionFeedback(specPath) {
|
|
104
|
+
if (!specPath)
|
|
105
|
+
return [];
|
|
106
|
+
try {
|
|
107
|
+
const content = readFileSync(join(specPath, 'spec.yaml'), 'utf-8');
|
|
108
|
+
const spec = yaml.load(content);
|
|
109
|
+
return Array.isArray(spec?.rejectionFeedback)
|
|
110
|
+
? spec.rejectionFeedback
|
|
111
|
+
: [];
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
return [];
|
|
115
|
+
}
|
|
116
|
+
}
|
|
97
117
|
/**
|
|
98
118
|
* Group timings by agentRunId, preserving order.
|
|
99
119
|
*/
|
|
@@ -117,7 +137,7 @@ function renderNodeTiming(t, isLast, isWaiting, isRunTerminal, run, maxDurationM
|
|
|
117
137
|
const lines = [];
|
|
118
138
|
const isSubPhase = t.phase.includes(':');
|
|
119
139
|
const label = isSubPhase
|
|
120
|
-
? ` \u21b3 ${t.phase.split(':')[1]}`.padEnd(16)
|
|
140
|
+
? ` \u21b3 rev ${t.phase.split(':')[1]}`.padEnd(16)
|
|
121
141
|
: (NODE_TO_PHASE[t.phase] ?? t.phase).padEnd(16);
|
|
122
142
|
// Completed phase - green bar with duration
|
|
123
143
|
if (t.completedAt && t.durationMs != null) {
|
|
@@ -185,7 +205,7 @@ function renderNodeTiming(t, isLast, isWaiting, isRunTerminal, run, maxDurationM
|
|
|
185
205
|
/**
|
|
186
206
|
* Render the full phase timing section, grouped by agent run with lifecycle events.
|
|
187
207
|
*/
|
|
188
|
-
function renderPhaseTimings(timings, currentRun) {
|
|
208
|
+
function renderPhaseTimings(timings, currentRun, rejections = []) {
|
|
189
209
|
const groups = groupTimingsByRun(timings);
|
|
190
210
|
const multiRun = groups.length > 1;
|
|
191
211
|
// Compute max duration across ALL timings for consistent bar scaling
|
|
@@ -220,12 +240,26 @@ function renderPhaseTimings(timings, currentRun) {
|
|
|
220
240
|
currentRun?.status === 'failed' ||
|
|
221
241
|
currentRun?.status === 'cancelled';
|
|
222
242
|
const isWaiting = isCurrentRun && currentRun?.status === 'waiting_approval';
|
|
243
|
+
let resumedIdx = 0;
|
|
223
244
|
for (const [idx, t] of group.timings.entries()) {
|
|
224
245
|
const isLast = isLastGroup && idx === group.timings.length - 1;
|
|
225
246
|
// Lifecycle event - render as a marker line
|
|
226
247
|
if (isLifecycleEvent(t.phase)) {
|
|
227
248
|
const event = LIFECYCLE_EVENTS[t.phase];
|
|
228
249
|
if (event) {
|
|
250
|
+
// For resumed events, show rejection feedback if available
|
|
251
|
+
if (t.phase === 'run:resumed' && rejections.length > 0) {
|
|
252
|
+
const feedback = rejections[resumedIdx];
|
|
253
|
+
resumedIdx++;
|
|
254
|
+
if (feedback?.message) {
|
|
255
|
+
const maxLen = 60;
|
|
256
|
+
const msg = feedback.message.length > maxLen
|
|
257
|
+
? `${feedback.message.slice(0, maxLen)}…`
|
|
258
|
+
: feedback.message;
|
|
259
|
+
lines.push(` ${colors.error(`↩ rejected: "${msg}"`)}`);
|
|
260
|
+
continue;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
229
263
|
const sym = t.phase === 'run:completed'
|
|
230
264
|
? symbols.success
|
|
231
265
|
: t.phase === 'run:failed' || t.phase === 'run:crashed'
|
|
@@ -292,7 +326,8 @@ export function createShowCommand() {
|
|
|
292
326
|
});
|
|
293
327
|
}
|
|
294
328
|
if (timings.length > 0) {
|
|
295
|
-
const
|
|
329
|
+
const rejections = loadRejectionFeedback(feature.specPath);
|
|
330
|
+
const lines = renderPhaseTimings(timings, run, rejections);
|
|
296
331
|
textBlocks.push({ title: 'Phase Timing', content: lines.join('\n') });
|
|
297
332
|
}
|
|
298
333
|
if (run?.status === 'waiting_approval') {
|
|
@@ -20,7 +20,7 @@ export declare function createAgentSelectConfig(): {
|
|
|
20
20
|
}, {
|
|
21
21
|
readonly name: "Gemini CLI";
|
|
22
22
|
readonly value: AgentType.GeminiCli;
|
|
23
|
-
readonly
|
|
23
|
+
readonly description: "Google Gemini CLI";
|
|
24
24
|
}, {
|
|
25
25
|
readonly name: "Aider";
|
|
26
26
|
readonly value: AgentType.Aider;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PRD Review Question Prompt Configuration
|
|
3
|
+
*
|
|
4
|
+
* Creates an @inquirer/select config for reviewing a single open question
|
|
5
|
+
* from the PRD spec.yaml. Users select from the available options.
|
|
6
|
+
*/
|
|
7
|
+
import type { QuestionOption } from '../../../../packages/core/src/domain/generated/output.js';
|
|
8
|
+
/**
|
|
9
|
+
* Creates the @inquirer/select configuration for a single open question.
|
|
10
|
+
*/
|
|
11
|
+
export declare function createQuestionSelectConfig(question: string, options: QuestionOption[], currentAnswer?: string): {
|
|
12
|
+
message: string;
|
|
13
|
+
choices: {
|
|
14
|
+
name: string;
|
|
15
|
+
value: string;
|
|
16
|
+
description: string;
|
|
17
|
+
}[];
|
|
18
|
+
default: string | undefined;
|
|
19
|
+
theme: {
|
|
20
|
+
readonly prefix: {
|
|
21
|
+
readonly idle: string;
|
|
22
|
+
readonly done: string;
|
|
23
|
+
};
|
|
24
|
+
readonly style: {
|
|
25
|
+
readonly highlight: import("picocolors/types.js").Formatter;
|
|
26
|
+
readonly answer: import("picocolors/types.js").Formatter;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=prd-review-question.prompt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prd-review-question.prompt.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/tui/prompts/prd-review-question.prompt.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAEnE;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,cAAc,EAAE,EACzB,aAAa,CAAC,EAAE,MAAM;;;;;;;;;;;;;;;;;;EAcvB"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PRD Review Question Prompt Configuration
|
|
3
|
+
*
|
|
4
|
+
* Creates an @inquirer/select config for reviewing a single open question
|
|
5
|
+
* from the PRD spec.yaml. Users select from the available options.
|
|
6
|
+
*/
|
|
7
|
+
import { shepTheme } from '../themes/shep.theme.js';
|
|
8
|
+
/**
|
|
9
|
+
* Creates the @inquirer/select configuration for a single open question.
|
|
10
|
+
*/
|
|
11
|
+
export function createQuestionSelectConfig(question, options, currentAnswer) {
|
|
12
|
+
const choices = options.map((opt) => ({
|
|
13
|
+
name: opt.option,
|
|
14
|
+
value: opt.option,
|
|
15
|
+
description: opt.description,
|
|
16
|
+
}));
|
|
17
|
+
return {
|
|
18
|
+
message: question,
|
|
19
|
+
choices,
|
|
20
|
+
default: currentAnswer,
|
|
21
|
+
theme: shepTheme,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PRD Review Summary Prompt Configuration
|
|
3
|
+
*
|
|
4
|
+
* Creates an @inquirer/select config for the final approve/reject
|
|
5
|
+
* action after reviewing open questions.
|
|
6
|
+
*/
|
|
7
|
+
export type ReviewAction = 'approve' | 'reject';
|
|
8
|
+
/**
|
|
9
|
+
* Creates the @inquirer/select configuration for the review action prompt.
|
|
10
|
+
*/
|
|
11
|
+
export declare function createReviewActionConfig(changeCount: number): {
|
|
12
|
+
message: string;
|
|
13
|
+
choices: {
|
|
14
|
+
name: string;
|
|
15
|
+
value: ReviewAction;
|
|
16
|
+
description: string;
|
|
17
|
+
}[];
|
|
18
|
+
theme: {
|
|
19
|
+
readonly prefix: {
|
|
20
|
+
readonly idle: string;
|
|
21
|
+
readonly done: string;
|
|
22
|
+
};
|
|
23
|
+
readonly style: {
|
|
24
|
+
readonly highlight: import("picocolors/types.js").Formatter;
|
|
25
|
+
readonly answer: import("picocolors/types.js").Formatter;
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=prd-review-summary.prompt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prd-review-summary.prompt.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/tui/prompts/prd-review-summary.prompt.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEhD;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,MAAM;;;;eAShC,YAAY;;;;;;;;;;;;;EAWvC"}
|