mustflow 2.22.17 → 2.22.47

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 (70) hide show
  1. package/README.md +6 -0
  2. package/dist/cli/commands/api.js +874 -0
  3. package/dist/cli/commands/dashboard.js +51 -4
  4. package/dist/cli/commands/explain.js +3 -2
  5. package/dist/cli/commands/help.js +0 -1
  6. package/dist/cli/commands/run.js +41 -4
  7. package/dist/cli/commands/verify.js +4 -43
  8. package/dist/cli/i18n/en.js +15 -0
  9. package/dist/cli/i18n/es.js +15 -0
  10. package/dist/cli/i18n/fr.js +15 -0
  11. package/dist/cli/i18n/hi.js +15 -0
  12. package/dist/cli/i18n/ko.js +15 -0
  13. package/dist/cli/i18n/zh.js +15 -0
  14. package/dist/cli/index.js +1 -0
  15. package/dist/cli/lib/cli-output.js +1 -1
  16. package/dist/cli/lib/command-registry.js +6 -0
  17. package/dist/cli/lib/dashboard-html/client-script.js +9 -0
  18. package/dist/cli/lib/dashboard-html/styles.js +48 -1
  19. package/dist/cli/lib/doc-review-ledger.js +1 -1
  20. package/dist/cli/lib/local-index/index.js +324 -298
  21. package/dist/cli/lib/repo-map.js +19 -5
  22. package/dist/cli/lib/validation/index.js +6 -2
  23. package/dist/core/active-run-locks.js +36 -8
  24. package/dist/core/atomic-state-write.js +5 -20
  25. package/dist/core/change-verification.js +18 -2
  26. package/dist/core/contract-lint.js +3 -3
  27. package/dist/core/public-json-contracts.js +48 -0
  28. package/dist/core/repeated-failure.js +1 -1
  29. package/dist/core/run-write-drift.js +30 -17
  30. package/dist/core/safe-filesystem.js +54 -5
  31. package/dist/core/skill-route-explanation.js +2 -1
  32. package/dist/core/source-anchors.js +7 -3
  33. package/dist/core/validation-ratchet.js +61 -18
  34. package/dist/core/verification-decision-graph.js +8 -1
  35. package/dist/core/verification-plan-id.js +44 -0
  36. package/package.json +1 -1
  37. package/schemas/README.md +6 -0
  38. package/schemas/command-catalog.schema.json +158 -0
  39. package/schemas/diff-risk.schema.json +74 -0
  40. package/schemas/health.schema.json +45 -0
  41. package/schemas/latest-evidence.schema.json +95 -0
  42. package/schemas/verification-plan.schema.json +245 -0
  43. package/schemas/workspace-summary.schema.json +282 -0
  44. package/templates/default/i18n.toml +139 -1
  45. package/templates/default/locales/en/.mustflow/skills/INDEX.md +24 -1
  46. package/templates/default/locales/en/.mustflow/skills/api-contract-change/SKILL.md +212 -0
  47. package/templates/default/locales/en/.mustflow/skills/astro-code-change/SKILL.md +184 -0
  48. package/templates/default/locales/en/.mustflow/skills/auth-permission-change/SKILL.md +194 -0
  49. package/templates/default/locales/en/.mustflow/skills/config-env-change/SKILL.md +189 -0
  50. package/templates/default/locales/en/.mustflow/skills/css-code-change/SKILL.md +199 -0
  51. package/templates/default/locales/en/.mustflow/skills/dart-code-change/SKILL.md +179 -0
  52. package/templates/default/locales/en/.mustflow/skills/database-migration-change/SKILL.md +178 -0
  53. package/templates/default/locales/en/.mustflow/skills/dependency-upgrade-review/SKILL.md +151 -0
  54. package/templates/default/locales/en/.mustflow/skills/elysia-code-change/SKILL.md +115 -0
  55. package/templates/default/locales/en/.mustflow/skills/file-path-cross-platform-change/SKILL.md +147 -0
  56. package/templates/default/locales/en/.mustflow/skills/flutter-code-change/SKILL.md +116 -0
  57. package/templates/default/locales/en/.mustflow/skills/go-code-change/SKILL.md +156 -0
  58. package/templates/default/locales/en/.mustflow/skills/hono-code-change/SKILL.md +117 -0
  59. package/templates/default/locales/en/.mustflow/skills/html-code-change/SKILL.md +173 -0
  60. package/templates/default/locales/en/.mustflow/skills/javascript-code-change/SKILL.md +149 -0
  61. package/templates/default/locales/en/.mustflow/skills/python-code-change/SKILL.md +154 -0
  62. package/templates/default/locales/en/.mustflow/skills/release-publish-change/SKILL.md +172 -0
  63. package/templates/default/locales/en/.mustflow/skills/routes.toml +138 -0
  64. package/templates/default/locales/en/.mustflow/skills/rust-code-change/SKILL.md +154 -0
  65. package/templates/default/locales/en/.mustflow/skills/svelte-code-change/SKILL.md +186 -0
  66. package/templates/default/locales/en/.mustflow/skills/tailwind-code-change/SKILL.md +164 -0
  67. package/templates/default/locales/en/.mustflow/skills/tauri-code-change/SKILL.md +185 -0
  68. package/templates/default/locales/en/.mustflow/skills/typescript-code-change/SKILL.md +184 -0
  69. package/templates/default/locales/en/.mustflow/skills/unocss-code-change/SKILL.md +186 -0
  70. package/templates/default/manifest.toml +158 -1
@@ -901,311 +901,327 @@ function createSourceAnchorRiskSignals(sourceAnchors) {
901
901
  canInstructAgent: anchor.canInstructAgent,
902
902
  }));
903
903
  }
