vibecodingmachine-core 2025.12.25-25 → 2026.1.3-2209
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/ERROR_REPORTING_API.md +212 -0
- package/ERROR_REPORTING_USAGE.md +380 -0
- package/__tests__/utils/git-branch-manager.test.js +61 -0
- package/package.json +1 -1
- package/src/beta-request.js +160 -0
- package/src/database/user-database-client.js +64 -0
- package/src/database/user-schema.js +21 -0
- package/src/ide-integration/applescript-manager.cjs +26 -6
- package/src/ide-integration/applescript-manager.js +6 -5
- package/src/ide-integration/applescript-utils.js +26 -18
- package/src/index.cjs +4 -0
- package/src/index.js +4 -0
- package/src/localization/translations/en.js +2 -0
- package/src/localization/translations/es.js +2 -0
- package/src/requirement-numbering.js +164 -0
- package/src/sync/aws-setup.js +4 -4
- package/src/utils/error-reporter.js +109 -0
- package/src/utils/git-branch-manager.js +278 -0
- package/src/utils/requirement-helpers.js +10 -1
- package/src/utils/requirements-parser.js +25 -0
package/src/sync/aws-setup.js
CHANGED
|
@@ -116,12 +116,12 @@ async function setupCognitoWithGoogle() {
|
|
|
116
116
|
|
|
117
117
|
// Add Google OAuth provider if not already configured
|
|
118
118
|
try {
|
|
119
|
-
const googleClientId = process.env.
|
|
119
|
+
const googleClientId = process.env.REACT_APP_GOOGLE_CLIENT_ID;
|
|
120
120
|
const googleClientSecret = process.env.GOOGLE_CLIENT_SECRET;
|
|
121
121
|
|
|
122
122
|
if (!googleClientId || !googleClientSecret) {
|
|
123
123
|
console.log('⚠ Google OAuth credentials not provided. Skipping Google provider setup.');
|
|
124
|
-
console.log(' Set
|
|
124
|
+
console.log(' Set REACT_APP_GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET environment variables.');
|
|
125
125
|
return { userPoolId: existingPoolId, status: 'existing' };
|
|
126
126
|
}
|
|
127
127
|
|
|
@@ -198,7 +198,7 @@ async function setupCognitoWithGoogle() {
|
|
|
198
198
|
console.log(`✓ Created Cognito User Pool: ${userPoolId}`);
|
|
199
199
|
|
|
200
200
|
// Add Google OAuth provider first (if credentials provided)
|
|
201
|
-
const googleClientId = process.env.
|
|
201
|
+
const googleClientId = process.env.REACT_APP_GOOGLE_CLIENT_ID;
|
|
202
202
|
const googleClientSecret = process.env.GOOGLE_CLIENT_SECRET;
|
|
203
203
|
|
|
204
204
|
let supportedProviders = ['COGNITO'];
|
|
@@ -231,7 +231,7 @@ async function setupCognitoWithGoogle() {
|
|
|
231
231
|
}
|
|
232
232
|
} else {
|
|
233
233
|
console.log('⚠ Google OAuth credentials not provided');
|
|
234
|
-
console.log(' Set
|
|
234
|
+
console.log(' Set REACT_APP_GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET to enable Google login');
|
|
235
235
|
}
|
|
236
236
|
|
|
237
237
|
// Create app client
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global Error Reporter for VibeCodingMachine
|
|
3
|
+
*
|
|
4
|
+
* Automatically reports errors to the admin database for tracking and fixing.
|
|
5
|
+
* This helps the admin know about issues and use VibeCodingMachine to fix itself.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const UserDatabase = require('../database/user-schema');
|
|
9
|
+
|
|
10
|
+
class ErrorReporter {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.db = new UserDatabase();
|
|
13
|
+
this.enabled = true;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Set authentication token for error reporting
|
|
18
|
+
*/
|
|
19
|
+
setAuthToken(token) {
|
|
20
|
+
this.db.setAuthToken(token);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Enable or disable error reporting
|
|
25
|
+
*/
|
|
26
|
+
setEnabled(enabled) {
|
|
27
|
+
this.enabled = enabled;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Report an error to the admin database
|
|
32
|
+
*/
|
|
33
|
+
async reportError(error, context = {}) {
|
|
34
|
+
if (!this.enabled) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
try {
|
|
39
|
+
const errorData = {
|
|
40
|
+
message: error.message || String(error),
|
|
41
|
+
stack: error.stack || '',
|
|
42
|
+
name: error.name || 'Error',
|
|
43
|
+
code: error.code || '',
|
|
44
|
+
context: {
|
|
45
|
+
...context,
|
|
46
|
+
cwd: process.cwd(),
|
|
47
|
+
argv: process.argv.slice(2).filter(arg =>
|
|
48
|
+
!arg.includes('password') &&
|
|
49
|
+
!arg.includes('token') &&
|
|
50
|
+
!arg.includes('secret')
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
await this.db.reportError(errorData);
|
|
56
|
+
return true;
|
|
57
|
+
} catch (reportError) {
|
|
58
|
+
// Silently fail - don't block the application
|
|
59
|
+
console.warn('Failed to report error:', reportError.message);
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Wrap a function to automatically report errors
|
|
66
|
+
*/
|
|
67
|
+
wrapFunction(fn, context = {}) {
|
|
68
|
+
return async (...args) => {
|
|
69
|
+
try {
|
|
70
|
+
return await fn(...args);
|
|
71
|
+
} catch (error) {
|
|
72
|
+
await this.reportError(error, {
|
|
73
|
+
...context,
|
|
74
|
+
functionName: fn.name,
|
|
75
|
+
args: args.filter(arg =>
|
|
76
|
+
typeof arg !== 'object' ||
|
|
77
|
+
!JSON.stringify(arg).match(/password|token|secret/i)
|
|
78
|
+
)
|
|
79
|
+
});
|
|
80
|
+
throw error;
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Create a global error handler for uncaught exceptions
|
|
87
|
+
*/
|
|
88
|
+
setupGlobalHandlers() {
|
|
89
|
+
process.on('uncaughtException', async (error) => {
|
|
90
|
+
await this.reportError(error, {
|
|
91
|
+
type: 'uncaughtException'
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
process.on('unhandledRejection', async (error) => {
|
|
96
|
+
await this.reportError(error, {
|
|
97
|
+
type: 'unhandledRejection'
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Singleton instance
|
|
104
|
+
const errorReporter = new ErrorReporter();
|
|
105
|
+
|
|
106
|
+
module.exports = {
|
|
107
|
+
ErrorReporter,
|
|
108
|
+
errorReporter
|
|
109
|
+
};
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
const { execSync } = require('child_process');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const { createBranchName, extractRequirementNumber } = require('../requirement-numbering');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Check if a directory is a git repository
|
|
7
|
+
* @param {string} repoPath - Path to check
|
|
8
|
+
* @returns {boolean} True if it's a git repo
|
|
9
|
+
*/
|
|
10
|
+
function isGitRepo(repoPath) {
|
|
11
|
+
try {
|
|
12
|
+
execSync('git rev-parse --git-dir', {
|
|
13
|
+
cwd: repoPath,
|
|
14
|
+
stdio: 'ignore'
|
|
15
|
+
});
|
|
16
|
+
return true;
|
|
17
|
+
} catch (error) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Get current git branch name
|
|
24
|
+
* @param {string} repoPath - Path to repository
|
|
25
|
+
* @returns {string|null} Current branch name or null
|
|
26
|
+
*/
|
|
27
|
+
function getCurrentBranch(repoPath) {
|
|
28
|
+
try {
|
|
29
|
+
const branch = execSync('git rev-parse --abbrev-ref HEAD', {
|
|
30
|
+
cwd: repoPath,
|
|
31
|
+
encoding: 'utf8'
|
|
32
|
+
}).trim();
|
|
33
|
+
return branch;
|
|
34
|
+
} catch (error) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Create a feature branch for a requirement
|
|
41
|
+
* @param {string} repoPath - Path to repository
|
|
42
|
+
* @param {string} requirementTitle - Full requirement title (e.g., "R1: Email System")
|
|
43
|
+
* @returns {Promise<{success: boolean, branchName: string|null, parentBranch: string|null, error: string|null}>}
|
|
44
|
+
*/
|
|
45
|
+
async function createRequirementBranch(repoPath, requirementTitle) {
|
|
46
|
+
try {
|
|
47
|
+
if (!isGitRepo(repoPath)) {
|
|
48
|
+
return {
|
|
49
|
+
success: false,
|
|
50
|
+
branchName: null,
|
|
51
|
+
parentBranch: null,
|
|
52
|
+
error: 'Not a git repository'
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Extract requirement number from title
|
|
57
|
+
const reqNumber = extractRequirementNumber(requirementTitle);
|
|
58
|
+
if (!reqNumber) {
|
|
59
|
+
return {
|
|
60
|
+
success: false,
|
|
61
|
+
branchName: null,
|
|
62
|
+
parentBranch: null,
|
|
63
|
+
error: 'Requirement number not found in title'
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Get parent branch (current branch before creating new one)
|
|
68
|
+
const parentBranch = getCurrentBranch(repoPath);
|
|
69
|
+
if (!parentBranch) {
|
|
70
|
+
return {
|
|
71
|
+
success: false,
|
|
72
|
+
branchName: null,
|
|
73
|
+
parentBranch: null,
|
|
74
|
+
error: 'Could not determine current branch'
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Create branch name
|
|
79
|
+
const branchName = createBranchName(reqNumber, requirementTitle);
|
|
80
|
+
|
|
81
|
+
// Check if branch already exists
|
|
82
|
+
try {
|
|
83
|
+
execSync(`git rev-parse --verify ${branchName}`, {
|
|
84
|
+
cwd: repoPath,
|
|
85
|
+
stdio: 'ignore'
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// Branch exists, check it out
|
|
89
|
+
execSync(`git checkout ${branchName}`, {
|
|
90
|
+
cwd: repoPath,
|
|
91
|
+
stdio: 'ignore'
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
return {
|
|
95
|
+
success: true,
|
|
96
|
+
branchName,
|
|
97
|
+
parentBranch,
|
|
98
|
+
error: null,
|
|
99
|
+
alreadyExists: true
|
|
100
|
+
};
|
|
101
|
+
} catch (error) {
|
|
102
|
+
// Branch doesn't exist, create it
|
|
103
|
+
execSync(`git checkout -b ${branchName}`, {
|
|
104
|
+
cwd: repoPath,
|
|
105
|
+
stdio: 'ignore'
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
return {
|
|
109
|
+
success: true,
|
|
110
|
+
branchName,
|
|
111
|
+
parentBranch,
|
|
112
|
+
error: null,
|
|
113
|
+
alreadyExists: false
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
} catch (error) {
|
|
117
|
+
return {
|
|
118
|
+
success: false,
|
|
119
|
+
branchName: null,
|
|
120
|
+
parentBranch: null,
|
|
121
|
+
error: error.message
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Merge a requirement branch back to parent and delete it
|
|
128
|
+
* @param {string} repoPath - Path to repository
|
|
129
|
+
* @param {string} requirementTitle - Full requirement title
|
|
130
|
+
* @param {string} parentBranch - Parent branch to merge into
|
|
131
|
+
* @returns {Promise<{success: boolean, error: string|null}>}
|
|
132
|
+
*/
|
|
133
|
+
async function mergeRequirementBranch(repoPath, requirementTitle, parentBranch = 'main') {
|
|
134
|
+
try {
|
|
135
|
+
if (!isGitRepo(repoPath)) {
|
|
136
|
+
return { success: false, error: 'Not a git repository' };
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Extract requirement number
|
|
140
|
+
const reqNumber = extractRequirementNumber(requirementTitle);
|
|
141
|
+
if (!reqNumber) {
|
|
142
|
+
return { success: false, error: 'Requirement number not found in title' };
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Create branch name
|
|
146
|
+
const branchName = createBranchName(reqNumber, requirementTitle);
|
|
147
|
+
|
|
148
|
+
// Checkout parent branch
|
|
149
|
+
execSync(`git checkout ${parentBranch}`, {
|
|
150
|
+
cwd: repoPath,
|
|
151
|
+
stdio: 'ignore'
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
// Merge the feature branch
|
|
155
|
+
execSync(`git merge --no-ff ${branchName} -m "Merge ${branchName}"`, {
|
|
156
|
+
cwd: repoPath,
|
|
157
|
+
stdio: 'ignore'
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
// Delete the feature branch
|
|
161
|
+
execSync(`git branch -d ${branchName}`, {
|
|
162
|
+
cwd: repoPath,
|
|
163
|
+
stdio: 'ignore'
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
return { success: true, error: null };
|
|
167
|
+
} catch (error) {
|
|
168
|
+
return { success: false, error: error.message };
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Remove a feature by reverting its merge commit
|
|
174
|
+
* @param {string} repoPath - Path to repository
|
|
175
|
+
* @param {string} requirementTitle - Full requirement title
|
|
176
|
+
* @returns {Promise<{success: boolean, error: string|null}>}
|
|
177
|
+
*/
|
|
178
|
+
async function removeRequirementFeature(repoPath, requirementTitle) {
|
|
179
|
+
try {
|
|
180
|
+
if (!isGitRepo(repoPath)) {
|
|
181
|
+
return { success: false, error: 'Not a git repository' };
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Extract requirement number
|
|
185
|
+
const reqNumber = extractRequirementNumber(requirementTitle);
|
|
186
|
+
if (!reqNumber) {
|
|
187
|
+
return { success: false, error: 'Requirement number not found in title' };
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Create branch name to search for
|
|
191
|
+
const branchName = createBranchName(reqNumber, requirementTitle);
|
|
192
|
+
|
|
193
|
+
// Find the merge commit for this branch
|
|
194
|
+
const mergeCommit = execSync(
|
|
195
|
+
`git log --grep="Merge ${branchName}" --oneline --format="%H" -1`,
|
|
196
|
+
{
|
|
197
|
+
cwd: repoPath,
|
|
198
|
+
encoding: 'utf8'
|
|
199
|
+
}
|
|
200
|
+
).trim();
|
|
201
|
+
|
|
202
|
+
if (!mergeCommit) {
|
|
203
|
+
return { success: false, error: 'Merge commit not found for this requirement' };
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Revert the merge commit
|
|
207
|
+
execSync(`git revert -m 1 ${mergeCommit} --no-edit`, {
|
|
208
|
+
cwd: repoPath,
|
|
209
|
+
stdio: 'ignore'
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
return { success: true, error: null };
|
|
213
|
+
} catch (error) {
|
|
214
|
+
return { success: false, error: error.message };
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Get list of all requirement branches
|
|
220
|
+
* @param {string} repoPath - Path to repository
|
|
221
|
+
* @returns {Array<{branchName: string, reqNumber: number}>}
|
|
222
|
+
*/
|
|
223
|
+
function listRequirementBranches(repoPath) {
|
|
224
|
+
try {
|
|
225
|
+
if (!isGitRepo(repoPath)) {
|
|
226
|
+
return [];
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const branches = execSync('git branch --list "R*"', {
|
|
230
|
+
cwd: repoPath,
|
|
231
|
+
encoding: 'utf8'
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
return branches
|
|
235
|
+
.split('\n')
|
|
236
|
+
.map(b => b.trim().replace(/^\*\s*/, ''))
|
|
237
|
+
.filter(b => b && b.startsWith('R'))
|
|
238
|
+
.map(b => {
|
|
239
|
+
const match = b.match(/^R(\d+)/);
|
|
240
|
+
return {
|
|
241
|
+
branchName: b,
|
|
242
|
+
reqNumber: match ? parseInt(match[1], 10) : 0
|
|
243
|
+
};
|
|
244
|
+
})
|
|
245
|
+
.filter(b => b.reqNumber > 0)
|
|
246
|
+
.sort((a, b) => a.reqNumber - b.reqNumber);
|
|
247
|
+
} catch (error) {
|
|
248
|
+
return [];
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Check if there are any uncommitted changes in the repository
|
|
254
|
+
* @param {string} repoPath - Path to repository
|
|
255
|
+
* @returns {boolean} True if there are uncommitted changes
|
|
256
|
+
*/
|
|
257
|
+
function hasUncommittedChanges(repoPath) {
|
|
258
|
+
try {
|
|
259
|
+
// Check for staged and unstaged changes
|
|
260
|
+
const status = execSync('git status --porcelain', {
|
|
261
|
+
cwd: repoPath,
|
|
262
|
+
encoding: 'utf8'
|
|
263
|
+
}).trim();
|
|
264
|
+
return status.length > 0;
|
|
265
|
+
} catch (error) {
|
|
266
|
+
return false;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
module.exports = {
|
|
271
|
+
isGitRepo,
|
|
272
|
+
getCurrentBranch,
|
|
273
|
+
hasUncommittedChanges,
|
|
274
|
+
createRequirementBranch,
|
|
275
|
+
mergeRequirementBranch,
|
|
276
|
+
removeRequirementFeature,
|
|
277
|
+
listRequirementBranches
|
|
278
|
+
};
|
|
@@ -514,8 +514,17 @@ async function loadVerifiedFromChangelog(repoPath) {
|
|
|
514
514
|
for (const line of lines) {
|
|
515
515
|
const trimmed = line.trim();
|
|
516
516
|
|
|
517
|
+
if (trimmed.includes('## Verified Requirements')) {
|
|
518
|
+
inVerifiedSection = true;
|
|
519
|
+
continue;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
if (inVerifiedSection && trimmed.startsWith('##') && !trimmed.includes('Verified Requirements')) {
|
|
523
|
+
break;
|
|
524
|
+
}
|
|
525
|
+
|
|
517
526
|
// Collect items starting with "- " as verified requirements
|
|
518
|
-
if (trimmed.startsWith('- ') && trimmed.length > 5) {
|
|
527
|
+
if (inVerifiedSection && trimmed.startsWith('- ') && trimmed.length > 5) {
|
|
519
528
|
let reqText = trimmed.substring(2);
|
|
520
529
|
// Extract title part (before timestamp in parentheses if present)
|
|
521
530
|
const titleMatch = reqText.match(/^(.+?)\s*\([\d-]+\)$/);
|
|
@@ -112,9 +112,11 @@ function parseRequirementsFile(content) {
|
|
|
112
112
|
}
|
|
113
113
|
|
|
114
114
|
const details = [];
|
|
115
|
+
const questions = [];
|
|
115
116
|
let package = null;
|
|
116
117
|
let options = null;
|
|
117
118
|
let optionsType = null;
|
|
119
|
+
let currentQuestion = null;
|
|
118
120
|
|
|
119
121
|
// Read package, description, and options
|
|
120
122
|
for (let j = i + 1; j < lines.length; j++) {
|
|
@@ -140,18 +142,41 @@ function parseRequirementsFile(content) {
|
|
|
140
142
|
options = [optionsText];
|
|
141
143
|
}
|
|
142
144
|
}
|
|
145
|
+
// Check for QUESTIONS line (pipe-separated)
|
|
146
|
+
else if (nextLine.startsWith('QUESTIONS:')) {
|
|
147
|
+
const questionsText = nextLine.replace(/^QUESTIONS:\s*/, '').trim();
|
|
148
|
+
const parsedQuestions = questionsText.split('|').map(q => q.trim()).filter(Boolean);
|
|
149
|
+
for (const q of parsedQuestions) {
|
|
150
|
+
questions.push({ question: q, response: null });
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
// Parse numbered questions/responses in needInformation section (CLI-style)
|
|
154
|
+
else if (currentSection === 'needInformation' && nextLine.match(/^\d+\./)) {
|
|
155
|
+
if (currentQuestion) {
|
|
156
|
+
questions.push(currentQuestion);
|
|
157
|
+
}
|
|
158
|
+
currentQuestion = { question: nextLine, response: null };
|
|
159
|
+
}
|
|
160
|
+
else if (currentSection === 'needInformation' && currentQuestion && nextLine.startsWith('Response:')) {
|
|
161
|
+
currentQuestion.response = nextLine.replace(/^Response:\s*/, '').trim();
|
|
162
|
+
}
|
|
143
163
|
// Description line (include all lines including empty ones to preserve formatting)
|
|
144
164
|
else if (nextLine !== undefined) {
|
|
145
165
|
details.push(nextLine);
|
|
146
166
|
}
|
|
147
167
|
}
|
|
148
168
|
|
|
169
|
+
if (currentQuestion) {
|
|
170
|
+
questions.push(currentQuestion);
|
|
171
|
+
}
|
|
172
|
+
|
|
149
173
|
const requirement = {
|
|
150
174
|
title,
|
|
151
175
|
description: details.join('\n'),
|
|
152
176
|
package,
|
|
153
177
|
options,
|
|
154
178
|
optionsType,
|
|
179
|
+
questions: currentSection === 'needInformation' ? questions : undefined,
|
|
155
180
|
lineIndex: i
|
|
156
181
|
};
|
|
157
182
|
|