mustflow 1.30.0 → 2.11.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.
Files changed (82) hide show
  1. package/README.md +35 -11
  2. package/dist/cli/commands/classify.js +61 -6
  3. package/dist/cli/commands/contract-lint.js +13 -4
  4. package/dist/cli/commands/dashboard.js +6 -0
  5. package/dist/cli/commands/index.js +5 -0
  6. package/dist/cli/commands/run.js +224 -48
  7. package/dist/cli/commands/upgrade.js +65 -0
  8. package/dist/cli/commands/verify.js +550 -33
  9. package/dist/cli/i18n/en.js +73 -10
  10. package/dist/cli/i18n/es.js +73 -10
  11. package/dist/cli/i18n/fr.js +73 -10
  12. package/dist/cli/i18n/hi.js +73 -10
  13. package/dist/cli/i18n/ko.js +73 -10
  14. package/dist/cli/i18n/zh.js +73 -10
  15. package/dist/cli/index.js +27 -46
  16. package/dist/cli/lib/command-registry.js +5 -0
  17. package/dist/cli/lib/dashboard-export.js +62 -12
  18. package/dist/cli/lib/dashboard-html/client-script.js +1936 -0
  19. package/dist/cli/lib/dashboard-html/locale-bootstrap.js +8 -0
  20. package/dist/cli/lib/dashboard-html/styles.js +572 -0
  21. package/dist/cli/lib/dashboard-html/template.js +134 -0
  22. package/dist/cli/lib/dashboard-html/types.js +1 -0
  23. package/dist/cli/lib/dashboard-html.js +1 -1907
  24. package/dist/cli/lib/dashboard-locale.js +37 -0
  25. package/dist/cli/lib/local-index/constants.js +48 -0
  26. package/dist/cli/lib/local-index/index.js +2256 -0
  27. package/dist/cli/lib/local-index/sql.js +15 -0
  28. package/dist/cli/lib/local-index/types.js +1 -0
  29. package/dist/cli/lib/local-index.js +1 -1908
  30. package/dist/cli/lib/reporter.js +6 -0
  31. package/dist/cli/lib/run-plan.js +96 -4
  32. package/dist/cli/lib/templates.js +18 -1
  33. package/dist/cli/lib/validation/command-intents.js +11 -0
  34. package/dist/cli/lib/validation/constants.js +238 -0
  35. package/dist/cli/lib/validation/index.js +1384 -0
  36. package/dist/cli/lib/validation/primitives.js +198 -0
  37. package/dist/cli/lib/validation/test-selection.js +95 -0
  38. package/dist/cli/lib/validation/types.js +1 -0
  39. package/dist/cli/lib/validation.js +1 -1661
  40. package/dist/core/bounded-output.js +38 -0
  41. package/dist/core/change-classification.js +6 -2
  42. package/dist/core/change-verification.js +240 -6
  43. package/dist/core/check-issues.js +12 -0
  44. package/dist/core/command-contract-validation.js +20 -0
  45. package/dist/core/command-effects.js +13 -0
  46. package/dist/core/completion-verdict.js +209 -0
  47. package/dist/core/contract-lint.js +316 -7
  48. package/dist/core/dashboard-verification.js +8 -0
  49. package/dist/core/external-evidence.js +9 -0
  50. package/dist/core/public-json-contracts.js +28 -0
  51. package/dist/core/repeated-failure.js +17 -0
  52. package/dist/core/repro-evidence.js +53 -0
  53. package/dist/core/run-performance-history.js +307 -0
  54. package/dist/core/run-profile.js +87 -0
  55. package/dist/core/run-receipt.js +171 -4
  56. package/dist/core/run-write-drift.js +18 -2
  57. package/dist/core/scope-risk.js +64 -0
  58. package/dist/core/skill-route-alignment.js +110 -0
  59. package/dist/core/source-anchor-status.js +4 -1
  60. package/dist/core/test-selection.js +227 -0
  61. package/dist/core/validation-ratchet.js +52 -0
  62. package/dist/core/verification-decision-graph.js +67 -0
  63. package/dist/core/verification-evidence.js +249 -0
  64. package/dist/core/verification-scheduler.js +96 -2
  65. package/examples/README.md +12 -4
  66. package/package.json +1 -1
  67. package/schemas/README.md +18 -4
  68. package/schemas/change-verification-report.schema.json +169 -5
  69. package/schemas/commands.schema.json +51 -1
  70. package/schemas/contract-lint-report.schema.json +80 -0
  71. package/schemas/dashboard-export.schema.json +500 -0
  72. package/schemas/explain-report.schema.json +2 -0
  73. package/schemas/latest-run-pointer.schema.json +384 -0
  74. package/schemas/run-receipt.schema.json +113 -0
  75. package/schemas/test-selection.schema.json +81 -0
  76. package/schemas/verify-report.schema.json +361 -1
  77. package/schemas/verify-run-manifest.schema.json +410 -0
  78. package/templates/default/common/.mustflow/config/commands.toml +1 -1
  79. package/templates/default/i18n.toml +1 -1
  80. package/templates/default/locales/en/.mustflow/skills/INDEX.md +124 -29
  81. package/templates/default/locales/en/.mustflow/skills/routes.toml +289 -0
  82. package/templates/default/manifest.toml +29 -2
