mustflow 2.69.0 → 2.74.0
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 +19 -5
- package/dist/cli/commands/api.js +17 -0
- package/dist/cli/commands/evidence.js +71 -0
- package/dist/cli/commands/script-pack.js +124 -0
- package/dist/cli/commands/verify.js +50 -15
- package/dist/cli/commands/workspace.js +2 -0
- package/dist/cli/i18n/en.js +38 -0
- package/dist/cli/i18n/es.js +38 -0
- package/dist/cli/i18n/fr.js +38 -0
- package/dist/cli/i18n/hi.js +38 -0
- package/dist/cli/i18n/ko.js +38 -0
- package/dist/cli/i18n/zh.js +38 -0
- package/dist/cli/index.js +1 -0
- package/dist/cli/lib/agent-context.js +179 -10
- package/dist/cli/lib/command-registry.js +6 -0
- package/dist/cli/lib/dashboard-export.js +1 -0
- package/dist/cli/lib/script-pack-registry.js +27 -0
- package/dist/cli/script-packs/core-text-budget.js +241 -0
- package/dist/core/change-verification.js +10 -0
- package/dist/core/completion-verdict.js +14 -1
- package/dist/core/complexity-budget.js +206 -0
- package/dist/core/conflict-ledger.js +122 -0
- package/dist/core/failure-replay-capsule.js +213 -0
- package/dist/core/public-json-contracts.js +27 -0
- package/dist/core/risk-priced-evidence.js +213 -0
- package/dist/core/script-check-result.js +1 -0
- package/dist/core/text-budget.js +262 -0
- package/dist/core/verification-evidence.js +61 -13
- package/package.json +1 -1
- package/schemas/README.md +23 -11
- package/schemas/change-verification-report.schema.json +29 -0
- package/schemas/context-report.schema.json +58 -2
- package/schemas/dashboard-export.schema.json +42 -1
- package/schemas/diff-risk.schema.json +6 -0
- package/schemas/evidence-report.schema.json +45 -0
- package/schemas/latest-run-pointer.schema.json +50 -1
- package/schemas/script-pack-catalog.schema.json +68 -0
- package/schemas/text-budget-report.schema.json +131 -0
- package/schemas/verification-plan.schema.json +32 -0
- package/schemas/verify-report.schema.json +360 -1
- package/schemas/verify-run-manifest.schema.json +50 -1
- package/schemas/workspace-verification-plan.schema.json +32 -0
- package/templates/default/i18n.toml +8 -2
- package/templates/default/locales/en/.mustflow/skills/INDEX.md +3 -2
- package/templates/default/locales/en/.mustflow/skills/adapter-boundary/SKILL.md +19 -2
- package/templates/default/locales/en/.mustflow/skills/design-implementation-handoff/SKILL.md +250 -0
- package/templates/default/locales/en/.mustflow/skills/routes.toml +7 -1
- package/templates/default/manifest.toml +8 -1
package/README.md
CHANGED
|
@@ -123,8 +123,16 @@ mustflow installs and validates an agent workflow for user projects.
|
|
|
123
123
|
- Reports host adapter compatibility with `mf adapters status` without generating host-specific files or treating them as command authority.
|
|
124
124
|
- Classifies changed files, public surfaces, and validation reasons with `mf classify`.
|
|
125
125
|
- Inspects changed files for quality-gaming patterns such as line stuffing, suppressions, test bypass markers, type escapes, and placeholder implementations with `mf quality check`.
|
|
126
|
-
- Prints execution-free verification plans with `mf verify --plan-only --json`, including a machine-readable verification decision graph and read-only local-index lock explanations when available.
|
|
126
|
+
- Prints execution-free verification plans with `mf verify --plan-only --json`, including a risk-priced evidence assessment, machine-readable verification decision graph, and read-only local-index lock explanations when available.
|
|
127
|
+
- Reports a read-only complexity budget in `mf api diff-risk --changed --json`, `mf verify`
|
|
128
|
+
evidence, and dashboard exports so agents justify new dependencies, helper-style surfaces,
|
|
129
|
+
config/schema churn, and broad structural changes before treating added complexity as free.
|
|
130
|
+
- Lists and runs bundled utility scripts through `mf script-pack`, including `core/text-budget` for
|
|
131
|
+
exact file and JSON-field length budgets, so future checks do not sprawl into top-level commands.
|
|
132
|
+
- Prints context trust metadata in `mf context --json` and prompt-cache bundles so agents can distinguish binding instructions, command contracts, contextual hints, generated evidence, and volatile runtime data before using them.
|
|
127
133
|
- Runs only allowed one-shot commands within a timeout via `mf run <intent>` or `mf verify` when the selected intent is runnable.
|
|
134
|
+
- Records blockers, contradictions, verification gaps, and remaining risks as a structured conflict ledger in verify, evidence, and dashboard reports.
|
|
135
|
+
- Stores bounded failure replay capsules for failed `mf verify` runs so future agents can reproduce the intent, receipt, command fingerprint, and changed-file state without copying raw command output.
|
|
128
136
|
- Writes command receipts under `.mustflow/state/runs/run-*` and atomically updates `.mustflow/state/runs/latest.json`.
|
|
129
137
|
- Generates a concise repository navigation map, `REPO_MAP.md`, with `mf map`.
|
|
130
138
|
- Indexes and searches mustflow docs, skills, skill routes, command rules, command-effect locks, file fingerprints, and opt-in source anchor metadata with SQLite via `mf index` and `mf search`. The local SQLite file is a rebuildable lookup cache, not a memory store, audit log, command transcript store, command-authority source, or source-content database.
|
|
@@ -251,7 +259,7 @@ mf run mustflow_update_apply
|
|
|
251
259
|
| `mf contract-lint` | Inspect `.mustflow/config/commands.toml` for command-contract errors and warnings without running commands. Add `--suggest` to print non-runnable candidate snippets from existing command files. |
|
|
252
260
|
| `mf onboard commands` | Suggest review-only command-intent snippets from package.json, Makefile, or justfile without writing files or granting command authority. |
|
|
253
261
|
| `mf next` | Inspect install state, changed files, verification coverage, and command-contract gaps, then print the next safe mustflow action without running commands. |
|
|
254
|
-
| `mf evidence` | Summarize changed-file verification requirements,
|
|
262
|
+
| `mf evidence` | Summarize changed-file verification requirements, risk-priced evidence assessment, latest failure replay capsule, conflict ledger, receipts, remaining risks, and gaps without running commands. |
|
|
255
263
|
| `mf workspace status` | Inspect configured workspace roots and nested repository contract readiness without granting parent-to-child command authority. |
|
|
256
264
|
| `mf workspace command-catalog` | Aggregate per-repository command intent availability with safe `mf run` entrypoints and no raw command strings. |
|
|
257
265
|
| `mf workspace verify --changed --plan-only` | Aggregate per-repository changed-file verification plans without running commands or granting parent-to-child command authority. |
|
|
@@ -260,7 +268,7 @@ mf run mustflow_update_apply
|
|
|
260
268
|
| `mf api command-catalog --json` | Print command intent availability and safe `mf run` entrypoints without exposing raw command strings. |
|
|
261
269
|
| `mf api verification-plan --changed --json` | Print a stable, read-only verification plan for changed files without executing commands. |
|
|
262
270
|
| `mf api latest-evidence --json` | Print bounded latest run or verify evidence without raw command output. |
|
|
263
|
-
| `mf api diff-risk --changed --json` | Print a compact changed-file risk, verification summary,
|
|
271
|
+
| `mf api diff-risk --changed --json` | Print a compact changed-file risk, verification summary, read-only complexity budget, and residual correction signals. |
|
|
264
272
|
| `mf api health --json` | Print a compact workspace health report for quick agent gating. |
|
|
265
273
|
| `mf api locks --json` | Print active `mf run` locks for multi-session coordination. |
|
|
266
274
|
| `mf api serve --stdio` | Serve the same read-only API reports as newline-delimited JSON responses over stdin/stdout. |
|
|
@@ -269,12 +277,15 @@ mf run mustflow_update_apply
|
|
|
269
277
|
| `mf docs review comment <path>` | Add multiline review guidance to an existing queue entry. |
|
|
270
278
|
| `mf docs review approve <path>` | Mark review complete and hide the document from the default queue. |
|
|
271
279
|
| `mf handoff validate <path>` | Validate a restricted work-item or handoff JSON record without writing files. |
|
|
272
|
-
| `mf context --json` | Print read order, command rules, available capabilities, and recent run summary as JSON. |
|
|
280
|
+
| `mf context --json` | Print read order, command rules, context trust metadata, available capabilities, prompt-cache bundles, and recent run summary as JSON. |
|
|
273
281
|
| `mf skill route` | Resolve compact skill route candidates from task text, paths, and reasons before reading selected skill documents. |
|
|
274
282
|
| `mf map --stdout` | Print the current mustflow root map to stdout. |
|
|
275
283
|
| `mf map --write` | Create or update `REPO_MAP.md`. |
|
|
276
284
|
| `mf quality check` | Inspect changed files for quality-gaming patterns without writing files. |
|
|
277
285
|
| `mf quality check --all` | Inspect every tracked text file for quality-gaming patterns. |
|
|
286
|
+
| `mf script-pack list` | List bundled script packs and script refs such as `core/text-budget`. |
|
|
287
|
+
| `mf script-pack run core/text-budget check <path...> --max <count>` | Check exact text length budgets for files using grapheme counts by default. |
|
|
288
|
+
| `mf script-pack run core/text-budget check package.json --json-pointer /description --max <count> --json` | Check a JSON string field and print the stable report schema. |
|
|
278
289
|
| `mf run <intent>` | Run an allowed one-shot command. |
|
|
279
290
|
| `mf run <intent> --wait` | Wait for conflicting active run locks before executing the command. |
|
|
280
291
|
| `mf run <intent> --dry-run --json` | Preview whether an intent is runnable and what command metadata would be used, without executing it. |
|
|
@@ -300,6 +311,9 @@ mf run mustflow_update_apply
|
|
|
300
311
|
|
|
301
312
|
Automation and agents should use `--json` output or `mf api serve --stdio` JSONL responses instead of parsing human-facing text. Published JSON Schemas for stable outputs live in `schemas/`.
|
|
302
313
|
|
|
314
|
+
`core/text-budget` counts `line` units by splitting text on line breaks; a trailing line break
|
|
315
|
+
therefore contributes an empty final line.
|
|
316
|
+
|
|
303
317
|
## Command execution policy
|
|
304
318
|
|
|
305
319
|
Runnable work is declared in `.mustflow/config/commands.toml` so agents do not guess commands.
|
|
@@ -318,7 +332,7 @@ Development servers, watch modes, browser UIs, interactive commands, and backgro
|
|
|
318
332
|
|
|
319
333
|
Command environments remove the project-local `node_modules/.bin` path from `PATH` by default. If an intent needs a project dependency binary such as `eslint`, `tsc`, or `vitest`, declare it through the package manager, for example `npm exec eslint -- ...`, `pnpm exec tsc -- --noEmit`, `bun x eslint ...`, or `yarn exec eslint ...`. `mf check --strict` warns when an agent-runnable intent uses a bare executable name that appears under the project-local `.bin` directory, except for names listed in `defaults.allow_project_local_bin_bare_executables`. `mf run` may resolve those allowed names directly from the local `.bin` directory without exposing every local binary through `PATH`. The installed template allows `mf` and `mustflow` by default. Intent-level `allow_env_inheritance_risks = true` is available when a command intentionally uses `env_policy = "inherit"`.
|
|
320
334
|
|
|
321
|
-
Use `mf verify --reason <event> --plan-only --json` to inspect matching verification intents, command eligibility, remaining gaps, and missing runnable coverage without executing commands. Use `mf run <intent> --dry-run --json` to inspect one resolved command intent without spawning a process or writing a run receipt. Plan-only verification includes a `decision_graph` that connects changed surfaces, classification reasons, command candidates, eligibility checks, effects, and gaps. When `.mustflow/cache/mustflow.sqlite` is fresh, scheduled entries also include read-only `effectGraph` metadata for write locks and lock conflicts. These graph rows are marked `explanation_only` and never grant command authority; `.mustflow/config/commands.toml` remains the only runnable command source.
|
|
335
|
+
Use `mf verify --reason <event> --plan-only --json` to inspect matching verification intents, command eligibility, risk-priced evidence requirements, remaining gaps, and missing runnable coverage without executing commands. Use `mf run <intent> --dry-run --json` to inspect one resolved command intent without spawning a process or writing a run receipt. Plan-only verification includes a `decision_graph` that connects changed surfaces, classification reasons, command candidates, eligibility checks, effects, and gaps. When `.mustflow/cache/mustflow.sqlite` is fresh, scheduled entries also include read-only `effectGraph` metadata for write locks and lock conflicts. These graph rows are marked `explanation_only` and never grant command authority; `.mustflow/config/commands.toml` remains the only runnable command source.
|
|
322
336
|
|
|
323
337
|
Each executed command run writes a run record under `.mustflow/state/runs/run-*` and atomically updates `.mustflow/state/runs/latest.json`. The record includes the intent name, working directory, timeout, exit code, timeout status, and the tail of stdout and stderr.
|
|
324
338
|
|
package/dist/cli/commands/api.js
CHANGED
|
@@ -7,6 +7,7 @@ import { runApiServe } from './api/serve.js';
|
|
|
7
7
|
import { createRecommendedNextCommands } from './api/workspace-recommendations.js';
|
|
8
8
|
import { listActiveRunLocks } from '../../core/active-run-locks.js';
|
|
9
9
|
import { createChangeVerificationReport, } from '../../core/change-verification.js';
|
|
10
|
+
import { createComplexityBudgetReport, } from '../../core/complexity-budget.js';
|
|
10
11
|
import { readUtf8FileInsideWithoutSymlinks } from '../../core/safe-filesystem.js';
|
|
11
12
|
import { createVerificationPlanId } from '../../core/verification-plan-id.js';
|
|
12
13
|
import { printUsageError, renderHelp } from '../lib/cli-output.js';
|
|
@@ -422,6 +423,7 @@ function createUnavailableVerificationPlanOutput(mustflowRoot, classification, i
|
|
|
422
423
|
requirements: [],
|
|
423
424
|
candidates: [],
|
|
424
425
|
gaps: [],
|
|
426
|
+
risk_assessment: null,
|
|
425
427
|
schedule: null,
|
|
426
428
|
test_selection: null,
|
|
427
429
|
execution_policy: createVerificationPlanExecutionPolicy(),
|
|
@@ -479,6 +481,7 @@ function createVerificationPlanOutput() {
|
|
|
479
481
|
surfaces: gap.surfaces,
|
|
480
482
|
detail: gap.detail,
|
|
481
483
|
})),
|
|
484
|
+
risk_assessment: report.risk_assessment,
|
|
482
485
|
schedule: toVerificationPlanSchedule(report),
|
|
483
486
|
test_selection: toVerificationPlanTestSelection(report),
|
|
484
487
|
execution_policy: createVerificationPlanExecutionPolicy(),
|
|
@@ -614,6 +617,14 @@ function getRiskLevel(classification, report) {
|
|
|
614
617
|
if (classification.summary.fileCount === 0) {
|
|
615
618
|
return 'none';
|
|
616
619
|
}
|
|
620
|
+
if (report.risk_assessment.level === 'critical') {
|
|
621
|
+
return 'high';
|
|
622
|
+
}
|
|
623
|
+
if (report.risk_assessment.level === 'high' ||
|
|
624
|
+
report.risk_assessment.level === 'medium' ||
|
|
625
|
+
report.risk_assessment.level === 'low') {
|
|
626
|
+
return report.risk_assessment.level;
|
|
627
|
+
}
|
|
617
628
|
const reasons = new Set(classification.summary.validationReasons);
|
|
618
629
|
if (report.gaps.length > 0 ||
|
|
619
630
|
classification.summary.publicSurfaceCount > 0 ||
|
|
@@ -794,6 +805,7 @@ function createDiffRiskOutput() {
|
|
|
794
805
|
update_policies: [],
|
|
795
806
|
drift_checks: [],
|
|
796
807
|
required_verification: [],
|
|
808
|
+
complexity_budget: null,
|
|
797
809
|
residual_corrections: createResidualCorrections(mustflowRoot, null),
|
|
798
810
|
gap_count: 0,
|
|
799
811
|
gaps: [],
|
|
@@ -820,6 +832,10 @@ function createDiffRiskOutput() {
|
|
|
820
832
|
}
|
|
821
833
|
const requiredVerification = report ? report.schedule.entries.map((entry) => entry.intent) : [];
|
|
822
834
|
const verificationPlanId = report && contract ? createVerificationPlanId(report, contract) : null;
|
|
835
|
+
const complexityBudget = createComplexityBudgetReport({
|
|
836
|
+
files: classification.files,
|
|
837
|
+
summary: classification.summary,
|
|
838
|
+
});
|
|
823
839
|
return {
|
|
824
840
|
schema_version: API_DIFF_RISK_SCHEMA_VERSION,
|
|
825
841
|
command: 'api diff-risk',
|
|
@@ -834,6 +850,7 @@ function createDiffRiskOutput() {
|
|
|
834
850
|
update_policies: classification.summary.updatePolicies,
|
|
835
851
|
drift_checks: classification.summary.driftChecks,
|
|
836
852
|
required_verification: requiredVerification,
|
|
853
|
+
complexity_budget: complexityBudget,
|
|
837
854
|
residual_corrections: createResidualCorrections(mustflowRoot, verificationPlanId),
|
|
838
855
|
gap_count: report?.gaps.length ?? 0,
|
|
839
856
|
gaps: report?.gaps.map((gap) => ({
|
|
@@ -234,6 +234,7 @@ function createPlanFromReport(report, contract, classification, latest) {
|
|
|
234
234
|
changed_files: classification.files,
|
|
235
235
|
validation_reasons: classification.summary.validationReasons,
|
|
236
236
|
selected_intents: report.schedule.entries.map((entry) => entry.intent),
|
|
237
|
+
risk_assessment: report.risk_assessment,
|
|
237
238
|
requirement_count: requirements.length,
|
|
238
239
|
gap_count: gaps.length,
|
|
239
240
|
requirements,
|
|
@@ -278,6 +279,7 @@ function unavailablePlan(source, error, classification = null) {
|
|
|
278
279
|
changed_files: classification?.files ?? [],
|
|
279
280
|
validation_reasons: classification?.summary.validationReasons ?? [],
|
|
280
281
|
selected_intents: [],
|
|
282
|
+
risk_assessment: fallbackRiskAssessment('Plan unavailable; risk assessment could not be computed.'),
|
|
281
283
|
requirement_count: 0,
|
|
282
284
|
gap_count: 0,
|
|
283
285
|
requirements: [],
|
|
@@ -304,6 +306,7 @@ function createPlanFromFile(mustflowRoot, planPath, latest) {
|
|
|
304
306
|
const schedule = isRecord(parsed.schedule) ? parsed.schedule : null;
|
|
305
307
|
const testSelection = isRecord(parsed.test_selection) ? parsed.test_selection : null;
|
|
306
308
|
const classification = isRecord(parsed.classification) ? parsed.classification : null;
|
|
309
|
+
const riskAssessment = readRiskAssessment(parsed.risk_assessment);
|
|
307
310
|
const selectedIntents = schedule
|
|
308
311
|
? uniqueSorted([
|
|
309
312
|
...readStringArrayField(schedule, 'selected_intents'),
|
|
@@ -324,6 +327,7 @@ function createPlanFromFile(mustflowRoot, planPath, latest) {
|
|
|
324
327
|
changed_files: classification ? readStringArrayField(classification, 'files') : readStringArrayField(parsed, 'files'),
|
|
325
328
|
validation_reasons: classification ? readStringArrayField(classification, 'validation_reasons') : [],
|
|
326
329
|
selected_intents: selectedIntents,
|
|
330
|
+
risk_assessment: riskAssessment ?? fallbackRiskAssessment('Plan file does not include risk_assessment.'),
|
|
327
331
|
requirement_count: requirementReports.length,
|
|
328
332
|
gap_count: gaps.length,
|
|
329
333
|
requirements: requirementReports,
|
|
@@ -371,6 +375,62 @@ function readLatestRequirement(record) {
|
|
|
371
375
|
skipped_intents: readStringArrayField(record, 'skipped_intents'),
|
|
372
376
|
};
|
|
373
377
|
}
|
|
378
|
+
function isRiskLevel(value) {
|
|
379
|
+
return value === 'low' || value === 'medium' || value === 'high' || value === 'critical';
|
|
380
|
+
}
|
|
381
|
+
function readRiskAssessment(value) {
|
|
382
|
+
if (!isRecord(value)) {
|
|
383
|
+
return null;
|
|
384
|
+
}
|
|
385
|
+
const level = readString(value, 'level');
|
|
386
|
+
if (value.schema_version !== '1' || value.source !== 'change_classification_and_command_contract' || !isRiskLevel(level)) {
|
|
387
|
+
return null;
|
|
388
|
+
}
|
|
389
|
+
return {
|
|
390
|
+
schema_version: '1',
|
|
391
|
+
source: 'change_classification_and_command_contract',
|
|
392
|
+
level,
|
|
393
|
+
reasons: readStringArrayField(value, 'reasons'),
|
|
394
|
+
required_evidence: readStringArrayField(value, 'required_evidence'),
|
|
395
|
+
blocking_gaps: readStringArrayField(value, 'blocking_gaps'),
|
|
396
|
+
rollback_required: readBooleanField(value, 'rollback_required') ?? false,
|
|
397
|
+
human_approval_required: readBooleanField(value, 'human_approval_required') ?? false,
|
|
398
|
+
manual_review_required: readBooleanField(value, 'manual_review_required') ?? false,
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
function readFailureReplayCapsule(value) {
|
|
402
|
+
if (!isRecord(value)) {
|
|
403
|
+
return null;
|
|
404
|
+
}
|
|
405
|
+
if (value.schema_version !== '1' ||
|
|
406
|
+
value.source !== 'mf_verify_failure' ||
|
|
407
|
+
value.authority !== 'replay_supporting_evidence') {
|
|
408
|
+
return null;
|
|
409
|
+
}
|
|
410
|
+
return value;
|
|
411
|
+
}
|
|
412
|
+
function readConflictLedger(value) {
|
|
413
|
+
if (!isRecord(value)) {
|
|
414
|
+
return null;
|
|
415
|
+
}
|
|
416
|
+
if (value.schema_version !== '1' || value.source !== 'verification_evidence_model' || !Array.isArray(value.items)) {
|
|
417
|
+
return null;
|
|
418
|
+
}
|
|
419
|
+
return value;
|
|
420
|
+
}
|
|
421
|
+
function fallbackRiskAssessment(reason) {
|
|
422
|
+
return {
|
|
423
|
+
schema_version: '1',
|
|
424
|
+
source: 'change_classification_and_command_contract',
|
|
425
|
+
level: 'low',
|
|
426
|
+
reasons: [reason],
|
|
427
|
+
required_evidence: ['changed_file_review'],
|
|
428
|
+
blocking_gaps: [],
|
|
429
|
+
rollback_required: false,
|
|
430
|
+
human_approval_required: false,
|
|
431
|
+
manual_review_required: false,
|
|
432
|
+
};
|
|
433
|
+
}
|
|
374
434
|
function createLatestReport(mustflowRoot, expectedPlanId, requested) {
|
|
375
435
|
if (!requested) {
|
|
376
436
|
return latestNotRequested();
|
|
@@ -392,6 +452,11 @@ function createLatestReport(mustflowRoot, expectedPlanId, requested) {
|
|
|
392
452
|
}
|
|
393
453
|
const evidenceModel = isRecord(parsed.evidence_model) ? parsed.evidence_model : null;
|
|
394
454
|
const completionVerdict = isRecord(parsed.completion_verdict) ? parsed.completion_verdict : null;
|
|
455
|
+
const latestRiskAssessment = readRiskAssessment(parsed.risk_assessment) ?? (evidenceModel ? readRiskAssessment(evidenceModel.risk_assessment) : null);
|
|
456
|
+
const failureReplayCapsule = readFailureReplayCapsule(parsed.failure_replay_capsule) ??
|
|
457
|
+
(evidenceModel ? readFailureReplayCapsule(evidenceModel.failure_replay_capsule) : null);
|
|
458
|
+
const conflictLedger = readConflictLedger(parsed.conflict_ledger) ??
|
|
459
|
+
(evidenceModel ? readConflictLedger(evidenceModel.conflict_ledger) : null);
|
|
395
460
|
const requirements = evidenceModel ? recordArray(evidenceModel.requirements).map(readLatestRequirement) : [];
|
|
396
461
|
const receipts = evidenceModel ? recordArray(evidenceModel.receipts).map(readLatestReceipt) : [];
|
|
397
462
|
const skippedChecks = evidenceModel ? recordArray(evidenceModel.skipped_checks).map(toGapReport) : [];
|
|
@@ -408,6 +473,9 @@ function createLatestReport(mustflowRoot, expectedPlanId, requested) {
|
|
|
408
473
|
receipt_count: receipts.length,
|
|
409
474
|
skipped_check_count: skippedChecks.length,
|
|
410
475
|
remaining_risk_count: remainingRisks.length,
|
|
476
|
+
risk_assessment: latestRiskAssessment,
|
|
477
|
+
failure_replay_capsule: failureReplayCapsule,
|
|
478
|
+
conflict_ledger: conflictLedger,
|
|
411
479
|
requirements,
|
|
412
480
|
receipts,
|
|
413
481
|
skipped_checks: skippedChecks,
|
|
@@ -428,6 +496,9 @@ function latestEmpty(status) {
|
|
|
428
496
|
receipt_count: null,
|
|
429
497
|
skipped_check_count: 0,
|
|
430
498
|
remaining_risk_count: 0,
|
|
499
|
+
risk_assessment: null,
|
|
500
|
+
failure_replay_capsule: null,
|
|
501
|
+
conflict_ledger: null,
|
|
431
502
|
requirements: [],
|
|
432
503
|
receipts: [],
|
|
433
504
|
skipped_checks: [],
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { printUsageError, renderHelp } from '../lib/cli-output.js';
|
|
2
|
+
import { t } from '../lib/i18n.js';
|
|
3
|
+
import { formatCliOptionParseError, hasCliOptionToken, hasParsedCliOption, parseCliOptions, } from '../lib/option-parser.js';
|
|
4
|
+
import { resolveMustflowRoot } from '../lib/project-root.js';
|
|
5
|
+
import { findScriptPackScript, SCRIPT_PACKS, } from '../lib/script-pack-registry.js';
|
|
6
|
+
const SCRIPT_PACK_LIST_OPTIONS = [{ name: '--json', kind: 'boolean' }];
|
|
7
|
+
function createCatalogReport(mustflowRoot, packs) {
|
|
8
|
+
return {
|
|
9
|
+
schema_version: '1',
|
|
10
|
+
command: 'script-pack',
|
|
11
|
+
action: 'list',
|
|
12
|
+
ok: true,
|
|
13
|
+
mustflow_root: mustflowRoot,
|
|
14
|
+
packs: packs.map((pack) => ({
|
|
15
|
+
id: pack.id,
|
|
16
|
+
summary_key: pack.summaryKey,
|
|
17
|
+
scripts: pack.scripts.map((script) => ({
|
|
18
|
+
id: script.id,
|
|
19
|
+
ref: script.ref,
|
|
20
|
+
usage: script.usage,
|
|
21
|
+
summary_key: script.summaryKey,
|
|
22
|
+
actions: script.actions,
|
|
23
|
+
report_schema_file: script.reportSchemaFile,
|
|
24
|
+
})),
|
|
25
|
+
})),
|
|
26
|
+
issues: [],
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export function getScriptPackHelp(lang = 'en') {
|
|
30
|
+
return renderHelp({
|
|
31
|
+
usage: 'mf script-pack <list|run> [options]',
|
|
32
|
+
summary: t(lang, 'scriptPack.help.summary'),
|
|
33
|
+
options: [
|
|
34
|
+
{ label: '--json', description: t(lang, 'cli.option.json') },
|
|
35
|
+
{ label: '-h, --help', description: t(lang, 'cli.option.help') },
|
|
36
|
+
],
|
|
37
|
+
examples: [
|
|
38
|
+
'mf script-pack list',
|
|
39
|
+
'mf script-pack list --json',
|
|
40
|
+
'mf script-pack run core/text-budget check README.md --max 5000',
|
|
41
|
+
'mf script-pack run core/text-budget --help',
|
|
42
|
+
],
|
|
43
|
+
exitCodes: [
|
|
44
|
+
{ label: '0', description: t(lang, 'scriptPack.help.exit.ok') },
|
|
45
|
+
{ label: '1', description: t(lang, 'scriptPack.help.exit.fail') },
|
|
46
|
+
],
|
|
47
|
+
}, lang);
|
|
48
|
+
}
|
|
49
|
+
function renderCatalogSummary(report, lang) {
|
|
50
|
+
const lines = [t(lang, 'scriptPack.title')];
|
|
51
|
+
for (const pack of report.packs) {
|
|
52
|
+
lines.push(`- ${pack.id}: ${t(lang, pack.summary_key)}`);
|
|
53
|
+
for (const script of pack.scripts) {
|
|
54
|
+
const schema = script.report_schema_file ?? t(lang, 'value.none');
|
|
55
|
+
lines.push(` - ${script.ref}: ${t(lang, script.summary_key)} ` +
|
|
56
|
+
`(${t(lang, 'scriptPack.label.actions')}: ${script.actions.join(', ')}, ` +
|
|
57
|
+
`${t(lang, 'scriptPack.label.schema')}: ${schema})`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return lines.join('\n');
|
|
61
|
+
}
|
|
62
|
+
function parseListOptions(args, lang) {
|
|
63
|
+
const parsed = parseCliOptions(args, SCRIPT_PACK_LIST_OPTIONS, { allowPositionals: false });
|
|
64
|
+
const json = hasParsedCliOption(parsed, '--json');
|
|
65
|
+
if (parsed.error) {
|
|
66
|
+
return { json, error: formatCliOptionParseError(parsed.error, lang) };
|
|
67
|
+
}
|
|
68
|
+
return { json };
|
|
69
|
+
}
|
|
70
|
+
async function runScriptPackList(args, reporter, lang) {
|
|
71
|
+
if (hasCliOptionToken(args, '--help', ['-h'])) {
|
|
72
|
+
reporter.stdout(getScriptPackHelp(lang));
|
|
73
|
+
return 0;
|
|
74
|
+
}
|
|
75
|
+
const options = parseListOptions(args, lang);
|
|
76
|
+
if (options.error) {
|
|
77
|
+
printUsageError(reporter, options.error, 'mf script-pack --help', getScriptPackHelp(lang), lang);
|
|
78
|
+
return 1;
|
|
79
|
+
}
|
|
80
|
+
const report = createCatalogReport(resolveMustflowRoot(), SCRIPT_PACKS);
|
|
81
|
+
if (options.json) {
|
|
82
|
+
reporter.stdout(JSON.stringify(report, null, 2));
|
|
83
|
+
return 0;
|
|
84
|
+
}
|
|
85
|
+
reporter.stdout(renderCatalogSummary(report, lang));
|
|
86
|
+
return 0;
|
|
87
|
+
}
|
|
88
|
+
async function runScriptPackScript(args, reporter, lang) {
|
|
89
|
+
const [scriptRef, ...scriptArgs] = args;
|
|
90
|
+
if (args.length === 1 && hasCliOptionToken(args, '--help', ['-h'])) {
|
|
91
|
+
reporter.stdout(getScriptPackHelp(lang));
|
|
92
|
+
return 0;
|
|
93
|
+
}
|
|
94
|
+
if (!scriptRef) {
|
|
95
|
+
printUsageError(reporter, t(lang, 'scriptPack.error.missingScript'), 'mf script-pack --help', getScriptPackHelp(lang), lang);
|
|
96
|
+
return 1;
|
|
97
|
+
}
|
|
98
|
+
const script = findScriptPackScript(scriptRef);
|
|
99
|
+
if (!script) {
|
|
100
|
+
printUsageError(reporter, t(lang, 'scriptPack.error.unknownScript', { script: scriptRef }), 'mf script-pack list', getScriptPackHelp(lang), lang);
|
|
101
|
+
return 1;
|
|
102
|
+
}
|
|
103
|
+
const runner = await script.loadRunner();
|
|
104
|
+
return runner(scriptArgs, reporter, lang);
|
|
105
|
+
}
|
|
106
|
+
export async function runScriptPack(args, reporter, lang = 'en') {
|
|
107
|
+
const [action, ...rest] = args;
|
|
108
|
+
if ((!action || action !== 'run') && hasCliOptionToken(args, '--help', ['-h'])) {
|
|
109
|
+
reporter.stdout(getScriptPackHelp(lang));
|
|
110
|
+
return 0;
|
|
111
|
+
}
|
|
112
|
+
if (!action) {
|
|
113
|
+
printUsageError(reporter, t(lang, 'scriptPack.error.missingAction'), 'mf script-pack --help', getScriptPackHelp(lang), lang);
|
|
114
|
+
return 1;
|
|
115
|
+
}
|
|
116
|
+
if (action === 'list') {
|
|
117
|
+
return runScriptPackList(rest, reporter, lang);
|
|
118
|
+
}
|
|
119
|
+
if (action === 'run') {
|
|
120
|
+
return runScriptPackScript(rest, reporter, lang);
|
|
121
|
+
}
|
|
122
|
+
printUsageError(reporter, t(lang, 'scriptPack.error.unknownAction', { action }), 'mf script-pack --help', getScriptPackHelp(lang), lang);
|
|
123
|
+
return 1;
|
|
124
|
+
}
|
|
@@ -5,11 +5,13 @@ import { createCorrelationId } from '../../core/correlation-id.js';
|
|
|
5
5
|
import { readUtf8FileInsideWithoutSymlinks, writeJsonFileInsideWithoutSymlinks } from '../../core/safe-filesystem.js';
|
|
6
6
|
import { createVerifyCompletionVerdict, } from '../../core/completion-verdict.js';
|
|
7
7
|
import { createExternalEvidenceRisks, } from '../../core/external-evidence.js';
|
|
8
|
+
import { createFailureReplayCapsule, } from '../../core/failure-replay-capsule.js';
|
|
8
9
|
import { createRepeatedFailureRisks, createVerificationFailureFingerprint, updateRepeatedFailureState, } from '../../core/repeated-failure.js';
|
|
9
10
|
import { createVerificationPlanId } from '../../core/verification-plan-id.js';
|
|
10
11
|
import { countReproEvidenceVerdictEffects, createReproEvidenceRisks, } from '../../core/repro-evidence.js';
|
|
11
12
|
import { createVerifyEvidenceModel } from '../../core/verification-evidence.js';
|
|
12
13
|
import { createScopeDiffRisks } from '../../core/scope-risk.js';
|
|
14
|
+
import { riskPricedEvidenceRiskCount, } from '../../core/risk-priced-evidence.js';
|
|
13
15
|
import { countValidationRatchetVerdictEffects, createValidationRatchetRisks, } from '../../core/validation-ratchet.js';
|
|
14
16
|
import { finishRunWriteBatchTracking, startRunWriteBatchTracking, } from '../../core/run-write-drift.js';
|
|
15
17
|
import { createCommandEnv } from '../../core/command-env.js';
|
|
@@ -486,6 +488,16 @@ function createCompletionVerdictForResults(input) {
|
|
|
486
488
|
const receiptBinding = createReceiptBindingEvidence(input.results, input.verificationPlanId);
|
|
487
489
|
const receiptBindingRiskCount = receiptBinding.plan_unbound_count + receiptBinding.fingerprint_unbound_count;
|
|
488
490
|
const repeatedFailureBlockerCount = input.repeatedFailureRisks.filter((risk) => risk.verdict_effect === 'blocker').length;
|
|
491
|
+
const writeDriftRiskCount = countUndeclaredWriteDrift(input.results);
|
|
492
|
+
const specificReviewRiskCount = input.sourceAnchorRiskCount +
|
|
493
|
+
input.scopeDiffRiskCount +
|
|
494
|
+
input.validationRatchetRiskCount +
|
|
495
|
+
input.reproEvidenceRiskCount +
|
|
496
|
+
input.externalEvidenceRiskCount +
|
|
497
|
+
writeDriftRiskCount +
|
|
498
|
+
receiptBindingRiskCount +
|
|
499
|
+
receiptBinding.stale_count;
|
|
500
|
+
const genericRiskPricedEvidenceRiskCount = specificReviewRiskCount === 0 ? riskPricedEvidenceRiskCount(input.report.risk_assessment) : 0;
|
|
489
501
|
return createVerifyCompletionVerdict({
|
|
490
502
|
verificationPlanId: input.verificationPlanId,
|
|
491
503
|
matchedIntents: input.summary.matched,
|
|
@@ -505,7 +517,8 @@ function createCompletionVerdictForResults(input) {
|
|
|
505
517
|
reproEvidenceContradictionCount: input.reproEvidenceContradictionCount,
|
|
506
518
|
reproEvidenceUnverifiedCount: input.reproEvidenceUnverifiedCount,
|
|
507
519
|
externalEvidenceRiskCount: input.externalEvidenceRiskCount,
|
|
508
|
-
|
|
520
|
+
riskPricedEvidenceRiskCount: genericRiskPricedEvidenceRiskCount,
|
|
521
|
+
writeDriftRiskCount,
|
|
509
522
|
receiptBindingRiskCount,
|
|
510
523
|
staleReceiptCount: receiptBinding.stale_count,
|
|
511
524
|
planMismatchCount: receiptBinding.plan_mismatch_count,
|
|
@@ -642,6 +655,15 @@ function writeVerifyRunReceipts(projectRoot, output, report, sourceAnchorRisks,
|
|
|
642
655
|
results,
|
|
643
656
|
}),
|
|
644
657
|
});
|
|
658
|
+
const failureReplayCapsule = createFailureReplayCapsule({
|
|
659
|
+
projectRoot,
|
|
660
|
+
verificationPlanId: output.verification_plan_id,
|
|
661
|
+
status: output.status,
|
|
662
|
+
reasons: output.reasons,
|
|
663
|
+
report,
|
|
664
|
+
results,
|
|
665
|
+
failureFingerprint,
|
|
666
|
+
});
|
|
645
667
|
const repeatedFailureSummary = updateRepeatedFailureState({
|
|
646
668
|
projectRoot,
|
|
647
669
|
failureFingerprint,
|
|
@@ -670,28 +692,32 @@ function writeVerifyRunReceipts(projectRoot, output, report, sourceAnchorRisks,
|
|
|
670
692
|
reproEvidenceUnverifiedCount: reproEvidenceVerdictEffects.unverified,
|
|
671
693
|
externalEvidenceRiskCount: externalEvidenceRisks.length,
|
|
672
694
|
});
|
|
695
|
+
const evidenceModel = createVerifyEvidenceModel({
|
|
696
|
+
report,
|
|
697
|
+
results,
|
|
698
|
+
verificationPlanId: output.verification_plan_id,
|
|
699
|
+
verdict: completionVerdict,
|
|
700
|
+
sourceAnchorRisks,
|
|
701
|
+
scopeDiffRisks,
|
|
702
|
+
repeatedFailureRisks: finalRepeatedFailureRisks,
|
|
703
|
+
validationRatchetRisks,
|
|
704
|
+
reproEvidence,
|
|
705
|
+
reproEvidenceRisks,
|
|
706
|
+
externalChecks,
|
|
707
|
+
externalEvidenceRisks,
|
|
708
|
+
failureReplayCapsule,
|
|
709
|
+
});
|
|
673
710
|
const outputWithReceiptPaths = {
|
|
674
711
|
...output,
|
|
675
712
|
completion_verdict: completionVerdict,
|
|
713
|
+
evidence_model: evidenceModel,
|
|
714
|
+
conflict_ledger: evidenceModel.conflict_ledger,
|
|
676
715
|
failure_fingerprint: failureFingerprint,
|
|
716
|
+
failure_replay_capsule: failureReplayCapsule,
|
|
677
717
|
repeated_failure_summary: repeatedFailureSummary,
|
|
678
718
|
run_dir: statePaths.runDir,
|
|
679
719
|
manifest_path: statePaths.manifestPath,
|
|
680
720
|
results,
|
|
681
|
-
evidence_model: createVerifyEvidenceModel({
|
|
682
|
-
report,
|
|
683
|
-
results,
|
|
684
|
-
verificationPlanId: output.verification_plan_id,
|
|
685
|
-
verdict: completionVerdict,
|
|
686
|
-
sourceAnchorRisks,
|
|
687
|
-
scopeDiffRisks,
|
|
688
|
-
repeatedFailureRisks: finalRepeatedFailureRisks,
|
|
689
|
-
validationRatchetRisks,
|
|
690
|
-
reproEvidence,
|
|
691
|
-
reproEvidenceRisks,
|
|
692
|
-
externalChecks,
|
|
693
|
-
externalEvidenceRisks,
|
|
694
|
-
}),
|
|
695
721
|
};
|
|
696
722
|
const manifest = {
|
|
697
723
|
schema_version: '1',
|
|
@@ -703,9 +729,12 @@ function writeVerifyRunReceipts(projectRoot, output, report, sourceAnchorRisks,
|
|
|
703
729
|
verification_plan_id: outputWithReceiptPaths.verification_plan_id,
|
|
704
730
|
execution_status: outputWithReceiptPaths.execution_status,
|
|
705
731
|
status: outputWithReceiptPaths.status,
|
|
732
|
+
risk_assessment: outputWithReceiptPaths.risk_assessment,
|
|
706
733
|
completion_verdict: outputWithReceiptPaths.completion_verdict,
|
|
707
734
|
evidence_model: outputWithReceiptPaths.evidence_model,
|
|
735
|
+
conflict_ledger: outputWithReceiptPaths.conflict_ledger,
|
|
708
736
|
failure_fingerprint: outputWithReceiptPaths.failure_fingerprint,
|
|
737
|
+
failure_replay_capsule: outputWithReceiptPaths.failure_replay_capsule,
|
|
709
738
|
repeated_failure_summary: outputWithReceiptPaths.repeated_failure_summary,
|
|
710
739
|
summary: outputWithReceiptPaths.summary,
|
|
711
740
|
...(outputWithReceiptPaths.repro_evidence ? { repro_evidence: outputWithReceiptPaths.repro_evidence } : {}),
|
|
@@ -724,9 +753,12 @@ function writeVerifyRunReceipts(projectRoot, output, report, sourceAnchorRisks,
|
|
|
724
753
|
verification_plan_id: outputWithReceiptPaths.verification_plan_id,
|
|
725
754
|
execution_status: outputWithReceiptPaths.execution_status,
|
|
726
755
|
status: outputWithReceiptPaths.status,
|
|
756
|
+
risk_assessment: outputWithReceiptPaths.risk_assessment,
|
|
727
757
|
completion_verdict: outputWithReceiptPaths.completion_verdict,
|
|
728
758
|
evidence_model: outputWithReceiptPaths.evidence_model,
|
|
759
|
+
conflict_ledger: outputWithReceiptPaths.conflict_ledger,
|
|
729
760
|
failure_fingerprint: outputWithReceiptPaths.failure_fingerprint,
|
|
761
|
+
failure_replay_capsule: outputWithReceiptPaths.failure_replay_capsule,
|
|
730
762
|
repeated_failure_summary: outputWithReceiptPaths.repeated_failure_summary,
|
|
731
763
|
summary: outputWithReceiptPaths.summary,
|
|
732
764
|
...(outputWithReceiptPaths.repro_evidence ? { repro_evidence: outputWithReceiptPaths.repro_evidence } : {}),
|
|
@@ -814,9 +846,12 @@ async function createVerifyOutput(input, planSource, projectRoot, lang, reproEvi
|
|
|
814
846
|
verification_plan_id: verificationPlanId,
|
|
815
847
|
execution_status: status,
|
|
816
848
|
status,
|
|
849
|
+
risk_assessment: report.risk_assessment,
|
|
817
850
|
completion_verdict: completionVerdict,
|
|
818
851
|
evidence_model: evidenceModel,
|
|
852
|
+
conflict_ledger: evidenceModel.conflict_ledger,
|
|
819
853
|
failure_fingerprint: failureFingerprint,
|
|
854
|
+
failure_replay_capsule: null,
|
|
820
855
|
repeated_failure_summary: null,
|
|
821
856
|
summary,
|
|
822
857
|
...(parallelismReport ? { parallelism: parallelismReport } : {}),
|
|
@@ -312,6 +312,7 @@ function createUnavailableVerificationRepository(repository, commandSurface, sta
|
|
|
312
312
|
changed_file_count: classification ? classification.summary.fileCount : null,
|
|
313
313
|
changed_files: classification ? classification.files : [],
|
|
314
314
|
verification_plan_id: null,
|
|
315
|
+
risk_assessment: null,
|
|
315
316
|
requirement_count: 0,
|
|
316
317
|
candidate_count: 0,
|
|
317
318
|
selected_intent_count: 0,
|
|
@@ -367,6 +368,7 @@ function createVerificationRepository(projectRoot, repository) {
|
|
|
367
368
|
changed_file_count: classification.summary.fileCount,
|
|
368
369
|
changed_files: classification.files,
|
|
369
370
|
verification_plan_id: createVerificationPlanId(report, contract),
|
|
371
|
+
risk_assessment: report.risk_assessment,
|
|
370
372
|
requirement_count: report.requirements.length,
|
|
371
373
|
candidate_count: report.candidates.length,
|
|
372
374
|
selected_intent_count: report.schedule.entries.length,
|
package/dist/cli/i18n/en.js
CHANGED
|
@@ -40,6 +40,7 @@ export const enMessages = {
|
|
|
40
40
|
"command.map.summary": "Generate REPO_MAP.md",
|
|
41
41
|
"command.lineEndings.summary": "Inspect and normalize line-ending policy",
|
|
42
42
|
"command.quality.summary": "Inspect changed files for quality-gaming patterns",
|
|
43
|
+
"command.scriptPack.summary": "List and run bundled mustflow script packs",
|
|
43
44
|
"command.run.summary": "Run a configured oneshot command",
|
|
44
45
|
"command.context.summary": "Print machine-readable agent context",
|
|
45
46
|
"command.tech.summary": "Manage technology preferences for agents",
|
|
@@ -182,6 +183,7 @@ export const enMessages = {
|
|
|
182
183
|
"label.results": "Results",
|
|
183
184
|
"label.comment": "Comment",
|
|
184
185
|
"label.mode": "Mode",
|
|
186
|
+
"label.status": "Status",
|
|
185
187
|
"adapters.help.summary": "Inspect repository-visible host adapter files without generating or authorizing adapter surfaces.",
|
|
186
188
|
"adapters.help.exit.ok": "Adapter compatibility was inspected and printed",
|
|
187
189
|
"adapters.help.exit.fail": "The command received invalid input",
|
|
@@ -747,6 +749,42 @@ Read these files before working:
|
|
|
747
749
|
"quality.clean": "No quality-gaming risks found.",
|
|
748
750
|
"quality.error.missingAction": "Specify a quality action: check",
|
|
749
751
|
"quality.error.unknownAction": "Unknown quality action: {action}",
|
|
752
|
+
"scriptPack.help.summary": "List and run bundled mustflow script-pack utilities through one stable command namespace.",
|
|
753
|
+
"scriptPack.help.exit.ok": "The script-pack command completed successfully",
|
|
754
|
+
"scriptPack.help.exit.fail": "The script-pack command received invalid input or the selected script failed",
|
|
755
|
+
"scriptPack.title": "mustflow script packs",
|
|
756
|
+
"scriptPack.pack.core.summary": "Core built-in utility scripts",
|
|
757
|
+
"scriptPack.script.textBudget.summary": "Check exact text length budgets for files or JSON string fields",
|
|
758
|
+
"scriptPack.label.script": "Script",
|
|
759
|
+
"scriptPack.label.actions": "actions",
|
|
760
|
+
"scriptPack.label.schema": "schema",
|
|
761
|
+
"scriptPack.error.missingAction": "Specify a script-pack action: list or run",
|
|
762
|
+
"scriptPack.error.unknownAction": "Unknown script-pack action: {action}",
|
|
763
|
+
"scriptPack.error.missingScript": "Specify a script ref such as core/text-budget",
|
|
764
|
+
"scriptPack.error.unknownScript": "Unknown script-pack script: {script}",
|
|
765
|
+
"textBudget.help.summary": "Check exact text length budgets for files or JSON string fields using grapheme counts by default.",
|
|
766
|
+
"textBudget.help.option.min": "Require at least this many units",
|
|
767
|
+
"textBudget.help.option.max": "Require at most this many units",
|
|
768
|
+
"textBudget.help.option.exact": "Require exactly this many units; cannot be combined with --min or --max",
|
|
769
|
+
"textBudget.help.option.unit": "Counting unit: grapheme, code-point, utf16, utf8-byte, word, or line",
|
|
770
|
+
"textBudget.help.option.jsonPointer": "Read a string field from each JSON file before counting",
|
|
771
|
+
"textBudget.help.exit.ok": "Every checked target is within the declared budget",
|
|
772
|
+
"textBudget.help.exit.fail": "A budget violation, read error, JSON error, or invalid input was found",
|
|
773
|
+
"textBudget.title": "mustflow text budget",
|
|
774
|
+
"textBudget.label.budget": "Budget",
|
|
775
|
+
"textBudget.label.checkedTargets": "Checked targets",
|
|
776
|
+
"textBudget.label.findings": "Findings",
|
|
777
|
+
"textBudget.label.metrics": "Metrics",
|
|
778
|
+
"textBudget.label.issues": "Issues",
|
|
779
|
+
"textBudget.clean": "All text budgets passed.",
|
|
780
|
+
"textBudget.error.missingAction": "Specify a text-budget action: check",
|
|
781
|
+
"textBudget.error.unknownAction": "Unknown text-budget action: {action}",
|
|
782
|
+
"textBudget.error.missingPath": "Provide at least one path to check",
|
|
783
|
+
"textBudget.error.missingBudget": "Declare at least one text budget with --min, --max, or --exact",
|
|
784
|
+
"textBudget.error.exactConflict": "Cannot combine --exact with --min or --max",
|
|
785
|
+
"textBudget.error.invalidNumber": "{option} must be a non-negative safe integer: {value}",
|
|
786
|
+
"textBudget.error.invalidUnit": "Unknown text-budget unit: {unit}. Use one of: {allowed}",
|
|
787
|
+
"textBudget.error.minGreaterThanMax": "--min must be less than or equal to --max",
|
|
750
788
|
"run.help.summary": "Run a configured oneshot command from .mustflow/config/commands.toml.",
|
|
751
789
|
"run.help.option.dryRun": "Print a non-executing command plan",
|
|
752
790
|
"run.help.option.planOnly": "Alias for --dry-run",
|