904
- function populateDatabase(database, capabilities, documents, skills, skillRoutes, commandIntents, sourceAnchors, indexedFiles, verificationEvidence, indexMode, sourceScopeHash, sourceIndexEnabled, indexedAt) {
905
- const sourceAnchorRiskSignals = createSourceAnchorRiskSignals(sourceAnchors);
906
- database.run('INSERT INTO metadata (key, value) VALUES (?, ?)', ['schema_version', LOCAL_INDEX_SCHEMA_VERSION]);
907
- database.run('INSERT INTO metadata (key, value) VALUES (?, ?)', ['parser_version', LOCAL_INDEX_PARSER_VERSION]);
908
- database.run('INSERT INTO metadata (key, value) VALUES (?, ?)', ['content_mode', LOCAL_INDEX_CONTENT_MODE]);
909
- database.run('INSERT INTO metadata (key, value) VALUES (?, ?)', [
910
- 'store_full_content',
911
- String(LOCAL_INDEX_STORE_FULL_CONTENT),
912
- ]);
913
- database.run('INSERT INTO metadata (key, value) VALUES (?, ?)', [
914
- 'max_snippet_bytes_per_document',
915
- String(MAX_SNIPPET_BYTES_PER_DOCUMENT),
916
- ]);
917
- database.run('INSERT INTO metadata (key, value) VALUES (?, ?)', [
918
- 'search_ngram_max_token_chars',
919
- String(SEARCH_NGRAM_MAX_TOKEN_CHARS),
920
- ]);
921
- database.run('INSERT INTO metadata (key, value) VALUES (?, ?)', [
922
- 'search_ngram_max_grams_per_target',
923
- String(SEARCH_NGRAM_MAX_GRAMS_PER_TARGET),
924
- ]);
925
- database.run('INSERT INTO metadata (key, value) VALUES (?, ?)', [
926
- 'source_index_max_file_bytes',
927
- String(SOURCE_INDEX_MAX_FILE_BYTES),
928
- ]);
929
- database.run('INSERT INTO metadata (key, value) VALUES (?, ?)', [
930
- 'excluded_raw_data_kinds',
931
- LOCAL_INDEX_EXCLUDED_RAW_DATA_KINDS.join(','),
932
- ]);
933
- database.run('INSERT INTO metadata (key, value) VALUES (?, ?)', ['search_backend', capabilities.backend]);
934
- database.run('INSERT INTO metadata (key, value) VALUES (?, ?)', [
935
- 'search_fts5_available',
936
- String(capabilities.fts5Available),
937
- ]);
938
- database.run('INSERT INTO metadata (key, value) VALUES (?, ?)', ['source_scope_hash', sourceScopeHash]);
939
- database.run('INSERT INTO metadata (key, value) VALUES (?, ?)', ['source_index_enabled', String(sourceIndexEnabled)]);
940
- database.run('INSERT INTO metadata (key, value) VALUES (?, ?)', ['index_mode', indexMode]);
941
- for (const indexedFile of indexedFiles) {
942
- database.run('INSERT INTO indexed_files (path, source_scope, size_bytes, mtime_ms, content_hash, indexed_at, index_mode, parser_version) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', [
943
- indexedFile.path,
944
- indexedFile.sourceScope,
945
- indexedFile.sizeBytes,
946
- indexedFile.mtimeMs,
947
- indexedFile.contentHash,
948
- indexedAt,
949
- indexMode,
950
- LOCAL_INDEX_PARSER_VERSION,
951
- ]);
952
- }
953
- for (const document of documents) {
954
- database.run('INSERT INTO documents (path, type, title, locale, revision, content_hash, content_snippet) VALUES (?, ?, ?, ?, ?, ?, ?)', [
955
- document.path,
956
- document.type,
957
- document.title,
958
- document.locale,
959
- document.revision,
960
- document.contentHash,
961
- document.contentSnippet,
962
- ]);
963
- document.sections.forEach((heading, index) => {
964
- database.run('INSERT INTO sections (document_path, ordinal, heading) VALUES (?, ?, ?)', [
965
- document.path,
966
- index + 1,
967
- heading,
968
- ]);
969
- });
970
- }
971
- for (const skill of skills) {
972
- database.run('INSERT INTO skills (name, path, title) VALUES (?, ?, ?)', [skill.name, skill.path, skill.title]);
973
- }
974
- for (const route of skillRoutes) {
975
- const verificationIntents = route.verificationIntents.join(', ');
976
- database.run('INSERT INTO skill_routes (skill_name, skill_path, trigger, required_input, edit_scope, risk, verification_intents, expected_output) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', [
977
- route.skillName,
978
- route.skillPath,
979
- route.trigger,
980
- route.requiredInput,
981
- route.editScope,
982
- route.risk,
983
- verificationIntents,
984
- route.expectedOutput,
985
- ]);
986
- insertDocumentTerm(database, '.mustflow/skills/INDEX.md', route.skillName, 'skill_route_name');
987
- insertDocumentTerm(database, '.mustflow/skills/INDEX.md', route.trigger, 'skill_route_trigger');
988
- insertDocumentTerm(database, '.mustflow/skills/INDEX.md', route.risk, 'skill_route_risk');
989
- insertDocumentTerm(database, '.mustflow/skills/INDEX.md', route.requiredInput, 'skill_route_required_input');
990
- insertDocumentTerm(database, '.mustflow/skills/INDEX.md', route.editScope, 'skill_route_edit_scope');
991
- insertDocumentTerm(database, '.mustflow/skills/INDEX.md', verificationIntents, 'skill_route_verification_intents');
992
- }
993
- for (const intent of commandIntents) {
994
- database.run('INSERT INTO command_intents (name, status, lifecycle, run_policy, description) VALUES (?, ?, ?, ?, ?)', [intent.name, intent.status, intent.lifecycle, intent.runPolicy, intent.description]);
995
- insertDocumentTerm(database, '.mustflow/config/commands.toml', intent.name, 'command_intent');
996
- insertDocumentTerm(database, '.mustflow/config/commands.toml', intent.status, 'command_status');
997
- insertDocumentTerm(database, '.mustflow/config/commands.toml', intent.lifecycle, 'command_lifecycle');
998
- insertDocumentTerm(database, '.mustflow/config/commands.toml', intent.runPolicy, 'command_run_policy');
999
- insertDocumentTerm(database, '.mustflow/config/commands.toml', intent.description, 'command_description');
1000
- for (const effect of intent.effects) {
1001
- database.run('INSERT INTO command_effects (intent, source, access, mode, path, lock, concurrency) VALUES (?, ?, ?, ?, ?, ?, ?)', [effect.intent, effect.source, effect.access, effect.mode, effect.path, effect.lock, effect.concurrency]);
1002
- if (effect.path !== null) {
1003
- insertDocumentTerm(database, '.mustflow/config/commands.toml', effect.path, 'command_effect_path');
1004
- }
1005
- insertDocumentTerm(database, '.mustflow/config/commands.toml', effect.lock, 'command_effect_lock');
1006
- insertDocumentTerm(database, '.mustflow/config/commands.toml', effect.mode, 'command_effect_mode');
1007
- }
1008
- }
1009
- for (const anchor of sourceAnchors) {
1010
- database.run('INSERT INTO source_anchors (id, path, line_start, purpose, search_terms, invariant, risk, navigation_only, can_instruct_agent) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)', [
1011
- anchor.id,
1012
- anchor.path,
1013
- anchor.lineStart,
1014
- anchor.purpose,
1015
- anchor.search.join(', '),
1016
- anchor.invariant,
1017
- anchor.risk.join(', '),
1018
- anchor.navigationOnly ? 1 : 0,
1019
- anchor.canInstructAgent ? 1 : 0,
1020
- ]);
1021
- database.run('INSERT INTO source_anchor_fingerprints (anchor_id, path, line_start, anchor_metadata_hash, anchor_text_hash, context_hash, search_terms_hash, invariant_hash, risk_hash, symbol_kind, symbol_name, symbol_exported, signature_hash, body_hash, symbol_start_line, symbol_end_line) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', [
1022
- anchor.id,
1023
- anchor.path,
1024
- anchor.lineStart,
1025
- anchor.fingerprint.anchorMetadataHash,
1026
- anchor.fingerprint.anchorTextHash,
1027
- anchor.fingerprint.contextHash,
1028
- anchor.fingerprint.searchTermsHash,
1029
- anchor.fingerprint.invariantHash,
1030
- anchor.fingerprint.riskHash,
1031
- anchor.fingerprint.symbol.kind,
1032
- anchor.fingerprint.symbol.name,
1033
- anchor.fingerprint.symbol.exported ? 1 : 0,
1034
- anchor.fingerprint.symbol.signatureHash,
1035
- anchor.fingerprint.symbol.bodyHash,
1036
- anchor.fingerprint.symbol.startLine,
1037
- anchor.fingerprint.symbol.endLine,
1038
- ]);
1039
- database.run('INSERT INTO source_anchor_status (anchor_id, status, confidence, identity_signal, location_signal, symbol_signal, body_signal, metadata_signal, semantic_signal, risk_signal, navigation_only, can_instruct_agent) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', [
1040
- anchor.id,
1041
- anchor.status,
1042
- anchor.confidence,
1043
- anchor.signals.identity,
1044
- anchor.signals.location,
1045
- anchor.signals.symbol,
1046
- anchor.signals.body,
1047
- anchor.signals.metadata,
1048
- anchor.signals.semantic,
1049
- anchor.signals.risk,
1050
- anchor.navigationOnly ? 1 : 0,
1051
- anchor.canInstructAgent ? 1 : 0,
1052
- ]);
1053
- }
1054
- for (const summary of verificationEvidence.summaries) {
1055
- database.run('INSERT INTO verification_evidence_summaries (source_path, source_hash, command, kind, status, run_dir, manifest_path, verification_plan_id, completion_status, primary_reason, matched_intents, ran_intents, passed_intents, failed_intents, skipped_intents, receipt_count, coverage_count, remaining_risk_count, failure_fingerprint) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', [
1056
- summary.sourcePath,
1057
- summary.sourceHash,
1058
- summary.command,
1059
- summary.kind,
1060
- summary.status,
1061
- summary.runDir,
1062
- summary.manifestPath,
1063
- summary.verificationPlanId,
1064
- summary.completionStatus,
1065
- summary.primaryReason,
1066
- summary.matchedIntents,
1067
- summary.ranIntents,
1068
- summary.passedIntents,
1069
- summary.failedIntents,
1070
- summary.skippedIntents,
1071
- summary.receiptCount,
1072
- summary.coverageCount,
1073
- summary.remainingRiskCount,
1074
- summary.failureFingerprint,
1075
- ]);
1076
- }
1077
- for (const plan of verificationEvidence.verificationPlans) {
1078
- database.run('INSERT INTO verification_plans (plan_id, source_path, classification_hash, command_contract_hash, selected_intents_hash, created_at, source_hash) VALUES (?, ?, ?, ?, ?, ?, ?)', [
1079
- plan.planId,
1080
- plan.sourcePath,
1081
- plan.classificationHash,
1082
- plan.commandContractHash,
1083
- plan.selectedIntentsHash,
1084
- plan.createdAt,
1085
- plan.sourceHash,
1086
- ]);
904
+ function rollbackTransaction(database) {
905
+ try {
906
+ database.run('ROLLBACK');
1087
907
  }
1088
- for (const criterion of verificationEvidence.acceptanceCriteria) {
1089
- database.run('INSERT INTO acceptance_criteria (criterion_id, plan_id, source, statement_hash, reason, surface, path_hash) VALUES (?, ?, ?, ?, ?, ?, ?)', [
1090
- criterion.criterionId,
1091
- criterion.planId,
1092
- criterion.source,
1093
- criterion.statementHash,
1094
- criterion.reason,
1095
- criterion.surface,
1096
- criterion.pathHash,
1097
- ]);
908
+ catch {
909
+ // Keep the original indexing failure as the actionable error.
1098
910
  }
1099
- for (const coverage of verificationEvidence.criterionCoverage) {
1100
- database.run('INSERT INTO criterion_coverage (criterion_id, plan_id, status, receipt_count, gap_count, risk_count) VALUES (?, ?, ?, ?, ?, ?)', [coverage.criterionId, coverage.planId, coverage.status, coverage.receiptCount, coverage.gapCount, coverage.riskCount]);
1101
- }
1102
- for (const receipt of verificationEvidence.receipts) {
1103
- database.run('INSERT INTO verification_receipt_summaries (source_path, ordinal, intent, status, skipped, verification_plan_id, receipt_path, receipt_sha256) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', [
1104
- receipt.sourcePath,
1105
- receipt.ordinal,
1106
- receipt.intent,
1107
- receipt.status,
1108
- receipt.skipped ? 1 : 0,
1109
- receipt.verificationPlanId,
1110
- receipt.receiptPath,
1111
- receipt.receiptSha256,
911
+ }
912
+ function populateDatabase(database, capabilities, documents, skills, skillRoutes, commandIntents, sourceAnchors, indexedFiles, verificationEvidence, indexMode, sourceScopeHash, sourceIndexEnabled, indexedAt) {
913
+ const sourceAnchorRiskSignals = createSourceAnchorRiskSignals(sourceAnchors);
914
+ database.run('BEGIN TRANSACTION');
915
+ try {
916
+ database.run('INSERT INTO metadata (key, value) VALUES (?, ?)', ['schema_version', LOCAL_INDEX_SCHEMA_VERSION]);
917
+ database.run('INSERT INTO metadata (key, value) VALUES (?, ?)', ['parser_version', LOCAL_INDEX_PARSER_VERSION]);
918
+ database.run('INSERT INTO metadata (key, value) VALUES (?, ?)', ['content_mode', LOCAL_INDEX_CONTENT_MODE]);
919
+ database.run('INSERT INTO metadata (key, value) VALUES (?, ?)', [
920
+ 'store_full_content',
921
+ String(LOCAL_INDEX_STORE_FULL_CONTENT),
1112
922
  ]);
1113
- }
1114
- for (const receipt of verificationEvidence.commandReceiptSummaries) {
1115
- database.run('INSERT INTO command_receipt_summaries (receipt_hash, plan_id, intent, status, command_fingerprint, contract_fingerprint, current_state_hash, write_drift_status) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', [
1116
- receipt.receiptHash,
1117
- receipt.planId,
1118
- receipt.intent,
1119
- receipt.status,
1120
- receipt.commandFingerprint,
1121
- receipt.contractFingerprint,
1122
- receipt.currentStateHash,
1123
- receipt.writeDriftStatus,
923
+ database.run('INSERT INTO metadata (key, value) VALUES (?, ?)', [
924
+ 'max_snippet_bytes_per_document',
925
+ String(MAX_SNIPPET_BYTES_PER_DOCUMENT),
1124
926
  ]);
1125
- }
1126
- for (const coverage of verificationEvidence.coverageStates) {
1127
- database.run('INSERT INTO verification_coverage_states (source_path, criterion_id, source, status, requirement_reason, intents, receipt_count, gap_count, source_anchor_count) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)', [
1128
- coverage.sourcePath,
1129
- coverage.criterionId,
1130
- coverage.source,
1131
- coverage.status,
1132
- coverage.requirementReason,
1133
- joinedList(coverage.intents),
1134
- coverage.receiptCount,
1135
- coverage.gapCount,
1136
- coverage.sourceAnchorCount,
927
+ database.run('INSERT INTO metadata (key, value) VALUES (?, ?)', [
928
+ 'search_ngram_max_token_chars',
929
+ String(SEARCH_NGRAM_MAX_TOKEN_CHARS),
1137
930
  ]);
1138
- }
1139
- for (const risk of verificationEvidence.riskSignals) {
1140
- database.run('INSERT INTO verification_risk_signals (source_path, ordinal, code, severity, detail_hash) VALUES (?, ?, ?, ?, ?)', [risk.sourcePath, risk.ordinal, risk.code, risk.severity, risk.detailHash]);
1141
- }
1142
- for (const signal of verificationEvidence.validationRatchetSignals) {
1143
- database.run('INSERT INTO validation_ratchet_signals (signal_id, plan_id, code, severity, path_hash, before_hash, after_hash) VALUES (?, ?, ?, ?, ?, ?, ?)', [signal.signalId, signal.planId, signal.code, signal.severity, signal.pathHash, signal.beforeHash, signal.afterHash]);
1144
- }
1145
- for (const verdict of verificationEvidence.completionVerdictSummaries) {
1146
- database.run('INSERT INTO completion_verdict_summaries (claim_id, plan_id, status, primary_reason, risk_count, contradiction_count, blocker_count) VALUES (?, ?, ?, ?, ?, ?, ?)', [
1147
- verdict.claimId,
1148
- verdict.planId,
1149
- verdict.status,
1150
- verdict.primaryReason,
1151
- verdict.riskCount,
1152
- verdict.contradictionCount,
1153
- verdict.blockerCount,
931
+ database.run('INSERT INTO metadata (key, value) VALUES (?, ?)', [
932
+ 'search_ngram_max_grams_per_target',
933
+ String(SEARCH_NGRAM_MAX_GRAMS_PER_TARGET),
1154
934
  ]);
1155
- }
1156
- for (const route of verificationEvidence.reproRoutes) {
1157
- database.run('INSERT INTO repro_routes (route_id, task_hash, route_digest, route_kind, failure_oracle_hash) VALUES (?, ?, ?, ?, ?)', [route.routeId, route.taskHash, route.routeDigest, route.routeKind, route.failureOracleHash]);
1158
- }
1159
- for (const observation of verificationEvidence.reproObservations) {
1160
- database.run('INSERT INTO repro_observations (route_id, phase, outcome, receipt_hash, diagnostic_fingerprint) VALUES (?, ?, ?, ?, ?)', [
1161
- observation.routeId,
1162
- observation.phase,
1163
- observation.outcome,
1164
- observation.receiptHash,
1165
- observation.diagnosticFingerprint,
935
+ database.run('INSERT INTO metadata (key, value) VALUES (?, ?)', [
936
+ 'source_index_max_file_bytes',
937
+ String(SOURCE_INDEX_MAX_FILE_BYTES),
1166
938
  ]);
1167
- }
1168
- for (const fingerprint of verificationEvidence.failureFingerprintReadModels) {
1169
- database.run('INSERT INTO failure_fingerprints (fingerprint, plan_id, failed_intents_hash, risk_codes_hash, seen_count, first_seen_at, last_seen_at) VALUES (?, ?, ?, ?, ?, ?, ?)', [
1170
- fingerprint.fingerprint,
1171
- fingerprint.planId,
1172
- fingerprint.failedIntentsHash,
1173
- fingerprint.riskCodesHash,
1174
- fingerprint.seenCount,
1175
- fingerprint.firstSeenAt,
1176
- fingerprint.lastSeenAt,
939
+ database.run('INSERT INTO metadata (key, value) VALUES (?, ?)', [
940
+ 'excluded_raw_data_kinds',
941
+ LOCAL_INDEX_EXCLUDED_RAW_DATA_KINDS.join(','),
1177
942
  ]);
1178
- }
1179
- for (const fingerprint of verificationEvidence.failureFingerprints) {
1180
- database.run('INSERT INTO verification_failure_fingerprints (source_path, fingerprint, verification_plan_id, status, failed_intents, primary_reason, failed_intents_hash, risk_codes_hash, affected_surfaces_hash, first_seen_at, last_seen_at, seen_count, requires_new_evidence) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', [
1181
- fingerprint.sourcePath,
1182
- fingerprint.fingerprint,
1183
- fingerprint.verificationPlanId,
1184
- fingerprint.status,
1185
- joinedList(fingerprint.failedIntents),
1186
- fingerprint.primaryReason,
1187
- fingerprint.failedIntentsHash,
1188
- fingerprint.riskCodesHash,
1189
- fingerprint.affectedSurfacesHash,
1190
- fingerprint.firstSeenAt,
1191
- fingerprint.lastSeenAt,
1192
- fingerprint.seenCount,
1193
- fingerprint.requiresNewEvidence ? 1 : 0,
943
+ database.run('INSERT INTO metadata (key, value) VALUES (?, ?)', ['search_backend', capabilities.backend]);
944
+ database.run('INSERT INTO metadata (key, value) VALUES (?, ?)', [
945
+ 'search_fts5_available',
946
+ String(capabilities.fts5Available),
1194
947
  ]);
948
+ database.run('INSERT INTO metadata (key, value) VALUES (?, ?)', ['source_scope_hash', sourceScopeHash]);
949
+ database.run('INSERT INTO metadata (key, value) VALUES (?, ?)', ['source_index_enabled', String(sourceIndexEnabled)]);
950
+ database.run('INSERT INTO metadata (key, value) VALUES (?, ?)', ['index_mode', indexMode]);
951
+ for (const indexedFile of indexedFiles) {
952
+ database.run('INSERT INTO indexed_files (path, source_scope, size_bytes, mtime_ms, content_hash, indexed_at, index_mode, parser_version) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', [
953
+ indexedFile.path,
954
+ indexedFile.sourceScope,
955
+ indexedFile.sizeBytes,
956
+ indexedFile.mtimeMs,
957
+ indexedFile.contentHash,
958
+ indexedAt,
959
+ indexMode,
960
+ LOCAL_INDEX_PARSER_VERSION,
961
+ ]);
962
+ }
963
+ for (const document of documents) {
964
+ database.run('INSERT INTO documents (path, type, title, locale, revision, content_hash, content_snippet) VALUES (?, ?, ?, ?, ?, ?, ?)', [
965
+ document.path,
966
+ document.type,
967
+ document.title,
968
+ document.locale,
969
+ document.revision,
970
+ document.contentHash,
971
+ document.contentSnippet,
972
+ ]);
973
+ document.sections.forEach((heading, index) => {
974
+ database.run('INSERT INTO sections (document_path, ordinal, heading) VALUES (?, ?, ?)', [
975
+ document.path,
976
+ index + 1,
977
+ heading,
978
+ ]);
979
+ });
980
+ }
981
+ for (const skill of skills) {
982
+ database.run('INSERT INTO skills (name, path, title) VALUES (?, ?, ?)', [skill.name, skill.path, skill.title]);
983
+ }
984
+ for (const route of skillRoutes) {
985
+ const verificationIntents = route.verificationIntents.join(', ');
986
+ database.run('INSERT INTO skill_routes (skill_name, skill_path, trigger, required_input, edit_scope, risk, verification_intents, expected_output) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', [
987
+ route.skillName,
988
+ route.skillPath,
989
+ route.trigger,
990
+ route.requiredInput,
991
+ route.editScope,
992
+ route.risk,
993
+ verificationIntents,
994
+ route.expectedOutput,
995
+ ]);
996
+ insertDocumentTerm(database, '.mustflow/skills/INDEX.md', route.skillName, 'skill_route_name');
997
+ insertDocumentTerm(database, '.mustflow/skills/INDEX.md', route.trigger, 'skill_route_trigger');
998
+ insertDocumentTerm(database, '.mustflow/skills/INDEX.md', route.risk, 'skill_route_risk');
999
+ insertDocumentTerm(database, '.mustflow/skills/INDEX.md', route.requiredInput, 'skill_route_required_input');
1000
+ insertDocumentTerm(database, '.mustflow/skills/INDEX.md', route.editScope, 'skill_route_edit_scope');
1001
+ insertDocumentTerm(database, '.mustflow/skills/INDEX.md', verificationIntents, 'skill_route_verification_intents');
1002
+ }
1003
+ for (const intent of commandIntents) {
1004
+ database.run('INSERT INTO command_intents (name, status, lifecycle, run_policy, description) VALUES (?, ?, ?, ?, ?)', [intent.name, intent.status, intent.lifecycle, intent.runPolicy, intent.description]);
1005
+ insertDocumentTerm(database, '.mustflow/config/commands.toml', intent.name, 'command_intent');
1006
+ insertDocumentTerm(database, '.mustflow/config/commands.toml', intent.status, 'command_status');
1007
+ insertDocumentTerm(database, '.mustflow/config/commands.toml', intent.lifecycle, 'command_lifecycle');
1008
+ insertDocumentTerm(database, '.mustflow/config/commands.toml', intent.runPolicy, 'command_run_policy');
1009
+ insertDocumentTerm(database, '.mustflow/config/commands.toml', intent.description, 'command_description');
1010
+ for (const effect of intent.effects) {
1011
+ database.run('INSERT INTO command_effects (intent, source, access, mode, path, lock, concurrency) VALUES (?, ?, ?, ?, ?, ?, ?)', [effect.intent, effect.source, effect.access, effect.mode, effect.path, effect.lock, effect.concurrency]);
1012
+ if (effect.path !== null) {
1013
+ insertDocumentTerm(database, '.mustflow/config/commands.toml', effect.path, 'command_effect_path');
1014
+ }
1015
+ insertDocumentTerm(database, '.mustflow/config/commands.toml', effect.lock, 'command_effect_lock');
1016
+ insertDocumentTerm(database, '.mustflow/config/commands.toml', effect.mode, 'command_effect_mode');
1017
+ }
1018
+ }
1019
+ for (const anchor of sourceAnchors) {
1020
+ database.run('INSERT INTO source_anchors (id, path, line_start, purpose, search_terms, invariant, risk, navigation_only, can_instruct_agent) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)', [
1021
+ anchor.id,
1022
+ anchor.path,
1023
+ anchor.lineStart,
1024
+ anchor.purpose,
1025
+ anchor.search.join(', '),
1026
+ anchor.invariant,
1027
+ anchor.risk.join(', '),
1028
+ anchor.navigationOnly ? 1 : 0,
1029
+ anchor.canInstructAgent ? 1 : 0,
1030
+ ]);
1031
+ database.run('INSERT INTO source_anchor_fingerprints (anchor_id, path, line_start, anchor_metadata_hash, anchor_text_hash, context_hash, search_terms_hash, invariant_hash, risk_hash, symbol_kind, symbol_name, symbol_exported, signature_hash, body_hash, symbol_start_line, symbol_end_line) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', [
1032
+ anchor.id,
1033
+ anchor.path,
1034
+ anchor.lineStart,
1035
+ anchor.fingerprint.anchorMetadataHash,
1036
+ anchor.fingerprint.anchorTextHash,
1037
+ anchor.fingerprint.contextHash,
1038
+ anchor.fingerprint.searchTermsHash,
1039
+ anchor.fingerprint.invariantHash,
1040
+ anchor.fingerprint.riskHash,
1041
+ anchor.fingerprint.symbol.kind,
1042
+ anchor.fingerprint.symbol.name,
1043
+ anchor.fingerprint.symbol.exported ? 1 : 0,
1044
+ anchor.fingerprint.symbol.signatureHash,
1045
+ anchor.fingerprint.symbol.bodyHash,
1046
+ anchor.fingerprint.symbol.startLine,
1047
+ anchor.fingerprint.symbol.endLine,
1048
+ ]);
1049
+ database.run('INSERT INTO source_anchor_status (anchor_id, status, confidence, identity_signal, location_signal, symbol_signal, body_signal, metadata_signal, semantic_signal, risk_signal, navigation_only, can_instruct_agent) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', [
1050
+ anchor.id,
1051
+ anchor.status,
1052
+ anchor.confidence,
1053
+ anchor.signals.identity,
1054
+ anchor.signals.location,
1055
+ anchor.signals.symbol,
1056
+ anchor.signals.body,
1057
+ anchor.signals.metadata,
1058
+ anchor.signals.semantic,
1059
+ anchor.signals.risk,
1060
+ anchor.navigationOnly ? 1 : 0,
1061
+ anchor.canInstructAgent ? 1 : 0,
1062
+ ]);
1063
+ }
1064
+ for (const summary of verificationEvidence.summaries) {
1065
+ database.run('INSERT INTO verification_evidence_summaries (source_path, source_hash, command, kind, status, run_dir, manifest_path, verification_plan_id, completion_status, primary_reason, matched_intents, ran_intents, passed_intents, failed_intents, skipped_intents, receipt_count, coverage_count, remaining_risk_count, failure_fingerprint) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', [
1066
+ summary.sourcePath,
1067
+ summary.sourceHash,
1068
+ summary.command,
1069
+ summary.kind,
1070
+ summary.status,
1071
+ summary.runDir,
1072
+ summary.manifestPath,
1073
+ summary.verificationPlanId,
1074
+ summary.completionStatus,
1075
+ summary.primaryReason,
1076
+ summary.matchedIntents,
1077
+ summary.ranIntents,
1078
+ summary.passedIntents,
1079
+ summary.failedIntents,
1080
+ summary.skippedIntents,
1081
+ summary.receiptCount,
1082
+ summary.coverageCount,
1083
+ summary.remainingRiskCount,
1084
+ summary.failureFingerprint,
1085
+ ]);
1086
+ }
1087
+ for (const plan of verificationEvidence.verificationPlans) {
1088
+ database.run('INSERT INTO verification_plans (plan_id, source_path, classification_hash, command_contract_hash, selected_intents_hash, created_at, source_hash) VALUES (?, ?, ?, ?, ?, ?, ?)', [
1089
+ plan.planId,
1090
+ plan.sourcePath,
1091
+ plan.classificationHash,
1092
+ plan.commandContractHash,
1093
+ plan.selectedIntentsHash,
1094
+ plan.createdAt,
1095
+ plan.sourceHash,
1096
+ ]);
1097
+ }
1098
+ for (const criterion of verificationEvidence.acceptanceCriteria) {
1099
+ database.run('INSERT INTO acceptance_criteria (criterion_id, plan_id, source, statement_hash, reason, surface, path_hash) VALUES (?, ?, ?, ?, ?, ?, ?)', [
1100
+ criterion.criterionId,
1101
+ criterion.planId,
1102
+ criterion.source,
1103
+ criterion.statementHash,
1104
+ criterion.reason,
1105
+ criterion.surface,
1106
+ criterion.pathHash,
1107
+ ]);
1108
+ }
1109
+ for (const coverage of verificationEvidence.criterionCoverage) {
1110
+ database.run('INSERT INTO criterion_coverage (criterion_id, plan_id, status, receipt_count, gap_count, risk_count) VALUES (?, ?, ?, ?, ?, ?)', [coverage.criterionId, coverage.planId, coverage.status, coverage.receiptCount, coverage.gapCount, coverage.riskCount]);
1111
+ }
1112
+ for (const receipt of verificationEvidence.receipts) {
1113
+ database.run('INSERT INTO verification_receipt_summaries (source_path, ordinal, intent, status, skipped, verification_plan_id, receipt_path, receipt_sha256) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', [
1114
+ receipt.sourcePath,
1115
+ receipt.ordinal,
1116
+ receipt.intent,
1117
+ receipt.status,
1118
+ receipt.skipped ? 1 : 0,
1119
+ receipt.verificationPlanId,
1120
+ receipt.receiptPath,
1121
+ receipt.receiptSha256,
1122
+ ]);
1123
+ }
1124
+ for (const receipt of verificationEvidence.commandReceiptSummaries) {
1125
+ database.run('INSERT INTO command_receipt_summaries (receipt_hash, plan_id, intent, status, command_fingerprint, contract_fingerprint, current_state_hash, write_drift_status) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', [
1126
+ receipt.receiptHash,
1127
+ receipt.planId,
1128
+ receipt.intent,
1129
+ receipt.status,
1130
+ receipt.commandFingerprint,
1131
+ receipt.contractFingerprint,
1132
+ receipt.currentStateHash,
1133
+ receipt.writeDriftStatus,
1134
+ ]);
1135
+ }
1136
+ for (const coverage of verificationEvidence.coverageStates) {
1137
+ database.run('INSERT INTO verification_coverage_states (source_path, criterion_id, source, status, requirement_reason, intents, receipt_count, gap_count, source_anchor_count) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)', [
1138
+ coverage.sourcePath,
1139
+ coverage.criterionId,
1140
+ coverage.source,
1141
+ coverage.status,
1142
+ coverage.requirementReason,
1143
+ joinedList(coverage.intents),
1144
+ coverage.receiptCount,
1145
+ coverage.gapCount,
1146
+ coverage.sourceAnchorCount,
1147
+ ]);
1148
+ }
1149
+ for (const risk of verificationEvidence.riskSignals) {
1150
+ database.run('INSERT INTO verification_risk_signals (source_path, ordinal, code, severity, detail_hash) VALUES (?, ?, ?, ?, ?)', [risk.sourcePath, risk.ordinal, risk.code, risk.severity, risk.detailHash]);
1151
+ }
1152
+ for (const signal of verificationEvidence.validationRatchetSignals) {
1153
+ database.run('INSERT INTO validation_ratchet_signals (signal_id, plan_id, code, severity, path_hash, before_hash, after_hash) VALUES (?, ?, ?, ?, ?, ?, ?)', [signal.signalId, signal.planId, signal.code, signal.severity, signal.pathHash, signal.beforeHash, signal.afterHash]);
1154
+ }
1155
+ for (const verdict of verificationEvidence.completionVerdictSummaries) {
1156
+ database.run('INSERT INTO completion_verdict_summaries (claim_id, plan_id, status, primary_reason, risk_count, contradiction_count, blocker_count) VALUES (?, ?, ?, ?, ?, ?, ?)', [
1157
+ verdict.claimId,
1158
+ verdict.planId,
1159
+ verdict.status,
1160
+ verdict.primaryReason,
1161
+ verdict.riskCount,
1162
+ verdict.contradictionCount,
1163
+ verdict.blockerCount,
1164
+ ]);
1165
+ }
1166
+ for (const route of verificationEvidence.reproRoutes) {
1167
+ database.run('INSERT INTO repro_routes (route_id, task_hash, route_digest, route_kind, failure_oracle_hash) VALUES (?, ?, ?, ?, ?)', [route.routeId, route.taskHash, route.routeDigest, route.routeKind, route.failureOracleHash]);
1168
+ }
1169
+ for (const observation of verificationEvidence.reproObservations) {
1170
+ database.run('INSERT INTO repro_observations (route_id, phase, outcome, receipt_hash, diagnostic_fingerprint) VALUES (?, ?, ?, ?, ?)', [
1171
+ observation.routeId,
1172
+ observation.phase,
1173
+ observation.outcome,
1174
+ observation.receiptHash,
1175
+ observation.diagnosticFingerprint,
1176
+ ]);
1177
+ }
1178
+ for (const fingerprint of verificationEvidence.failureFingerprintReadModels) {
1179
+ database.run('INSERT INTO failure_fingerprints (fingerprint, plan_id, failed_intents_hash, risk_codes_hash, seen_count, first_seen_at, last_seen_at) VALUES (?, ?, ?, ?, ?, ?, ?)', [
1180
+ fingerprint.fingerprint,
1181
+ fingerprint.planId,
1182
+ fingerprint.failedIntentsHash,
1183
+ fingerprint.riskCodesHash,
1184
+ fingerprint.seenCount,
1185
+ fingerprint.firstSeenAt,
1186
+ fingerprint.lastSeenAt,
1187
+ ]);
1188
+ }
1189
+ for (const fingerprint of verificationEvidence.failureFingerprints) {
1190
+ database.run('INSERT INTO verification_failure_fingerprints (source_path, fingerprint, verification_plan_id, status, failed_intents, primary_reason, failed_intents_hash, risk_codes_hash, affected_surfaces_hash, first_seen_at, last_seen_at, seen_count, requires_new_evidence) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', [
1191
+ fingerprint.sourcePath,
1192
+ fingerprint.fingerprint,
1193
+ fingerprint.verificationPlanId,
1194
+ fingerprint.status,
1195
+ joinedList(fingerprint.failedIntents),
1196
+ fingerprint.primaryReason,
1197
+ fingerprint.failedIntentsHash,
1198
+ fingerprint.riskCodesHash,
1199
+ fingerprint.affectedSurfacesHash,
1200
+ fingerprint.firstSeenAt,
1201
+ fingerprint.lastSeenAt,
1202
+ fingerprint.seenCount,
1203
+ fingerprint.requiresNewEvidence ? 1 : 0,
1204
+ ]);
1205
+ }
1206
+ for (const signal of sourceAnchorRiskSignals) {
1207
+ database.run('INSERT INTO source_anchor_risk_signals (anchor_id, path_hash, status, risk_signal, confidence, navigation_only, can_instruct_agent) VALUES (?, ?, ?, ?, ?, ?, ?)', [
1208
+ signal.anchorId,
1209
+ signal.pathHash,
1210
+ signal.status,
1211
+ signal.riskSignal,
1212
+ signal.confidence,
1213
+ signal.navigationOnly ? 1 : 0,
1214
+ signal.canInstructAgent ? 1 : 0,
1215
+ ]);
1216
+ }
1217
+ populatePathSurfaceReadModel(database);
1218
+ populateSearchTables(database, capabilities, documents, skills, skillRoutes, commandIntents, sourceAnchors);
1219
+ database.run('COMMIT');
1195
1220
  }
1196
- for (const signal of sourceAnchorRiskSignals) {
1197
- database.run('INSERT INTO source_anchor_risk_signals (anchor_id, path_hash, status, risk_signal, confidence, navigation_only, can_instruct_agent) VALUES (?, ?, ?, ?, ?, ?, ?)', [
1198
- signal.anchorId,
1199
- signal.pathHash,
1200
- signal.status,
1201
- signal.riskSignal,
1202
- signal.confidence,
1203
- signal.navigationOnly ? 1 : 0,
1204
- signal.canInstructAgent ? 1 : 0,
1205
- ]);
1221
+ catch (error) {
1222
+ rollbackTransaction(database);
1223
+ throw error;
1206
1224
  }
1207
- populatePathSurfaceReadModel(database);
1208
- populateSearchTables(database, capabilities, documents, skills, skillRoutes, commandIntents, sourceAnchors);
1209
1225
  }
1210
1226
  function readCount(database, tableName) {
1211
1227
  if (!hasTable(database, tableName)) {
@@ -2193,14 +2209,24 @@ function scoreIndexedOrTableScan(primaryFields, secondaryFields, query, indexedM
2193
2209
  return indexedMatches.active && matchSet.size > 0 && matchSet.has(key) ? Math.max(tableScore, 20) : tableScore;
2194
2210
  }
2195
2211
  function sortLocalSearchResults(results, scope, limit) {
2196
- return [...results]
2197
- .sort((left, right) => {
2212
+ const sorted = [...results].sort((left, right) => {
2198
2213
  if (scope === 'all' && left.authority_rank !== right.authority_rank) {
2199
2214
  return left.authority_rank - right.authority_rank;
2200
2215
  }
2201
2216
  return right.score - left.score || (left.path ?? left.name ?? '').localeCompare(right.path ?? right.name ?? '');
2202
- })
2203
- .slice(0, limit);
2217
+ });
2218
+ const limited = sorted.slice(0, limit);
2219
+ if (scope !== 'all' || limited.some((item) => item.kind === 'source_anchor')) {
2220
+ return limited;
2221
+ }
2222
+ const sourceAnchor = sorted.find((item) => item.kind === 'source_anchor');
2223
+ if (!sourceAnchor) {
2224
+ return limited;
2225
+ }
2226
+ if (limited.length < limit) {
2227
+ return [...limited, sourceAnchor];
2228
+ }
2229
+ return [...limited.slice(0, Math.max(0, limit - 1)), sourceAnchor];
2204
2230
  }
2205
2231
  function collectBoundedDirectSearchDocuments(projectRoot) {
2206
2232
  const documents = [];