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.
Files changed (48) hide show
  1. package/README.md +19 -5
  2. package/dist/cli/commands/api.js +17 -0
  3. package/dist/cli/commands/evidence.js +71 -0
  4. package/dist/cli/commands/script-pack.js +124 -0
  5. package/dist/cli/commands/verify.js +50 -15
  6. package/dist/cli/commands/workspace.js +2 -0
  7. package/dist/cli/i18n/en.js +38 -0
  8. package/dist/cli/i18n/es.js +38 -0
  9. package/dist/cli/i18n/fr.js +38 -0
  10. package/dist/cli/i18n/hi.js +38 -0
  11. package/dist/cli/i18n/ko.js +38 -0
  12. package/dist/cli/i18n/zh.js +38 -0
  13. package/dist/cli/index.js +1 -0
  14. package/dist/cli/lib/agent-context.js +179 -10
  15. package/dist/cli/lib/command-registry.js +6 -0
  16. package/dist/cli/lib/dashboard-export.js +1 -0
  17. package/dist/cli/lib/script-pack-registry.js +27 -0
  18. package/dist/cli/script-packs/core-text-budget.js +241 -0
  19. package/dist/core/change-verification.js +10 -0
  20. package/dist/core/completion-verdict.js +14 -1
  21. package/dist/core/complexity-budget.js +206 -0
  22. package/dist/core/conflict-ledger.js +122 -0
  23. package/dist/core/failure-replay-capsule.js +213 -0
  24. package/dist/core/public-json-contracts.js +27 -0
  25. package/dist/core/risk-priced-evidence.js +213 -0
  26. package/dist/core/script-check-result.js +1 -0
  27. package/dist/core/text-budget.js +262 -0
  28. package/dist/core/verification-evidence.js +61 -13
  29. package/package.json +1 -1
  30. package/schemas/README.md +23 -11
  31. package/schemas/change-verification-report.schema.json +29 -0
  32. package/schemas/context-report.schema.json +58 -2
  33. package/schemas/dashboard-export.schema.json +42 -1
  34. package/schemas/diff-risk.schema.json +6 -0
  35. package/schemas/evidence-report.schema.json +45 -0
  36. package/schemas/latest-run-pointer.schema.json +50 -1
  37. package/schemas/script-pack-catalog.schema.json +68 -0
  38. package/schemas/text-budget-report.schema.json +131 -0
  39. package/schemas/verification-plan.schema.json +32 -0
  40. package/schemas/verify-report.schema.json +360 -1
  41. package/schemas/verify-run-manifest.schema.json +50 -1
  42. package/schemas/workspace-verification-plan.schema.json +32 -0
  43. package/templates/default/i18n.toml +8 -2
  44. package/templates/default/locales/en/.mustflow/skills/INDEX.md +3 -2
  45. package/templates/default/locales/en/.mustflow/skills/adapter-boundary/SKILL.md +19 -2
  46. package/templates/default/locales/en/.mustflow/skills/design-implementation-handoff/SKILL.md +250 -0
  47. package/templates/default/locales/en/.mustflow/skills/routes.toml +7 -1
  48. package/templates/default/manifest.toml +8 -1
