projscan 4.3.0 → 4.3.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/README.md +72 -23
- package/dist/cli/commands/missionProof.js +421 -3
- package/dist/cli/commands/missionProof.js.map +1 -1
- package/dist/core/missionProof.js +2 -33
- package/dist/core/missionProof.js.map +1 -1
- package/dist/core/missionProofBaseline.d.ts +10 -0
- package/dist/core/missionProofBaseline.js +131 -0
- package/dist/core/missionProofBaseline.js.map +1 -0
- package/dist/core/missionProofMarkdown.d.ts +2 -0
- package/dist/core/missionProofMarkdown.js +80 -0
- package/dist/core/missionProofMarkdown.js.map +1 -0
- package/dist/core/missionProofSummary.d.ts +2 -0
- package/dist/core/missionProofSummary.js +16 -0
- package/dist/core/missionProofSummary.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/projscan-sbom.cdx.json +6 -6
- package/dist/tool-manifest.json +2 -2
- package/dist/utils/formatSupport.d.ts +1 -1
- package/dist/utils/formatSupport.js +1 -1
- package/dist/utils/formatSupport.js.map +1 -1
- package/docs/GUIDE.md +23 -1
- package/docs/demos/projscan-mission-control.tape +13 -0
- package/docs/demos/projscan-mission-proof.tape +25 -0
- package/docs/projscan-mission-control.gif +0 -0
- package/docs/projscan-mission-proof.gif +0 -0
- package/package.json +8 -1
- package/scripts/capture-vhs-demos.mjs +80 -0
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
export const MISSION_PROOF_BASELINE_STATUSES = [
|
|
4
|
+
'passed',
|
|
5
|
+
'failed',
|
|
6
|
+
'running',
|
|
7
|
+
'not_run',
|
|
8
|
+
'unknown',
|
|
9
|
+
];
|
|
10
|
+
const BASELINE_NUMERIC_FIELDS = ['failedGates', 'reruns', 'minutesSpent', 'reviewerApprovals'];
|
|
11
|
+
export async function loadMissionProofBaseline(rootPath, baselineFile) {
|
|
12
|
+
const resolved = path.resolve(rootPath, baselineFile);
|
|
13
|
+
const input = parseMissionProofBaselineInput(await readMissionProofBaselineFile(resolved, baselineFile), baselineFile);
|
|
14
|
+
const runs = validateMissionProofBaselineRuns(input, baselineFile);
|
|
15
|
+
const totals = totalsFromBaselineRuns(runs);
|
|
16
|
+
return {
|
|
17
|
+
path: path.relative(rootPath, resolved) || resolved,
|
|
18
|
+
runs,
|
|
19
|
+
totals,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export function missionProofBaselineTemplate() {
|
|
23
|
+
return {
|
|
24
|
+
schemaVersion: 1,
|
|
25
|
+
runs: [],
|
|
26
|
+
exampleRun: {
|
|
27
|
+
id: 'manual-before-mission-control',
|
|
28
|
+
status: 'passed',
|
|
29
|
+
minutesSpent: 30,
|
|
30
|
+
reruns: 1,
|
|
31
|
+
failedGates: 0,
|
|
32
|
+
reviewerApprovals: 1,
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
export function parseMissionProofBaselineInput(raw, baselineFile) {
|
|
37
|
+
let parsed;
|
|
38
|
+
try {
|
|
39
|
+
parsed = JSON.parse(raw);
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
throw new Error(`Mission proof baseline file is not valid JSON: ${baselineFile}\n` +
|
|
43
|
+
'Expected shape: {"schemaVersion":1,"runs":[...]}', { cause: err });
|
|
44
|
+
}
|
|
45
|
+
if (!parsed || typeof parsed !== 'object') {
|
|
46
|
+
throw baselineValidationError(baselineFile, 'root', 'expected an object.');
|
|
47
|
+
}
|
|
48
|
+
return parsed;
|
|
49
|
+
}
|
|
50
|
+
export function validateMissionProofBaselineRuns(input, baselineFile) {
|
|
51
|
+
if (typeof input.runs === 'undefined')
|
|
52
|
+
return [];
|
|
53
|
+
if (!Array.isArray(input.runs)) {
|
|
54
|
+
throw baselineValidationError(baselineFile, 'runs', 'expected an array.');
|
|
55
|
+
}
|
|
56
|
+
const runs = input.runs.map((run, index) => validateMissionProofBaselineRun(run, index, baselineFile));
|
|
57
|
+
validateUniqueBaselineRunIds(runs, baselineFile);
|
|
58
|
+
return runs;
|
|
59
|
+
}
|
|
60
|
+
function validateMissionProofBaselineRun(run, index, baselineFile) {
|
|
61
|
+
if (!run || typeof run !== 'object') {
|
|
62
|
+
throw baselineValidationError(baselineFile, `runs[${index}]`, 'expected an object.');
|
|
63
|
+
}
|
|
64
|
+
const candidate = run;
|
|
65
|
+
if (typeof candidate.id !== 'string' || candidate.id.trim().length === 0) {
|
|
66
|
+
throw baselineValidationError(baselineFile, `runs[${index}].id`, 'expected a non-empty string.');
|
|
67
|
+
}
|
|
68
|
+
if (!MISSION_PROOF_BASELINE_STATUSES.includes(candidate.status)) {
|
|
69
|
+
throw baselineValidationError(baselineFile, `runs[${index}].status`, 'expected passed, failed, running, not_run, or unknown.');
|
|
70
|
+
}
|
|
71
|
+
for (const field of BASELINE_NUMERIC_FIELDS) {
|
|
72
|
+
const value = candidate[field];
|
|
73
|
+
if (typeof value !== 'undefined' && (typeof value !== 'number' || !Number.isFinite(value) || value < 0)) {
|
|
74
|
+
throw baselineValidationError(baselineFile, `runs[${index}].${field}`, 'expected a non-negative number.');
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return candidate;
|
|
78
|
+
}
|
|
79
|
+
function validateUniqueBaselineRunIds(runs, baselineFile) {
|
|
80
|
+
const seen = new Set();
|
|
81
|
+
for (const [index, run] of runs.entries()) {
|
|
82
|
+
if (seen.has(run.id)) {
|
|
83
|
+
throw baselineValidationError(baselineFile, `runs[${index}].id`, `duplicate id ${run.id}.`);
|
|
84
|
+
}
|
|
85
|
+
seen.add(run.id);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function totalsFromBaselineRuns(runs) {
|
|
89
|
+
const passed = runs.filter((run) => run.status === 'passed').length;
|
|
90
|
+
return {
|
|
91
|
+
missions: runs.length,
|
|
92
|
+
passed,
|
|
93
|
+
failed: runs.filter((run) => run.status === 'failed').length,
|
|
94
|
+
running: runs.filter((run) => run.status === 'running').length,
|
|
95
|
+
notRun: runs.filter((run) => run.status === 'not_run').length,
|
|
96
|
+
unavailable: runs.filter((run) => run.status === 'unknown').length,
|
|
97
|
+
proofCompletionRate: runs.length > 0 ? round(passed / runs.length) : 0,
|
|
98
|
+
reruns: sum(runs.map((run) => run.reruns)),
|
|
99
|
+
failedGates: sum(runs.map((run) => run.failedGates)),
|
|
100
|
+
reviewerApprovals: sum(runs.map((run) => run.reviewerApprovals)),
|
|
101
|
+
minutesSpent: sum(runs.map((run) => run.minutesSpent)),
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
function sum(values) {
|
|
105
|
+
return values.reduce((total, value) => total + (typeof value === 'number' && Number.isFinite(value) ? value : 0), 0);
|
|
106
|
+
}
|
|
107
|
+
async function readMissionProofBaselineFile(resolved, baselineFile) {
|
|
108
|
+
try {
|
|
109
|
+
return await fs.readFile(resolved, 'utf8');
|
|
110
|
+
}
|
|
111
|
+
catch (err) {
|
|
112
|
+
if (isNodeError(err) && err.code === 'ENOENT') {
|
|
113
|
+
throw new Error(`Mission proof baseline file not found: ${baselineFile}\n` +
|
|
114
|
+
`Create one with: projscan mission-proof --init-baseline ${shellToken(baselineFile)}`, { cause: err });
|
|
115
|
+
}
|
|
116
|
+
throw err;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function baselineValidationError(baselineFile, pathLabel, message) {
|
|
120
|
+
return new Error(`Mission proof baseline invalid at ${pathLabel}: ${message}\nFile: ${baselineFile}`);
|
|
121
|
+
}
|
|
122
|
+
function shellToken(value) {
|
|
123
|
+
return /^[A-Za-z0-9_./:-]+$/.test(value) ? value : JSON.stringify(value);
|
|
124
|
+
}
|
|
125
|
+
function isNodeError(value) {
|
|
126
|
+
return value instanceof Error && 'code' in value;
|
|
127
|
+
}
|
|
128
|
+
function round(value) {
|
|
129
|
+
return Math.round(value * 100) / 100;
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=missionProofBaseline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"missionProofBaseline.js","sourceRoot":"","sources":["../../src/core/missionProofBaseline.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
export function renderMissionProofMarkdown(report) {
|
|
2
|
+
const totals = report.missionControl.totals;
|
|
3
|
+
const lines = [
|
|
4
|
+
'# Mission Proof Report',
|
|
5
|
+
'',
|
|
6
|
+
'## Summary',
|
|
7
|
+
`- Mission bundles: ${totals.missions}`,
|
|
8
|
+
`- Passed: ${totals.passed}`,
|
|
9
|
+
`- Failed: ${totals.failed}`,
|
|
10
|
+
`- Running: ${totals.running}`,
|
|
11
|
+
`- Not run: ${totals.notRun}`,
|
|
12
|
+
`- Unavailable: ${totals.unavailable}`,
|
|
13
|
+
`- Proof completion: ${formatPercent(totals.proofCompletionRate)}`,
|
|
14
|
+
`- Reruns: ${totals.reruns}`,
|
|
15
|
+
`- Failed gates: ${totals.failedGates}`,
|
|
16
|
+
`- Reviewer approvals: ${totals.reviewerApprovals}`,
|
|
17
|
+
'',
|
|
18
|
+
report.summary,
|
|
19
|
+
'',
|
|
20
|
+
'## Mission Outcomes',
|
|
21
|
+
'',
|
|
22
|
+
];
|
|
23
|
+
for (const outcome of report.missionControl.missions) {
|
|
24
|
+
lines.push(...renderMissionOutcome(outcome));
|
|
25
|
+
}
|
|
26
|
+
if (report.baseline && report.comparison) {
|
|
27
|
+
lines.push(...renderBaselineComparison(report.baseline.path, report.baseline.totals, report.comparison));
|
|
28
|
+
}
|
|
29
|
+
lines.push('## Risk Avoided', '');
|
|
30
|
+
for (const item of report.riskAvoided) {
|
|
31
|
+
lines.push(`- ${item}`);
|
|
32
|
+
}
|
|
33
|
+
lines.push('', '## Next Actions', '');
|
|
34
|
+
for (const action of report.nextActions) {
|
|
35
|
+
lines.push(`- ${action.label}`);
|
|
36
|
+
if (action.command) {
|
|
37
|
+
lines.push('', '```bash', action.command, '```', '');
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return lines.join('\n').replace(/\n{3,}/g, '\n\n').trimEnd() + '\n';
|
|
41
|
+
}
|
|
42
|
+
function renderMissionOutcome(outcome) {
|
|
43
|
+
const lines = [
|
|
44
|
+
`### ${outcome.missionDir}`,
|
|
45
|
+
'',
|
|
46
|
+
`- Status: ${outcome.status}`,
|
|
47
|
+
`- Commands: ${outcome.proof.completedCommands} completed, ${outcome.proof.failedCommands} failed, ${outcome.proof.reruns} reruns`,
|
|
48
|
+
`- Version candidate: ${outcome.versionCandidate.recommendation}`,
|
|
49
|
+
`- Changed: ${joinEvidence(outcome.whatChanged)}`,
|
|
50
|
+
`- Remains: ${joinEvidence(outcome.whatRemains)}`,
|
|
51
|
+
];
|
|
52
|
+
if (!outcome.available && outcome.reason) {
|
|
53
|
+
lines.push(`- Reason: ${outcome.reason}`);
|
|
54
|
+
}
|
|
55
|
+
if (outcome.review.decisions.length > 0) {
|
|
56
|
+
lines.push(`- Reviewer decisions: ${outcome.review.decisions.map((decision) => decision.decision).join(', ')}`);
|
|
57
|
+
}
|
|
58
|
+
lines.push('');
|
|
59
|
+
return lines;
|
|
60
|
+
}
|
|
61
|
+
function renderBaselineComparison(baselinePath, baselineTotals, comparison) {
|
|
62
|
+
return [
|
|
63
|
+
'## Baseline Comparison',
|
|
64
|
+
'',
|
|
65
|
+
`- Baseline: ${baselinePath}`,
|
|
66
|
+
`- Baseline runs: ${baselineTotals.missions}`,
|
|
67
|
+
`- Completion delta: ${comparison.completionRateDelta}`,
|
|
68
|
+
`- Reruns avoided: ${comparison.rerunsAvoided}`,
|
|
69
|
+
`- Failed gates avoided: ${comparison.failedGatesAvoided}`,
|
|
70
|
+
`- Minutes saved: ${comparison.minutesSaved}`,
|
|
71
|
+
'',
|
|
72
|
+
];
|
|
73
|
+
}
|
|
74
|
+
function joinEvidence(values) {
|
|
75
|
+
return values.length > 0 ? values.join('; ') : 'None recorded.';
|
|
76
|
+
}
|
|
77
|
+
function formatPercent(value) {
|
|
78
|
+
return `${Math.round(value * 100)}%`;
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=missionProofMarkdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"missionProofMarkdown.js","sourceRoot":"","sources":["../../src/core/missionProofMarkdown.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export function renderMissionProofSummary(report) {
|
|
2
|
+
const totals = report.missionControl.totals;
|
|
3
|
+
const status = totals.missions > 0 && totals.passed === totals.missions ? 'PASS' : 'FAIL';
|
|
4
|
+
return `Mission proof: ${status} (${summarizeTotals(totals)}).`;
|
|
5
|
+
}
|
|
6
|
+
function summarizeTotals(totals) {
|
|
7
|
+
const details = [
|
|
8
|
+
`${totals.passed} of ${totals.missions} passed`,
|
|
9
|
+
totals.failed > 0 ? `${totals.failed} failed` : undefined,
|
|
10
|
+
totals.running > 0 ? `${totals.running} running` : undefined,
|
|
11
|
+
totals.notRun > 0 ? `${totals.notRun} not run` : undefined,
|
|
12
|
+
totals.unavailable > 0 ? `${totals.unavailable} unavailable` : undefined,
|
|
13
|
+
].filter(Boolean);
|
|
14
|
+
return details.join('; ');
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=missionProofSummary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"missionProofSummary.js","sourceRoot":"","sources":["../../src/core/missionProofSummary.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,yBAAyB,CAAC,MAA0B;IAClE,MAAM,MAAM,GAAG,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC;IAC5C,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,GAAG,CAAC,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;IAC1F,OAAO,kBAAkB,MAAM,KAAK,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC;AAClE,CAAC;AAED,SAAS,eAAe,CAAC,MAA0B;IACjD,MAAM,OAAO,GAAG;QACd,GAAG,MAAM,CAAC,MAAM,OAAO,MAAM,CAAC,QAAQ,SAAS;QAC/C,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,SAAS,CAAC,CAAC,CAAC,SAAS;QACzD,MAAM,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,OAAO,UAAU,CAAC,CAAC,CAAC,SAAS;QAC5D,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,UAAU,CAAC,CAAC,CAAC,SAAS;QAC1D,MAAM,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,WAAW,cAAc,CAAC,CAAC,CAAC,SAAS;KACzE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAClB,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC5B,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -44,6 +44,9 @@ export { computeQualityScorecard } from './core/qualityScorecard.js';
|
|
|
44
44
|
export { computeStartReport } from './core/start.js';
|
|
45
45
|
export { loadMissionOutcome } from './core/missionOutcome.js';
|
|
46
46
|
export { computeMissionProofReport } from './core/missionProof.js';
|
|
47
|
+
export { loadMissionProofBaseline, missionProofBaselineTemplate, validateMissionProofBaselineRuns, } from './core/missionProofBaseline.js';
|
|
48
|
+
export { renderMissionProofMarkdown } from './core/missionProofMarkdown.js';
|
|
49
|
+
export { renderMissionProofSummary } from './core/missionProofSummary.js';
|
|
47
50
|
export { computeDogfoodReport } from './core/dogfood.js';
|
|
48
51
|
export { computeTrialReport } from './core/trial.js';
|
|
49
52
|
export { addFeedbackResponse, createFeedbackTemplate, readFeedbackFile, summarizeFeedback, summarizeFeedbackFile } from './core/feedback.js';
|
package/dist/index.js
CHANGED
|
@@ -42,6 +42,9 @@ export { computeQualityScorecard } from './core/qualityScorecard.js';
|
|
|
42
42
|
export { computeStartReport } from './core/start.js';
|
|
43
43
|
export { loadMissionOutcome } from './core/missionOutcome.js';
|
|
44
44
|
export { computeMissionProofReport } from './core/missionProof.js';
|
|
45
|
+
export { loadMissionProofBaseline, missionProofBaselineTemplate, validateMissionProofBaselineRuns, } from './core/missionProofBaseline.js';
|
|
46
|
+
export { renderMissionProofMarkdown } from './core/missionProofMarkdown.js';
|
|
47
|
+
export { renderMissionProofSummary } from './core/missionProofSummary.js';
|
|
45
48
|
export { computeDogfoodReport } from './core/dogfood.js';
|
|
46
49
|
export { computeTrialReport } from './core/trial.js';
|
|
47
50
|
export { addFeedbackResponse, createFeedbackTemplate, readFeedbackFile, summarizeFeedback, summarizeFeedbackFile } from './core/feedback.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"bomFormat": "CycloneDX",
|
|
3
3
|
"specVersion": "1.5",
|
|
4
|
-
"serialNumber": "urn:uuid:
|
|
4
|
+
"serialNumber": "urn:uuid:8393c87a-7b85-472f-8c74-9c1188baddb9",
|
|
5
5
|
"version": 1,
|
|
6
6
|
"metadata": {
|
|
7
|
-
"timestamp": "2026-06-
|
|
7
|
+
"timestamp": "2026-06-10T13:12:08.406Z",
|
|
8
8
|
"tools": [
|
|
9
9
|
{
|
|
10
10
|
"vendor": "projscan",
|
|
11
11
|
"name": "projscan-sbom-generator",
|
|
12
|
-
"version": "4.3.
|
|
12
|
+
"version": "4.3.1"
|
|
13
13
|
}
|
|
14
14
|
],
|
|
15
15
|
"component": {
|
|
16
16
|
"type": "application",
|
|
17
|
-
"bom-ref": "pkg:npm/projscan@4.3.
|
|
17
|
+
"bom-ref": "pkg:npm/projscan@4.3.1",
|
|
18
18
|
"name": "projscan",
|
|
19
|
-
"version": "4.3.
|
|
20
|
-
"purl": "pkg:npm/projscan@4.3.
|
|
19
|
+
"version": "4.3.1",
|
|
20
|
+
"purl": "pkg:npm/projscan@4.3.1"
|
|
21
21
|
}
|
|
22
22
|
},
|
|
23
23
|
"components": [
|
package/dist/tool-manifest.json
CHANGED
|
@@ -47,7 +47,7 @@ export declare const COMMAND_FORMAT_SUPPORT: {
|
|
|
47
47
|
readonly 'init team': readonly ["console", "json"];
|
|
48
48
|
readonly 'install-hook': readonly ["console"];
|
|
49
49
|
readonly mcp: readonly ["console"];
|
|
50
|
-
readonly 'mission-proof': readonly ["console", "json"];
|
|
50
|
+
readonly 'mission-proof': readonly ["console", "json", "markdown"];
|
|
51
51
|
readonly 'mcp doctor': readonly ["console", "json"];
|
|
52
52
|
readonly memory: readonly ["console", "json"];
|
|
53
53
|
readonly 'memory stable': readonly ["console", "json"];
|
|
@@ -46,7 +46,7 @@ export const COMMAND_FORMAT_SUPPORT = {
|
|
|
46
46
|
'init team': ['console', 'json'],
|
|
47
47
|
'install-hook': ['console'],
|
|
48
48
|
mcp: ['console'],
|
|
49
|
-
'mission-proof': ['console', 'json'],
|
|
49
|
+
'mission-proof': ['console', 'json', 'markdown'],
|
|
50
50
|
'mcp doctor': ['console', 'json'],
|
|
51
51
|
memory: ['console', 'json'],
|
|
52
52
|
'memory stable': ['console', 'json'],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"formatSupport.js","sourceRoot":"","sources":["../../src/utils/formatSupport.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"formatSupport.js","sourceRoot":"","sources":["../../src/utils/formatSupport.ts"],"names":[],"mappings":"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"}
|
package/docs/GUIDE.md
CHANGED
|
@@ -81,6 +81,7 @@ npx projscan
|
|
|
81
81
|
- Node.js >= 18
|
|
82
82
|
- npm, yarn, or pnpm
|
|
83
83
|
- Git (optional - unlocks `hotspots` and `--changed-only`)
|
|
84
|
+
- VHS (optional - regenerates checked-in terminal demos with `npm run docs:demos`)
|
|
84
85
|
|
|
85
86
|
---
|
|
86
87
|
|
|
@@ -207,7 +208,28 @@ When the agent first opens a repo, or before starting a refactor, the question i
|
|
|
207
208
|
|
|
208
209
|
**Typical agent flow:** start with `projscan privacy-check`, then `projscan_start` with an optional plain-language intent. If no explicit mode is supplied, start infers the workflow mode from the intent, such as `before_commit` for commit-safety checks; read `modeSource` and `modeReason` to see whether the mode was explicit, inferred, or defaulted. `modeReason` distinguishes workflow-mode defaulting from action routing, so an impact intent can still route through Mission Control while the workflow stays `before_edit`. The `firstTenMinutes` path and current-worktree coordination hint follow that resolved mode, so a commit-safety start does not send the developer back through a before-edit gate. Follow `missionControl.actionPlan`, call `missionControl.readyActions` immediately, use `missionControl.executionPlan.currentPhase` as the cursor-aligned phase pointer, and use `missionControl.executionPlan.cursor.tool` / `args` when the cursor is directly MCP-callable. Use routed-intent weighted `confidence`, `score`, and `matchedKeywords` to judge weak or ambiguous matches, and read the same confidence line in console output when working manually. Fill any `missionControl.unresolvedInputs` before running placeholder follow-ups, inspect `missionControl.alternatives` when the intent mixes goals, stop only when `missionControl.successCriteria` is satisfied, and hand off with `missionControl.handoff`, `missionControl.runbook`, or the concise `missionControl.handoffPrompt`. Use `missionControl.reviewGate` as the autonomous-work stop boundary: finish the current checklist and proof, capture `git status --short` and `git diff --stat`, then wait for approval before another slice, release, publish, or deploy. Read `missionControl.reviewGate.worktree` for current worktree availability, changed-file count, base ref, and visible changed files. Use `missionControl.reviewGate.proof` when the reviewer needs the remaining proof queue without reading the full resume object. Read `missionControl.reviewGate.doneWhen` for the success criteria the reviewer must confirm before approving more work. Read `missionControl.reviewGate.policy` before continuing from a review handoff; it lists the actions blocked until explicit reviewer approval: another slice, release, publish, deploy, push, merge, and version bump. Use `projscan start --review-gate-json --intent "<goal>"` or saved `review-gate.json` when a script needs proof, worktree evidence, done criteria, decisions, and policy in one review object. Use `projscan start --review-policy --intent "<goal>"` or saved `review-policy.json` when a script only needs that approval boundary. Use `missionControl.reviewGate.decisions` as the approval menu in review gates, task cards, and runbooks; each decision includes copyable reviewer reply text so agents do not infer permission to continue, release, or publish. The default console review gate, saved mission bundle README, concise handoff prompt, `--review-replies`, and saved `review-replies.txt` show those replies for first-open review. `missionControl.handoff.reviewGate`, `--handoff-json`, and saved `handoff.json` carry that same gate for transfer-only flows. The handoff prompt starts with `missionControl.resume.prompt`, so it carries the current cursor, runnable command or blocked input instruction, labeled unlocks or blockers, done criteria, ready proof, review stop condition, and reviewer replies in one copyable sentence; the normal console prints that same value as `Handoff Prompt` without requiring JSON or `--include-handoff`, `projscan start --handoff-prompt --intent "<goal>"` prints only that prompt for piping or copy/paste, and the Markdown runbook renders it as `## Handoff Prompt` so copied runbooks carry the same next-agent prompt. When a human just needs the runnable shell step, `projscan start --next-command --intent "<goal>"` prints only the current cursor command; when an MCP agent needs the callable equivalent, `projscan start --next-tool-call --intent "<goal>"` prints the current cursor tool call as compact JSON. Cite `missionControl.proofSummary` plus the runnable-only `missionControl.proofCommands` in broad handoff notes, and use `missionControl.handoff.readyProof.items` when resuming because it is the complete ordered remaining-proof queue; each item carries its CLI command and an optional MCP `toolCall`. `missionControl.handoff.readyProof.commands` and `toolCalls` remain convenient command-only and MCP-callable views. MCP agents should use `missionControl.resume.toolCall` when present, use `missionControl.resume.inputBindings` to map unlocked placeholders to input steps, then call `missionControl.resume.followUps` as the next template calls; when they need one ordered sequence, follow `missionControl.resume.checklist`, whose `run_proof` rows include `tool` and `args` for MCP-callable proof steps. The normal console `Resume Checklist` and Markdown runbook checklist print callable rows inline as `(MCP: ...)` and mark unmapped proof rows as `(CLI only)`, so a copied runbook or default terminal run remains self-contained even outside the JSON payload. After the current action, prefer `missionControl.resume.remainingProofItems` for complete proof, using `remainingProofToolCalls` for the callable MCP subset without rerunning the current command. Humans can run the matching `command`; the normal console `Ready Proof` command list, normal console `Proof Queue`, and runbook `Proof queue` all use remaining proof so the current cursor command is not repeated, and each queued item shows either its MCP call or `CLI only`. Use `projscan_understand` and `projscan_preflight` when you need broader context or a safety gate. Use `projscan_workplan` when you need an ordered execution plan, `projscan_agent_brief` for a compact handoff, and `projscan_evidence_pack --pr-comment` when you need reviewer-facing proof. Deeper tools such as `doctor`, `hotspots`, `dataflow`, `review`, `bug-hunt`, `quality-scorecard`, `dogfood`, and `trial` are follow-up tools.
|
|
209
210
|
|
|
210
|
-
For shortcut discovery, `projscan start --shortcuts --intent "<goal>"` prints the copyable command menu for the current mission, and `projscan start --shortcuts-json --intent "<goal>"` prints the same menu as JSON for agents and scripts. For shell copy/paste, `projscan start --mission-script --intent "<goal>"` prints a POSIX script that runs the current cursor command, then the remaining proof queue, then prints the review evidence commands. For MCP queue copy/paste, `projscan start --ready-tool-calls --intent "<goal>"` prints the current cursor call followed by remaining MCP-callable proof as compact JSON. For structured resume handoff, `projscan start --resume-json --intent "<goal>"` prints only `missionControl.resume`. For the complete transfer object, `projscan start --handoff-json --intent "<goal>"` prints only `missionControl.handoff`. For a file bundle, `projscan start --save-mission .projscan/mission --intent "<goal>"` writes `README.md`, `next-command.txt`, `next-tool-call.json`, `handoff-prompt.txt`, `resume-prompt.txt`, `task-card.md`, `review-gate.md`, `review-gate.json`, `review-policy.json`, `review-replies.txt`, the runbook, handoff JSON, resume JSON, `ready-tool-calls.json`, `shortcuts.json`, `mission.sh`, `status.sh`, `proof-logs/README.md`, `proof-logs/status.jsonl`, `proof-logs/run-report.md`, `proof-logs/summary.json`, proof commands, and manifest. Saved `mission.sh` writes current-command and proof-command output under `proof-logs/`, appends exit-code rows to `status.jsonl`, refreshes `run-report.md`, and writes `summary.json`, so reviewers and wrappers can scan pass/fail proof before opening raw logs. Bundle `status.sh` reads `summary.json` and uses exit codes `0`, `1`, and `2` for passed, failed, and not-ready states. For verification-only copy/paste, `projscan start --proof-commands --intent "<goal>"` prints the remaining ready proof commands one per line without the rest of the start report. For an ordered checklist without the full report, `projscan start --checklist --intent "<goal>"` prints only the resume checklist rows. For paste-ready PR, issue, or handoff notes, `projscan start --task-card --intent "<goal>"` prints the Markdown task card. MCP agents can read `missionControl.taskCard.markdown` when they need the same checklist without rendering it from `resume.checklist`. For stop-and-review notes, `projscan start --review-gate --intent "<goal>"` prints only `missionControl.reviewGate.markdown`, `projscan start --review-gate-json --intent "<goal>"` prints only the review gate JSON, `projscan start --review-policy --intent "<goal>"` prints only the review policy JSON, and `projscan start --review-replies --intent "<goal>"` prints only the copyable reviewer replies. For a full Markdown artifact, `projscan start --runbook --intent "<goal>"` prints the mission runbook.
|
|
211
|
+
For shortcut discovery, `projscan start --shortcuts --intent "<goal>"` prints the copyable command menu for the current mission, and `projscan start --shortcuts-json --intent "<goal>"` prints the same menu as JSON for agents and scripts. For shell copy/paste, `projscan start --mission-script --intent "<goal>"` prints a POSIX script that runs the current cursor command, then the remaining proof queue, then prints the review evidence commands. For MCP queue copy/paste, `projscan start --ready-tool-calls --intent "<goal>"` prints the current cursor call followed by remaining MCP-callable proof as compact JSON. For structured resume handoff, `projscan start --resume-json --intent "<goal>"` prints only `missionControl.resume`. For the complete transfer object, `projscan start --handoff-json --intent "<goal>"` prints only `missionControl.handoff`. For a file bundle, `projscan start --save-mission .projscan/mission --intent "<goal>"` writes `README.md`, `next-command.txt`, `next-tool-call.json`, `handoff-prompt.txt`, `resume-prompt.txt`, `task-card.md`, `review-gate.md`, `review-gate.json`, `review-policy.json`, `review-replies.txt`, the runbook, handoff JSON, resume JSON, `ready-tool-calls.json`, `shortcuts.json`, `mission.sh`, `status.sh`, `proof-logs/README.md`, `proof-logs/status.jsonl`, `proof-logs/run-report.md`, `proof-logs/summary.json`, proof commands, and manifest. Saved `mission.sh` writes current-command and proof-command output under `proof-logs/`, appends exit-code rows to `status.jsonl`, refreshes `run-report.md`, and writes `summary.json`, so reviewers and wrappers can scan pass/fail proof before opening raw logs. Bundle `status.sh` reads `summary.json` and uses exit codes `0`, `1`, and `2` for passed, failed, and not-ready states. For verification-only copy/paste, `projscan start --proof-commands --intent "<goal>"` prints the remaining ready proof commands one per line without the rest of the start report. For an ordered checklist without the full report, `projscan start --checklist --intent "<goal>"` prints only the resume checklist rows. For paste-ready PR, issue, or handoff notes, `projscan start --task-card --intent "<goal>"` prints the Markdown task card. MCP agents can read `missionControl.taskCard.markdown` when they need the same checklist without rendering it from `resume.checklist`. For stop-and-review notes, `projscan start --review-gate --intent "<goal>"` prints only `missionControl.reviewGate.markdown`, `projscan start --review-gate-json --intent "<goal>"` prints only the review gate JSON, `projscan start --review-policy --intent "<goal>"` prints only the review policy JSON, and `projscan start --review-replies --intent "<goal>"` prints only the copyable reviewer replies. For a full Markdown artifact, `projscan start --runbook --intent "<goal>"` prints the mission runbook. For post-run proof, `projscan mission-proof --mission .projscan/mission --format markdown` prints a paste-ready evidence report, while `--format json` keeps the same data machine-readable. Add `--list` to show saved mission bundles, status, update time, totals, and copyable resume/proof commands before choosing a target; add `--needs-attention` or `--mission-status failed` to focus that list. Add `--latest` to select the saved mission bundle with the newest `proof-logs/summary.json`. Add `--all` to include `.projscan/mission` and direct child bundles under `.projscan/missions/`. Add `--summary` when logs need one pass/fail line. Add `--require-passed` when a local script should fail unless every selected bundle passed. Add `--write reports/mission-proof.md` or `--write reports/mission-proof.json` when a reviewer, CI job, or next agent needs a saved local artifact. Run `projscan mission-proof --init-baseline manual-runs.json` before manual comparison if the team has not created the baseline file yet; use `--add-baseline-run manual-runs.json --id manual-1 --status passed --minutes-spent 25` to append measured manual runs without editing JSON. Run `--check-baseline manual-runs.json` before comparison when you want to validate the file without scanning mission bundles. Add `--format json` to baseline init, append, or check commands when a wrapper needs the written path, run count, added run, or totals. Baseline run IDs must be non-empty and unique; statuses must be `passed`, `failed`, `running`, `not_run`, or `unknown`; metric fields must be non-negative numbers.
|
|
212
|
+
|
|
213
|
+
#### Mission Control demos
|
|
214
|
+
|
|
215
|
+
The checked-in VHS demos show the current terminal flow without manual screen recording.
|
|
216
|
+
|
|
217
|
+
<img src="projscan-mission-control.gif" alt="projscan Mission Control shortcut menu for a plain-language goal" width="760">
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
npx projscan start --save-mission .projscan/mission --intent "what breaks if I rename the auth token loader?"
|
|
221
|
+
cd .projscan/mission && ./mission.sh && ./status.sh && ./review.sh
|
|
222
|
+
npx projscan start --mission .projscan/mission
|
|
223
|
+
npx projscan mission-proof --mission .projscan/mission --format markdown
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
<img src="projscan-mission-proof.gif" alt="projscan Mission Proof report and resume command reading a saved Mission Control bundle" width="760">
|
|
227
|
+
|
|
228
|
+
Regenerate the demos with:
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
npm run docs:demos
|
|
232
|
+
```
|
|
211
233
|
|
|
212
234
|
### 2. Review — "is this PR safe to merge?"
|
|
213
235
|
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Output docs/projscan-mission-control.gif
|
|
2
|
+
|
|
3
|
+
Set Shell "bash"
|
|
4
|
+
Set FontSize 16
|
|
5
|
+
Set Width 1200
|
|
6
|
+
Set Height 720
|
|
7
|
+
Set Theme "Catppuccin Mocha"
|
|
8
|
+
Set TypingSpeed 35ms
|
|
9
|
+
Set Padding 16
|
|
10
|
+
|
|
11
|
+
Type "projscan start --shortcuts --intent 'is it safe to commit this change?'"
|
|
12
|
+
Enter
|
|
13
|
+
Sleep 12s
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
Output docs/projscan-mission-proof.gif
|
|
2
|
+
|
|
3
|
+
Set Shell "bash"
|
|
4
|
+
Set FontSize 16
|
|
5
|
+
Set Width 1200
|
|
6
|
+
Set Height 720
|
|
7
|
+
Set Theme "Catppuccin Mocha"
|
|
8
|
+
Set TypingSpeed 35ms
|
|
9
|
+
Set Padding 16
|
|
10
|
+
|
|
11
|
+
Type "rm -rf .projscan/vhs-mission"
|
|
12
|
+
Enter
|
|
13
|
+
Sleep 500ms
|
|
14
|
+
|
|
15
|
+
Type "projscan start --save-mission .projscan/vhs-mission --intent 'is it safe to commit this change?'"
|
|
16
|
+
Enter
|
|
17
|
+
Sleep 10s
|
|
18
|
+
|
|
19
|
+
Type "projscan mission-proof --mission .projscan/vhs-mission --format markdown | sed -n '1,38p'"
|
|
20
|
+
Enter
|
|
21
|
+
Sleep 8s
|
|
22
|
+
|
|
23
|
+
Type "projscan start --mission .projscan/vhs-mission --handoff-prompt | sed -n '1,8p'"
|
|
24
|
+
Enter
|
|
25
|
+
Sleep 16s
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "projscan",
|
|
3
3
|
"mcpName": "io.github.abhiyoheswaran1/projscan",
|
|
4
|
-
"version": "4.3.
|
|
4
|
+
"version": "4.3.1",
|
|
5
5
|
"description": "Agent-first code intelligence. MCP server (2025-03-26) with 11 AST adapters covering 12 named languages: JavaScript, TypeScript, Python, Go, Java, Ruby, Rust, PHP, C#, Kotlin, Swift, and C++; repo understanding maps (projscan_understand), stable v3 semantic graph (projscan_semantic_graph), dataflow risk engine with bridge-helper detection (projscan_dataflow), code graph, file + per-function AST cyclomatic complexity, per-function fan-in + fan-out, coupling + cycle detection, structural PR diff with HTML reporter, coverage report with HTML reporter, intent-grounded one-call PR review (projscan_review with optional `intent` arg, new taint flows, contract changes, and newDataflowRisks) and long-running PR-watch mode with structured per-bucket deltas (projscan_review_watch), first-60-seconds workflow orientation (projscan_start), agent workplans (projscan_workplan), bug-hunt queues (projscan_bug_hunt), product-line planning (projscan_release_train), evidence packs (projscan_evidence_pack), regression planning (projscan_regression_plan), agent briefs (projscan_agent_brief), quality scorecards (projscan_quality_scorecard), and preflight with supply-chain IOC evidence, rule-driven fix suggestions + mechanical apply layer with rollback (projscan_apply_fix, projscan_fix_suggest, projscan_explain_issue), source-to-sink taint analysis (projscan_taint) with truncation reporting, transitive blast-radius analysis with cross-repo mode (projscan_impact for files and symbols), cross-repo workspace registration + intelligence (projscan_workspace_graph), per-function semantic search chunks (sub-file embeddings), per-rule confidence + severity drift + cost-summary analytics with live streaming (projscan_cost_summary), stable local analyzer + reporter plugin API (projscan_plugin, CLI --reporter, opt-in via PROJSCAN_PLUGINS_PREVIEW=1), monorepo workspace awareness with cross-package import policy + per-package dependencies / outdated / audit, BM25 + optional semantic search, cursor pagination, progress notifications, context-budgeted output, and a stable-surface CI guard. CLI on the side.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./dist/index.js",
|
|
@@ -18,11 +18,16 @@
|
|
|
18
18
|
"docs/PLUGIN-GALLERY.md",
|
|
19
19
|
"docs/ROADMAP.md",
|
|
20
20
|
"docs/demos/projscan-4-1-demo.html",
|
|
21
|
+
"docs/demos/projscan-mission-control.tape",
|
|
22
|
+
"docs/demos/projscan-mission-proof.tape",
|
|
21
23
|
"docs/plugin.schema.json",
|
|
22
24
|
"docs/projscan-mission-control.png",
|
|
25
|
+
"docs/projscan-mission-control.gif",
|
|
23
26
|
"docs/projscan-proof-router.png",
|
|
27
|
+
"docs/projscan-mission-proof.gif",
|
|
24
28
|
"docs/examples/plugins",
|
|
25
29
|
"scripts/capture-readme-assets.mjs",
|
|
30
|
+
"scripts/capture-vhs-demos.mjs",
|
|
26
31
|
"public/brand/baseframe-labs",
|
|
27
32
|
"public/.well-known/security.txt",
|
|
28
33
|
"CONTRIBUTING.md",
|
|
@@ -44,6 +49,8 @@
|
|
|
44
49
|
"bench": "node scripts/bench.mjs",
|
|
45
50
|
"bench:references": "node scripts/bench-references.mjs",
|
|
46
51
|
"docs:screenshots": "node scripts/capture-readme-assets.mjs",
|
|
52
|
+
"docs:demos": "npm run build && node scripts/capture-vhs-demos.mjs",
|
|
53
|
+
"docs:assets": "npm run docs:screenshots && npm run docs:demos",
|
|
47
54
|
"smoke:packed-install": "node scripts/packed-install-smoke.mjs",
|
|
48
55
|
"check:stability": "node scripts/check-stability.mjs",
|
|
49
56
|
"release:check": "node scripts/release-check.mjs",
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { chmodSync, existsSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { spawnSync } from 'node:child_process';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
|
|
6
|
+
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
7
|
+
const cliPath = path.join(repoRoot, 'dist', 'cli', 'index.js');
|
|
8
|
+
const vhsBinDir = path.join(repoRoot, '.projscan', 'vhs-bin');
|
|
9
|
+
const vhsShimPath = path.join(vhsBinDir, 'projscan');
|
|
10
|
+
const vhsMissionDir = path.join(repoRoot, '.projscan', 'vhs-mission');
|
|
11
|
+
|
|
12
|
+
const tapes = [
|
|
13
|
+
{
|
|
14
|
+
name: 'Mission Control terminal demo',
|
|
15
|
+
tape: path.join(repoRoot, 'docs', 'demos', 'projscan-mission-control.tape'),
|
|
16
|
+
output: path.join(repoRoot, 'docs', 'projscan-mission-control.gif'),
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
name: 'Mission Proof terminal demo',
|
|
20
|
+
tape: path.join(repoRoot, 'docs', 'demos', 'projscan-mission-proof.tape'),
|
|
21
|
+
output: path.join(repoRoot, 'docs', 'projscan-mission-proof.gif'),
|
|
22
|
+
},
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
const quoteForShell = (value) => `'${value.replaceAll("'", "'\"'\"'")}'`;
|
|
26
|
+
|
|
27
|
+
const fail = (message, status = 1) => {
|
|
28
|
+
console.error(message);
|
|
29
|
+
process.exit(status);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
if (!existsSync(cliPath)) {
|
|
33
|
+
fail('Missing dist/cli/index.js. Run `npm run build` before capturing VHS demos.');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const vhsVersion = spawnSync('vhs', ['--version'], { cwd: repoRoot, encoding: 'utf8' });
|
|
37
|
+
if (vhsVersion.status !== 0) {
|
|
38
|
+
fail('Missing `vhs`. Install it with `brew install vhs`, then run `npm run docs:demos`.');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
for (const tape of tapes) {
|
|
42
|
+
if (!existsSync(tape.tape)) {
|
|
43
|
+
fail(`Missing VHS tape: ${path.relative(repoRoot, tape.tape)}`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
mkdirSync(vhsBinDir, { recursive: true });
|
|
48
|
+
writeFileSync(vhsShimPath, `#!/usr/bin/env sh\nexec node ${quoteForShell(cliPath)} "$@"\n`);
|
|
49
|
+
chmodSync(vhsShimPath, 0o755);
|
|
50
|
+
|
|
51
|
+
const env = {
|
|
52
|
+
...process.env,
|
|
53
|
+
PATH: `${vhsBinDir}${path.delimiter}${process.env.PATH ?? ''}`,
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
rmSync(vhsMissionDir, { recursive: true, force: true });
|
|
58
|
+
|
|
59
|
+
for (const tape of tapes) {
|
|
60
|
+
console.log(`Capturing ${tape.name} -> ${path.relative(repoRoot, tape.output)}`);
|
|
61
|
+
const result = spawnSync('vhs', [path.relative(repoRoot, tape.tape)], {
|
|
62
|
+
cwd: repoRoot,
|
|
63
|
+
env,
|
|
64
|
+
stdio: 'inherit',
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
if (result.status !== 0) {
|
|
68
|
+
fail(`VHS capture failed for ${path.relative(repoRoot, tape.tape)}`, result.status ?? 1);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (!existsSync(tape.output)) {
|
|
72
|
+
fail(`VHS did not write expected output: ${path.relative(repoRoot, tape.output)}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
} finally {
|
|
76
|
+
rmSync(vhsMissionDir, { recursive: true, force: true });
|
|
77
|
+
rmSync(vhsBinDir, { recursive: true, force: true });
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
console.log('VHS demos captured.');
|