mustflow 2.17.0 → 2.18.2
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 +3 -3
- package/dist/cli/commands/classify.js +13 -3
- package/dist/cli/commands/dashboard.js +2 -1
- package/dist/cli/commands/explain-verify.js +2 -2
- package/dist/cli/commands/impact.js +13 -3
- package/dist/cli/commands/run.js +156 -104
- package/dist/cli/commands/verify.js +157 -45
- package/dist/cli/i18n/en.js +10 -1
- package/dist/cli/i18n/es.js +10 -1
- package/dist/cli/i18n/fr.js +10 -1
- package/dist/cli/i18n/hi.js +10 -1
- package/dist/cli/i18n/ko.js +10 -1
- package/dist/cli/i18n/zh.js +10 -1
- package/dist/cli/lib/git-changes.js +25 -2
- package/dist/cli/lib/local-index/constants.js +4 -1
- package/dist/cli/lib/local-index/index.js +22 -5
- package/dist/cli/lib/repo-map.js +90 -30
- package/dist/cli/lib/run-plan.js +25 -2
- package/dist/cli/lib/validation/index.js +2 -1
- package/dist/core/atomic-state-write.js +31 -0
- package/dist/core/bounded-output.js +23 -1
- package/dist/core/check-issues.js +3 -0
- package/dist/core/command-contract-rules.js +104 -2
- package/dist/core/command-contract-validation.js +71 -9
- package/dist/core/command-intent-eligibility.js +9 -1
- package/dist/core/command-output-limits.js +5 -0
- package/dist/core/completion-verdict.js +2 -1
- package/dist/core/contract-lint.js +10 -1
- package/dist/core/public-json-contracts.js +1 -1
- package/dist/core/run-receipt.js +20 -13
- package/dist/core/source-anchors.js +96 -24
- package/dist/core/verification-evidence.js +4 -1
- package/package.json +1 -1
- package/schemas/README.md +4 -4
- package/schemas/change-verification-report.schema.json +2 -1
- package/schemas/contract-lint-report.schema.json +2 -1
- package/schemas/explain-report.schema.json +1 -0
- package/schemas/latest-run-pointer.schema.json +1 -0
- package/schemas/run-receipt.schema.json +26 -3
- package/schemas/verify-report.schema.json +2 -1
- package/schemas/verify-run-manifest.schema.json +2 -1
- package/templates/default/manifest.toml +1 -1
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
|
-
import { mkdirSync, readFileSync,
|
|
2
|
+
import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { createClassifyOutput } from './classify.js';
|
|
5
5
|
import { runRun } from './run.js';
|
|
6
6
|
import { createChangeVerificationReport, } from '../../core/change-verification.js';
|
|
7
7
|
import { createVerifyCompletionVerdict, } from '../../core/completion-verdict.js';
|
|
8
|
+
import { atomicWriteJsonFile, createStateRunId } from '../../core/atomic-state-write.js';
|
|
8
9
|
import { createExternalEvidenceRisks, } from '../../core/external-evidence.js';
|
|
9
10
|
import { createRepeatedFailureRisks, createVerificationFailureFingerprint, updateRepeatedFailureState, } from '../../core/repeated-failure.js';
|
|
10
11
|
import { countReproEvidenceVerdictEffects, createReproEvidenceRisks, } from '../../core/repro-evidence.js';
|
|
@@ -17,9 +18,9 @@ import { t } from '../lib/i18n.js';
|
|
|
17
18
|
import { readLocalCommandEffectGraph, readLocalPathSurfaces, readLocalSourceAnchorVerdictRisks, } from '../lib/local-index.js';
|
|
18
19
|
import { resolveMustflowRoot } from '../lib/project-root.js';
|
|
19
20
|
const VERIFY_SCHEMA_VERSION = '1';
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
const
|
|
21
|
+
const RUN_STATE_DIR = path.join('.mustflow', 'state', 'runs');
|
|
22
|
+
const LATEST_RUN_RECEIPT_PATH = path.join(RUN_STATE_DIR, 'latest.json');
|
|
23
|
+
const DEFAULT_VERIFY_PARALLELISM = 1;
|
|
23
24
|
function createBufferedOutput() {
|
|
24
25
|
const stdout = [];
|
|
25
26
|
const stderr = [];
|
|
@@ -52,6 +53,7 @@ export function getVerifyHelp(lang = 'en') {
|
|
|
52
53
|
{ label: '--write-plan <path>', description: t(lang, 'verify.help.option.writePlan') },
|
|
53
54
|
{ label: '--repro-evidence <path>', description: t(lang, 'verify.help.option.reproEvidence') },
|
|
54
55
|
{ label: '--external-evidence <path>', description: t(lang, 'verify.help.option.externalEvidence') },
|
|
56
|
+
{ label: '--parallel <count>', description: t(lang, 'verify.help.option.parallel') },
|
|
55
57
|
{ label: '--plan-only', description: t(lang, 'verify.help.option.planOnly') },
|
|
56
58
|
{ label: '--json', description: t(lang, 'cli.option.json') },
|
|
57
59
|
{ label: '-h, --help', description: t(lang, 'cli.option.help') },
|
|
@@ -81,6 +83,7 @@ function parseVerifyArgs(args) {
|
|
|
81
83
|
let json = false;
|
|
82
84
|
let planOnly = false;
|
|
83
85
|
let changed = false;
|
|
86
|
+
let parallelism = DEFAULT_VERIFY_PARALLELISM;
|
|
84
87
|
for (let index = 0; index < args.length; index += 1) {
|
|
85
88
|
const arg = args[index];
|
|
86
89
|
if (arg === '--json') {
|
|
@@ -95,6 +98,19 @@ function parseVerifyArgs(args) {
|
|
|
95
98
|
changed = true;
|
|
96
99
|
continue;
|
|
97
100
|
}
|
|
101
|
+
if (arg === '--parallel') {
|
|
102
|
+
const value = args[index + 1];
|
|
103
|
+
if (!value || value.startsWith('-')) {
|
|
104
|
+
return { json, planOnly, changed, reason, parallelism, error: 'missing_parallel_value' };
|
|
105
|
+
}
|
|
106
|
+
const parsedParallelism = parseVerifyParallelism(value);
|
|
107
|
+
if (parsedParallelism === null) {
|
|
108
|
+
return { json, planOnly, changed, reason, parallelism, error: 'invalid_parallel_value' };
|
|
109
|
+
}
|
|
110
|
+
parallelism = parsedParallelism;
|
|
111
|
+
index += 1;
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
98
114
|
if (arg === '--reason') {
|
|
99
115
|
const value = args[index + 1];
|
|
100
116
|
if (!value || value.startsWith('-')) {
|
|
@@ -195,6 +211,15 @@ function parseVerifyArgs(args) {
|
|
|
195
211
|
reason = value;
|
|
196
212
|
continue;
|
|
197
213
|
}
|
|
214
|
+
if (arg.startsWith('--parallel=')) {
|
|
215
|
+
const value = arg.slice('--parallel='.length);
|
|
216
|
+
const parsedParallelism = parseVerifyParallelism(value);
|
|
217
|
+
if (parsedParallelism === null) {
|
|
218
|
+
return { json, planOnly, changed, reason, parallelism, error: 'invalid_parallel_value' };
|
|
219
|
+
}
|
|
220
|
+
parallelism = parsedParallelism;
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
198
223
|
if (arg.startsWith('--from-plan=')) {
|
|
199
224
|
const value = arg.slice('--from-plan='.length);
|
|
200
225
|
if (value.length === 0) {
|
|
@@ -289,7 +314,25 @@ function parseVerifyArgs(args) {
|
|
|
289
314
|
error: `unexpected:${arg}`,
|
|
290
315
|
};
|
|
291
316
|
}
|
|
292
|
-
return {
|
|
317
|
+
return {
|
|
318
|
+
json,
|
|
319
|
+
planOnly,
|
|
320
|
+
changed,
|
|
321
|
+
reason,
|
|
322
|
+
fromClassification,
|
|
323
|
+
fromPlan,
|
|
324
|
+
writePlan,
|
|
325
|
+
reproEvidence,
|
|
326
|
+
externalEvidence,
|
|
327
|
+
parallelism,
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
function parseVerifyParallelism(value) {
|
|
331
|
+
if (!/^[1-9][0-9]*$/u.test(value)) {
|
|
332
|
+
return null;
|
|
333
|
+
}
|
|
334
|
+
const parsed = Number(value);
|
|
335
|
+
return Number.isSafeInteger(parsed) ? parsed : null;
|
|
293
336
|
}
|
|
294
337
|
function uniqueStrings(values) {
|
|
295
338
|
return [...new Set(values.map((value) => value.trim()).filter((value) => value.length > 0))];
|
|
@@ -297,6 +340,18 @@ function uniqueStrings(values) {
|
|
|
297
340
|
function toPosixPath(value) {
|
|
298
341
|
return value.split(path.sep).join('/');
|
|
299
342
|
}
|
|
343
|
+
function createVerifyRunStatePaths(projectRoot) {
|
|
344
|
+
const runDir = toPosixPath(path.join(RUN_STATE_DIR, createStateRunId('verify')));
|
|
345
|
+
const manifestPath = toPosixPath(path.join(runDir, 'manifest.json'));
|
|
346
|
+
const absoluteRunDir = path.join(projectRoot, runDir);
|
|
347
|
+
return {
|
|
348
|
+
runDir,
|
|
349
|
+
manifestPath,
|
|
350
|
+
absoluteRunDir,
|
|
351
|
+
absoluteIntentDir: path.join(absoluteRunDir, 'intents'),
|
|
352
|
+
absoluteManifestPath: path.join(projectRoot, manifestPath),
|
|
353
|
+
};
|
|
354
|
+
}
|
|
300
355
|
function sanitizeIntentFilePart(value) {
|
|
301
356
|
const sanitized = value.replace(/[^A-Za-z0-9._-]+/g, '_').replace(/^_+|_+$/g, '');
|
|
302
357
|
return sanitized.length > 0 ? sanitized.slice(0, 80) : 'intent';
|
|
@@ -445,7 +500,7 @@ function resolvePlanPath(projectRoot, inputPath) {
|
|
|
445
500
|
}
|
|
446
501
|
return resolved;
|
|
447
502
|
}
|
|
448
|
-
export function
|
|
503
|
+
export function readInputFromClassificationReport(projectRoot, inputPath) {
|
|
449
504
|
let parsed;
|
|
450
505
|
const planPath = resolvePlanPath(projectRoot, inputPath);
|
|
451
506
|
try {
|
|
@@ -764,6 +819,8 @@ export function planErrorMessageKey(code) {
|
|
|
764
819
|
return 'verify.error.unsupported_plan_source';
|
|
765
820
|
case 'plan_root_mismatch':
|
|
766
821
|
return 'verify.error.plan_root_mismatch';
|
|
822
|
+
case 'git_changed_files_unavailable':
|
|
823
|
+
return 'verify.error.changed_files_unavailable';
|
|
767
824
|
default:
|
|
768
825
|
return 'verify.error.invalid_plan_file';
|
|
769
826
|
}
|
|
@@ -834,7 +891,8 @@ async function runVerificationIntent(intent, lang, verificationPlanId, testTarge
|
|
|
834
891
|
if (receiptStatus === 'passed' ||
|
|
835
892
|
receiptStatus === 'failed' ||
|
|
836
893
|
receiptStatus === 'timed_out' ||
|
|
837
|
-
receiptStatus === 'start_failed'
|
|
894
|
+
receiptStatus === 'start_failed' ||
|
|
895
|
+
receiptStatus === 'output_limit_exceeded') {
|
|
838
896
|
status = receiptStatus;
|
|
839
897
|
}
|
|
840
898
|
}
|
|
@@ -854,12 +912,52 @@ async function runVerificationIntent(intent, lang, verificationPlanId, testTarge
|
|
|
854
912
|
receipt,
|
|
855
913
|
};
|
|
856
914
|
}
|
|
915
|
+
function entriesForScheduleBatch(entries, batch) {
|
|
916
|
+
const batchIntents = new Set(batch.intents);
|
|
917
|
+
return entries.filter((entry) => batchIntents.has(entry.intent));
|
|
918
|
+
}
|
|
919
|
+
async function runVerificationEntriesSequentially(entries, lang, verificationPlanId, scheduledTestTargets) {
|
|
920
|
+
const results = [];
|
|
921
|
+
for (const entry of entries) {
|
|
922
|
+
results.push(await runVerificationIntent(entry.intent, lang, verificationPlanId, scheduledTestTargets.get(entry.intent) ?? []));
|
|
923
|
+
}
|
|
924
|
+
return results;
|
|
925
|
+
}
|
|
926
|
+
async function runVerificationEntriesInParallelChunks(entries, parallelism, lang, verificationPlanId, scheduledTestTargets) {
|
|
927
|
+
const results = [];
|
|
928
|
+
for (let index = 0; index < entries.length; index += parallelism) {
|
|
929
|
+
const chunk = entries.slice(index, index + parallelism);
|
|
930
|
+
results.push(...(await Promise.all(chunk.map((entry) => runVerificationIntent(entry.intent, lang, verificationPlanId, scheduledTestTargets.get(entry.intent) ?? [])))));
|
|
931
|
+
}
|
|
932
|
+
return results;
|
|
933
|
+
}
|
|
934
|
+
async function runScheduledVerificationIntents(report, lang, verificationPlanId, scheduledTestTargets, parallelism) {
|
|
935
|
+
if (parallelism <= DEFAULT_VERIFY_PARALLELISM) {
|
|
936
|
+
return runVerificationEntriesSequentially(report.schedule.entries, lang, verificationPlanId, scheduledTestTargets);
|
|
937
|
+
}
|
|
938
|
+
const results = [];
|
|
939
|
+
for (const batch of report.schedule.batches) {
|
|
940
|
+
const entries = entriesForScheduleBatch(report.schedule.entries, batch);
|
|
941
|
+
if (entries.length === 0) {
|
|
942
|
+
continue;
|
|
943
|
+
}
|
|
944
|
+
if (entries.length > 1 && entries.every((entry) => entry.parallelEligible)) {
|
|
945
|
+
results.push(...(await runVerificationEntriesInParallelChunks(entries, parallelism, lang, verificationPlanId, scheduledTestTargets)));
|
|
946
|
+
continue;
|
|
947
|
+
}
|
|
948
|
+
results.push(...(await runVerificationEntriesSequentially(entries, lang, verificationPlanId, scheduledTestTargets)));
|
|
949
|
+
}
|
|
950
|
+
return results;
|
|
951
|
+
}
|
|
857
952
|
function summarizeResults(results) {
|
|
858
953
|
const ran = results.filter((result) => !result.skipped).length;
|
|
859
954
|
const passed = results.filter((result) => result.status === 'passed').length;
|
|
860
955
|
const skipped = results.filter((result) => result.skipped).length;
|
|
861
956
|
const failed = results.filter((result) => !result.skipped &&
|
|
862
|
-
(result.status === 'failed' ||
|
|
957
|
+
(result.status === 'failed' ||
|
|
958
|
+
result.status === 'timed_out' ||
|
|
959
|
+
result.status === 'start_failed' ||
|
|
960
|
+
result.status === 'output_limit_exceeded')).length;
|
|
863
961
|
return {
|
|
864
962
|
matched: results.filter((result) => result.intent !== null).length,
|
|
865
963
|
ran,
|
|
@@ -908,11 +1006,15 @@ function timedOutForResult(result) {
|
|
|
908
1006
|
return result.status === 'timed_out' || resultSummary?.timed_out === true;
|
|
909
1007
|
}
|
|
910
1008
|
function errorKindForResult(result) {
|
|
911
|
-
return stringField(resultSummaryForResult(result)?.error_kind) ??
|
|
1009
|
+
return (stringField(resultSummaryForResult(result)?.error_kind) ??
|
|
1010
|
+
(result.status === 'start_failed' || result.status === 'output_limit_exceeded' ? result.status : null));
|
|
912
1011
|
}
|
|
913
1012
|
function failedResults(results) {
|
|
914
1013
|
return results.filter((result) => !result.skipped &&
|
|
915
|
-
(result.status === 'failed' ||
|
|
1014
|
+
(result.status === 'failed' ||
|
|
1015
|
+
result.status === 'timed_out' ||
|
|
1016
|
+
result.status === 'start_failed' ||
|
|
1017
|
+
result.status === 'output_limit_exceeded'));
|
|
916
1018
|
}
|
|
917
1019
|
function createFailureFingerprintForVerify(input) {
|
|
918
1020
|
const failures = failedResults(input.results);
|
|
@@ -1024,7 +1126,10 @@ function createCriteriaEvidence(report, results) {
|
|
|
1024
1126
|
.filter((intent) => intent !== null);
|
|
1025
1127
|
const gapCount = report.gaps.filter((gap) => gap.reason === requirement.reason).length;
|
|
1026
1128
|
const selectedResults = selectedIntents.map((intent) => resultForSelectedIntent(results, intent));
|
|
1027
|
-
if (selectedResults.some((result) => result?.status === 'failed' ||
|
|
1129
|
+
if (selectedResults.some((result) => result?.status === 'failed' ||
|
|
1130
|
+
result?.status === 'timed_out' ||
|
|
1131
|
+
result?.status === 'start_failed' ||
|
|
1132
|
+
result?.status === 'output_limit_exceeded')) {
|
|
1028
1133
|
return { ...current, contradicted: current.contradicted + 1 };
|
|
1029
1134
|
}
|
|
1030
1135
|
if (gapCount > 0 || (selectedIntents.length === 0 && skippedIntents.length > 0)) {
|
|
@@ -1179,20 +1284,18 @@ function createVerificationPlanId(report, contract) {
|
|
|
1179
1284
|
return hashTextSha256(stableJson(fingerprintSource));
|
|
1180
1285
|
}
|
|
1181
1286
|
function writeVerifyRunReceipts(projectRoot, output, report, sourceAnchorRisks, scopeDiffRisks, validationRatchetRisks, reproEvidence, externalChecks) {
|
|
1182
|
-
const
|
|
1183
|
-
const intentDir = path.join(runDir, 'intents');
|
|
1287
|
+
const statePaths = createVerifyRunStatePaths(projectRoot);
|
|
1184
1288
|
const receipts = [];
|
|
1185
1289
|
const results = [];
|
|
1186
|
-
|
|
1187
|
-
mkdirSync(intentDir, { recursive: true });
|
|
1290
|
+
mkdirSync(statePaths.absoluteIntentDir, { recursive: true });
|
|
1188
1291
|
for (const [index, result] of output.results.entries()) {
|
|
1189
1292
|
let receiptPath = null;
|
|
1190
1293
|
let receiptSha256 = null;
|
|
1191
1294
|
let receipt = result.receipt;
|
|
1192
1295
|
if (result.intent && result.receipt) {
|
|
1193
1296
|
const fileName = `${String(index + 1).padStart(3, '0')}-${sanitizeIntentFilePart(result.intent)}.json`;
|
|
1194
|
-
const absoluteReceiptPath = path.join(
|
|
1195
|
-
receiptPath = toPosixPath(path.join(
|
|
1297
|
+
const absoluteReceiptPath = path.join(statePaths.absoluteIntentDir, fileName);
|
|
1298
|
+
receiptPath = toPosixPath(path.join(statePaths.runDir, 'intents', fileName));
|
|
1196
1299
|
receipt = {
|
|
1197
1300
|
...result.receipt,
|
|
1198
1301
|
verification_plan_id: output.verification_plan_id,
|
|
@@ -1200,7 +1303,7 @@ function writeVerifyRunReceipts(projectRoot, output, report, sourceAnchorRisks,
|
|
|
1200
1303
|
};
|
|
1201
1304
|
const receiptContent = `${JSON.stringify(receipt, null, 2)}\n`;
|
|
1202
1305
|
receiptSha256 = hashTextSha256(receiptContent);
|
|
1203
|
-
|
|
1306
|
+
atomicWriteJsonFile(absoluteReceiptPath, receipt);
|
|
1204
1307
|
}
|
|
1205
1308
|
receipts.push({
|
|
1206
1309
|
intent: result.intent,
|
|
@@ -1270,6 +1373,8 @@ function writeVerifyRunReceipts(projectRoot, output, report, sourceAnchorRisks,
|
|
|
1270
1373
|
completion_verdict: completionVerdict,
|
|
1271
1374
|
failure_fingerprint: failureFingerprint,
|
|
1272
1375
|
repeated_failure_summary: repeatedFailureSummary,
|
|
1376
|
+
run_dir: statePaths.runDir,
|
|
1377
|
+
manifest_path: statePaths.manifestPath,
|
|
1273
1378
|
results,
|
|
1274
1379
|
evidence_model: createVerifyEvidenceModel({
|
|
1275
1380
|
report,
|
|
@@ -1293,6 +1398,7 @@ function writeVerifyRunReceipts(projectRoot, output, report, sourceAnchorRisks,
|
|
|
1293
1398
|
reasons: outputWithReceiptPaths.reasons,
|
|
1294
1399
|
plan_source: outputWithReceiptPaths.plan_source,
|
|
1295
1400
|
verification_plan_id: outputWithReceiptPaths.verification_plan_id,
|
|
1401
|
+
execution_status: outputWithReceiptPaths.execution_status,
|
|
1296
1402
|
status: outputWithReceiptPaths.status,
|
|
1297
1403
|
completion_verdict: outputWithReceiptPaths.completion_verdict,
|
|
1298
1404
|
evidence_model: outputWithReceiptPaths.evidence_model,
|
|
@@ -1303,7 +1409,7 @@ function writeVerifyRunReceipts(projectRoot, output, report, sourceAnchorRisks,
|
|
|
1303
1409
|
...(outputWithReceiptPaths.external_checks ? { external_checks: outputWithReceiptPaths.external_checks } : {}),
|
|
1304
1410
|
receipts,
|
|
1305
1411
|
};
|
|
1306
|
-
|
|
1412
|
+
atomicWriteJsonFile(statePaths.absoluteManifestPath, manifest);
|
|
1307
1413
|
const latest = {
|
|
1308
1414
|
schema_version: '1',
|
|
1309
1415
|
command: 'verify',
|
|
@@ -1312,6 +1418,7 @@ function writeVerifyRunReceipts(projectRoot, output, report, sourceAnchorRisks,
|
|
|
1312
1418
|
reasons: outputWithReceiptPaths.reasons,
|
|
1313
1419
|
plan_source: outputWithReceiptPaths.plan_source,
|
|
1314
1420
|
verification_plan_id: outputWithReceiptPaths.verification_plan_id,
|
|
1421
|
+
execution_status: outputWithReceiptPaths.execution_status,
|
|
1315
1422
|
status: outputWithReceiptPaths.status,
|
|
1316
1423
|
completion_verdict: outputWithReceiptPaths.completion_verdict,
|
|
1317
1424
|
evidence_model: outputWithReceiptPaths.evidence_model,
|
|
@@ -1320,13 +1427,13 @@ function writeVerifyRunReceipts(projectRoot, output, report, sourceAnchorRisks,
|
|
|
1320
1427
|
summary: outputWithReceiptPaths.summary,
|
|
1321
1428
|
...(outputWithReceiptPaths.repro_evidence ? { repro_evidence: outputWithReceiptPaths.repro_evidence } : {}),
|
|
1322
1429
|
...(outputWithReceiptPaths.external_checks ? { external_checks: outputWithReceiptPaths.external_checks } : {}),
|
|
1323
|
-
run_dir:
|
|
1324
|
-
manifest_path:
|
|
1430
|
+
run_dir: statePaths.runDir,
|
|
1431
|
+
manifest_path: statePaths.manifestPath,
|
|
1325
1432
|
};
|
|
1326
|
-
|
|
1433
|
+
atomicWriteJsonFile(path.join(projectRoot, LATEST_RUN_RECEIPT_PATH), latest);
|
|
1327
1434
|
return outputWithReceiptPaths;
|
|
1328
1435
|
}
|
|
1329
|
-
async function createVerifyOutput(input, planSource, projectRoot, lang, reproEvidence = null, externalChecks = []) {
|
|
1436
|
+
async function createVerifyOutput(input, planSource, projectRoot, lang, reproEvidence = null, externalChecks = [], parallelism = DEFAULT_VERIFY_PARALLELISM) {
|
|
1330
1437
|
const contract = readCommandContract(projectRoot);
|
|
1331
1438
|
const report = createChangeVerificationReport(input.classificationReport, contract, projectRoot);
|
|
1332
1439
|
const verificationPlanId = createVerificationPlanId(report, contract);
|
|
@@ -1339,10 +1446,7 @@ async function createVerifyOutput(input, planSource, projectRoot, lang, reproEvi
|
|
|
1339
1446
|
const reproEvidenceRisks = createReproEvidenceRisks(reproEvidence, { verificationPlanId });
|
|
1340
1447
|
const reproEvidenceVerdictEffects = countReproEvidenceVerdictEffects(reproEvidenceRisks);
|
|
1341
1448
|
const externalEvidenceRisks = createExternalEvidenceRisks(externalChecks);
|
|
1342
|
-
const results =
|
|
1343
|
-
for (const entry of report.schedule.entries) {
|
|
1344
|
-
results.push(await runVerificationIntent(entry.intent, lang, verificationPlanId, scheduledTestTargets.get(entry.intent) ?? []));
|
|
1345
|
-
}
|
|
1449
|
+
const results = await runScheduledVerificationIntents(report, lang, verificationPlanId, scheduledTestTargets, parallelism);
|
|
1346
1450
|
results.push(...createSkippedResults(report.candidates, scheduledIntents, report.gaps));
|
|
1347
1451
|
const summary = summarizeResults(results);
|
|
1348
1452
|
const status = getVerificationStatus(summary);
|
|
@@ -1403,6 +1507,7 @@ async function createVerifyOutput(input, planSource, projectRoot, lang, reproEvi
|
|
|
1403
1507
|
reasons: input.reasons,
|
|
1404
1508
|
plan_source: planSource,
|
|
1405
1509
|
verification_plan_id: verificationPlanId,
|
|
1510
|
+
execution_status: status,
|
|
1406
1511
|
status,
|
|
1407
1512
|
completion_verdict: completionVerdict,
|
|
1408
1513
|
evidence_model: evidenceModel,
|
|
@@ -1411,8 +1516,8 @@ async function createVerifyOutput(input, planSource, projectRoot, lang, reproEvi
|
|
|
1411
1516
|
summary,
|
|
1412
1517
|
...(reproEvidence ? { repro_evidence: reproEvidence } : {}),
|
|
1413
1518
|
...(externalChecks.length > 0 ? { external_checks: externalChecks } : {}),
|
|
1414
|
-
run_dir:
|
|
1415
|
-
manifest_path:
|
|
1519
|
+
run_dir: '',
|
|
1520
|
+
manifest_path: '',
|
|
1416
1521
|
results,
|
|
1417
1522
|
};
|
|
1418
1523
|
return writeVerifyRunReceipts(projectRoot, output, report, sourceAnchorRisks, scopeDiffRisks, validationRatchetRisks, reproEvidence, externalChecks);
|
|
@@ -1486,19 +1591,23 @@ export async function runVerify(args, reporter, lang = 'en') {
|
|
|
1486
1591
|
if (parsed.error) {
|
|
1487
1592
|
const message = parsed.error === 'missing_reason_value'
|
|
1488
1593
|
? t(lang, 'cli.error.missingValue', { option: '--reason' })
|
|
1489
|
-
: parsed.error === '
|
|
1490
|
-
? t(lang, 'cli.error.missingValue', { option: '--
|
|
1491
|
-
: parsed.error === '
|
|
1492
|
-
? t(lang, '
|
|
1493
|
-
: parsed.error === '
|
|
1494
|
-
? t(lang, 'cli.error.missingValue', { option: '--
|
|
1495
|
-
: parsed.error === '
|
|
1496
|
-
? t(lang, 'cli.error.missingValue', { option: '--
|
|
1497
|
-
: parsed.error === '
|
|
1498
|
-
? t(lang, 'cli.error.missingValue', { option: '--
|
|
1499
|
-
: parsed.error
|
|
1500
|
-
? t(lang, 'cli.error.
|
|
1501
|
-
:
|
|
1594
|
+
: parsed.error === 'missing_parallel_value'
|
|
1595
|
+
? t(lang, 'cli.error.missingValue', { option: '--parallel' })
|
|
1596
|
+
: parsed.error === 'invalid_parallel_value'
|
|
1597
|
+
? t(lang, 'verify.error.invalidParallel')
|
|
1598
|
+
: parsed.error === 'missing_from_classification_value'
|
|
1599
|
+
? t(lang, 'cli.error.missingValue', { option: '--from-classification' })
|
|
1600
|
+
: parsed.error === 'missing_from_plan_value'
|
|
1601
|
+
? t(lang, 'cli.error.missingValue', { option: '--from-plan' })
|
|
1602
|
+
: parsed.error === 'missing_write_plan_value'
|
|
1603
|
+
? t(lang, 'cli.error.missingValue', { option: '--write-plan' })
|
|
1604
|
+
: parsed.error === 'missing_repro_evidence_value'
|
|
1605
|
+
? t(lang, 'cli.error.missingValue', { option: '--repro-evidence' })
|
|
1606
|
+
: parsed.error === 'missing_external_evidence_value'
|
|
1607
|
+
? t(lang, 'cli.error.missingValue', { option: '--external-evidence' })
|
|
1608
|
+
: parsed.error.startsWith('unexpected:')
|
|
1609
|
+
? t(lang, 'cli.error.unexpectedArgument', { argument: parsed.error.slice('unexpected:'.length) })
|
|
1610
|
+
: t(lang, 'cli.error.unknownOption', { option: parsed.error });
|
|
1502
1611
|
printUsageError(reporter, message, 'mf verify --help', getVerifyHelp(lang), lang);
|
|
1503
1612
|
return 1;
|
|
1504
1613
|
}
|
|
@@ -1538,13 +1647,16 @@ export async function runVerify(args, reporter, lang = 'en') {
|
|
|
1538
1647
|
let reproEvidence = null;
|
|
1539
1648
|
let externalChecks = [];
|
|
1540
1649
|
try {
|
|
1650
|
+
if (parsed.writePlan) {
|
|
1651
|
+
resolvePlanPath(projectRoot, parsed.writePlan);
|
|
1652
|
+
}
|
|
1541
1653
|
if (parsed.changed) {
|
|
1542
1654
|
const changedInput = createInputFromChanged(projectRoot);
|
|
1543
1655
|
input = changedInput.input;
|
|
1544
1656
|
changedPlan = changedInput.plan;
|
|
1545
1657
|
}
|
|
1546
1658
|
else if (parsed.fromClassification || parsed.fromPlan) {
|
|
1547
|
-
input =
|
|
1659
|
+
input = readInputFromClassificationReport(projectRoot, (parsed.fromClassification ?? parsed.fromPlan));
|
|
1548
1660
|
}
|
|
1549
1661
|
else {
|
|
1550
1662
|
input = {
|
|
@@ -1580,12 +1692,12 @@ export async function runVerify(args, reporter, lang = 'en') {
|
|
|
1580
1692
|
reporter.stdout(JSON.stringify(await createPlanOnlyOutput(input, projectRoot), null, 2));
|
|
1581
1693
|
return 0;
|
|
1582
1694
|
}
|
|
1583
|
-
const output = await createVerifyOutput(input, parsed.fromClassification ?? parsed.fromPlan ?? (parsed.changed ? 'changed' : null), projectRoot, lang, reproEvidence, externalChecks);
|
|
1695
|
+
const output = await createVerifyOutput(input, parsed.fromClassification ?? parsed.fromPlan ?? (parsed.changed ? 'changed' : null), projectRoot, lang, reproEvidence, externalChecks, parsed.parallelism ?? DEFAULT_VERIFY_PARALLELISM);
|
|
1584
1696
|
if (parsed.json) {
|
|
1585
1697
|
reporter.stdout(JSON.stringify(output, null, 2));
|
|
1586
1698
|
}
|
|
1587
1699
|
else {
|
|
1588
1700
|
reporter.stdout(renderVerifyOutput(output, lang));
|
|
1589
1701
|
}
|
|
1590
|
-
return output.status === '
|
|
1702
|
+
return output.completion_verdict.status === 'verified' ? 0 : 1;
|
|
1591
1703
|
}
|
package/dist/cli/i18n/en.js
CHANGED
|
@@ -664,8 +664,12 @@ Read these files before working:
|
|
|
664
664
|
"run.error.unsafeIntentDetail": "Use a shell-safe intent name.",
|
|
665
665
|
"run.error.blockedShellBackground": 'Intent "{intent}" is blocked. {detail}',
|
|
666
666
|
"run.error.blockedShellBackgroundDetail": "Shell commands must not spawn background work.",
|
|
667
|
+
"run.error.blockedLongRunningCommand": 'Intent "{intent}" is blocked. {detail}',
|
|
668
|
+
"run.error.blockedLongRunningCommandDetail": "Command argv must describe a finite one-shot command, not a development server, watcher, shell wrapper, interpreter loop, or background process.",
|
|
667
669
|
"run.error.cwdOutsideProject": 'Command "{intent}" has an invalid cwd: {detail}',
|
|
668
670
|
"run.error.cwdOutsideProjectDetail": "Intent cwd must stay inside the current root.",
|
|
671
|
+
"run.error.maxOutputBytes": 'Command "{intent}" has invalid max_output_bytes. {detail}',
|
|
672
|
+
"run.error.maxOutputBytesDetail": "The output limit must stay within the allowed maximum.",
|
|
669
673
|
"run.error.conflictingPreviewModes": "Use either --dry-run or --plan-only, not both",
|
|
670
674
|
"run.error.timedOut": 'Command "{intent}" timed out after {seconds} seconds',
|
|
671
675
|
"run.error.startFailed": 'Command "{intent}" failed to start: {message}',
|
|
@@ -727,6 +731,7 @@ Read these files before working:
|
|
|
727
731
|
"classify.source.changed": "changed files",
|
|
728
732
|
"classify.source.paths": "explicit paths",
|
|
729
733
|
"classify.error.missingInput": "Specify --changed or at least one path",
|
|
734
|
+
"classify.error.changed_files_unavailable": "Unable to inspect changed files with git status",
|
|
730
735
|
"classify.error.write_path_outside_root": "Classification report path must stay inside the mustflow root",
|
|
731
736
|
"impact.help.summary": "Report whether changed paths require a package or template version decision without modifying files.",
|
|
732
737
|
"impact.help.option.changed": "Read paths from git status --short --untracked-files=all",
|
|
@@ -741,14 +746,16 @@ Read these files before working:
|
|
|
741
746
|
"impact.label.affectedVersionSources": "Affected version sources",
|
|
742
747
|
"impact.label.affectedSurfaces": "Affected surfaces",
|
|
743
748
|
"impact.error.missingInput": "Specify --changed or at least one path",
|
|
749
|
+
"impact.error.changed_files_unavailable": "Unable to inspect changed files with git status",
|
|
744
750
|
"verify.help.summary": "Run configured verification intents selected by required_after metadata.",
|
|
745
751
|
"verify.help.option.reason": "Select the required_after reason to verify",
|
|
746
752
|
"verify.help.option.fromClassification": "Read verification reasons from an mf classify report inside this repository",
|
|
747
|
-
"verify.help.option.fromPlan": "
|
|
753
|
+
"verify.help.option.fromPlan": "Deprecated compatibility alias for --from-classification; it still expects an mf classify report",
|
|
748
754
|
"verify.help.option.changed": "Classify current Git changes and verify the matching reasons",
|
|
749
755
|
"verify.help.option.writePlan": "Compatibility option that writes the changed-file classification report",
|
|
750
756
|
"verify.help.option.reproEvidence": "Read structured bug-fix reproduction evidence from a repository-local JSON summary",
|
|
751
757
|
"verify.help.option.externalEvidence": "Read lower-authority external CI evidence from a repository-local JSON summary",
|
|
758
|
+
"verify.help.option.parallel": "Run safe non-conflicting schedule batches with up to this many commands; default is 1",
|
|
752
759
|
"verify.help.option.planOnly": "Print the verification plan without running commands; requires --json",
|
|
753
760
|
"verify.help.exit.ok": "All selected verification intents passed",
|
|
754
761
|
"verify.help.exit.fail": "Verification failed, was partial, was blocked, or input was invalid",
|
|
@@ -763,11 +770,13 @@ Read these files before working:
|
|
|
763
770
|
"verify.error.planOnlyJson": "--plan-only requires --json",
|
|
764
771
|
"verify.error.reproEvidenceRequiresRun": "--repro-evidence cannot be used with --plan-only",
|
|
765
772
|
"verify.error.externalEvidenceRequiresRun": "--external-evidence cannot be used with --plan-only",
|
|
773
|
+
"verify.error.invalidParallel": "--parallel must be a positive integer",
|
|
766
774
|
"verify.error.invalid_plan_file": "Classification report must be a readable JSON file",
|
|
767
775
|
"verify.error.unsupported_plan_source": "Verification input must be an mf classify report",
|
|
768
776
|
"verify.error.plan_root_mismatch": "Classification report must come from this mustflow root",
|
|
769
777
|
"verify.error.missing_plan_reasons": "Classification report must include summary.validationReasons",
|
|
770
778
|
"verify.error.plan_path_outside_root": "Classification report path must stay inside the mustflow root",
|
|
779
|
+
"verify.error.changed_files_unavailable": "Unable to inspect changed files with git status",
|
|
771
780
|
"verify.error.invalid_repro_evidence_file": "Repro evidence must be a readable JSON summary with structured evidence fields",
|
|
772
781
|
"verify.error.unsupported_repro_evidence_source": "Repro evidence input must use command repro-evidence",
|
|
773
782
|
"verify.error.invalid_external_evidence_file": "External evidence must be a readable JSON summary with checks",
|
package/dist/cli/i18n/es.js
CHANGED
|
@@ -664,8 +664,12 @@ Lee estos archivos antes de trabajar:
|
|
|
664
664
|
"run.error.unsafeIntentDetail": "Usa un nombre de intención seguro para shell.",
|
|
665
665
|
"run.error.blockedShellBackground": 'La intención "{intent}" está bloqueada. {detail}',
|
|
666
666
|
"run.error.blockedShellBackgroundDetail": "Los comandos de shell no deben iniciar trabajo en segundo plano.",
|
|
667
|
+
"run.error.blockedLongRunningCommand": 'La intención "{intent}" está bloqueada. {detail}',
|
|
668
|
+
"run.error.blockedLongRunningCommandDetail": "argv debe describir un comando finito de una sola ejecución, no un servidor de desarrollo, watcher, envoltorio de shell, bucle de intérprete o proceso en segundo plano.",
|
|
667
669
|
"run.error.cwdOutsideProject": 'El comando "{intent}" tiene un cwd no válido: {detail}',
|
|
668
670
|
"run.error.cwdOutsideProjectDetail": "El cwd de la intención debe permanecer dentro de la raíz actual.",
|
|
671
|
+
"run.error.maxOutputBytes": 'El comando "{intent}" tiene max_output_bytes no válido. {detail}',
|
|
672
|
+
"run.error.maxOutputBytesDetail": "El límite de salida debe permanecer dentro del máximo permitido.",
|
|
669
673
|
"run.error.conflictingPreviewModes": "Usa --dry-run o --plan-only, no ambos",
|
|
670
674
|
"run.error.timedOut": 'El comando "{intent}" agotó el tiempo después de {seconds} segundos',
|
|
671
675
|
"run.error.startFailed": 'No se pudo iniciar el comando "{intent}": {message}',
|
|
@@ -727,6 +731,7 @@ Lee estos archivos antes de trabajar:
|
|
|
727
731
|
"classify.source.changed": "archivos cambiados",
|
|
728
732
|
"classify.source.paths": "rutas explicitas",
|
|
729
733
|
"classify.error.missingInput": "Indica --changed o al menos una ruta",
|
|
734
|
+
"classify.error.changed_files_unavailable": "No se pudieron inspeccionar los archivos cambiados con git status",
|
|
730
735
|
"classify.error.write_path_outside_root": "La ruta del informe de clasificacion debe permanecer dentro de la raiz mustflow",
|
|
731
736
|
"impact.help.summary": "Informa si las rutas cambiadas requieren una decision de version de paquete o plantilla sin modificar archivos.",
|
|
732
737
|
"impact.help.option.changed": "Lee rutas desde git status --short --untracked-files=all",
|
|
@@ -741,14 +746,16 @@ Lee estos archivos antes de trabajar:
|
|
|
741
746
|
"impact.label.affectedVersionSources": "Fuentes de version afectadas",
|
|
742
747
|
"impact.label.affectedSurfaces": "Superficies afectadas",
|
|
743
748
|
"impact.error.missingInput": "Indica --changed o al menos una ruta",
|
|
749
|
+
"impact.error.changed_files_unavailable": "No se pudieron inspeccionar los archivos cambiados con git status",
|
|
744
750
|
"verify.help.summary": "Ejecuta intenciones de verificación configuradas seleccionadas por metadatos required_after.",
|
|
745
751
|
"verify.help.option.reason": "Selecciona la razón required_after que se debe verificar",
|
|
746
752
|
"verify.help.option.fromClassification": "Lee razones de verificación desde un informe de mf classify dentro de este repositorio",
|
|
747
|
-
"verify.help.option.fromPlan": "Alias de compatibilidad para --from-classification",
|
|
753
|
+
"verify.help.option.fromPlan": "Alias de compatibilidad obsoleto para --from-classification; todavía espera un informe de mf classify",
|
|
748
754
|
"verify.help.option.changed": "Clasifica los cambios actuales de Git y verifica las razones correspondientes",
|
|
749
755
|
"verify.help.option.writePlan": "Opción de compatibilidad que escribe el informe de clasificación de cambios",
|
|
750
756
|
"verify.help.option.reproEvidence": "Lee evidencia estructurada de reproducción de errores desde un resumen JSON local del repositorio",
|
|
751
757
|
"verify.help.option.externalEvidence": "Lee evidencia de CI externa de menor autoridad desde un resumen JSON local del repositorio",
|
|
758
|
+
"verify.help.option.parallel": "Ejecuta lotes programados seguros y sin conflictos con hasta esta cantidad de comandos; el valor predeterminado es 1",
|
|
752
759
|
"verify.help.option.planOnly": "Imprime el plan de verificación sin ejecutar comandos; requiere --json",
|
|
753
760
|
"verify.help.exit.ok": "Todas las intenciones de verificación seleccionadas pasaron",
|
|
754
761
|
"verify.help.exit.fail": "La verificación falló, fue parcial, quedó bloqueada o la entrada no fue válida",
|
|
@@ -763,11 +770,13 @@ Lee estos archivos antes de trabajar:
|
|
|
763
770
|
"verify.error.planOnlyJson": "--plan-only requiere --json",
|
|
764
771
|
"verify.error.reproEvidenceRequiresRun": "--repro-evidence no se puede usar con --plan-only",
|
|
765
772
|
"verify.error.externalEvidenceRequiresRun": "--external-evidence no se puede usar con --plan-only",
|
|
773
|
+
"verify.error.invalidParallel": "--parallel debe ser un entero positivo",
|
|
766
774
|
"verify.error.invalid_plan_file": "El informe de clasificación debe ser un archivo JSON legible",
|
|
767
775
|
"verify.error.unsupported_plan_source": "La entrada de verificación debe ser un informe de mf classify",
|
|
768
776
|
"verify.error.plan_root_mismatch": "El informe de clasificación debe provenir de esta raíz mustflow",
|
|
769
777
|
"verify.error.missing_plan_reasons": "El informe de clasificación debe incluir summary.validationReasons",
|
|
770
778
|
"verify.error.plan_path_outside_root": "La ruta del informe de clasificación debe permanecer dentro de la raíz mustflow",
|
|
779
|
+
"verify.error.changed_files_unavailable": "No se pudieron inspeccionar los archivos cambiados con git status",
|
|
771
780
|
"verify.error.invalid_repro_evidence_file": "La evidencia de reproducción debe ser un resumen JSON legible con campos de evidencia estructurados",
|
|
772
781
|
"verify.error.unsupported_repro_evidence_source": "La entrada de evidencia de reproducción debe usar command repro-evidence",
|
|
773
782
|
"verify.error.invalid_external_evidence_file": "La evidencia externa debe ser un resumen JSON legible con checks",
|
package/dist/cli/i18n/fr.js
CHANGED
|
@@ -664,8 +664,12 @@ Lisez ces fichiers avant de travailler :
|
|
|
664
664
|
"run.error.unsafeIntentDetail": "Utilisez un nom d’intention sûr pour le shell.",
|
|
665
665
|
"run.error.blockedShellBackground": 'L’intention "{intent}" est bloquée. {detail}',
|
|
666
666
|
"run.error.blockedShellBackgroundDetail": "Les commandes shell ne doivent pas lancer de travail en arrière-plan.",
|
|
667
|
+
"run.error.blockedLongRunningCommand": 'L’intention "{intent}" est bloquée. {detail}',
|
|
668
|
+
"run.error.blockedLongRunningCommandDetail": "argv doit décrire une commande ponctuelle finie, pas un serveur de développement, un watcher, un wrapper shell, une boucle d'interpréteur ou un processus en arrière-plan.",
|
|
667
669
|
"run.error.cwdOutsideProject": 'La commande "{intent}" a un cwd non valide : {detail}',
|
|
668
670
|
"run.error.cwdOutsideProjectDetail": "Le cwd de l’intention doit rester dans la racine actuelle.",
|
|
671
|
+
"run.error.maxOutputBytes": 'La commande "{intent}" a une valeur max_output_bytes non valide. {detail}',
|
|
672
|
+
"run.error.maxOutputBytesDetail": "La limite de sortie doit rester dans le maximum autorisé.",
|
|
669
673
|
"run.error.conflictingPreviewModes": "Utilisez --dry-run ou --plan-only, pas les deux",
|
|
670
674
|
"run.error.timedOut": 'La commande "{intent}" a expiré après {seconds} secondes',
|
|
671
675
|
"run.error.startFailed": 'Impossible de démarrer la commande "{intent}" : {message}',
|
|
@@ -727,6 +731,7 @@ Lisez ces fichiers avant de travailler :
|
|
|
727
731
|
"classify.source.changed": "fichiers modifies",
|
|
728
732
|
"classify.source.paths": "chemins explicites",
|
|
729
733
|
"classify.error.missingInput": "Indiquez --changed ou au moins un chemin",
|
|
734
|
+
"classify.error.changed_files_unavailable": "Impossible d'inspecter les fichiers modifies avec git status",
|
|
730
735
|
"classify.error.write_path_outside_root": "Le chemin du rapport de classification doit rester dans la racine mustflow",
|
|
731
736
|
"impact.help.summary": "Signale si les chemins modifies exigent une decision de version de paquet ou de modele sans modifier les fichiers.",
|
|
732
737
|
"impact.help.option.changed": "Lire les chemins depuis git status --short --untracked-files=all",
|
|
@@ -741,14 +746,16 @@ Lisez ces fichiers avant de travailler :
|
|
|
741
746
|
"impact.label.affectedVersionSources": "Sources de version affectees",
|
|
742
747
|
"impact.label.affectedSurfaces": "Surfaces affectees",
|
|
743
748
|
"impact.error.missingInput": "Indiquez --changed ou au moins un chemin",
|
|
749
|
+
"impact.error.changed_files_unavailable": "Impossible d'inspecter les fichiers modifies avec git status",
|
|
744
750
|
"verify.help.summary": "Exécute les intentions de vérification configurées sélectionnées par les métadonnées required_after.",
|
|
745
751
|
"verify.help.option.reason": "Sélectionne la raison required_after à vérifier",
|
|
746
752
|
"verify.help.option.fromClassification": "Lit les raisons de vérification depuis un rapport mf classify dans ce dépôt",
|
|
747
|
-
"verify.help.option.fromPlan": "Alias de compatibilité pour --from-classification",
|
|
753
|
+
"verify.help.option.fromPlan": "Alias de compatibilité obsolète pour --from-classification; il attend toujours un rapport mf classify",
|
|
748
754
|
"verify.help.option.changed": "Classe les changements Git actuels et vérifie les raisons correspondantes",
|
|
749
755
|
"verify.help.option.writePlan": "Option de compatibilité qui écrit le rapport de classification des changements",
|
|
750
756
|
"verify.help.option.reproEvidence": "Lit une preuve structurée de reproduction de bogue depuis un résumé JSON local au dépôt",
|
|
751
757
|
"verify.help.option.externalEvidence": "Lit une preuve CI externe de moindre autorité depuis un résumé JSON local au dépôt",
|
|
758
|
+
"verify.help.option.parallel": "Exécute les lots planifiés sûrs et sans conflit avec au plus ce nombre de commandes ; valeur par défaut : 1",
|
|
752
759
|
"verify.help.option.planOnly": "Affiche le plan de vérification sans exécuter de commandes; nécessite --json",
|
|
753
760
|
"verify.help.exit.ok": "Toutes les intentions de vérification sélectionnées ont réussi",
|
|
754
761
|
"verify.help.exit.fail": "La vérification a échoué, est partielle, est bloquée ou l'entrée est invalide",
|
|
@@ -763,11 +770,13 @@ Lisez ces fichiers avant de travailler :
|
|
|
763
770
|
"verify.error.planOnlyJson": "--plan-only nécessite --json",
|
|
764
771
|
"verify.error.reproEvidenceRequiresRun": "--repro-evidence ne peut pas être utilisé avec --plan-only",
|
|
765
772
|
"verify.error.externalEvidenceRequiresRun": "--external-evidence ne peut pas être utilisé avec --plan-only",
|
|
773
|
+
"verify.error.invalidParallel": "--parallel doit être un entier positif",
|
|
766
774
|
"verify.error.invalid_plan_file": "Le rapport de classification doit être un fichier JSON lisible",
|
|
767
775
|
"verify.error.unsupported_plan_source": "L'entrée de vérification doit être un rapport mf classify",
|
|
768
776
|
"verify.error.plan_root_mismatch": "Le rapport de classification doit venir de cette racine mustflow",
|
|
769
777
|
"verify.error.missing_plan_reasons": "Le rapport de classification doit inclure summary.validationReasons",
|
|
770
778
|
"verify.error.plan_path_outside_root": "Le chemin du rapport de classification doit rester dans la racine mustflow",
|
|
779
|
+
"verify.error.changed_files_unavailable": "Impossible d'inspecter les fichiers modifies avec git status",
|
|
771
780
|
"verify.error.invalid_repro_evidence_file": "La preuve de reproduction doit être un résumé JSON lisible avec des champs de preuve structurés",
|
|
772
781
|
"verify.error.unsupported_repro_evidence_source": "L'entrée de preuve de reproduction doit utiliser command repro-evidence",
|
|
773
782
|
"verify.error.invalid_external_evidence_file": "La preuve externe doit être un résumé JSON lisible avec checks",
|