package/dist/cli/index.js CHANGED
@@ -2,29 +2,6 @@
2
2
  import { realpathSync } from 'node:fs';
3
3
  import path from 'node:path';
4
4
  import { fileURLToPath } from 'node:url';
5
- import { runAdapters } from './commands/adapters.js';
6
- import { runCheck } from './commands/check.js';
7
- import { runClassify } from './commands/classify.js';
8
- import { runContractLint } from './commands/contract-lint.js';
9
- import { runContext } from './commands/context.js';
10
- import { runDashboard } from './commands/dashboard.js';
11
- import { runDoctor } from './commands/doctor.js';
12
- import { runDocs } from './commands/docs.js';
13
- import { runExplain } from './commands/explain.js';
14
- import { runHelp } from './commands/help.js';
15
- import { runHandoff } from './commands/handoff.js';
16
- import { runImpact } from './commands/impact.js';
17
- import { runInit } from './commands/init.js';
18
- import { runIndex } from './commands/index.js';
19
- import { runLineEndings } from './commands/line-endings.js';
20
- import { runMap } from './commands/map.js';
21
- import { runRun } from './commands/run.js';
22
- import { runSearch } from './commands/search.js';
23
- import { runStatus } from './commands/status.js';
24
- import { runUpdate } from './commands/update.js';
25
- import { runVerify } from './commands/verify.js';
26
- import { runVersion } from './commands/version.js';
27
- import { runVersionSources } from './commands/version-sources.js';
28
5
  import { COMMAND_DEFINITIONS } from './lib/command-registry.js';
29
6
  import { renderCliError, renderHelp } from './lib/cli-output.js';
30
7
  import { DEFAULT_CLI_LANG, SUPPORTED_CLI_LANGS, isCliLang, t } from './lib/i18n.js';
