mustflow 2.22.15 → 2.22.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/commands/check.js +1 -0
- package/dist/cli/commands/context.js +3 -3
- package/dist/cli/commands/doctor.js +17 -5
- package/dist/cli/commands/explain.js +65 -1
- package/dist/cli/commands/index.js +2 -2
- package/dist/cli/commands/run.js +20 -4
- package/dist/cli/commands/status.js +1 -1
- package/dist/cli/commands/verify.js +16 -9
- package/dist/cli/i18n/en.js +25 -0
- package/dist/cli/i18n/es.js +25 -0
- package/dist/cli/i18n/fr.js +25 -0
- package/dist/cli/i18n/hi.js +25 -0
- package/dist/cli/i18n/ko.js +25 -0
- package/dist/cli/i18n/zh.js +25 -0
- package/dist/cli/index.js +1 -0
- package/dist/cli/lib/filesystem.js +1 -1
- package/dist/cli/lib/git-changes.js +2 -0
- package/dist/cli/lib/local-index/index.js +1 -1
- package/dist/cli/lib/npm-version-check.js +22 -12
- package/dist/cli/lib/run-plan.js +20 -7
- package/dist/cli/lib/run-root-trust.js +33 -2
- package/dist/cli/lib/validation/test-selection.js +11 -1
- package/dist/core/active-run-locks.js +3 -1
- package/dist/core/command-intent-eligibility.js +7 -0
- package/dist/core/command-preconditions.js +27 -8
- package/dist/core/line-endings.js +2 -0
- package/dist/core/run-performance-history.js +20 -7
- package/dist/core/run-write-drift.js +12 -9
- package/dist/core/test-selection.js +13 -2
- package/dist/core/test-target-paths.js +17 -0
- package/dist/core/validation-ratchet.js +3 -1
- package/package.json +1 -1
- package/schemas/explain-report.schema.json +53 -0
- package/templates/default/i18n.toml +2 -2
- package/templates/default/locales/en/.mustflow/skills/security-privacy-review/SKILL.md +22 -7
- package/templates/default/locales/en/.mustflow/skills/security-regression-tests/SKILL.md +31 -20
- package/templates/default/manifest.toml +1 -1
|
@@ -86,10 +86,10 @@ export async function runContext(args, reporter, lang = 'en') {
|
|
|
86
86
|
}
|
|
87
87
|
const context = getAgentContext(mustflowRoot);
|
|
88
88
|
reporter.stdout(t(lang, 'context.title'));
|
|
89
|
-
reporter.stdout(`${t(lang, 'label.installed')}: ${context.installed ? 'yes' : 'no'}`);
|
|
89
|
+
reporter.stdout(`${t(lang, 'label.installed')}: ${context.installed ? t(lang, 'value.yes') : t(lang, 'value.no')}`);
|
|
90
90
|
reporter.stdout(`${t(lang, 'label.mustflowRoot')}: ${context.mustflow_root}`);
|
|
91
|
-
reporter.stdout(`${t(lang, 'label.commandContract')}: ${context.command_contract.exists ? 'present' : 'missing'}`);
|
|
91
|
+
reporter.stdout(`${t(lang, 'label.commandContract')}: ${context.command_contract.exists ? t(lang, 'value.present') : t(lang, 'value.missing')}`);
|
|
92
92
|
reporter.stdout(`${t(lang, 'label.runnableIntents')}: ${context.command_contract.runnable_intents.length}`);
|
|
93
|
-
reporter.stdout(`${t(lang, 'label.latestRun')}: ${context.latest_run.exists ? 'present' : 'missing'}`);
|
|
93
|
+
reporter.stdout(`${t(lang, 'label.latestRun')}: ${context.latest_run.exists ? t(lang, 'value.present') : t(lang, 'value.missing')}`);
|
|
94
94
|
return 0;
|
|
95
95
|
}
|
|
@@ -223,20 +223,32 @@ function getDiagnosticLabel(id, lang) {
|
|
|
223
223
|
return t(lang, 'doctor.diagnostic.latestRun');
|
|
224
224
|
}
|
|
225
225
|
}
|
|
226
|
+
function getDiagnosticStatusLabel(status, lang) {
|
|
227
|
+
switch (status) {
|
|
228
|
+
case 'ok':
|
|
229
|
+
return t(lang, 'doctor.status.ok');
|
|
230
|
+
case 'warn':
|
|
231
|
+
return t(lang, 'doctor.status.warn');
|
|
232
|
+
case 'fail':
|
|
233
|
+
return t(lang, 'doctor.status.fail');
|
|
234
|
+
case 'info':
|
|
235
|
+
return t(lang, 'doctor.status.info');
|
|
236
|
+
}
|
|
237
|
+
}
|
|
226
238
|
function renderDoctorOutput(output, lang) {
|
|
227
239
|
const lines = [];
|
|
228
240
|
lines.push(t(lang, 'doctor.title'));
|
|
229
241
|
lines.push(`${t(lang, 'label.mustflowRoot')}: ${output.mustflow_root}`);
|
|
230
|
-
lines.push(`${t(lang, 'label.installed')}: ${output.installed ? 'yes' : 'no'}`);
|
|
231
|
-
lines.push(`${t(lang, 'doctor.label.strict')}: ${output.strict ? 'yes' : 'no'}`);
|
|
232
|
-
lines.push(`${t(lang, 'doctor.label.check')}: ${output.check.ok ? 'passed' : 'failed'}`);
|
|
242
|
+
lines.push(`${t(lang, 'label.installed')}: ${output.installed ? t(lang, 'value.yes') : t(lang, 'value.no')}`);
|
|
243
|
+
lines.push(`${t(lang, 'doctor.label.strict')}: ${output.strict ? t(lang, 'value.yes') : t(lang, 'value.no')}`);
|
|
244
|
+
lines.push(`${t(lang, 'doctor.label.check')}: ${output.check.ok ? t(lang, 'value.passed') : t(lang, 'value.failed')}`);
|
|
233
245
|
lines.push(`${t(lang, 'doctor.label.issues')}: ${output.check.issue_count}`);
|
|
234
|
-
lines.push(`${t(lang, 'label.commandContract')}: ${output.context.command_contract_exists ? 'present' : 'missing'}`);
|
|
246
|
+
lines.push(`${t(lang, 'label.commandContract')}: ${output.context.command_contract_exists ? t(lang, 'value.present') : t(lang, 'value.missing')}`);
|
|
235
247
|
lines.push(`${t(lang, 'label.runnableIntents')}: ${output.context.runnable_intents.length}`);
|
|
236
248
|
lines.push('', t(lang, 'doctor.section.health'));
|
|
237
249
|
for (const diagnostic of output.diagnostics) {
|
|
238
250
|
const action = diagnostic.action && diagnostic.status !== 'ok' ? ` (${t(lang, 'doctor.actionLabel')}: ${diagnostic.action})` : '';
|
|
239
|
-
lines.push(`- [${diagnostic.status}] ${getDiagnosticLabel(diagnostic.id, lang)}: ${diagnostic.summary}${action}`);
|
|
251
|
+
lines.push(`- [${getDiagnosticStatusLabel(diagnostic.status, lang)}] ${getDiagnosticLabel(diagnostic.id, lang)}: ${diagnostic.summary}${action}`);
|
|
240
252
|
}
|
|
241
253
|
if (output.check.issues.length > 0) {
|
|
242
254
|
lines.push('', t(lang, 'doctor.section.issueList'));
|
|
@@ -14,11 +14,12 @@ import { explainSourceAnchor } from '../../core/source-anchor-explanation.js';
|
|
|
14
14
|
import { checkMustflowProject } from '../lib/validation.js';
|
|
15
15
|
import { readLocalCommandEffectGraph, readLocalPathSurface, } from '../lib/local-index.js';
|
|
16
16
|
import { explainVerifyArgErrorMessage, explainVerifyPlanErrorMessage, getVerifyExplainOutput, parseExplainVerifyArgs, readExplainVerifyPlanReasons, renderVerifyExplainDecision, } from './explain-verify.js';
|
|
17
|
+
import { createRunPlan, } from '../lib/run-plan.js';
|
|
17
18
|
const EXPLAIN_SCHEMA_VERSION = '1';
|
|
18
19
|
const LATEST_RUN_RECEIPT_RELATIVE_PATH = '.mustflow/state/runs/latest.json';
|
|
19
20
|
export function getExplainHelp(lang = 'en') {
|
|
20
21
|
return renderHelp({
|
|
21
|
-
usage: 'mf explain <topic> [target] [options] | mf explain verify --reason <event> [options] | mf explain why <target> [options]',
|
|
22
|
+
usage: 'mf explain <topic> [target] [options] | mf explain verify --reason <event> [options] | mf explain why <target> [options] | mf explain --why-blocked <intent> [options]',
|
|
22
23
|
summary: t(lang, 'explain.help.summary'),
|
|
23
24
|
options: [
|
|
24
25
|
{ label: '--json', description: t(lang, 'cli.option.json') },
|
|
@@ -33,6 +34,8 @@ export function getExplainHelp(lang = 'en') {
|
|
|
33
34
|
'mf explain asset-optimization --json',
|
|
34
35
|
'mf explain command test',
|
|
35
36
|
'mf explain command lint --json',
|
|
37
|
+
'mf explain --why-blocked deploy',
|
|
38
|
+
'mf explain --why-blocked lint --json',
|
|
36
39
|
'mf explain retention',
|
|
37
40
|
'mf explain retention --json',
|
|
38
41
|
'mf explain verify --reason code_change',
|
|
@@ -92,6 +95,43 @@ async function getCommandExplainOutput(projectRoot, commandName) {
|
|
|
92
95
|
decision: effectGraph ? { ...decision, effectGraph } : decision,
|
|
93
96
|
};
|
|
94
97
|
}
|
|
98
|
+
function getWhyBlockedExplainOutput(projectRoot, commandName) {
|
|
99
|
+
const contract = readCommandContract(projectRoot);
|
|
100
|
+
const plan = createRunPlan(projectRoot, contract, commandName);
|
|
101
|
+
const commandDecision = explainCommandIntent(contract, commandName, { projectRoot });
|
|
102
|
+
const blockedRunPlan = {
|
|
103
|
+
runnable: plan.ok,
|
|
104
|
+
reasonCode: plan.reasonCode,
|
|
105
|
+
detail: plan.detail,
|
|
106
|
+
status: plan.intentStatus,
|
|
107
|
+
lifecycle: plan.lifecycle,
|
|
108
|
+
runPolicy: plan.runPolicy,
|
|
109
|
+
configuredCwd: plan.configuredCwd,
|
|
110
|
+
timeoutSeconds: plan.timeoutSeconds,
|
|
111
|
+
mode: plan.mode,
|
|
112
|
+
writes: plan.writes ?? [],
|
|
113
|
+
suggestedIntentSnippet: plan.suggestedIntentSnippet,
|
|
114
|
+
};
|
|
115
|
+
const decision = {
|
|
116
|
+
...commandDecision,
|
|
117
|
+
decision: plan.ok
|
|
118
|
+
? `command intent "${commandName}" is not blocked for mf run`
|
|
119
|
+
: `command intent "${commandName}" is blocked for mf run`,
|
|
120
|
+
effectiveAction: plan.ok
|
|
121
|
+
? `Run mf run ${commandName} when this intent is required for the changed behavior.`
|
|
122
|
+
: plan.suggestedIntentSnippet
|
|
123
|
+
? 'Review the suggested command contract snippet before enabling agent execution.'
|
|
124
|
+
: commandDecision.effectiveAction,
|
|
125
|
+
blockedRunPlan,
|
|
126
|
+
};
|
|
127
|
+
return {
|
|
128
|
+
schema_version: EXPLAIN_SCHEMA_VERSION,
|
|
129
|
+
command: 'explain',
|
|
130
|
+
topic: 'why',
|
|
131
|
+
mustflow_root: projectRoot,
|
|
132
|
+
decision,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
95
135
|
function getRetentionExplainOutput(projectRoot) {
|
|
96
136
|
return {
|
|
97
137
|
schema_version: EXPLAIN_SCHEMA_VERSION,
|
|
@@ -393,6 +433,13 @@ function renderExplainDecision(output, lang) {
|
|
|
393
433
|
const latest = output.decision.latestFailure;
|
|
394
434
|
lines.push('', 'Latest run failure', `- path: ${latest.path}`, `- present: ${latest.present ? t(lang, 'value.yes') : t(lang, 'value.no')}`, `- valid: ${latest.valid ? t(lang, 'value.yes') : t(lang, 'value.no')}`, `- failed: ${latest.failed ? t(lang, 'value.yes') : t(lang, 'value.no')}`, `- status: ${latest.status ?? t(lang, 'value.none')}`, `- intent: ${latest.intent ?? t(lang, 'value.none')}`, `- exit_code: ${latest.exitCode ?? t(lang, 'value.none')}`, `- error_kind: ${latest.errorKind ?? t(lang, 'value.none')}`, `- duration_ms: ${latest.durationMs ?? t(lang, 'value.none')}`, `- summary: ${latest.summary}`);
|
|
395
435
|
}
|
|
436
|
+
if ('blockedRunPlan' in output.decision && output.decision.blockedRunPlan) {
|
|
437
|
+
const plan = output.decision.blockedRunPlan;
|
|
438
|
+
lines.push('', t(lang, 'explain.label.blockedRunPlan'), `- runnable: ${plan.runnable ? t(lang, 'value.yes') : t(lang, 'value.no')}`, `- reason_code: ${plan.reasonCode ?? t(lang, 'value.none')}`, `- detail: ${plan.detail ?? t(lang, 'value.none')}`, `- status: ${plan.status ?? t(lang, 'value.none')}`, `- lifecycle: ${plan.lifecycle ?? t(lang, 'value.none')}`, `- run_policy: ${plan.runPolicy ?? t(lang, 'value.none')}`, `- configured_cwd: ${plan.configuredCwd ?? t(lang, 'value.none')}`, `- timeout_seconds: ${plan.timeoutSeconds ?? t(lang, 'value.none')}`, `- mode: ${plan.mode ?? t(lang, 'value.none')}`, `- writes: ${plan.writes.join(', ') || t(lang, 'value.none')}`);
|
|
439
|
+
if (plan.suggestedIntentSnippet) {
|
|
440
|
+
lines.push('', `${t(lang, 'run.label.suggestedIntentSnippet')}:`, plan.suggestedIntentSnippet);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
396
443
|
if ('boundary' in output.decision) {
|
|
397
444
|
lines.push('', t(lang, 'explain.label.authorityBoundary'), `- role: ${output.decision.boundary.role}`);
|
|
398
445
|
if (output.decision.boundary.canDefine.length > 0) {
|
|
@@ -508,6 +555,23 @@ export async function runExplain(args, reporter, lang = 'en') {
|
|
|
508
555
|
const json = args.includes('--json');
|
|
509
556
|
const positional = args.filter((arg) => arg !== '--json');
|
|
510
557
|
const [topic, targetArg, ...rest] = positional;
|
|
558
|
+
if (topic === '--why-blocked') {
|
|
559
|
+
if (!targetArg) {
|
|
560
|
+
printUsageError(reporter, t(lang, 'explain.error.missingCommand'), 'mf explain --help', getExplainHelp(lang), lang);
|
|
561
|
+
return 1;
|
|
562
|
+
}
|
|
563
|
+
if (rest.length > 0) {
|
|
564
|
+
printUsageError(reporter, t(lang, 'cli.error.unexpectedArgument', { argument: rest[0] }), 'mf explain --help', getExplainHelp(lang), lang);
|
|
565
|
+
return 1;
|
|
566
|
+
}
|
|
567
|
+
const output = getWhyBlockedExplainOutput(resolveMustflowRoot(), targetArg);
|
|
568
|
+
if (json) {
|
|
569
|
+
reporter.stdout(JSON.stringify(output, null, 2));
|
|
570
|
+
return 0;
|
|
571
|
+
}
|
|
572
|
+
reporter.stdout(renderExplainDecision(output, lang));
|
|
573
|
+
return 0;
|
|
574
|
+
}
|
|
511
575
|
if (topic === 'why') {
|
|
512
576
|
const projectRoot = resolveMustflowRoot();
|
|
513
577
|
const output = await getWhyExplainOutput(projectRoot, targetArg, rest, lang, reporter);
|
|
@@ -58,8 +58,8 @@ function renderIndexSummary(result, lang) {
|
|
|
58
58
|
`source_anchors: ${result.source_anchor_count}`,
|
|
59
59
|
`source_anchor_risk_signals: ${result.source_anchor_risk_signal_count}`,
|
|
60
60
|
`index_mode: ${result.index_mode}`,
|
|
61
|
-
`reused_existing: ${result.reused_existing ? 'yes' : 'no'}`,
|
|
62
|
-
`${t(lang, 'label.wroteFiles')}: ${result.wrote_files ? 'yes' : 'no'}`,
|
|
61
|
+
`reused_existing: ${result.reused_existing ? t(lang, 'value.yes') : t(lang, 'value.no')}`,
|
|
62
|
+
`${t(lang, 'label.wroteFiles')}: ${result.wrote_files ? t(lang, 'value.yes') : t(lang, 'value.no')}`,
|
|
63
63
|
];
|
|
64
64
|
if (result.dry_run) {
|
|
65
65
|
lines.push(t(lang, 'index.dryRunNoFiles'));
|
package/dist/cli/commands/run.js
CHANGED
|
@@ -36,6 +36,9 @@ function reportRunPlanFailure(plan, reporter, lang) {
|
|
|
36
36
|
case 'stdin_not_closed':
|
|
37
37
|
message = t(lang, 'run.error.stdin', { intent: plan.intentName });
|
|
38
38
|
break;
|
|
39
|
+
case 'agent_shell_requires_allow':
|
|
40
|
+
message = t(lang, 'run.error.agentShellRequiresAllow', { intent: plan.intentName });
|
|
41
|
+
break;
|
|
39
42
|
case 'missing_timeout':
|
|
40
43
|
message = t(lang, 'run.error.timeout', { intent: plan.intentName });
|
|
41
44
|
break;
|
|
@@ -66,6 +69,12 @@ function reportRunPlanFailure(plan, reporter, lang) {
|
|
|
66
69
|
detail: getRunPlanDetail(plan, lang, 'run.error.cwdOutsideProjectDetail'),
|
|
67
70
|
});
|
|
68
71
|
break;
|
|
72
|
+
case 'invalid_test_target':
|
|
73
|
+
message = t(lang, 'run.error.invalidTestTarget', {
|
|
74
|
+
intent: plan.intentName,
|
|
75
|
+
detail: getRunPlanDetail(plan, lang, 'run.error.invalidTestTargetDetail'),
|
|
76
|
+
});
|
|
77
|
+
break;
|
|
69
78
|
case 'max_output_bytes_exceeds_limit':
|
|
70
79
|
message = t(lang, 'run.error.maxOutputBytes', {
|
|
71
80
|
intent: plan.intentName,
|
|
@@ -97,10 +106,16 @@ function createPlanCommandHash(plan) {
|
|
|
97
106
|
};
|
|
98
107
|
return `sha256:${createHash('sha256').update(JSON.stringify(payload)).digest('hex')}`;
|
|
99
108
|
}
|
|
100
|
-
function renderActiveLockConflictMessage(intentName, conflicts) {
|
|
109
|
+
function renderActiveLockConflictMessage(intentName, conflicts, lang) {
|
|
101
110
|
const [first] = conflicts;
|
|
102
|
-
const detail = first
|
|
103
|
-
|
|
111
|
+
const detail = first
|
|
112
|
+
? t(lang, 'run.error.activeLockConflictDetail', {
|
|
113
|
+
lock: first.lock,
|
|
114
|
+
intent: first.conflictsWithIntent,
|
|
115
|
+
pid: first.conflictsWithPid,
|
|
116
|
+
})
|
|
117
|
+
: t(lang, 'run.error.activeLockConflictUnknown');
|
|
118
|
+
return t(lang, 'run.error.activeLockConflict', { intent: intentName, detail });
|
|
104
119
|
}
|
|
105
120
|
export function getRunHelp(lang = 'en') {
|
|
106
121
|
return renderHelp({
|
|
@@ -205,7 +220,7 @@ export async function runRun(args, reporter, lang = 'en', options = {}) {
|
|
|
205
220
|
}
|
|
206
221
|
const activeRunLock = profiler.measure('active_lock_acquire', () => acquireActiveRunLock(projectRoot, contract, intentName, { commandHash: createPlanCommandHash(plan) }));
|
|
207
222
|
if (!activeRunLock.ok) {
|
|
208
|
-
reporter.stderr(renderCliError(renderActiveLockConflictMessage(intentName, activeRunLock.conflicts), 'mf run --dry-run --json', lang));
|
|
223
|
+
reporter.stderr(renderCliError(renderActiveLockConflictMessage(intentName, activeRunLock.conflicts, lang), 'mf run --dry-run --json', lang));
|
|
209
224
|
writeLatestProfile(profiler, options, {
|
|
210
225
|
projectRoot,
|
|
211
226
|
intent: intentName,
|
|
@@ -219,6 +234,7 @@ export async function runRun(args, reporter, lang = 'en', options = {}) {
|
|
|
219
234
|
const env = profiler.measure('environment', () => createCommandEnv(projectRoot, { policy: plan.envPolicy, allowlist: plan.envAllowlist }));
|
|
220
235
|
const writeTracker = profiler.measure('write_drift_before', () => startRunWriteTracking(projectRoot, contract, intentName, {
|
|
221
236
|
additionalDeclaredPaths: options.additionalDeclaredWritePaths,
|
|
237
|
+
env,
|
|
222
238
|
}));
|
|
223
239
|
const stdoutTailBytes = Math.min(runReceiptPolicy.stdoutTailBytes, plan.maxOutputBytes);
|
|
224
240
|
const stderrTailBytes = Math.min(runReceiptPolicy.stderrTailBytes, plan.maxOutputBytes);
|
|
@@ -53,7 +53,7 @@ export function runStatus(args, reporter, lang = 'en') {
|
|
|
53
53
|
return 0;
|
|
54
54
|
}
|
|
55
55
|
reporter.stdout(t(lang, 'status.title'));
|
|
56
|
-
reporter.stdout(`${t(lang, 'label.installed')}: ${status.installed ? 'yes' : 'no'}`);
|
|
56
|
+
reporter.stdout(`${t(lang, 'label.installed')}: ${status.installed ? t(lang, 'value.yes') : t(lang, 'value.no')}`);
|
|
57
57
|
reporter.stdout(`${t(lang, 'label.manifestLock')}: ${status.manifestLock}`);
|
|
58
58
|
reporter.stdout(`${t(lang, 'label.trackedFiles')}: ${status.trackedFiles}`);
|
|
59
59
|
reporter.stdout(`${t(lang, 'label.changedFiles')}: ${status.changedFiles.length}`);
|
|
@@ -11,6 +11,7 @@ import { createVerifyEvidenceModel } from '../../core/verification-evidence.js';
|
|
|
11
11
|
import { createScopeDiffRisks } from '../../core/scope-risk.js';
|
|
12
12
|
import { countValidationRatchetVerdictEffects, createValidationRatchetRisks, } from '../../core/validation-ratchet.js';
|
|
13
13
|
import { finishRunWriteBatchTracking, startRunWriteBatchTracking, } from '../../core/run-write-drift.js';
|
|
14
|
+
import { createCommandEnv } from '../../core/command-env.js';
|
|
14
15
|
import { readCommandContract } from '../../core/config-loading.js';
|
|
15
16
|
import { evaluateCommandPreconditions, } from '../../core/command-preconditions.js';
|
|
16
17
|
import { DEFAULT_VERIFY_PARALLELISM, parseVerifyArgs, resolveVerifyParallelism, } from './verify/args.js';
|
|
@@ -198,7 +199,7 @@ async function runVerificationEntriesInParallelChunks(projectRoot, entries, para
|
|
|
198
199
|
const results = [];
|
|
199
200
|
for (let index = 0; index < entries.length; index += parallelism) {
|
|
200
201
|
const chunk = entries.slice(index, index + parallelism);
|
|
201
|
-
const batchTracker = startRunWriteBatchTracking(projectRoot);
|
|
202
|
+
const batchTracker = startRunWriteBatchTracking(projectRoot, createCommandEnv(projectRoot, { policy: 'minimal', allowlist: [] }));
|
|
202
203
|
const chunkResults = await Promise.all(chunk.map((entry) => runVerificationIntent(entry.intent, lang, verificationPlanId, correlationId, scheduledTestTargets.get(entry.intent) ?? [])));
|
|
203
204
|
const writeDriftByIntent = finishRunWriteBatchTracking(batchTracker, chunk.map((entry) => ({
|
|
204
205
|
intentName: entry.intent,
|
|
@@ -919,18 +920,24 @@ function renderVerifyOutput(output, lang) {
|
|
|
919
920
|
`${t(lang, 'verify.label.reason')}: ${output.reason}`,
|
|
920
921
|
`${t(lang, 'verify.label.planSource')}: ${output.plan_source ?? t(lang, 'value.none')}`,
|
|
921
922
|
`${t(lang, 'verify.label.status')}: ${output.status}`,
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
923
|
+
`${t(lang, 'verify.label.completionVerdict')}: ${output.completion_verdict.status} (${output.completion_verdict.primary_reason})`,
|
|
924
|
+
`${t(lang, 'verify.label.matched')}: ${output.summary.matched}`,
|
|
925
|
+
`${t(lang, 'verify.label.ran')}: ${output.summary.ran}`,
|
|
926
|
+
`${t(lang, 'verify.label.passed')}: ${output.summary.passed}`,
|
|
927
|
+
`${t(lang, 'verify.label.failed')}: ${output.summary.failed}`,
|
|
928
|
+
`${t(lang, 'verify.label.skipped')}: ${output.summary.skipped}`,
|
|
928
929
|
];
|
|
929
930
|
if (output.parallelism) {
|
|
930
931
|
const cpuAvailable = output.parallelism.cpu_available ?? t(lang, 'value.none');
|
|
931
|
-
lines.push(
|
|
932
|
+
lines.push(`${t(lang, 'verify.label.parallelism')}: ${t(lang, 'verify.parallelism.summary', {
|
|
933
|
+
requested: output.parallelism.requested,
|
|
934
|
+
effective: output.parallelism.effective,
|
|
935
|
+
repositoryMax: output.parallelism.repository_max,
|
|
936
|
+
cpuAvailable,
|
|
937
|
+
mode: output.parallelism.mode,
|
|
938
|
+
})}`);
|
|
932
939
|
if (output.parallelism.capped) {
|
|
933
|
-
lines.push(
|
|
940
|
+
lines.push(`${t(lang, 'verify.label.parallelismNote')}: ${output.parallelism.note}`);
|
|
934
941
|
}
|
|
935
942
|
}
|
|
936
943
|
lines.push('', t(lang, 'verify.label.results'));
|
package/dist/cli/i18n/en.js
CHANGED
|
@@ -20,6 +20,10 @@ export const enMessages = {
|
|
|
20
20
|
"value.yes": "yes",
|
|
21
21
|
"value.no": "no",
|
|
22
22
|
"value.none": "none",
|
|
23
|
+
"value.present": "present",
|
|
24
|
+
"value.missing": "missing",
|
|
25
|
+
"value.passed": "passed",
|
|
26
|
+
"value.failed": "failed",
|
|
23
27
|
"command.adapters.summary": "Inspect host adapter compatibility without generating adapter files",
|
|
24
28
|
"command.init.summary": "Copy the default mustflow agent workflow",
|
|
25
29
|
"command.check.summary": "Validate mustflow files",
|
|
@@ -54,6 +58,7 @@ export const enMessages = {
|
|
|
54
58
|
"check.help.exit.fail": "Validation failed or the command received invalid input",
|
|
55
59
|
"check.result.passed": "mustflow check passed",
|
|
56
60
|
"check.result.strictPassed": "mustflow strict check passed",
|
|
61
|
+
"check.result.failed": "mustflow check failed: {count} issue(s) found.",
|
|
57
62
|
"contractLint.help.summary": "Inspect .mustflow/config/commands.toml for command-contract errors and warnings.",
|
|
58
63
|
"contractLint.help.option.coverage": "Also report required_after coverage for change-classification reasons",
|
|
59
64
|
"contractLint.help.option.suggest": "Suggest non-runnable intent snippets from package.json, Makefile, or justfile",
|
|
@@ -484,6 +489,10 @@ export const enMessages = {
|
|
|
484
489
|
"doctor.section.issueList": "Issue list:",
|
|
485
490
|
"doctor.section.suggestedCommands": "Suggested commands:",
|
|
486
491
|
"doctor.actionLabel": "run",
|
|
492
|
+
"doctor.status.ok": "ok",
|
|
493
|
+
"doctor.status.warn": "warn",
|
|
494
|
+
"doctor.status.fail": "fail",
|
|
495
|
+
"doctor.status.info": "info",
|
|
487
496
|
"doctor.diagnostic.install": "Install",
|
|
488
497
|
"doctor.diagnostic.validation": "Validation",
|
|
489
498
|
"doctor.diagnostic.skillRoutes": "Skill routes",
|
|
@@ -662,6 +671,7 @@ Read these files before working:
|
|
|
662
671
|
"run.error.lifecycleNotOneshot": 'Refused: command "{intent}" has lifecycle = "{lifecycle}"; mf run only executes oneshot commands',
|
|
663
672
|
"run.error.runPolicy": 'Command "{intent}" requires run_policy = "agent_allowed" for mf run',
|
|
664
673
|
"run.error.stdin": 'Command "{intent}" must set stdin = "closed"',
|
|
674
|
+
"run.error.agentShellRequiresAllow": 'Command "{intent}" must set allow_shell = true when mode = "shell"',
|
|
665
675
|
"run.error.timeout": 'Command "{intent}" must define timeout_seconds',
|
|
666
676
|
"run.error.commandSource": 'Command "{intent}" must define argv or mode = "shell" with cmd',
|
|
667
677
|
"run.error.unsafeIntent": 'Intent "{intent}" has an unsafe name. {detail}',
|
|
@@ -672,6 +682,8 @@ Read these files before working:
|
|
|
672
682
|
"run.error.blockedLongRunningCommandDetail": "Command argv must describe a finite one-shot command, not a development server, watcher, shell wrapper, interpreter loop, or background process.",
|
|
673
683
|
"run.error.cwdOutsideProject": 'Command "{intent}" has an invalid cwd: {detail}',
|
|
674
684
|
"run.error.cwdOutsideProjectDetail": "Intent cwd must stay inside the current root.",
|
|
685
|
+
"run.error.invalidTestTarget": 'Command "{intent}" received an invalid test target. {detail}',
|
|
686
|
+
"run.error.invalidTestTargetDetail": "Test targets must be relative file paths and cannot start with '-'.",
|
|
675
687
|
"run.error.maxOutputBytes": 'Command "{intent}" has invalid max_output_bytes. {detail}',
|
|
676
688
|
"run.error.maxOutputBytesDetail": "The output limit must stay within the allowed maximum.",
|
|
677
689
|
"run.error.conflictingPreviewModes": "Use either --dry-run or --plan-only, not both",
|
|
@@ -680,6 +692,9 @@ Read these files before working:
|
|
|
680
692
|
"run.error.timedOut": 'Command "{intent}" timed out after {seconds} seconds',
|
|
681
693
|
"run.error.outputLimitExceeded": 'Command "{intent}" exceeded max_output_bytes: {message}',
|
|
682
694
|
"run.error.startFailed": 'Command "{intent}" failed to start: {message}',
|
|
695
|
+
"run.error.activeLockConflict": "mf run {intent} is blocked by an active run lock: {detail}",
|
|
696
|
+
"run.error.activeLockConflictDetail": "{lock} conflicts with active intent {intent} (pid {pid})",
|
|
697
|
+
"run.error.activeLockConflictUnknown": "unknown active lock conflict",
|
|
683
698
|
"search.help.summary": "Search the local SQLite index for the mustflow workflow.",
|
|
684
699
|
"search.help.option.limit": "Set the number of results to print. Default: 10, max: 50",
|
|
685
700
|
"search.help.option.scope": "Select indexed workflow data, source anchors, or both. Default: workflow",
|
|
@@ -771,6 +786,15 @@ Read these files before working:
|
|
|
771
786
|
"verify.label.planSource": "Plan source",
|
|
772
787
|
"verify.label.status": "Status",
|
|
773
788
|
"verify.label.results": "Results",
|
|
789
|
+
"verify.label.completionVerdict": "Completion verdict",
|
|
790
|
+
"verify.label.matched": "Matched",
|
|
791
|
+
"verify.label.ran": "Ran",
|
|
792
|
+
"verify.label.passed": "Passed",
|
|
793
|
+
"verify.label.failed": "Failed",
|
|
794
|
+
"verify.label.skipped": "Skipped",
|
|
795
|
+
"verify.label.parallelism": "Parallelism",
|
|
796
|
+
"verify.label.parallelismNote": "Parallelism note",
|
|
797
|
+
"verify.parallelism.summary": "requested {requested}, effective {effective}, repository max {repositoryMax}, CPU available {cpuAvailable}, mode {mode}",
|
|
774
798
|
"verify.error.missingReason": "Missing verification reason",
|
|
775
799
|
"verify.error.conflictingInputs": "Use only one of --reason, --from-classification, --from-plan, or --changed",
|
|
776
800
|
"verify.error.writePlanRequiresChanged": "--write-plan requires --changed",
|
|
@@ -810,6 +834,7 @@ Read these files before working:
|
|
|
810
834
|
"explain.label.publicSurface": "Public surface",
|
|
811
835
|
"explain.label.validationReasons": "Validation reasons",
|
|
812
836
|
"explain.label.affectedContracts": "Affected contracts",
|
|
837
|
+
"explain.label.blockedRunPlan": "Blocked run plan",
|
|
813
838
|
"explain.error.missingTopic": "Missing explain topic",
|
|
814
839
|
"explain.error.missingCommand": "Missing command intent",
|
|
815
840
|
"explain.error.missingSkill": "Missing skill id",
|
package/dist/cli/i18n/es.js
CHANGED
|
@@ -20,6 +20,10 @@ export const esMessages = {
|
|
|
20
20
|
"value.yes": "sí",
|
|
21
21
|
"value.no": "no",
|
|
22
22
|
"value.none": "ninguno",
|
|
23
|
+
"value.present": "presente",
|
|
24
|
+
"value.missing": "faltante",
|
|
25
|
+
"value.passed": "superado",
|
|
26
|
+
"value.failed": "fallido",
|
|
23
27
|
"command.adapters.summary": "Inspecciona compatibilidad de adaptadores sin generar archivos",
|
|
24
28
|
"command.init.summary": "Copia el flujo de trabajo de agente mustflow predeterminado",
|
|
25
29
|
"command.check.summary": "Valida los archivos mustflow",
|
|
@@ -54,6 +58,7 @@ export const esMessages = {
|
|
|
54
58
|
"check.help.exit.fail": "La validación falló o el comando recibió una entrada no válida",
|
|
55
59
|
"check.result.passed": "comprobacion mustflow superada",
|
|
56
60
|
"check.result.strictPassed": "comprobacion estricta de mustflow superada",
|
|
61
|
+
"check.result.failed": "comprobacion mustflow fallida: se encontraron {count} problema(s).",
|
|
57
62
|
"contractLint.help.summary": "Inspecciona .mustflow/config/commands.toml para encontrar errores y advertencias del contrato de comandos.",
|
|
58
63
|
"contractLint.help.option.coverage": "También informa cobertura required_after para razones de clasificación de cambios",
|
|
59
64
|
"contractLint.help.option.suggest": "Sugiere fragmentos de intent no ejecutables desde package.json, Makefile o justfile",
|
|
@@ -484,6 +489,10 @@ export const esMessages = {
|
|
|
484
489
|
"doctor.section.issueList": "Lista de problemas:",
|
|
485
490
|
"doctor.section.suggestedCommands": "Comandos sugeridos:",
|
|
486
491
|
"doctor.actionLabel": "ejecutar",
|
|
492
|
+
"doctor.status.ok": "ok",
|
|
493
|
+
"doctor.status.warn": "advertencia",
|
|
494
|
+
"doctor.status.fail": "fallo",
|
|
495
|
+
"doctor.status.info": "info",
|
|
487
496
|
"doctor.diagnostic.install": "Instalación",
|
|
488
497
|
"doctor.diagnostic.validation": "Validación",
|
|
489
498
|
"doctor.diagnostic.skillRoutes": "Rutas de skills",
|
|
@@ -662,6 +671,7 @@ Lee estos archivos antes de trabajar:
|
|
|
662
671
|
"run.error.lifecycleNotOneshot": 'Rechazado: el comando "{intent}" tiene lifecycle = "{lifecycle}"; mf run sólo ejecuta comandos oneshot',
|
|
663
672
|
"run.error.runPolicy": 'El comando "{intent}" requiere run_policy = "agent_allowed" para mf run',
|
|
664
673
|
"run.error.stdin": 'El comando "{intent}" debe establecer stdin = "closed"',
|
|
674
|
+
"run.error.agentShellRequiresAllow": 'El comando "{intent}" debe establecer allow_shell = true cuando mode = "shell"',
|
|
665
675
|
"run.error.timeout": 'El comando "{intent}" debe definir timeout_seconds',
|
|
666
676
|
"run.error.commandSource": 'El comando "{intent}" debe definir argv o mode = "shell" con cmd',
|
|
667
677
|
"run.error.unsafeIntent": 'La intención "{intent}" tiene un nombre no seguro. {detail}',
|
|
@@ -672,6 +682,8 @@ Lee estos archivos antes de trabajar:
|
|
|
672
682
|
"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.",
|
|
673
683
|
"run.error.cwdOutsideProject": 'El comando "{intent}" tiene un cwd no válido: {detail}',
|
|
674
684
|
"run.error.cwdOutsideProjectDetail": "El cwd de la intención debe permanecer dentro de la raíz actual.",
|
|
685
|
+
"run.error.invalidTestTarget": 'El comando "{intent}" recibió un objetivo de prueba no válido. {detail}',
|
|
686
|
+
"run.error.invalidTestTargetDetail": "Los objetivos de prueba deben ser rutas relativas y no pueden empezar con '-'.",
|
|
675
687
|
"run.error.maxOutputBytes": 'El comando "{intent}" tiene max_output_bytes no válido. {detail}',
|
|
676
688
|
"run.error.maxOutputBytesDetail": "El límite de salida debe permanecer dentro del máximo permitido.",
|
|
677
689
|
"run.error.conflictingPreviewModes": "Usa --dry-run o --plan-only, no ambos",
|
|
@@ -680,6 +692,9 @@ Lee estos archivos antes de trabajar:
|
|
|
680
692
|
"run.error.timedOut": 'El comando "{intent}" agotó el tiempo después de {seconds} segundos',
|
|
681
693
|
"run.error.outputLimitExceeded": 'El comando "{intent}" superó max_output_bytes: {message}',
|
|
682
694
|
"run.error.startFailed": 'No se pudo iniciar el comando "{intent}": {message}',
|
|
695
|
+
"run.error.activeLockConflict": "mf run {intent} está bloqueado por un bloqueo de ejecución activo: {detail}",
|
|
696
|
+
"run.error.activeLockConflictDetail": "{lock} entra en conflicto con la intención activa {intent} (pid {pid})",
|
|
697
|
+
"run.error.activeLockConflictUnknown": "conflicto de bloqueo de ejecución activo desconocido",
|
|
683
698
|
"search.help.summary": "Busca en el índice SQLite local del flujo de trabajo mustflow.",
|
|
684
699
|
"search.help.option.limit": "Define la cantidad de resultados que se imprimen. Predeterminado: 10, máximo: 50",
|
|
685
700
|
"search.help.option.scope": "Selecciona datos del flujo de trabajo indexados, anchors de código fuente o ambos. Predeterminado: workflow",
|
|
@@ -771,6 +786,15 @@ Lee estos archivos antes de trabajar:
|
|
|
771
786
|
"verify.label.planSource": "Fuente del plan",
|
|
772
787
|
"verify.label.status": "Estado",
|
|
773
788
|
"verify.label.results": "Resultados",
|
|
789
|
+
"verify.label.completionVerdict": "Veredicto de finalización",
|
|
790
|
+
"verify.label.matched": "Coincidencias",
|
|
791
|
+
"verify.label.ran": "Ejecutadas",
|
|
792
|
+
"verify.label.passed": "Superadas",
|
|
793
|
+
"verify.label.failed": "Fallidas",
|
|
794
|
+
"verify.label.skipped": "Omitidas",
|
|
795
|
+
"verify.label.parallelism": "Paralelismo",
|
|
796
|
+
"verify.label.parallelismNote": "Nota de paralelismo",
|
|
797
|
+
"verify.parallelism.summary": "solicitado {requested}, efectivo {effective}, máximo del repositorio {repositoryMax}, CPU disponible {cpuAvailable}, modo {mode}",
|
|
774
798
|
"verify.error.missingReason": "Falta la razón de verificación",
|
|
775
799
|
"verify.error.conflictingInputs": "Usa solo uno de --reason, --from-classification, --from-plan o --changed",
|
|
776
800
|
"verify.error.writePlanRequiresChanged": "--write-plan requiere --changed",
|
|
@@ -810,6 +834,7 @@ Lee estos archivos antes de trabajar:
|
|
|
810
834
|
"explain.label.publicSurface": "Superficie publica",
|
|
811
835
|
"explain.label.validationReasons": "Razones de validacion",
|
|
812
836
|
"explain.label.affectedContracts": "Contratos afectados",
|
|
837
|
+
"explain.label.blockedRunPlan": "Plan de ejecución bloqueado",
|
|
813
838
|
"explain.error.missingTopic": "Falta el tema de explicación",
|
|
814
839
|
"explain.error.missingCommand": "Falta la intención de comando",
|
|
815
840
|
"explain.error.missingSkill": "Falta el id de skill",
|
package/dist/cli/i18n/fr.js
CHANGED
|
@@ -20,6 +20,10 @@ export const frMessages = {
|
|
|
20
20
|
"value.yes": "oui",
|
|
21
21
|
"value.no": "non",
|
|
22
22
|
"value.none": "aucun",
|
|
23
|
+
"value.present": "présent",
|
|
24
|
+
"value.missing": "manquant",
|
|
25
|
+
"value.passed": "réussi",
|
|
26
|
+
"value.failed": "échoué",
|
|
23
27
|
"command.adapters.summary": "Inspecte la compatibilité des adaptateurs sans générer de fichiers",
|
|
24
28
|
"command.init.summary": "Copie le flux de travail d'agent mustflow par défaut",
|
|
25
29
|
"command.check.summary": "Valide les fichiers mustflow",
|
|
@@ -54,6 +58,7 @@ export const frMessages = {
|
|
|
54
58
|
"check.help.exit.fail": "La validation a échoué ou la commande a reçu une entrée non valide",
|
|
55
59
|
"check.result.passed": "vérification mustflow réussie",
|
|
56
60
|
"check.result.strictPassed": "vérification stricte mustflow réussie",
|
|
61
|
+
"check.result.failed": "vérification mustflow échouée : {count} problème(s) trouvé(s).",
|
|
57
62
|
"contractLint.help.summary": "Inspecte .mustflow/config/commands.toml pour trouver les erreurs et avertissements du contrat de commandes.",
|
|
58
63
|
"contractLint.help.option.coverage": "Signale aussi la couverture required_after des raisons de classification",
|
|
59
64
|
"contractLint.help.option.suggest": "Suggère des fragments d'intent non exécutables depuis package.json, Makefile ou justfile",
|
|
@@ -484,6 +489,10 @@ export const frMessages = {
|
|
|
484
489
|
"doctor.section.issueList": "Liste des problèmes :",
|
|
485
490
|
"doctor.section.suggestedCommands": "Commandes suggérées :",
|
|
486
491
|
"doctor.actionLabel": "exécuter",
|
|
492
|
+
"doctor.status.ok": "ok",
|
|
493
|
+
"doctor.status.warn": "alerte",
|
|
494
|
+
"doctor.status.fail": "échec",
|
|
495
|
+
"doctor.status.info": "info",
|
|
487
496
|
"doctor.diagnostic.install": "Installation",
|
|
488
497
|
"doctor.diagnostic.validation": "Validation",
|
|
489
498
|
"doctor.diagnostic.skillRoutes": "Routage des skills",
|
|
@@ -662,6 +671,7 @@ Lisez ces fichiers avant de travailler :
|
|
|
662
671
|
"run.error.lifecycleNotOneshot": 'Refusé : la commande "{intent}" a lifecycle = "{lifecycle}" ; mf run exécute uniquement les commandes oneshot',
|
|
663
672
|
"run.error.runPolicy": 'La commande "{intent}" nécessite run_policy = "agent_allowed" pour mf run',
|
|
664
673
|
"run.error.stdin": 'La commande "{intent}" doit définir stdin = "closed"',
|
|
674
|
+
"run.error.agentShellRequiresAllow": 'La commande "{intent}" doit définir allow_shell = true lorsque mode = "shell"',
|
|
665
675
|
"run.error.timeout": 'La commande "{intent}" doit définir timeout_seconds',
|
|
666
676
|
"run.error.commandSource": 'La commande "{intent}" doit définir argv ou mode = "shell" avec cmd',
|
|
667
677
|
"run.error.unsafeIntent": 'L’intention "{intent}" a un nom non sûr. {detail}',
|
|
@@ -672,6 +682,8 @@ Lisez ces fichiers avant de travailler :
|
|
|
672
682
|
"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.",
|
|
673
683
|
"run.error.cwdOutsideProject": 'La commande "{intent}" a un cwd non valide : {detail}',
|
|
674
684
|
"run.error.cwdOutsideProjectDetail": "Le cwd de l’intention doit rester dans la racine actuelle.",
|
|
685
|
+
"run.error.invalidTestTarget": 'La commande "{intent}" a reçu une cible de test invalide. {detail}',
|
|
686
|
+
"run.error.invalidTestTargetDetail": "Les cibles de test doivent être des chemins relatifs et ne peuvent pas commencer par '-'.",
|
|
675
687
|
"run.error.maxOutputBytes": 'La commande "{intent}" a une valeur max_output_bytes non valide. {detail}',
|
|
676
688
|
"run.error.maxOutputBytesDetail": "La limite de sortie doit rester dans le maximum autorisé.",
|
|
677
689
|
"run.error.conflictingPreviewModes": "Utilisez --dry-run ou --plan-only, pas les deux",
|
|
@@ -680,6 +692,9 @@ Lisez ces fichiers avant de travailler :
|
|
|
680
692
|
"run.error.timedOut": 'La commande "{intent}" a expiré après {seconds} secondes',
|
|
681
693
|
"run.error.outputLimitExceeded": 'La commande "{intent}" a dépassé max_output_bytes : {message}',
|
|
682
694
|
"run.error.startFailed": 'Impossible de démarrer la commande "{intent}" : {message}',
|
|
695
|
+
"run.error.activeLockConflict": "mf run {intent} est bloqué par un verrou d'exécution actif : {detail}",
|
|
696
|
+
"run.error.activeLockConflictDetail": "{lock} entre en conflit avec l'intention active {intent} (pid {pid})",
|
|
697
|
+
"run.error.activeLockConflictUnknown": "conflit de verrou d'exécution actif inconnu",
|
|
683
698
|
"search.help.summary": "Recherche dans l'index SQLite local du flux de travail mustflow.",
|
|
684
699
|
"search.help.option.limit": "Définit le nombre de résultats à imprimer. Par défaut : 10, max : 50",
|
|
685
700
|
"search.help.option.scope": "Sélectionne les données de workflow indexées, les anchors de source, ou les deux. Par défaut : workflow",
|
|
@@ -771,6 +786,15 @@ Lisez ces fichiers avant de travailler :
|
|
|
771
786
|
"verify.label.planSource": "Source du plan",
|
|
772
787
|
"verify.label.status": "État",
|
|
773
788
|
"verify.label.results": "Résultats",
|
|
789
|
+
"verify.label.completionVerdict": "Verdict de complétion",
|
|
790
|
+
"verify.label.matched": "Correspondants",
|
|
791
|
+
"verify.label.ran": "Exécutés",
|
|
792
|
+
"verify.label.passed": "Réussis",
|
|
793
|
+
"verify.label.failed": "Échoués",
|
|
794
|
+
"verify.label.skipped": "Ignorés",
|
|
795
|
+
"verify.label.parallelism": "Parallélisme",
|
|
796
|
+
"verify.label.parallelismNote": "Note de parallélisme",
|
|
797
|
+
"verify.parallelism.summary": "demandé {requested}, effectif {effective}, maximum du dépôt {repositoryMax}, CPU disponible {cpuAvailable}, mode {mode}",
|
|
774
798
|
"verify.error.missingReason": "Raison de vérification manquante",
|
|
775
799
|
"verify.error.conflictingInputs": "Utilisez un seul de --reason, --from-classification, --from-plan ou --changed",
|
|
776
800
|
"verify.error.writePlanRequiresChanged": "--write-plan nécessite --changed",
|
|
@@ -810,6 +834,7 @@ Lisez ces fichiers avant de travailler :
|
|
|
810
834
|
"explain.label.publicSurface": "Surface publique",
|
|
811
835
|
"explain.label.validationReasons": "Raisons de validation",
|
|
812
836
|
"explain.label.affectedContracts": "Contrats affectes",
|
|
837
|
+
"explain.label.blockedRunPlan": "Plan d'exécution bloqué",
|
|
813
838
|
"explain.error.missingTopic": "Sujet d'explication manquant",
|
|
814
839
|
"explain.error.missingCommand": "Intention de commande manquante",
|
|
815
840
|
"explain.error.missingSkill": "Identifiant de skill manquant",
|