ripp-cli 1.0.1 → 1.2.1
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/CHANGELOG.md +35 -0
- package/index.js +138 -8
- package/lib/build.js +116 -10
- package/lib/checklist-parser.js +224 -0
- package/lib/config.js +2 -3
- package/lib/confirmation.js +77 -6
- package/lib/doctor.js +370 -0
- package/lib/metrics.js +410 -0
- package/lib/packager.js +26 -14
- package/package.json +10 -3
- package/schema/evidence-pack.schema.json +201 -0
- package/schema/intent-candidates.schema.json +109 -0
- package/schema/intent-confirmed.schema.json +85 -0
- package/schema/ripp-1.0.schema.json +543 -0
- package/schema/ripp-config.schema.json +104 -0
package/lib/confirmation.js
CHANGED
|
@@ -53,23 +53,69 @@ async function interactiveConfirm(cwd, candidates) {
|
|
|
53
53
|
const candidate = candidates.candidates[i];
|
|
54
54
|
|
|
55
55
|
console.log(`\n--- Candidate ${i + 1}/${candidates.candidates.length} ---`);
|
|
56
|
-
|
|
56
|
+
const sectionName = candidate.purpose?.problem ? 'purpose' : 'full-packet';
|
|
57
|
+
console.log(`Section: ${sectionName}`);
|
|
57
58
|
console.log(`Confidence: ${(candidate.confidence * 100).toFixed(1)}%`);
|
|
58
59
|
console.log(`Evidence: ${candidate.evidence.length} reference(s)`);
|
|
59
60
|
console.log('\nContent:');
|
|
60
|
-
|
|
61
|
+
// Build content object from candidate fields
|
|
62
|
+
const content = {};
|
|
63
|
+
const contentFields = [
|
|
64
|
+
'purpose',
|
|
65
|
+
'ux_flow',
|
|
66
|
+
'data_contracts',
|
|
67
|
+
'api_contracts',
|
|
68
|
+
'permissions',
|
|
69
|
+
'failure_modes',
|
|
70
|
+
'audit_events',
|
|
71
|
+
'nfrs',
|
|
72
|
+
'acceptance_tests',
|
|
73
|
+
'design_philosophy',
|
|
74
|
+
'design_decisions',
|
|
75
|
+
'constraints',
|
|
76
|
+
'success_criteria'
|
|
77
|
+
];
|
|
78
|
+
contentFields.forEach(field => {
|
|
79
|
+
if (candidate[field]) {
|
|
80
|
+
content[field] = candidate[field];
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
console.log(yaml.dump(content, { indent: 2 }));
|
|
61
84
|
|
|
62
85
|
const answer = await question(rl, '\nAccept this candidate? (y/n/e to edit/s to skip): ');
|
|
63
86
|
|
|
64
87
|
if (answer.toLowerCase() === 'y') {
|
|
88
|
+
// Build content object from candidate fields
|
|
89
|
+
const content = {};
|
|
90
|
+
const contentFields = [
|
|
91
|
+
'purpose',
|
|
92
|
+
'ux_flow',
|
|
93
|
+
'data_contracts',
|
|
94
|
+
'api_contracts',
|
|
95
|
+
'permissions',
|
|
96
|
+
'failure_modes',
|
|
97
|
+
'audit_events',
|
|
98
|
+
'nfrs',
|
|
99
|
+
'acceptance_tests',
|
|
100
|
+
'design_philosophy',
|
|
101
|
+
'design_decisions',
|
|
102
|
+
'constraints',
|
|
103
|
+
'success_criteria'
|
|
104
|
+
];
|
|
105
|
+
contentFields.forEach(field => {
|
|
106
|
+
if (candidate[field]) {
|
|
107
|
+
content[field] = candidate[field];
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
|
|
65
111
|
confirmed.push({
|
|
66
|
-
section: candidate.
|
|
112
|
+
section: candidate.purpose?.problem ? 'purpose' : 'full-packet',
|
|
67
113
|
source: 'confirmed',
|
|
68
114
|
confirmed_at: new Date().toISOString(),
|
|
69
115
|
confirmed_by: options.user || 'unknown',
|
|
70
116
|
original_confidence: candidate.confidence,
|
|
71
117
|
evidence: candidate.evidence,
|
|
72
|
-
content:
|
|
118
|
+
content: content
|
|
73
119
|
});
|
|
74
120
|
console.log('✓ Accepted');
|
|
75
121
|
} else if (answer.toLowerCase() === 'e') {
|
|
@@ -136,7 +182,10 @@ async function generateChecklistConfirm(cwd, candidates) {
|
|
|
136
182
|
markdown += '---\n\n';
|
|
137
183
|
|
|
138
184
|
candidates.candidates.forEach((candidate, index) => {
|
|
139
|
-
|
|
185
|
+
// Extract section name from purpose or use generic identifier
|
|
186
|
+
const sectionName = candidate.purpose?.problem ? 'purpose' : 'full-packet';
|
|
187
|
+
|
|
188
|
+
markdown += `## Candidate ${index + 1}: ${sectionName}\n\n`;
|
|
140
189
|
markdown += `- **Confidence**: ${(candidate.confidence * 100).toFixed(1)}%\n`;
|
|
141
190
|
markdown += `- **Evidence**: ${candidate.evidence.length} reference(s)\n\n`;
|
|
142
191
|
|
|
@@ -145,7 +194,29 @@ async function generateChecklistConfirm(cwd, candidates) {
|
|
|
145
194
|
|
|
146
195
|
markdown += '### Content\n\n';
|
|
147
196
|
markdown += '```yaml\n';
|
|
148
|
-
|
|
197
|
+
// Build content object from candidate fields (purpose, ux_flow, data_contracts, etc.)
|
|
198
|
+
const content = {};
|
|
199
|
+
const contentFields = [
|
|
200
|
+
'purpose',
|
|
201
|
+
'ux_flow',
|
|
202
|
+
'data_contracts',
|
|
203
|
+
'api_contracts',
|
|
204
|
+
'permissions',
|
|
205
|
+
'failure_modes',
|
|
206
|
+
'audit_events',
|
|
207
|
+
'nfrs',
|
|
208
|
+
'acceptance_tests',
|
|
209
|
+
'design_philosophy',
|
|
210
|
+
'design_decisions',
|
|
211
|
+
'constraints',
|
|
212
|
+
'success_criteria'
|
|
213
|
+
];
|
|
214
|
+
contentFields.forEach(field => {
|
|
215
|
+
if (candidate[field]) {
|
|
216
|
+
content[field] = candidate[field];
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
markdown += yaml.dump(content, { indent: 2 });
|
|
149
220
|
markdown += '```\n\n';
|
|
150
221
|
|
|
151
222
|
markdown += '### Evidence References\n\n';
|
package/lib/doctor.js
ADDED
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RIPP Doctor - Health Check and Diagnostics
|
|
3
|
+
*
|
|
4
|
+
* Checks repository health and provides actionable fix-it commands
|
|
5
|
+
* for common RIPP setup issues.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const { execSync } = require('child_process');
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Run all health checks
|
|
14
|
+
* @param {string} cwd - Current working directory
|
|
15
|
+
* @returns {Object} Health check results
|
|
16
|
+
*/
|
|
17
|
+
function runHealthChecks(cwd = process.cwd()) {
|
|
18
|
+
const checks = {
|
|
19
|
+
nodeVersion: checkNodeVersion(),
|
|
20
|
+
gitRepository: checkGitRepository(cwd),
|
|
21
|
+
rippDirectory: checkRippDirectory(cwd),
|
|
22
|
+
configFile: checkConfigFile(cwd),
|
|
23
|
+
evidencePack: checkEvidencePack(cwd),
|
|
24
|
+
candidates: checkCandidates(cwd),
|
|
25
|
+
confirmedIntent: checkConfirmedIntent(cwd),
|
|
26
|
+
schema: checkSchema(),
|
|
27
|
+
cliVersion: checkCliVersion()
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
// Calculate overall health
|
|
31
|
+
const total = Object.keys(checks).length;
|
|
32
|
+
const passed = Object.values(checks).filter(c => c.status === 'pass').length;
|
|
33
|
+
const warnings = Object.values(checks).filter(c => c.status === 'warning').length;
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
checks,
|
|
37
|
+
summary: {
|
|
38
|
+
total,
|
|
39
|
+
passed,
|
|
40
|
+
warnings,
|
|
41
|
+
failed: total - passed - warnings,
|
|
42
|
+
healthy: passed === total
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Check Node.js version (>= 20.0.0)
|
|
49
|
+
*/
|
|
50
|
+
function checkNodeVersion() {
|
|
51
|
+
const version = process.version;
|
|
52
|
+
const major = parseInt(version.slice(1).split('.')[0]);
|
|
53
|
+
|
|
54
|
+
if (major >= 20) {
|
|
55
|
+
return {
|
|
56
|
+
status: 'pass',
|
|
57
|
+
message: `Node.js ${version}`,
|
|
58
|
+
fix: null
|
|
59
|
+
};
|
|
60
|
+
} else {
|
|
61
|
+
return {
|
|
62
|
+
status: 'fail',
|
|
63
|
+
message: `Node.js ${version} is too old`,
|
|
64
|
+
fix: 'Install Node.js 20 or later: https://nodejs.org/',
|
|
65
|
+
docs: 'https://dylan-natter.github.io/ripp-protocol/getting-started.html#prerequisites'
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Check if current directory is a Git repository
|
|
72
|
+
*/
|
|
73
|
+
function checkGitRepository(cwd) {
|
|
74
|
+
try {
|
|
75
|
+
const gitDir = path.join(cwd, '.git');
|
|
76
|
+
if (fs.existsSync(gitDir)) {
|
|
77
|
+
return {
|
|
78
|
+
status: 'pass',
|
|
79
|
+
message: 'Git repository detected',
|
|
80
|
+
fix: null
|
|
81
|
+
};
|
|
82
|
+
} else {
|
|
83
|
+
return {
|
|
84
|
+
status: 'fail',
|
|
85
|
+
message: 'Not a Git repository',
|
|
86
|
+
fix: 'Initialize Git: git init',
|
|
87
|
+
docs: 'https://git-scm.com/docs/git-init'
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
} catch (error) {
|
|
91
|
+
return {
|
|
92
|
+
status: 'fail',
|
|
93
|
+
message: 'Unable to check Git repository',
|
|
94
|
+
fix: 'Ensure you are in a valid directory',
|
|
95
|
+
docs: null
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Check if .ripp directory exists
|
|
102
|
+
*/
|
|
103
|
+
function checkRippDirectory(cwd) {
|
|
104
|
+
const rippDir = path.join(cwd, '.ripp');
|
|
105
|
+
if (fs.existsSync(rippDir) && fs.statSync(rippDir).isDirectory()) {
|
|
106
|
+
return {
|
|
107
|
+
status: 'pass',
|
|
108
|
+
message: '.ripp directory exists',
|
|
109
|
+
fix: null
|
|
110
|
+
};
|
|
111
|
+
} else {
|
|
112
|
+
return {
|
|
113
|
+
status: 'fail',
|
|
114
|
+
message: '.ripp directory not found',
|
|
115
|
+
fix: 'Initialize RIPP: ripp init',
|
|
116
|
+
docs: 'https://dylan-natter.github.io/ripp-protocol/getting-started.html'
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Check if config.yaml exists
|
|
123
|
+
*/
|
|
124
|
+
function checkConfigFile(cwd) {
|
|
125
|
+
const configPath = path.join(cwd, '.ripp', 'config.yaml');
|
|
126
|
+
if (fs.existsSync(configPath)) {
|
|
127
|
+
return {
|
|
128
|
+
status: 'pass',
|
|
129
|
+
message: 'config.yaml present',
|
|
130
|
+
fix: null
|
|
131
|
+
};
|
|
132
|
+
} else {
|
|
133
|
+
return {
|
|
134
|
+
status: 'warning',
|
|
135
|
+
message: 'config.yaml not found (using defaults)',
|
|
136
|
+
fix: 'Initialize RIPP: ripp init',
|
|
137
|
+
docs: 'https://dylan-natter.github.io/ripp-protocol/getting-started.html'
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Check if evidence pack exists
|
|
144
|
+
*/
|
|
145
|
+
function checkEvidencePack(cwd) {
|
|
146
|
+
const evidenceIndex = path.join(cwd, '.ripp', 'evidence', 'index.yaml');
|
|
147
|
+
if (fs.existsSync(evidenceIndex)) {
|
|
148
|
+
return {
|
|
149
|
+
status: 'pass',
|
|
150
|
+
message: 'Evidence pack built',
|
|
151
|
+
fix: null
|
|
152
|
+
};
|
|
153
|
+
} else {
|
|
154
|
+
return {
|
|
155
|
+
status: 'warning',
|
|
156
|
+
message: 'Evidence pack not built',
|
|
157
|
+
fix: 'Build evidence: ripp evidence build',
|
|
158
|
+
docs: 'https://dylan-natter.github.io/ripp-protocol/getting-started.html#step-2-build-evidence'
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Check if candidates exist (discovery has run)
|
|
165
|
+
*/
|
|
166
|
+
function checkCandidates(cwd) {
|
|
167
|
+
const candidatesDir = path.join(cwd, '.ripp', 'candidates');
|
|
168
|
+
if (fs.existsSync(candidatesDir)) {
|
|
169
|
+
const files = fs.readdirSync(candidatesDir);
|
|
170
|
+
const yamlFiles = files.filter(f => f.endsWith('.yaml') || f.endsWith('.yml'));
|
|
171
|
+
|
|
172
|
+
if (yamlFiles.length > 0) {
|
|
173
|
+
return {
|
|
174
|
+
status: 'pass',
|
|
175
|
+
message: `${yamlFiles.length} candidate(s) found`,
|
|
176
|
+
fix: null
|
|
177
|
+
};
|
|
178
|
+
} else {
|
|
179
|
+
return {
|
|
180
|
+
status: 'warning',
|
|
181
|
+
message: 'No candidate files in candidates directory',
|
|
182
|
+
fix: 'Run discovery: ripp discover (requires AI enabled)',
|
|
183
|
+
docs: 'https://dylan-natter.github.io/ripp-protocol/getting-started.html#step-3-discover-intent'
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
} else {
|
|
187
|
+
return {
|
|
188
|
+
status: 'warning',
|
|
189
|
+
message: 'Discovery not run',
|
|
190
|
+
fix: 'Run discovery: ripp discover (requires AI enabled)',
|
|
191
|
+
docs: 'https://dylan-natter.github.io/ripp-protocol/getting-started.html#step-3-discover-intent'
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Check if confirmed intent exists
|
|
198
|
+
*/
|
|
199
|
+
function checkConfirmedIntent(cwd) {
|
|
200
|
+
const intentPath = path.join(cwd, '.ripp', 'intent.confirmed.yaml');
|
|
201
|
+
if (fs.existsSync(intentPath)) {
|
|
202
|
+
return {
|
|
203
|
+
status: 'pass',
|
|
204
|
+
message: 'Intent confirmed',
|
|
205
|
+
fix: null
|
|
206
|
+
};
|
|
207
|
+
} else {
|
|
208
|
+
return {
|
|
209
|
+
status: 'warning',
|
|
210
|
+
message: 'Intent not confirmed',
|
|
211
|
+
fix: 'Confirm intent: ripp confirm --checklist (then ripp build --from-checklist)',
|
|
212
|
+
docs: 'https://dylan-natter.github.io/ripp-protocol/getting-started.html#step-4-confirm-intent'
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Check if RIPP schema is accessible
|
|
219
|
+
*/
|
|
220
|
+
function checkSchema() {
|
|
221
|
+
try {
|
|
222
|
+
// First check bundled schema (always available when CLI is installed)
|
|
223
|
+
const bundledSchemaPath = path.join(__dirname, '../schema', 'ripp-1.0.schema.json');
|
|
224
|
+
if (fs.existsSync(bundledSchemaPath)) {
|
|
225
|
+
return {
|
|
226
|
+
status: 'pass',
|
|
227
|
+
message: 'RIPP schema accessible',
|
|
228
|
+
fix: null
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Fallback: check if we're in project root (for development)
|
|
233
|
+
const projectRoot = path.resolve(__dirname, '../../..');
|
|
234
|
+
const schemaPath = path.join(projectRoot, 'schema', 'ripp-1.0.schema.json');
|
|
235
|
+
if (fs.existsSync(schemaPath)) {
|
|
236
|
+
return {
|
|
237
|
+
status: 'pass',
|
|
238
|
+
message: 'RIPP schema accessible',
|
|
239
|
+
fix: null
|
|
240
|
+
};
|
|
241
|
+
} else {
|
|
242
|
+
return {
|
|
243
|
+
status: 'warning',
|
|
244
|
+
message: 'RIPP schema not found locally',
|
|
245
|
+
fix: 'Schema will be loaded from repository when needed',
|
|
246
|
+
docs: 'https://dylan-natter.github.io/ripp-protocol/schema/ripp-1.0.schema.json'
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
} catch (error) {
|
|
250
|
+
return {
|
|
251
|
+
status: 'warning',
|
|
252
|
+
message: 'Unable to check schema',
|
|
253
|
+
fix: null,
|
|
254
|
+
docs: null
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Check CLI version
|
|
261
|
+
*/
|
|
262
|
+
function checkCliVersion() {
|
|
263
|
+
try {
|
|
264
|
+
const pkg = require('../package.json');
|
|
265
|
+
return {
|
|
266
|
+
status: 'pass',
|
|
267
|
+
message: `ripp-cli v${pkg.version}`,
|
|
268
|
+
fix: null
|
|
269
|
+
};
|
|
270
|
+
} catch (error) {
|
|
271
|
+
return {
|
|
272
|
+
status: 'warning',
|
|
273
|
+
message: 'Unable to determine CLI version',
|
|
274
|
+
fix: null,
|
|
275
|
+
docs: null
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Format health check results as text
|
|
282
|
+
*/
|
|
283
|
+
function formatHealthCheckText(results) {
|
|
284
|
+
const { checks, summary } = results;
|
|
285
|
+
|
|
286
|
+
let output = '\n';
|
|
287
|
+
output += '🔍 RIPP Health Check\n';
|
|
288
|
+
output += '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n';
|
|
289
|
+
|
|
290
|
+
// Overall summary
|
|
291
|
+
if (summary.healthy) {
|
|
292
|
+
output += '✅ All checks passed!\n\n';
|
|
293
|
+
} else {
|
|
294
|
+
output += `📊 Summary: ${summary.passed}/${summary.total} checks passed`;
|
|
295
|
+
if (summary.warnings > 0) {
|
|
296
|
+
output += `, ${summary.warnings} warnings`;
|
|
297
|
+
}
|
|
298
|
+
if (summary.failed > 0) {
|
|
299
|
+
output += `, ${summary.failed} failed`;
|
|
300
|
+
}
|
|
301
|
+
output += '\n\n';
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// Individual checks
|
|
305
|
+
for (const [name, check] of Object.entries(checks)) {
|
|
306
|
+
const icon = check.status === 'pass' ? '✓' : check.status === 'warning' ? '⚠' : '✗';
|
|
307
|
+
const statusColor = check.status === 'pass' ? '' : check.status === 'warning' ? '⚠ ' : '✗ ';
|
|
308
|
+
|
|
309
|
+
output += `${icon} ${formatCheckName(name)}: ${check.message}\n`;
|
|
310
|
+
|
|
311
|
+
if (check.fix) {
|
|
312
|
+
output += ` → Fix: ${check.fix}\n`;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
if (check.docs) {
|
|
316
|
+
output += ` → Docs: ${check.docs}\n`;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
output += '\n';
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// Next steps
|
|
323
|
+
if (!summary.healthy) {
|
|
324
|
+
output += '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n';
|
|
325
|
+
output += '💡 Next Steps:\n\n';
|
|
326
|
+
|
|
327
|
+
const failedChecks = Object.entries(checks)
|
|
328
|
+
.filter(([_, check]) => check.status === 'fail')
|
|
329
|
+
.map(([_, check]) => check.fix)
|
|
330
|
+
.filter(fix => fix !== null);
|
|
331
|
+
|
|
332
|
+
if (failedChecks.length > 0) {
|
|
333
|
+
failedChecks.forEach((fix, idx) => {
|
|
334
|
+
output += ` ${idx + 1}. ${fix}\n`;
|
|
335
|
+
});
|
|
336
|
+
} else {
|
|
337
|
+
output += ' All critical checks passed. Address warnings to improve workflow.\n';
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
output += '\n';
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
output += '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n';
|
|
344
|
+
output += 'For more help: https://dylan-natter.github.io/ripp-protocol/getting-started.html\n';
|
|
345
|
+
|
|
346
|
+
return output;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Format check name for display
|
|
351
|
+
*/
|
|
352
|
+
function formatCheckName(name) {
|
|
353
|
+
const names = {
|
|
354
|
+
nodeVersion: 'Node.js Version',
|
|
355
|
+
gitRepository: 'Git Repository',
|
|
356
|
+
rippDirectory: 'RIPP Directory',
|
|
357
|
+
configFile: 'Configuration',
|
|
358
|
+
evidencePack: 'Evidence Pack',
|
|
359
|
+
candidates: 'Intent Candidates',
|
|
360
|
+
confirmedIntent: 'Confirmed Intent',
|
|
361
|
+
schema: 'RIPP Schema',
|
|
362
|
+
cliVersion: 'CLI Version'
|
|
363
|
+
};
|
|
364
|
+
return names[name] || name;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
module.exports = {
|
|
368
|
+
runHealthChecks,
|
|
369
|
+
formatHealthCheckText
|
|
370
|
+
};
|