@@ -40,6 +40,7 @@ export const esMessages = {
40
40
  "command.map.summary": "Genera REPO_MAP.md",
41
41
  "command.lineEndings.summary": "Inspecciona y normaliza la política de finales de línea",
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": "Ejecuta un comando configurado de una sola ejecución",
44
45
  "command.context.summary": "Imprime contexto de agente legible por máquinas",
45
46
  "command.tech.summary": "Gestiona preferencias tecnológicas para agentes",
@@ -182,6 +183,7 @@ export const esMessages = {
182
183
  "label.results": "Resultados",
183
184
  "label.comment": "Comentario",
184
185
  "label.mode": "Modo",
186
+ "label.status": "Status",
185
187
  "adapters.help.summary": "Inspecciona archivos de adaptadores visibles en el repositorio sin generarlos ni autorizarlos.",
186
188
  "adapters.help.exit.ok": "La compatibilidad de adaptadores fue inspeccionada e impresa",
187
189
  "adapters.help.exit.fail": "El comando recibió entrada inválida",
@@ -747,6 +749,42 @@ Lee estos archivos antes de trabajar:
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": "Ejecuta un comando configurado de una sola ejecución desde .mustflow/config/commands.toml.",
751
789
  "run.help.option.dryRun": "Imprime un plan de comando sin ejecutarlo",
752
790
  "run.help.option.planOnly": "Alias de --dry-run",
@@ -40,6 +40,7 @@ export const frMessages = {
40
40
  "command.map.summary": "Génère REPO_MAP.md",
41
41
  "command.lineEndings.summary": "Inspecte et normalise la politique de fins de ligne",
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": "Exécute une commande configurée à exécution unique",
44
45
  "command.context.summary": "Imprime le contexte d'agent lisible par machine",
45
46
  "command.tech.summary": "Gère les préférences technologiques pour les agents",
@@ -182,6 +183,7 @@ export const frMessages = {
182
183
  "label.results": "Résultats",
183
184
  "label.comment": "Commentaire",
184
185
  "label.mode": "Mode",
186
+ "label.status": "Status",
185
187
  "adapters.help.summary": "Inspecte les fichiers d'adaptateur visibles dans le dépôt sans les générer ni leur donner d'autorité.",
186
188
  "adapters.help.exit.ok": "La compatibilité des adaptateurs a été inspectée et affichée",
187
189
  "adapters.help.exit.fail": "La commande a reçu une entrée non valide",
@@ -747,6 +749,42 @@ Lisez ces fichiers avant de travailler :
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": "Exécute une commande configurée à exécution unique depuis .mustflow/config/commands.toml.",
751
789
  "run.help.option.dryRun": "Imprime un plan de commande sans l'exécuter",
752
790
  "run.help.option.planOnly": "Alias de --dry-run",
@@ -40,6 +40,7 @@ export const hiMessages = {
40
40
  "command.map.summary": "REPO_MAP.md बनाएँ",
41
41
  "command.lineEndings.summary": "लाइन-एंडिंग नीति की जाँच और सामान्यीकरण करें",
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": "कॉन्फ़िगर की गई एक-बार चलने वाली कमांड चलाएँ",
44
45
  "command.context.summary": "मशीन-पठनीय एजेंट संदर्भ प्रिंट करें",
45
46
  "command.tech.summary": "एजेंटों के लिए technology preferences प्रबंधित करें",
@@ -182,6 +183,7 @@ export const hiMessages = {
182
183
  "label.results": "परिणाम",
183
184
  "label.comment": "टिप्पणी",
184
185
  "label.mode": "मोड",
186
+ "label.status": "Status",
185
187
  "adapters.help.summary": "रिपॉज़िटरी में दिखने वाली होस्ट एडाप्टर फ़ाइलों की जाँच करें, बिना फ़ाइल बनाए या अधिकार दिए।",
186
188
  "adapters.help.exit.ok": "एडाप्टर संगतता जाँची और प्रिंट की गई",
187
189
  "adapters.help.exit.fail": "कमांड को अमान्य इनपुट मिला",
@@ -747,6 +749,42 @@ export const hiMessages = {
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": ".mustflow/config/commands.toml से कॉन्फ़िगर की गई एक-बार चलने वाली कमांड चलाएँ।",
751
789
  "run.help.option.dryRun": "कमांड चलाए बिना उसका plan प्रिंट करें",
752
790
  "run.help.option.planOnly": "--dry-run का alias",
@@ -40,6 +40,7 @@ export const koMessages = {
40
40
  "command.map.summary": "REPO_MAP.md를 작성합니다",
41
41
  "command.lineEndings.summary": "줄바꿈 정책을 검사하고 정규화합니다",
42
42
  "command.quality.summary": "변경 파일의 품질 지표 꼼수를 검사합니다",
43
+ "command.scriptPack.summary": "mustflow 내장 script pack을 나열하고 실행합니다",
43
44
  "command.run.summary": "설정된 일회성 명령을 실행합니다",
44
45
  "command.context.summary": "에이전트 작업 맥락을 출력합니다",
45
46
  "command.tech.summary": "에이전트용 기술 선호를 관리합니다",
@@ -182,6 +183,7 @@ export const koMessages = {
182
183
  "label.results": "결과",
183
184
  "label.comment": "코멘트",
184
185
  "label.mode": "모드",
186
+ "label.status": "상태",
185
187
  "adapters.help.summary": "파일을 만들거나 어댑터 표면에 권한을 주지 않고, 저장소에서 보이는 호스트 어댑터 파일을 확인합니다.",
186
188
  "adapters.help.exit.ok": "어댑터 호환성을 확인하고 출력했습니다",
187
189
  "adapters.help.exit.fail": "잘못된 입력이 제공되었습니다",
@@ -747,6 +749,42 @@ export const koMessages = {
747
749
  "quality.clean": "품질 지표 꼼수가 발견되지 않았습니다.",
748
750
  "quality.error.missingAction": "quality 작업을 지정하세요: check",
749
751
  "quality.error.unknownAction": "알 수 없는 quality 작업: {action}",
752
+ "scriptPack.help.summary": "mustflow 내장 utility script들을 하나의 안정적인 command namespace 아래에서 나열하고 실행합니다.",
753
+ "scriptPack.help.exit.ok": "script-pack 명령이 성공적으로 완료되었습니다",
754
+ "scriptPack.help.exit.fail": "script-pack 명령에 잘못된 입력이 제공되었거나 선택한 script가 실패했습니다",
755
+ "scriptPack.title": "mustflow script packs",
756
+ "scriptPack.pack.core.summary": "핵심 내장 utility script",
757
+ "scriptPack.script.textBudget.summary": "파일이나 JSON 문자열 필드의 정확한 텍스트 길이 예산을 검사합니다",
758
+ "scriptPack.label.script": "Script",
759
+ "scriptPack.label.actions": "작업",
760
+ "scriptPack.label.schema": "스키마",
761
+ "scriptPack.error.missingAction": "script-pack 작업을 지정하세요: list 또는 run",
762
+ "scriptPack.error.unknownAction": "알 수 없는 script-pack 작업: {action}",
763
+ "scriptPack.error.missingScript": "core/text-budget 같은 script ref를 지정하세요",
764
+ "scriptPack.error.unknownScript": "알 수 없는 script-pack script: {script}",
765
+ "textBudget.help.summary": "파일이나 JSON 문자열 필드의 정확한 텍스트 길이 예산을 검사합니다. 기본 단위는 grapheme입니다.",
766
+ "textBudget.help.option.min": "최소 단위 수를 요구합니다",
767
+ "textBudget.help.option.max": "최대 단위 수를 요구합니다",
768
+ "textBudget.help.option.exact": "정확히 이 단위 수를 요구합니다. --min 또는 --max와 함께 쓸 수 없습니다",
769
+ "textBudget.help.option.unit": "계산 단위: grapheme, code-point, utf16, utf8-byte, word, line",
770
+ "textBudget.help.option.jsonPointer": "계산 전에 각 JSON 파일에서 문자열 필드를 읽습니다",
771
+ "textBudget.help.exit.ok": "모든 대상이 선언된 예산 안에 있습니다",
772
+ "textBudget.help.exit.fail": "예산 위반, 읽기 오류, JSON 오류, 또는 잘못된 입력이 발견되었습니다",
773
+ "textBudget.title": "mustflow text budget",
774
+ "textBudget.label.budget": "예산",
775
+ "textBudget.label.checkedTargets": "검사한 대상",
776
+ "textBudget.label.findings": "발견 항목",
777
+ "textBudget.label.metrics": "측정값",
778
+ "textBudget.label.issues": "문제",
779
+ "textBudget.clean": "모든 텍스트 예산을 통과했습니다.",
780
+ "textBudget.error.missingAction": "text-budget 작업을 지정하세요: check",
781
+ "textBudget.error.unknownAction": "알 수 없는 text-budget 작업: {action}",
782
+ "textBudget.error.missingPath": "검사할 경로를 하나 이상 제공하세요",
783
+ "textBudget.error.missingBudget": "--min, --max, 또는 --exact 중 하나로 텍스트 예산을 선언하세요",
784
+ "textBudget.error.exactConflict": "--exact는 --min 또는 --max와 함께 쓸 수 없습니다",
785
+ "textBudget.error.invalidNumber": "{option} 값은 0 이상의 안전한 정수여야 합니다: {value}",
786
+ "textBudget.error.invalidUnit": "알 수 없는 text-budget 단위: {unit}. 다음 중 하나를 사용하세요: {allowed}",
787
+ "textBudget.error.minGreaterThanMax": "--min은 --max보다 작거나 같아야 합니다",
750
788
  "run.help.summary": ".mustflow/config/commands.toml에 설정된 일회성 명령을 실행합니다.",
751
789
  "run.help.option.dryRun": "실행하지 않고 명령 계획을 출력합니다",
752
790
  "run.help.option.planOnly": "--dry-run과 같은 동작입니다",
@@ -40,6 +40,7 @@ export const zhMessages = {
40
40
  "command.map.summary": "生成 REPO_MAP.md",
41
41
  "command.lineEndings.summary": "检查并规范化换行符策略",
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": "运行已配置的一次性命令",
44
45
  "command.context.summary": "输出机器可读的代理上下文",
45
46
  "command.tech.summary": "管理代理使用的技术偏好",
@@ -182,6 +183,7 @@ export const zhMessages = {
182
183
  "label.results": "结果",
183
184
  "label.comment": "评论",
184
185
  "label.mode": "模式",
186
+ "label.status": "Status",
185
187
  "adapters.help.summary": "检查仓库中可见的宿主适配器文件,但不生成文件,也不授予适配器执行权限。",
186
188
  "adapters.help.exit.ok": "已检查并输出适配器兼容性",
187
189
  "adapters.help.exit.fail": "命令收到无效输入",
@@ -747,6 +749,42 @@ export const zhMessages = {
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": "从 .mustflow/config/commands.toml 运行已配置的一次性命令。",
751
789
  "run.help.option.dryRun": "输出命令计划但不执行",
752
790
  "run.help.option.planOnly": "--dry-run 的别名",
package/dist/cli/index.js CHANGED
@@ -54,6 +54,7 @@ function getTopLevelHelp(lang) {
54
54
  'mf verify --reason code_change',
55
55
  'mf line-endings check',
56
56
  'mf quality check',
57
+ 'mf script-pack run core/text-budget check README.md --max 5000',
57
58
  'mf version --check',
58
59
  'mf version-sources --json',
59
60
  ],
@@ -87,10 +87,20 @@ function readNumber(table, key) {
87
87
  return typeof value === 'number' && Number.isFinite(value) ? value : null;
88
88
  }
89
89
  function readPathContext(projectRoot, paths) {
90
- return paths.map((relativePath) => ({
91
- path: toPosixPath(relativePath),
92
- exists: safeExists(projectRoot, relativePath),
93
- }));
90
+ return paths.map((relativePath) => {
91
+ const normalizedPath = toPosixPath(relativePath);
92
+ const content = safeRead(projectRoot, normalizedPath);
93
+ return {
94
+ path: normalizedPath,
95
+ exists: content !== null,
96
+ trust: createContextTrust({
97
+ relativePath: normalizedPath,
98
+ cacheLayer: null,
99
+ contentHash: content === null ? null : sha256(content),
100
+ exists: content !== null,
101
+ }),
102
+ };
103
+ });
94
104
  }
95
105
  function readScalarObject(table) {
96
106
  if (!table) {
@@ -111,6 +121,100 @@ function readScalarObject(table) {
111
121
  function sha256(content) {
112
122
  return `sha256:${createHash('sha256').update(content).digest('hex')}`;
113
123
  }
124
+ function trustSourceKind(relativePath, sourceKind) {
125
+ if (sourceKind === 'runtime_volatile') {
126
+ return 'runtime_volatile';
127
+ }
128
+ if (relativePath === null) {
129
+ return sourceKind === 'dynamic_selection' ? 'source_placeholder' : 'unknown_file';
130
+ }
131
+ if (relativePath === COMMANDS_RELATIVE_PATH) {
132
+ return 'command_contract';
133
+ }
134
+ if (relativePath === LATEST_RUN_RELATIVE_PATH || relativePath.startsWith('.mustflow/state/')) {
135
+ return 'generated_state';
136
+ }
137
+ if (relativePath.startsWith('.mustflow/cache/')) {
138
+ return 'generated_cache';
139
+ }
140
+ if (relativePath.startsWith('.mustflow/skills/') && relativePath.endsWith('/SKILL.md')) {
141
+ return 'skill_file';
142
+ }
143
+ if (relativePath.startsWith('.mustflow/context/')) {
144
+ return 'context_file';
145
+ }
146
+ if (relativePath === 'AGENTS.md' ||
147
+ relativePath.startsWith('.mustflow/docs/') ||
148
+ relativePath.startsWith('.mustflow/config/') ||
149
+ relativePath.startsWith('.mustflow/skills/')) {
150
+ return 'workflow_file';
151
+ }
152
+ return 'unknown_file';
153
+ }
154
+ function trustAuthority(relativePath, sourceKind) {
155
+ if (relativePath === 'AGENTS.md') {
156
+ return 'binding';
157
+ }
158
+ if (relativePath === COMMANDS_RELATIVE_PATH) {
159
+ return 'command_contract';
160
+ }
161
+ if (relativePath === MUSTFLOW_RELATIVE_PATH ||
162
+ relativePath === PREFERENCES_RELATIVE_PATH ||
163
+ relativePath === TECHNOLOGY_RELATIVE_PATH) {
164
+ return 'configuration';
165
+ }
166
+ if (relativePath?.startsWith('.mustflow/docs/')) {
167
+ return 'workflow_policy';
168
+ }
169
+ if (relativePath?.startsWith('.mustflow/skills/') && relativePath.endsWith('/SKILL.md')) {
170
+ return 'procedure';
171
+ }
172
+ if (relativePath?.startsWith('.mustflow/context/')) {
173
+ return 'contextual';
174
+ }
175
+ if (sourceKind === 'generated_cache') {
176
+ return 'generated';
177
+ }
178
+ if (sourceKind === 'generated_state') {
179
+ return 'evidence_only';
180
+ }
181
+ if (sourceKind === 'runtime_volatile') {
182
+ return 'volatile';
183
+ }
184
+ if (sourceKind === 'source_placeholder') {
185
+ return 'hint';
186
+ }
187
+ return 'unknown';
188
+ }
189
+ function createContextTrust(input) {
190
+ const normalizedPath = input.relativePath === null ? null : toPosixPath(input.relativePath);
191
+ const sourceKind = trustSourceKind(normalizedPath, input.sourceKind ?? null);
192
+ const authority = trustAuthority(normalizedPath, sourceKind);
193
+ const freshness = sourceKind === 'runtime_volatile'
194
+ ? 'runtime_volatile'
195
+ : input.contentHash !== null
196
+ ? 'hash_verified'
197
+ : input.exists === false
198
+ ? 'missing'
199
+ : sourceKind === 'source_placeholder'
200
+ ? 'dynamic'
201
+ : 'unchecked';
202
+ return {
203
+ source_kind: sourceKind,
204
+ authority,
205
+ cache_layer: input.cacheLayer,
206
+ freshness,
207
+ content_hash: input.contentHash,
208
+ can_instruct_agent: authority === 'binding' ||
209
+ authority === 'workflow_policy' ||
210
+ authority === 'configuration' ||
211
+ authority === 'command_contract' ||
212
+ authority === 'procedure' ||
213
+ authority === 'contextual',
214
+ grants_command_authority: authority === 'command_contract',
215
+ notes: input.notes ?? [],
216
+ };
217
+ }
114
218
  function estimateTokens(renderedBytes) {
115
219
  return Math.ceil(renderedBytes / 4);
116
220
  }
@@ -396,10 +500,19 @@ function readStablePromptCacheLayer(projectRoot, mustflow) {
396
500
  const read = readOptionalStringArray(layer, 'read') ?? [...DEFAULT_PROMPT_CACHE_STABLE_READ];
397
501
  const documents = read.map((relativePath) => {
398
502
  const content = safeRead(projectRoot, relativePath);
503
+ const contentHash = content === null ? null : sha256(content);
504
+ const normalizedPath = toPosixPath(relativePath);
399
505
  return {
400
- path: toPosixPath(relativePath),
506
+ path: normalizedPath,
401
507
  exists: content !== null,
402
- content_hash: content === null ? null : sha256(content),
508
+ content_hash: contentHash,
509
+ trust: createContextTrust({
510
+ relativePath: normalizedPath,
511
+ cacheLayer: 'stable',
512
+ contentHash,
513
+ exists: content !== null,
514
+ sourceKind: 'file_reference',
515
+ }),
403
516
  };
404
517
  });
405
518
  const cacheMaterial = documents
@@ -515,6 +628,7 @@ function readStablePromptBundleLayer(projectRoot, mustflow) {
515
628
  blocks: read.map((relativePath, index) => {
516
629
  const path = toPosixPath(relativePath);
517
630
  const content = safeRead(projectRoot, relativePath);
631
+ const contentHash = content === null ? null : sha256(content);
518
632
  const renderedBytes = content === null ? null : measurePromptCacheReferenceBlockBytes(relativePath, content);
519
633
  const issue = content === null ? `stable prefix document is missing: ${path}` : null;
520
634
  return {
@@ -527,12 +641,19 @@ function readStablePromptBundleLayer(projectRoot, mustflow) {
527
641
  source_kind: 'file_reference',
528
642
  selection_policy: 'always_rendered',
529
643
  content_included: false,
530
- content_hash: content === null ? null : sha256(content),
644
+ content_hash: contentHash,
531
645
  rendered_digest: content === null ? null : renderedDigest(relativePath, content),
532
646
  rendered_bytes: renderedBytes,
533
647
  estimated_tokens: renderedBytes === null ? null : estimateTokens(renderedBytes),
534
648
  cacheability: 'provider_prefix_candidate',
535
649
  reload_on: ['stable_file_hash_changed'],
650
+ trust: createContextTrust({
651
+ relativePath: path,
652
+ cacheLayer: 'stable',
653
+ contentHash,
654
+ exists: content !== null,
655
+ sourceKind: 'file_reference',
656
+ }),
536
657
  issue,
537
658
  };
538
659
  }),
@@ -589,6 +710,14 @@ function readTaskPromptBundleLayer(projectRoot, mustflow, routeReport) {
589
710
  estimated_tokens: renderedBytes === null ? null : estimateTokens(renderedBytes),
590
711
  cacheability: taskSourceCacheability(source, selectionPolicy),
591
712
  reload_on: taskSourceReloadOn(source, selectionPolicy),
713
+ trust: createContextTrust({
714
+ relativePath: routeCandidateContent !== null ? SKILL_ROUTE_CANDIDATES_VIRTUAL_PATH : referencePath,
715
+ cacheLayer: 'task',
716
+ contentHash,
717
+ exists: routeCandidateContent !== null || content !== null ? true : sourceKind === 'file_reference' ? false : null,
718
+ sourceKind,
719
+ notes: source === 'skill_route_candidates' ? ['derived from route resolver input'] : [],
720
+ }),
592
721
  issue,
593
722
  };
594
723
  if (source !== 'matching_skill') {
@@ -597,6 +726,7 @@ function readTaskPromptBundleLayer(projectRoot, mustflow, routeReport) {
597
726
  const selectedBlocks = selectedSkillPaths.map((skillPath, selectedIndex) => {
598
727
  const normalizedPath = toPosixPath(skillPath);
599
728
  const skillContent = safeRead(projectRoot, normalizedPath);
729
+ const skillContentHash = skillContent === null ? null : sha256(skillContent);
600
730
  const skillRenderedBytes = skillContent === null ? null : measurePromptCacheReferenceBlockBytes(normalizedPath, skillContent);
601
731
  const skillIssue = skillContent === null
602
732
  ? taskSourceIssue(normalizedPath, 'hash_only_deferred')
@@ -611,12 +741,20 @@ function readTaskPromptBundleLayer(projectRoot, mustflow, routeReport) {
611
741
  source_kind: skillContent === null ? 'dynamic_selection' : 'file_reference',
612
742
  selection_policy: 'selected_at_runtime',
613
743
  content_included: false,
614
- content_hash: skillContent === null ? null : sha256(skillContent),
744
+ content_hash: skillContentHash,
615
745
  rendered_digest: skillContent === null ? null : renderedDigest(normalizedPath, skillContent),
616
746
  rendered_bytes: skillRenderedBytes,
617
747
  estimated_tokens: skillRenderedBytes === null ? null : estimateTokens(skillRenderedBytes),
618
748
  cacheability: 'runtime_selection',
619
749
  reload_on: ['route_resolution_changed', 'source_file_hash_changed'],
750
+ trust: createContextTrust({
751
+ relativePath: normalizedPath,
752
+ cacheLayer: 'task',
753
+ contentHash: skillContentHash,
754
+ exists: skillContent !== null,
755
+ sourceKind: skillContent === null ? 'dynamic_selection' : 'file_reference',
756
+ notes: ['selected by task route resolver'],
757
+ }),
620
758
  issue: skillIssue,
621
759
  };
622
760
  });
@@ -646,6 +784,14 @@ function readVolatilePromptBundleLayer(mustflow) {
646
784
  estimated_tokens: null,
647
785
  cacheability: 'volatile_suffix',
648
786
  reload_on: ['volatile_state_changed'],
787
+ trust: createContextTrust({
788
+ relativePath: null,
789
+ cacheLayer: 'volatile',
790
+ contentHash: null,
791
+ exists: null,
792
+ sourceKind: 'runtime_volatile',
793
+ notes: ['not rendered in stable or task prompt cache layers'],
794
+ }),
649
795
  issue,
650
796
  })),
651
797
  };
@@ -663,10 +809,27 @@ function readPromptBundle(projectRoot, mustflow, profile, routeReport = null) {
663
809
  }
664
810
  const blocks = layers.flatMap((layer) => layer.blocks);
665
811
  const shapeMaterial = blocks
666
- .map((block) => [block.cache_layer, block.order, block.kind, block.path ?? '', block.source ?? '', block.selection_policy, block.cacheability].join('\0'))
812
+ .map((block) => [
813
+ block.cache_layer,
814
+ block.order,
815
+ block.kind,
816
+ block.path ?? '',
817
+ block.source ?? '',
818
+ block.selection_policy,
819
+ block.cacheability,
820
+ block.trust.authority,
821
+ block.trust.source_kind,
822
+ ].join('\0'))
667
823
  .join('\n');
668
824
  const bundleMaterial = blocks
669
- .map((block) => [block.id, block.content_hash ?? '', block.rendered_digest ?? '', block.issue ?? ''].join('\0'))
825
+ .map((block) => [
826
+ block.id,
827
+ block.content_hash ?? '',
828
+ block.rendered_digest ?? '',
829
+ block.trust.freshness,
830
+ block.trust.content_hash ?? '',
831
+ block.issue ?? '',
832
+ ].join('\0'))
670
833
  .join('\n');
671
834
  return {
672
835
  schema_version: '1',
@@ -744,6 +907,9 @@ function blockLocation(block) {
744
907
  function compareStringArray(left, right) {
745
908
  return left.length === right.length && left.every((entry, index) => entry === right[index]);
746
909
  }
910
+ function contextTrustMatches(left, right) {
911
+ return JSON.stringify(left ?? null) === JSON.stringify(right ?? null);
912
+ }
747
913
  function changedBlockFields(current, baseline) {
748
914
  const fields = [];
749
915
  if (current.id !== baseline.id) {
@@ -779,6 +945,9 @@ function changedBlockFields(current, baseline) {
779
945
  if (current.cacheability !== baseline.cacheability) {
780
946
  fields.push('cacheability');
781
947
  }
948
+ if (!contextTrustMatches(current.trust, baseline.trust)) {
949
+ fields.push('trust');
950
+ }
782
951
  if (!compareStringArray(current.reload_on, baseline.reload_on)) {
783
952
  fields.push('reload_on');
784
953
  }
@@ -95,6 +95,12 @@ export const COMMAND_DEFINITIONS = [
95
95
  summaryKey: 'command.quality.summary',
96
96
  loadRunner: async () => (await import('../commands/quality.js')).runQuality,
97
97
  },
98
+ {
99
+ id: 'script-pack',
100
+ usage: 'mf script-pack',
101
+ summaryKey: 'command.scriptPack.summary',
102
+ loadRunner: async () => (await import('../commands/script-pack.js')).runScriptPack,
103
+ },
98
104
  {
99
105
  id: 'run',
100
106
  usage: 'mf run',
@@ -448,6 +448,7 @@ function createDashboardHarnessReport(statusValue, docsReviewValue) {
448
448
  verification: {
449
449
  completion_verdict: completionVerdict,
450
450
  evidence_model: evidenceModel,
451
+ conflict_ledger: evidenceModel.conflict_ledger,
451
452
  changed_file_count: changedFileCount,
452
453
  changed_surfaces: changedSurfaces,
453
454
  decision_graph_summary: decisionGraphSummary,
@@ -0,0 +1,27 @@
1
+ function scriptRef(packId, scriptId) {
2
+ return `${packId}/${scriptId}`;
3
+ }
4
+ export const SCRIPT_PACKS = [
5
+ {
6
+ id: 'core',
7
+ summaryKey: 'scriptPack.pack.core.summary',
8
+ scripts: [
9
+ {
10
+ packId: 'core',
11
+ id: 'text-budget',
12
+ ref: scriptRef('core', 'text-budget'),
13
+ usage: 'mf script-pack run core/text-budget check <path...> [options]',
14
+ summaryKey: 'scriptPack.script.textBudget.summary',
15
+ actions: ['check'],
16
+ reportSchemaFile: 'text-budget-report.schema.json',
17
+ loadRunner: async () => (await import('../script-packs/core-text-budget.js')).runCoreTextBudgetScript,
18
+ },
19
+ ],
20
+ },
21
+ ];
22
+ export function listScriptPackScripts() {
23
+ return SCRIPT_PACKS.flatMap((pack) => pack.scripts);
24
+ }
25
+ export function findScriptPackScript(ref) {
26
+ return listScriptPackScripts().find((script) => script.ref === ref);
27
+ }