@@ -59,6 +36,7 @@ function getTopLevelHelp(lang) {
59
36
  'mf search mustflow_check',
60
37
  'mf explain authority AGENTS.md',
61
38
  'mf impact --changed',
39
+ 'mf upgrade --dry-run',
62
40
  'mf verify --changed --plan-only --json',
63
41
  'mf verify --reason code_change',
64
42
  'mf line-endings check',
@@ -125,73 +103,76 @@ export async function runCli(argv, reporter = consoleReporter) {
125
103
  return 0;
126
104
  }
127
105
  if (command === '--version' || command === '-v' || command === 'version') {
128
- return runVersion(args, reporter, parsed.lang);
106
+ return (await import('./commands/version.js')).runVersion(args, reporter, parsed.lang);
129
107
  }
130
108
  if (command === 'init') {
131
- return runInit(args, reporter, parsed.lang);
109
+ return (await import('./commands/init.js')).runInit(args, reporter, parsed.lang);
132
110
  }
133
111
  if (command === 'adapters') {
134
- return runAdapters(args, reporter, parsed.lang);
112
+ return (await import('./commands/adapters.js')).runAdapters(args, reporter, parsed.lang);
135
113
  }
136
114
  if (command === 'check') {
137
- return runCheck(args, reporter, parsed.lang);
115
+ return (await import('./commands/check.js')).runCheck(args, reporter, parsed.lang);
138
116
  }
139
117
  if (command === 'classify') {
140
- return runClassify(args, reporter, parsed.lang);
118
+ return (await import('./commands/classify.js')).runClassify(args, reporter, parsed.lang);
141
119
  }
142
120
  if (command === 'contract-lint') {
143
- return runContractLint(args, reporter, parsed.lang);
121
+ return (await import('./commands/contract-lint.js')).runContractLint(args, reporter, parsed.lang);
144
122
  }
145
123
  if (command === 'status') {
146
- return runStatus(args, reporter, parsed.lang);
124
+ return (await import('./commands/status.js')).runStatus(args, reporter, parsed.lang);
147
125
  }
148
126
  if (command === 'update') {
149
- return runUpdate(args, reporter, parsed.lang);
127
+ return (await import('./commands/update.js')).runUpdate(args, reporter, parsed.lang);
128
+ }
129
+ if (command === 'upgrade') {
130
+ return (await import('./commands/upgrade.js')).runUpgrade(args, reporter, parsed.lang);
150
131
  }
151
132
  if (command === 'map') {
152
- return runMap(args, reporter, parsed.lang);
133
+ return (await import('./commands/map.js')).runMap(args, reporter, parsed.lang);
153
134
  }
154
135
  if (command === 'line-endings') {
155
- return runLineEndings(args, reporter, parsed.lang);
136
+ return (await import('./commands/line-endings.js')).runLineEndings(args, reporter, parsed.lang);
156
137
  }
157
138
  if (command === 'run') {
158
- return runRun(args, reporter, parsed.lang);
139
+ return (await import('./commands/run.js')).runRun(args, reporter, parsed.lang);
159
140
  }
160
141
  if (command === 'context') {
161
- return runContext(args, reporter, parsed.lang);
142
+ return (await import('./commands/context.js')).runContext(args, reporter, parsed.lang);
162
143
  }
163
144
  if (command === 'doctor') {
164
- return runDoctor(args, reporter, parsed.lang);
145
+ return (await import('./commands/doctor.js')).runDoctor(args, reporter, parsed.lang);
165
146
  }
166
147
  if (command === 'docs') {
167
- return runDocs(args, reporter, parsed.lang);
148
+ return (await import('./commands/docs.js')).runDocs(args, reporter, parsed.lang);
168
149
  }
169
150
  if (command === 'handoff') {
170
- return runHandoff(args, reporter, parsed.lang);
151
+ return (await import('./commands/handoff.js')).runHandoff(args, reporter, parsed.lang);
171
152
  }
172
153
  if (command === 'index') {
173
- return runIndex(args, reporter, parsed.lang);
154
+ return (await import('./commands/index.js')).runIndex(args, reporter, parsed.lang);
174
155
  }
175
156
  if (command === 'search') {
176
- return runSearch(args, reporter, parsed.lang);
157
+ return (await import('./commands/search.js')).runSearch(args, reporter, parsed.lang);
177
158
  }
178
159
  if (command === 'dashboard') {
179
- return runDashboard(args, reporter, parsed.lang);
160
+ return (await import('./commands/dashboard.js')).runDashboard(args, reporter, parsed.lang);
180
161
  }
181
162
  if (command === 'version-sources') {
182
- return runVersionSources(args, reporter, parsed.lang);
163
+ return (await import('./commands/version-sources.js')).runVersionSources(args, reporter, parsed.lang);
183
164
  }
184
165
  if (command === 'verify') {
185
- return runVerify(args, reporter, parsed.lang);
166
+ return (await import('./commands/verify.js')).runVerify(args, reporter, parsed.lang);
186
167
  }
187
168
  if (command === 'explain') {
188
- return runExplain(args, reporter, parsed.lang);
169
+ return (await import('./commands/explain.js')).runExplain(args, reporter, parsed.lang);
189
170
  }
190
171
  if (command === 'impact') {
191
- return runImpact(args, reporter, parsed.lang);
172
+ return (await import('./commands/impact.js')).runImpact(args, reporter, parsed.lang);
192
173
  }
193
174
  if (command === 'help') {
194
- return runHelp(args, reporter, parsed.lang);
175
+ return (await import('./commands/help.js')).runHelp(args, reporter, parsed.lang);
195
176
  }
196
177
  reporter.stderr(renderCliError(t(parsed.lang, 'cli.error.unknownCommand', { command }), 'mf --help', parsed.lang));
197
178
  reporter.stdout(getTopLevelHelp(parsed.lang));
@@ -34,6 +34,11 @@ export const COMMAND_DEFINITIONS = [
34
34
  usage: 'mf update',
35
35
  summaryKey: 'command.update.summary',
36
36
  },
37
+ {
38
+ id: 'upgrade',
39
+ usage: 'mf upgrade',
40
+ summaryKey: 'command.upgrade.summary',
41
+ },
37
42
  {
38
43
  id: 'map',
39
44
  usage: 'mf map',
@@ -1,5 +1,7 @@
1
1
  import { Buffer } from 'node:buffer';
2
2
  import path from 'node:path';
3
+ import { createDashboardCompletionVerdict } from '../../core/completion-verdict.js';
4
+ import { createDashboardEvidenceModel } from '../../core/verification-evidence.js';
3
5
  import { redactSecretLikeText } from '../../core/secret-redaction.js';
4
6
  import { ensureFileTargetInsideWithoutSymlinks, ensureInside, toPosixPath, writeUtf8FileInsideWithoutSymlinks, } from './filesystem.js';
5
7
  export class DashboardExportPathError extends Error {
@@ -380,6 +382,56 @@ function createDashboardHarnessReport(statusValue, docsReviewValue) {
380
382
  .map((entry) => stringOrNull(entry.intent))
381
383
  .filter((entry) => entry !== null)
382
384
  .slice(0, DASHBOARD_HARNESS_MAX_ITEMS);
385
+ const skippedIntents = asArray(verification.skipped)
386
+ .map(asRecord)
387
+ .map((entry) => ({
388
+ intent: text(entry.intent),
389
+ reason_key: text(entry.reason_key),
390
+ }))
391
+ .slice(0, DASHBOARD_HARNESS_MAX_ITEMS);
392
+ const verificationGaps = createVerificationGaps(verification.decision_graph);
393
+ const runHistory = createRunHistorySummary(status);
394
+ const changedFileCount = stringArray(verification.changed_files).length;
395
+ const changedSurfaces = stringArray(verification.surfaces);
396
+ const remainingRisks = createRemainingRisks(status, docsReview, decisionGraphSummary);
397
+ const completionVerdict = createDashboardCompletionVerdict({
398
+ changedFileCount,
399
+ runnableIntentCount: runnableIntents.length,
400
+ skippedIntentCount: skippedIntents.length,
401
+ gapCount: verificationGaps.length,
402
+ latestRunExists: runHistory.exists,
403
+ latestRunValid: runHistory.valid,
404
+ latestRunStatus: runHistory.status,
405
+ });
406
+ const evidenceModel = createDashboardEvidenceModel({
407
+ changedSurfaces,
408
+ runnableIntents,
409
+ skippedChecks: skippedIntents.map((entry) => ({
410
+ intent: entry.intent || null,
411
+ reason: entry.reason_key || null,
412
+ detail: null,
413
+ })),
414
+ gaps: verificationGaps.map((gap) => ({
415
+ reason: gap.reason,
416
+ intent: gap.intent,
417
+ status: gap.kind,
418
+ detail: gap.detail,
419
+ files: gap.files,
420
+ surfaces: gap.surfaces,
421
+ })),
422
+ latestReceipt: runHistory.exists && runHistory.valid
423
+ ? {
424
+ intent: runHistory.intent,
425
+ status: runHistory.status ?? 'unknown',
426
+ skipped: false,
427
+ verification_plan_id: null,
428
+ receipt_path: runHistory.receipt_path,
429
+ receipt_sha256: null,
430
+ }
431
+ : null,
432
+ remainingRisks,
433
+ verdict: completionVerdict,
434
+ });
383
435
  return {
384
436
  schema_version: '1',
385
437
  generated_from: 'dashboard_status_snapshot',
@@ -392,25 +444,21 @@ function createDashboardHarnessReport(statusValue, docsReviewValue) {
392
444
  issues: stringArray(status.issues).length,
393
445
  },
394
446
  verification: {
395
- changed_file_count: stringArray(verification.changed_files).length,
396
- changed_surfaces: stringArray(verification.surfaces),
447
+ completion_verdict: completionVerdict,
448
+ evidence_model: evidenceModel,
449
+ changed_file_count: changedFileCount,
450
+ changed_surfaces: changedSurfaces,
397
451
  decision_graph_summary: decisionGraphSummary,
398
452
  runnable_intents: runnableIntents,
399
- skipped_intents: asArray(verification.skipped)
400
- .map(asRecord)
401
- .map((entry) => ({
402
- intent: text(entry.intent),
403
- reason_key: text(entry.reason_key),
404
- }))
405
- .slice(0, DASHBOARD_HARNESS_MAX_ITEMS),
406
- gaps: createVerificationGaps(verification.decision_graph),
453
+ skipped_intents: skippedIntents,
454
+ gaps: verificationGaps,
407
455
  },
408
- run_history: createRunHistorySummary(status),
456
+ run_history: runHistory,
409
457
  docs_review: {
410
458
  ledger_path: text(docsReview.ledger_path),
411
459
  active_documents: numberOrZero(docsReview.count),
412
460
  },
413
- remaining_risks: createRemainingRisks(status, docsReview, decisionGraphSummary),
461
+ remaining_risks: remainingRisks,
414
462
  };
415
463
  }
416
464
  export function resolveDashboardExportPath(projectRoot, outputPath) {
@@ -582,6 +630,7 @@ export function renderDashboardExportHtml(snapshot) {
582
630
  const harnessReport = asRecord(snapshot.harness_report);
583
631
  const harnessInstall = asRecord(harnessReport.install);
584
632
  const harnessVerification = asRecord(harnessReport.verification);
633
+ const completionVerdict = asRecord(harnessVerification.completion_verdict);
585
634
  const graphSummary = asRecord(harnessVerification.decision_graph_summary);
586
635
  const harnessRunHistory = asRecord(harnessReport.run_history);
587
636
  const harnessDocsReview = asRecord(harnessReport.docs_review);
@@ -676,6 +725,7 @@ ul { margin: 0; padding-left: 22px; }
676
725
  renderMetric('Tracked files', harnessInstall.tracked_files),
677
726
  renderMetric('Changed files', harnessVerification.changed_file_count),
678
727
  renderMetric('Changed surfaces', asArray(harnessVerification.changed_surfaces).join(', ') || 'none'),
728
+ renderMetric('Completion verdict', completionVerdict.status),
679
729
  renderMetric('Runnable verification intents', asArray(harnessVerification.runnable_intents).length),
680
730
  renderMetric('Skipped verification intents', asArray(harnessVerification.skipped_intents).length),
681
731
  renderMetric('Verification gaps', asArray(harnessVerification.gaps).length),